angr 9.2.101__py3-none-win_amd64.whl → 9.2.103__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of angr might be problematic. Click here for more details.

Files changed (240) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/analysis.py +7 -6
  3. angr/analyses/calling_convention.py +33 -35
  4. angr/analyses/cdg.py +2 -4
  5. angr/analyses/cfg/cfb.py +4 -3
  6. angr/analyses/cfg/cfg_base.py +14 -14
  7. angr/analyses/cfg/cfg_emulated.py +3 -4
  8. angr/analyses/cfg/cfg_fast.py +46 -46
  9. angr/analyses/cfg/cfg_fast_soot.py +1 -2
  10. angr/analyses/cfg/cfg_job_base.py +2 -2
  11. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +14 -13
  12. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +5 -5
  13. angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +3 -3
  14. angr/analyses/complete_calling_conventions.py +13 -12
  15. angr/analyses/data_dep/data_dependency_analysis.py +24 -24
  16. angr/analyses/data_dep/dep_nodes.py +3 -3
  17. angr/analyses/ddg.py +1 -2
  18. angr/analyses/decompiler/ail_simplifier.py +35 -34
  19. angr/analyses/decompiler/block_io_finder.py +20 -20
  20. angr/analyses/decompiler/block_similarity.py +4 -6
  21. angr/analyses/decompiler/block_simplifier.py +17 -16
  22. angr/analyses/decompiler/callsite_maker.py +25 -10
  23. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -3
  24. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +2 -4
  25. angr/analyses/decompiler/clinic.py +250 -45
  26. angr/analyses/decompiler/condition_processor.py +15 -8
  27. angr/analyses/decompiler/decompilation_cache.py +7 -7
  28. angr/analyses/decompiler/decompilation_options.py +4 -4
  29. angr/analyses/decompiler/decompiler.py +19 -15
  30. angr/analyses/decompiler/expression_counters.py +10 -9
  31. angr/analyses/decompiler/goto_manager.py +2 -4
  32. angr/analyses/decompiler/graph_region.py +9 -9
  33. angr/analyses/decompiler/jump_target_collector.py +1 -2
  34. angr/analyses/decompiler/optimization_passes/__init__.py +4 -3
  35. angr/analyses/decompiler/optimization_passes/code_motion.py +5 -6
  36. angr/analyses/decompiler/optimization_passes/const_derefs.py +4 -4
  37. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +73 -0
  38. angr/analyses/decompiler/optimization_passes/engine_base.py +25 -3
  39. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +6 -5
  40. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
  41. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +3 -0
  42. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +2 -2
  43. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +17 -17
  44. angr/analyses/decompiler/optimization_passes/optimization_pass.py +12 -13
  45. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +25 -21
  46. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +3 -3
  47. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +1 -2
  48. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +7 -7
  49. angr/analyses/decompiler/optimization_passes/spilled_register_finder.py +18 -0
  50. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +2 -3
  51. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -2
  52. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +2 -2
  53. angr/analyses/decompiler/peephole_optimizations/__init__.py +4 -3
  54. angr/analyses/decompiler/peephole_optimizations/base.py +13 -15
  55. angr/analyses/decompiler/peephole_optimizations/bswap.py +1 -3
  56. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +72 -0
  57. angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -2
  58. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
  59. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +5 -10
  60. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +3 -4
  61. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +7 -10
  62. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +2 -3
  63. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -2
  64. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +4 -4
  65. angr/analyses/decompiler/redundant_label_remover.py +4 -5
  66. angr/analyses/decompiler/region_identifier.py +4 -5
  67. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -2
  68. angr/analyses/decompiler/region_simplifiers/expr_folding.py +19 -20
  69. angr/analyses/decompiler/region_simplifiers/goto.py +2 -3
  70. angr/analyses/decompiler/region_simplifiers/loop.py +1 -2
  71. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -2
  72. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +1 -3
  73. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +19 -19
  74. angr/analyses/decompiler/return_maker.py +1 -2
  75. angr/analyses/decompiler/structured_codegen/base.py +5 -6
  76. angr/analyses/decompiler/structured_codegen/c.py +39 -38
  77. angr/analyses/decompiler/structuring/__init__.py +1 -1
  78. angr/analyses/decompiler/structuring/dream.py +17 -16
  79. angr/analyses/decompiler/structuring/phoenix.py +45 -46
  80. angr/analyses/decompiler/structuring/recursive_structurer.py +4 -4
  81. angr/analyses/decompiler/structuring/structurer_base.py +16 -15
  82. angr/analyses/decompiler/structuring/structurer_nodes.py +10 -9
  83. angr/analyses/decompiler/utils.py +17 -16
  84. angr/analyses/disassembly.py +7 -6
  85. angr/analyses/flirt.py +9 -9
  86. angr/analyses/forward_analysis/forward_analysis.py +15 -14
  87. angr/analyses/forward_analysis/visitors/function_graph.py +1 -2
  88. angr/analyses/forward_analysis/visitors/graph.py +16 -15
  89. angr/analyses/propagator/engine_ail.py +30 -26
  90. angr/analyses/propagator/outdated_definition_walker.py +8 -7
  91. angr/analyses/propagator/propagator.py +11 -13
  92. angr/analyses/proximity_graph.py +21 -21
  93. angr/analyses/reaching_definitions/__init__.py +3 -3
  94. angr/analyses/reaching_definitions/call_trace.py +3 -6
  95. angr/analyses/reaching_definitions/dep_graph.py +41 -48
  96. angr/analyses/reaching_definitions/engine_ail.py +11 -5
  97. angr/analyses/reaching_definitions/engine_vex.py +9 -8
  98. angr/analyses/reaching_definitions/function_handler.py +51 -34
  99. angr/analyses/reaching_definitions/heap_allocator.py +3 -4
  100. angr/analyses/reaching_definitions/rd_initializer.py +8 -8
  101. angr/analyses/reaching_definitions/rd_state.py +57 -58
  102. angr/analyses/reaching_definitions/reaching_definitions.py +18 -17
  103. angr/analyses/reaching_definitions/subject.py +2 -3
  104. angr/analyses/stack_pointer_tracker.py +15 -6
  105. angr/analyses/typehoon/dfa.py +4 -4
  106. angr/analyses/typehoon/simple_solver.py +48 -52
  107. angr/analyses/typehoon/translator.py +3 -6
  108. angr/analyses/typehoon/typeconsts.py +13 -14
  109. angr/analyses/typehoon/typehoon.py +9 -9
  110. angr/analyses/typehoon/typevars.py +18 -17
  111. angr/analyses/variable_recovery/engine_ail.py +5 -5
  112. angr/analyses/variable_recovery/engine_base.py +25 -21
  113. angr/analyses/variable_recovery/irsb_scanner.py +8 -9
  114. angr/analyses/variable_recovery/variable_recovery.py +1 -2
  115. angr/analyses/variable_recovery/variable_recovery_base.py +14 -13
  116. angr/analyses/variable_recovery/variable_recovery_fast.py +8 -8
  117. angr/analyses/veritesting.py +1 -2
  118. angr/analyses/vfg.py +57 -56
  119. angr/analyses/xrefs.py +1 -2
  120. angr/angrdb/db.py +7 -7
  121. angr/angrdb/serializers/kb.py +16 -13
  122. angr/angrdb/serializers/loader.py +1 -2
  123. angr/angrdb/serializers/structured_code.py +2 -2
  124. angr/annocfg.py +1 -2
  125. angr/block.py +16 -6
  126. angr/calling_conventions.py +27 -27
  127. angr/code_location.py +8 -8
  128. angr/codenode.py +1 -2
  129. angr/concretization_strategies/max.py +1 -3
  130. angr/distributed/server.py +1 -3
  131. angr/distributed/worker.py +1 -2
  132. angr/engines/engine.py +2 -3
  133. angr/engines/light/engine.py +4 -4
  134. angr/engines/pcode/behavior.py +20 -2
  135. angr/engines/pcode/emulate.py +1 -1
  136. angr/engines/pcode/engine.py +7 -7
  137. angr/engines/pcode/lifter.py +78 -77
  138. angr/engines/vex/claripy/ccall.py +1 -2
  139. angr/engines/vex/claripy/datalayer.py +1 -2
  140. angr/engines/vex/light/light.py +1 -2
  141. angr/exploration_techniques/tracer.py +4 -4
  142. angr/factory.py +12 -15
  143. angr/flirt/__init__.py +8 -8
  144. angr/flirt/build_sig.py +2 -3
  145. angr/keyed_region.py +2 -2
  146. angr/knowledge_base/knowledge_base.py +3 -3
  147. angr/knowledge_plugins/callsite_prototypes.py +4 -6
  148. angr/knowledge_plugins/cfg/cfg_manager.py +19 -6
  149. angr/knowledge_plugins/cfg/cfg_model.py +26 -27
  150. angr/knowledge_plugins/cfg/cfg_node.py +2 -2
  151. angr/knowledge_plugins/cfg/indirect_jump.py +6 -8
  152. angr/knowledge_plugins/cfg/memory_data.py +8 -9
  153. angr/knowledge_plugins/custom_strings.py +1 -3
  154. angr/knowledge_plugins/debug_variables.py +2 -2
  155. angr/knowledge_plugins/functions/function.py +21 -22
  156. angr/knowledge_plugins/functions/function_manager.py +5 -5
  157. angr/knowledge_plugins/indirect_jumps.py +1 -3
  158. angr/knowledge_plugins/key_definitions/atoms.py +7 -7
  159. angr/knowledge_plugins/key_definitions/definition.py +14 -14
  160. angr/knowledge_plugins/key_definitions/environment.py +5 -7
  161. angr/knowledge_plugins/key_definitions/heap_address.py +1 -3
  162. angr/knowledge_plugins/key_definitions/key_definition_manager.py +3 -2
  163. angr/knowledge_plugins/key_definitions/live_definitions.py +60 -59
  164. angr/knowledge_plugins/key_definitions/liveness.py +16 -16
  165. angr/knowledge_plugins/key_definitions/rd_model.py +15 -15
  166. angr/knowledge_plugins/key_definitions/uses.py +11 -11
  167. angr/knowledge_plugins/patches.py +4 -8
  168. angr/knowledge_plugins/propagations/prop_value.py +10 -9
  169. angr/knowledge_plugins/propagations/propagation_manager.py +3 -5
  170. angr/knowledge_plugins/propagations/propagation_model.py +9 -9
  171. angr/knowledge_plugins/propagations/states.py +52 -22
  172. angr/knowledge_plugins/structured_code/manager.py +2 -2
  173. angr/knowledge_plugins/sync/sync_controller.py +3 -3
  174. angr/knowledge_plugins/variables/variable_access.py +4 -4
  175. angr/knowledge_plugins/variables/variable_manager.py +56 -39
  176. angr/knowledge_plugins/xrefs/xref.py +9 -11
  177. angr/knowledge_plugins/xrefs/xref_manager.py +3 -4
  178. angr/lib/angr_native.dll +0 -0
  179. angr/misc/ansi.py +1 -2
  180. angr/misc/autoimport.py +3 -3
  181. angr/misc/plugins.py +9 -9
  182. angr/procedures/definitions/__init__.py +16 -16
  183. angr/procedures/definitions/linux_kernel.py +1 -1
  184. angr/procedures/definitions/parse_win32json.py +1 -1
  185. angr/procedures/java_jni/__init__.py +1 -1
  186. angr/procedures/java_jni/array_operations.py +1 -2
  187. angr/procedures/java_jni/method_calls.py +1 -2
  188. angr/procedures/posix/inet_ntoa.py +1 -2
  189. angr/procedures/stubs/format_parser.py +3 -3
  190. angr/project.py +13 -11
  191. angr/sim_manager.py +12 -12
  192. angr/sim_procedure.py +7 -3
  193. angr/sim_state.py +2 -2
  194. angr/sim_type.py +60 -45
  195. angr/sim_variable.py +5 -5
  196. angr/simos/simos.py +1 -2
  197. angr/simos/userland.py +1 -2
  198. angr/state_plugins/callstack.py +3 -2
  199. angr/state_plugins/history.py +1 -2
  200. angr/state_plugins/solver.py +34 -34
  201. angr/storage/memory_mixins/__init__.py +4 -3
  202. angr/storage/memory_mixins/actions_mixin.py +1 -3
  203. angr/storage/memory_mixins/address_concretization_mixin.py +1 -3
  204. angr/storage/memory_mixins/convenient_mappings_mixin.py +3 -4
  205. angr/storage/memory_mixins/default_filler_mixin.py +1 -1
  206. angr/storage/memory_mixins/label_merger_mixin.py +2 -2
  207. angr/storage/memory_mixins/multi_value_merger_mixin.py +4 -3
  208. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +9 -8
  209. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +12 -11
  210. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +8 -8
  211. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +2 -3
  212. angr/storage/memory_mixins/paged_memory/pages/list_page.py +10 -11
  213. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +11 -10
  214. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +18 -17
  215. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +12 -11
  216. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +3 -3
  217. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +3 -2
  218. angr/storage/memory_mixins/regioned_memory/region_data.py +1 -2
  219. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +2 -2
  220. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +3 -3
  221. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +18 -21
  222. angr/storage/memory_mixins/size_resolution_mixin.py +1 -2
  223. angr/storage/memory_mixins/symbolic_merger_mixin.py +3 -2
  224. angr/storage/memory_mixins/top_merger_mixin.py +3 -2
  225. angr/storage/memory_object.py +2 -4
  226. angr/utils/algo.py +3 -2
  227. angr/utils/dynamic_dictlist.py +5 -5
  228. angr/utils/formatting.py +4 -4
  229. angr/utils/funcid.py +1 -2
  230. angr/utils/graph.py +5 -6
  231. angr/utils/library.py +5 -5
  232. angr/utils/mp.py +5 -4
  233. angr/utils/segment_list.py +3 -4
  234. angr/utils/typing.py +3 -2
  235. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
  236. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/RECORD +240 -237
  237. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
  238. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
  239. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
  240. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
- from typing import Dict, Any, Tuple, Iterable, Generator, Optional, TYPE_CHECKING
1
+ from typing import Any, Optional, TYPE_CHECKING
2
+ from collections.abc import Iterable, Generator
2
3
 
3
4
  import claripy
4
5
  import ailment
@@ -17,7 +18,7 @@ class Detail:
17
18
 
18
19
  __slots__ = ("size", "expr", "def_at")
19
20
 
20
- def __init__(self, size: int, expr: Optional[ailment.Expression], def_at: Optional["CodeLocation"]):
21
+ def __init__(self, size: int, expr: ailment.Expression | None, def_at: Optional["CodeLocation"]):
21
22
  self.size = size
22
23
  self.expr = expr
23
24
  self.def_at = def_at
@@ -39,7 +40,7 @@ class PropValue:
39
40
  "offset_and_details",
40
41
  )
41
42
 
42
- def __init__(self, value: claripy.ast.Bits, offset_and_details: Optional[Dict[int, Detail]] = None):
43
+ def __init__(self, value: claripy.ast.Bits, offset_and_details: dict[int, Detail] | None = None):
43
44
  self.value = value
44
45
  self.offset_and_details = offset_and_details
45
46
 
@@ -48,7 +49,7 @@ class PropValue:
48
49
  return not bool(self.offset_and_details)
49
50
 
50
51
  @property
51
- def one_expr(self) -> Optional[ailment.Expression]:
52
+ def one_expr(self) -> ailment.Expression | None:
52
53
  """
53
54
  Get the expression that starts at offset 0 and covers the entire PropValue. Returns None if there are no
54
55
  expressions or multiple expressions.
@@ -109,7 +110,7 @@ class PropValue:
109
110
  value = claripy.fpToIEEEBV(value)
110
111
  return value[chop_start:chop_end]
111
112
 
112
- def value_and_labels(self) -> Generator[Tuple[int, claripy.ast.Bits, int, Optional[Dict]], None, None]:
113
+ def value_and_labels(self) -> Generator[tuple[int, claripy.ast.Bits, int, dict | None], None, None]:
113
114
  if not self.offset_and_details:
114
115
  return
115
116
  keys = list(sorted(self.offset_and_details.keys()))
@@ -140,7 +141,7 @@ class PropValue:
140
141
 
141
142
  @staticmethod
142
143
  def from_value_and_labels(
143
- value: claripy.ast.Bits, labels: Iterable[Tuple[int, int, int, Dict[str, Any]]]
144
+ value: claripy.ast.Bits, labels: Iterable[tuple[int, int, int, dict[str, Any]]]
144
145
  ) -> "PropValue":
145
146
  if not labels:
146
147
  return PropValue(value)
@@ -164,8 +165,8 @@ class PropValue:
164
165
 
165
166
  @staticmethod
166
167
  def extract_ail_expression(
167
- start: int, bits: int, expr: Optional[ailment.Expr.Expression]
168
- ) -> Optional[ailment.Expr.Expression]:
168
+ start: int, bits: int, expr: ailment.Expr.Expression | None
169
+ ) -> ailment.Expr.Expression | None:
169
170
  if expr is None:
170
171
  return None
171
172
 
@@ -182,7 +183,7 @@ class PropValue:
182
183
  return ailment.Expr.Convert(None, a.bits, bits, False, a, **expr.tags)
183
184
 
184
185
  @staticmethod
185
- def extend_ail_expression(bits: int, expr: Optional[ailment.Expr.Expression]) -> Optional[ailment.Expr.Expression]:
186
+ def extend_ail_expression(bits: int, expr: ailment.Expr.Expression | None) -> ailment.Expr.Expression | None:
186
187
  if expr is None:
187
188
  return None
188
189
  if isinstance(expr, ailment.Expr.Const):
@@ -1,5 +1,3 @@
1
- from typing import Dict, Tuple
2
-
3
1
  from angr.knowledge_plugins.plugin import KnowledgeBasePlugin
4
2
  from .propagation_model import PropagationModel
5
3
 
@@ -11,9 +9,9 @@ class PropagationManager(KnowledgeBasePlugin):
11
9
 
12
10
  def __init__(self, kb):
13
11
  super().__init__(kb=kb)
14
- self._propagations: Dict[Tuple, PropagationModel] = {}
12
+ self._propagations: dict[tuple, PropagationModel] = {}
15
13
 
16
- def exists(self, prop_key: Tuple) -> bool:
14
+ def exists(self, prop_key: tuple) -> bool:
17
15
  """
18
16
  Internal function to check if a func, specified as a CodeLocation
19
17
  exists in our known propagations
@@ -23,7 +21,7 @@ class PropagationManager(KnowledgeBasePlugin):
23
21
  """
24
22
  return prop_key in self._propagations
25
23
 
26
- def update(self, prop_key: Tuple, model: PropagationModel) -> None:
24
+ def update(self, prop_key: tuple, model: PropagationModel) -> None:
27
25
  """
28
26
  Add the replacements to known propagations
29
27
 
@@ -1,4 +1,4 @@
1
- from typing import Tuple, Dict, Set, DefaultDict, Any, Optional
1
+ from typing import DefaultDict, Any
2
2
  from collections import defaultdict
3
3
 
4
4
  import claripy
@@ -29,14 +29,14 @@ class PropagationModel(Serializable):
29
29
 
30
30
  def __init__(
31
31
  self,
32
- prop_key: Tuple,
33
- node_iterations: Optional[DefaultDict[Any, int]] = None,
34
- states: Optional[Dict] = None,
35
- block_initial_reg_values: Optional[Dict] = None,
36
- replacements: Optional[DefaultDict[Any, Dict]] = None,
37
- equivalence: Optional[Set] = None,
38
- function: Optional[Function] = None,
39
- input_states: Optional[Dict] = None,
32
+ prop_key: tuple,
33
+ node_iterations: DefaultDict[Any, int] | None = None,
34
+ states: dict | None = None,
35
+ block_initial_reg_values: dict | None = None,
36
+ replacements: DefaultDict[Any, dict] | None = None,
37
+ equivalence: set | None = None,
38
+ function: Function | None = None,
39
+ input_states: dict | None = None,
40
40
  ):
41
41
  self.key = prop_key
42
42
  self.node_iterations = node_iterations if node_iterations is not None else defaultdict(int)
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=too-many-boolean-expressions
2
- from typing import Set, Optional, Union, Tuple, DefaultDict, List, Any, Dict, TYPE_CHECKING
2
+ from typing import Optional, Union, DefaultDict, Any, TYPE_CHECKING
3
3
  from collections import defaultdict
4
4
  import weakref
5
5
 
@@ -39,7 +39,7 @@ class CallExprFinder(ailment.AILBlockWalker):
39
39
  expr: ailment.Stmt.Call,
40
40
  stmt_idx: int,
41
41
  stmt: ailment.Stmt.Statement,
42
- block: Optional[ailment.Block],
42
+ block: ailment.Block | None,
43
43
  ):
44
44
  self.has_call = True
45
45
 
@@ -73,6 +73,7 @@ class PropagatorState:
73
73
  "_gp",
74
74
  "_max_prop_expr_occurrence",
75
75
  "model",
76
+ "_artificial_reg_offsets",
76
77
  "__weakref__",
77
78
  )
78
79
 
@@ -83,14 +84,15 @@ class PropagatorState:
83
84
  arch: "Arch",
84
85
  project: Optional["Project"] = None,
85
86
  rda=None,
86
- replacements: Optional[DefaultDict[CodeLocation, Dict]] = None,
87
+ replacements: DefaultDict[CodeLocation, dict] | None = None,
87
88
  only_consts: bool = False,
88
- expr_used_locs: Optional[DefaultDict[Any, Set[CodeLocation]]] = None,
89
- equivalence: Optional[Set["Equivalence"]] = None,
89
+ expr_used_locs: DefaultDict[Any, set[CodeLocation]] | None = None,
90
+ equivalence: set["Equivalence"] | None = None,
90
91
  store_tops: bool = True,
91
- gp: Optional[int] = None,
92
+ gp: int | None = None,
92
93
  max_prop_expr_occurrence: int = 1,
93
94
  model=None,
95
+ artificial_reg_offsets=None,
94
96
  ):
95
97
  self.arch = arch
96
98
  self.gpr_size = arch.bits // arch.byte_width # size of the general-purpose registers
@@ -99,12 +101,13 @@ class PropagatorState:
99
101
  self._expr_used_locs = defaultdict(list) if expr_used_locs is None else expr_used_locs
100
102
  self._only_consts = only_consts
101
103
  self._replacements = defaultdict(dict) if replacements is None else replacements
102
- self._equivalence: Set[Equivalence] = equivalence if equivalence is not None else set()
104
+ self._equivalence: set[Equivalence] = equivalence if equivalence is not None else set()
103
105
  self._store_tops = store_tops
104
106
  self._max_prop_expr_occurrence = max_prop_expr_occurrence
107
+ self._artificial_reg_offsets = artificial_reg_offsets if artificial_reg_offsets is not None else set()
105
108
 
106
109
  # architecture-specific information
107
- self._gp: Optional[int] = gp # Value of gp for MIPS32 and 64 binaries
110
+ self._gp: int | None = gp # Value of gp for MIPS32 and 64 binaries
108
111
 
109
112
  self.project = project
110
113
  self.model = model
@@ -202,7 +205,7 @@ class PropagatorState:
202
205
  :return: Whether merging has happened or not.
203
206
  """
204
207
 
205
- def _get_repl_size(repl_value: Union[Dict, ailment.Expression, claripy.ast.Bits]) -> int:
208
+ def _get_repl_size(repl_value: dict | ailment.Expression | claripy.ast.Bits) -> int:
206
209
  if isinstance(repl_value, dict):
207
210
  return _get_repl_size(repl_value["expr"])
208
211
  if isinstance(repl_value, ailment.Expression):
@@ -384,6 +387,7 @@ class PropagatorVEXState(PropagatorState):
384
387
  gp=None,
385
388
  max_prop_expr_occurrence: int = 1,
386
389
  model=None,
390
+ artificial_reg_offsets=None,
387
391
  ):
388
392
  super().__init__(
389
393
  arch,
@@ -396,6 +400,7 @@ class PropagatorVEXState(PropagatorState):
396
400
  gp=gp,
397
401
  max_prop_expr_occurrence=max_prop_expr_occurrence,
398
402
  model=model,
403
+ artificial_reg_offsets=artificial_reg_offsets,
399
404
  )
400
405
  self.do_binops = do_binops
401
406
  self._registers = (
@@ -487,11 +492,12 @@ class PropagatorVEXState(PropagatorState):
487
492
  gp=self._gp,
488
493
  max_prop_expr_occurrence=self._max_prop_expr_occurrence,
489
494
  model=self.model,
495
+ artificial_reg_offsets=self._artificial_reg_offsets,
490
496
  )
491
497
 
492
498
  return cp
493
499
 
494
- def merge(self, *others: "PropagatorVEXState") -> Tuple["PropagatorVEXState", bool]:
500
+ def merge(self, *others: "PropagatorVEXState") -> tuple["PropagatorVEXState", bool]:
495
501
  state = self.copy()
496
502
  merge_occurred = state._registers.merge([o._registers for o in others], None)
497
503
  merge_occurred |= state._stack_variables.merge([o._stack_variables for o in others], None)
@@ -524,7 +530,7 @@ class PropagatorVEXState(PropagatorState):
524
530
  except SimMemoryMissingError:
525
531
  return self.top(size * self.arch.byte_width).annotate(RegisterAnnotation(offset, size))
526
532
 
527
- def register_results(self) -> Dict[str, claripy.ast.BV]:
533
+ def register_results(self) -> dict[str, claripy.ast.BV]:
528
534
  result = {}
529
535
  for reg, (offset, size) in self.arch.registers.items():
530
536
  val = self.load_register(offset, size)
@@ -600,6 +606,7 @@ class PropagatorAILState(PropagatorState):
600
606
  max_prop_expr_occurrence: int = 1,
601
607
  sp_adjusted: bool = False,
602
608
  model=None,
609
+ artificial_reg_offsets=None,
603
610
  ):
604
611
  super().__init__(
605
612
  arch,
@@ -612,6 +619,7 @@ class PropagatorAILState(PropagatorState):
612
619
  gp=gp,
613
620
  max_prop_expr_occurrence=max_prop_expr_occurrence,
614
621
  model=model,
622
+ artificial_reg_offsets=artificial_reg_offsets,
615
623
  )
616
624
 
617
625
  self._stack_variables = (
@@ -628,7 +636,7 @@ class PropagatorAILState(PropagatorState):
628
636
  self.temp_expressions = {}
629
637
  self.register_expressions = {}
630
638
  self.block_initial_reg_values: DefaultDict[
631
- Tuple[int, int], List[Tuple[ailment.Expr.Register, ailment.Expr.Const]]
639
+ tuple[int, int], list[tuple[ailment.Expr.Register, ailment.Expr.Const]]
632
640
  ] = (defaultdict(list) if block_initial_reg_values is None else block_initial_reg_values)
633
641
  self._sp_adjusted: bool = sp_adjusted
634
642
 
@@ -637,8 +645,8 @@ class PropagatorAILState(PropagatorState):
637
645
  # last_stack_store stores the most recent stack store statement with a non-concrete or unresolvable address. we
638
646
  # use this information to determine if stack reads after this store can be safely resolved to definitions prior
639
647
  # to the stack read.
640
- self.last_stack_store: Optional[Tuple[int, int, ailment.Stmt.Store]] = None
641
- self.global_stores: List[Tuple[int, int, Any, ailment.Stmt.Store]] = []
648
+ self.last_stack_store: tuple[int, int, ailment.Stmt.Store] | None = None
649
+ self.global_stores: list[tuple[int, int, Any, ailment.Stmt.Store]] = []
642
650
 
643
651
  def __repr__(self):
644
652
  return "<PropagatorAILState>"
@@ -711,6 +719,18 @@ class PropagatorAILState(PropagatorState):
711
719
  PropValue(claripy.BVV(0, 32), offset_and_details={0: Detail(4, reg_value, initial_codeloc)}),
712
720
  )
713
721
 
722
+ elif project.arch.name.startswith("PowerPC:"):
723
+ # pcode PowerPC
724
+ state._artificial_reg_offsets = {project.arch.registers["tea"][0]}
725
+
726
+ # clear xer_so
727
+ reg_expr = ailment.Expr.Register(None, None, *project.arch.registers["xer_so"])
728
+ reg_value = ailment.Expr.Const(None, None, 0, 8)
729
+ state.store_register(
730
+ reg_expr,
731
+ PropValue(claripy.BVV(0, 8), offset_and_details={0: Detail(1, reg_value, initial_codeloc)}),
732
+ )
733
+
714
734
  if project is not None and project.simos is not None and project.simos.function_initial_registers:
715
735
  if func_addr is not None:
716
736
  for reg_name, reg_value in project.simos.function_initial_registers.items():
@@ -744,12 +764,13 @@ class PropagatorAILState(PropagatorState):
744
764
  max_prop_expr_occurrence=self._max_prop_expr_occurrence,
745
765
  sp_adjusted=self._sp_adjusted,
746
766
  model=self.model,
767
+ artificial_reg_offsets=self._artificial_reg_offsets,
747
768
  )
748
769
 
749
770
  return rd
750
771
 
751
772
  @staticmethod
752
- def is_const_or_register(value: Optional[Union[ailment.Expr.Expression, claripy.ast.Bits]]) -> bool:
773
+ def is_const_or_register(value: ailment.Expr.Expression | claripy.ast.Bits | None) -> bool:
753
774
  if value is None:
754
775
  return False
755
776
  if isinstance(value, claripy.ast.BV):
@@ -769,7 +790,7 @@ class PropagatorAILState(PropagatorState):
769
790
  return True
770
791
  return False
771
792
 
772
- def merge(self, *others) -> Tuple["PropagatorAILState", bool]:
793
+ def merge(self, *others) -> tuple["PropagatorAILState", bool]:
773
794
  state, merge_occurred = super().merge(*others)
774
795
  state: "PropagatorAILState"
775
796
 
@@ -781,7 +802,7 @@ class PropagatorAILState(PropagatorState):
781
802
  def store_temp(self, tmp_idx: int, value: PropValue):
782
803
  self._tmps[tmp_idx] = value
783
804
 
784
- def load_tmp(self, tmp_idx: int) -> Optional[PropValue]:
805
+ def load_tmp(self, tmp_idx: int) -> PropValue | None:
785
806
  return self._tmps.get(tmp_idx, None)
786
807
 
787
808
  def store_register(self, reg: ailment.Expr.Register, value: PropValue) -> None:
@@ -807,7 +828,7 @@ class PropagatorAILState(PropagatorState):
807
828
  for offset, value, size, label in new.value_and_labels():
808
829
  self._stack_variables.store(sp_offset + offset, value, size=size, endness=endness, label=label)
809
830
 
810
- def load_register(self, reg: ailment.Expr.Register) -> Optional[PropValue]:
831
+ def load_register(self, reg: ailment.Expr.Register) -> PropValue | None:
811
832
  try:
812
833
  value, labels = self._registers.load_with_labels(
813
834
  reg.reg_offset, size=reg.size, endness=self.project.arch.register_endness
@@ -819,7 +840,7 @@ class PropagatorAILState(PropagatorState):
819
840
  prop_value = PropValue.from_value_and_labels(value, labels)
820
841
  return prop_value
821
842
 
822
- def load_stack_variable(self, sp_offset: int, size, endness=None) -> Optional[PropValue]:
843
+ def load_stack_variable(self, sp_offset: int, size, endness=None) -> PropValue | None:
823
844
  # normalize sp_offset to handle negative offsets
824
845
  sp_offset += 0x65536
825
846
  sp_offset &= (1 << self.arch.bits) - 1
@@ -847,13 +868,22 @@ class PropagatorAILState(PropagatorState):
847
868
  prop_value = PropValue.from_value_and_labels(value, labels)
848
869
  return prop_value
849
870
 
871
+ def should_replace_reg(self, old_reg_offset: int, bp_as_gpr: bool, new_value) -> bool:
872
+ if old_reg_offset == self.arch.sp_offset or (not bp_as_gpr and old_reg_offset == self.arch.bp_offset):
873
+ return True
874
+ if old_reg_offset in self._artificial_reg_offsets:
875
+ return True
876
+ if isinstance(new_value, ailment.Expr.StackBaseOffset):
877
+ return True
878
+ return False
879
+
850
880
  def add_replacement(
851
881
  self,
852
882
  codeloc: CodeLocation,
853
883
  old,
854
884
  new,
855
885
  force_replace: bool = False,
856
- stmt_to_remove: Optional[CodeLocation] = None,
886
+ stmt_to_remove: CodeLocation | None = None,
857
887
  bp_as_gpr: bool = False,
858
888
  ) -> bool:
859
889
  if self._only_consts:
@@ -889,7 +919,7 @@ class PropagatorAILState(PropagatorState):
889
919
  if (
890
920
  isinstance(old, ailment.Expr.Tmp)
891
921
  or isinstance(old, ailment.Expr.Register)
892
- and (old.reg_offset == self.arch.sp_offset or (not bp_as_gpr and old.reg_offset == self.arch.bp_offset))
922
+ and self.should_replace_reg(old.reg_offset, bp_as_gpr, new)
893
923
  ):
894
924
  self._replacements[codeloc][old] = (
895
925
  new if stmt_to_remove is None else {"expr": new, "stmt_to_remove": stmt_to_remove}
@@ -955,7 +985,7 @@ class PropagatorAILState(PropagatorState):
955
985
 
956
986
  return replaced
957
987
 
958
- def revert_past_replacements(self, replaced_by, to_replace=None, to_replace_def=None) -> Set[CodeLocation]:
988
+ def revert_past_replacements(self, replaced_by, to_replace=None, to_replace_def=None) -> set[CodeLocation]:
959
989
  updated_codelocs = set()
960
990
  if self.model.replacements is not None:
961
991
  for codeloc_ in self._expr_used_locs[to_replace_def if to_replace_def is not None else to_replace]:
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=import-outside-toplevel
2
- from typing import Dict, Any, Union, TYPE_CHECKING
2
+ from typing import Any, Union, TYPE_CHECKING
3
3
 
4
4
  from .. import KnowledgeBasePlugin
5
5
 
@@ -11,7 +11,7 @@ if TYPE_CHECKING:
11
11
  class StructuredCodeManager(KnowledgeBasePlugin):
12
12
  def __init__(self, kb):
13
13
  super().__init__(kb=kb)
14
- self.cached: Dict[Any, "DecompilationCache"] = {}
14
+ self.cached: dict[Any, "DecompilationCache"] = {}
15
15
 
16
16
  def _normalize_key(self, item):
17
17
  if type(item) is not tuple:
@@ -1,6 +1,6 @@
1
1
  # pylint:disable=import-outside-toplevel
2
2
  from functools import wraps
3
- from typing import Optional, List
3
+ from typing import Optional
4
4
 
5
5
  from ... import knowledge_plugins
6
6
  from ...knowledge_plugins.plugin import KnowledgeBasePlugin
@@ -172,7 +172,7 @@ class SyncController(KnowledgeBasePlugin):
172
172
  @init_checker
173
173
  @make_state
174
174
  # pylint:disable=unused-argument,no-self-use
175
- def push_comments(self, comments: List["binsync.data.Comment"], user=None, state=None):
175
+ def push_comments(self, comments: list["binsync.data.Comment"], user=None, state=None):
176
176
  """
177
177
  Push a bunch of comments upwards.
178
178
 
@@ -189,7 +189,7 @@ class SyncController(KnowledgeBasePlugin):
189
189
  @make_state
190
190
  # pylint:disable=unused-argument,no-self-use
191
191
  def push_stack_variables(
192
- self, stack_variables: List[SimStackVariable], var_manager: VariableManagerInternal, user=None, state=None
192
+ self, stack_variables: list[SimStackVariable], var_manager: VariableManagerInternal, user=None, state=None
193
193
  ):
194
194
  """
195
195
 
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=arguments-differ,no-member
2
- from typing import Dict, Optional, TYPE_CHECKING
2
+ from typing import TYPE_CHECKING
3
3
 
4
4
  from ...code_location import CodeLocation
5
5
  from ...serializable import Serializable
@@ -36,8 +36,8 @@ class VariableAccess(Serializable):
36
36
  self.variable: "SimVariable" = variable
37
37
  self.access_type: int = access_type
38
38
  self.location: CodeLocation = location
39
- self.offset: Optional[int] = offset
40
- self.atom_hash: Optional[int] = atom_hash
39
+ self.offset: int | None = offset
40
+ self.atom_hash: int | None = atom_hash
41
41
 
42
42
  def __repr__(self):
43
43
  access_type = {
@@ -90,7 +90,7 @@ class VariableAccess(Serializable):
90
90
 
91
91
  @classmethod
92
92
  def parse_from_cmessage(
93
- cls, cmsg, variable_by_ident: Optional[Dict[str, "SimVariable"]] = None, **kwargs
93
+ cls, cmsg, variable_by_ident: dict[str, "SimVariable"] | None = None, **kwargs
94
94
  ) -> "VariableAccess":
95
95
  assert variable_by_ident is not None
96
96