angr 9.2.137__py3-none-macosx_11_0_arm64.whl → 9.2.139__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.
- angr/__init__.py +1 -1
- angr/analyses/calling_convention/fact_collector.py +59 -12
- angr/analyses/calling_convention/utils.py +2 -2
- angr/analyses/cfg/cfg_fast.py +15 -4
- angr/analyses/complete_calling_conventions.py +3 -3
- angr/analyses/decompiler/ail_simplifier.py +14 -3
- angr/analyses/decompiler/block_simplifier.py +0 -2
- angr/analyses/decompiler/callsite_maker.py +80 -14
- angr/analyses/decompiler/clinic.py +31 -37
- angr/analyses/decompiler/condition_processor.py +2 -2
- angr/analyses/decompiler/decompilation_options.py +10 -0
- angr/analyses/decompiler/decompiler.py +2 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +16 -7
- angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +149 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +12 -3
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +5 -2
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +15 -7
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +12 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +61 -25
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +21 -3
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +50 -1
- angr/analyses/decompiler/presets/fast.py +2 -0
- angr/analyses/decompiler/presets/full.py +2 -0
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +4 -0
- angr/analyses/decompiler/ssailification/rewriting_engine.py +20 -2
- angr/analyses/decompiler/ssailification/traversal_engine.py +4 -3
- angr/analyses/decompiler/structured_codegen/c.py +10 -3
- angr/analyses/decompiler/structuring/dream.py +7 -2
- angr/analyses/decompiler/structuring/phoenix.py +101 -49
- angr/analyses/decompiler/structuring/structurer_base.py +85 -36
- angr/analyses/decompiler/structuring/structurer_nodes.py +3 -1
- angr/analyses/deobfuscator/api_obf_finder.py +6 -1
- angr/analyses/deobfuscator/api_obf_type2_finder.py +158 -0
- angr/analyses/s_propagator.py +202 -47
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -2
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -1
- angr/analyses/variable_recovery/engine_ail.py +1 -1
- angr/analyses/variable_recovery/engine_base.py +55 -62
- angr/analyses/variable_recovery/engine_vex.py +1 -1
- angr/analyses/variable_recovery/irsb_scanner.py +2 -2
- angr/calling_conventions.py +66 -9
- angr/engines/engine.py +2 -18
- angr/engines/light/engine.py +3 -8
- angr/engines/pcode/emulate.py +2 -2
- angr/engines/pcode/lifter.py +2 -2
- angr/engines/successors.py +1 -8
- angr/engines/vex/lifter.py +2 -2
- angr/engines/vex/light/light.py +2 -2
- angr/knowledge_plugins/cfg/cfg_model.py +3 -2
- angr/knowledge_plugins/labels.py +2 -2
- angr/knowledge_plugins/obfuscations.py +1 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +4 -0
- angr/lib/angr_native.dylib +0 -0
- angr/procedures/glibc/__libc_start_main.py +10 -3
- angr/utils/ssa/__init__.py +14 -1
- {angr-9.2.137.dist-info → angr-9.2.139.dist-info}/METADATA +6 -6
- {angr-9.2.137.dist-info → angr-9.2.139.dist-info}/RECORD +65 -63
- {angr-9.2.137.dist-info → angr-9.2.139.dist-info}/LICENSE +0 -0
- {angr-9.2.137.dist-info → angr-9.2.139.dist-info}/WHEEL +0 -0
- {angr-9.2.137.dist-info → angr-9.2.139.dist-info}/entry_points.txt +0 -0
- {angr-9.2.137.dist-info → angr-9.2.139.dist-info}/top_level.txt +0 -0
angr/analyses/s_propagator.py
CHANGED
|
@@ -4,6 +4,8 @@ import contextlib
|
|
|
4
4
|
from collections.abc import Mapping
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
|
|
7
|
+
import networkx
|
|
8
|
+
|
|
7
9
|
from ailment.block import Block
|
|
8
10
|
from ailment.expression import (
|
|
9
11
|
Const,
|
|
@@ -14,7 +16,7 @@ from ailment.expression import (
|
|
|
14
16
|
Convert,
|
|
15
17
|
Expression,
|
|
16
18
|
)
|
|
17
|
-
from ailment.statement import Assignment, Store, Return, Jump
|
|
19
|
+
from ailment.statement import Assignment, Store, Return, Jump, ConditionalJump
|
|
18
20
|
|
|
19
21
|
from angr.knowledge_plugins.functions import Function
|
|
20
22
|
from angr.code_location import CodeLocation, ExternalCodeLocation
|
|
@@ -22,6 +24,8 @@ from angr.analyses import Analysis, register_analysis
|
|
|
22
24
|
from angr.utils.ssa import (
|
|
23
25
|
get_vvar_uselocs,
|
|
24
26
|
get_vvar_deflocs,
|
|
27
|
+
has_ite_expr,
|
|
28
|
+
has_ite_stmt,
|
|
25
29
|
is_phi_assignment,
|
|
26
30
|
is_const_assignment,
|
|
27
31
|
is_const_and_vvar_assignment,
|
|
@@ -41,6 +45,8 @@ class SPropagatorModel:
|
|
|
41
45
|
|
|
42
46
|
def __init__(self):
|
|
43
47
|
self.replacements: Mapping[CodeLocation, Mapping[Expression, Expression]] = {}
|
|
48
|
+
# store vvars that are definitely dead (but usually not removed by default because they are stack variables)
|
|
49
|
+
self.dead_vvar_ids: set[int] = set()
|
|
44
50
|
|
|
45
51
|
|
|
46
52
|
class SPropagatorAnalysis(Analysis):
|
|
@@ -51,7 +57,7 @@ class SPropagatorAnalysis(Analysis):
|
|
|
51
57
|
def __init__( # pylint: disable=too-many-positional-arguments
|
|
52
58
|
self,
|
|
53
59
|
subject: Block | Function,
|
|
54
|
-
func_graph=None,
|
|
60
|
+
func_graph: networkx.DiGraph | None = None,
|
|
55
61
|
only_consts: bool = True,
|
|
56
62
|
stack_pointer_tracker=None,
|
|
57
63
|
func_args: set[VirtualVariable] | None = None,
|
|
@@ -86,6 +92,7 @@ class SPropagatorAnalysis(Analysis):
|
|
|
86
92
|
bp_as_gpr = the_func.info.get("bp_as_gpr", False)
|
|
87
93
|
self._bp_as_gpr = bp_as_gpr
|
|
88
94
|
|
|
95
|
+
# output
|
|
89
96
|
self.model = SPropagatorModel()
|
|
90
97
|
|
|
91
98
|
self._analyze()
|
|
@@ -94,6 +101,10 @@ class SPropagatorAnalysis(Analysis):
|
|
|
94
101
|
def replacements(self):
|
|
95
102
|
return self.model.replacements
|
|
96
103
|
|
|
104
|
+
@property
|
|
105
|
+
def dead_vvar_ids(self):
|
|
106
|
+
return self.model.dead_vvar_ids
|
|
107
|
+
|
|
97
108
|
def _analyze(self):
|
|
98
109
|
blocks: dict[tuple[int, int | None], Block]
|
|
99
110
|
match self.mode:
|
|
@@ -128,7 +139,7 @@ class SPropagatorAnalysis(Analysis):
|
|
|
128
139
|
|
|
129
140
|
replacements = defaultdict(dict)
|
|
130
141
|
|
|
131
|
-
# find constant assignments
|
|
142
|
+
# find constant and other propagatable assignments
|
|
132
143
|
vvarid_to_vvar = {}
|
|
133
144
|
const_vvars: dict[int, Const] = {}
|
|
134
145
|
for vvar, defloc in vvar_deflocs.items():
|
|
@@ -136,10 +147,12 @@ class SPropagatorAnalysis(Analysis):
|
|
|
136
147
|
continue
|
|
137
148
|
|
|
138
149
|
vvarid_to_vvar[vvar.varid] = vvar
|
|
139
|
-
defloc = vvar_deflocs[vvar]
|
|
140
150
|
if isinstance(defloc, ExternalCodeLocation):
|
|
141
151
|
continue
|
|
142
152
|
|
|
153
|
+
assert defloc.block_addr is not None
|
|
154
|
+
assert defloc.stmt_idx is not None
|
|
155
|
+
|
|
143
156
|
block = blocks[(defloc.block_addr, defloc.block_idx)]
|
|
144
157
|
stmt = block.statements[defloc.stmt_idx]
|
|
145
158
|
r, v = is_const_assignment(stmt)
|
|
@@ -155,78 +168,143 @@ class SPropagatorAnalysis(Analysis):
|
|
|
155
168
|
if v is not None:
|
|
156
169
|
src_varids = {vvar.varid if vvar is not None else None for _, vvar in v.src_and_vvars}
|
|
157
170
|
if None not in src_varids and all(varid in const_vvars for varid in src_varids):
|
|
171
|
+
all_int_src_varids: set[int] = {varid for varid in src_varids if varid is not None}
|
|
158
172
|
src_values = {
|
|
159
173
|
(
|
|
160
174
|
(const_vvars[varid].value, const_vvars[varid].bits)
|
|
161
175
|
if isinstance(const_vvars[varid], Const)
|
|
162
176
|
else const_vvars[varid]
|
|
163
177
|
)
|
|
164
|
-
for varid in
|
|
178
|
+
for varid in all_int_src_varids
|
|
165
179
|
}
|
|
166
180
|
if len(src_values) == 1:
|
|
167
181
|
# replace it!
|
|
168
|
-
const_value = const_vvars[next(iter(
|
|
182
|
+
const_value = const_vvars[next(iter(all_int_src_varids))]
|
|
169
183
|
const_vvars[vvar.varid] = const_value
|
|
170
184
|
for vvar_at_use, useloc in vvar_uselocs[vvar.varid]:
|
|
171
185
|
replacements[useloc][vvar_at_use] = const_value
|
|
172
186
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
# function mode only
|
|
188
|
+
if self.mode == "function":
|
|
189
|
+
for vvar, defloc in vvar_deflocs.items():
|
|
190
|
+
if vvar.varid not in vvar_uselocs:
|
|
191
|
+
continue
|
|
192
|
+
if vvar.varid in const_vvars:
|
|
193
|
+
continue
|
|
194
|
+
if isinstance(defloc, ExternalCodeLocation):
|
|
195
|
+
continue
|
|
196
|
+
|
|
197
|
+
assert defloc.block_addr is not None
|
|
198
|
+
assert defloc.stmt_idx is not None
|
|
199
|
+
|
|
200
|
+
block = blocks[(defloc.block_addr, defloc.block_idx)]
|
|
201
|
+
stmt = block.statements[defloc.stmt_idx]
|
|
202
|
+
if (
|
|
203
|
+
(vvar.was_reg or vvar.was_parameter)
|
|
204
|
+
and len(vvar_uselocs[vvar.varid]) <= 2
|
|
205
|
+
and isinstance(stmt, Assignment)
|
|
206
|
+
and isinstance(stmt.src, Load)
|
|
207
|
+
):
|
|
208
|
+
# do we want to propagate this Load expression if it's used for less than twice?
|
|
209
|
+
# it's often seen in the following pattern, where propagation will be beneficial:
|
|
210
|
+
# v0 = Load(...)
|
|
211
|
+
# if (!v0) {
|
|
212
|
+
# v1 = v0 + 1;
|
|
213
|
+
# }
|
|
214
|
+
can_replace = True
|
|
215
|
+
for _, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
216
|
+
if self.has_store_stmt_in_between(blocks, defloc, vvar_useloc):
|
|
217
|
+
can_replace = False
|
|
218
|
+
|
|
219
|
+
if can_replace:
|
|
185
220
|
# we can propagate this load because there is no store between its def and use
|
|
186
|
-
|
|
221
|
+
for vvar_used, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
222
|
+
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
187
223
|
continue
|
|
188
224
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
):
|
|
201
|
-
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
202
|
-
else:
|
|
225
|
+
if (
|
|
226
|
+
(vvar.was_reg or vvar.was_stack)
|
|
227
|
+
and len(vvar_uselocs[vvar.varid]) == 2
|
|
228
|
+
and not is_phi_assignment(stmt)
|
|
229
|
+
):
|
|
230
|
+
# a special case: in a typical switch-case construct, a variable may be used once for comparison
|
|
231
|
+
# for the default case and then used again for constructing the jump target. we can propagate this
|
|
232
|
+
# variable for such cases.
|
|
233
|
+
uselocs = {loc for _, loc in vvar_uselocs[vvar.varid]}
|
|
234
|
+
if self.is_vvar_used_for_addr_loading_switch_case(uselocs, blocks):
|
|
235
|
+
for vvar_used, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
203
236
|
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
237
|
+
# mark the vvar as dead and should be removed
|
|
238
|
+
self.model.dead_vvar_ids.add(vvar.varid)
|
|
204
239
|
continue
|
|
205
240
|
|
|
206
|
-
|
|
207
|
-
len(
|
|
208
|
-
|
|
241
|
+
if vvar.was_reg or vvar.was_parameter:
|
|
242
|
+
if len(vvar_uselocs[vvar.varid]) == 1:
|
|
243
|
+
vvar_used, vvar_useloc = next(iter(vvar_uselocs[vvar.varid]))
|
|
244
|
+
if is_const_vvar_load_assignment(stmt) and not self.has_store_stmt_in_between(
|
|
245
|
+
blocks, defloc, vvar_useloc
|
|
246
|
+
):
|
|
247
|
+
# we can propagate this load because there is no store between its def and use
|
|
248
|
+
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
249
|
+
continue
|
|
250
|
+
|
|
251
|
+
if is_const_and_vvar_assignment(stmt):
|
|
252
|
+
# if the useloc is a phi assignment statement, ensure that stmt.src is the same as the phi
|
|
253
|
+
# variable
|
|
254
|
+
assert vvar_useloc.block_addr is not None
|
|
255
|
+
assert vvar_useloc.stmt_idx is not None
|
|
256
|
+
useloc_stmt = blocks[(vvar_useloc.block_addr, vvar_useloc.block_idx)].statements[
|
|
257
|
+
vvar_useloc.stmt_idx
|
|
258
|
+
]
|
|
259
|
+
if is_phi_assignment(useloc_stmt):
|
|
260
|
+
if (
|
|
261
|
+
isinstance(stmt.src, VirtualVariable)
|
|
262
|
+
and stmt.src.oident == useloc_stmt.dst.oident
|
|
263
|
+
and stmt.src.category == useloc_stmt.dst.category
|
|
264
|
+
):
|
|
265
|
+
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
266
|
+
else:
|
|
267
|
+
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
else:
|
|
271
|
+
non_exitsite_uselocs = [
|
|
209
272
|
loc
|
|
210
273
|
for _, loc in vvar_uselocs[vvar.varid]
|
|
211
274
|
if (loc.block_addr, loc.block_idx, loc.stmt_idx) not in (retsites | jumpsites)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
275
|
+
]
|
|
276
|
+
if is_const_and_vvar_assignment(stmt):
|
|
277
|
+
if len(non_exitsite_uselocs) == 1:
|
|
278
|
+
# this vvar is used once if we exclude its uses at ret sites or jump sites. we can
|
|
279
|
+
# propagate it
|
|
280
|
+
for vvar_used, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
281
|
+
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
282
|
+
continue
|
|
283
|
+
|
|
284
|
+
if len(set(non_exitsite_uselocs)) == 1 and not has_ite_expr(stmt.src):
|
|
285
|
+
useloc = non_exitsite_uselocs[0]
|
|
286
|
+
assert useloc.block_addr is not None
|
|
287
|
+
assert useloc.stmt_idx is not None
|
|
288
|
+
useloc_stmt = blocks[(useloc.block_addr, useloc.block_idx)].statements[useloc.stmt_idx]
|
|
289
|
+
if stmt.src.depth <= 3 and not has_ite_stmt(useloc_stmt):
|
|
290
|
+
# remove duplicate use locs (e.g., if the variable is used multiple times by the
|
|
291
|
+
# same statement) - but ensure stmt is simple enough
|
|
292
|
+
for vvar_used, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
293
|
+
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
294
|
+
continue
|
|
221
295
|
|
|
222
296
|
# special logic for global variables: if it's used once or multiple times, and the variable is never
|
|
223
297
|
# updated before it's used, we will propagate the load
|
|
224
|
-
if isinstance(stmt, Assignment):
|
|
298
|
+
if (vvar.was_reg or vvar.was_parameter) and isinstance(stmt, Assignment):
|
|
225
299
|
stmt_src = stmt.src
|
|
226
300
|
# unpack conversions
|
|
227
301
|
while isinstance(stmt_src, Convert):
|
|
228
302
|
stmt_src = stmt_src.operand
|
|
229
|
-
if
|
|
303
|
+
if (
|
|
304
|
+
isinstance(stmt_src, Load)
|
|
305
|
+
and isinstance(stmt_src.addr, Const)
|
|
306
|
+
and isinstance(stmt_src.addr.value, int)
|
|
307
|
+
):
|
|
230
308
|
gv_updated = False
|
|
231
309
|
for _vvar_used, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
232
310
|
gv_updated |= self.is_global_variable_updated(
|
|
@@ -286,6 +364,8 @@ class SPropagatorAnalysis(Analysis):
|
|
|
286
364
|
for block_loc, tmp_and_uses in tmp_uselocs.items():
|
|
287
365
|
for tmp_atom, tmp_uses in tmp_and_uses.items():
|
|
288
366
|
# take a look at the definition and propagate the definition if supported
|
|
367
|
+
assert block_loc.block_addr is not None
|
|
368
|
+
|
|
289
369
|
block = blocks[(block_loc.block_addr, block_loc.block_idx)]
|
|
290
370
|
tmp_def_stmtidx = tmp_deflocs[block_loc][tmp_atom]
|
|
291
371
|
|
|
@@ -350,6 +430,8 @@ class SPropagatorAnalysis(Analysis):
|
|
|
350
430
|
|
|
351
431
|
start_stmt_idx = defloc.stmt_idx if block is defblock else 0 # inclusive
|
|
352
432
|
end_stmt_idx = useloc.stmt_idx if block is useblock else len(block.statements) # exclusive
|
|
433
|
+
assert start_stmt_idx is not None
|
|
434
|
+
assert end_stmt_idx is not None
|
|
353
435
|
|
|
354
436
|
for idx in range(start_stmt_idx, end_stmt_idx):
|
|
355
437
|
stmt = block.statements[idx]
|
|
@@ -380,5 +462,78 @@ class SPropagatorAnalysis(Analysis):
|
|
|
380
462
|
|
|
381
463
|
return False
|
|
382
464
|
|
|
465
|
+
def has_store_stmt_in_between(
|
|
466
|
+
self, blocks: dict[tuple[int, int | None], Block], defloc: CodeLocation, useloc: CodeLocation
|
|
467
|
+
) -> bool:
|
|
468
|
+
assert defloc.block_addr is not None
|
|
469
|
+
assert defloc.stmt_idx is not None
|
|
470
|
+
assert useloc.block_addr is not None
|
|
471
|
+
assert useloc.stmt_idx is not None
|
|
472
|
+
assert self.func_graph is not None
|
|
473
|
+
|
|
474
|
+
use_block = blocks[(useloc.block_addr, useloc.block_idx)]
|
|
475
|
+
def_block = blocks[(defloc.block_addr, defloc.block_idx)]
|
|
476
|
+
|
|
477
|
+
# traverse the graph, go from use_block until we reach def_block, and look for Store statements
|
|
478
|
+
seen = {use_block}
|
|
479
|
+
queue = [use_block]
|
|
480
|
+
while queue:
|
|
481
|
+
block = queue.pop(0)
|
|
482
|
+
|
|
483
|
+
starting_stmt_idx, ending_stmt_idx = 0, len(block.statements)
|
|
484
|
+
if block is def_block:
|
|
485
|
+
starting_stmt_idx = defloc.stmt_idx + 1
|
|
486
|
+
if block is use_block:
|
|
487
|
+
ending_stmt_idx = useloc.stmt_idx
|
|
488
|
+
|
|
489
|
+
for i in range(starting_stmt_idx, ending_stmt_idx):
|
|
490
|
+
if isinstance(block.statements[i], Store):
|
|
491
|
+
return True
|
|
492
|
+
|
|
493
|
+
if block is def_block:
|
|
494
|
+
continue
|
|
495
|
+
|
|
496
|
+
for pred in self.func_graph.predecessors(block):
|
|
497
|
+
if pred not in seen:
|
|
498
|
+
seen.add(pred)
|
|
499
|
+
queue.append(pred)
|
|
500
|
+
|
|
501
|
+
return False
|
|
502
|
+
|
|
503
|
+
@staticmethod
|
|
504
|
+
def is_vvar_used_for_addr_loading_switch_case(uselocs: set[CodeLocation], blocks) -> bool:
|
|
505
|
+
"""
|
|
506
|
+
Check if a virtual variable is used for loading an address in a switch-case construct.
|
|
507
|
+
|
|
508
|
+
:param uselocs: The use locations of the virtual variable.
|
|
509
|
+
:param blocks: All blocks of the current function.
|
|
510
|
+
:return: True if the virtual variable is used for loading an address in a switch-case construct, False
|
|
511
|
+
otherwise.
|
|
512
|
+
"""
|
|
513
|
+
|
|
514
|
+
if len(uselocs) != 2:
|
|
515
|
+
return False
|
|
516
|
+
|
|
517
|
+
useloc_0, useloc_1 = list(uselocs)
|
|
518
|
+
block_0 = blocks[(useloc_0.block_addr, useloc_0.block_idx)]
|
|
519
|
+
stmt_0 = block_0.statements[useloc_0.stmt_idx]
|
|
520
|
+
block_1 = blocks[(useloc_1.block_addr, useloc_1.block_idx)]
|
|
521
|
+
stmt_1 = block_1.statements[useloc_1.stmt_idx]
|
|
522
|
+
|
|
523
|
+
if isinstance(stmt_0, Jump):
|
|
524
|
+
stmt_0, stmt_1 = stmt_1, stmt_0
|
|
525
|
+
block_0, block_1 = block_1, block_0
|
|
526
|
+
if not isinstance(stmt_0, ConditionalJump) or not isinstance(stmt_1, Jump):
|
|
527
|
+
return False
|
|
528
|
+
|
|
529
|
+
# check if stmt_0 jumps to block_1
|
|
530
|
+
if not isinstance(stmt_0.true_target, Const) or not isinstance(stmt_0.false_target, Const):
|
|
531
|
+
return False
|
|
532
|
+
stmt_0_targets = {
|
|
533
|
+
(stmt_0.true_target.value, stmt_0.true_target_idx),
|
|
534
|
+
(stmt_0.false_target.value, stmt_0.false_target_idx),
|
|
535
|
+
}
|
|
536
|
+
return (block_1.addr, block_1.idx) in stmt_0_targets
|
|
537
|
+
|
|
383
538
|
|
|
384
539
|
register_analysis(SPropagatorAnalysis, "SPropagator")
|
|
@@ -79,8 +79,8 @@ class StackVVarPredicate:
|
|
|
79
79
|
isinstance(stmt, Assignment)
|
|
80
80
|
and isinstance(stmt.dst, VirtualVariable)
|
|
81
81
|
and stmt.dst.was_stack
|
|
82
|
-
and stmt.dst.stack_offset
|
|
83
|
-
and stmt.dst.
|
|
82
|
+
and stmt.dst.stack_offset <= self.stack_offset < stmt.dst.stack_offset + stmt.dst.size
|
|
83
|
+
and stmt.dst.stack_offset <= self.stack_offset + self.size <= stmt.dst.stack_offset + stmt.dst.size
|
|
84
84
|
):
|
|
85
85
|
self.vvars.add(stmt.dst)
|
|
86
86
|
return True
|
|
@@ -143,7 +143,9 @@ class SReachingDefinitionsAnalysis(Analysis):
|
|
|
143
143
|
cc = cc_cls(self.project.arch)
|
|
144
144
|
|
|
145
145
|
codeloc = CodeLocation(block_addr, stmt_idx, block_idx=block_idx, ins_addr=stmt.ins_addr)
|
|
146
|
-
arg_locs = cc.ARG_REGS
|
|
146
|
+
arg_locs = list(cc.ARG_REGS)
|
|
147
|
+
if cc.FP_ARG_REGS:
|
|
148
|
+
arg_locs += [r_name for r_name in cc.FP_ARG_REGS if r_name not in arg_locs]
|
|
147
149
|
|
|
148
150
|
for arg_reg_name in arg_locs:
|
|
149
151
|
reg_offset = self.project.arch.registers[arg_reg_name][0]
|
|
@@ -84,7 +84,7 @@ class SimEngineVRAIL(
|
|
|
84
84
|
if vvar is not None:
|
|
85
85
|
r = self._read_from_vvar(vvar, expr=stmt.src, vvar_id=self._mapped_vvarid(vvar.varid))
|
|
86
86
|
if r.variable is not None:
|
|
87
|
-
pv = self.variable_manager[self.func_addr]._phi_variables
|
|
87
|
+
pv = self.state.variable_manager[self.func_addr]._phi_variables
|
|
88
88
|
if variable not in pv:
|
|
89
89
|
pv[variable] = set()
|
|
90
90
|
pv[variable].add(r.variable)
|