angr 9.2.122__py3-none-macosx_10_9_x86_64.whl → 9.2.124__py3-none-macosx_10_9_x86_64.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.py +6 -1
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +11 -8
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +2 -2
- angr/analyses/decompiler/ail_simplifier.py +38 -342
- angr/analyses/decompiler/callsite_maker.py +8 -7
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +24 -2
- angr/analyses/decompiler/clinic.py +30 -3
- angr/analyses/decompiler/condition_processor.py +10 -3
- angr/analyses/decompiler/decompilation_cache.py +2 -0
- angr/analyses/decompiler/decompiler.py +50 -8
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +10 -2
- angr/analyses/decompiler/dephication/rewriting_engine.py +65 -2
- angr/analyses/decompiler/expression_narrower.py +206 -6
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +4 -1
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +7 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +34 -11
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +10 -1
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +3 -1
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +8 -5
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +10 -5
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +18 -7
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +6 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +2 -0
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +75 -42
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +8 -2
- angr/analyses/decompiler/region_identifier.py +36 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +4 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +2 -8
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +9 -3
- angr/analyses/decompiler/sequence_walker.py +20 -4
- angr/analyses/decompiler/ssailification/rewriting.py +5 -2
- angr/analyses/decompiler/ssailification/rewriting_engine.py +151 -25
- angr/analyses/decompiler/ssailification/rewriting_state.py +1 -0
- angr/analyses/decompiler/ssailification/ssailification.py +17 -9
- angr/analyses/decompiler/ssailification/traversal.py +3 -1
- angr/analyses/decompiler/ssailification/traversal_engine.py +35 -8
- angr/analyses/decompiler/ssailification/traversal_state.py +1 -0
- angr/analyses/decompiler/structured_codegen/c.py +42 -4
- angr/analyses/decompiler/structuring/phoenix.py +3 -0
- angr/analyses/propagator/engine_ail.py +10 -3
- angr/analyses/reaching_definitions/engine_ail.py +10 -15
- angr/analyses/s_propagator.py +26 -15
- angr/analyses/s_reaching_definitions/s_rda_view.py +127 -63
- angr/analyses/variable_recovery/engine_ail.py +14 -0
- angr/analyses/variable_recovery/engine_base.py +11 -0
- angr/calling_conventions.py +2 -2
- angr/engines/light/engine.py +24 -2
- angr/engines/soot/expressions/instanceOf.py +4 -1
- angr/engines/successors.py +1 -1
- angr/engines/vex/heavy/concretizers.py +47 -47
- angr/engines/vex/heavy/dirty.py +4 -4
- angr/knowledge_plugins/__init__.py +2 -0
- angr/knowledge_plugins/decompilation.py +45 -0
- angr/knowledge_plugins/key_definitions/atoms.py +8 -0
- angr/lib/angr_native.dylib +0 -0
- angr/procedures/definitions/parse_win32json.py +2 -1
- angr/procedures/java_lang/getsimplename.py +4 -1
- angr/procedures/linux_kernel/iovec.py +5 -2
- angr/sim_type.py +3 -1
- angr/storage/memory_mixins/actions_mixin.py +7 -7
- angr/storage/memory_mixins/address_concretization_mixin.py +5 -5
- angr/storage/memory_mixins/bvv_conversion_mixin.py +1 -1
- angr/storage/memory_mixins/clouseau_mixin.py +3 -3
- angr/storage/memory_mixins/conditional_store_mixin.py +3 -3
- angr/storage/memory_mixins/default_filler_mixin.py +3 -3
- angr/storage/memory_mixins/memory_mixin.py +45 -34
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +15 -14
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +27 -16
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +18 -9
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +5 -5
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +89 -55
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +16 -25
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +11 -9
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +23 -7
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +1 -1
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +9 -7
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +9 -9
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +1 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +2 -2
- angr/storage/memory_mixins/simplification_mixin.py +2 -2
- angr/storage/memory_mixins/size_resolution_mixin.py +1 -1
- angr/storage/memory_mixins/slotted_memory.py +3 -3
- angr/storage/memory_mixins/smart_find_mixin.py +1 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +5 -5
- angr/storage/memory_mixins/unwrapper_mixin.py +4 -4
- angr/storage/memory_object.py +4 -3
- angr/utils/constants.py +1 -1
- angr/utils/graph.py +15 -0
- angr/vaults.py +2 -2
- {angr-9.2.122.dist-info → angr-9.2.124.dist-info}/METADATA +7 -6
- {angr-9.2.122.dist-info → angr-9.2.124.dist-info}/RECORD +96 -95
- {angr-9.2.122.dist-info → angr-9.2.124.dist-info}/WHEEL +1 -1
- {angr-9.2.122.dist-info → angr-9.2.124.dist-info}/LICENSE +0 -0
- {angr-9.2.122.dist-info → angr-9.2.124.dist-info}/entry_points.txt +0 -0
- {angr-9.2.122.dist-info → angr-9.2.124.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
|
@@ -356,9 +356,12 @@ class CallingConventionAnalysis(Analysis):
|
|
|
356
356
|
caller_block_addr: int,
|
|
357
357
|
call_insn_addr: int,
|
|
358
358
|
include_preds: bool = False,
|
|
359
|
-
) -> CallSiteFact:
|
|
359
|
+
) -> CallSiteFact | None:
|
|
360
360
|
func = self.kb.functions[caller_addr]
|
|
361
361
|
subgraph = self._generate_callsite_subgraph(func, caller_block_addr, include_preds=include_preds)
|
|
362
|
+
if subgraph is None:
|
|
363
|
+
# failed to generate a subgraph when the caller block cannot be found in the function graph
|
|
364
|
+
return None
|
|
362
365
|
|
|
363
366
|
observation_points: list = [("insn", call_insn_addr, OP_BEFORE), ("node", caller_block_addr, OP_AFTER)]
|
|
364
367
|
|
|
@@ -440,6 +443,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
440
443
|
call_insn_addr,
|
|
441
444
|
include_preds=include_callsite_preds,
|
|
442
445
|
)
|
|
446
|
+
if fact is None:
|
|
447
|
+
continue
|
|
443
448
|
facts.append(fact)
|
|
444
449
|
|
|
445
450
|
ctr += 1
|
|
@@ -153,6 +153,11 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
153
153
|
|
|
154
154
|
def _resolve_case_1(self, addr: int, block: pyvex.IRSB, func_addr: int, gp_value: int, cfg) -> int | None:
|
|
155
155
|
# lift the block again with the correct setting
|
|
156
|
+
|
|
157
|
+
inital_regs = [(self.project.arch.registers["t9"][0], self.project.arch.registers["t9"][1], func_addr)]
|
|
158
|
+
if gp_value is not None:
|
|
159
|
+
inital_regs.append((self.project.arch.registers["gp"][0], self.project.arch.registers["gp"][1], gp_value))
|
|
160
|
+
|
|
156
161
|
first_irsb = self.project.factory.block(
|
|
157
162
|
addr,
|
|
158
163
|
size=block.size,
|
|
@@ -160,10 +165,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
160
165
|
const_prop=True,
|
|
161
166
|
cross_insn_opt=False,
|
|
162
167
|
load_from_ro_regions=True,
|
|
163
|
-
initial_regs=
|
|
164
|
-
(self.project.arch.registers["t9"][0], self.project.arch.registers["t9"][1], func_addr),
|
|
165
|
-
(self.project.arch.registers["gp"][0], self.project.arch.registers["gp"][1], gp_value),
|
|
166
|
-
],
|
|
168
|
+
initial_regs=inital_regs,
|
|
167
169
|
).vex_nostmt
|
|
168
170
|
|
|
169
171
|
if not isinstance(first_irsb.next, pyvex.IRExpr.RdTmp):
|
|
@@ -193,6 +195,10 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
193
195
|
# the register (t9) is set in this block - we can resolve the jump target using only the current block
|
|
194
196
|
return Case2Result.RESUME, None
|
|
195
197
|
|
|
198
|
+
inital_regs = [(self.project.arch.registers["t9"][0], self.project.arch.registers["t9"][1], func_addr)]
|
|
199
|
+
if gp_value is not None:
|
|
200
|
+
inital_regs.append((self.project.arch.registers["gp"][0], self.project.arch.registers["gp"][1], gp_value))
|
|
201
|
+
|
|
196
202
|
# lift the first block again with the correct setting
|
|
197
203
|
first_irsb = self.project.factory.block(
|
|
198
204
|
first_block_addr,
|
|
@@ -200,10 +206,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
|
|
|
200
206
|
collect_data_refs=False,
|
|
201
207
|
const_prop=True,
|
|
202
208
|
load_from_ro_regions=True,
|
|
203
|
-
initial_regs=
|
|
204
|
-
(self.project.arch.registers["t9"][0], self.project.arch.registers["t9"][1], func_addr),
|
|
205
|
-
(self.project.arch.registers["gp"][0], self.project.arch.registers["gp"][1], gp_value),
|
|
206
|
-
],
|
|
209
|
+
initial_regs=inital_regs,
|
|
207
210
|
).vex_nostmt
|
|
208
211
|
|
|
209
212
|
last_reg_setting_tmp = self._get_last_reg_setting_tmp(first_irsb, jump_target_reg)
|
|
@@ -51,11 +51,11 @@ class MipsElfGotResolver(IndirectJumpResolver):
|
|
|
51
51
|
return False, []
|
|
52
52
|
dynsym_addr = self._find_and_cache_section_addr(obj, ".dynsym")
|
|
53
53
|
if dynsym_addr is None:
|
|
54
|
-
return
|
|
54
|
+
return False, []
|
|
55
55
|
|
|
56
56
|
dynstr_addr = self._find_and_cache_section_addr(obj, ".dynstr")
|
|
57
57
|
if dynstr_addr is None:
|
|
58
|
-
return
|
|
58
|
+
return False, []
|
|
59
59
|
|
|
60
60
|
if block.size != 16:
|
|
61
61
|
return False, []
|
|
@@ -22,7 +22,6 @@ from ailment.expression import (
|
|
|
22
22
|
Const,
|
|
23
23
|
BinaryOp,
|
|
24
24
|
VirtualVariable,
|
|
25
|
-
Phi,
|
|
26
25
|
)
|
|
27
26
|
|
|
28
27
|
from angr.analyses.s_reaching_definitions import SRDAModel
|
|
@@ -36,7 +35,7 @@ from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE
|
|
|
36
35
|
from angr.errors import AngrRuntimeError
|
|
37
36
|
from angr.analyses import Analysis, AnalysesHub
|
|
38
37
|
from .ailgraph_walker import AILGraphWalker
|
|
39
|
-
from .expression_narrower import
|
|
38
|
+
from .expression_narrower import ExprNarrowingInfo, NarrowingInfoExtractor, ExpressionNarrower
|
|
40
39
|
from .block_simplifier import BlockSimplifier
|
|
41
40
|
from .ccall_rewriters import CCALL_REWRITERS
|
|
42
41
|
from .counters.expression_counters import SingleExpressionCounter
|
|
@@ -76,26 +75,6 @@ class AILBlockTempCollector(AILBlockWalker):
|
|
|
76
75
|
self.temps.add(expr)
|
|
77
76
|
|
|
78
77
|
|
|
79
|
-
class ExprNarrowingInfo:
|
|
80
|
-
"""
|
|
81
|
-
Stores the analysis result of _narrowing_needed().
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
__slots__ = ("narrowable", "to_size", "use_exprs", "phi_vars")
|
|
85
|
-
|
|
86
|
-
def __init__(
|
|
87
|
-
self,
|
|
88
|
-
narrowable: bool,
|
|
89
|
-
to_size: int | None = None,
|
|
90
|
-
use_exprs: list[tuple[atoms.VirtualVariable, CodeLocation, tuple[str, tuple[Expression, ...]]]] | None = None,
|
|
91
|
-
phi_vars: set[atoms.VirtualVariable] | None = None,
|
|
92
|
-
):
|
|
93
|
-
self.narrowable = narrowable
|
|
94
|
-
self.to_size = to_size
|
|
95
|
-
self.use_exprs = use_exprs
|
|
96
|
-
self.phi_vars = phi_vars
|
|
97
|
-
|
|
98
|
-
|
|
99
78
|
class AILSimplifier(Analysis):
|
|
100
79
|
"""
|
|
101
80
|
Perform function-level simplifications.
|
|
@@ -343,309 +322,26 @@ class AILSimplifier(Analysis):
|
|
|
343
322
|
if not repeat:
|
|
344
323
|
break
|
|
345
324
|
|
|
346
|
-
replaced_vvar_ids = set()
|
|
347
|
-
|
|
348
325
|
# let's narrow them (finally)
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if use_type == "binop-convert" and self._exprs_contain_vvar(use_expr_tpl, replaced_vvar_ids):
|
|
356
|
-
should_skip = True
|
|
357
|
-
break
|
|
358
|
-
if should_skip:
|
|
359
|
-
continue
|
|
360
|
-
|
|
361
|
-
# replace the definition
|
|
362
|
-
if not isinstance(def_.codeloc, ExternalCodeLocation):
|
|
363
|
-
old_block = addr_and_idx_to_block.get((def_.codeloc.block_addr, def_.codeloc.block_idx))
|
|
364
|
-
if old_block is None:
|
|
365
|
-
# this definition might be inside a callee function, which is why the block does not exist
|
|
366
|
-
# ignore it
|
|
367
|
-
continue
|
|
368
|
-
|
|
369
|
-
the_block = self.blocks.get(old_block, old_block)
|
|
370
|
-
stmt = the_block.statements[def_.codeloc.stmt_idx]
|
|
371
|
-
r, new_block = False, None
|
|
372
|
-
replaced_vvar: VirtualVariable | None = None
|
|
373
|
-
if is_phi_assignment(stmt):
|
|
374
|
-
new_assignment_dst = VirtualVariable(
|
|
375
|
-
stmt.dst.idx,
|
|
376
|
-
stmt.dst.varid,
|
|
377
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
378
|
-
category=def_.atom.category,
|
|
379
|
-
oident=def_.atom.oident,
|
|
380
|
-
**stmt.dst.tags,
|
|
381
|
-
)
|
|
382
|
-
new_src_and_vvars = []
|
|
383
|
-
for src, vvar in stmt.src.src_and_vvars:
|
|
384
|
-
if vvar is not None and vvar.varid == stmt.dst.varid:
|
|
385
|
-
new_vvar = VirtualVariable(
|
|
386
|
-
vvar.idx,
|
|
387
|
-
vvar.varid,
|
|
388
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
389
|
-
category=vvar.category,
|
|
390
|
-
oident=vvar.oident,
|
|
391
|
-
**vvar.tags,
|
|
392
|
-
)
|
|
393
|
-
else:
|
|
394
|
-
new_vvar = vvar
|
|
395
|
-
new_src_and_vvars.append((src, new_vvar))
|
|
396
|
-
new_assignment_src = Phi(
|
|
397
|
-
stmt.src.idx,
|
|
398
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
399
|
-
new_src_and_vvars,
|
|
400
|
-
**stmt.src.tags,
|
|
401
|
-
)
|
|
402
|
-
replaced_vvar = stmt.dst
|
|
403
|
-
r, new_block = BlockSimplifier._replace_and_build(
|
|
404
|
-
the_block,
|
|
405
|
-
{
|
|
406
|
-
def_.codeloc: {
|
|
407
|
-
stmt.dst: new_assignment_dst,
|
|
408
|
-
stmt.src: new_assignment_src,
|
|
409
|
-
}
|
|
410
|
-
},
|
|
411
|
-
replace_assignment_dsts=True,
|
|
412
|
-
replace_loads=True,
|
|
413
|
-
)
|
|
414
|
-
elif isinstance(stmt, Assignment) and isinstance(stmt.dst, VirtualVariable) and stmt.dst.was_reg:
|
|
415
|
-
new_assignment_dst = VirtualVariable(
|
|
416
|
-
stmt.dst.idx,
|
|
417
|
-
stmt.dst.varid,
|
|
418
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
419
|
-
category=def_.atom.category,
|
|
420
|
-
oident=def_.atom.oident,
|
|
421
|
-
**stmt.dst.tags,
|
|
422
|
-
)
|
|
423
|
-
new_assignment_src = Convert(
|
|
424
|
-
stmt.src.idx, # FIXME: This is a hack
|
|
425
|
-
stmt.src.bits,
|
|
426
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
427
|
-
False,
|
|
428
|
-
stmt.src,
|
|
429
|
-
**stmt.src.tags,
|
|
430
|
-
)
|
|
431
|
-
replaced_vvar = stmt.dst
|
|
432
|
-
r, new_block = BlockSimplifier._replace_and_build(
|
|
433
|
-
the_block,
|
|
434
|
-
{
|
|
435
|
-
def_.codeloc: {
|
|
436
|
-
stmt.dst: new_assignment_dst,
|
|
437
|
-
stmt.src: new_assignment_src,
|
|
438
|
-
}
|
|
439
|
-
},
|
|
440
|
-
replace_assignment_dsts=True,
|
|
441
|
-
replace_loads=True,
|
|
442
|
-
)
|
|
443
|
-
elif isinstance(stmt, Call):
|
|
444
|
-
if stmt.ret_expr is not None:
|
|
445
|
-
tags = dict(stmt.ret_expr.tags)
|
|
446
|
-
tags["reg_name"] = self.project.arch.translate_register_name(
|
|
447
|
-
def_.atom.reg_offset, size=narrow_info.to_size
|
|
448
|
-
)
|
|
449
|
-
replaced_vvar = stmt.ret_expr
|
|
450
|
-
new_retexpr = VirtualVariable(
|
|
451
|
-
stmt.ret_expr.idx,
|
|
452
|
-
stmt.ret_expr.varid,
|
|
453
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
454
|
-
category=def_.atom.category,
|
|
455
|
-
oident=def_.atom.oident,
|
|
456
|
-
**stmt.ret_expr.tags,
|
|
457
|
-
)
|
|
458
|
-
r, new_block = BlockSimplifier._replace_and_build(
|
|
459
|
-
the_block, {def_.codeloc: {stmt.ret_expr: new_retexpr}}
|
|
460
|
-
)
|
|
461
|
-
if not r:
|
|
462
|
-
# couldn't replace the definition...
|
|
463
|
-
continue
|
|
326
|
+
narrower = ExpressionNarrower(self.project, rd, narrowables, addr_and_idx_to_block, self.blocks)
|
|
327
|
+
for old_block in addr_and_idx_to_block.values():
|
|
328
|
+
new_block = self.blocks.get(old_block, old_block)
|
|
329
|
+
new_block = narrower.walk(new_block)
|
|
330
|
+
if narrower.narrowed_any:
|
|
331
|
+
narrowed = True
|
|
464
332
|
self.blocks[old_block] = new_block
|
|
465
|
-
if replaced_vvar is not None:
|
|
466
|
-
replaced_vvar_ids.add(replaced_vvar.varid)
|
|
467
|
-
|
|
468
|
-
use_exprs = list(narrow_info.use_exprs)
|
|
469
|
-
if narrow_info.phi_vars:
|
|
470
|
-
for phi_var in narrow_info.phi_vars:
|
|
471
|
-
loc = rd.all_vvar_definitions[phi_var]
|
|
472
|
-
old_block = addr_and_idx_to_block.get((loc.block_addr, loc.block_idx))
|
|
473
|
-
the_block = self.blocks.get(old_block, old_block)
|
|
474
|
-
stmt = the_block.statements[loc.stmt_idx]
|
|
475
|
-
assert is_phi_assignment(stmt)
|
|
476
|
-
|
|
477
|
-
for _, vvar in stmt.src.src_and_vvars:
|
|
478
|
-
if vvar is not None and vvar.varid == def_.atom.varid:
|
|
479
|
-
use_exprs.append((vvar, loc, ("phi-src-expr", (vvar,))))
|
|
480
|
-
|
|
481
|
-
# replace all uses if necessary
|
|
482
|
-
for use_atom, use_loc, (use_type, use_expr_tpl) in use_exprs:
|
|
483
|
-
if (
|
|
484
|
-
isinstance(use_expr_tpl[0], VirtualVariable)
|
|
485
|
-
and use_expr_tpl[0].was_reg
|
|
486
|
-
and narrow_info.to_size == use_expr_tpl[0].size
|
|
487
|
-
):
|
|
488
|
-
# don't replace registers to the same registers
|
|
489
|
-
continue
|
|
490
|
-
if use_atom.varid != def_.atom.varid:
|
|
491
|
-
# don't replace this use - it will be replaced later
|
|
492
|
-
continue
|
|
493
|
-
|
|
494
|
-
old_block = addr_and_idx_to_block.get((use_loc.block_addr, use_loc.block_idx))
|
|
495
|
-
the_block = self.blocks.get(old_block, old_block)
|
|
496
|
-
|
|
497
|
-
if use_type in {"expr", "mask", "convert"}:
|
|
498
|
-
# the first used expr
|
|
499
|
-
use_expr_0 = use_expr_tpl[0]
|
|
500
|
-
new_use_expr_0 = VirtualVariable(
|
|
501
|
-
use_expr_0.idx,
|
|
502
|
-
def_.atom.varid,
|
|
503
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
504
|
-
category=def_.atom.category,
|
|
505
|
-
oident=def_.atom.oident,
|
|
506
|
-
**use_expr_0.tags,
|
|
507
|
-
)
|
|
508
|
-
new_use_expr = new_use_expr_0
|
|
509
|
-
|
|
510
|
-
# the second used expr (if it exists)
|
|
511
|
-
if len(use_expr_tpl) == 2:
|
|
512
|
-
use_expr_1 = use_expr_tpl[1]
|
|
513
|
-
assert isinstance(use_expr_1, BinaryOp)
|
|
514
|
-
con = use_expr_1.operands[1]
|
|
515
|
-
assert isinstance(con, Const)
|
|
516
|
-
new_use_expr_1 = BinaryOp(
|
|
517
|
-
use_expr_1.idx,
|
|
518
|
-
use_expr_1.op,
|
|
519
|
-
[
|
|
520
|
-
new_use_expr_0,
|
|
521
|
-
Const(con.idx, con.variable, con.value, new_use_expr_0.bits, **con.tags),
|
|
522
|
-
],
|
|
523
|
-
use_expr_1.signed,
|
|
524
|
-
floating_point=use_expr_1.floating_point,
|
|
525
|
-
rounding_mode=use_expr_1.rounding_mode,
|
|
526
|
-
**use_expr_1.tags,
|
|
527
|
-
)
|
|
528
|
-
|
|
529
|
-
if use_expr_1.size > new_use_expr_1.size:
|
|
530
|
-
new_use_expr_1 = Convert(
|
|
531
|
-
None,
|
|
532
|
-
new_use_expr_1.bits,
|
|
533
|
-
use_expr_1.bits,
|
|
534
|
-
False,
|
|
535
|
-
new_use_expr_1,
|
|
536
|
-
**new_use_expr_1.tags,
|
|
537
|
-
)
|
|
538
|
-
|
|
539
|
-
r, new_block = BlockSimplifier._replace_and_build(
|
|
540
|
-
the_block, {use_loc: {use_expr_1: new_use_expr_1}}
|
|
541
|
-
)
|
|
542
|
-
elif len(use_expr_tpl) == 1:
|
|
543
|
-
if use_expr_0.size > new_use_expr_0.size:
|
|
544
|
-
new_use_expr_0 = Convert(
|
|
545
|
-
None,
|
|
546
|
-
new_use_expr_0.bits,
|
|
547
|
-
use_expr_0.bits,
|
|
548
|
-
False,
|
|
549
|
-
new_use_expr_0,
|
|
550
|
-
**new_use_expr_0.tags,
|
|
551
|
-
)
|
|
552
333
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
new_use_expr = VirtualVariable(
|
|
565
|
-
use_expr.idx,
|
|
566
|
-
def_.atom.varid,
|
|
567
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
568
|
-
category=def_.atom.category,
|
|
569
|
-
oident=def_.atom.oident,
|
|
570
|
-
**use_expr.tags,
|
|
571
|
-
)
|
|
572
|
-
r, new_block = BlockSimplifier._replace_and_build(the_block, {use_loc: {use_expr: new_use_expr}})
|
|
573
|
-
|
|
574
|
-
elif use_type == "binop-convert":
|
|
575
|
-
use_expr_0 = use_expr_tpl[0]
|
|
576
|
-
new_use_expr_0 = VirtualVariable(
|
|
577
|
-
use_expr_0.idx,
|
|
578
|
-
def_.atom.varid,
|
|
579
|
-
narrow_info.to_size * self.project.arch.byte_width,
|
|
580
|
-
category=def_.atom.category,
|
|
581
|
-
oident=def_.atom.oident,
|
|
582
|
-
**use_expr_0.tags,
|
|
583
|
-
)
|
|
584
|
-
new_use_expr = new_use_expr_0
|
|
585
|
-
|
|
586
|
-
use_expr_1: BinaryOp = use_expr_tpl[1]
|
|
587
|
-
# build the new use_expr_1
|
|
588
|
-
new_use_expr_1_operands = {}
|
|
589
|
-
if use_expr_1.operands[0] is use_expr_0:
|
|
590
|
-
new_use_expr_1_operands[0] = new_use_expr_0
|
|
591
|
-
other_operand = use_expr_1.operands[1]
|
|
592
|
-
else:
|
|
593
|
-
new_use_expr_1_operands[1] = new_use_expr_0
|
|
594
|
-
other_operand = use_expr_1.operands[0]
|
|
595
|
-
use_expr_2: Convert = use_expr_tpl[2]
|
|
596
|
-
if other_operand.bits == use_expr_2.from_bits:
|
|
597
|
-
new_other_operand = Convert(
|
|
598
|
-
None, use_expr_2.from_bits, use_expr_2.to_bits, False, other_operand
|
|
599
|
-
)
|
|
600
|
-
else:
|
|
601
|
-
# Some operations, like Sar and Shl, have operands with different sizes
|
|
602
|
-
new_other_operand = other_operand
|
|
603
|
-
|
|
604
|
-
if 0 in new_use_expr_1_operands:
|
|
605
|
-
new_use_expr_1_operands[1] = new_other_operand
|
|
606
|
-
else:
|
|
607
|
-
new_use_expr_1_operands[0] = new_other_operand
|
|
608
|
-
|
|
609
|
-
# build new use_expr_1
|
|
610
|
-
new_use_expr_1 = BinaryOp(
|
|
611
|
-
use_expr_1.idx,
|
|
612
|
-
use_expr_1.op,
|
|
613
|
-
[new_use_expr_1_operands[0], new_use_expr_1_operands[1]],
|
|
614
|
-
use_expr_1.signed,
|
|
615
|
-
bits=narrow_info.to_size * 8,
|
|
616
|
-
floating_point=use_expr_1.floating_point,
|
|
617
|
-
rounding_mode=use_expr_1.rounding_mode,
|
|
618
|
-
**use_expr_1.tags,
|
|
619
|
-
)
|
|
620
|
-
|
|
621
|
-
# first remove the old conversion
|
|
622
|
-
r, new_block = BlockSimplifier._replace_and_build(
|
|
623
|
-
the_block, {use_loc: {use_expr_2: use_expr_2.operand}}
|
|
624
|
-
)
|
|
625
|
-
# then replace use_expr_1
|
|
626
|
-
if r:
|
|
627
|
-
r, new_block = BlockSimplifier._replace_and_build(
|
|
628
|
-
new_block, {use_loc: {use_expr_1: new_use_expr_1}}
|
|
629
|
-
)
|
|
630
|
-
else:
|
|
631
|
-
raise TypeError(f'Unsupported use_type value "{use_type}"')
|
|
632
|
-
|
|
633
|
-
if not r:
|
|
634
|
-
_l.warning("Failed to replace use-expr at %s.", use_loc)
|
|
635
|
-
else:
|
|
636
|
-
# update self._arg_vvars if necessary
|
|
637
|
-
if new_use_expr is not None and new_use_expr.was_parameter and self._arg_vvars:
|
|
638
|
-
for func_arg_idx in list(self._arg_vvars):
|
|
639
|
-
vvar, simvar = self._arg_vvars[func_arg_idx]
|
|
640
|
-
if vvar.varid == new_use_expr.varid:
|
|
641
|
-
simvar_new = simvar.copy()
|
|
642
|
-
simvar_new._hash = None
|
|
643
|
-
simvar_new.size = new_use_expr.size
|
|
644
|
-
self._arg_vvars[func_arg_idx] = new_use_expr, simvar_new
|
|
645
|
-
|
|
646
|
-
self.blocks[old_block] = new_block
|
|
647
|
-
|
|
648
|
-
narrowed = True
|
|
334
|
+
# update self._arg_vvars if necessary
|
|
335
|
+
for new_vvars in narrower.replacement_core_vvars.values():
|
|
336
|
+
for new_vvar in new_vvars:
|
|
337
|
+
if new_vvar.was_parameter and self._arg_vvars:
|
|
338
|
+
for func_arg_idx in list(self._arg_vvars):
|
|
339
|
+
vvar, simvar = self._arg_vvars[func_arg_idx]
|
|
340
|
+
if vvar.varid == new_vvar.varid:
|
|
341
|
+
simvar_new = simvar.copy()
|
|
342
|
+
simvar_new._hash = None
|
|
343
|
+
simvar_new.size = new_vvar.size
|
|
344
|
+
self._arg_vvars[func_arg_idx] = new_vvar, simvar_new
|
|
649
345
|
|
|
650
346
|
return narrowed
|
|
651
347
|
|
|
@@ -669,6 +365,9 @@ class AILSimplifier(Analysis):
|
|
|
669
365
|
if len(narrowing_sizes) == 1 and None not in narrowing_sizes:
|
|
670
366
|
# we can narrow this phi vvar!
|
|
671
367
|
narrowable_phivarids.add(def_vvarid)
|
|
368
|
+
else:
|
|
369
|
+
# blacklist it for now
|
|
370
|
+
blacklist_varids.add(def_vvarid)
|
|
672
371
|
|
|
673
372
|
# now determine what to narrow!
|
|
674
373
|
narrowables = []
|
|
@@ -834,7 +533,7 @@ class AILSimplifier(Analysis):
|
|
|
834
533
|
Determine the effective size of an expression when it's used.
|
|
835
534
|
"""
|
|
836
535
|
|
|
837
|
-
walker =
|
|
536
|
+
walker = NarrowingInfoExtractor(expr)
|
|
838
537
|
walker.walk_statement(statement)
|
|
839
538
|
if not walker.operations:
|
|
840
539
|
if expr is None:
|
|
@@ -1617,18 +1316,7 @@ class AILSimplifier(Analysis):
|
|
|
1617
1316
|
continue
|
|
1618
1317
|
uses = rd.get_vvar_uses(def_.atom)
|
|
1619
1318
|
|
|
1620
|
-
elif def_.atom.was_reg:
|
|
1621
|
-
uses = rd.get_vvar_uses(def_.atom)
|
|
1622
|
-
if (
|
|
1623
|
-
def_.atom.reg_offset in self.project.arch.artificial_registers_offsets
|
|
1624
|
-
and len(uses) == 1
|
|
1625
|
-
and next(iter(uses)) == def_.codeloc
|
|
1626
|
-
):
|
|
1627
|
-
# TODO: Verify if we still need this hack after moving to SSA
|
|
1628
|
-
# cc_ndep = amd64g_calculate_condition(..., cc_ndep)
|
|
1629
|
-
uses = set()
|
|
1630
|
-
|
|
1631
|
-
elif def_.atom.was_parameter:
|
|
1319
|
+
elif def_.atom.was_reg or def_.atom.was_parameter:
|
|
1632
1320
|
uses = rd.get_vvar_uses(def_.atom)
|
|
1633
1321
|
|
|
1634
1322
|
else:
|
|
@@ -1726,9 +1414,17 @@ class AILSimplifier(Analysis):
|
|
|
1726
1414
|
simplified = True
|
|
1727
1415
|
continue
|
|
1728
1416
|
if isinstance(stmt, Assignment) and isinstance(stmt.dst, VirtualVariable):
|
|
1729
|
-
# no one is using the returned virtual variable.
|
|
1730
|
-
# a
|
|
1731
|
-
|
|
1417
|
+
# no one is using the returned virtual variable.
|
|
1418
|
+
# now the things are a bit tricky here
|
|
1419
|
+
if isinstance(stmt.src, Call):
|
|
1420
|
+
# replace this assignment statement with a call statement
|
|
1421
|
+
stmt = stmt.src
|
|
1422
|
+
elif isinstance(stmt.src, Convert) and isinstance(stmt.src.operand, Call):
|
|
1423
|
+
# the convert is useless now
|
|
1424
|
+
stmt = stmt.src.operand
|
|
1425
|
+
else:
|
|
1426
|
+
# we can't change this stmt at all because it has an expression with Calls inside
|
|
1427
|
+
pass
|
|
1732
1428
|
else:
|
|
1733
1429
|
# no calls. remove it
|
|
1734
1430
|
simplified = True
|
|
@@ -1761,7 +1457,7 @@ class AILSimplifier(Analysis):
|
|
|
1761
1457
|
def _find_cyclic_dependent_phis_and_dirty_vvars(self, rd: SRDAModel) -> set[int]:
|
|
1762
1458
|
blocks_dict = {(bb.addr, bb.idx): bb for bb in self.func_graph}
|
|
1763
1459
|
|
|
1764
|
-
# find dirty vvars
|
|
1460
|
+
# find dirty vvars and vexccall vvars
|
|
1765
1461
|
dirty_vvar_ids = set()
|
|
1766
1462
|
for bb in self.func_graph:
|
|
1767
1463
|
for stmt in bb.statements:
|
|
@@ -1769,7 +1465,7 @@ class AILSimplifier(Analysis):
|
|
|
1769
1465
|
isinstance(stmt, Assignment)
|
|
1770
1466
|
and isinstance(stmt.dst, VirtualVariable)
|
|
1771
1467
|
and stmt.dst.was_reg
|
|
1772
|
-
and isinstance(stmt.src, DirtyExpression)
|
|
1468
|
+
and isinstance(stmt.src, (DirtyExpression, VEXCCallExpression))
|
|
1773
1469
|
):
|
|
1774
1470
|
dirty_vvar_ids.add(stmt.dst.varid)
|
|
1775
1471
|
|
|
@@ -1845,8 +1541,8 @@ class AILSimplifier(Analysis):
|
|
|
1845
1541
|
v = False
|
|
1846
1542
|
|
|
1847
1543
|
def _handle_expr(expr_idx: int, expr: Expression, stmt_idx: int, stmt: Statement, block) -> Expression | None:
|
|
1848
|
-
if isinstance(expr,
|
|
1849
|
-
rewriter = rewriter_cls(expr
|
|
1544
|
+
if isinstance(expr, VEXCCallExpression):
|
|
1545
|
+
rewriter = rewriter_cls(expr, self.project.arch)
|
|
1850
1546
|
if rewriter.result is not None:
|
|
1851
1547
|
_any_update.v = True
|
|
1852
1548
|
return rewriter.result
|
|
@@ -143,7 +143,7 @@ class CallSiteMaker(Analysis):
|
|
|
143
143
|
if isinstance(arg_loc, SimRegArg):
|
|
144
144
|
size = arg_loc.size
|
|
145
145
|
offset = arg_loc.check_offset(cc.arch)
|
|
146
|
-
value_and_def = self._resolve_register_argument(
|
|
146
|
+
value_and_def = self._resolve_register_argument(arg_loc)
|
|
147
147
|
if value_and_def is not None:
|
|
148
148
|
vvar_def = value_and_def[1]
|
|
149
149
|
arg_vvars.append(vvar_def)
|
|
@@ -283,14 +283,15 @@ class CallSiteMaker(Analysis):
|
|
|
283
283
|
l.warning("TODO: Unsupported statement type %s for definitions.", type(stmt))
|
|
284
284
|
return None
|
|
285
285
|
|
|
286
|
-
def _resolve_register_argument(self,
|
|
286
|
+
def _resolve_register_argument(self, arg_loc) -> tuple[int | None, Expr.VirtualVariable] | None:
|
|
287
287
|
offset = arg_loc.check_offset(self.project.arch)
|
|
288
288
|
|
|
289
289
|
if self._reaching_definitions is not None:
|
|
290
290
|
# Find its definition
|
|
291
|
-
ins_addr = call_stmt.tags["ins_addr"]
|
|
292
291
|
view = SRDAView(self._reaching_definitions.model)
|
|
293
|
-
vvar = view.
|
|
292
|
+
vvar = view.get_reg_vvar_by_stmt(
|
|
293
|
+
offset, self.block.addr, self.block.idx, len(self.block.statements) - 1, OP_BEFORE
|
|
294
|
+
)
|
|
294
295
|
|
|
295
296
|
if vvar is not None:
|
|
296
297
|
vvar_value = view.get_vvar_value(vvar)
|
|
@@ -318,8 +319,8 @@ class CallSiteMaker(Analysis):
|
|
|
318
319
|
if self._reaching_definitions is not None:
|
|
319
320
|
# find its definition
|
|
320
321
|
view = SRDAView(self._reaching_definitions.model)
|
|
321
|
-
vvar = view.
|
|
322
|
-
sp_offset, size,
|
|
322
|
+
vvar = view.get_stack_vvar_by_stmt(
|
|
323
|
+
sp_offset, size, self.block.addr, self.block.idx, len(self.block.statements) - 1, OP_BEFORE
|
|
323
324
|
)
|
|
324
325
|
if vvar is not None:
|
|
325
326
|
value = view.get_vvar_value(vvar)
|
|
@@ -416,7 +417,7 @@ class CallSiteMaker(Analysis):
|
|
|
416
417
|
|
|
417
418
|
value = None
|
|
418
419
|
if isinstance(arg_loc, SimRegArg):
|
|
419
|
-
value_and_def = self._resolve_register_argument(
|
|
420
|
+
value_and_def = self._resolve_register_argument(arg_loc)
|
|
420
421
|
if value_and_def is not None:
|
|
421
422
|
value = value_and_def[0]
|
|
422
423
|
|
|
@@ -20,7 +20,7 @@ class AMD64CCallRewriter(CCallRewriterBase):
|
|
|
20
20
|
__slots__ = ()
|
|
21
21
|
|
|
22
22
|
def _rewrite(self, ccall: Expr.VEXCCallExpression) -> Expr.Expression | None:
|
|
23
|
-
if ccall.
|
|
23
|
+
if ccall.callee == "amd64g_calculate_condition":
|
|
24
24
|
cond = ccall.operands[0]
|
|
25
25
|
op = ccall.operands[1]
|
|
26
26
|
dep_1 = ccall.operands[2]
|
|
@@ -288,6 +288,28 @@ class AMD64CCallRewriter(CCallRewriterBase):
|
|
|
288
288
|
|
|
289
289
|
r = Expr.BinaryOp(ccall.idx, "CmpLT", (dep_1, dep_2), True, **ccall.tags)
|
|
290
290
|
return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
|
|
291
|
+
|
|
292
|
+
if op_v in {
|
|
293
|
+
AMD64_OpTypes["G_CC_OP_LOGICB"],
|
|
294
|
+
AMD64_OpTypes["G_CC_OP_LOGICW"],
|
|
295
|
+
AMD64_OpTypes["G_CC_OP_LOGICL"],
|
|
296
|
+
AMD64_OpTypes["G_CC_OP_LOGICQ"],
|
|
297
|
+
}:
|
|
298
|
+
# dep_1 is the result, dep_2 is always zero
|
|
299
|
+
# dep_1 <s 0
|
|
300
|
+
|
|
301
|
+
dep_1 = self._fix_size(
|
|
302
|
+
dep_1,
|
|
303
|
+
op_v,
|
|
304
|
+
AMD64_OpTypes["G_CC_OP_LOGICB"],
|
|
305
|
+
AMD64_OpTypes["G_CC_OP_LOGICW"],
|
|
306
|
+
AMD64_OpTypes["G_CC_OP_LOGICL"],
|
|
307
|
+
ccall.tags,
|
|
308
|
+
)
|
|
309
|
+
zero = Expr.Const(None, None, 0, dep_1.bits)
|
|
310
|
+
r = Expr.BinaryOp(ccall.idx, "CmpLT", (dep_1, zero), True, **ccall.tags)
|
|
311
|
+
return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
|
|
312
|
+
|
|
291
313
|
elif cond_v == AMD64_CondTypes["CondNBE"]:
|
|
292
314
|
if op_v in {
|
|
293
315
|
AMD64_OpTypes["G_CC_OP_SUBB"],
|
|
@@ -390,7 +412,7 @@ class AMD64CCallRewriter(CCallRewriterBase):
|
|
|
390
412
|
)
|
|
391
413
|
return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
|
|
392
414
|
|
|
393
|
-
elif ccall.
|
|
415
|
+
elif ccall.callee == "amd64g_calculate_rflags_c":
|
|
394
416
|
# calculate the carry flag
|
|
395
417
|
op = ccall.operands[0]
|
|
396
418
|
dep_1 = ccall.operands[1]
|