angr 9.2.131__py3-none-macosx_11_0_arm64.whl → 9.2.132__py3-none-macosx_11_0_arm64.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 (112) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/analysis.py +6 -2
  3. angr/analyses/cfg/cfg_emulated.py +5 -5
  4. angr/analyses/cfg/cfg_fast.py +2 -2
  5. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +139 -94
  6. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
  7. angr/analyses/ddg.py +14 -11
  8. angr/analyses/decompiler/ail_simplifier.py +3 -2
  9. angr/analyses/decompiler/block_simplifier.py +10 -21
  10. angr/analyses/decompiler/clinic.py +108 -34
  11. angr/analyses/decompiler/condition_processor.py +12 -10
  12. angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
  13. angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
  14. angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
  15. angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
  16. angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
  17. angr/analyses/decompiler/optimization_passes/engine_base.py +261 -83
  18. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +173 -35
  19. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +5 -2
  20. angr/analyses/decompiler/optimization_passes/optimization_pass.py +39 -19
  21. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +2 -0
  22. angr/analyses/decompiler/ssailification/rewriting.py +1 -2
  23. angr/analyses/decompiler/ssailification/rewriting_engine.py +138 -55
  24. angr/analyses/decompiler/ssailification/ssailification.py +2 -1
  25. angr/analyses/decompiler/ssailification/traversal.py +4 -6
  26. angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
  27. angr/analyses/decompiler/structured_codegen/c.py +5 -3
  28. angr/analyses/decompiler/structuring/phoenix.py +26 -9
  29. angr/analyses/decompiler/structuring/structurer_nodes.py +9 -0
  30. angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
  31. angr/analyses/deobfuscator/string_obf_finder.py +2 -2
  32. angr/analyses/init_finder.py +47 -22
  33. angr/analyses/propagator/engine_base.py +21 -14
  34. angr/analyses/propagator/engine_vex.py +149 -179
  35. angr/analyses/propagator/propagator.py +10 -28
  36. angr/analyses/propagator/top_checker_mixin.py +211 -5
  37. angr/analyses/propagator/vex_vars.py +1 -1
  38. angr/analyses/reaching_definitions/dep_graph.py +1 -1
  39. angr/analyses/reaching_definitions/engine_ail.py +304 -329
  40. angr/analyses/reaching_definitions/engine_vex.py +243 -229
  41. angr/analyses/reaching_definitions/function_handler.py +3 -3
  42. angr/analyses/reaching_definitions/rd_state.py +37 -32
  43. angr/analyses/s_propagator.py +18 -3
  44. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
  45. angr/analyses/typehoon/simple_solver.py +7 -5
  46. angr/analyses/typehoon/translator.py +8 -0
  47. angr/analyses/typehoon/typeconsts.py +10 -2
  48. angr/analyses/typehoon/typevars.py +9 -7
  49. angr/analyses/variable_recovery/engine_ail.py +299 -259
  50. angr/analyses/variable_recovery/engine_base.py +135 -117
  51. angr/analyses/variable_recovery/engine_vex.py +175 -185
  52. angr/analyses/variable_recovery/irsb_scanner.py +49 -38
  53. angr/analyses/variable_recovery/variable_recovery.py +28 -5
  54. angr/analyses/variable_recovery/variable_recovery_base.py +32 -33
  55. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
  56. angr/analyses/xrefs.py +46 -19
  57. angr/annocfg.py +19 -14
  58. angr/block.py +4 -9
  59. angr/calling_conventions.py +1 -1
  60. angr/engines/engine.py +30 -14
  61. angr/engines/light/__init__.py +11 -3
  62. angr/engines/light/engine.py +1003 -1185
  63. angr/engines/pcode/cc.py +2 -0
  64. angr/engines/successors.py +13 -9
  65. angr/engines/vex/claripy/datalayer.py +1 -1
  66. angr/engines/vex/claripy/irop.py +1 -1
  67. angr/engines/vex/light/slicing.py +2 -2
  68. angr/exploration_techniques/__init__.py +1 -124
  69. angr/exploration_techniques/base.py +126 -0
  70. angr/exploration_techniques/bucketizer.py +1 -1
  71. angr/exploration_techniques/dfs.py +3 -1
  72. angr/exploration_techniques/director.py +2 -3
  73. angr/exploration_techniques/driller_core.py +1 -1
  74. angr/exploration_techniques/explorer.py +4 -2
  75. angr/exploration_techniques/lengthlimiter.py +2 -1
  76. angr/exploration_techniques/local_loop_seer.py +2 -1
  77. angr/exploration_techniques/loop_seer.py +5 -5
  78. angr/exploration_techniques/manual_mergepoint.py +2 -1
  79. angr/exploration_techniques/memory_watcher.py +3 -1
  80. angr/exploration_techniques/oppologist.py +4 -5
  81. angr/exploration_techniques/slicecutor.py +4 -2
  82. angr/exploration_techniques/spiller.py +1 -1
  83. angr/exploration_techniques/stochastic.py +2 -1
  84. angr/exploration_techniques/stub_stasher.py +2 -1
  85. angr/exploration_techniques/suggestions.py +3 -1
  86. angr/exploration_techniques/symbion.py +3 -1
  87. angr/exploration_techniques/tech_builder.py +2 -1
  88. angr/exploration_techniques/threading.py +4 -7
  89. angr/exploration_techniques/timeout.py +4 -2
  90. angr/exploration_techniques/tracer.py +4 -3
  91. angr/exploration_techniques/unique.py +3 -2
  92. angr/exploration_techniques/veritesting.py +1 -1
  93. angr/knowledge_plugins/key_definitions/atoms.py +2 -2
  94. angr/knowledge_plugins/key_definitions/live_definitions.py +16 -13
  95. angr/knowledge_plugins/propagations/states.py +13 -8
  96. angr/knowledge_plugins/variables/variable_manager.py +23 -9
  97. angr/lib/angr_native.dylib +0 -0
  98. angr/sim_manager.py +1 -3
  99. angr/sim_state.py +39 -41
  100. angr/sim_type.py +5 -0
  101. angr/sim_variable.py +29 -28
  102. angr/utils/bits.py +12 -0
  103. angr/utils/orderedset.py +4 -1
  104. angr/utils/ssa/__init__.py +21 -3
  105. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/METADATA +6 -6
  106. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/RECORD +110 -111
  107. angr/analyses/propagator/engine_ail.py +0 -1562
  108. angr/storage/memory_mixins/__init__.pyi +0 -48
  109. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/LICENSE +0 -0
  110. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/WHEEL +0 -0
  111. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/entry_points.txt +0 -0
  112. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/top_level.txt +0 -0
@@ -5,29 +5,25 @@ import logging
5
5
  from ailment.block import Block
6
6
  from ailment.statement import Statement, Assignment, Store, Call, Return, ConditionalJump, DirtyStatement
7
7
  from ailment.expression import (
8
- Register,
8
+ Expression,
9
9
  VirtualVariable,
10
10
  Load,
11
- Const,
12
11
  BinaryOp,
12
+ UnaryOp,
13
13
  Phi,
14
14
  Convert,
15
- StackBaseOffset,
16
15
  ITE,
17
16
  VEXCCallExpression,
18
17
  DirtyExpression,
19
18
  )
20
19
 
21
- from angr.engines.light import SimEngineLight, SimEngineLightAILMixin
20
+ from angr.engines.light import SimEngineNostmtAIL
22
21
 
23
22
 
24
23
  _l = logging.getLogger(__name__)
25
24
 
26
25
 
27
- class SimEngineDephiRewriting(
28
- SimEngineLightAILMixin,
29
- SimEngineLight,
30
- ):
26
+ class SimEngineDephiRewriting(SimEngineNostmtAIL[None, Expression | None, Statement | tuple[Statement, ...], None]):
31
27
  """
32
28
  This engine rewrites every block to insert phi variables and replaces every used variable with their versioned
33
29
  copies at each use location.
@@ -37,15 +33,22 @@ class SimEngineDephiRewriting(
37
33
 
38
34
  def __init__(
39
35
  self,
40
- arch,
36
+ project,
41
37
  vvar_to_vvar: dict[int, int],
42
38
  ):
43
- super().__init__()
39
+ super().__init__(project)
44
40
 
45
- self.arch = arch
46
41
  self.vvar_to_vvar = vvar_to_vvar
47
42
  self.out_block = None
48
43
 
44
+ self._stmt_handlers["IncompleteSwitchCaseHeadStatement"] = self._handle_stmt_IncompleteSwitchCaseHeadStatement
45
+
46
+ def _top(self, bits):
47
+ assert False, "Unreachable"
48
+
49
+ def _is_top(self, expr):
50
+ return False
51
+
49
52
  def append_statement(self, stmt: Statement) -> None:
50
53
  if self.out_block is None:
51
54
  self.out_block = Block(self.block.addr, self.block.original_size, statements=[], idx=self.block.idx)
@@ -55,18 +58,19 @@ class SimEngineDephiRewriting(
55
58
  # Handlers
56
59
  #
57
60
 
58
- def _handle_Stmt(self, stmt: Statement):
59
- new_stmt = super()._handle_Stmt(stmt)
60
- if new_stmt is not None:
61
- if type(new_stmt) is tuple:
62
- for s in new_stmt:
63
- self.append_statement(s)
61
+ def _process_block_end(self, block, stmt_data, whitelist):
62
+ assert whitelist is None
63
+ for stmt_idx, new_stmt in enumerate(stmt_data):
64
+ if new_stmt is not None:
65
+ if isinstance(new_stmt, tuple):
66
+ for stmt_ in new_stmt:
67
+ self.append_statement(stmt_)
68
+ else:
69
+ self.append_statement(new_stmt)
64
70
  else:
65
- self.append_statement(new_stmt)
66
- else:
67
- self.append_statement(stmt)
71
+ self.append_statement(block.statements[stmt_idx])
68
72
 
69
- def _handle_Assignment(self, stmt: Assignment) -> Assignment | tuple[Assignment, ...] | None:
73
+ def _handle_stmt_Assignment(self, stmt):
70
74
  new_src = self._expr(stmt.src)
71
75
  new_dst = None
72
76
 
@@ -92,7 +96,7 @@ class SimEngineDephiRewriting(
92
96
  )
93
97
  return None
94
98
 
95
- def _handle_Store(self, stmt: Store) -> Store | None:
99
+ def _handle_stmt_Store(self, stmt):
96
100
  new_addr = self._expr(stmt.addr)
97
101
  new_data = self._expr(stmt.data)
98
102
 
@@ -110,7 +114,7 @@ class SimEngineDephiRewriting(
110
114
 
111
115
  return None
112
116
 
113
- def _handle_ConditionalJump(self, stmt: ConditionalJump) -> ConditionalJump | None:
117
+ def _handle_stmt_ConditionalJump(self, stmt):
114
118
  new_cond = self._expr(stmt.condition)
115
119
  new_true_target = self._expr(stmt.true_target) if stmt.true_target is not None else None
116
120
  new_false_target = self._expr(stmt.false_target) if stmt.false_target is not None else None
@@ -127,7 +131,7 @@ class SimEngineDephiRewriting(
127
131
  )
128
132
  return None
129
133
 
130
- def _handle_Call(self, stmt: Call) -> Call | None:
134
+ def _handle_stmt_Call(self, stmt):
131
135
  new_target = self._expr(stmt.target) if stmt.target is not None and not isinstance(stmt.target, str) else None
132
136
  new_ret_expr = self._expr(stmt.ret_expr) if stmt.ret_expr is not None else None
133
137
  new_fp_ret_expr = self._expr(stmt.fp_ret_expr) if stmt.fp_ret_expr is not None else None
@@ -146,24 +150,19 @@ class SimEngineDephiRewriting(
146
150
  )
147
151
  return None
148
152
 
149
- _handle_CallExpr = _handle_Call
150
-
151
- def _handle_DirtyStatement(self, stmt: DirtyStatement) -> DirtyStatement | None:
153
+ def _handle_stmt_DirtyStatement(self, stmt: DirtyStatement) -> DirtyStatement | None:
152
154
  dirty = self._expr(stmt.dirty)
153
155
  if dirty is None or dirty is stmt.dirty:
154
156
  return None
155
157
  return DirtyStatement(stmt.idx, dirty, **stmt.tags)
156
158
 
157
- def _handle_Register(self, expr: Register) -> None:
158
- return None
159
-
160
- def _handle_Load(self, expr: Load) -> Load | None:
159
+ def _handle_expr_Load(self, expr):
161
160
  new_addr = self._expr(expr.addr)
162
161
  if new_addr is not None:
163
162
  return Load(expr.idx, new_addr, expr.size, expr.endness, guard=expr.guard, alt=expr.alt, **expr.tags)
164
163
  return None
165
164
 
166
- def _handle_Convert(self, expr: Convert) -> Convert | None:
165
+ def _handle_expr_Convert(self, expr):
167
166
  new_operand = self._expr(expr.operand)
168
167
  if new_operand is not None:
169
168
  return Convert(
@@ -179,13 +178,13 @@ class SimEngineDephiRewriting(
179
178
  )
180
179
  return None
181
180
 
182
- def _handle_Const(self, expr: Const) -> None:
181
+ def _handle_expr_Const(self, expr):
183
182
  return None
184
183
 
185
- def _handle_Phi(self, expr: Phi) -> None:
184
+ def _handle_expr_Phi(self, expr: Phi) -> None:
186
185
  return None
187
186
 
188
- def _handle_VirtualVariable(self, expr: VirtualVariable) -> VirtualVariable | None:
187
+ def _handle_expr_VirtualVariable(self, expr: VirtualVariable) -> VirtualVariable | None:
189
188
  if expr.varid in self.vvar_to_vvar:
190
189
  return VirtualVariable(
191
190
  expr.idx,
@@ -199,13 +198,13 @@ class SimEngineDephiRewriting(
199
198
  )
200
199
  return None
201
200
 
202
- def _handle_Return(self, expr: Return) -> Return | None:
203
- if expr.ret_exprs is None:
201
+ def _handle_stmt_Return(self, stmt):
202
+ if stmt.ret_exprs is None:
204
203
  new_ret_exprs = None
205
204
  else:
206
205
  updated = False
207
206
  new_ret_exprs = []
208
- for r in expr.ret_exprs:
207
+ for r in stmt.ret_exprs:
209
208
  new_r = self._expr(r)
210
209
  if new_r is not None:
211
210
  updated = True
@@ -214,10 +213,13 @@ class SimEngineDephiRewriting(
214
213
  new_ret_exprs = None
215
214
 
216
215
  if new_ret_exprs:
217
- return Return(expr.idx, new_ret_exprs, **expr.tags)
216
+ return Return(stmt.idx, new_ret_exprs, **stmt.tags)
217
+ return None
218
+
219
+ def _handle_stmt_IncompleteSwitchCaseHeadStatement(self, stmt):
218
220
  return None
219
221
 
220
- def _handle_BinaryOp(self, expr: BinaryOp) -> BinaryOp | None:
222
+ def _handle_expr_BinaryOp(self, expr):
221
223
  new_op0 = self._expr(expr.operands[0])
222
224
  new_op1 = self._expr(expr.operands[1])
223
225
 
@@ -233,13 +235,24 @@ class SimEngineDephiRewriting(
233
235
  bits=expr.bits,
234
236
  floating_point=expr.floating_point,
235
237
  rounding_mode=expr.rounding_mode,
236
- from_bits=expr.from_bits,
237
- to_bits=expr.to_bits,
238
238
  **expr.tags,
239
239
  )
240
240
  return None
241
241
 
242
- def _handle_ITE(self, expr: ITE) -> ITE | None:
242
+ def _handle_expr_UnaryOp(self, expr):
243
+ new_op0 = self._expr(expr.operands[0])
244
+
245
+ if new_op0 is not None:
246
+ return UnaryOp(
247
+ expr.idx,
248
+ expr.op,
249
+ expr.operands[0] if new_op0 is None else new_op0,
250
+ bits=expr.bits,
251
+ **expr.tags,
252
+ )
253
+ return None
254
+
255
+ def _handle_expr_ITE(self, expr):
243
256
  new_cond = self._expr(expr.cond)
244
257
  new_iftrue = self._expr(expr.iftrue)
245
258
  new_iffalse = self._expr(expr.iffalse)
@@ -275,7 +288,7 @@ class SimEngineDephiRewriting(
275
288
  )
276
289
  return None
277
290
 
278
- def _handle_DirtyExpression(self, expr: DirtyExpression) -> DirtyExpression | None:
291
+ def _handle_expr_DirtyExpression(self, expr: DirtyExpression) -> DirtyExpression | None:
279
292
  new_operands = []
280
293
  updated = False
281
294
  for o in expr.operands:
@@ -306,5 +319,116 @@ class SimEngineDephiRewriting(
306
319
  )
307
320
  return None
308
321
 
309
- def _handle_StackBaseOffset(self, expr: StackBaseOffset) -> None:
322
+ def _handle_expr_BasePointerOffset(self, expr):
323
+ return None
324
+
325
+ def _handle_expr_StackBaseOffset(self, expr):
326
+ return None
327
+
328
+ def _handle_expr_Call(self, expr: Call):
329
+ new_target = self._expr(expr.target) if expr.target is not None and not isinstance(expr.target, str) else None
330
+ new_ret_expr = self._expr(expr.ret_expr) if expr.ret_expr is not None else None
331
+ new_fp_ret_expr = self._expr(expr.fp_ret_expr) if expr.fp_ret_expr is not None else None
332
+
333
+ if new_target is not None or new_ret_expr is not None or new_fp_ret_expr is not None:
334
+ return Call(
335
+ expr.idx,
336
+ expr.target if new_target is None else new_target,
337
+ calling_convention=expr.calling_convention,
338
+ prototype=expr.prototype,
339
+ args=expr.args,
340
+ ret_expr=expr.ret_expr if new_ret_expr is None else new_ret_expr,
341
+ fp_ret_expr=expr.fp_ret_expr if new_fp_ret_expr is None else new_fp_ret_expr,
342
+ bits=expr.bits,
343
+ **expr.tags,
344
+ )
345
+ return None
346
+
347
+ def _handle_expr_DirtyExpression(self, expr):
310
348
  return None
349
+
350
+ def _handle_expr_MultiStatementExpression(self, expr):
351
+ return None
352
+
353
+ def _handle_expr_Register(self, expr):
354
+ return None
355
+
356
+ def _handle_expr_Reinterpret(self, expr):
357
+ return None
358
+
359
+ def _handle_expr_Tmp(self, expr):
360
+ return None
361
+
362
+ def _handle_expr_VEXCCallExpression(self, expr):
363
+ return None
364
+
365
+ def _unreachable(self, *args, **kwargs):
366
+ assert False
367
+
368
+ _handle_binop_Add = _unreachable
369
+ _handle_binop_AddF = _unreachable
370
+ _handle_binop_AddV = _unreachable
371
+ _handle_binop_And = _unreachable
372
+ _handle_binop_Carry = _unreachable
373
+ _handle_binop_CmpEQ = _unreachable
374
+ _handle_binop_CmpF = _unreachable
375
+ _handle_binop_CmpGE = _unreachable
376
+ _handle_binop_CmpGT = _unreachable
377
+ _handle_binop_CmpLE = _unreachable
378
+ _handle_binop_CmpLT = _unreachable
379
+ _handle_binop_CmpNE = _unreachable
380
+ _handle_binop_Concat = _unreachable
381
+ _handle_binop_Div = _unreachable
382
+ _handle_binop_DivF = _unreachable
383
+ _handle_binop_DivV = _unreachable
384
+ _handle_binop_LogicalAnd = _unreachable
385
+ _handle_binop_LogicalOr = _unreachable
386
+ _handle_binop_Mod = _unreachable
387
+ _handle_binop_Mul = _unreachable
388
+ _handle_binop_Mull = _unreachable
389
+ _handle_binop_MulF = _unreachable
390
+ _handle_binop_MulV = _unreachable
391
+ _handle_binop_MulHiV = _unreachable
392
+ _handle_binop_Or = _unreachable
393
+ _handle_binop_Rol = _unreachable
394
+ _handle_binop_Ror = _unreachable
395
+ _handle_binop_SBorrow = _unreachable
396
+ _handle_binop_SCarry = _unreachable
397
+ _handle_binop_Sar = _unreachable
398
+ _handle_binop_Shl = _unreachable
399
+ _handle_binop_Shr = _unreachable
400
+ _handle_binop_Sub = _unreachable
401
+ _handle_binop_SubF = _unreachable
402
+ _handle_binop_SubV = _unreachable
403
+ _handle_binop_Xor = _unreachable
404
+ _handle_binop_InterleaveLOV = _unreachable
405
+ _handle_binop_InterleaveHIV = _unreachable
406
+ _handle_binop_CasCmpEQ = _unreachable
407
+ _handle_binop_CasCmpNE = _unreachable
408
+ _handle_binop_ExpCmpNE = _unreachable
409
+ _handle_binop_SarNV = _unreachable
410
+ _handle_binop_ShrNV = _unreachable
411
+ _handle_binop_ShlNV = _unreachable
412
+ _handle_binop_CmpEQV = _unreachable
413
+ _handle_binop_CmpNEV = _unreachable
414
+ _handle_binop_CmpGEV = _unreachable
415
+ _handle_binop_CmpGTV = _unreachable
416
+ _handle_binop_CmpLEV = _unreachable
417
+ _handle_binop_CmpLTV = _unreachable
418
+ _handle_binop_MinV = _unreachable
419
+ _handle_binop_MaxV = _unreachable
420
+ _handle_binop_QAddV = _unreachable
421
+ _handle_binop_QNarrowBinV = _unreachable
422
+ _handle_binop_PermV = _unreachable
423
+ _handle_binop_Set = _unreachable
424
+ _handle_unop_BitwiseNeg = _unreachable
425
+ _handle_unop_Dereference = _unreachable
426
+ _handle_unop_Neg = _unreachable
427
+ _handle_unop_Not = _unreachable
428
+ _handle_unop_Reference = _unreachable
429
+ _handle_unop_Clz = _unreachable
430
+ _handle_unop_Ctz = _unreachable
431
+ _handle_unop_GetMSBs = _unreachable
432
+ _handle_unop_unpack = _unreachable
433
+ _handle_unop_Sqrt = _unreachable
434
+ _handle_unop_RSqrtEst = _unreachable
@@ -7,6 +7,7 @@ from ailment.block import Block
7
7
  from ailment.statement import Assignment
8
8
  from ailment.expression import VirtualVariable, Phi
9
9
 
10
+ import angr
10
11
  from angr.utils.ail import is_phi_assignment
11
12
  from angr.knowledge_plugins.functions import Function
12
13
  from angr.analyses import register_analysis
@@ -53,7 +54,7 @@ class SeqNodeRewriter(SequenceWalker):
53
54
  variables.
54
55
  """
55
56
 
56
- def __init__(self, seq_node: SequenceNode, vvar_to_vvar: dict[int, int], arch):
57
+ def __init__(self, seq_node: SequenceNode, vvar_to_vvar: dict[int, int], project: angr.Project):
57
58
  super().__init__(
58
59
  handlers={
59
60
  Block: self._handle_Block,
@@ -63,7 +64,7 @@ class SeqNodeRewriter(SequenceWalker):
63
64
  )
64
65
 
65
66
  self.vvar_to_vvar = vvar_to_vvar
66
- self.engine = SimEngineDephiRewriting(arch, self.vvar_to_vvar)
67
+ self.engine = SimEngineDephiRewriting(project, self.vvar_to_vvar)
67
68
 
68
69
  self.output = self.walk(seq_node)
69
70
  if self.output is None:
@@ -71,7 +72,7 @@ class SeqNodeRewriter(SequenceWalker):
71
72
  self.output = seq_node
72
73
 
73
74
  def _handle_Assignment(self, stmt: Assignment, **kwargs) -> Assignment: # pylint:disable=unused-argument
74
- return self.engine._handle_Assignment(stmt)
75
+ return self.engine._handle_stmt_Assignment(stmt)
75
76
 
76
77
  def _handle_Block(self, block: Block, **kwargs) -> Block | None: # pylint:disable=unused-argument
77
78
  self.engine.out_block = None
@@ -117,7 +118,7 @@ class SeqNodeDephication(DephicationBase):
117
118
  return collector.phi_to_src
118
119
 
119
120
  def _rewrite_container(self) -> Any:
120
- rewriter = SeqNodeRewriter(self._seq_node, self.vvar_to_vvar_mapping, self.project.arch)
121
+ rewriter = SeqNodeRewriter(self._seq_node, self.vvar_to_vvar_mapping, self.project)
121
122
  return rewriter.output
122
123
 
123
124
 
@@ -212,6 +212,7 @@ class BlockWalker(AILBlockWalker):
212
212
  expr.signed,
213
213
  variable=expr.variable,
214
214
  variable_offset=expr.variable_offset,
215
+ bits=expr.bits,
215
216
  **expr.tags,
216
217
  )
217
218
  return None
@@ -19,7 +19,7 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
19
19
  """
20
20
 
21
21
  @staticmethod
22
- def _check_divisor(a, b, ndigits=6):
22
+ def _check_divisor(a: int, b: int, ndigits: int = 6) -> int | None:
23
23
  if b == 0:
24
24
  return None
25
25
  divisor_1 = 1 + (a // b)
@@ -27,7 +27,7 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
27
27
  return divisor_1 if divisor_1 == divisor_2 else None
28
28
 
29
29
  # pylint: disable=too-many-boolean-expressions
30
- def _ail_handle_Convert(self, expr: Expr.Convert):
30
+ def _handle_expr_Convert(self, expr: Expr.Convert):
31
31
  if expr.from_bits == 128 and expr.to_bits == 64:
32
32
  operand_expr = self._expr(expr.operand)
33
33
  if (
@@ -42,18 +42,20 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
42
42
  ):
43
43
  if operand_expr.operands[0].op == "Shr":
44
44
  Y = operand_expr.operands[0].operands[1].value
45
+ assert isinstance(Y, int)
45
46
  else:
46
47
  Y = int(math.log2(operand_expr.operands[0].operands[1].value))
47
48
  C = operand_expr.operands[1].value
49
+ assert isinstance(C, int)
48
50
  divisor = self._check_divisor(pow(2, 64 + Y), C)
49
51
  if divisor:
50
52
  X = operand_expr.operands[0].operands[0]
51
53
  new_const = Expr.Const(expr.idx, None, divisor, 64)
52
54
  return Expr.BinaryOp(expr.idx, "Div", [X, new_const], expr.signed, **expr.tags)
53
55
 
54
- return super()._ail_handle_Convert(expr)
56
+ return expr
55
57
 
56
- def _ail_handle_Shr(self, expr):
58
+ def _handle_binop_Shr(self, expr):
57
59
  operand_0 = self._expr(expr.operands[0])
58
60
  operand_1 = self._expr(expr.operands[1])
59
61
 
@@ -90,6 +92,8 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
90
92
  if isinstance(operand_0.operand.operands[1], Expr.Const):
91
93
  C = operand_0.operand.operands[1].value
92
94
  Y = operand_1.value
95
+ assert isinstance(C, int)
96
+ assert isinstance(Y, int)
93
97
  divisor = self._check_divisor(pow(2, 64 + Y), C)
94
98
  X = operand_0.operand.operands[0]
95
99
  elif isinstance(operand_0.operand.operands[0], Expr.BinaryOp) and operand_0.operand.operands[0].op in {
@@ -102,6 +106,9 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
102
106
  Y = operand_0.operand.operands[0].operands[1].value
103
107
  else:
104
108
  Y = int(math.log2(operand_0.operand.operands[0].operands[1].value))
109
+ assert isinstance(C, int)
110
+ assert isinstance(Y, int)
111
+ assert isinstance(Z, int)
105
112
  divisor = self._check_divisor(pow(2, 64 + Z + Y), C)
106
113
  X = operand_0.operand.operands[0].operands[0]
107
114
  if isinstance(operand_1, Expr.Const) and isinstance(operand_0, Expr.BinaryOp) and operand_0.op == "Add":
@@ -127,6 +134,9 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
127
134
  and V_.operands[0] == X
128
135
  and V_.operands[1] == xC
129
136
  ):
137
+ assert isinstance(Y, int)
138
+ assert isinstance(Z, int)
139
+ assert isinstance(V, int)
130
140
  divisor = self._check_divisor(
131
141
  pow(2, Y + V + Z), C * (pow(2, V) - 1) + pow(2, Y)
132
142
  )
@@ -141,6 +151,9 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
141
151
  if isinstance(V, Expr.Const):
142
152
  V = V.value
143
153
  if isinstance(V_, Expr.BinaryOp) and V_.op == "Sub" and V_.operands[1] == xC:
154
+ assert isinstance(Y, int)
155
+ assert isinstance(Z, int)
156
+ assert isinstance(V, int)
144
157
  divisor = self._check_divisor(pow(2, Y + V + Z), C * (pow(2, V) - 1) + pow(2, Y))
145
158
  elif (
146
159
  isinstance(xC, Expr.BinaryOp)
@@ -164,6 +177,9 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
164
177
  Y = xC.operands[1].value
165
178
  V = x_xC.operands[1].value
166
179
  if x_xC.operands[0].operands[0] == X:
180
+ assert isinstance(Y, int)
181
+ assert isinstance(Z, int)
182
+ assert isinstance(V, int)
167
183
  divisor = self._check_divisor(pow(2, Y + V + Z), C * (pow(2, V) - 1) + pow(2, Y))
168
184
 
169
185
  # unsigned int
@@ -178,6 +194,9 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
178
194
  C = operand_0.operands[1].value
179
195
  Z = operand_1.value
180
196
  X = operand_0.operands[0]
197
+ assert isinstance(C, int)
198
+ assert isinstance(Z, int)
199
+ assert isinstance(V, int)
181
200
  divisor = self._check_divisor(pow(2, V + Z), C)
182
201
  elif (
183
202
  isinstance(operand_0.operands[0], Expr.BinaryOp)
@@ -196,11 +215,17 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
196
215
  if operand_0.operands[0].op == "Mod":
197
216
  Y = int(math.log2(operand_0.operands[0].operands[1].value))
198
217
  Z = operand_1.value
218
+ assert isinstance(Y, int)
219
+ assert isinstance(Z, int)
220
+ assert isinstance(V, int)
221
+ assert isinstance(C, int)
199
222
  divisor = self._check_divisor(pow(2, Y + Z + V), C, ndigits)
200
223
  else:
201
224
  X = operand_0.operands[0]
202
225
  Y = operand_1.value
203
226
  C = operand_0.operands[1].value
227
+ assert isinstance(Y, int)
228
+ assert isinstance(C, int)
204
229
  divisor = self._check_divisor(pow(2, Y), C)
205
230
 
206
231
  if divisor and X:
@@ -225,7 +250,7 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
225
250
  return Expr.BinaryOp(expr.idx, "Shr", [operand_0, operand_1], expr.signed)
226
251
  return expr
227
252
 
228
- def _ail_handle_Mul(self, expr):
253
+ def _handle_binop_Mul(self, expr):
229
254
  operand_0, operand_1 = expr.operands
230
255
 
231
256
  if (
@@ -234,6 +259,8 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
234
259
  and isinstance(operand_0.operands[1], Expr.Const)
235
260
  and operand_0.op in {"Mod", "Shr"}
236
261
  ):
262
+ assert isinstance(operand_0.operands[1].value, int)
263
+ assert isinstance(operand_1.value, int)
237
264
  Y = int(math.log2(operand_0.operands[1].value)) if operand_0.op == "Mod" else operand_0.operands[1].value
238
265
  C = operand_1.value
239
266
  X = operand_0.operands[0]
@@ -242,8 +269,7 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
242
269
  if isinstance(X, Expr.Convert):
243
270
  V = X.from_bits - X.to_bits
244
271
  ndigits = 5 if V == 32 else 6
245
- if self._check_divisor(pow(2, V + Y), C, ndigits) and X:
246
- divisor = self._check_divisor(pow(2, Y + V), C, ndigits)
272
+ if (divisor := self._check_divisor(pow(2, V + Y), C, ndigits)) and X:
247
273
  new_const = Expr.Const(expr.idx, None, divisor, 64)
248
274
  return Expr.BinaryOp(expr.idx, "Div", [X, new_const], expr.signed, **expr.tags)
249
275
  if (
@@ -252,7 +278,9 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
252
278
  and isinstance(operand_0.operand, Expr.BinaryOp)
253
279
  and isinstance(operand_0.operand.operands[1], Expr.Const)
254
280
  and operand_0.operand.op in {"Mod", "Shr"}
281
+ and isinstance(operand_1.value, int)
255
282
  ):
283
+ assert isinstance(operand_0.operand.operands[1].value, int)
256
284
  if operand_0.operand.op == "Mod":
257
285
  Y = int(math.log2(operand_0.operand.operands[1].value))
258
286
  else:
@@ -261,13 +289,12 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
261
289
  X = operand_0.operand.operands[0]
262
290
  V = operand_0.from_bits - operand_0.to_bits
263
291
  ndigits = 5 if V == 32 else 6
264
- if self._check_divisor(pow(2, V + Y), C, ndigits) and X:
265
- divisor = self._check_divisor(pow(2, Y + V), C, ndigits)
292
+ if (divisor := self._check_divisor(pow(2, V + Y), C, ndigits)) and X:
266
293
  new_const = Expr.Const(expr.idx, None, divisor, 64)
267
294
  return Expr.BinaryOp(expr.idx, "Div", [X, new_const], expr.signed, **expr.tags)
268
- return super()._ail_handle_Mul(expr)
295
+ return expr
269
296
 
270
- def _ail_handle_Div(self, expr):
297
+ def _handle_binop_Div(self, expr):
271
298
  operand_0 = self._expr(expr.operands[0])
272
299
  operand_1 = self._expr(expr.operands[1])
273
300
 
@@ -285,10 +312,7 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
285
312
  return Expr.BinaryOp(expr.idx, "Div", [operand_0, operand_1], expr.signed, **expr.tags)
286
313
  return expr
287
314
 
288
- def _ail_handle_Add(self, expr):
289
- if len(expr.operands) != 2:
290
- return super()._ail_handle_Add(expr)
291
-
315
+ def _handle_binop_Add(self, expr):
292
316
  op0 = self._expr(expr.operands[0])
293
317
  op1 = self._expr(expr.operands[1])
294
318
 
@@ -350,6 +374,7 @@ class DivSimplifierAILEngine(SimplifierAILEngine):
350
374
  X = operand_1
351
375
  V = bits
352
376
  ndigits = 5 if V == 32 else 6
377
+ assert isinstance(C, int)
353
378
  divisor = self._check_divisor(pow(2, V), C, ndigits)
354
379
  if divisor is not None and X:
355
380
  new_const = Expr.Const(None, None, divisor, V)
@@ -380,7 +405,7 @@ class DivSimplifier(OptimizationPass):
380
405
  super().__init__(func, **kwargs)
381
406
 
382
407
  self.state = SimplifierAILState(self.project.arch)
383
- self.engine = DivSimplifierAILEngine()
408
+ self.engine = DivSimplifierAILEngine(self.project)
384
409
 
385
410
  self.analyze()
386
411