angr 9.2.135__py3-none-win_amd64.whl → 9.2.137__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.
- angr/__init__.py +1 -1
- angr/analyses/__init__.py +3 -7
- angr/analyses/analysis.py +4 -0
- angr/analyses/backward_slice.py +1 -2
- angr/analyses/binary_optimizer.py +3 -4
- angr/analyses/bindiff.py +4 -6
- angr/analyses/boyscout.py +1 -3
- angr/analyses/callee_cleanup_finder.py +4 -4
- angr/analyses/calling_convention/calling_convention.py +6 -4
- angr/analyses/calling_convention/fact_collector.py +10 -3
- angr/analyses/cdg.py +1 -2
- angr/analyses/cfg/cfb.py +1 -3
- angr/analyses/cfg/cfg.py +2 -2
- angr/analyses/cfg/cfg_base.py +40 -68
- angr/analyses/cfg/cfg_emulated.py +1 -104
- angr/analyses/cfg/cfg_fast.py +90 -27
- angr/analyses/cfg/cfg_fast_soot.py +1 -1
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +46 -10
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +5 -1
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +65 -14
- angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +24 -5
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +2 -5
- angr/analyses/class_identifier.py +1 -2
- angr/analyses/complete_calling_conventions.py +3 -0
- angr/analyses/congruency_check.py +2 -3
- angr/analyses/data_dep/data_dependency_analysis.py +2 -2
- angr/analyses/ddg.py +1 -4
- angr/analyses/decompiler/ail_simplifier.py +15 -5
- angr/analyses/decompiler/block_simplifier.py +2 -2
- angr/analyses/decompiler/ccall_rewriters/__init__.py +2 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +69 -0
- angr/analyses/decompiler/clinic.py +119 -72
- angr/analyses/decompiler/condition_processor.py +2 -0
- angr/analyses/decompiler/decompiler.py +1 -0
- angr/analyses/decompiler/dephication/dephication_base.py +2 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +8 -6
- angr/analyses/decompiler/dephication/seqnode_dephication.py +10 -1
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +2 -2
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +1 -1
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +1 -2
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
- angr/analyses/decompiler/sequence_walker.py +6 -2
- angr/analyses/decompiler/ssailification/rewriting.py +11 -1
- angr/analyses/decompiler/ssailification/rewriting_engine.py +56 -19
- angr/analyses/decompiler/ssailification/ssailification.py +13 -3
- angr/analyses/decompiler/ssailification/traversal.py +28 -2
- angr/analyses/decompiler/ssailification/traversal_state.py +6 -1
- angr/analyses/decompiler/structured_codegen/c.py +44 -21
- angr/analyses/decompiler/structuring/phoenix.py +118 -15
- angr/analyses/decompiler/utils.py +113 -8
- angr/analyses/disassembly.py +5 -5
- angr/analyses/fcp/__init__.py +4 -0
- angr/analyses/fcp/fcp.py +429 -0
- angr/analyses/identifier/identify.py +1 -3
- angr/analyses/loopfinder.py +4 -3
- angr/analyses/patchfinder.py +1 -1
- angr/analyses/propagator/engine_base.py +4 -3
- angr/analyses/propagator/propagator.py +14 -53
- angr/analyses/reaching_definitions/function_handler.py +1 -1
- angr/analyses/reassembler.py +1 -2
- angr/analyses/s_liveness.py +5 -1
- angr/analyses/s_propagator.py +26 -7
- angr/analyses/s_reaching_definitions/s_rda_model.py +2 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +20 -1
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +11 -1
- angr/analyses/soot_class_hierarchy.py +1 -2
- angr/analyses/stack_pointer_tracker.py +29 -3
- angr/analyses/static_hooker.py +1 -2
- angr/analyses/typehoon/simple_solver.py +2 -2
- angr/analyses/variable_recovery/engine_ail.py +19 -7
- angr/analyses/variable_recovery/engine_base.py +16 -14
- angr/analyses/variable_recovery/engine_vex.py +2 -2
- angr/analyses/variable_recovery/variable_recovery_fast.py +23 -3
- angr/analyses/veritesting.py +4 -7
- angr/analyses/vfg.py +1 -1
- angr/analyses/vsa_ddg.py +1 -2
- angr/block.py +62 -22
- angr/callable.py +1 -3
- angr/calling_conventions.py +3 -3
- angr/codenode.py +5 -1
- angr/concretization_strategies/__init__.py +1 -83
- angr/concretization_strategies/any.py +2 -1
- angr/concretization_strategies/any_named.py +1 -1
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +2 -1
- angr/concretization_strategies/eval.py +2 -1
- angr/concretization_strategies/logging.py +3 -1
- angr/concretization_strategies/max.py +2 -1
- angr/concretization_strategies/nonzero.py +2 -1
- angr/concretization_strategies/nonzero_range.py +2 -1
- angr/concretization_strategies/norepeats.py +2 -1
- angr/concretization_strategies/norepeats_range.py +2 -1
- angr/concretization_strategies/range.py +2 -1
- angr/concretization_strategies/signed_add.py +2 -1
- angr/concretization_strategies/single.py +2 -1
- angr/concretization_strategies/solutions.py +2 -1
- angr/concretization_strategies/unlimited_range.py +2 -1
- angr/engines/__init__.py +8 -5
- angr/engines/engine.py +3 -5
- angr/engines/failure.py +4 -5
- angr/engines/pcode/emulate.py +1 -1
- angr/engines/pcode/lifter.py +31 -18
- angr/engines/procedure.py +5 -7
- angr/engines/soot/expressions/__init__.py +20 -23
- angr/engines/soot/expressions/base.py +4 -4
- angr/engines/soot/expressions/invoke.py +1 -2
- angr/engines/soot/statements/__init__.py +10 -12
- angr/engines/soot/values/__init__.py +10 -12
- angr/engines/soot/values/arrayref.py +3 -3
- angr/engines/soot/values/instancefieldref.py +3 -2
- angr/engines/successors.py +18 -12
- angr/engines/syscall.py +4 -6
- angr/engines/unicorn.py +3 -2
- angr/engines/vex/claripy/ccall.py +8 -10
- angr/engines/vex/claripy/datalayer.py +4 -5
- angr/engines/vex/lifter.py +9 -6
- angr/exploration_techniques/__init__.py +0 -2
- angr/exploration_techniques/spiller.py +1 -3
- angr/exploration_techniques/stochastic.py +2 -3
- angr/factory.py +3 -9
- angr/flirt/build_sig.py +8 -15
- angr/knowledge_plugins/cfg/cfg_model.py +20 -17
- angr/knowledge_plugins/functions/function.py +70 -79
- angr/knowledge_plugins/functions/function_manager.py +8 -7
- angr/knowledge_plugins/functions/function_parser.py +1 -1
- angr/knowledge_plugins/functions/soot_function.py +21 -24
- angr/knowledge_plugins/propagations/propagation_model.py +4 -5
- angr/knowledge_plugins/propagations/states.py +0 -511
- angr/knowledge_plugins/variables/variable_manager.py +16 -10
- angr/lib/angr_native.dll +0 -0
- angr/procedures/libc/memcpy.py +4 -4
- angr/procedures/procedure_dict.py +3 -2
- angr/protos/__init__.py +2 -5
- angr/protos/cfg_pb2.py +21 -18
- angr/protos/function_pb2.py +17 -14
- angr/protos/primitives_pb2.py +44 -39
- angr/protos/variables_pb2.py +36 -31
- angr/protos/xrefs_pb2.py +15 -12
- angr/sim_procedure.py +15 -16
- angr/sim_variable.py +13 -1
- angr/simos/__init__.py +2 -0
- angr/simos/javavm.py +4 -6
- angr/simos/xbox.py +32 -0
- angr/state_plugins/__init__.py +0 -2
- angr/state_plugins/callstack.py +4 -4
- angr/state_plugins/cgc.py +3 -2
- angr/state_plugins/gdb.py +6 -5
- angr/state_plugins/globals.py +1 -2
- angr/state_plugins/heap/heap_brk.py +1 -2
- angr/state_plugins/history.py +10 -12
- angr/state_plugins/inspect.py +3 -5
- angr/state_plugins/libc.py +2 -2
- angr/state_plugins/log.py +8 -10
- angr/state_plugins/loop_data.py +1 -2
- angr/state_plugins/posix.py +7 -7
- angr/state_plugins/preconstrainer.py +2 -3
- angr/state_plugins/scratch.py +5 -8
- angr/state_plugins/sim_action.py +3 -3
- angr/state_plugins/solver.py +8 -3
- angr/state_plugins/symbolizer.py +5 -4
- angr/state_plugins/uc_manager.py +3 -3
- angr/state_plugins/unicorn_engine.py +5 -1
- angr/state_plugins/view.py +3 -5
- angr/storage/file.py +3 -5
- angr/storage/memory_mixins/address_concretization_mixin.py +2 -2
- angr/storage/memory_mixins/bvv_conversion_mixin.py +3 -3
- angr/storage/memory_mixins/clouseau_mixin.py +1 -3
- angr/storage/memory_mixins/name_resolution_mixin.py +1 -3
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +13 -15
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +1 -22
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +3 -4
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +4 -2
- angr/storage/memory_mixins/smart_find_mixin.py +1 -1
- angr/storage/memory_mixins/underconstrained_mixin.py +1 -1
- angr/storage/memory_mixins/unwrapper_mixin.py +1 -3
- angr/utils/enums_conv.py +28 -12
- angr/utils/segment_list.py +25 -22
- angr/utils/timing.py +18 -1
- angr/vaults.py +5 -6
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/METADATA +7 -7
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/RECORD +194 -192
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/WHEEL +1 -1
- angr/analyses/propagator/outdated_definition_walker.py +0 -159
- angr/analyses/propagator/tmpvar_finder.py +0 -18
- angr/engines/concrete.py +0 -180
- angr/exploration_techniques/symbion.py +0 -80
- angr/state_plugins/concrete.py +0 -295
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/LICENSE +0 -0
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/entry_points.txt +0 -0
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/top_level.txt +0 -0
|
@@ -17,11 +17,7 @@ from angr.storage.memory_object import SimMemoryObject, SimLabeledMemoryObject
|
|
|
17
17
|
from angr.storage.memory_mixins import LabeledMemory
|
|
18
18
|
from angr.engines.light.engine import SimEngineLight
|
|
19
19
|
from angr.code_location import CodeLocation
|
|
20
|
-
from angr.knowledge_plugins.key_definitions import atoms
|
|
21
|
-
from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE
|
|
22
|
-
from angr.engines.light.data import SpOffset
|
|
23
20
|
|
|
24
|
-
from .prop_value import PropValue, Detail
|
|
25
21
|
|
|
26
22
|
if TYPE_CHECKING:
|
|
27
23
|
from archinfo import Arch
|
|
@@ -55,7 +51,6 @@ class PropagatorState:
|
|
|
55
51
|
:ivar arch: Architecture of the binary.
|
|
56
52
|
:ivar gp: value of the global pointer for MIPS binaries.
|
|
57
53
|
:ivar _replacements: Stores expressions to replace, keyed by CodeLocation instances
|
|
58
|
-
:ivar _equivalence: Stores equivalence constraints that Propagator discovers during the analysis.
|
|
59
54
|
:ivar _only_consts: Only track constants.
|
|
60
55
|
:ivar _expr_used_locs: A dict keyed by expressions and valued by CodeLocations where the expression is used.
|
|
61
56
|
:ivar _max_prop_expr_occurrence: The upperbound for the number of occurrences of an expression for Propagator
|
|
@@ -67,7 +62,6 @@ class PropagatorState:
|
|
|
67
62
|
__slots__ = (
|
|
68
63
|
"__weakref__",
|
|
69
64
|
"_artificial_reg_offsets",
|
|
70
|
-
"_equivalence",
|
|
71
65
|
"_expr_used_locs",
|
|
72
66
|
"_gp",
|
|
73
67
|
"_max_prop_expr_occurrence",
|
|
@@ -78,7 +72,6 @@ class PropagatorState:
|
|
|
78
72
|
"gpr_size",
|
|
79
73
|
"model",
|
|
80
74
|
"project",
|
|
81
|
-
"rda",
|
|
82
75
|
)
|
|
83
76
|
|
|
84
77
|
_tops = {}
|
|
@@ -87,11 +80,9 @@ class PropagatorState:
|
|
|
87
80
|
self,
|
|
88
81
|
arch: Arch,
|
|
89
82
|
project: Project | None = None,
|
|
90
|
-
rda=None,
|
|
91
83
|
replacements: defaultdict[CodeLocation, dict] | None = None,
|
|
92
84
|
only_consts: bool = False,
|
|
93
85
|
expr_used_locs: defaultdict[Any, set[CodeLocation]] | None = None,
|
|
94
|
-
equivalence: set[Equivalence] | None = None,
|
|
95
86
|
store_tops: bool = True,
|
|
96
87
|
gp: int | None = None,
|
|
97
88
|
max_prop_expr_occurrence: int = 1,
|
|
@@ -105,7 +96,6 @@ class PropagatorState:
|
|
|
105
96
|
self._expr_used_locs = defaultdict(list) if expr_used_locs is None else expr_used_locs
|
|
106
97
|
self._only_consts = only_consts
|
|
107
98
|
self._replacements = defaultdict(dict) if replacements is None else replacements
|
|
108
|
-
self._equivalence: set[Equivalence] = equivalence if equivalence is not None else set()
|
|
109
99
|
self._store_tops = store_tops
|
|
110
100
|
self._max_prop_expr_occurrence = max_prop_expr_occurrence
|
|
111
101
|
self._artificial_reg_offsets = artificial_reg_offsets if artificial_reg_offsets is not None else set()
|
|
@@ -115,7 +105,6 @@ class PropagatorState:
|
|
|
115
105
|
|
|
116
106
|
self.project = project
|
|
117
107
|
self.model = model
|
|
118
|
-
self.rda = rda
|
|
119
108
|
|
|
120
109
|
def __repr__(self) -> str:
|
|
121
110
|
return "<PropagatorState>"
|
|
@@ -124,7 +113,6 @@ class PropagatorState:
|
|
|
124
113
|
def initial_state(
|
|
125
114
|
cls,
|
|
126
115
|
project: Project,
|
|
127
|
-
rda=None,
|
|
128
116
|
only_consts=False,
|
|
129
117
|
gp=None,
|
|
130
118
|
do_binops=True,
|
|
@@ -257,10 +245,6 @@ class PropagatorState:
|
|
|
257
245
|
for o in others:
|
|
258
246
|
merge_occurred |= PropagatorState.merge_replacements(state._replacements, o._replacements)
|
|
259
247
|
|
|
260
|
-
if state._equivalence != o._equivalence:
|
|
261
|
-
merge_occurred = True
|
|
262
|
-
state._equivalence |= o._equivalence
|
|
263
|
-
|
|
264
248
|
return state, merge_occurred
|
|
265
249
|
|
|
266
250
|
def init_replacements(self):
|
|
@@ -378,7 +362,6 @@ class PropagatorVEXState(PropagatorState):
|
|
|
378
362
|
self,
|
|
379
363
|
arch,
|
|
380
364
|
project=None,
|
|
381
|
-
rda=None,
|
|
382
365
|
registers=None,
|
|
383
366
|
local_variables=None,
|
|
384
367
|
replacements=None,
|
|
@@ -395,7 +378,6 @@ class PropagatorVEXState(PropagatorState):
|
|
|
395
378
|
super().__init__(
|
|
396
379
|
arch,
|
|
397
380
|
project=project,
|
|
398
|
-
rda=rda,
|
|
399
381
|
replacements=replacements,
|
|
400
382
|
only_consts=only_consts,
|
|
401
383
|
expr_used_locs=expr_used_locs,
|
|
@@ -430,7 +412,6 @@ class PropagatorVEXState(PropagatorState):
|
|
|
430
412
|
def initial_state(
|
|
431
413
|
cls,
|
|
432
414
|
project,
|
|
433
|
-
rda=None,
|
|
434
415
|
only_consts=False,
|
|
435
416
|
gp=None,
|
|
436
417
|
do_binops=True,
|
|
@@ -443,7 +424,6 @@ class PropagatorVEXState(PropagatorState):
|
|
|
443
424
|
state = cls(
|
|
444
425
|
project.arch,
|
|
445
426
|
project=project,
|
|
446
|
-
rda=rda,
|
|
447
427
|
only_consts=only_consts,
|
|
448
428
|
do_binops=do_binops,
|
|
449
429
|
store_tops=store_tops,
|
|
@@ -483,7 +463,6 @@ class PropagatorVEXState(PropagatorState):
|
|
|
483
463
|
return PropagatorVEXState(
|
|
484
464
|
self.arch,
|
|
485
465
|
project=self.project,
|
|
486
|
-
rda=self.rda,
|
|
487
466
|
registers=self._registers.copy(),
|
|
488
467
|
local_variables=self._stack_variables.copy(),
|
|
489
468
|
replacements=self._replacements.copy(),
|
|
@@ -519,11 +498,6 @@ class PropagatorVEXState(PropagatorState):
|
|
|
519
498
|
self._registers.store(offset, value, size=size)
|
|
520
499
|
|
|
521
500
|
def load_register(self, offset, size):
|
|
522
|
-
# TODO: Fix me
|
|
523
|
-
# load register even if size != self.gpr_size
|
|
524
|
-
# if size != self.gpr_size:
|
|
525
|
-
# return self.top(size * self.arch.byte_width).annotate(RegisterAnnotation(offset, size))
|
|
526
|
-
|
|
527
501
|
try:
|
|
528
502
|
v = self._registers.load(offset, size=size)
|
|
529
503
|
if self.is_top(v):
|
|
@@ -573,488 +547,3 @@ class Equivalence:
|
|
|
573
547
|
|
|
574
548
|
def __hash__(self):
|
|
575
549
|
return hash((Equivalence, self.codeloc, self.atom0, self.atom1))
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
class PropagatorAILState(PropagatorState):
|
|
579
|
-
"""
|
|
580
|
-
Describes the state used in the AIL engine of Propagator.
|
|
581
|
-
"""
|
|
582
|
-
|
|
583
|
-
__slots__ = (
|
|
584
|
-
"_registers",
|
|
585
|
-
"_sp_adjusted",
|
|
586
|
-
"_stack_variables",
|
|
587
|
-
"_tmps",
|
|
588
|
-
"block_initial_reg_values",
|
|
589
|
-
"global_stores",
|
|
590
|
-
"last_stack_store",
|
|
591
|
-
"register_expressions",
|
|
592
|
-
"temp_expressions",
|
|
593
|
-
)
|
|
594
|
-
|
|
595
|
-
def __init__(
|
|
596
|
-
self,
|
|
597
|
-
arch,
|
|
598
|
-
project=None,
|
|
599
|
-
rda=None,
|
|
600
|
-
replacements=None,
|
|
601
|
-
only_consts=False,
|
|
602
|
-
expr_used_locs=None,
|
|
603
|
-
equivalence=None,
|
|
604
|
-
stack_variables=None,
|
|
605
|
-
registers=None,
|
|
606
|
-
gp=None,
|
|
607
|
-
block_initial_reg_values=None,
|
|
608
|
-
max_prop_expr_occurrence: int = 1,
|
|
609
|
-
sp_adjusted: bool = False,
|
|
610
|
-
model=None,
|
|
611
|
-
artificial_reg_offsets=None,
|
|
612
|
-
):
|
|
613
|
-
super().__init__(
|
|
614
|
-
arch,
|
|
615
|
-
project=project,
|
|
616
|
-
rda=rda,
|
|
617
|
-
replacements=replacements,
|
|
618
|
-
only_consts=only_consts,
|
|
619
|
-
expr_used_locs=expr_used_locs,
|
|
620
|
-
equivalence=equivalence,
|
|
621
|
-
gp=gp,
|
|
622
|
-
max_prop_expr_occurrence=max_prop_expr_occurrence,
|
|
623
|
-
model=model,
|
|
624
|
-
artificial_reg_offsets=artificial_reg_offsets,
|
|
625
|
-
)
|
|
626
|
-
|
|
627
|
-
self._stack_variables = (
|
|
628
|
-
LabeledMemory(memory_id="mem", top_func=self.top, page_kwargs={"mo_cmp": self._mo_cmp})
|
|
629
|
-
if stack_variables is None
|
|
630
|
-
else stack_variables
|
|
631
|
-
)
|
|
632
|
-
self._registers = (
|
|
633
|
-
LabeledMemory(memory_id="reg", top_func=self.top, page_kwargs={"mo_cmp": self._mo_cmp})
|
|
634
|
-
if registers is None
|
|
635
|
-
else registers
|
|
636
|
-
)
|
|
637
|
-
self._tmps = {}
|
|
638
|
-
self.temp_expressions = {}
|
|
639
|
-
self.register_expressions = {}
|
|
640
|
-
self.block_initial_reg_values: defaultdict[
|
|
641
|
-
tuple[int, int], list[tuple[ailment.Expr.Register, ailment.Expr.Const]]
|
|
642
|
-
] = (defaultdict(list) if block_initial_reg_values is None else block_initial_reg_values)
|
|
643
|
-
self._sp_adjusted: bool = sp_adjusted
|
|
644
|
-
|
|
645
|
-
self._registers.set_state(self)
|
|
646
|
-
self._stack_variables.set_state(self)
|
|
647
|
-
# last_stack_store stores the most recent stack store statement with a non-concrete or unresolvable address. we
|
|
648
|
-
# use this information to determine if stack reads after this store can be safely resolved to definitions prior
|
|
649
|
-
# to the stack read.
|
|
650
|
-
self.last_stack_store: tuple[int, int, ailment.Stmt.Store] | None = None
|
|
651
|
-
self.global_stores: list[tuple[int, int, Any, ailment.Stmt.Store]] = []
|
|
652
|
-
|
|
653
|
-
def __repr__(self):
|
|
654
|
-
return "<PropagatorAILState>"
|
|
655
|
-
|
|
656
|
-
@classmethod
|
|
657
|
-
def initial_state(
|
|
658
|
-
cls,
|
|
659
|
-
project: Project,
|
|
660
|
-
rda=None,
|
|
661
|
-
only_consts=False,
|
|
662
|
-
gp=None,
|
|
663
|
-
do_binops=True,
|
|
664
|
-
store_tops=False,
|
|
665
|
-
func_addr=None,
|
|
666
|
-
max_prop_expr_occurrence=None,
|
|
667
|
-
initial_codeloc=None,
|
|
668
|
-
model=None,
|
|
669
|
-
):
|
|
670
|
-
state = cls(
|
|
671
|
-
project.arch,
|
|
672
|
-
project=project,
|
|
673
|
-
rda=rda,
|
|
674
|
-
only_consts=only_consts,
|
|
675
|
-
gp=gp,
|
|
676
|
-
max_prop_expr_occurrence=max_prop_expr_occurrence,
|
|
677
|
-
model=model,
|
|
678
|
-
)
|
|
679
|
-
spoffset_var = ailment.Expr.StackBaseOffset(None, project.arch.bits, 0)
|
|
680
|
-
sp_value = PropValue(
|
|
681
|
-
claripy.BVV(0x7FFF_FF00, project.arch.bits),
|
|
682
|
-
offset_and_details={0: Detail(project.arch.bytes, spoffset_var, initial_codeloc)},
|
|
683
|
-
)
|
|
684
|
-
state.store_register(
|
|
685
|
-
ailment.Expr.Register(None, None, project.arch.sp_offset, project.arch.bits),
|
|
686
|
-
sp_value,
|
|
687
|
-
)
|
|
688
|
-
|
|
689
|
-
if project.arch.name == "MIPS64":
|
|
690
|
-
if func_addr is not None:
|
|
691
|
-
reg_expr = ailment.Expr.Register(
|
|
692
|
-
None, None, project.arch.registers["t9"][0], project.arch.registers["t9"][1]
|
|
693
|
-
)
|
|
694
|
-
reg_value = ailment.Expr.Const(None, None, func_addr, 64)
|
|
695
|
-
state.store_register(
|
|
696
|
-
reg_expr,
|
|
697
|
-
PropValue(
|
|
698
|
-
claripy.BVV(func_addr, 64),
|
|
699
|
-
offset_and_details={0: Detail(8, reg_value, initial_codeloc)},
|
|
700
|
-
),
|
|
701
|
-
)
|
|
702
|
-
elif project.arch.name == "MIPS32":
|
|
703
|
-
if func_addr is not None:
|
|
704
|
-
reg_expr = ailment.Expr.Register(
|
|
705
|
-
None, None, project.arch.registers["t9"][0], project.arch.registers["t9"][1]
|
|
706
|
-
)
|
|
707
|
-
reg_value = ailment.Expr.Const(None, None, func_addr, 32)
|
|
708
|
-
state.store_register(
|
|
709
|
-
reg_expr,
|
|
710
|
-
PropValue(
|
|
711
|
-
claripy.BVV(func_addr, 32),
|
|
712
|
-
offset_and_details={0: Detail(4, reg_value, initial_codeloc)},
|
|
713
|
-
),
|
|
714
|
-
)
|
|
715
|
-
elif archinfo.arch_arm.is_arm_arch(project.arch):
|
|
716
|
-
# clear fpscr
|
|
717
|
-
reg_expr = ailment.Expr.Register(None, None, *project.arch.registers["fpscr"])
|
|
718
|
-
reg_value = ailment.Expr.Const(None, None, 0, 32)
|
|
719
|
-
state.store_register(
|
|
720
|
-
reg_expr,
|
|
721
|
-
PropValue(claripy.BVV(0, 32), offset_and_details={0: Detail(4, reg_value, initial_codeloc)}),
|
|
722
|
-
)
|
|
723
|
-
|
|
724
|
-
elif project.arch.name.startswith("PowerPC:"):
|
|
725
|
-
# pcode PowerPC
|
|
726
|
-
state._artificial_reg_offsets = {project.arch.registers["tea"][0]}
|
|
727
|
-
|
|
728
|
-
# clear xer_so
|
|
729
|
-
reg_expr = ailment.Expr.Register(None, None, *project.arch.registers["xer_so"])
|
|
730
|
-
reg_value = ailment.Expr.Const(None, None, 0, 8)
|
|
731
|
-
state.store_register(
|
|
732
|
-
reg_expr,
|
|
733
|
-
PropValue(claripy.BVV(0, 8), offset_and_details={0: Detail(1, reg_value, initial_codeloc)}),
|
|
734
|
-
)
|
|
735
|
-
|
|
736
|
-
if (
|
|
737
|
-
project is not None
|
|
738
|
-
and project.simos is not None
|
|
739
|
-
and project.simos.function_initial_registers
|
|
740
|
-
and func_addr is not None
|
|
741
|
-
):
|
|
742
|
-
for reg_name, reg_value in project.simos.function_initial_registers.items():
|
|
743
|
-
reg_size = project.arch.registers[reg_name][1]
|
|
744
|
-
reg_expr = ailment.Expr.Register(None, None, project.arch.registers[reg_name][0], reg_size)
|
|
745
|
-
reg_value_expr = ailment.Expr.Const(None, None, reg_value, reg_size * 8)
|
|
746
|
-
state.store_register(
|
|
747
|
-
reg_expr,
|
|
748
|
-
PropValue(
|
|
749
|
-
claripy.BVV(reg_value, project.arch.bits),
|
|
750
|
-
offset_and_details={0: Detail(reg_size, reg_value_expr, initial_codeloc)},
|
|
751
|
-
),
|
|
752
|
-
)
|
|
753
|
-
|
|
754
|
-
return state
|
|
755
|
-
|
|
756
|
-
def copy(self) -> PropagatorAILState:
|
|
757
|
-
return PropagatorAILState(
|
|
758
|
-
self.arch,
|
|
759
|
-
project=self.project,
|
|
760
|
-
rda=self.rda,
|
|
761
|
-
replacements=self._replacements.copy(),
|
|
762
|
-
expr_used_locs=self._expr_used_locs.copy(),
|
|
763
|
-
only_consts=self._only_consts,
|
|
764
|
-
equivalence=self._equivalence.copy(),
|
|
765
|
-
stack_variables=self._stack_variables.copy(),
|
|
766
|
-
registers=self._registers.copy(),
|
|
767
|
-
block_initial_reg_values=self.block_initial_reg_values.copy(),
|
|
768
|
-
# drop tmps
|
|
769
|
-
gp=self._gp,
|
|
770
|
-
max_prop_expr_occurrence=self._max_prop_expr_occurrence,
|
|
771
|
-
sp_adjusted=self._sp_adjusted,
|
|
772
|
-
model=self.model,
|
|
773
|
-
artificial_reg_offsets=self._artificial_reg_offsets,
|
|
774
|
-
)
|
|
775
|
-
|
|
776
|
-
@staticmethod
|
|
777
|
-
def is_const_or_register(value: ailment.Expr.Expression | claripy.ast.Bits | None) -> bool:
|
|
778
|
-
if value is None:
|
|
779
|
-
return False
|
|
780
|
-
if isinstance(value, claripy.ast.BV):
|
|
781
|
-
return not value.symbolic
|
|
782
|
-
if isinstance(value, ailment.Expr.Register):
|
|
783
|
-
return True
|
|
784
|
-
if isinstance(value, ailment.Expr.Const) or (isinstance(value, int) and value == 0):
|
|
785
|
-
return True
|
|
786
|
-
if isinstance(value, ailment.Expr.StackBaseOffset):
|
|
787
|
-
return True
|
|
788
|
-
# more hacks: also store the eq comparisons
|
|
789
|
-
if (
|
|
790
|
-
isinstance(value, ailment.Expr.BinaryOp)
|
|
791
|
-
and value.op == "CmpEQ"
|
|
792
|
-
and all(isinstance(arg, (ailment.Expr.Const, ailment.Expr.Tmp)) for arg in value.operands)
|
|
793
|
-
):
|
|
794
|
-
return True
|
|
795
|
-
# more hacks: also store the conversions
|
|
796
|
-
return bool(isinstance(value, ailment.Expr.Convert) and PropagatorAILState.is_const_or_register(value.operand))
|
|
797
|
-
|
|
798
|
-
def merge(self, *others) -> tuple[PropagatorAILState, bool]:
|
|
799
|
-
state, merge_occurred = super().merge(*others)
|
|
800
|
-
state: PropagatorAILState
|
|
801
|
-
|
|
802
|
-
merge_occurred |= state._registers.merge([o._registers for o in others], None)
|
|
803
|
-
merge_occurred |= state._stack_variables.merge([o._stack_variables for o in others], None)
|
|
804
|
-
|
|
805
|
-
return state, merge_occurred
|
|
806
|
-
|
|
807
|
-
def store_temp(self, tmp_idx: int, value: PropValue):
|
|
808
|
-
self._tmps[tmp_idx] = value
|
|
809
|
-
|
|
810
|
-
def load_tmp(self, tmp_idx: int) -> PropValue | None:
|
|
811
|
-
return self._tmps.get(tmp_idx, None)
|
|
812
|
-
|
|
813
|
-
def store_register(self, reg: ailment.Expr.Register, value: PropValue) -> None:
|
|
814
|
-
if isinstance(value, ailment.Expr.Expression) and value.has_atom(reg, identity=False):
|
|
815
|
-
return
|
|
816
|
-
|
|
817
|
-
for offset, chopped_value, size, label in value.value_and_labels():
|
|
818
|
-
self._registers.store(
|
|
819
|
-
reg.reg_offset + offset,
|
|
820
|
-
chopped_value,
|
|
821
|
-
size=size,
|
|
822
|
-
label=label,
|
|
823
|
-
endness=self.project.arch.register_endness,
|
|
824
|
-
)
|
|
825
|
-
|
|
826
|
-
def store_stack_variable(
|
|
827
|
-
self, sp_offset: int, new: PropValue, endness=None
|
|
828
|
-
) -> None: # pylint:disable=unused-argument
|
|
829
|
-
# normalize sp_offset to handle negative offsets
|
|
830
|
-
sp_offset += 0x65536
|
|
831
|
-
sp_offset &= (1 << self.arch.bits) - 1
|
|
832
|
-
|
|
833
|
-
for offset, value, size, label in new.value_and_labels():
|
|
834
|
-
self._stack_variables.store(sp_offset + offset, value, size=size, endness=endness, label=label)
|
|
835
|
-
|
|
836
|
-
def load_register(self, reg: ailment.Expr.Register) -> PropValue | None:
|
|
837
|
-
try:
|
|
838
|
-
value, labels = self._registers.load_with_labels(
|
|
839
|
-
reg.reg_offset, size=reg.size, endness=self.project.arch.register_endness
|
|
840
|
-
)
|
|
841
|
-
except SimMemoryMissingError:
|
|
842
|
-
# value does not exist
|
|
843
|
-
return None
|
|
844
|
-
|
|
845
|
-
return PropValue.from_value_and_labels(value, labels)
|
|
846
|
-
|
|
847
|
-
def load_stack_variable(self, sp_offset: int, size, endness=None) -> PropValue | None:
|
|
848
|
-
# normalize sp_offset to handle negative offsets
|
|
849
|
-
sp_offset += 0x65536
|
|
850
|
-
sp_offset &= (1 << self.arch.bits) - 1
|
|
851
|
-
try:
|
|
852
|
-
value, labels = self._stack_variables.load_with_labels(sp_offset, size=size, endness=endness)
|
|
853
|
-
except SimMemoryMissingError as ex:
|
|
854
|
-
# the stack variable does not exist - however, maybe some portion of it exists!
|
|
855
|
-
if ex.missing_addr > sp_offset:
|
|
856
|
-
# some data exist. load again
|
|
857
|
-
try:
|
|
858
|
-
value, labels = self._stack_variables.load_with_labels(
|
|
859
|
-
sp_offset, size=ex.missing_addr - sp_offset, endness=endness
|
|
860
|
-
)
|
|
861
|
-
# then we zero-extend both the value and labels
|
|
862
|
-
if value is not None and len(labels) == 1 and labels[0][0] == 0:
|
|
863
|
-
value = claripy.ZeroExt(ex.missing_size * self.arch.byte_width, value)
|
|
864
|
-
offset, offset_in_expr, size, label = labels[0]
|
|
865
|
-
labels = ((offset, offset_in_expr, size + ex.missing_size, label),)
|
|
866
|
-
except SimMemoryMissingError:
|
|
867
|
-
# failed again... welp
|
|
868
|
-
return None
|
|
869
|
-
else:
|
|
870
|
-
return None
|
|
871
|
-
|
|
872
|
-
return PropValue.from_value_and_labels(value, labels)
|
|
873
|
-
|
|
874
|
-
def should_replace_reg(self, old_reg_offset: int, bp_as_gpr: bool, new_value) -> bool:
|
|
875
|
-
if old_reg_offset == self.arch.sp_offset or (not bp_as_gpr and old_reg_offset == self.arch.bp_offset):
|
|
876
|
-
return True
|
|
877
|
-
if old_reg_offset in self._artificial_reg_offsets:
|
|
878
|
-
return True
|
|
879
|
-
return bool(isinstance(new_value, ailment.Expr.StackBaseOffset))
|
|
880
|
-
|
|
881
|
-
def add_replacement(
|
|
882
|
-
self,
|
|
883
|
-
codeloc: CodeLocation,
|
|
884
|
-
old,
|
|
885
|
-
new,
|
|
886
|
-
force_replace: bool = False,
|
|
887
|
-
stmt_to_remove: CodeLocation | None = None,
|
|
888
|
-
bp_as_gpr: bool = False,
|
|
889
|
-
) -> bool:
|
|
890
|
-
if self._only_consts:
|
|
891
|
-
if self.is_const_or_register(new) or self.is_top(new):
|
|
892
|
-
pass
|
|
893
|
-
else:
|
|
894
|
-
new = self.top(1)
|
|
895
|
-
|
|
896
|
-
# do not replace anything with a call expression
|
|
897
|
-
if isinstance(new, ailment.statement.Call):
|
|
898
|
-
return False
|
|
899
|
-
callexpr_finder = CallExprFinder()
|
|
900
|
-
callexpr_finder.walk_expression(new)
|
|
901
|
-
if callexpr_finder.has_call:
|
|
902
|
-
return False
|
|
903
|
-
|
|
904
|
-
if self.is_top(new):
|
|
905
|
-
self._replacements[codeloc][old] = self.top(1) # placeholder
|
|
906
|
-
return False
|
|
907
|
-
|
|
908
|
-
if isinstance(new, ailment.Expr.Expression) and (
|
|
909
|
-
self.is_expression_too_deep(new) or (self.has_ternary_expr(new) and not isinstance(old, ailment.Expr.Tmp))
|
|
910
|
-
):
|
|
911
|
-
# eliminate the past propagation of this expression
|
|
912
|
-
self._replacements[codeloc][old] = self.top(1) # placeholder
|
|
913
|
-
self.revert_past_replacements(new, to_replace=old)
|
|
914
|
-
return False
|
|
915
|
-
|
|
916
|
-
replaced = False
|
|
917
|
-
# count-based propagation rule only matters when we are performing a full-function copy propagation
|
|
918
|
-
if self._max_prop_expr_occurrence == 0:
|
|
919
|
-
if isinstance(old, ailment.Expr.Tmp) or (
|
|
920
|
-
isinstance(old, ailment.Expr.Register) and self.should_replace_reg(old.reg_offset, bp_as_gpr, new)
|
|
921
|
-
):
|
|
922
|
-
self._replacements[codeloc][old] = (
|
|
923
|
-
new if stmt_to_remove is None else {"expr": new, "stmt_to_remove": stmt_to_remove}
|
|
924
|
-
)
|
|
925
|
-
replaced = True
|
|
926
|
-
else:
|
|
927
|
-
prop_count = 0
|
|
928
|
-
def_ = None
|
|
929
|
-
if isinstance(old, ailment.Expr.Tmp) or isinstance(new, ailment.Expr.Const):
|
|
930
|
-
# we always propagate tmp and constants
|
|
931
|
-
pass
|
|
932
|
-
elif self.is_simple_expression(new):
|
|
933
|
-
# always propagate variables without other operations
|
|
934
|
-
pass
|
|
935
|
-
else:
|
|
936
|
-
if self.rda is not None:
|
|
937
|
-
if isinstance(old, ailment.Expr.Register):
|
|
938
|
-
defs = self.rda.get_defs(atoms.Register(old.reg_offset, old.size), codeloc, OP_BEFORE)
|
|
939
|
-
if len(defs) == 1:
|
|
940
|
-
def_ = next(iter(defs))
|
|
941
|
-
elif isinstance(old, ailment.Expr.Load) and isinstance(old.addr, ailment.Expr.StackBaseOffset):
|
|
942
|
-
defs = self.rda.get_defs(
|
|
943
|
-
atoms.MemoryLocation(SpOffset(old.addr.bits, old.addr.offset), old.size), codeloc, OP_BEFORE
|
|
944
|
-
)
|
|
945
|
-
if len(defs) == 1:
|
|
946
|
-
def_ = next(iter(defs))
|
|
947
|
-
if def_ is not None:
|
|
948
|
-
self._expr_used_locs[def_].append(codeloc)
|
|
949
|
-
# we must consider known future uses of this definition as well
|
|
950
|
-
prop_count = max(len(self._expr_used_locs[def_]), len(self.rda.all_uses.get_uses(def_)))
|
|
951
|
-
else:
|
|
952
|
-
# multiple definitions or no definitions - do not propagate
|
|
953
|
-
return False
|
|
954
|
-
else:
|
|
955
|
-
# when RDA result is not available, we use the expression directly for worse results
|
|
956
|
-
self._expr_used_locs[new].append(codeloc)
|
|
957
|
-
prop_count = len(self._expr_used_locs[new])
|
|
958
|
-
|
|
959
|
-
if ( # pylint:disable=too-many-boolean-expressions
|
|
960
|
-
force_replace
|
|
961
|
-
or prop_count <= self._max_prop_expr_occurrence
|
|
962
|
-
or isinstance(new, ailment.Expr.StackBaseOffset)
|
|
963
|
-
or (isinstance(new, ailment.Expr.Convert) and isinstance(new.operand, ailment.Expr.StackBaseOffset))
|
|
964
|
-
or (
|
|
965
|
-
isinstance(old, ailment.Expr.Register)
|
|
966
|
-
and self.arch.is_artificial_register(old.reg_offset, old.size)
|
|
967
|
-
)
|
|
968
|
-
):
|
|
969
|
-
# we can propagate this expression
|
|
970
|
-
self._replacements[codeloc][old] = (
|
|
971
|
-
new if stmt_to_remove is None else {"expr": new, "stmt_to_remove": stmt_to_remove}
|
|
972
|
-
)
|
|
973
|
-
replaced = True
|
|
974
|
-
else:
|
|
975
|
-
self._replacements[codeloc][old] = self.top(1) # placeholder
|
|
976
|
-
|
|
977
|
-
# eliminate the past propagation of this expression
|
|
978
|
-
for codeloc_ in self._replacements:
|
|
979
|
-
if old in self._replacements[codeloc_]:
|
|
980
|
-
self._replacements[codeloc_][old] = self.top(1)
|
|
981
|
-
self.revert_past_replacements(new, to_replace=old, to_replace_def=def_)
|
|
982
|
-
|
|
983
|
-
return replaced
|
|
984
|
-
|
|
985
|
-
def revert_past_replacements(self, replaced_by, to_replace=None, to_replace_def=None) -> set[CodeLocation]:
|
|
986
|
-
updated_codelocs = set()
|
|
987
|
-
if self.model.replacements is not None:
|
|
988
|
-
for codeloc_ in self._expr_used_locs[to_replace_def if to_replace_def is not None else to_replace]:
|
|
989
|
-
for key, replace_with in list(self.model.replacements[codeloc_].items()):
|
|
990
|
-
if isinstance(replace_with, dict):
|
|
991
|
-
replace_with = replace_with["expr"]
|
|
992
|
-
if not self.is_top(replace_with) and replace_with == replaced_by:
|
|
993
|
-
self.model.replacements[codeloc_][key] = self.top(1)
|
|
994
|
-
updated_codelocs.add(codeloc_)
|
|
995
|
-
|
|
996
|
-
for codeloc_ in self._expr_used_locs[to_replace_def if to_replace_def is not None else to_replace]:
|
|
997
|
-
if codeloc_ in self._replacements:
|
|
998
|
-
for key, replace_with in list(self._replacements[codeloc_].items()):
|
|
999
|
-
if isinstance(replace_with, dict):
|
|
1000
|
-
replace_with = replace_with["expr"]
|
|
1001
|
-
if not self.is_top(replace_with) and replace_with == replaced_by and to_replace.likes(key):
|
|
1002
|
-
self._replacements[codeloc_][key] = self.top(1)
|
|
1003
|
-
updated_codelocs.add(codeloc_)
|
|
1004
|
-
|
|
1005
|
-
return updated_codelocs
|
|
1006
|
-
|
|
1007
|
-
def add_equivalence(self, codeloc, old, new):
|
|
1008
|
-
eq = Equivalence(codeloc, old, new)
|
|
1009
|
-
self._equivalence.add(eq)
|
|
1010
|
-
|
|
1011
|
-
@staticmethod
|
|
1012
|
-
def is_simple_expression(expr: ailment.Expr.Expression) -> bool:
|
|
1013
|
-
if PropagatorAILState.is_shallow_expression(expr):
|
|
1014
|
-
return True
|
|
1015
|
-
return bool(
|
|
1016
|
-
isinstance(expr, ailment.Expr.BinaryOp)
|
|
1017
|
-
and expr.op in {"Add", "Sub"}
|
|
1018
|
-
and (
|
|
1019
|
-
(
|
|
1020
|
-
isinstance(expr.operands[0], ailment.Expr.Register)
|
|
1021
|
-
and PropagatorAILState.is_global_variable_load(expr.operands[1])
|
|
1022
|
-
)
|
|
1023
|
-
or (
|
|
1024
|
-
isinstance(expr.operands[1], ailment.Expr.Register)
|
|
1025
|
-
and PropagatorAILState.is_global_variable_load(expr.operands[0])
|
|
1026
|
-
)
|
|
1027
|
-
)
|
|
1028
|
-
)
|
|
1029
|
-
|
|
1030
|
-
@staticmethod
|
|
1031
|
-
def is_shallow_expression(expr: ailment.Expr.Expression) -> bool:
|
|
1032
|
-
return expr.depth <= 0 or PropagatorAILState.is_global_variable_load(expr)
|
|
1033
|
-
|
|
1034
|
-
@staticmethod
|
|
1035
|
-
def is_global_variable_load(expr: ailment.Expr.Expression) -> bool:
|
|
1036
|
-
if isinstance(expr, ailment.Expr.Load) and isinstance(expr.addr, ailment.Expr.Const):
|
|
1037
|
-
return True
|
|
1038
|
-
return bool(isinstance(expr, ailment.Expr.Convert) and PropagatorAILState.is_global_variable_load(expr.operand))
|
|
1039
|
-
|
|
1040
|
-
@staticmethod
|
|
1041
|
-
def is_expression_too_deep(expr: ailment.Expr.Expression) -> bool:
|
|
1042
|
-
# determine if the expression is too deep to propagate
|
|
1043
|
-
return expr.depth >= 30
|
|
1044
|
-
|
|
1045
|
-
@staticmethod
|
|
1046
|
-
def has_ternary_expr(expr: ailment.Expr.Expression) -> bool:
|
|
1047
|
-
class _has_ternary_expr:
|
|
1048
|
-
"""
|
|
1049
|
-
Temporary class holding values.
|
|
1050
|
-
"""
|
|
1051
|
-
|
|
1052
|
-
v = False
|
|
1053
|
-
|
|
1054
|
-
def _handle_ITE(*args, **kwargs): # pylint:disable=unused-argument
|
|
1055
|
-
_has_ternary_expr.v = True
|
|
1056
|
-
|
|
1057
|
-
walker = ailment.AILBlockWalkerBase()
|
|
1058
|
-
walker.expr_handlers[ailment.Expr.ITE] = _handle_ITE
|
|
1059
|
-
walker.walk_expression(expr, 0, None, None)
|
|
1060
|
-
return _has_ternary_expr.v
|
|
@@ -915,7 +915,7 @@ class VariableManagerInternal(Serializable):
|
|
|
915
915
|
# rename variables in a fixed order
|
|
916
916
|
var_ctr = count(0)
|
|
917
917
|
|
|
918
|
-
sorted_stack_variables = sorted(sorted_stack_variables, key=lambda v: v.offset)
|
|
918
|
+
sorted_stack_variables = sorted(sorted_stack_variables, key=lambda v: (v.offset, v.ident))
|
|
919
919
|
sorted_reg_variables = sorted(sorted_reg_variables, key=lambda v: _id_from_varident(v.ident))
|
|
920
920
|
|
|
921
921
|
# find variables that are likely only used by phi assignments
|
|
@@ -1033,7 +1033,7 @@ class VariableManagerInternal(Serializable):
|
|
|
1033
1033
|
Map SSA variables to a unified variable. Fill in self._unified_variables.
|
|
1034
1034
|
"""
|
|
1035
1035
|
|
|
1036
|
-
stack_vars:
|
|
1036
|
+
stack_vars: set[SimStackVariable] = set()
|
|
1037
1037
|
reg_vars: set[SimRegisterVariable] = set()
|
|
1038
1038
|
|
|
1039
1039
|
# unify stack variables based on their locations
|
|
@@ -1042,19 +1042,14 @@ class VariableManagerInternal(Serializable):
|
|
|
1042
1042
|
# do not unify twice
|
|
1043
1043
|
continue
|
|
1044
1044
|
if isinstance(v, SimStackVariable):
|
|
1045
|
-
stack_vars
|
|
1045
|
+
stack_vars.add(v)
|
|
1046
1046
|
elif isinstance(v, SimRegisterVariable):
|
|
1047
1047
|
reg_vars.add(v)
|
|
1048
1048
|
|
|
1049
|
-
for _, vs in stack_vars.items():
|
|
1050
|
-
unified = vs[0].copy()
|
|
1051
|
-
for v in vs:
|
|
1052
|
-
self.set_unified_variable(v, unified)
|
|
1053
|
-
|
|
1054
1049
|
# unify register variables based on phi nodes
|
|
1055
1050
|
graph = networkx.DiGraph() # an edge v1 -> v2 means v2 is the phi variable for v1
|
|
1056
1051
|
for v, subvs in self._phi_variables.items():
|
|
1057
|
-
if not isinstance(v, SimRegisterVariable):
|
|
1052
|
+
if not isinstance(v, (SimRegisterVariable, SimStackVariable)):
|
|
1058
1053
|
continue
|
|
1059
1054
|
for subv in subvs:
|
|
1060
1055
|
graph.add_edge(subv, v)
|
|
@@ -1086,10 +1081,21 @@ class VariableManagerInternal(Serializable):
|
|
|
1086
1081
|
self.set_unified_variable(v, unified)
|
|
1087
1082
|
for v in nodes:
|
|
1088
1083
|
reg_vars.discard(v)
|
|
1084
|
+
stack_vars.discard(v)
|
|
1089
1085
|
|
|
1090
|
-
|
|
1086
|
+
# deal with remaining variables
|
|
1087
|
+
for v in sorted(reg_vars, key=lambda v: v.ident):
|
|
1091
1088
|
self.set_unified_variable(v, v)
|
|
1092
1089
|
|
|
1090
|
+
stack_vars_by_offset: dict[int, list[SimStackVariable]] = defaultdict(list)
|
|
1091
|
+
for v in stack_vars:
|
|
1092
|
+
stack_vars_by_offset[v.offset].append(v)
|
|
1093
|
+
for vs in stack_vars_by_offset.values():
|
|
1094
|
+
vs = sorted(vs, key=lambda v: v.ident)
|
|
1095
|
+
unified = vs[0].copy()
|
|
1096
|
+
for v in vs:
|
|
1097
|
+
self.set_unified_variable(v, unified)
|
|
1098
|
+
|
|
1093
1099
|
def set_unified_variable(self, variable: SimVariable, unified: SimVariable) -> None:
|
|
1094
1100
|
"""
|
|
1095
1101
|
Set the unified variable for a given SSA variable.
|
angr/lib/angr_native.dll
CHANGED
|
Binary file
|