angr 9.2.131__py3-none-manylinux2014_aarch64.whl → 9.2.133__py3-none-manylinux2014_aarch64.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 (264) hide show
  1. angr/__init__.py +128 -128
  2. angr/analyses/__init__.py +38 -38
  3. angr/analyses/analysis.py +6 -2
  4. angr/analyses/backward_slice.py +3 -4
  5. angr/analyses/binary_optimizer.py +5 -12
  6. angr/analyses/bindiff.py +3 -6
  7. angr/analyses/calling_convention.py +3 -4
  8. angr/analyses/cfg/__init__.py +3 -3
  9. angr/analyses/cfg/cfg_base.py +1 -1
  10. angr/analyses/cfg/cfg_emulated.py +5 -5
  11. angr/analyses/cfg/cfg_fast.py +19 -17
  12. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +5 -5
  13. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
  14. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +148 -101
  15. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
  16. angr/analyses/data_dep/__init__.py +4 -4
  17. angr/analyses/datagraph_meta.py +1 -1
  18. angr/analyses/ddg.py +16 -17
  19. angr/analyses/decompiler/__init__.py +12 -12
  20. angr/analyses/decompiler/ail_simplifier.py +24 -12
  21. angr/analyses/decompiler/block_similarity.py +2 -4
  22. angr/analyses/decompiler/block_simplifier.py +10 -21
  23. angr/analyses/decompiler/callsite_maker.py +1 -1
  24. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
  25. angr/analyses/decompiler/clinic.py +122 -41
  26. angr/analyses/decompiler/condition_processor.py +57 -39
  27. angr/analyses/decompiler/counters/__init__.py +3 -3
  28. angr/analyses/decompiler/decompilation_cache.py +7 -7
  29. angr/analyses/decompiler/dephication/__init__.py +1 -1
  30. angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
  31. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +11 -3
  32. angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
  33. angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
  34. angr/analyses/decompiler/expression_narrower.py +1 -1
  35. angr/analyses/decompiler/graph_region.py +8 -8
  36. angr/analyses/decompiler/optimization_passes/__init__.py +20 -20
  37. angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
  38. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +1 -2
  39. angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
  40. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +8 -7
  41. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +1 -3
  42. angr/analyses/decompiler/optimization_passes/engine_base.py +262 -84
  43. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +175 -39
  44. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +2 -5
  45. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +5 -5
  46. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +12 -3
  47. angr/analyses/decompiler/optimization_passes/optimization_pass.py +42 -19
  48. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +9 -5
  49. angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -1
  50. angr/analyses/decompiler/peephole_optimizations/base.py +6 -6
  51. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +2 -0
  52. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
  53. angr/analyses/decompiler/presets/__init__.py +1 -1
  54. angr/analyses/decompiler/region_simplifiers/expr_folding.py +3 -3
  55. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +8 -12
  56. angr/analyses/decompiler/ssailification/rewriting.py +1 -2
  57. angr/analyses/decompiler/ssailification/rewriting_engine.py +139 -56
  58. angr/analyses/decompiler/ssailification/ssailification.py +2 -1
  59. angr/analyses/decompiler/ssailification/traversal.py +4 -6
  60. angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
  61. angr/analyses/decompiler/structured_codegen/__init__.py +5 -5
  62. angr/analyses/decompiler/structured_codegen/base.py +3 -3
  63. angr/analyses/decompiler/structured_codegen/c.py +39 -40
  64. angr/analyses/decompiler/structuring/__init__.py +3 -3
  65. angr/analyses/decompiler/structuring/phoenix.py +45 -29
  66. angr/analyses/decompiler/structuring/structurer_base.py +2 -2
  67. angr/analyses/decompiler/structuring/structurer_nodes.py +23 -14
  68. angr/analyses/deobfuscator/__init__.py +3 -3
  69. angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
  70. angr/analyses/deobfuscator/string_obf_finder.py +2 -2
  71. angr/analyses/deobfuscator/string_obf_opt_passes.py +1 -1
  72. angr/analyses/disassembly.py +4 -4
  73. angr/analyses/forward_analysis/__init__.py +1 -1
  74. angr/analyses/forward_analysis/visitors/graph.py +6 -6
  75. angr/analyses/init_finder.py +47 -22
  76. angr/analyses/loop_analysis.py +1 -1
  77. angr/analyses/loopfinder.py +1 -1
  78. angr/analyses/propagator/engine_base.py +21 -14
  79. angr/analyses/propagator/engine_vex.py +149 -179
  80. angr/analyses/propagator/outdated_definition_walker.py +12 -6
  81. angr/analyses/propagator/propagator.py +10 -28
  82. angr/analyses/propagator/top_checker_mixin.py +211 -5
  83. angr/analyses/propagator/vex_vars.py +4 -4
  84. angr/analyses/reaching_definitions/__init__.py +9 -9
  85. angr/analyses/reaching_definitions/call_trace.py +2 -2
  86. angr/analyses/reaching_definitions/dep_graph.py +1 -1
  87. angr/analyses/reaching_definitions/engine_ail.py +304 -329
  88. angr/analyses/reaching_definitions/engine_vex.py +243 -229
  89. angr/analyses/reaching_definitions/function_handler.py +3 -3
  90. angr/analyses/reaching_definitions/function_handler_library/__init__.py +1 -1
  91. angr/analyses/reaching_definitions/rd_state.py +47 -42
  92. angr/analyses/reassembler.py +26 -31
  93. angr/analyses/s_liveness.py +8 -0
  94. angr/analyses/s_propagator.py +18 -3
  95. angr/analyses/s_reaching_definitions/s_rda_view.py +2 -5
  96. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
  97. angr/analyses/stack_pointer_tracker.py +4 -4
  98. angr/analyses/typehoon/simple_solver.py +14 -14
  99. angr/analyses/typehoon/translator.py +10 -2
  100. angr/analyses/typehoon/typeconsts.py +11 -3
  101. angr/analyses/typehoon/typevars.py +26 -26
  102. angr/analyses/unpacker/__init__.py +1 -1
  103. angr/analyses/variable_recovery/engine_ail.py +299 -259
  104. angr/analyses/variable_recovery/engine_base.py +138 -121
  105. angr/analyses/variable_recovery/engine_vex.py +175 -185
  106. angr/analyses/variable_recovery/irsb_scanner.py +49 -38
  107. angr/analyses/variable_recovery/variable_recovery.py +28 -5
  108. angr/analyses/variable_recovery/variable_recovery_base.py +33 -34
  109. angr/analyses/variable_recovery/variable_recovery_fast.py +4 -8
  110. angr/analyses/veritesting.py +2 -2
  111. angr/analyses/vfg.py +5 -5
  112. angr/analyses/xrefs.py +46 -19
  113. angr/angrdb/serializers/__init__.py +1 -1
  114. angr/annocfg.py +20 -15
  115. angr/blade.py +2 -2
  116. angr/block.py +20 -25
  117. angr/calling_conventions.py +12 -14
  118. angr/code_location.py +6 -10
  119. angr/codenode.py +3 -3
  120. angr/engines/__init__.py +12 -14
  121. angr/engines/engine.py +24 -61
  122. angr/engines/light/__init__.py +13 -5
  123. angr/engines/light/data.py +1 -1
  124. angr/engines/light/engine.py +1003 -1185
  125. angr/engines/pcode/__init__.py +1 -1
  126. angr/engines/pcode/behavior.py +1 -1
  127. angr/engines/pcode/cc.py +2 -0
  128. angr/engines/pcode/lifter.py +13 -15
  129. angr/engines/soot/expressions/__init__.py +12 -12
  130. angr/engines/soot/statements/__init__.py +6 -6
  131. angr/engines/soot/values/__init__.py +6 -6
  132. angr/engines/soot/values/arrayref.py +2 -2
  133. angr/engines/soot/values/constants.py +1 -1
  134. angr/engines/soot/values/instancefieldref.py +1 -1
  135. angr/engines/soot/values/paramref.py +1 -1
  136. angr/engines/soot/values/staticfieldref.py +1 -1
  137. angr/engines/successors.py +15 -14
  138. angr/engines/vex/__init__.py +5 -5
  139. angr/engines/vex/claripy/ccall.py +2 -2
  140. angr/engines/vex/claripy/datalayer.py +1 -1
  141. angr/engines/vex/claripy/irop.py +19 -19
  142. angr/engines/vex/heavy/__init__.py +2 -2
  143. angr/engines/vex/heavy/actions.py +1 -3
  144. angr/engines/vex/heavy/heavy.py +4 -6
  145. angr/engines/vex/lifter.py +2 -4
  146. angr/engines/vex/light/light.py +0 -2
  147. angr/engines/vex/light/slicing.py +5 -5
  148. angr/exploration_techniques/__init__.py +19 -142
  149. angr/exploration_techniques/base.py +126 -0
  150. angr/exploration_techniques/bucketizer.py +1 -1
  151. angr/exploration_techniques/dfs.py +3 -1
  152. angr/exploration_techniques/director.py +2 -3
  153. angr/exploration_techniques/driller_core.py +1 -1
  154. angr/exploration_techniques/explorer.py +4 -2
  155. angr/exploration_techniques/lengthlimiter.py +2 -1
  156. angr/exploration_techniques/local_loop_seer.py +2 -1
  157. angr/exploration_techniques/loop_seer.py +5 -5
  158. angr/exploration_techniques/manual_mergepoint.py +2 -1
  159. angr/exploration_techniques/memory_watcher.py +3 -1
  160. angr/exploration_techniques/oppologist.py +4 -5
  161. angr/exploration_techniques/slicecutor.py +4 -2
  162. angr/exploration_techniques/spiller.py +1 -1
  163. angr/exploration_techniques/stochastic.py +2 -1
  164. angr/exploration_techniques/stub_stasher.py +2 -1
  165. angr/exploration_techniques/suggestions.py +3 -1
  166. angr/exploration_techniques/symbion.py +3 -1
  167. angr/exploration_techniques/tech_builder.py +2 -1
  168. angr/exploration_techniques/threading.py +2 -11
  169. angr/exploration_techniques/timeout.py +4 -2
  170. angr/exploration_techniques/tracer.py +4 -3
  171. angr/exploration_techniques/unique.py +3 -2
  172. angr/exploration_techniques/veritesting.py +1 -1
  173. angr/factory.py +36 -6
  174. angr/keyed_region.py +4 -4
  175. angr/knowledge_base.py +1 -1
  176. angr/knowledge_plugins/__init__.py +11 -11
  177. angr/knowledge_plugins/cfg/__init__.py +5 -5
  178. angr/knowledge_plugins/cfg/cfg_manager.py +2 -2
  179. angr/knowledge_plugins/cfg/cfg_model.py +8 -8
  180. angr/knowledge_plugins/cfg/cfg_node.py +19 -19
  181. angr/knowledge_plugins/cfg/indirect_jump.py +6 -6
  182. angr/knowledge_plugins/cfg/memory_data.py +5 -7
  183. angr/knowledge_plugins/functions/function.py +48 -52
  184. angr/knowledge_plugins/functions/function_parser.py +4 -4
  185. angr/knowledge_plugins/key_definitions/__init__.py +3 -3
  186. angr/knowledge_plugins/key_definitions/atoms.py +8 -8
  187. angr/knowledge_plugins/key_definitions/definition.py +1 -1
  188. angr/knowledge_plugins/key_definitions/live_definitions.py +30 -27
  189. angr/knowledge_plugins/labels.py +1 -1
  190. angr/knowledge_plugins/propagations/__init__.py +1 -1
  191. angr/knowledge_plugins/propagations/prop_value.py +2 -2
  192. angr/knowledge_plugins/propagations/propagation_model.py +7 -8
  193. angr/knowledge_plugins/propagations/states.py +44 -39
  194. angr/knowledge_plugins/variables/variable_access.py +2 -2
  195. angr/knowledge_plugins/variables/variable_manager.py +24 -10
  196. angr/knowledge_plugins/xrefs/xref.py +5 -8
  197. angr/misc/__init__.py +4 -4
  198. angr/misc/hookset.py +4 -5
  199. angr/misc/loggers.py +2 -2
  200. angr/misc/telemetry.py +1 -1
  201. angr/procedures/__init__.py +1 -1
  202. angr/procedures/cgc/fdwait.py +2 -2
  203. angr/procedures/definitions/__init__.py +2 -2
  204. angr/procedures/definitions/linux_kernel.py +0 -1
  205. angr/procedures/definitions/parse_syscalls_from_local_system.py +1 -1
  206. angr/procedures/definitions/parse_win32json.py +0 -1
  207. angr/procedures/ntdll/exceptions.py +1 -1
  208. angr/procedures/stubs/format_parser.py +3 -3
  209. angr/procedures/win32/dynamic_loading.py +1 -1
  210. angr/protos/__init__.py +3 -3
  211. angr/sim_manager.py +3 -5
  212. angr/sim_state.py +40 -42
  213. angr/sim_state_options.py +3 -3
  214. angr/sim_type.py +15 -14
  215. angr/sim_variable.py +42 -45
  216. angr/simos/__init__.py +4 -4
  217. angr/simos/cgc.py +1 -1
  218. angr/simos/simos.py +1 -1
  219. angr/simos/userland.py +1 -1
  220. angr/slicer.py +4 -7
  221. angr/state_plugins/__init__.py +34 -34
  222. angr/state_plugins/callstack.py +5 -12
  223. angr/state_plugins/heap/__init__.py +2 -2
  224. angr/state_plugins/heap/heap_brk.py +2 -4
  225. angr/state_plugins/heap/heap_ptmalloc.py +1 -1
  226. angr/state_plugins/jni_references.py +3 -2
  227. angr/state_plugins/scratch.py +1 -1
  228. angr/state_plugins/sim_action.py +1 -4
  229. angr/state_plugins/sim_event.py +1 -1
  230. angr/state_plugins/solver.py +7 -9
  231. angr/state_plugins/uc_manager.py +1 -1
  232. angr/state_plugins/view.py +2 -2
  233. angr/storage/__init__.py +1 -1
  234. angr/storage/file.py +10 -10
  235. angr/storage/memory_mixins/__init__.py +46 -46
  236. angr/storage/memory_mixins/default_filler_mixin.py +1 -3
  237. angr/storage/memory_mixins/javavm_memory_mixin.py +2 -2
  238. angr/storage/memory_mixins/name_resolution_mixin.py +2 -2
  239. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -3
  240. angr/storage/memory_mixins/paged_memory/pages/__init__.py +6 -6
  241. angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
  242. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +1 -1
  243. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
  244. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
  245. angr/storage/memory_mixins/regioned_memory/__init__.py +3 -3
  246. angr/storage/memory_mixins/regioned_memory/region_data.py +5 -5
  247. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +7 -9
  248. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +4 -4
  249. angr/storage/memory_object.py +4 -4
  250. angr/utils/__init__.py +3 -3
  251. angr/utils/bits.py +12 -0
  252. angr/utils/dynamic_dictlist.py +1 -1
  253. angr/utils/graph.py +1 -1
  254. angr/utils/orderedset.py +4 -1
  255. angr/utils/segment_list.py +2 -2
  256. angr/utils/ssa/__init__.py +33 -8
  257. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/METADATA +6 -6
  258. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/RECORD +262 -263
  259. angr/analyses/propagator/engine_ail.py +0 -1562
  260. angr/storage/memory_mixins/__init__.pyi +0 -48
  261. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/LICENSE +0 -0
  262. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/WHEEL +0 -0
  263. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/entry_points.txt +0 -0
  264. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/top_level.txt +0 -0
@@ -7,10 +7,9 @@ import logging
7
7
  import pyvex
8
8
  import claripy
9
9
 
10
- from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
11
- from angr.engines.light import SimEngineLight, SimEngineLightVEXMixin, SpOffset
10
+ from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues, mv_is_bv
11
+ from angr.engines.light import SimEngineNostmtVEX, SpOffset
12
12
  from angr.engines.vex.claripy.datalayer import value as claripy_value
13
- from angr.engines.vex.claripy.irop import operations as vex_operations
14
13
  from angr.errors import SimEngineError, SimMemoryMissingError
15
14
  from angr.utils.constants import DEFAULT_STATEMENT
16
15
  from angr.knowledge_plugins.key_definitions.live_definitions import Definition, LiveDefinitions
@@ -29,36 +28,43 @@ if TYPE_CHECKING:
29
28
 
30
29
  l = logging.getLogger(name=__name__)
31
30
 
31
+ unop_handler = SimEngineNostmtVEX[
32
+ ReachingDefinitionsState, MultiValues[claripy.ast.BV | claripy.ast.FP], ReachingDefinitionsState
33
+ ].unop_handler
34
+ binop_handler = SimEngineNostmtVEX[
35
+ ReachingDefinitionsState, MultiValues[claripy.ast.BV | claripy.ast.FP], ReachingDefinitionsState
36
+ ].binop_handler
37
+
32
38
 
33
39
  class SimEngineRDVEX(
34
- SimEngineLightVEXMixin,
35
- SimEngineLight,
40
+ SimEngineNostmtVEX[
41
+ ReachingDefinitionsState, MultiValues[claripy.ast.BV | claripy.ast.FP], ReachingDefinitionsState
42
+ ],
36
43
  ): # pylint:disable=abstract-method
37
44
  """
38
45
  Implements the VEX execution engine for reaching definition analysis.
39
46
  """
40
47
 
41
- state: ReachingDefinitionsState
42
-
43
- def __init__(self, project, functions=None, function_handler=None):
44
- super().__init__()
45
- self.project = project
46
- self.functions: FunctionManager | None = functions
47
- self._function_handler: FunctionHandler | None = function_handler
48
+ def __init__(self, project, function_handler: FunctionHandler, functions: FunctionManager):
49
+ super().__init__(project)
50
+ self.functions = functions
51
+ self._function_handler = function_handler
48
52
  self._visited_blocks = None
49
53
  self._dep_graph = None
50
54
 
51
55
  self.state: ReachingDefinitionsState
52
56
 
53
- def process(self, state, *args, block=None, fail_fast=False, visited_blocks=None, dep_graph=None, **kwargs):
57
+ def process(
58
+ self, state, *, block=None, fail_fast=False, visited_blocks=None, dep_graph=None, whitelist=None, **kwargs
59
+ ):
54
60
  self._visited_blocks = visited_blocks
55
61
  self._dep_graph = dep_graph
56
62
  # we are using a completely different state. Therefore, we directly call our _process() method before
57
63
  # SimEngine becomes flexible enough.
58
64
  try:
59
- self._process(
65
+ return super().process(
60
66
  state,
61
- None,
67
+ whitelist=whitelist,
62
68
  block=block,
63
69
  )
64
70
  except SimEngineError as e:
@@ -67,16 +73,16 @@ class SimEngineRDVEX(
67
73
  l.error(e)
68
74
  return self.state
69
75
 
70
- def _process_block_end(self):
76
+ def _process_block_end(self, stmt_result, whitelist):
71
77
  self.stmt_idx = DEFAULT_STATEMENT
72
78
  self._set_codeloc()
73
79
  if self.block.vex.jumpkind == "Ijk_Call":
74
80
  # it has to be a function
75
- addr = self._expr(self.block.vex.next)
81
+ addr = self._expr_bv(self.block.vex.next)
76
82
  self._handle_function(addr)
77
83
  elif self.block.vex.jumpkind == "Ijk_Boring":
78
84
  # test if the target addr is a function or not
79
- addr = self._expr(self.block.vex.next)
85
+ addr = self._expr_bv(self.block.vex.next)
80
86
  addr_v = addr.one_value()
81
87
  if addr_v is not None and addr_v.concrete:
82
88
  addr_int = addr_v.concrete_value
@@ -84,10 +90,28 @@ class SimEngineRDVEX(
84
90
  # yes it's a jump to a function
85
91
  self._handle_function(addr)
86
92
 
93
+ return self.state
94
+
87
95
  #
88
96
  # Private methods
89
97
  #
90
98
 
99
+ def _expr_bv(self, expr: pyvex.expr.IRExpr) -> MultiValues[claripy.ast.BV]:
100
+ result = self._expr(expr)
101
+ assert mv_is_bv(result)
102
+ return result
103
+
104
+ def _expr_pair(
105
+ self, arg0: pyvex.expr.IRExpr, arg1: pyvex.expr.IRExpr
106
+ ) -> (
107
+ tuple[MultiValues[claripy.ast.BV], MultiValues[claripy.ast.BV]]
108
+ | tuple[MultiValues[claripy.ast.FP], MultiValues[claripy.ast.FP]]
109
+ ):
110
+ r0 = self._expr(arg0)
111
+ r1 = self._expr(arg1)
112
+ assert type(r0) is type(r1)
113
+ return r0, r1 # type: ignore
114
+
91
115
  def _external_codeloc(self):
92
116
  return ExternalCodeLocation(self.state.codeloc.context)
93
117
 
@@ -106,34 +130,29 @@ class SimEngineRDVEX(
106
130
  """
107
131
  return False
108
132
 
109
- def _top(self, size) -> MultiValues:
110
- """
111
- Because _is_top is always False, this method is only very rarely called.
112
- Currently, it is only expected to be called from the _handle_Cmp*_v methods that aren't
113
- implemented in the SimEngineLightVexMixin, which then falls back to returning top
114
- :param size:
115
- :return:
116
- """
117
- return MultiValues(self.state.top(size))
133
+ def _top(self, bits) -> MultiValues[claripy.ast.BV | claripy.ast.FP]:
134
+ return MultiValues(self.state.top(bits))
118
135
 
119
136
  #
120
137
  # VEX statement handlers
121
138
  #
122
139
 
123
- def _handle_Stmt(self, stmt):
140
+ def _stmt(self, stmt):
124
141
  if self.state.analysis:
125
142
  self.state.analysis.stmt_observe(self.stmt_idx, stmt, self.block, self.state, OP_BEFORE)
126
143
  self.state.analysis.insn_observe(self.ins_addr, stmt, self.block, self.state, OP_BEFORE)
127
144
 
128
145
  self._set_codeloc()
129
- super()._handle_Stmt(stmt)
146
+ result = super()._stmt(stmt)
130
147
 
131
148
  if self.state.analysis:
132
149
  self.state.analysis.stmt_observe(self.stmt_idx, stmt, self.block, self.state, OP_AFTER)
133
150
  self.state.analysis.insn_observe(self.ins_addr, stmt, self.block, self.state, OP_AFTER)
134
151
 
135
- def _handle_WrTmp(self, stmt: pyvex.IRStmt.WrTmp):
136
- data: MultiValues = self._expr(stmt.data)
152
+ return result
153
+
154
+ def _handle_stmt_WrTmp(self, stmt):
155
+ data = self._expr(stmt.data)
137
156
 
138
157
  tmp_atom = Tmp(stmt.tmp, self.tyenv.sizeof(stmt.tmp) // self.arch.byte_width)
139
158
  # if len(data.values) == 1 and 0 in data.values:
@@ -151,15 +170,10 @@ class SimEngineRDVEX(
151
170
  data,
152
171
  )
153
172
 
154
- def _handle_WrTmpData(self, tmp: int, data):
155
- super()._handle_WrTmpData(tmp, data)
156
- self.state.kill_and_add_definition(Tmp(tmp, self.tyenv.sizeof(tmp)), self.tmps[tmp])
157
-
158
173
  # e.g. PUT(rsp) = t2, t2 might include multiple values
159
- def _handle_Put(self, stmt):
160
- reg_offset: int = stmt.offset
174
+ def _handle_stmt_Put(self, stmt):
161
175
  size: int = stmt.data.result_size(self.tyenv) // 8
162
- reg = Register(reg_offset, size, self.arch)
176
+ reg = Register(stmt.offset, size, self.arch)
163
177
  data = self._expr(stmt.data)
164
178
 
165
179
  # special handling for references to heap or stack variables
@@ -174,16 +188,16 @@ class SimEngineRDVEX(
174
188
  if stack_offset is not None:
175
189
  self.state.add_stack_use(stack_offset, 1)
176
190
 
177
- if self.state.exit_observed and reg_offset == self.arch.sp_offset:
191
+ if self.state.exit_observed and stmt.offset == self.arch.sp_offset:
178
192
  return
179
193
  self.state.kill_and_add_definition(reg, data)
180
194
 
181
- def _handle_PutI(self, stmt):
195
+ def _handle_stmt_PutI(self, stmt):
182
196
  pass
183
197
 
184
198
  # e.g. STle(t6) = t21, t6 and/or t21 might include multiple values
185
- def _handle_Store(self, stmt):
186
- addr = self._expr(stmt.addr)
199
+ def _handle_stmt_Store(self, stmt):
200
+ addr = self._expr_bv(stmt.addr)
187
201
  size = stmt.data.result_size(self.tyenv) // 8
188
202
  data = self._expr(stmt.data)
189
203
 
@@ -191,23 +205,23 @@ class SimEngineRDVEX(
191
205
  addrs = next(iter(addr.values()))
192
206
  self._store_core(addrs, size, data, endness=stmt.endness)
193
207
 
194
- def _handle_StoreG(self, stmt: pyvex.IRStmt.StoreG):
195
- guard = self._expr(stmt.guard)
208
+ def _handle_stmt_StoreG(self, stmt):
209
+ guard = self._expr_bv(stmt.guard)
196
210
  guard_v = guard.one_value()
197
211
 
198
- if claripy.is_true(guard_v):
199
- addr = self._expr(stmt.addr)
212
+ if guard_v is not None and claripy.is_true(guard_v != 0):
213
+ addr = self._expr_bv(stmt.addr)
200
214
  if addr.count() == 1:
201
215
  addrs = next(iter(addr.values()))
202
216
  size = stmt.data.result_size(self.tyenv) // 8
203
217
  data = self._expr(stmt.data)
204
218
  self._store_core(addrs, size, data)
205
- elif claripy.is_false(guard_v):
219
+ elif guard_v is not None and claripy.is_false(guard_v != 0):
206
220
  pass
207
221
  else:
208
222
  # guard.data == {True, False}
209
223
  # get current data
210
- addr = self._expr(stmt.addr)
224
+ addr = self._expr_bv(stmt.addr)
211
225
  if addr.count() == 1:
212
226
  addrs = next(iter(addr.values()))
213
227
  size = stmt.data.result_size(self.tyenv) // 8
@@ -270,20 +284,20 @@ class SimEngineRDVEX(
270
284
  # with same index and same size
271
285
  self.state.kill_and_add_definition(atom, data, tags=tags, endness=endness)
272
286
 
273
- def _handle_LoadG(self, stmt):
274
- guard = self._expr(stmt.guard)
287
+ def _handle_stmt_LoadG(self, stmt):
288
+ guard = self._expr_bv(stmt.guard)
275
289
  guard_v = guard.one_value()
276
290
 
277
- if claripy.is_true(guard_v):
291
+ if guard_v is not None and claripy.is_true(guard_v != 0):
278
292
  # FIXME: full conversion support
279
293
  if stmt.cvt.find("Ident") < 0:
280
294
  l.warning("Unsupported conversion %s in LoadG.", stmt.cvt)
281
295
  load_expr = pyvex.expr.Load(stmt.end, stmt.cvt_types[1], stmt.addr)
282
296
  wr_tmp_stmt = pyvex.stmt.WrTmp(stmt.dst, load_expr)
283
- self._handle_WrTmp(wr_tmp_stmt)
284
- elif claripy.is_false(guard_v):
297
+ self._handle_stmt_WrTmp(wr_tmp_stmt)
298
+ elif guard_v is not None and claripy.is_false(guard_v != 0):
285
299
  wr_tmp_stmt = pyvex.stmt.WrTmp(stmt.dst, stmt.alt)
286
- self._handle_WrTmp(wr_tmp_stmt)
300
+ self._handle_stmt_WrTmp(wr_tmp_stmt)
287
301
  else:
288
302
  if stmt.cvt.find("Ident") < 0:
289
303
  l.warning("Unsupported conversion %s in LoadG.", stmt.cvt)
@@ -293,9 +307,9 @@ class SimEngineRDVEX(
293
307
  alt_v = self._expr(stmt.alt)
294
308
 
295
309
  data = load_expr_v.merge(alt_v)
296
- self._handle_WrTmpData(stmt.dst, data)
310
+ self.state.kill_and_add_definition(Tmp(stmt.dst, self.tyenv.sizeof(stmt.dst)), data)
297
311
 
298
- def _handle_Exit(self, stmt):
312
+ def _handle_stmt_Exit(self, stmt):
299
313
  _ = self._expr(stmt.guard)
300
314
  target = stmt.dst.value
301
315
  self.state.mark_guard(target)
@@ -305,7 +319,6 @@ class SimEngineRDVEX(
305
319
  self.stmt_idx,
306
320
  self.block,
307
321
  self.state,
308
- node_idx=self.block.block_idx if hasattr(self.block, "block_idx") else None,
309
322
  )
310
323
  if (
311
324
  self.block.instruction_addrs
@@ -314,16 +327,16 @@ class SimEngineRDVEX(
314
327
  ):
315
328
  self.state.exit_observed = True
316
329
 
317
- def _handle_IMark(self, stmt):
330
+ def _handle_stmt_IMark(self, stmt):
318
331
  pass
319
332
 
320
- def _handle_AbiHint(self, stmt):
333
+ def _handle_stmt_AbiHint(self, stmt):
321
334
  pass
322
335
 
323
- def _handle_LLSC(self, stmt: pyvex.IRStmt.LLSC):
336
+ def _handle_stmt_LLSC(self, stmt):
324
337
  if stmt.storedata is None:
325
338
  # load-link
326
- addr = self._expr(stmt.addr)
339
+ addr = self._expr_bv(stmt.addr)
327
340
  if addr.count() == 1:
328
341
  addrs = next(iter(addr.values()))
329
342
  size = self.tyenv.sizeof(stmt.result) // self.arch.byte_width
@@ -336,12 +349,13 @@ class SimEngineRDVEX(
336
349
  else:
337
350
  # store-conditional
338
351
  storedata = self._expr(stmt.storedata)
339
- addr = self._expr(stmt.addr)
352
+ addr = self._expr_bv(stmt.addr)
340
353
  if addr.count() == 1:
341
354
  addrs = next(iter(addr.values()))
342
- if isinstance(stmt.storedata, pyvex.IRExpr.Const):
355
+ if isinstance(stmt.storedata, pyvex.expr.Const):
343
356
  size = stmt.storedata.con.size // self.arch.byte_width
344
357
  else:
358
+ assert isinstance(stmt.storedata, pyvex.expr.RdTmp)
345
359
  size = self.tyenv.sizeof(stmt.storedata.tmp) // self.arch.byte_width
346
360
 
347
361
  self._store_core(addrs, size, storedata)
@@ -355,32 +369,21 @@ class SimEngineRDVEX(
355
369
  # VEX expression handlers
356
370
  #
357
371
 
358
- def _expr(self, expr) -> MultiValues:
359
- data = super()._expr(expr)
360
- if data is None:
361
- bits = expr.result_size(self.tyenv)
362
- top = self.state.top(bits)
363
- data = MultiValues(top)
364
- return data
372
+ def _handle_expr_RdTmp(self, expr: pyvex.expr.RdTmp):
373
+ self.state.add_tmp_use(expr.tmp)
365
374
 
366
- def _handle_RdTmp(self, expr: pyvex.IRExpr.RdTmp) -> MultiValues | None:
367
- tmp: int = expr.tmp
368
-
369
- self.state.add_tmp_use(tmp)
370
-
371
- if tmp in self.tmps:
372
- return self.tmps[tmp]
373
- return None
375
+ if expr.tmp in self.tmps:
376
+ return self.tmps[expr.tmp]
377
+ return self._top(pyvex.get_type_size(self.tyenv.lookup(expr.tmp)))
374
378
 
375
379
  # e.g. t0 = GET:I64(rsp), rsp might be defined multiple times
376
- def _handle_Get(self, expr: pyvex.IRExpr.Get) -> MultiValues:
377
- reg_offset: int = expr.offset
380
+ def _handle_expr_Get(self, expr: pyvex.expr.Get):
378
381
  bits: int = expr.result_size(self.tyenv)
379
382
  size: int = bits // self.arch.byte_width
380
383
 
381
- reg_atom = Register(reg_offset, size, self.arch)
384
+ reg_atom = Register(expr.offset, size, self.arch)
382
385
  try:
383
- values: MultiValues = self.state.registers.load(reg_offset, size=size)
386
+ values: MultiValues = self.state.registers.load(expr.offset, size=size)
384
387
  except SimMemoryMissingError:
385
388
  top = self.state.top(size * self.arch.byte_width)
386
389
  # annotate it
@@ -389,7 +392,7 @@ class SimEngineRDVEX(
389
392
  # write it to registers
390
393
  self.state.kill_and_add_definition(reg_atom, values, override_codeloc=self._external_codeloc())
391
394
 
392
- current_defs: Iterable[Definition] | None = None
395
+ current_defs: Iterable[Definition[Atom]] | None = None
393
396
  for vs in values.values():
394
397
  for v in vs:
395
398
  if current_defs is None:
@@ -397,32 +400,24 @@ class SimEngineRDVEX(
397
400
  else:
398
401
  current_defs = chain(current_defs, self.state.extract_defs(v))
399
402
 
400
- if current_defs is None:
401
- # no defs can be found. add a fake definition
402
- mv = self.state.kill_and_add_definition(reg_atom, values, override_codeloc=self._external_codeloc())
403
- current_defs = set()
404
- for vs in mv.values():
405
- for v in vs:
406
- current_defs |= self.state.extract_defs(v)
407
-
403
+ assert current_defs is not None
408
404
  self.state.add_register_use_by_defs(current_defs)
409
405
 
410
406
  return values
411
407
 
412
- def _handle_GetI(self, expr: pyvex.IRExpr.GetI) -> MultiValues:
408
+ def _handle_expr_GetI(self, expr) -> MultiValues[claripy.ast.BV | claripy.ast.FP]:
413
409
  return MultiValues(self.state.top(expr.result_size(self.tyenv)))
414
410
 
415
411
  # e.g. t27 = LDle:I64(t9), t9 might include multiple values
416
412
  # caution: Is also called from StoreG
417
- def _handle_Load(self, expr) -> MultiValues:
418
- addr = self._expr(expr.addr)
413
+ def _handle_expr_Load(self, expr) -> MultiValues[claripy.ast.BV | claripy.ast.FP]:
414
+ addr = self._expr_bv(expr.addr)
419
415
  bits = expr.result_size(self.tyenv)
420
416
  size = bits // self.arch.byte_width
421
417
 
422
418
  # convert addr from MultiValues to a list of valid addresses
423
- if addr.count() == 1 and 0 in addr:
424
- addrs = list(addr[0])
425
- return self._load_core(addrs, size, expr.endness)
419
+ if (one_addr := addr.one_value()) is not None:
420
+ return self._load_core([one_addr], size, expr.endness)
426
421
 
427
422
  top = self.state.top(bits)
428
423
  # annotate it
@@ -433,7 +428,9 @@ class SimEngineRDVEX(
433
428
  self.state.add_memory_use_by_def(def_)
434
429
  return MultiValues(top)
435
430
 
436
- def _load_core(self, addrs: Iterable[claripy.ast.Base], size: int, endness: str) -> MultiValues:
431
+ def _load_core(
432
+ self, addrs: Iterable[claripy.ast.BV], size: int, endness: str
433
+ ) -> MultiValues[claripy.ast.BV | claripy.ast.FP]:
437
434
  result: MultiValues | None = None
438
435
  # we may get more than one stack addrs with the same value but different annotations (because they are defined
439
436
  # at different locations). only load them once.
@@ -506,7 +503,7 @@ class SimEngineRDVEX(
506
503
  return result
507
504
 
508
505
  # CAUTION: experimental
509
- def _handle_ITE(self, expr: pyvex.IRExpr.ITE):
506
+ def _handle_expr_ITE(self, expr):
510
507
  cond = self._expr(expr.cond)
511
508
  cond_v = cond.one_value()
512
509
  iftrue = self._expr(expr.iftrue)
@@ -522,51 +519,40 @@ class SimEngineRDVEX(
522
519
  # Unary operation handlers
523
520
  #
524
521
 
525
- def _handle_Const(self, expr) -> MultiValues:
522
+ def _handle_expr_Const(self, expr):
526
523
  clrp = claripy_value(expr.con.type, expr.con.value)
527
524
  self.state.mark_const(expr.con.value, len(clrp) // 8)
528
525
  return MultiValues(clrp)
529
526
 
530
- def _handle_Conversion(self, expr):
531
- simop = vex_operations[expr.op]
532
- bits = int(simop.op_attrs["to_size"])
533
- arg_0 = self._expr(expr.args[0])
527
+ def _handle_conversion(self, from_size, to_size, signed, operand) -> MultiValues[claripy.ast.BV | claripy.ast.FP]:
528
+ arg_0 = self._expr_bv(operand)
534
529
 
535
530
  # if there are multiple values with only one offset, we apply conversion to each one of them
536
531
  # otherwise, we return a TOP
537
532
 
538
533
  if arg_0.count() == 1:
539
534
  # extension, extract, or doing nothing
540
- data = set()
535
+ data: set[claripy.ast.BV | claripy.ast.FP] = set()
541
536
  for v in next(iter(arg_0.values())):
542
- if bits > v.size():
543
- data.add(v.zero_extend(bits - v.size()))
544
- else:
545
- if isinstance(v, claripy.ast.fp.FP):
546
- data.add(v.val_to_bv(bits))
537
+ assert v.size() == from_size
538
+ if to_size > from_size:
539
+ if signed:
540
+ data.add(v.sign_extend(to_size - from_size))
547
541
  else:
548
- data.add(v[bits - 1 : 0])
549
- r = MultiValues(offset_to_values={next(iter(arg_0.keys())): data})
542
+ data.add(v.zero_extend(to_size - from_size))
543
+ else:
544
+ data.add(v[to_size - 1 : 0])
545
+ r = MultiValues({next(iter(arg_0.keys())): data})
550
546
 
551
547
  else:
552
- r = MultiValues(self.state.top(bits))
548
+ r = self._top(to_size)
553
549
 
554
550
  return r
555
551
 
556
- def _handle_Not1(self, expr):
557
- arg0 = expr.args[0]
558
- expr_0 = self._expr(arg0)
559
-
560
- e0 = expr_0.one_value()
561
-
562
- if e0 is not None and not e0.symbolic:
563
- return MultiValues(claripy.BVV(1, 1) if e0.concrete_value != 1 else claripy.BVV(0, 1))
564
-
565
- return MultiValues(self.state.top(1))
566
-
567
- def _handle_Not(self, expr):
552
+ @unop_handler
553
+ def _handle_unop_Not(self, expr):
568
554
  arg0 = expr.args[0]
569
- expr_0 = self._expr(arg0)
555
+ expr_0 = self._expr_bv(arg0)
570
556
  bits = expr.result_size(self.tyenv)
571
557
 
572
558
  e0 = expr_0.one_value()
@@ -576,14 +562,16 @@ class SimEngineRDVEX(
576
562
 
577
563
  return MultiValues(self.state.top(bits))
578
564
 
579
- def _handle_Clz(self, expr):
565
+ @unop_handler
566
+ def _handle_unop_Clz(self, expr):
580
567
  arg0 = expr.args[0]
581
568
  _ = self._expr(arg0)
582
569
  bits = expr.result_size(self.tyenv)
583
570
  # Need to actually implement this later
584
571
  return MultiValues(self.state.top(bits))
585
572
 
586
- def _handle_Ctz(self, expr):
573
+ @unop_handler
574
+ def _handle_unop_Ctz(self, expr):
587
575
  arg0 = expr.args[0]
588
576
  _ = self._expr(arg0)
589
577
  bits = expr.result_size(self.tyenv)
@@ -593,29 +581,30 @@ class SimEngineRDVEX(
593
581
  #
594
582
  # Binary operation handlers
595
583
  #
596
- def _handle_ExpCmpNE64(self, expr):
584
+ @binop_handler
585
+ def _handle_binop_ExpCmpNE64(self, expr):
597
586
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
598
587
  bits = expr.result_size(self.tyenv)
599
588
  # Need to actually implement this later
600
589
  return MultiValues(self.state.top(bits))
601
590
 
602
- def _handle_16HLto32(self, expr):
603
- _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
604
- bits = expr.result_size(self.tyenv)
605
- # Need to actually implement this later
606
- return MultiValues(self.state.top(bits))
591
+ @binop_handler
592
+ def _handle_binop_16HLto32(self, expr):
593
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
594
+ return expr0.concat(expr1)
607
595
 
608
- def _handle_Add(self, expr):
609
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
596
+ @binop_handler
597
+ def _handle_binop_Add(self, expr):
598
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
610
599
  bits = expr.result_size(self.tyenv)
611
600
 
612
601
  r = None
613
602
  expr0_v = expr0.one_value()
614
603
  expr1_v = expr1.one_value()
615
604
 
616
- if expr0_v is None and expr1_v is None:
617
- # we do not support addition between two real multivalues
618
- r = MultiValues(self.state.top(bits))
605
+ if expr0_v is not None and expr1_v is not None:
606
+ # adding two single values together
607
+ r = MultiValues(expr0_v + expr1_v)
619
608
  elif expr0_v is None and expr1_v is not None:
620
609
  # adding a single value to a multivalue
621
610
  if expr0.count() == 1 and 0 in expr0:
@@ -627,25 +616,26 @@ class SimEngineRDVEX(
627
616
  vs = {expr0_v + v.sign_extend(expr0_v.size() - v.size()) for v in expr1[0]}
628
617
  r = MultiValues(offset_to_values={0: vs})
629
618
  else:
630
- # adding two single values together
631
- r = MultiValues(expr0_v + expr1_v)
619
+ # we do not support addition between two real multivalues
620
+ r = MultiValues(self.state.top(bits))
632
621
 
633
622
  if r is None:
634
623
  r = MultiValues(self.state.top(bits))
635
624
 
636
625
  return r
637
626
 
638
- def _handle_Sub(self, expr):
639
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
627
+ @binop_handler
628
+ def _handle_binop_Sub(self, expr):
629
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
640
630
  bits = expr.result_size(self.tyenv)
641
631
 
642
632
  r = None
643
633
  expr0_v = expr0.one_value()
644
634
  expr1_v = expr1.one_value()
645
635
 
646
- if expr0_v is None and expr1_v is None:
647
- # we do not support addition between two real multivalues
648
- r = MultiValues(self.state.top(bits))
636
+ if expr0_v is not None and expr1_v is not None:
637
+ # subtracting a single value from another single value
638
+ r = MultiValues(expr0_v - expr1_v)
649
639
  elif expr0_v is None and expr1_v is not None:
650
640
  # subtracting a single value from a multivalue
651
641
  if expr0.count() == 1 and 0 in expr0:
@@ -657,16 +647,17 @@ class SimEngineRDVEX(
657
647
  vs = {expr0_v - v for v in expr1[0]}
658
648
  r = MultiValues(offset_to_values={0: vs})
659
649
  else:
660
- # subtracting a single value from another single value
661
- r = MultiValues(expr0_v - expr1_v)
650
+ # we do not support addition between two real multivalues
651
+ r = MultiValues(self.state.top(bits))
662
652
 
663
653
  if r is None:
664
654
  r = MultiValues(self.state.top(bits))
665
655
 
666
656
  return r
667
657
 
668
- def _handle_Mul(self, expr):
669
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
658
+ @binop_handler
659
+ def _handle_binop_Mul(self, expr):
660
+ expr0, expr1 = self._expr_pair(expr.args[0], expr.args[1])
670
661
  bits = expr.result_size(self.tyenv)
671
662
 
672
663
  r = None
@@ -679,59 +670,64 @@ class SimEngineRDVEX(
679
670
  elif expr0_v is None and expr1_v is not None:
680
671
  # multiplying a single value to a multivalue
681
672
  if expr0.count() == 1 and 0 in expr0:
682
- vs = {v * expr1_v for v in expr0[0]}
673
+ vs = {v * expr1_v for v in expr0[0]} # type: ignore
683
674
  r = MultiValues(offset_to_values={0: vs})
684
675
  elif expr0_v is not None and expr1_v is None:
685
676
  # multiplying a single value to a multivalue
686
677
  if expr1.count() == 1 and 0 in expr1:
687
- vs = {v * expr0_v for v in expr1[0]}
678
+ vs = {v * expr0_v for v in expr1[0]} # type: ignore
688
679
  r = MultiValues(offset_to_values={0: vs})
689
680
  else:
690
681
  # multiplying two single values together
691
- r = MultiValues(expr0_v * expr1_v)
682
+ r = MultiValues(expr0_v * expr1_v) # type: ignore
692
683
 
693
684
  if r is None:
694
685
  r = MultiValues(self.state.top(bits))
695
686
 
696
687
  return r
697
688
 
698
- def _handle_Mull(self, expr):
689
+ @binop_handler
690
+ def _handle_binop_Mull(self, expr):
699
691
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
700
692
  bits = expr.result_size(self.tyenv)
701
693
  return MultiValues(self.state.top(bits))
702
694
 
703
- def _handle_Div(self, expr):
704
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
695
+ @binop_handler
696
+ def _handle_binop_Div(self, expr):
697
+ expr0, expr1 = self._expr_pair(expr.args[0], expr.args[1])
705
698
  bits = expr.result_size(self.tyenv)
706
699
 
707
700
  r = None
708
701
  expr0_v = expr0.one_value()
709
702
  expr1_v = expr1.one_value()
710
703
 
711
- if expr0_v is None and expr1_v is None:
712
- # we do not support division between two real multivalues
713
- r = MultiValues(self.state.top(bits))
704
+ if expr0_v is not None and expr1_v is not None:
705
+ if expr0_v.concrete and expr1_v.concrete:
706
+ # dividing two single values
707
+ r = (
708
+ MultiValues(self.state.top(bits)) if expr1_v.concrete_value == 0 else MultiValues(expr0_v / expr1_v)
709
+ ) # type: ignore
714
710
  elif expr0_v is None and expr1_v is not None:
715
711
  if expr1_v.concrete and expr1_v.concrete_value == 0:
716
712
  r = MultiValues(self.state.top(bits))
717
713
  elif expr0.count() == 1 and 0 in expr0:
718
- vs = {v / expr1_v for v in expr0[0]}
714
+ vs = {v / expr1_v for v in expr0[0]} # type: ignore
719
715
  r = MultiValues(offset_to_values={0: vs})
720
716
  elif expr0_v is not None and expr1_v is None:
721
717
  if expr1.count() == 1 and 0 in expr1:
722
- vs = {expr0_v / v for v in expr1[0] if (not v.concrete) or v.concrete_value != 0}
718
+ vs = {expr0_v / v for v in expr1[0] if (not v.concrete) or v.concrete_value != 0} # type: ignore
723
719
  r = MultiValues(offset_to_values={0: vs})
724
720
  else:
725
- if expr0_v.concrete and expr1_v.concrete:
726
- # dividing two single values
727
- r = MultiValues(self.state.top(bits)) if expr1_v.concrete_value == 0 else MultiValues(expr0_v / expr1_v)
721
+ # we do not support division between two real multivalues
722
+ r = MultiValues(self.state.top(bits))
728
723
 
729
724
  if r is None:
730
725
  r = MultiValues(self.state.top(bits))
731
726
 
732
727
  return r
733
728
 
734
- def _handle_DivMod(self, expr):
729
+ @binop_handler
730
+ def _handle_binop_DivMod(self, expr):
735
731
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
736
732
  bits = expr.result_size(self.tyenv)
737
733
 
@@ -742,17 +738,19 @@ class SimEngineRDVEX(
742
738
  bits = expr.result_size(self.tyenv)
743
739
  return MultiValues(self.state.top(bits))
744
740
 
745
- def _handle_And(self, expr):
746
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
741
+ @binop_handler
742
+ def _handle_binop_And(self, expr):
743
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
747
744
  bits = expr.result_size(self.tyenv)
748
745
 
749
746
  r = None
750
747
  expr0_v = expr0.one_value()
751
748
  expr1_v = expr1.one_value()
752
749
 
753
- if expr0_v is None and expr1_v is None:
754
- # we do not support addition between two real multivalues
755
- r = MultiValues(self.state.top(bits))
750
+ if expr0_v is not None and expr1_v is not None:
751
+ if expr0_v.concrete and expr1_v.concrete:
752
+ # bitwise-and two single values together
753
+ r = MultiValues(expr0_v & expr1_v)
756
754
  elif expr0_v is None and expr1_v is not None:
757
755
  # bitwise-and a single value with a multivalue
758
756
  if expr0.count() == 1 and 0 in expr0:
@@ -764,26 +762,27 @@ class SimEngineRDVEX(
764
762
  vs = {v & expr0_v for v in expr1[0]}
765
763
  r = MultiValues(offset_to_values={0: vs})
766
764
  else:
767
- if expr0_v.concrete and expr1_v.concrete:
768
- # bitwise-and two single values together
769
- r = MultiValues(expr0_v & expr1_v)
765
+ # we do not support addition between two real multivalues
766
+ r = MultiValues(self.state.top(bits))
770
767
 
771
768
  if r is None:
772
769
  r = MultiValues(self.state.top(bits))
773
770
 
774
771
  return r
775
772
 
776
- def _handle_Xor(self, expr):
777
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
773
+ @binop_handler
774
+ def _handle_binop_Xor(self, expr):
775
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
778
776
  bits = expr.result_size(self.tyenv)
779
777
 
780
778
  r = None
781
779
  expr0_v = expr0.one_value()
782
780
  expr1_v = expr1.one_value()
783
781
 
784
- if expr0_v is None and expr1_v is None:
785
- # we do not support xor between two real multivalues
786
- r = MultiValues(self.state.top(bits))
782
+ if expr0_v is not None and expr1_v is not None:
783
+ if expr0_v.concrete and expr1_v.concrete:
784
+ # bitwise-xor two single values together
785
+ r = MultiValues(expr0_v ^ expr1_v)
787
786
  elif expr0_v is None and expr1_v is not None:
788
787
  # bitwise-xor a single value with a multivalue
789
788
  if expr0.count() == 1 and 0 in expr0:
@@ -795,26 +794,26 @@ class SimEngineRDVEX(
795
794
  vs = {v.sign_extend(expr0_v.size() - v.size()) ^ expr0_v for v in expr1[0]}
796
795
  r = MultiValues(offset_to_values={0: vs})
797
796
  else:
798
- if expr0_v.concrete and expr1_v.concrete:
799
- # bitwise-xor two single values together
800
- r = MultiValues(expr0_v ^ expr1_v)
797
+ # we do not support xor between two real multivalues
798
+ r = MultiValues(self.state.top(bits))
801
799
 
802
800
  if r is None:
803
801
  r = MultiValues(self.state.top(bits))
804
802
 
805
803
  return r
806
804
 
807
- def _handle_Or(self, expr):
808
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
805
+ @binop_handler
806
+ def _handle_binop_Or(self, expr):
807
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
809
808
  bits = expr.result_size(self.tyenv)
810
809
 
811
810
  r = None
812
811
  expr0_v = expr0.one_value()
813
812
  expr1_v = expr1.one_value()
814
813
 
815
- if expr0_v is None and expr1_v is None:
816
- # we do not support or between two real multivalues
817
- r = MultiValues(self.state.top(bits))
814
+ if expr0_v is not None and expr1_v is not None:
815
+ # bitwise-and two single values together
816
+ r = MultiValues(expr0_v | expr1_v)
818
817
  elif expr0_v is None and expr1_v is not None:
819
818
  # bitwise-or a single value with a multivalue
820
819
  if expr0.count() == 1 and 0 in expr0:
@@ -826,37 +825,38 @@ class SimEngineRDVEX(
826
825
  vs = {v | expr0_v for v in expr1[0]}
827
826
  r = MultiValues(offset_to_values={0: vs})
828
827
  else:
829
- # bitwise-and two single values together
830
- r = MultiValues(expr0_v | expr1_v)
828
+ # we do not support or between two real multivalues
829
+ r = MultiValues(self.state.top(bits))
831
830
 
832
831
  if r is None:
833
832
  r = MultiValues(self.state.top(bits))
834
833
 
835
834
  return r
836
835
 
837
- def _handle_Sar(self, expr):
838
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
836
+ @binop_handler
837
+ def _handle_binop_Sar(self, expr):
838
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
839
839
  bits = expr.result_size(self.tyenv)
840
840
 
841
841
  r = None
842
842
  expr0_v = expr0.one_value()
843
843
  expr1_v = expr1.one_value()
844
844
 
845
- def _shift_sar(e0, e1):
845
+ def _shift_sar(e0: claripy.ast.BV, e1: claripy.ast.BV):
846
846
  # convert e1 to an integer to prevent claripy from complaining "args' lengths must all be equal"
847
847
  if e1.symbolic:
848
848
  return self.state.top(bits)
849
- e1 = e1.concrete_value
849
+ e1_int = e1.concrete_value
850
850
 
851
- if e1 > bits:
851
+ if e1_int > bits:
852
852
  return claripy.BVV(0, bits)
853
853
 
854
- head = claripy.BVV(0, bits) if claripy.is_true(e0 >> bits - 1 == 0) else (1 << e1) - 1 << bits - e1
855
- return head | (e0 >> e1)
854
+ head = claripy.BVV(0, bits) if claripy.is_true(e0 >> bits - 1 == 0) else (1 << e1_int) - 1 << bits - e1_int
855
+ return head | (e0 >> e1_int)
856
856
 
857
- if expr0_v is None and expr1_v is None:
858
- # we do not support shifting between two real multivalues
859
- r = MultiValues(self.state.top(bits))
857
+ if expr0_v is not None and expr1_v is not None:
858
+ # subtracting a single value from another single value
859
+ r = MultiValues(_shift_sar(expr0_v, expr1_v))
860
860
  elif expr0_v is None and expr1_v is not None:
861
861
  # shifting a single value by a multivalue
862
862
  if expr0.count() == 1 and 0 in expr0:
@@ -868,16 +868,17 @@ class SimEngineRDVEX(
868
868
  vs = {_shift_sar(expr0_v, v) for v in expr1[0]}
869
869
  r = MultiValues(offset_to_values={0: vs})
870
870
  else:
871
- # subtracting a single value from another single value
872
- r = MultiValues(_shift_sar(expr0_v, expr1_v))
871
+ # we do not support shifting between two real multivalues
872
+ r = MultiValues(self.state.top(bits))
873
873
 
874
874
  if r is None:
875
875
  r = MultiValues(self.state.top(bits))
876
876
 
877
877
  return r
878
878
 
879
- def _handle_Shr(self, expr):
880
- expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
879
+ @binop_handler
880
+ def _handle_binop_Shr(self, expr):
881
+ expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
881
882
  bits = expr.result_size(self.tyenv)
882
883
 
883
884
  r = None
@@ -916,7 +917,8 @@ class SimEngineRDVEX(
916
917
 
917
918
  return r
918
919
 
919
- def _handle_Shl(self, expr):
920
+ @binop_handler
921
+ def _handle_binop_Shl(self, expr):
920
922
  expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
921
923
  bits = expr.result_size(self.tyenv)
922
924
 
@@ -953,7 +955,8 @@ class SimEngineRDVEX(
953
955
 
954
956
  return r
955
957
 
956
- def _handle_CmpEQ(self, expr):
958
+ @binop_handler
959
+ def _handle_binop_CmpEQ(self, expr):
957
960
  arg0, arg1 = expr.args
958
961
  expr_0 = self._expr(arg0)
959
962
  expr_1 = self._expr(arg1)
@@ -970,7 +973,8 @@ class SimEngineRDVEX(
970
973
 
971
974
  return MultiValues(self.state.top(1))
972
975
 
973
- def _handle_CmpNE(self, expr):
976
+ @binop_handler
977
+ def _handle_binop_CmpNE(self, expr):
974
978
  arg0, arg1 = expr.args
975
979
  expr_0 = self._expr(arg0)
976
980
  expr_1 = self._expr(arg1)
@@ -984,67 +988,71 @@ class SimEngineRDVEX(
984
988
  return MultiValues(claripy.BVV(0, 1))
985
989
  return MultiValues(self.state.top(1))
986
990
 
987
- def _handle_CmpLT(self, expr):
991
+ @binop_handler
992
+ def _handle_binop_CmpLT(self, expr):
988
993
  arg0, arg1 = expr.args
989
- expr_0 = self._expr(arg0)
990
- expr_1 = self._expr(arg1)
994
+ expr_0, expr_1 = self._expr_pair(arg0, arg1)
991
995
 
992
996
  e0 = expr_0.one_value()
993
997
  e1 = expr_1.one_value()
994
998
  if e0 is not None and e1 is not None:
995
999
  if not e0.symbolic and not e1.symbolic:
996
- return MultiValues(claripy.BVV(1, 1) if e0.concrete_value < e1.concrete_value else claripy.BVV(0, 1))
1000
+ cmp = e0.concrete_value < e1.concrete_value # type: ignore
1001
+ return MultiValues(claripy.BVV(1, 1) if cmp else claripy.BVV(0, 1))
997
1002
  if e0 is e1:
998
1003
  return MultiValues(claripy.BVV(0, 1))
999
1004
  return MultiValues(self.state.top(1))
1000
1005
 
1001
- def _handle_CmpLE(self, expr):
1006
+ @binop_handler
1007
+ def _handle_binop_CmpLE(self, expr):
1002
1008
  arg0, arg1 = expr.args
1003
- expr_0 = self._expr(arg0)
1004
- expr_1 = self._expr(arg1)
1009
+ expr_0, expr_1 = self._expr_pair(arg0, arg1)
1005
1010
 
1006
1011
  e0 = expr_0.one_value()
1007
1012
  e1 = expr_1.one_value()
1008
1013
  if e0 is not None and e1 is not None:
1009
1014
  if not e0.symbolic and not e1.symbolic:
1010
- return MultiValues(claripy.BVV(1, 1) if e0.concrete_value <= e1.concrete_value else claripy.BVV(0, 1))
1015
+ cmp = e0.concrete_value <= e1.concrete_value # type: ignore
1016
+ return MultiValues(claripy.BVV(1, 1) if cmp else claripy.BVV(0, 1))
1011
1017
  if e0 is e1:
1012
1018
  return MultiValues(claripy.BVV(0, 1))
1013
1019
  return MultiValues(self.state.top(1))
1014
1020
 
1015
- def _handle_CmpGT(self, expr):
1021
+ @binop_handler
1022
+ def _handle_binop_CmpGT(self, expr):
1016
1023
  arg0, arg1 = expr.args
1017
- expr_0 = self._expr(arg0)
1018
- expr_1 = self._expr(arg1)
1024
+ expr_0, expr_1 = self._expr_pair(arg0, arg1)
1019
1025
 
1020
1026
  e0 = expr_0.one_value()
1021
1027
  e1 = expr_1.one_value()
1022
1028
  if e0 is not None and e1 is not None:
1023
1029
  if not e0.symbolic and not e1.symbolic:
1024
- return MultiValues(claripy.BVV(1, 1) if e0.concrete_value > e1.concrete_value else claripy.BVV(0, 1))
1030
+ cmp = e0.concrete_value > e1.concrete_value # type: ignore
1031
+ return MultiValues(claripy.BVV(1, 1) if cmp else claripy.BVV(0, 1))
1025
1032
  if e0 is e1:
1026
1033
  return MultiValues(claripy.BVV(0, 1))
1027
1034
  return MultiValues(self.state.top(1))
1028
1035
 
1029
- def _handle_CmpGE(self, expr):
1036
+ @binop_handler
1037
+ def _handle_binop_CmpGE(self, expr):
1030
1038
  arg0, arg1 = expr.args
1031
- expr_0 = self._expr(arg0)
1032
- expr_1 = self._expr(arg1)
1039
+ expr_0, expr_1 = self._expr_pair(arg0, arg1)
1033
1040
 
1034
1041
  e0 = expr_0.one_value()
1035
1042
  e1 = expr_1.one_value()
1036
1043
  if e0 is not None and e1 is not None:
1037
1044
  if not e0.symbolic and not e1.symbolic:
1038
- return MultiValues(claripy.BVV(1, 1) if e0.concrete_value >= e1.concrete_value else claripy.BVV(0, 1))
1045
+ cmp = e0.concrete_value >= e1.concrete_value # type: ignore
1046
+ return MultiValues(claripy.BVV(1, 1) if cmp else claripy.BVV(0, 1))
1039
1047
  if e0 is e1:
1040
1048
  return MultiValues(claripy.BVV(0, 1))
1041
1049
  return MultiValues(self.state.top(1))
1042
1050
 
1043
1051
  # ppc only
1044
- def _handle_CmpORD(self, expr):
1052
+ @binop_handler
1053
+ def _handle_binop_CmpORD(self, expr):
1045
1054
  arg0, arg1 = expr.args
1046
- expr_0 = self._expr(arg0)
1047
- expr_1 = self._expr(arg1)
1055
+ expr_0, expr_1 = self._expr_pair(arg0, arg1)
1048
1056
 
1049
1057
  e0 = expr_0.one_value()
1050
1058
  e1 = expr_1.one_value()
@@ -1054,9 +1062,9 @@ class SimEngineRDVEX(
1054
1062
  if not e0.symbolic and not e1.symbolic:
1055
1063
  e0 = e0.concrete_value
1056
1064
  e1 = e1.concrete_value
1057
- if e0 < e1:
1065
+ if e0 < e1: # type: ignore
1058
1066
  return MultiValues(claripy.BVV(0x8, bits))
1059
- if e0 > e1:
1067
+ if e0 > e1: # type: ignore
1060
1068
  return MultiValues(claripy.BVV(0x4, bits))
1061
1069
  return MultiValues(claripy.BVV(0x2, bits))
1062
1070
  if e0 is e1:
@@ -1064,19 +1072,25 @@ class SimEngineRDVEX(
1064
1072
 
1065
1073
  return MultiValues(self.state.top(1))
1066
1074
 
1067
- def _handle_CCall(self, expr):
1075
+ def _handle_expr_CCall(self, expr) -> MultiValues[claripy.ast.BV | claripy.ast.FP]:
1068
1076
  bits = expr.result_size(self.tyenv)
1069
1077
  for arg_expr in expr.args:
1070
1078
  self._expr(arg_expr)
1071
1079
  return MultiValues(self.state.top(bits))
1072
1080
 
1081
+ def _handle_expr_GSPTR(self, expr):
1082
+ return self._top(expr.result_size(self.tyenv))
1083
+
1084
+ def _handle_expr_VECRET(self, expr):
1085
+ return self._top(expr.result_size(self.tyenv))
1086
+
1073
1087
  #
1074
1088
  # User defined high level statement handlers
1075
1089
  #
1076
1090
 
1077
- def _handle_function(self, func_addr: MultiValues | None):
1091
+ def _handle_function(self, func_addr: MultiValues[claripy.ast.BV] | None):
1078
1092
  if func_addr is None:
1079
- func_addr = self.state.top(self.state.arch.bits)
1093
+ func_addr = MultiValues(self.state.top(self.state.arch.bits))
1080
1094
 
1081
1095
  callsite = self.state.codeloc
1082
1096
  data = FunctionCallData(