angr 9.2.130__py3-none-win_amd64.whl → 9.2.132__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 (128) 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 +361 -8
  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/__init__.py +0 -3
  16. angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
  17. angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
  18. angr/analyses/decompiler/optimization_passes/engine_base.py +261 -83
  19. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +173 -35
  20. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +5 -2
  21. angr/analyses/decompiler/optimization_passes/optimization_pass.py +39 -19
  22. angr/analyses/decompiler/peephole_optimizations/__init__.py +5 -1
  23. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
  24. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +3 -1
  25. angr/analyses/decompiler/peephole_optimizations/bswap.py +10 -6
  26. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +100 -19
  27. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +17 -0
  28. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +42 -3
  29. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +4 -2
  30. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +37 -10
  31. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
  32. angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
  33. angr/analyses/decompiler/presets/fast.py +0 -2
  34. angr/analyses/decompiler/presets/full.py +0 -2
  35. angr/analyses/decompiler/ssailification/rewriting.py +1 -2
  36. angr/analyses/decompiler/ssailification/rewriting_engine.py +140 -57
  37. angr/analyses/decompiler/ssailification/ssailification.py +2 -1
  38. angr/analyses/decompiler/ssailification/traversal.py +4 -6
  39. angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
  40. angr/analyses/decompiler/structured_codegen/c.py +79 -16
  41. angr/analyses/decompiler/structuring/phoenix.py +40 -14
  42. angr/analyses/decompiler/structuring/structurer_nodes.py +9 -0
  43. angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
  44. angr/analyses/deobfuscator/string_obf_finder.py +2 -2
  45. angr/analyses/init_finder.py +47 -22
  46. angr/analyses/propagator/engine_base.py +21 -14
  47. angr/analyses/propagator/engine_vex.py +149 -179
  48. angr/analyses/propagator/propagator.py +10 -28
  49. angr/analyses/propagator/top_checker_mixin.py +211 -5
  50. angr/analyses/propagator/vex_vars.py +1 -1
  51. angr/analyses/reaching_definitions/dep_graph.py +1 -1
  52. angr/analyses/reaching_definitions/engine_ail.py +304 -329
  53. angr/analyses/reaching_definitions/engine_vex.py +243 -229
  54. angr/analyses/reaching_definitions/function_handler.py +3 -3
  55. angr/analyses/reaching_definitions/rd_state.py +37 -32
  56. angr/analyses/s_propagator.py +38 -5
  57. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
  58. angr/analyses/typehoon/simple_solver.py +16 -7
  59. angr/analyses/typehoon/translator.py +8 -0
  60. angr/analyses/typehoon/typeconsts.py +10 -2
  61. angr/analyses/typehoon/typehoon.py +4 -1
  62. angr/analyses/typehoon/typevars.py +9 -7
  63. angr/analyses/variable_recovery/engine_ail.py +296 -256
  64. angr/analyses/variable_recovery/engine_base.py +137 -116
  65. angr/analyses/variable_recovery/engine_vex.py +175 -185
  66. angr/analyses/variable_recovery/irsb_scanner.py +49 -38
  67. angr/analyses/variable_recovery/variable_recovery.py +28 -5
  68. angr/analyses/variable_recovery/variable_recovery_base.py +32 -33
  69. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
  70. angr/analyses/xrefs.py +46 -19
  71. angr/annocfg.py +19 -14
  72. angr/block.py +4 -9
  73. angr/calling_conventions.py +1 -1
  74. angr/engines/engine.py +30 -14
  75. angr/engines/light/__init__.py +11 -3
  76. angr/engines/light/engine.py +1003 -1185
  77. angr/engines/pcode/cc.py +2 -0
  78. angr/engines/successors.py +13 -9
  79. angr/engines/vex/claripy/datalayer.py +1 -1
  80. angr/engines/vex/claripy/irop.py +14 -3
  81. angr/engines/vex/light/slicing.py +2 -2
  82. angr/exploration_techniques/__init__.py +1 -124
  83. angr/exploration_techniques/base.py +126 -0
  84. angr/exploration_techniques/bucketizer.py +1 -1
  85. angr/exploration_techniques/dfs.py +3 -1
  86. angr/exploration_techniques/director.py +2 -3
  87. angr/exploration_techniques/driller_core.py +1 -1
  88. angr/exploration_techniques/explorer.py +4 -2
  89. angr/exploration_techniques/lengthlimiter.py +2 -1
  90. angr/exploration_techniques/local_loop_seer.py +2 -1
  91. angr/exploration_techniques/loop_seer.py +5 -5
  92. angr/exploration_techniques/manual_mergepoint.py +2 -1
  93. angr/exploration_techniques/memory_watcher.py +3 -1
  94. angr/exploration_techniques/oppologist.py +4 -5
  95. angr/exploration_techniques/slicecutor.py +4 -2
  96. angr/exploration_techniques/spiller.py +1 -1
  97. angr/exploration_techniques/stochastic.py +2 -1
  98. angr/exploration_techniques/stub_stasher.py +2 -1
  99. angr/exploration_techniques/suggestions.py +3 -1
  100. angr/exploration_techniques/symbion.py +3 -1
  101. angr/exploration_techniques/tech_builder.py +2 -1
  102. angr/exploration_techniques/threading.py +4 -7
  103. angr/exploration_techniques/timeout.py +4 -2
  104. angr/exploration_techniques/tracer.py +4 -3
  105. angr/exploration_techniques/unique.py +3 -2
  106. angr/exploration_techniques/veritesting.py +1 -1
  107. angr/knowledge_plugins/key_definitions/atoms.py +2 -2
  108. angr/knowledge_plugins/key_definitions/live_definitions.py +16 -13
  109. angr/knowledge_plugins/propagations/states.py +13 -8
  110. angr/knowledge_plugins/variables/variable_manager.py +23 -9
  111. angr/lib/angr_native.dll +0 -0
  112. angr/sim_manager.py +1 -3
  113. angr/sim_state.py +39 -41
  114. angr/sim_type.py +5 -0
  115. angr/sim_variable.py +29 -28
  116. angr/utils/bits.py +17 -0
  117. angr/utils/formatting.py +4 -1
  118. angr/utils/orderedset.py +4 -1
  119. angr/utils/ssa/__init__.py +21 -3
  120. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/METADATA +6 -6
  121. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/RECORD +125 -124
  122. angr/analyses/decompiler/optimization_passes/multi_simplifier.py +0 -223
  123. angr/analyses/propagator/engine_ail.py +0 -1562
  124. angr/storage/memory_mixins/__init__.pyi +0 -48
  125. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/LICENSE +0 -0
  126. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/WHEEL +0 -0
  127. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/entry_points.txt +0 -0
  128. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/top_level.txt +0 -0
@@ -1,50 +1,53 @@
1
1
  from __future__ import annotations
2
2
  from collections import OrderedDict
3
3
 
4
- from ailment.statement import Assignment, Call, Store, ConditionalJump
4
+ from ailment.statement import Call, Store, ConditionalJump
5
5
  from ailment.expression import Register, BinaryOp, StackBaseOffset, ITE, VEXCCallExpression, Tmp, DirtyExpression
6
6
 
7
- from angr.engines.light import SimEngineLight, SimEngineLightAILMixin
7
+ from angr.engines.light import SimEngineLightAIL
8
+ from angr.project import Project
8
9
  from angr.utils.ssa import get_reg_offset_base
9
10
  from angr.utils.orderedset import OrderedSet
10
11
  from angr.calling_conventions import default_cc
11
12
  from .traversal_state import TraversalState
12
13
 
13
14
 
14
- class SimEngineSSATraversal(
15
- SimEngineLightAILMixin,
16
- SimEngineLight,
17
- ):
15
+ class SimEngineSSATraversal(SimEngineLightAIL[TraversalState, None, None, None]):
18
16
  """
19
17
  This engine collects all register and stack variable locations and links them to the block of their creation.
20
18
  """
21
19
 
22
- state: TraversalState
23
-
24
20
  def __init__(
25
21
  self,
26
- arch,
22
+ project: Project,
27
23
  simos,
28
24
  sp_tracker=None,
29
25
  bp_as_gpr: bool = False,
30
26
  def_to_loc=None,
31
27
  loc_to_defs=None,
32
28
  stackvars: bool = False,
33
- tmps: bool = False,
29
+ use_tmps: bool = False,
34
30
  ):
35
- super().__init__()
36
-
37
- self.arch = arch
31
+ super().__init__(project)
38
32
  self.simos = simos
39
33
  self.sp_tracker = sp_tracker
40
34
  self.bp_as_gpr = bp_as_gpr
41
35
  self.stackvars = stackvars
42
- self.tmps = tmps
36
+ self.use_tmps = use_tmps
43
37
 
44
38
  self.def_to_loc = def_to_loc if def_to_loc is not None else []
45
39
  self.loc_to_defs = loc_to_defs if loc_to_defs is not None else OrderedDict()
46
40
 
47
- def _handle_Assignment(self, stmt: Assignment):
41
+ def _is_top(self, expr):
42
+ return True
43
+
44
+ def _top(self, bits):
45
+ return None
46
+
47
+ def _process_block_end(self, block, stmt_data, whitelist):
48
+ pass
49
+
50
+ def _handle_stmt_Assignment(self, stmt):
48
51
  if isinstance(stmt.dst, Register):
49
52
  codeloc = self._codeloc()
50
53
  self.def_to_loc.append((stmt.dst, codeloc))
@@ -57,7 +60,7 @@ class SimEngineSSATraversal(
57
60
 
58
61
  self._expr(stmt.src)
59
62
 
60
- def _handle_Store(self, stmt: Store):
63
+ def _handle_stmt_Store(self, stmt: Store):
61
64
  self._expr(stmt.addr)
62
65
  self._expr(stmt.data)
63
66
  if stmt.guard is not None:
@@ -72,14 +75,14 @@ class SimEngineSSATraversal(
72
75
 
73
76
  self.state.live_stackvars.add((stmt.addr.offset, stmt.size))
74
77
 
75
- def _handle_ConditionalJump(self, stmt: ConditionalJump):
78
+ def _handle_stmt_ConditionalJump(self, stmt: ConditionalJump):
76
79
  self._expr(stmt.condition)
77
80
  if stmt.true_target is not None:
78
81
  self._expr(stmt.true_target)
79
82
  if stmt.false_target is not None:
80
83
  self._expr(stmt.false_target)
81
84
 
82
- def _handle_Call(self, stmt: Call):
85
+ def _handle_stmt_Call(self, stmt: Call):
83
86
 
84
87
  # kill caller-saved registers
85
88
  cc = (
@@ -87,6 +90,7 @@ class SimEngineSSATraversal(
87
90
  if stmt.calling_convention is None
88
91
  else stmt.calling_convention
89
92
  )
93
+ assert cc is not None
90
94
  for reg_name in cc.CALLER_SAVED_REGS:
91
95
  reg_offset = self.arch.registers[reg_name][0]
92
96
  base_off = get_reg_offset_base(reg_offset, self.arch)
@@ -102,11 +106,22 @@ class SimEngineSSATraversal(
102
106
  base_off = get_reg_offset_base(stmt.ret_expr.reg_offset, self.arch)
103
107
  self.state.live_registers.add(base_off)
104
108
 
105
- super()._ail_handle_Call(stmt)
109
+ def _handle_stmt_Dummy(self, stmt):
110
+ pass
111
+
112
+ def _handle_stmt_DirtyStatement(self, stmt):
113
+ self._expr(stmt.dirty)
114
+
115
+ def _handle_stmt_Jump(self, stmt):
116
+ self._expr(stmt.target)
106
117
 
107
- _handle_CallExpr = _handle_Call
118
+ _handle_stmt_Label = _handle_stmt_Dummy
108
119
 
109
- def _handle_Register(self, expr: Register):
120
+ def _handle_stmt_Return(self, stmt):
121
+ for expr in stmt.ret_exprs:
122
+ self._expr(expr)
123
+
124
+ def _handle_expr_Register(self, expr: Register):
110
125
  base_offset = get_reg_offset_base(expr.reg_offset, self.arch)
111
126
 
112
127
  if base_offset not in self.state.live_registers:
@@ -118,8 +133,8 @@ class SimEngineSSATraversal(
118
133
 
119
134
  self.state.live_registers.add(base_offset)
120
135
 
121
- def _handle_Tmp(self, expr: Tmp):
122
- if self.tmps:
136
+ def _handle_expr_Tmp(self, expr: Tmp):
137
+ if self.use_tmps:
123
138
  codeloc = self._codeloc()
124
139
  self.def_to_loc.append((expr, codeloc))
125
140
  if codeloc not in self.loc_to_defs:
@@ -128,39 +143,99 @@ class SimEngineSSATraversal(
128
143
 
129
144
  self.state.live_tmps.add(expr.tmp_idx)
130
145
 
131
- def _handle_Cmp(self, expr: BinaryOp):
146
+ def _handle_binop_Default(self, expr: BinaryOp):
132
147
  self._expr(expr.operands[0])
133
148
  self._expr(expr.operands[1])
134
149
 
135
- _handle_CmpLE = _handle_Cmp
136
- _handle_CmpLT = _handle_Cmp
137
- _handle_CmpGE = _handle_Cmp
138
- _handle_CmpGT = _handle_Cmp
139
- _handle_CmpEQ = _handle_Cmp
140
- _handle_CmpNE = _handle_Cmp
150
+ _handle_binop_CmpLE = _handle_binop_Default
151
+ _handle_binop_CmpLT = _handle_binop_Default
152
+ _handle_binop_CmpGE = _handle_binop_Default
153
+ _handle_binop_CmpGT = _handle_binop_Default
154
+ _handle_binop_CmpEQ = _handle_binop_Default
155
+ _handle_binop_CmpNE = _handle_binop_Default
156
+ _handle_binop_Add = _handle_binop_Default
157
+ _handle_binop_AddF = _handle_binop_Default
158
+ _handle_binop_AddV = _handle_binop_Default
159
+ _handle_binop_And = _handle_binop_Default
160
+ _handle_binop_Carry = _handle_binop_Default
161
+ _handle_binop_CmpF = _handle_binop_Default
162
+ _handle_binop_Concat = _handle_binop_Default
163
+ _handle_binop_Div = _handle_binop_Default
164
+ _handle_binop_DivF = _handle_binop_Default
165
+ _handle_binop_DivV = _handle_binop_Default
166
+ _handle_binop_LogicalAnd = _handle_binop_Default
167
+ _handle_binop_LogicalOr = _handle_binop_Default
168
+ _handle_binop_Mod = _handle_binop_Default
169
+ _handle_binop_Mul = _handle_binop_Default
170
+ _handle_binop_Mull = _handle_binop_Default
171
+ _handle_binop_MulF = _handle_binop_Default
172
+ _handle_binop_MulV = _handle_binop_Default
173
+ _handle_binop_MulHiV = _handle_binop_Default
174
+ _handle_binop_Or = _handle_binop_Default
175
+ _handle_binop_Rol = _handle_binop_Default
176
+ _handle_binop_Ror = _handle_binop_Default
177
+ _handle_binop_SBorrow = _handle_binop_Default
178
+ _handle_binop_SCarry = _handle_binop_Default
179
+ _handle_binop_Sar = _handle_binop_Default
180
+ _handle_binop_Shl = _handle_binop_Default
181
+ _handle_binop_Shr = _handle_binop_Default
182
+ _handle_binop_Sub = _handle_binop_Default
183
+ _handle_binop_SubF = _handle_binop_Default
184
+ _handle_binop_SubV = _handle_binop_Default
185
+ _handle_binop_Xor = _handle_binop_Default
186
+ _handle_binop_InterleaveLOV = _handle_binop_Default
187
+ _handle_binop_InterleaveHIV = _handle_binop_Default
188
+ _handle_binop_CasCmpEQ = _handle_binop_Default
189
+ _handle_binop_CasCmpNE = _handle_binop_Default
190
+ _handle_binop_ExpCmpNE = _handle_binop_Default
191
+ _handle_binop_SarNV = _handle_binop_Default
192
+ _handle_binop_ShrNV = _handle_binop_Default
193
+ _handle_binop_ShlNV = _handle_binop_Default
194
+ _handle_binop_CmpEQV = _handle_binop_Default
195
+ _handle_binop_CmpNEV = _handle_binop_Default
196
+ _handle_binop_CmpGEV = _handle_binop_Default
197
+ _handle_binop_CmpGTV = _handle_binop_Default
198
+ _handle_binop_CmpLEV = _handle_binop_Default
199
+ _handle_binop_CmpLTV = _handle_binop_Default
200
+ _handle_binop_MinV = _handle_binop_Default
201
+ _handle_binop_MaxV = _handle_binop_Default
202
+ _handle_binop_QAddV = _handle_binop_Default
203
+ _handle_binop_QNarrowBinV = _handle_binop_Default
204
+ _handle_binop_PermV = _handle_binop_Default
205
+ _handle_binop_Set = _handle_binop_Default
206
+
207
+ def _handle_unop_Default(self, expr):
208
+ self._expr(expr.operands[0])
141
209
 
142
- def _handle_UnaryOp(self, expr):
210
+ _handle_unop_BitwiseNeg = _handle_unop_Default
211
+ _handle_unop_Dereference = _handle_unop_Default
212
+ _handle_unop_Neg = _handle_unop_Default
213
+ _handle_unop_Not = _handle_unop_Default
214
+ _handle_unop_Reference = _handle_unop_Default
215
+ _handle_unop_Clz = _handle_unop_Default
216
+ _handle_unop_Ctz = _handle_unop_Default
217
+ _handle_unop_GetMSBs = _handle_unop_Default
218
+ _handle_unop_unpack = _handle_unop_Default
219
+ _handle_unop_Sqrt = _handle_unop_Default
220
+ _handle_unop_RSqrtEst = _handle_unop_Default
221
+
222
+ def _handle_expr_UnaryOp(self, expr):
143
223
  self._expr(expr.operand)
144
224
 
145
- def _handle_BinaryOp(self, expr):
146
- self._expr(expr.operands[0])
147
- self._expr(expr.operands[1])
148
-
149
- def _handle_TernaryOp(self, expr):
225
+ def _handle_expr_BinaryOp(self, expr):
150
226
  self._expr(expr.operands[0])
151
227
  self._expr(expr.operands[1])
152
- self._expr(expr.operands[2])
153
228
 
154
- def _handle_ITE(self, expr: ITE):
229
+ def _handle_expr_ITE(self, expr: ITE):
155
230
  self._expr(expr.cond)
156
231
  self._expr(expr.iftrue)
157
232
  self._expr(expr.iffalse)
158
233
 
159
- def _handle_VEXCCallExpression(self, expr: VEXCCallExpression):
234
+ def _handle_expr_VEXCCallExpression(self, expr: VEXCCallExpression):
160
235
  for operand in expr.operands:
161
236
  self._expr(operand)
162
237
 
163
- def _handle_DirtyExpression(self, expr: DirtyExpression):
238
+ def _handle_expr_DirtyExpression(self, expr: DirtyExpression):
164
239
  for operand in expr.operands:
165
240
  self._expr(operand)
166
241
  if expr.guard is not None:
@@ -171,5 +246,13 @@ class SimEngineSSATraversal(
171
246
  def _handle_Dummy(self, expr):
172
247
  pass
173
248
 
174
- _handle_VirtualVariable = _handle_Dummy
175
- _handle_Phi = _handle_Dummy
249
+ _handle_expr_VirtualVariable = _handle_Dummy
250
+ _handle_expr_Phi = _handle_Dummy
251
+ _handle_expr_Load = _handle_Dummy
252
+ _handle_expr_Convert = _handle_Dummy
253
+ _handle_expr_Const = _handle_Dummy
254
+ _handle_expr_MultiStatementExpression = _handle_Dummy
255
+ _handle_expr_Reinterpret = _handle_Dummy
256
+ _handle_expr_StackBaseOffset = _handle_Dummy
257
+ _handle_expr_BasePointerOffset = _handle_Dummy
258
+ _handle_expr_Call = _handle_Dummy
@@ -33,6 +33,7 @@ from angr.sim_type import (
33
33
  dereference_simtype,
34
34
  SimTypeInt128,
35
35
  SimTypeInt256,
36
+ SimTypeInt512,
36
37
  )
37
38
  from angr.knowledge_plugins.functions import Function
38
39
  from angr.sim_variable import SimVariable, SimTemporaryVariable, SimStackVariable, SimMemoryVariable
@@ -52,6 +53,7 @@ from angr.analyses.decompiler.structuring.structurer_nodes import (
52
53
  LoopNode,
53
54
  BreakNode,
54
55
  SwitchCaseNode,
56
+ IncompleteSwitchCaseNode,
55
57
  ContinueNode,
56
58
  CascadingConditionNode,
57
59
  )
@@ -1136,6 +1138,53 @@ class CSwitchCase(CStatement):
1136
1138
  yield "\n", None
1137
1139
 
1138
1140
 
1141
+ class CIncompleteSwitchCase(CStatement):
1142
+ """
1143
+ Represents an incomplete switch-case construct; this only appear in the decompilation output when switch-case
1144
+ structuring fails (for whatever reason).
1145
+ """
1146
+
1147
+ __slots__ = ("head", "cases", "tags")
1148
+
1149
+ def __init__(self, head, cases, tags=None, **kwargs):
1150
+ super().__init__(**kwargs)
1151
+
1152
+ self.head = head
1153
+ self.cases: list[tuple[int, CStatements]] = cases
1154
+ self.tags = tags
1155
+
1156
+ def c_repr_chunks(self, indent=0, asexpr=False):
1157
+ indent_str = self.indent_str(indent=indent)
1158
+ paren = CClosingObject("(")
1159
+ brace = CClosingObject("{")
1160
+
1161
+ yield from self.head.c_repr_chunks(indent=indent)
1162
+ yield "\n", None
1163
+ yield indent_str, None
1164
+ yield "switch ", self
1165
+ yield "(", paren
1166
+ yield "/* incomplete */", None
1167
+ yield ")", paren
1168
+ if self.codegen.braces_on_own_lines:
1169
+ yield "\n", None
1170
+ yield indent_str, None
1171
+ else:
1172
+ yield " ", None
1173
+ yield "{", brace
1174
+ yield "\n", None
1175
+
1176
+ # cases
1177
+ for case_addr, case in self.cases:
1178
+ yield indent_str, None
1179
+ yield f"case {case_addr:#x}", self
1180
+ yield ":\n", None
1181
+ yield from case.c_repr_chunks(indent=indent + INDENT_DELTA)
1182
+
1183
+ yield indent_str, None
1184
+ yield "}", brace
1185
+ yield "\n", None
1186
+
1187
+
1139
1188
  class CAssignment(CStatement):
1140
1189
  """
1141
1190
  a = b
@@ -1299,6 +1348,8 @@ class CFunctionCall(CStatement, CExpression):
1299
1348
  if self.show_disambiguated_name and self._is_target_ambiguous(func_name):
1300
1349
  func_name = self.callee_func.get_unambiguous_name(display_name=func_name)
1301
1350
  yield func_name, self
1351
+ elif isinstance(self.callee_target, str):
1352
+ yield self.callee_target, self
1302
1353
  else:
1303
1354
  yield from CExpression._try_c_repr_chunks(self.callee_target)
1304
1355
 
@@ -1819,7 +1870,6 @@ class CBinaryOp(CExpression):
1819
1870
  "Mul": self._c_repr_chunks_mul,
1820
1871
  "Mull": self._c_repr_chunks_mull,
1821
1872
  "Div": self._c_repr_chunks_div,
1822
- "DivMod": self._c_repr_chunks_divmod,
1823
1873
  "Mod": self._c_repr_chunks_mod,
1824
1874
  "And": self._c_repr_chunks_and,
1825
1875
  "Xor": self._c_repr_chunks_xor,
@@ -2443,6 +2493,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
2443
2493
  Block: self._handle_AILBlock,
2444
2494
  BreakNode: self._handle_Break,
2445
2495
  SwitchCaseNode: self._handle_SwitchCase,
2496
+ IncompleteSwitchCaseNode: self._handle_IncompleteSwitchCase,
2446
2497
  ContinueNode: self._handle_Continue,
2447
2498
  # AIL statements
2448
2499
  Stmt.Store: self._handle_Stmt_Store,
@@ -2671,16 +2722,16 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
2671
2722
  # Util methods
2672
2723
  #
2673
2724
 
2674
- def default_simtype_from_size(self, n: int, signed: bool = True) -> SimType:
2725
+ def default_simtype_from_bits(self, n: int, signed: bool = True) -> SimType:
2675
2726
  _mapping = {
2676
- 8: SimTypeLongLong,
2677
- 4: SimTypeInt,
2678
- 2: SimTypeShort,
2679
- 1: SimTypeChar,
2727
+ 64: SimTypeLongLong,
2728
+ 32: SimTypeInt,
2729
+ 16: SimTypeShort,
2730
+ 8: SimTypeChar,
2680
2731
  }
2681
2732
  if n in _mapping:
2682
2733
  return _mapping.get(n)(signed=signed).with_arch(self.project.arch)
2683
- return SimTypeNum(n * self.project.arch.byte_width, signed=signed).with_arch(self.project.arch)
2734
+ return SimTypeNum(n, signed=signed).with_arch(self.project.arch)
2684
2735
 
2685
2736
  def _variable(self, variable: SimVariable, fallback_type_size: int | None) -> CVariable:
2686
2737
  # TODO: we need to fucking make sure that variable recovery and type inference actually generates a size
@@ -2690,7 +2741,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
2690
2741
  variable, is_global=isinstance(variable, SimMemoryVariable) and not isinstance(variable, SimStackVariable)
2691
2742
  )
2692
2743
  if variable_type is None:
2693
- variable_type = self.default_simtype_from_size(fallback_type_size or self.project.arch.bytes)
2744
+ variable_type = self.default_simtype_from_bits(
2745
+ (fallback_type_size or self.project.arch.bytes) * self.project.arch.byte_width
2746
+ )
2694
2747
  cvar = CVariable(variable, unified_variable=unified, variable_type=variable_type, codegen=self)
2695
2748
  self._variables_in_use[variable] = cvar
2696
2749
  return cvar
@@ -3172,6 +3225,12 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3172
3225
  tags = {"ins_addr": node.addr}
3173
3226
  return CSwitchCase(switch_expr, cases, default=default, tags=tags, codegen=self)
3174
3227
 
3228
+ def _handle_IncompleteSwitchCase(self, node: IncompleteSwitchCaseNode, **kwargs):
3229
+ head = self._handle(node.head, is_expr=False)
3230
+ cases = [(case.addr, self._handle(case, is_expr=False)) for case in node.cases]
3231
+ tags = {"ins_addr": node.addr}
3232
+ return CIncompleteSwitchCase(head, cases, tags=tags, codegen=self)
3233
+
3175
3234
  def _handle_Continue(self, node, **kwargs):
3176
3235
  tags = {"ins_addr": node.addr}
3177
3236
 
@@ -3313,7 +3372,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3313
3372
  if result.is_expr and result.type.size != stmt.size * self.project.arch.byte_width:
3314
3373
  result = CTypeCast(
3315
3374
  result.type,
3316
- self.default_simtype_from_size(stmt.size, signed=getattr(result.type, "signed", False)),
3375
+ self.default_simtype_from_bits(
3376
+ stmt.size * self.project.arch.byte_width, signed=getattr(result.type, "signed", False)
3377
+ ),
3317
3378
  result,
3318
3379
  codegen=self,
3319
3380
  )
@@ -3376,12 +3437,12 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3376
3437
  return cvar
3377
3438
  offset = 0 if expr.variable_offset is None else expr.variable_offset
3378
3439
  # FIXME: The type should be associated to the register expression itself
3379
- type_ = self.default_simtype_from_size(expr.size, signed=False)
3440
+ type_ = self.default_simtype_from_bits(expr.bits, signed=False)
3380
3441
  return self._access_constant_offset(self._get_variable_reference(cvar), offset, type_, lvalue, negotiate)
3381
3442
  return CRegister(expr, tags=expr.tags, codegen=self)
3382
3443
 
3383
3444
  def _handle_Expr_Load(self, expr: Expr.Load, **kwargs):
3384
- ty = self.default_simtype_from_size(expr.size)
3445
+ ty = self.default_simtype_from_bits(expr.bits)
3385
3446
 
3386
3447
  def negotiate(old_ty: SimType, proposed_ty: SimType) -> SimType:
3387
3448
  # we do not allow returning a struct for a primitive type
@@ -3404,9 +3465,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3404
3465
 
3405
3466
  def _handle_Expr_Tmp(self, expr: Tmp, **kwargs):
3406
3467
  l.warning("FIXME: Leftover Tmp expressions are found.")
3407
- return self._variable(SimTemporaryVariable(expr.tmp_idx), expr.size)
3468
+ return self._variable(SimTemporaryVariable(expr.tmp_idx, expr.bits), expr.size)
3408
3469
 
3409
- def _handle_Expr_Const(self, expr, type_=None, reference_values=None, variable=None, **kwargs):
3470
+ def _handle_Expr_Const(self, expr: Expr.Const, type_=None, reference_values=None, variable=None, **kwargs):
3410
3471
  inline_string = False
3411
3472
  function_pointer = False
3412
3473
 
@@ -3483,7 +3544,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3483
3544
 
3484
3545
  if type_ is None:
3485
3546
  # default to int
3486
- type_ = self.default_simtype_from_size(expr.size)
3547
+ type_ = self.default_simtype_from_bits(expr.bits)
3487
3548
 
3488
3549
  if variable is None and hasattr(expr, "reference_variable") and expr.reference_variable is not None:
3489
3550
  variable = expr.reference_variable
@@ -3529,7 +3590,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3529
3590
  def _handle_Expr_Convert(self, expr: Expr.Convert, **kwargs):
3530
3591
  # width of converted type is easy
3531
3592
  dst_type: SimTypeInt | SimTypeChar
3532
- if 258 >= expr.to_bits > 128:
3593
+ if 512 >= expr.to_bits > 256:
3594
+ dst_type = SimTypeInt512()
3595
+ elif 256 >= expr.to_bits > 128:
3533
3596
  dst_type = SimTypeInt256()
3534
3597
  elif 128 >= expr.to_bits > 64:
3535
3598
  dst_type = SimTypeInt128()
@@ -3561,7 +3624,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
3561
3624
  # do we need an intermediate cast?
3562
3625
  if orig_child_signed != expr.is_signed and expr.to_bits > expr.from_bits:
3563
3626
  # this is a problem. sign-extension only happens when the SOURCE of the cast is signed
3564
- child_ty = self.default_simtype_from_size(child.type.size // self.project.arch.byte_width, expr.is_signed)
3627
+ child_ty = self.default_simtype_from_bits(child.type.size, expr.is_signed)
3565
3628
  child = CTypeCast(None, child_ty, child, codegen=self)
3566
3629
 
3567
3630
  return CTypeCast(None, dst_type.with_arch(self.project.arch), child, tags=expr.tags, codegen=self)
@@ -1192,8 +1192,10 @@ class PhoenixStructurer(StructurerBase):
1192
1192
  # update node_a
1193
1193
  node_a = next(iter(nn for nn in graph.nodes if nn.addr == target))
1194
1194
  if isinstance(node_a, IncompleteSwitchCaseNode):
1195
- self._unpack_incompleteswitchcasenode(graph, node_a)
1196
- self._unpack_incompleteswitchcasenode(full_graph, node_a)
1195
+ r = self._unpack_incompleteswitchcasenode(graph, node_a)
1196
+ if not r:
1197
+ return False
1198
+ self._unpack_incompleteswitchcasenode(full_graph, node_a) # this shall not fail
1197
1199
  # update node_a
1198
1200
  node_a = next(iter(nn for nn in graph.nodes if nn.addr == target))
1199
1201
 
@@ -1308,7 +1310,9 @@ class PhoenixStructurer(StructurerBase):
1308
1310
  ):
1309
1311
  out_nodes = set()
1310
1312
  for succ in successors:
1311
- out_nodes |= set(full_graph.successors(succ))
1313
+ out_nodes |= {
1314
+ succ for succ in full_graph.successors(succ) if succ is not node and succ not in successors
1315
+ }
1312
1316
  out_nodes = list(out_nodes)
1313
1317
  if len(out_nodes) <= 1:
1314
1318
  new_node = IncompleteSwitchCaseNode(node.addr, node, successors)
@@ -1508,7 +1512,10 @@ class PhoenixStructurer(StructurerBase):
1508
1512
  if node_default is not None:
1509
1513
  all_case_nodes.append(node_default)
1510
1514
  case_node: SequenceNode = next(nn for nn in all_case_nodes if nn.addr == out_src.addr)
1511
- case_node_last_stmt = self.cond_proc.get_last_statement(case_node)
1515
+ try:
1516
+ case_node_last_stmt = self.cond_proc.get_last_statement(case_node)
1517
+ except EmptyBlockNotice:
1518
+ case_node_last_stmt = None
1512
1519
  if not isinstance(case_node_last_stmt, Jump):
1513
1520
  jump_stmt = Jump(
1514
1521
  None, Const(None, None, head.addr, self.project.arch.bits), None, ins_addr=out_src.addr
@@ -1562,6 +1569,15 @@ class PhoenixStructurer(StructurerBase):
1562
1569
 
1563
1570
  return case_and_entry_addrs
1564
1571
 
1572
+ def _is_switch_cases_address_loaded_from_memory_head_or_jumpnode(self, graph, node) -> bool:
1573
+ jump_tables = self.kb.cfgs["CFGFast"].jump_tables
1574
+ if node.addr in jump_tables:
1575
+ return True
1576
+ for succ in graph.successors(node):
1577
+ if succ.addr in jump_tables:
1578
+ return True
1579
+ return node in self.switch_case_known_heads
1580
+
1565
1581
  # other acyclic schemas
1566
1582
 
1567
1583
  def _match_acyclic_sequence(self, graph, full_graph, start_node) -> bool:
@@ -1571,14 +1587,12 @@ class PhoenixStructurer(StructurerBase):
1571
1587
  succs = list(graph.successors(start_node))
1572
1588
  if len(succs) == 1:
1573
1589
  end_node = succs[0]
1574
- jump_tables = self.kb.cfgs["CFGFast"].jump_tables
1575
1590
  if (
1576
1591
  full_graph.out_degree[start_node] == 1
1577
1592
  and full_graph.in_degree[end_node] == 1
1578
1593
  and not full_graph.has_edge(end_node, start_node)
1579
- and end_node.addr not in jump_tables
1580
- and end_node not in self.switch_case_known_heads
1581
- and start_node not in self.switch_case_known_heads
1594
+ and not self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, end_node)
1595
+ and not self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, start_node)
1582
1596
  and end_node not in self.dowhile_known_tail_nodes
1583
1597
  ):
1584
1598
  # merge two blocks
@@ -1599,7 +1613,9 @@ class PhoenixStructurer(StructurerBase):
1599
1613
  succs = list(full_graph.successors(start_node))
1600
1614
  if len(succs) == 2:
1601
1615
  left, right = succs
1602
- if left in self.switch_case_known_heads or right in self.switch_case_known_heads:
1616
+ if self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(
1617
+ full_graph, left
1618
+ ) or self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, right):
1603
1619
  # structure the switch-case first before we wrap them into an ITE. give up
1604
1620
  return False
1605
1621
 
@@ -2032,7 +2048,9 @@ class PhoenixStructurer(StructurerBase):
2032
2048
  left, right = right, left
2033
2049
 
2034
2050
  # ensure left and right nodes are not the head of a switch-case construct
2035
- if left in self.switch_case_known_heads or right in self.switch_case_known_heads:
2051
+ if self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(
2052
+ full_graph, left
2053
+ ) or self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, right):
2036
2054
  return None
2037
2055
 
2038
2056
  if (
@@ -2079,7 +2097,9 @@ class PhoenixStructurer(StructurerBase):
2079
2097
  left, right = right, left
2080
2098
 
2081
2099
  # ensure left and right nodes are not the head of a switch-case construct
2082
- if left in self.switch_case_known_heads or right in self.switch_case_known_heads:
2100
+ if self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(
2101
+ full_graph, left
2102
+ ) or self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, right):
2083
2103
  return None
2084
2104
 
2085
2105
  if (
@@ -2120,7 +2140,9 @@ class PhoenixStructurer(StructurerBase):
2120
2140
  left, successor = successor, left
2121
2141
 
2122
2142
  # ensure left and successor nodes are not the head of a switch-case construct
2123
- if left in self.switch_case_known_heads or successor in self.switch_case_known_heads:
2143
+ if self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(
2144
+ full_graph, left
2145
+ ) or self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, successor):
2124
2146
  return None
2125
2147
 
2126
2148
  if (
@@ -2168,7 +2190,9 @@ class PhoenixStructurer(StructurerBase):
2168
2190
  left, else_node = else_node, left
2169
2191
 
2170
2192
  # ensure left and else nodes are not the head of a switch-case construct
2171
- if left in self.switch_case_known_heads or else_node in self.switch_case_known_heads:
2193
+ if self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(
2194
+ full_graph, left
2195
+ ) or self._is_switch_cases_address_loaded_from_memory_head_or_jumpnode(full_graph, else_node):
2172
2196
  return None
2173
2197
 
2174
2198
  if (
@@ -2460,7 +2484,7 @@ class PhoenixStructurer(StructurerBase):
2460
2484
  return True, new_seq
2461
2485
 
2462
2486
  @staticmethod
2463
- def _unpack_incompleteswitchcasenode(graph: networkx.DiGraph, incscnode: IncompleteSwitchCaseNode):
2487
+ def _unpack_incompleteswitchcasenode(graph: networkx.DiGraph, incscnode: IncompleteSwitchCaseNode) -> bool:
2464
2488
  preds = list(graph.predecessors(incscnode))
2465
2489
  succs = list(graph.successors(incscnode))
2466
2490
  if len(succs) <= 1:
@@ -2471,6 +2495,8 @@ class PhoenixStructurer(StructurerBase):
2471
2495
  graph.add_edge(incscnode.head, case_node)
2472
2496
  if succs:
2473
2497
  graph.add_edge(case_node, succs[0])
2498
+ return True
2499
+ return False
2474
2500
 
2475
2501
  @staticmethod
2476
2502
  def _count_statements(node: BaseNode | Block) -> int:
@@ -411,3 +411,12 @@ class IncompleteSwitchCaseHeadStatement(ailment.statement.Statement):
411
411
  return ailment.utils.stable_hash(
412
412
  (IncompleteSwitchCaseHeadStatement, self.idx, self.switch_variable, self._case_addrs_str)
413
413
  )
414
+
415
+ def replace(self, old_expr, new_expr):
416
+ return self
417
+
418
+ def likes(self, other):
419
+ return self == other
420
+
421
+ def matches(self, other):
422
+ return self == other