angr 9.2.135__py3-none-macosx_11_0_arm64.whl → 9.2.137__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/__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.dylib +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
|
@@ -263,7 +263,7 @@ class ITERegionConverter(OptimizationPass):
|
|
|
263
263
|
|
|
264
264
|
# is this the statement that we are looking for?
|
|
265
265
|
found_true_src_vvar, found_false_src_vvar = False, False
|
|
266
|
-
for
|
|
266
|
+
for _src, vvar in stmt.src.src_and_vvars:
|
|
267
267
|
if vvar is not None:
|
|
268
268
|
if vvar.varid == true_stmt_dst.varid:
|
|
269
269
|
found_true_src_vvar = True
|
|
@@ -557,7 +557,7 @@ class LoweredSwitchSimplifier(StructuringOptimizationPass):
|
|
|
557
557
|
varhash_to_caselists[v].append((cases, extra_cmp_nodes))
|
|
558
558
|
|
|
559
559
|
for v, caselists in list(varhash_to_caselists.items()):
|
|
560
|
-
for idx, (cases,
|
|
560
|
+
for idx, (cases, _redundant_nodes) in list(enumerate(caselists)):
|
|
561
561
|
# filter: each case value should only appear once
|
|
562
562
|
if len({case.value for case in cases}) != len(cases):
|
|
563
563
|
caselists[idx] = None
|
|
@@ -571,8 +571,7 @@ class ReturnDuplicatorBase:
|
|
|
571
571
|
new_name = stmt.name if stmt.name else f"Label_{stmt.ins_addr:x}"
|
|
572
572
|
if stmt.block_idx is not None:
|
|
573
573
|
suffix = f"__{stmt.block_idx}"
|
|
574
|
-
|
|
575
|
-
new_name = new_name[: -len(suffix)]
|
|
574
|
+
new_name = new_name.removesuffix(suffix)
|
|
576
575
|
else:
|
|
577
576
|
new_name = stmt.name
|
|
578
577
|
new_name += f"__{block.idx}"
|
|
@@ -144,7 +144,7 @@ class StackCanarySimplifier(OptimizationPass):
|
|
|
144
144
|
nodes_to_process.append((pred, canary_check_stmt_idx, stack_chk_fail_caller, ret_node))
|
|
145
145
|
|
|
146
146
|
# Awesome. Now patch this function.
|
|
147
|
-
for pred,
|
|
147
|
+
for pred, _canary_check_stmt_idx, stack_chk_fail_caller, ret_node in nodes_to_process:
|
|
148
148
|
# Patch the pred so that it jumps to the one that is not stack_chk_fail_caller
|
|
149
149
|
pred_copy = pred.copy()
|
|
150
150
|
pred_copy.statements[-1] = ailment.Stmt.Jump(
|
|
@@ -204,13 +204,17 @@ class SequenceWalker:
|
|
|
204
204
|
|
|
205
205
|
new_false_node = self._handle(node.false_node, parent=node, index=1) if node.false_node is not None else None
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
new_condition = (
|
|
208
|
+
self._handle(node.condition, parent=node, label="condition") if node.condition is not None else None
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
if new_true_node is None and new_false_node is None and new_condition is None:
|
|
208
212
|
return None
|
|
209
213
|
|
|
210
214
|
return ConditionNode(
|
|
211
215
|
node.addr,
|
|
212
216
|
node.reaching_condition,
|
|
213
|
-
node.condition,
|
|
217
|
+
node.condition if new_condition is None else new_condition,
|
|
214
218
|
node.true_node if new_true_node is None else new_true_node,
|
|
215
219
|
false_node=node.false_node if new_false_node is None else new_false_node,
|
|
216
220
|
)
|
|
@@ -40,6 +40,7 @@ class RewritingAnalysis(ForwardAnalysis[RewritingState, NodeType, object, object
|
|
|
40
40
|
stackvar_locs: dict[int, int],
|
|
41
41
|
rewrite_tmps: bool,
|
|
42
42
|
ail_manager,
|
|
43
|
+
func_args: set[VirtualVariable],
|
|
43
44
|
vvar_id_start: int = 0,
|
|
44
45
|
):
|
|
45
46
|
self.project = project
|
|
@@ -55,6 +56,7 @@ class RewritingAnalysis(ForwardAnalysis[RewritingState, NodeType, object, object
|
|
|
55
56
|
self._stackvar_locs = stackvar_locs
|
|
56
57
|
self._rewrite_tmps = rewrite_tmps
|
|
57
58
|
self._ail_manager = ail_manager
|
|
59
|
+
self._func_args = func_args
|
|
58
60
|
self._engine_ail = SimEngineSSARewriting(
|
|
59
61
|
self.project,
|
|
60
62
|
sp_tracker=sp_tracker,
|
|
@@ -205,12 +207,20 @@ class RewritingAnalysis(ForwardAnalysis[RewritingState, NodeType, object, object
|
|
|
205
207
|
self.insert_phi_statements(node, phi_stmts)
|
|
206
208
|
|
|
207
209
|
def _initial_abstract_state(self, node) -> RewritingState:
|
|
208
|
-
|
|
210
|
+
state = RewritingState(
|
|
209
211
|
CodeLocation(node.addr, stmt_idx=0, ins_addr=node.addr, block_idx=node.idx),
|
|
210
212
|
self.project.arch,
|
|
211
213
|
self._function,
|
|
212
214
|
node,
|
|
213
215
|
)
|
|
216
|
+
# update state with function arguments
|
|
217
|
+
for func_arg in self._func_args:
|
|
218
|
+
if func_arg.oident[0] == VirtualVariableCategory.REGISTER:
|
|
219
|
+
reg_offset, reg_size = func_arg.oident[1], func_arg.size
|
|
220
|
+
state.registers[reg_offset][reg_size] = func_arg
|
|
221
|
+
elif func_arg.oident[0] == VirtualVariableCategory.STACK:
|
|
222
|
+
state.stackvars[func_arg.oident[1]][func_arg.size] = func_arg
|
|
223
|
+
return state
|
|
214
224
|
|
|
215
225
|
def _run_on_node(self, node, state: RewritingState):
|
|
216
226
|
"""
|
|
@@ -462,7 +462,7 @@ class SimEngineSSARewriting(
|
|
|
462
462
|
base_mask = Const(self.ail_manager.next_atom(), None, base_mask, existing_vvar.bits)
|
|
463
463
|
new_base_expr = BinaryOp(
|
|
464
464
|
self.ail_manager.next_atom(),
|
|
465
|
-
"
|
|
465
|
+
"And",
|
|
466
466
|
[existing_vvar, base_mask],
|
|
467
467
|
False,
|
|
468
468
|
bits=existing_vvar.bits,
|
|
@@ -618,6 +618,15 @@ class SimEngineSSARewriting(
|
|
|
618
618
|
):
|
|
619
619
|
vvar = self.state.registers[reg_expr.reg_offset][reg_expr.size]
|
|
620
620
|
assert vvar is not None
|
|
621
|
+
if vvar.category == VirtualVariableCategory.PARAMETER:
|
|
622
|
+
return VirtualVariable(
|
|
623
|
+
reg_expr.idx,
|
|
624
|
+
vvar.varid,
|
|
625
|
+
vvar.bits,
|
|
626
|
+
VirtualVariableCategory.PARAMETER,
|
|
627
|
+
oident=vvar.oident,
|
|
628
|
+
**vvar.tags,
|
|
629
|
+
)
|
|
621
630
|
return VirtualVariable(
|
|
622
631
|
reg_expr.idx,
|
|
623
632
|
vvar.varid,
|
|
@@ -640,6 +649,20 @@ class SimEngineSSARewriting(
|
|
|
640
649
|
vvar,
|
|
641
650
|
**reg_expr.tags,
|
|
642
651
|
)
|
|
652
|
+
elif reg_expr.size > existing_size:
|
|
653
|
+
# part of the variable exists... maybe it's a parameter?
|
|
654
|
+
vvar = self.state.registers[reg_expr.reg_offset][existing_size]
|
|
655
|
+
if vvar.category == VirtualVariableCategory.PARAMETER:
|
|
656
|
+
# just zero-extend it
|
|
657
|
+
return Convert(
|
|
658
|
+
self.ail_manager.next_atom(),
|
|
659
|
+
existing_size * self.project.arch.byte_width,
|
|
660
|
+
reg_expr.size * self.project.arch.byte_width,
|
|
661
|
+
False,
|
|
662
|
+
vvar,
|
|
663
|
+
**vvar.tags,
|
|
664
|
+
)
|
|
665
|
+
break
|
|
643
666
|
else:
|
|
644
667
|
break
|
|
645
668
|
|
|
@@ -651,24 +674,29 @@ class SimEngineSSARewriting(
|
|
|
651
674
|
ins_addr=reg_expr.ins_addr,
|
|
652
675
|
)
|
|
653
676
|
# extract
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
677
|
+
if reg_expr.reg_offset == vvar.oident:
|
|
678
|
+
shifted = vvar
|
|
679
|
+
else:
|
|
680
|
+
shift_amount = Const(
|
|
681
|
+
self.ail_manager.next_atom(),
|
|
682
|
+
None,
|
|
683
|
+
(reg_expr.reg_offset - vvar.oident) * self.arch.byte_width,
|
|
684
|
+
8,
|
|
685
|
+
**reg_expr.tags,
|
|
686
|
+
)
|
|
687
|
+
shifted = BinaryOp(
|
|
688
|
+
self.ail_manager.next_atom(),
|
|
689
|
+
"Shr",
|
|
690
|
+
[
|
|
691
|
+
vvar,
|
|
692
|
+
shift_amount,
|
|
693
|
+
],
|
|
694
|
+
False,
|
|
695
|
+
bits=vvar.bits,
|
|
696
|
+
**reg_expr.tags,
|
|
697
|
+
)
|
|
698
|
+
if shifted.bits == reg_expr.bits:
|
|
699
|
+
return shifted
|
|
672
700
|
return Convert(
|
|
673
701
|
self.ail_manager.next_atom(),
|
|
674
702
|
shifted.bits,
|
|
@@ -700,6 +728,15 @@ class SimEngineSSARewriting(
|
|
|
700
728
|
# TODO: Support truncation
|
|
701
729
|
# TODO: Maybe also support concatenation
|
|
702
730
|
vvar = self.state.stackvars[expr.addr.offset][expr.size]
|
|
731
|
+
if vvar.category == VirtualVariableCategory.PARAMETER:
|
|
732
|
+
return VirtualVariable(
|
|
733
|
+
expr.idx,
|
|
734
|
+
vvar.varid,
|
|
735
|
+
vvar.bits,
|
|
736
|
+
VirtualVariableCategory.PARAMETER,
|
|
737
|
+
oident=vvar.oident,
|
|
738
|
+
**vvar.tags,
|
|
739
|
+
)
|
|
703
740
|
return VirtualVariable(
|
|
704
741
|
expr.idx,
|
|
705
742
|
vvar.varid,
|
|
@@ -5,7 +5,7 @@ from collections import defaultdict
|
|
|
5
5
|
from itertools import count
|
|
6
6
|
from bisect import bisect_left
|
|
7
7
|
|
|
8
|
-
from ailment.expression import Expression, Register, StackBaseOffset, Tmp
|
|
8
|
+
from ailment.expression import Expression, Register, StackBaseOffset, Tmp, VirtualVariable, VirtualVariableCategory
|
|
9
9
|
from ailment.statement import Statement, Store
|
|
10
10
|
|
|
11
11
|
from angr.knowledge_plugins.functions import Function
|
|
@@ -34,6 +34,7 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
34
34
|
ail_manager=None,
|
|
35
35
|
ssa_stackvars: bool = False,
|
|
36
36
|
ssa_tmps: bool = False,
|
|
37
|
+
func_args: set[VirtualVariable] | None = None,
|
|
37
38
|
vvar_id_start: int = 0,
|
|
38
39
|
):
|
|
39
40
|
"""
|
|
@@ -53,6 +54,7 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
53
54
|
self._ail_manager = ail_manager
|
|
54
55
|
self._ssa_stackvars = ssa_stackvars
|
|
55
56
|
self._ssa_tmps = ssa_tmps
|
|
57
|
+
self._func_args = func_args if func_args is not None else set()
|
|
56
58
|
self._entry = (
|
|
57
59
|
entry
|
|
58
60
|
if entry is not None
|
|
@@ -71,6 +73,7 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
71
73
|
bp_as_gpr,
|
|
72
74
|
ssa_stackvars,
|
|
73
75
|
ssa_tmps,
|
|
76
|
+
self._func_args,
|
|
74
77
|
)
|
|
75
78
|
|
|
76
79
|
# calculate virtual variables and phi nodes
|
|
@@ -91,6 +94,7 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
91
94
|
self._stackvar_locs,
|
|
92
95
|
self._ssa_tmps,
|
|
93
96
|
self._ail_manager,
|
|
97
|
+
self._func_args,
|
|
94
98
|
vvar_id_start=vvar_id_start,
|
|
95
99
|
)
|
|
96
100
|
self.out_graph = rewriter.out_graph
|
|
@@ -122,6 +126,11 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
122
126
|
# for stack variables, we collect all definitions and identify stack variable locations using heuristics
|
|
123
127
|
|
|
124
128
|
stackvar_locs = self._synthesize_stackvar_locs([def_ for def_, _ in def_to_loc if isinstance(def_, Store)])
|
|
129
|
+
# handle function arguments
|
|
130
|
+
if self._func_args:
|
|
131
|
+
for func_arg in self._func_args:
|
|
132
|
+
if func_arg.oident[0] == VirtualVariableCategory.STACK:
|
|
133
|
+
stackvar_locs[func_arg.oident[1]] = func_arg.size
|
|
125
134
|
sorted_stackvar_offs = sorted(stackvar_locs)
|
|
126
135
|
else:
|
|
127
136
|
stackvar_locs = {}
|
|
@@ -137,9 +146,10 @@ class Ssailification(Analysis): # pylint:disable=abstract-method
|
|
|
137
146
|
udef_to_defs[("reg", base_off, base_reg_bits)].add(def_)
|
|
138
147
|
udef_to_blockkeys[("reg", base_off, base_reg_bits)].add((loc.block_addr, loc.block_idx))
|
|
139
148
|
# add a definition for the partial register
|
|
140
|
-
if base_off != def_.reg_offset:
|
|
149
|
+
if base_off != def_.reg_offset or base_size != def_.size:
|
|
141
150
|
reg_bits = def_.size * self.project.arch.byte_width
|
|
142
|
-
udef_to_defs[("reg", def_.reg_offset, reg_bits)].add(
|
|
151
|
+
udef_to_defs[("reg", def_.reg_offset, reg_bits)].add(def_)
|
|
152
|
+
udef_to_blockkeys[("reg", def_.reg_offset, reg_bits)].add((loc.block_addr, loc.block_idx))
|
|
143
153
|
elif isinstance(def_, Store):
|
|
144
154
|
if isinstance(def_.addr, StackBaseOffset) and isinstance(def_.addr.offset, int):
|
|
145
155
|
idx_begin = bisect_left(sorted_stackvar_offs, def_.addr.offset)
|
|
@@ -17,13 +17,24 @@ class TraversalAnalysis(ForwardAnalysis[TraversalState, ailment.Block, object, t
|
|
|
17
17
|
TraversalAnalysis traverses the AIL graph and collects definitions.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
def __init__(
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
project,
|
|
23
|
+
func,
|
|
24
|
+
ail_graph,
|
|
25
|
+
sp_tracker,
|
|
26
|
+
bp_as_gpr: bool,
|
|
27
|
+
stackvars: bool,
|
|
28
|
+
tmps: bool,
|
|
29
|
+
func_args: set[ailment.Expr.VirtualVariable],
|
|
30
|
+
):
|
|
21
31
|
|
|
22
32
|
self.project = project
|
|
23
33
|
self._stackvars = stackvars
|
|
24
34
|
self._tmps = tmps
|
|
25
35
|
self._function = func
|
|
26
36
|
self._graph_visitor = FunctionGraphVisitor(self._function, ail_graph)
|
|
37
|
+
self._func_args = func_args
|
|
27
38
|
|
|
28
39
|
ForwardAnalysis.__init__(
|
|
29
40
|
self, order_jobs=True, allow_merging=True, allow_widening=False, graph_visitor=self._graph_visitor
|
|
@@ -52,13 +63,28 @@ class TraversalAnalysis(ForwardAnalysis[TraversalState, ailment.Block, object, t
|
|
|
52
63
|
pass
|
|
53
64
|
|
|
54
65
|
def _initial_abstract_state(self, node: ailment.Block) -> TraversalState:
|
|
55
|
-
|
|
66
|
+
state = TraversalState(self.project.arch, self._function)
|
|
67
|
+
# update it with function arguments
|
|
68
|
+
if self._func_args:
|
|
69
|
+
for func_arg in self._func_args:
|
|
70
|
+
if func_arg.oident[0] == ailment.Expr.VirtualVariableCategory.REGISTER:
|
|
71
|
+
reg_offset = func_arg.oident[1]
|
|
72
|
+
reg_size = func_arg.size
|
|
73
|
+
state.live_registers.add(reg_offset)
|
|
74
|
+
# get the full register if needed
|
|
75
|
+
basereg_offset, basereg_size = self.project.arch.get_base_register(reg_offset, size=reg_size)
|
|
76
|
+
if basereg_size != reg_size or basereg_offset != reg_offset:
|
|
77
|
+
state.live_registers.add(basereg_offset)
|
|
78
|
+
elif func_arg.oident[0] == ailment.Expr.VirtualVariableCategory.STACK:
|
|
79
|
+
state.live_stackvars.add((func_arg.oident[1], func_arg.size))
|
|
80
|
+
return state
|
|
56
81
|
|
|
57
82
|
def _merge_states(self, node: ailment.Block, *states: TraversalState) -> tuple[TraversalState, bool]:
|
|
58
83
|
merged_state = TraversalState(
|
|
59
84
|
self.project.arch,
|
|
60
85
|
self._function,
|
|
61
86
|
live_registers=states[0].live_registers.copy(),
|
|
87
|
+
live_stackvars=states[0].live_stackvars.copy(),
|
|
62
88
|
)
|
|
63
89
|
merge_occurred = merged_state.merge(*states[1:])
|
|
64
90
|
return merged_state, not merge_occurred
|
|
@@ -37,7 +37,12 @@ class TraversalState:
|
|
|
37
37
|
merge_occurred = True
|
|
38
38
|
all_regs |= o.live_registers
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
all_stackvars: set[tuple[int, int]] = self.live_stackvars.copy()
|
|
41
|
+
for o in others:
|
|
42
|
+
if o.live_stackvars.difference(all_stackvars):
|
|
43
|
+
merge_occurred = True
|
|
44
|
+
all_stackvars |= o.live_stackvars
|
|
41
45
|
|
|
42
46
|
self.live_registers = all_regs
|
|
47
|
+
self.live_stackvars = all_stackvars
|
|
43
48
|
return merge_occurred
|
|
@@ -679,14 +679,23 @@ class CStatements(CStatement):
|
|
|
679
679
|
Represents a sequence of statements in C.
|
|
680
680
|
"""
|
|
681
681
|
|
|
682
|
-
__slots__ = (
|
|
682
|
+
__slots__ = (
|
|
683
|
+
"addr",
|
|
684
|
+
"statements",
|
|
685
|
+
)
|
|
683
686
|
|
|
684
|
-
def __init__(self, statements, **kwargs):
|
|
687
|
+
def __init__(self, statements, addr=None, **kwargs):
|
|
685
688
|
super().__init__(**kwargs)
|
|
686
689
|
|
|
687
690
|
self.statements = statements
|
|
691
|
+
self.addr = addr
|
|
688
692
|
|
|
689
693
|
def c_repr_chunks(self, indent=0, asexpr=False):
|
|
694
|
+
indent_str = self.indent_str(indent)
|
|
695
|
+
if self.codegen.display_block_addrs:
|
|
696
|
+
yield indent_str, None
|
|
697
|
+
yield f"/* Block {hex(self.addr) if self.addr is not None else 'unknown'} */", None
|
|
698
|
+
yield "\n", None
|
|
690
699
|
for stmt in self.statements:
|
|
691
700
|
yield from stmt.c_repr_chunks(indent=indent, asexpr=asexpr)
|
|
692
701
|
if asexpr:
|
|
@@ -1572,15 +1581,19 @@ class CVariable(CExpression):
|
|
|
1572
1581
|
"unified_variable",
|
|
1573
1582
|
"variable",
|
|
1574
1583
|
"variable_type",
|
|
1584
|
+
"vvar_id",
|
|
1575
1585
|
)
|
|
1576
1586
|
|
|
1577
|
-
def __init__(
|
|
1587
|
+
def __init__(
|
|
1588
|
+
self, variable: SimVariable, unified_variable=None, variable_type=None, tags=None, vvar_id=None, **kwargs
|
|
1589
|
+
):
|
|
1578
1590
|
super().__init__(**kwargs)
|
|
1579
1591
|
|
|
1580
1592
|
self.variable: SimVariable = variable
|
|
1581
1593
|
self.unified_variable: SimVariable | None = unified_variable
|
|
1582
1594
|
self.variable_type: SimType = variable_type.with_arch(self.codegen.project.arch)
|
|
1583
1595
|
self.tags = tags
|
|
1596
|
+
self.vvar_id = vvar_id
|
|
1584
1597
|
|
|
1585
1598
|
@property
|
|
1586
1599
|
def type(self):
|
|
@@ -1598,6 +1611,8 @@ class CVariable(CExpression):
|
|
|
1598
1611
|
|
|
1599
1612
|
def c_repr_chunks(self, indent=0, asexpr=False):
|
|
1600
1613
|
yield self.name, self
|
|
1614
|
+
if self.codegen.display_vvar_ids:
|
|
1615
|
+
yield f"<vvar_{self.vvar_id}>", self
|
|
1601
1616
|
|
|
1602
1617
|
|
|
1603
1618
|
class CIndexedVariable(CExpression):
|
|
@@ -2141,7 +2156,8 @@ class CConstant(CExpression):
|
|
|
2141
2156
|
result = self.fmt.get("neg", None)
|
|
2142
2157
|
if result is None:
|
|
2143
2158
|
result = False
|
|
2144
|
-
|
|
2159
|
+
# guess it
|
|
2160
|
+
if isinstance(self._type, (SimTypeInt, SimTypeChar)) and self._type.signed and isinstance(self.value, int):
|
|
2145
2161
|
value_size = self._type.size if self._type is not None else None
|
|
2146
2162
|
if (value_size == 32 and 0xF000_0000 <= self.value <= 0xFFFF_FFFF) or (
|
|
2147
2163
|
value_size == 64 and 0xF000_0000_0000_0000 <= self.value <= 0xFFFF_FFFF_FFFF_FFFF
|
|
@@ -2486,6 +2502,8 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2486
2502
|
simplify_else_scope=True,
|
|
2487
2503
|
cstyle_ifs=True,
|
|
2488
2504
|
omit_func_header=False,
|
|
2505
|
+
display_block_addrs=False,
|
|
2506
|
+
display_vvar_ids=False,
|
|
2489
2507
|
):
|
|
2490
2508
|
super().__init__(flavor=flavor)
|
|
2491
2509
|
|
|
@@ -2558,6 +2576,8 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2558
2576
|
self.simplify_else_scope = simplify_else_scope
|
|
2559
2577
|
self.cstyle_ifs = cstyle_ifs
|
|
2560
2578
|
self.omit_func_header = omit_func_header
|
|
2579
|
+
self.display_block_addrs = display_block_addrs
|
|
2580
|
+
self.display_vvar_ids = display_vvar_ids
|
|
2561
2581
|
self.text = None
|
|
2562
2582
|
self.map_pos_to_node = None
|
|
2563
2583
|
self.map_pos_to_addr = None
|
|
@@ -2740,7 +2760,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2740
2760
|
return _mapping.get(n)(signed=signed).with_arch(self.project.arch)
|
|
2741
2761
|
return SimTypeNum(n, signed=signed).with_arch(self.project.arch)
|
|
2742
2762
|
|
|
2743
|
-
def _variable(self, variable: SimVariable, fallback_type_size: int | None) -> CVariable:
|
|
2763
|
+
def _variable(self, variable: SimVariable, fallback_type_size: int | None, vvar_id: int | None = None) -> CVariable:
|
|
2744
2764
|
# TODO: we need to fucking make sure that variable recovery and type inference actually generates a size
|
|
2745
2765
|
# TODO: for each variable it links into the fucking ail. then we can remove fallback_type_size.
|
|
2746
2766
|
unified = self._variable_kb.variables[self._func.addr].unified_variable(variable)
|
|
@@ -2751,7 +2771,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2751
2771
|
variable_type = self.default_simtype_from_bits(
|
|
2752
2772
|
(fallback_type_size or self.project.arch.bytes) * self.project.arch.byte_width
|
|
2753
2773
|
)
|
|
2754
|
-
cvar = CVariable(variable, unified_variable=unified, variable_type=variable_type, codegen=self)
|
|
2774
|
+
cvar = CVariable(variable, unified_variable=unified, variable_type=variable_type, codegen=self, vvar_id=vvar_id)
|
|
2755
2775
|
self._variables_in_use[variable] = cvar
|
|
2756
2776
|
return cvar
|
|
2757
2777
|
|
|
@@ -3106,14 +3126,18 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3106
3126
|
# Handlers
|
|
3107
3127
|
#
|
|
3108
3128
|
|
|
3109
|
-
def _handle(self, node, is_expr: bool = True, lvalue: bool = False):
|
|
3129
|
+
def _handle(self, node, is_expr: bool = True, lvalue: bool = False, likely_signed=False):
|
|
3110
3130
|
if (node, is_expr) in self.ailexpr2cnode:
|
|
3111
3131
|
return self.ailexpr2cnode[(node, is_expr)]
|
|
3112
3132
|
|
|
3113
3133
|
handler: Callable | None = self._handlers.get(node.__class__, None)
|
|
3114
3134
|
if handler is not None:
|
|
3115
3135
|
# special case for Call
|
|
3116
|
-
converted =
|
|
3136
|
+
converted = (
|
|
3137
|
+
handler(node, is_expr=is_expr)
|
|
3138
|
+
if isinstance(node, Stmt.Call)
|
|
3139
|
+
else handler(node, lvalue=lvalue, likely_signed=likely_signed)
|
|
3140
|
+
)
|
|
3117
3141
|
self.ailexpr2cnode[(node, is_expr)] = converted
|
|
3118
3142
|
return converted
|
|
3119
3143
|
raise UnsupportedNodeTypeError(f"Node type {type(node)} is not supported yet.")
|
|
@@ -3127,10 +3151,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3127
3151
|
for node in seq.nodes:
|
|
3128
3152
|
lines.append(self._handle(node, is_expr=False))
|
|
3129
3153
|
|
|
3130
|
-
if
|
|
3131
|
-
return CStatements([], codegen=None)
|
|
3132
|
-
|
|
3133
|
-
return CStatements(lines, codegen=self) if len(lines) > 1 else lines[0]
|
|
3154
|
+
return lines[0] if len(lines) == 1 else CStatements(lines, codegen=self, addr=seq.addr)
|
|
3134
3155
|
|
|
3135
3156
|
def _handle_Loop(self, loop_node, **kwargs):
|
|
3136
3157
|
tags = {"ins_addr": loop_node.addr}
|
|
@@ -3217,7 +3238,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3217
3238
|
r = self._handle(n, is_expr=False)
|
|
3218
3239
|
lines.append(r)
|
|
3219
3240
|
|
|
3220
|
-
return
|
|
3241
|
+
return lines[0] if len(lines) == 1 else CStatements(lines, codegen=self, addr=node.addr)
|
|
3221
3242
|
|
|
3222
3243
|
def _handle_SwitchCase(self, node, **kwargs):
|
|
3223
3244
|
"""
|
|
@@ -3260,7 +3281,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3260
3281
|
cstmt = CUnsupportedStatement(stmt, codegen=self)
|
|
3261
3282
|
cstmts.append(cstmt)
|
|
3262
3283
|
|
|
3263
|
-
return CStatements(cstmts, codegen=self)
|
|
3284
|
+
return CStatements(cstmts, codegen=self, addr=node.addr)
|
|
3264
3285
|
|
|
3265
3286
|
#
|
|
3266
3287
|
# AIL statement handlers
|
|
@@ -3315,9 +3336,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3315
3336
|
if stmt.dst.variable is not None:
|
|
3316
3337
|
if "struct_member_info" in stmt.dst.tags:
|
|
3317
3338
|
offset, var, _ = stmt.dst.struct_member_info
|
|
3318
|
-
cvar = self._variable(var, stmt.dst.size)
|
|
3339
|
+
cvar = self._variable(var, stmt.dst.size, vvar_id=stmt.dst.varid)
|
|
3319
3340
|
else:
|
|
3320
|
-
cvar = self._variable(stmt.dst.variable, stmt.dst.size)
|
|
3341
|
+
cvar = self._variable(stmt.dst.variable, stmt.dst.size, vvar_id=stmt.dst.varid)
|
|
3321
3342
|
offset = stmt.dst.variable_offset or 0
|
|
3322
3343
|
assert type(offset) is int # I refuse to deal with the alternative
|
|
3323
3344
|
|
|
@@ -3474,7 +3495,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3474
3495
|
l.warning("FIXME: Leftover Tmp expressions are found.")
|
|
3475
3496
|
return self._variable(SimTemporaryVariable(expr.tmp_idx, expr.bits), expr.size)
|
|
3476
3497
|
|
|
3477
|
-
def _handle_Expr_Const(
|
|
3498
|
+
def _handle_Expr_Const(
|
|
3499
|
+
self, expr: Expr.Const, type_=None, reference_values=None, variable=None, likely_signed=True, **kwargs
|
|
3500
|
+
):
|
|
3478
3501
|
inline_string = False
|
|
3479
3502
|
function_pointer = False
|
|
3480
3503
|
|
|
@@ -3550,8 +3573,8 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3550
3573
|
inline_string = True
|
|
3551
3574
|
|
|
3552
3575
|
if type_ is None:
|
|
3553
|
-
# default to int
|
|
3554
|
-
type_ = self.default_simtype_from_bits(expr.bits)
|
|
3576
|
+
# default to int or unsigned int, determined by likely_signed
|
|
3577
|
+
type_ = self.default_simtype_from_bits(expr.bits, signed=likely_signed)
|
|
3555
3578
|
|
|
3556
3579
|
if variable is None and hasattr(expr, "reference_variable") and expr.reference_variable is not None:
|
|
3557
3580
|
variable = expr.reference_variable
|
|
@@ -3583,7 +3606,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3583
3606
|
)
|
|
3584
3607
|
|
|
3585
3608
|
lhs = self._handle(expr.operands[0])
|
|
3586
|
-
rhs = self._handle(expr.operands[1])
|
|
3609
|
+
rhs = self._handle(expr.operands[1], likely_signed=expr.op not in {"And", "Or"})
|
|
3587
3610
|
|
|
3588
3611
|
return CBinaryOp(
|
|
3589
3612
|
expr.op,
|
|
@@ -3679,7 +3702,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3679
3702
|
|
|
3680
3703
|
def _handle_VirtualVariable(self, expr: Expr.VirtualVariable, **kwargs):
|
|
3681
3704
|
if expr.variable:
|
|
3682
|
-
cvar = self._variable(expr.variable, None)
|
|
3705
|
+
cvar = self._variable(expr.variable, None, vvar_id=expr.varid)
|
|
3683
3706
|
if expr.variable.size != expr.size:
|
|
3684
3707
|
l.warning(
|
|
3685
3708
|
"VirtualVariable size (%d) and variable size (%d) do not match. Force a type cast.",
|