angr 9.2.102__py3-none-win_amd64.whl → 9.2.103__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/analysis.py +7 -6
- angr/analyses/calling_convention.py +33 -35
- angr/analyses/cdg.py +2 -4
- angr/analyses/cfg/cfb.py +4 -3
- angr/analyses/cfg/cfg_base.py +14 -14
- angr/analyses/cfg/cfg_emulated.py +3 -4
- angr/analyses/cfg/cfg_fast.py +46 -46
- angr/analyses/cfg/cfg_fast_soot.py +1 -2
- angr/analyses/cfg/cfg_job_base.py +2 -2
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +14 -13
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +5 -5
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +3 -3
- angr/analyses/complete_calling_conventions.py +13 -12
- angr/analyses/data_dep/data_dependency_analysis.py +24 -24
- angr/analyses/data_dep/dep_nodes.py +3 -3
- angr/analyses/ddg.py +1 -2
- angr/analyses/decompiler/ail_simplifier.py +35 -34
- angr/analyses/decompiler/block_io_finder.py +20 -20
- angr/analyses/decompiler/block_similarity.py +4 -6
- angr/analyses/decompiler/block_simplifier.py +17 -16
- angr/analyses/decompiler/callsite_maker.py +25 -10
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -3
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +2 -4
- angr/analyses/decompiler/clinic.py +250 -45
- angr/analyses/decompiler/condition_processor.py +15 -8
- angr/analyses/decompiler/decompilation_cache.py +7 -7
- angr/analyses/decompiler/decompilation_options.py +4 -4
- angr/analyses/decompiler/decompiler.py +19 -15
- angr/analyses/decompiler/expression_counters.py +10 -9
- angr/analyses/decompiler/goto_manager.py +2 -4
- angr/analyses/decompiler/graph_region.py +9 -9
- angr/analyses/decompiler/jump_target_collector.py +1 -2
- angr/analyses/decompiler/optimization_passes/__init__.py +4 -3
- angr/analyses/decompiler/optimization_passes/code_motion.py +5 -6
- angr/analyses/decompiler/optimization_passes/const_derefs.py +4 -4
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +73 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +25 -3
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +6 -5
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +3 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +2 -2
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +17 -17
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +12 -13
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +25 -21
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +3 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +1 -2
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +7 -7
- angr/analyses/decompiler/optimization_passes/spilled_register_finder.py +18 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +2 -3
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -2
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/__init__.py +4 -3
- angr/analyses/decompiler/peephole_optimizations/base.py +13 -15
- angr/analyses/decompiler/peephole_optimizations/bswap.py +1 -3
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +72 -0
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +5 -10
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +3 -4
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +2 -3
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +4 -4
- angr/analyses/decompiler/redundant_label_remover.py +4 -5
- angr/analyses/decompiler/region_identifier.py +4 -5
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -2
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +19 -20
- angr/analyses/decompiler/region_simplifiers/goto.py +2 -3
- angr/analyses/decompiler/region_simplifiers/loop.py +1 -2
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -2
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +1 -3
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +19 -19
- angr/analyses/decompiler/return_maker.py +1 -2
- angr/analyses/decompiler/structured_codegen/base.py +5 -6
- angr/analyses/decompiler/structured_codegen/c.py +39 -38
- angr/analyses/decompiler/structuring/__init__.py +1 -1
- angr/analyses/decompiler/structuring/dream.py +17 -16
- angr/analyses/decompiler/structuring/phoenix.py +45 -46
- angr/analyses/decompiler/structuring/recursive_structurer.py +4 -4
- angr/analyses/decompiler/structuring/structurer_base.py +16 -15
- angr/analyses/decompiler/structuring/structurer_nodes.py +10 -9
- angr/analyses/decompiler/utils.py +17 -16
- angr/analyses/disassembly.py +7 -6
- angr/analyses/flirt.py +9 -9
- angr/analyses/forward_analysis/forward_analysis.py +15 -14
- angr/analyses/forward_analysis/visitors/function_graph.py +1 -2
- angr/analyses/forward_analysis/visitors/graph.py +16 -15
- angr/analyses/propagator/engine_ail.py +30 -26
- angr/analyses/propagator/outdated_definition_walker.py +8 -7
- angr/analyses/propagator/propagator.py +11 -13
- angr/analyses/proximity_graph.py +21 -21
- angr/analyses/reaching_definitions/__init__.py +3 -3
- angr/analyses/reaching_definitions/call_trace.py +3 -6
- angr/analyses/reaching_definitions/dep_graph.py +41 -48
- angr/analyses/reaching_definitions/engine_ail.py +11 -5
- angr/analyses/reaching_definitions/engine_vex.py +9 -8
- angr/analyses/reaching_definitions/function_handler.py +51 -34
- angr/analyses/reaching_definitions/heap_allocator.py +3 -4
- angr/analyses/reaching_definitions/rd_initializer.py +8 -8
- angr/analyses/reaching_definitions/rd_state.py +57 -58
- angr/analyses/reaching_definitions/reaching_definitions.py +18 -17
- angr/analyses/reaching_definitions/subject.py +2 -3
- angr/analyses/stack_pointer_tracker.py +15 -6
- angr/analyses/typehoon/dfa.py +4 -4
- angr/analyses/typehoon/simple_solver.py +48 -52
- angr/analyses/typehoon/translator.py +3 -6
- angr/analyses/typehoon/typeconsts.py +13 -14
- angr/analyses/typehoon/typehoon.py +9 -9
- angr/analyses/typehoon/typevars.py +18 -17
- angr/analyses/variable_recovery/engine_ail.py +5 -5
- angr/analyses/variable_recovery/engine_base.py +25 -21
- angr/analyses/variable_recovery/irsb_scanner.py +8 -9
- angr/analyses/variable_recovery/variable_recovery.py +1 -2
- angr/analyses/variable_recovery/variable_recovery_base.py +14 -13
- angr/analyses/variable_recovery/variable_recovery_fast.py +8 -8
- angr/analyses/veritesting.py +1 -2
- angr/analyses/vfg.py +57 -56
- angr/analyses/xrefs.py +1 -2
- angr/angrdb/db.py +7 -7
- angr/angrdb/serializers/kb.py +16 -13
- angr/angrdb/serializers/loader.py +1 -2
- angr/angrdb/serializers/structured_code.py +2 -2
- angr/annocfg.py +1 -2
- angr/block.py +16 -6
- angr/calling_conventions.py +27 -27
- angr/code_location.py +8 -8
- angr/codenode.py +1 -2
- angr/concretization_strategies/max.py +1 -3
- angr/distributed/server.py +1 -3
- angr/distributed/worker.py +1 -2
- angr/engines/engine.py +2 -3
- angr/engines/light/engine.py +4 -4
- angr/engines/pcode/behavior.py +20 -2
- angr/engines/pcode/emulate.py +1 -1
- angr/engines/pcode/engine.py +7 -7
- angr/engines/pcode/lifter.py +78 -77
- angr/engines/vex/claripy/ccall.py +1 -2
- angr/engines/vex/claripy/datalayer.py +1 -2
- angr/engines/vex/light/light.py +1 -2
- angr/exploration_techniques/tracer.py +4 -4
- angr/factory.py +12 -15
- angr/flirt/__init__.py +8 -8
- angr/flirt/build_sig.py +2 -3
- angr/keyed_region.py +2 -2
- angr/knowledge_base/knowledge_base.py +3 -3
- angr/knowledge_plugins/callsite_prototypes.py +4 -6
- angr/knowledge_plugins/cfg/cfg_manager.py +19 -6
- angr/knowledge_plugins/cfg/cfg_model.py +26 -27
- angr/knowledge_plugins/cfg/cfg_node.py +2 -2
- angr/knowledge_plugins/cfg/indirect_jump.py +6 -8
- angr/knowledge_plugins/cfg/memory_data.py +8 -9
- angr/knowledge_plugins/custom_strings.py +1 -3
- angr/knowledge_plugins/debug_variables.py +2 -2
- angr/knowledge_plugins/functions/function.py +21 -22
- angr/knowledge_plugins/functions/function_manager.py +5 -5
- angr/knowledge_plugins/indirect_jumps.py +1 -3
- angr/knowledge_plugins/key_definitions/atoms.py +7 -7
- angr/knowledge_plugins/key_definitions/definition.py +14 -14
- angr/knowledge_plugins/key_definitions/environment.py +5 -7
- angr/knowledge_plugins/key_definitions/heap_address.py +1 -3
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +3 -2
- angr/knowledge_plugins/key_definitions/live_definitions.py +60 -59
- angr/knowledge_plugins/key_definitions/liveness.py +16 -16
- angr/knowledge_plugins/key_definitions/rd_model.py +15 -15
- angr/knowledge_plugins/key_definitions/uses.py +11 -11
- angr/knowledge_plugins/patches.py +4 -8
- angr/knowledge_plugins/propagations/prop_value.py +10 -9
- angr/knowledge_plugins/propagations/propagation_manager.py +3 -5
- angr/knowledge_plugins/propagations/propagation_model.py +9 -9
- angr/knowledge_plugins/propagations/states.py +52 -22
- angr/knowledge_plugins/structured_code/manager.py +2 -2
- angr/knowledge_plugins/sync/sync_controller.py +3 -3
- angr/knowledge_plugins/variables/variable_access.py +4 -4
- angr/knowledge_plugins/variables/variable_manager.py +39 -39
- angr/knowledge_plugins/xrefs/xref.py +9 -11
- angr/knowledge_plugins/xrefs/xref_manager.py +3 -4
- angr/lib/angr_native.dll +0 -0
- angr/misc/ansi.py +1 -2
- angr/misc/autoimport.py +3 -3
- angr/misc/plugins.py +9 -9
- angr/procedures/definitions/__init__.py +16 -16
- angr/procedures/definitions/linux_kernel.py +1 -1
- angr/procedures/definitions/parse_win32json.py +1 -1
- angr/procedures/java_jni/__init__.py +1 -1
- angr/procedures/java_jni/array_operations.py +1 -2
- angr/procedures/java_jni/method_calls.py +1 -2
- angr/procedures/posix/inet_ntoa.py +1 -2
- angr/procedures/stubs/format_parser.py +3 -3
- angr/project.py +13 -11
- angr/sim_manager.py +12 -12
- angr/sim_procedure.py +7 -3
- angr/sim_state.py +2 -2
- angr/sim_type.py +60 -45
- angr/sim_variable.py +5 -5
- angr/simos/simos.py +1 -2
- angr/simos/userland.py +1 -2
- angr/state_plugins/callstack.py +3 -2
- angr/state_plugins/history.py +1 -2
- angr/state_plugins/solver.py +34 -34
- angr/storage/memory_mixins/__init__.py +4 -3
- angr/storage/memory_mixins/actions_mixin.py +1 -3
- angr/storage/memory_mixins/address_concretization_mixin.py +1 -3
- angr/storage/memory_mixins/convenient_mappings_mixin.py +3 -4
- angr/storage/memory_mixins/default_filler_mixin.py +1 -1
- angr/storage/memory_mixins/label_merger_mixin.py +2 -2
- angr/storage/memory_mixins/multi_value_merger_mixin.py +4 -3
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +9 -8
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +12 -11
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +8 -8
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +2 -3
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +10 -11
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +11 -10
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +18 -17
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +12 -11
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +3 -3
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +3 -2
- angr/storage/memory_mixins/regioned_memory/region_data.py +1 -2
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +2 -2
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +3 -3
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +18 -21
- angr/storage/memory_mixins/size_resolution_mixin.py +1 -2
- angr/storage/memory_mixins/symbolic_merger_mixin.py +3 -2
- angr/storage/memory_mixins/top_merger_mixin.py +3 -2
- angr/storage/memory_object.py +2 -4
- angr/utils/algo.py +3 -2
- angr/utils/dynamic_dictlist.py +5 -5
- angr/utils/formatting.py +4 -4
- angr/utils/funcid.py +1 -2
- angr/utils/graph.py +5 -6
- angr/utils/library.py +5 -5
- angr/utils/mp.py +5 -4
- angr/utils/segment_list.py +3 -4
- angr/utils/typing.py +3 -2
- {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
- {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/RECORD +240 -237
- {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
- {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
- {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
- {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import math
|
|
5
|
-
from typing import Optional,
|
|
5
|
+
from typing import Optional, Union, TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from networkx import DiGraph
|
|
8
8
|
|
|
@@ -54,9 +54,9 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
54
54
|
def __init__(
|
|
55
55
|
self,
|
|
56
56
|
end_state: "SimState",
|
|
57
|
-
start_from:
|
|
58
|
-
end_at:
|
|
59
|
-
block_addrs:
|
|
57
|
+
start_from: int | None = None,
|
|
58
|
+
end_at: int | None = None,
|
|
59
|
+
block_addrs: list[int] | None = None,
|
|
60
60
|
):
|
|
61
61
|
"""
|
|
62
62
|
:param end_state: Simulation state used to extract all SimActionData
|
|
@@ -64,9 +64,9 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
64
64
|
:param end_at: An address or None, Specifies where to end generation of DDG
|
|
65
65
|
:param iterable or None block_addrs: List of block addresses that the DDG analysis should be run on
|
|
66
66
|
"""
|
|
67
|
-
self._graph:
|
|
68
|
-
self._simplified_graph:
|
|
69
|
-
self._sub_graph:
|
|
67
|
+
self._graph: DiGraph | None = None
|
|
68
|
+
self._simplified_graph: DiGraph | None = None
|
|
69
|
+
self._sub_graph: DiGraph | None = None
|
|
70
70
|
|
|
71
71
|
self._end_state = end_state
|
|
72
72
|
self._start_from = start_from if start_from else self.project.entry
|
|
@@ -77,12 +77,12 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
77
77
|
self._register_file.set_state(self._end_state)
|
|
78
78
|
self._memory_map = DefaultMemory(memory_id="mem") # Tracks the current state of all parsed memory addresses
|
|
79
79
|
self._memory_map.set_state(self._end_state)
|
|
80
|
-
self._tmp_nodes:
|
|
81
|
-
self._constant_nodes:
|
|
82
|
-
self._actions:
|
|
80
|
+
self._tmp_nodes: dict[str, TmpDepNode] = {} # Per-block: Maps temp name to its current node
|
|
81
|
+
self._constant_nodes: dict[int, ConstantDepNode] = {} # Per program: Maps values to their ConstantDepNodes
|
|
82
|
+
self._actions: list["SimActionData"] = []
|
|
83
83
|
|
|
84
84
|
# Used by parser to track instruction addresses processed
|
|
85
|
-
self._parsed_ins_addrs:
|
|
85
|
+
self._parsed_ins_addrs: list[ParsedInstruction] = [] # Instruction address, min stmt_idx, max stmt_idx
|
|
86
86
|
|
|
87
87
|
# Parameter sanity check
|
|
88
88
|
if self._block_addrs and self._end_at:
|
|
@@ -91,15 +91,15 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
91
91
|
self._work()
|
|
92
92
|
|
|
93
93
|
@property
|
|
94
|
-
def graph(self) ->
|
|
94
|
+
def graph(self) -> DiGraph | None:
|
|
95
95
|
return self._graph
|
|
96
96
|
|
|
97
97
|
@property
|
|
98
|
-
def simplified_graph(self) ->
|
|
98
|
+
def simplified_graph(self) -> DiGraph | None:
|
|
99
99
|
return self._simplified_graph
|
|
100
100
|
|
|
101
101
|
@property
|
|
102
|
-
def sub_graph(self) ->
|
|
102
|
+
def sub_graph(self) -> DiGraph | None:
|
|
103
103
|
return self._sub_graph
|
|
104
104
|
|
|
105
105
|
def _pop(self) -> Optional["SimActionData"]:
|
|
@@ -171,7 +171,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
171
171
|
self,
|
|
172
172
|
type_: int,
|
|
173
173
|
sim_act: "SimActionData",
|
|
174
|
-
val:
|
|
174
|
+
val: tuple["BV", int],
|
|
175
175
|
*constructor_params,
|
|
176
176
|
) -> "BaseDepNode":
|
|
177
177
|
"""
|
|
@@ -213,7 +213,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
213
213
|
return ret_node
|
|
214
214
|
|
|
215
215
|
def _get_dep_node(
|
|
216
|
-
self, dep_type: int, sim_act: SimActionData, var_src: Union[int, "BV"], val:
|
|
216
|
+
self, dep_type: int, sim_act: SimActionData, var_src: Union[int, "BV"], val: int | BV
|
|
217
217
|
) -> "BaseDepNode":
|
|
218
218
|
if isinstance(var_src, BV):
|
|
219
219
|
var_src = self._end_state.solver.eval(var_src)
|
|
@@ -287,7 +287,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
287
287
|
def _parse_action(self) -> "BaseDepNode":
|
|
288
288
|
return self._get_generic_node(self._pop())
|
|
289
289
|
|
|
290
|
-
def _parse_read_statement(self, read_nodes:
|
|
290
|
+
def _parse_read_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> "BaseDepNode":
|
|
291
291
|
act = self._peek()
|
|
292
292
|
read_node = self._parse_action()
|
|
293
293
|
ancestor_node = self._get_active_node(read_node)
|
|
@@ -310,7 +310,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
310
310
|
|
|
311
311
|
return read_node
|
|
312
312
|
|
|
313
|
-
def _create_dep_edges(self, act, write_node, read_nodes:
|
|
313
|
+
def _create_dep_edges(self, act, write_node, read_nodes: dict[int, list["BaseDepNode"]]) -> bool:
|
|
314
314
|
"""Last resort for linking dependencies"""
|
|
315
315
|
# Check tmp and reg deps
|
|
316
316
|
var_read_nodes = []
|
|
@@ -337,7 +337,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
337
337
|
|
|
338
338
|
return dep_found
|
|
339
339
|
|
|
340
|
-
def _parse_var_statement(self, read_nodes:
|
|
340
|
+
def _parse_var_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> SimActLocation:
|
|
341
341
|
act = self._peek()
|
|
342
342
|
act_loc = SimActLocation(act.bbl_addr, act.ins_addr, act.stmt_idx)
|
|
343
343
|
|
|
@@ -383,7 +383,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
383
383
|
self._parse_statement(read_nodes) if self._peek() and act.stmt_idx == self._peek().stmt_idx else act_loc
|
|
384
384
|
)
|
|
385
385
|
|
|
386
|
-
def _parse_mem_statement(self, read_nodes:
|
|
386
|
+
def _parse_mem_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> SimActLocation:
|
|
387
387
|
act = self._peek()
|
|
388
388
|
act_loc = SimActLocation(act.bbl_addr, act.ins_addr, act.stmt_idx)
|
|
389
389
|
|
|
@@ -416,7 +416,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
416
416
|
|
|
417
417
|
return ret_val if ret_val else self._parse_statement(read_nodes)
|
|
418
418
|
|
|
419
|
-
def _parse_statement(self, read_nodes:
|
|
419
|
+
def _parse_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> SimActLocation:
|
|
420
420
|
"""
|
|
421
421
|
statement -> write_var | write_mem
|
|
422
422
|
statement -> read_var | write_mem statement
|
|
@@ -493,7 +493,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
493
493
|
self._parse_block()
|
|
494
494
|
self._parse_blocks()
|
|
495
495
|
|
|
496
|
-
def _filter_sim_actions(self) ->
|
|
496
|
+
def _filter_sim_actions(self) -> list[SimActionData]:
|
|
497
497
|
"""
|
|
498
498
|
Using the user's start/end address OR block address list parameters,
|
|
499
499
|
filters the actions down to those that are relevant
|
|
@@ -574,7 +574,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
574
574
|
return g0
|
|
575
575
|
|
|
576
576
|
@staticmethod
|
|
577
|
-
def _get_related_nodes(G: DiGraph, curr_node: "BaseDepNode", nodes:
|
|
577
|
+
def _get_related_nodes(G: DiGraph, curr_node: "BaseDepNode", nodes: set["BaseDepNode"], get_ancestors: bool):
|
|
578
578
|
nodes.add(curr_node)
|
|
579
579
|
|
|
580
580
|
next_nodes = G.predecessors(curr_node) if get_ancestors else G.successors(curr_node)
|
|
@@ -587,7 +587,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
587
587
|
else:
|
|
588
588
|
return
|
|
589
589
|
|
|
590
|
-
def get_data_dep(self, g_node: "BaseDepNode", include_tmp_nodes: bool, backwards: bool) ->
|
|
590
|
+
def get_data_dep(self, g_node: "BaseDepNode", include_tmp_nodes: bool, backwards: bool) -> DiGraph | None:
|
|
591
591
|
# We have a matching node and can proceed to build a subgraph
|
|
592
592
|
if g_node in self._graph:
|
|
593
593
|
relevant_nodes = set()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional,
|
|
1
|
+
from typing import Optional, TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
if TYPE_CHECKING:
|
|
4
4
|
from claripy.ast.bv import BV
|
|
@@ -27,10 +27,10 @@ class BaseDepNode:
|
|
|
27
27
|
self.ins_addr = sim_act.ins_addr
|
|
28
28
|
self.stmt_idx = sim_act.stmt_idx
|
|
29
29
|
self.action_id: int = sim_act.id
|
|
30
|
-
self.value:
|
|
30
|
+
self.value: int | None = None
|
|
31
31
|
self._value_ast: Optional["BV"] = None
|
|
32
32
|
|
|
33
|
-
def value_tuple(self) ->
|
|
33
|
+
def value_tuple(self) -> tuple["BV", int]:
|
|
34
34
|
"""
|
|
35
35
|
:return: A tuple containing the node's value as a BV and as an evaluated integer
|
|
36
36
|
"""
|
angr/analyses/ddg.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections import defaultdict
|
|
3
|
-
from typing import List
|
|
4
3
|
|
|
5
4
|
import networkx
|
|
6
5
|
import pyvex
|
|
@@ -425,7 +424,7 @@ class DDGViewInstruction:
|
|
|
425
424
|
return DDGViewItem(self._ddg, pv, simplified=self._simplified)
|
|
426
425
|
|
|
427
426
|
@property
|
|
428
|
-
def definitions(self) ->
|
|
427
|
+
def definitions(self) -> list[DDGViewItem]:
|
|
429
428
|
"""
|
|
430
429
|
Get all definitions located at the current instruction address.
|
|
431
430
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# pylint:disable=too-many-boolean-expressions
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Any, Optional, TYPE_CHECKING
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import logging
|
|
5
5
|
|
|
@@ -74,14 +74,15 @@ class AILSimplifier(Analysis):
|
|
|
74
74
|
func,
|
|
75
75
|
func_graph=None,
|
|
76
76
|
remove_dead_memdefs=False,
|
|
77
|
-
stack_arg_offsets:
|
|
77
|
+
stack_arg_offsets: set[tuple[int, int]] | None = None,
|
|
78
78
|
unify_variables=False,
|
|
79
79
|
ail_manager: Optional["Manager"] = None,
|
|
80
|
-
gp:
|
|
80
|
+
gp: int | None = None,
|
|
81
81
|
narrow_expressions=False,
|
|
82
82
|
only_consts=False,
|
|
83
83
|
fold_callexprs_into_conditions=False,
|
|
84
84
|
use_callee_saved_regs_at_return=True,
|
|
85
|
+
rewrite_ccalls=True,
|
|
85
86
|
):
|
|
86
87
|
self.func = func
|
|
87
88
|
self.func_graph = func_graph if func_graph is not None else func.graph
|
|
@@ -97,9 +98,10 @@ class AILSimplifier(Analysis):
|
|
|
97
98
|
self._only_consts = only_consts
|
|
98
99
|
self._fold_callexprs_into_conditions = fold_callexprs_into_conditions
|
|
99
100
|
self._use_callee_saved_regs_at_return = use_callee_saved_regs_at_return
|
|
101
|
+
self._should_rewrite_ccalls = rewrite_ccalls
|
|
100
102
|
|
|
101
|
-
self._calls_to_remove:
|
|
102
|
-
self._assignments_to_remove:
|
|
103
|
+
self._calls_to_remove: set[CodeLocation] = set()
|
|
104
|
+
self._assignments_to_remove: set[CodeLocation] = set()
|
|
103
105
|
self.blocks = {} # Mapping nodes to simplified blocks
|
|
104
106
|
|
|
105
107
|
self.simplified: bool = False
|
|
@@ -127,13 +129,14 @@ class AILSimplifier(Analysis):
|
|
|
127
129
|
if self._only_consts:
|
|
128
130
|
return
|
|
129
131
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
if self._should_rewrite_ccalls:
|
|
133
|
+
_l.debug("Rewriting ccalls")
|
|
134
|
+
ccalls_rewritten = self._rewrite_ccalls()
|
|
135
|
+
self.simplified |= ccalls_rewritten
|
|
136
|
+
if ccalls_rewritten:
|
|
137
|
+
_l.debug("... ccalls rewritten")
|
|
138
|
+
self._rebuild_func_graph()
|
|
139
|
+
self._clear_cache()
|
|
137
140
|
|
|
138
141
|
if self._unify_vars:
|
|
139
142
|
_l.debug("Removing dead assignments")
|
|
@@ -227,7 +230,7 @@ class AILSimplifier(Analysis):
|
|
|
227
230
|
|
|
228
231
|
narrowed = False
|
|
229
232
|
|
|
230
|
-
addr_and_idx_to_block:
|
|
233
|
+
addr_and_idx_to_block: dict[tuple[int, int], Block] = {}
|
|
231
234
|
for block in self.func_graph.nodes():
|
|
232
235
|
addr_and_idx_to_block[(block.addr, block.idx)] = block
|
|
233
236
|
|
|
@@ -457,13 +460,13 @@ class AILSimplifier(Analysis):
|
|
|
457
460
|
|
|
458
461
|
def _narrowing_needed(
|
|
459
462
|
self, def_, rd, addr_and_idx_to_block
|
|
460
|
-
) ->
|
|
463
|
+
) -> tuple[bool, int | None, list[tuple[CodeLocation, tuple[str, tuple[Expression, ...]]]] | None]:
|
|
461
464
|
def_size = def_.size
|
|
462
465
|
# find its uses
|
|
463
466
|
use_and_exprs = rd.all_uses.get_uses_with_expr(def_)
|
|
464
467
|
|
|
465
468
|
all_used_sizes = set()
|
|
466
|
-
used_by:
|
|
469
|
+
used_by: list[tuple[CodeLocation, tuple[str, tuple[Expression, ...]]]] = []
|
|
467
470
|
|
|
468
471
|
for loc, expr in use_and_exprs:
|
|
469
472
|
old_block = addr_and_idx_to_block.get((loc.block_addr, loc.block_idx), None)
|
|
@@ -492,7 +495,7 @@ class AILSimplifier(Analysis):
|
|
|
492
495
|
|
|
493
496
|
def _extract_expression_effective_size(
|
|
494
497
|
self, statement, expr
|
|
495
|
-
) ->
|
|
498
|
+
) -> tuple[int | None, tuple[str, tuple[Expression, ...]] | None]:
|
|
496
499
|
"""
|
|
497
500
|
Determine the effective size of an expression when it's used.
|
|
498
501
|
"""
|
|
@@ -603,11 +606,11 @@ class AILSimplifier(Analysis):
|
|
|
603
606
|
if not prop.model.equivalence:
|
|
604
607
|
return simplified
|
|
605
608
|
|
|
606
|
-
addr_and_idx_to_block:
|
|
609
|
+
addr_and_idx_to_block: dict[tuple[int, int], Block] = {}
|
|
607
610
|
for block in self.func_graph.nodes():
|
|
608
611
|
addr_and_idx_to_block[(block.addr, block.idx)] = block
|
|
609
612
|
|
|
610
|
-
equivalences:
|
|
613
|
+
equivalences: dict[Any, set[Equivalence]] = defaultdict(set)
|
|
611
614
|
atom_by_loc = set()
|
|
612
615
|
for eq in prop.model.equivalence:
|
|
613
616
|
equivalences[eq.atom1].add(eq)
|
|
@@ -735,7 +738,7 @@ class AILSimplifier(Analysis):
|
|
|
735
738
|
continue
|
|
736
739
|
|
|
737
740
|
# find all its uses
|
|
738
|
-
all_arg_copy_var_uses:
|
|
741
|
+
all_arg_copy_var_uses: set[tuple[CodeLocation, Any]] = set(
|
|
739
742
|
rd.all_uses.get_uses_with_expr(arg_copy_def)
|
|
740
743
|
)
|
|
741
744
|
all_uses_with_def = set()
|
|
@@ -816,7 +819,7 @@ class AILSimplifier(Analysis):
|
|
|
816
819
|
|
|
817
820
|
# find all uses of this definition
|
|
818
821
|
# we make a copy of the set since we may touch the set (uses) when replacing expressions
|
|
819
|
-
all_uses:
|
|
822
|
+
all_uses: set[tuple[CodeLocation, Any]] = set(rd.all_uses.get_uses_with_expr(to_replace_def))
|
|
820
823
|
# make sure none of these uses are phi nodes (depends on more than one def)
|
|
821
824
|
all_uses_with_unique_def = set()
|
|
822
825
|
for use_and_expr in all_uses:
|
|
@@ -943,7 +946,7 @@ class AILSimplifier(Analysis):
|
|
|
943
946
|
return simplified
|
|
944
947
|
|
|
945
948
|
@staticmethod
|
|
946
|
-
def _find_atom_def_at(atom, rd, codeloc: CodeLocation) ->
|
|
949
|
+
def _find_atom_def_at(atom, rd, codeloc: CodeLocation) -> Definition | None:
|
|
947
950
|
if isinstance(atom, Register):
|
|
948
951
|
defs = rd.get_defs(atom, codeloc, OP_BEFORE)
|
|
949
952
|
return next(iter(defs)) if len(defs) == 1 else None
|
|
@@ -1007,18 +1010,18 @@ class AILSimplifier(Analysis):
|
|
|
1007
1010
|
if not prop.model.equivalence:
|
|
1008
1011
|
return simplified
|
|
1009
1012
|
|
|
1010
|
-
addr_and_idx_to_block:
|
|
1013
|
+
addr_and_idx_to_block: dict[tuple[int, int], Block] = {}
|
|
1011
1014
|
for block in self.func_graph.nodes():
|
|
1012
1015
|
addr_and_idx_to_block[(block.addr, block.idx)] = block
|
|
1013
1016
|
|
|
1014
|
-
def_locations_to_remove:
|
|
1015
|
-
updated_use_locations:
|
|
1017
|
+
def_locations_to_remove: set[CodeLocation] = set()
|
|
1018
|
+
updated_use_locations: set[CodeLocation] = set()
|
|
1016
1019
|
|
|
1017
1020
|
eq: Equivalence
|
|
1018
1021
|
for eq in prop.model.equivalence:
|
|
1019
1022
|
# register variable == Call
|
|
1020
1023
|
if isinstance(eq.atom0, Register):
|
|
1021
|
-
call_addr:
|
|
1024
|
+
call_addr: int | None
|
|
1022
1025
|
if isinstance(eq.atom1, Call):
|
|
1023
1026
|
# register variable = Call
|
|
1024
1027
|
call: Expression = eq.atom1
|
|
@@ -1052,7 +1055,7 @@ class AILSimplifier(Analysis):
|
|
|
1052
1055
|
the_def: Definition = defs[0]
|
|
1053
1056
|
|
|
1054
1057
|
# find all uses of this definition
|
|
1055
|
-
all_uses:
|
|
1058
|
+
all_uses: set[tuple[CodeLocation, Any]] = set(rd.all_uses.get_uses_with_expr(the_def))
|
|
1056
1059
|
|
|
1057
1060
|
if len(all_uses) != 1:
|
|
1058
1061
|
continue
|
|
@@ -1156,8 +1159,8 @@ class AILSimplifier(Analysis):
|
|
|
1156
1159
|
# no need to clear the cache at the end of this method
|
|
1157
1160
|
return simplified
|
|
1158
1161
|
|
|
1159
|
-
def _get_super_node_blocks(self, start_node: Block) ->
|
|
1160
|
-
lst:
|
|
1162
|
+
def _get_super_node_blocks(self, start_node: Block) -> list[Block]:
|
|
1163
|
+
lst: list[Block] = [start_node]
|
|
1161
1164
|
while True:
|
|
1162
1165
|
b = lst[-1]
|
|
1163
1166
|
successors = list(self.func_graph.successors(b))
|
|
@@ -1178,7 +1181,7 @@ class AILSimplifier(Analysis):
|
|
|
1178
1181
|
|
|
1179
1182
|
def _replace_expr_and_update_block(
|
|
1180
1183
|
self, block, stmt_idx, stmt, the_def, codeloc, src_expr, dst_expr
|
|
1181
|
-
) ->
|
|
1184
|
+
) -> tuple[bool, Block | None]:
|
|
1182
1185
|
replaced, new_stmt = stmt.replace(src_expr, dst_expr)
|
|
1183
1186
|
if replaced:
|
|
1184
1187
|
new_block = block.copy()
|
|
@@ -1193,7 +1196,7 @@ class AILSimplifier(Analysis):
|
|
|
1193
1196
|
return False, None
|
|
1194
1197
|
|
|
1195
1198
|
def _remove_dead_assignments(self) -> bool:
|
|
1196
|
-
stmts_to_remove_per_block:
|
|
1199
|
+
stmts_to_remove_per_block: dict[tuple[int, int], set[int]] = defaultdict(set)
|
|
1197
1200
|
|
|
1198
1201
|
# Find all statements that should be removed
|
|
1199
1202
|
mask = (1 << self.project.arch.bits) - 1
|
|
@@ -1325,9 +1328,7 @@ class AILSimplifier(Analysis):
|
|
|
1325
1328
|
|
|
1326
1329
|
v = False
|
|
1327
1330
|
|
|
1328
|
-
def _handle_expr(
|
|
1329
|
-
expr_idx: int, expr: Expression, stmt_idx: int, stmt: Statement, block
|
|
1330
|
-
) -> Optional[Expression]:
|
|
1331
|
+
def _handle_expr(expr_idx: int, expr: Expression, stmt_idx: int, stmt: Statement, block) -> Expression | None:
|
|
1331
1332
|
if isinstance(expr, DirtyExpression) and isinstance(expr.dirty_expr, VEXCCallExpression):
|
|
1332
1333
|
rewriter = rewriter_cls(expr.dirty_expr, self.project.arch)
|
|
1333
1334
|
if rewriter.result is not None:
|
|
@@ -1383,7 +1384,7 @@ class AILSimplifier(Analysis):
|
|
|
1383
1384
|
return False
|
|
1384
1385
|
|
|
1385
1386
|
@staticmethod
|
|
1386
|
-
def _count_calls_in_supernodeblocks(blocks:
|
|
1387
|
+
def _count_calls_in_supernodeblocks(blocks: list[Block], start: CodeLocation, end: CodeLocation) -> int:
|
|
1387
1388
|
"""
|
|
1388
1389
|
Count the number of call statements in a list of blocks for a single super block between two given code
|
|
1389
1390
|
locations (exclusive).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
4
|
from ailment import Block
|
|
5
5
|
from ailment.statement import Call, Statement, ConditionalJump, Assignment, Store, Return, Jump
|
|
@@ -26,7 +26,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
26
26
|
I/O locations can be a Register, MemoryLocation, or SpOffset (wrapped in a Memory Location).
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
|
-
def __init__(self, ail_obj:
|
|
29
|
+
def __init__(self, ail_obj: Block | list[Statement], project, as_atom=True):
|
|
30
30
|
super().__init__()
|
|
31
31
|
self.expr_handlers[StackBaseOffset] = self._handle_StackBaseOffset
|
|
32
32
|
self._as_atom = as_atom
|
|
@@ -86,7 +86,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
86
86
|
other_input = self.inputs_by_stmt[other_idx]
|
|
87
87
|
return target_output.intersection(other_input)
|
|
88
88
|
|
|
89
|
-
def can_swap(self, stmt, ail_obj:
|
|
89
|
+
def can_swap(self, stmt, ail_obj: Block | list[Statement], offset: int):
|
|
90
90
|
all_stmts = (ail_obj.statements or []) if isinstance(ail_obj, Block) else ail_obj
|
|
91
91
|
if stmt not in all_stmts:
|
|
92
92
|
raise RuntimeError("Statement not in block, and we can't compute moving a stmt to a new block!")
|
|
@@ -123,14 +123,14 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
123
123
|
# Statements (all with side effects)
|
|
124
124
|
#
|
|
125
125
|
|
|
126
|
-
def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block:
|
|
126
|
+
def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block: Block | None):
|
|
127
127
|
output_loc = self._handle_expr(0, stmt.dst, stmt_idx, stmt, block)
|
|
128
128
|
self._add_or_update_dict(self.outputs_by_stmt, stmt_idx, output_loc)
|
|
129
129
|
|
|
130
130
|
input_loc = self._handle_expr(1, stmt.src, stmt_idx, stmt, block)
|
|
131
131
|
self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input_loc)
|
|
132
132
|
|
|
133
|
-
def _handle_Call(self, stmt_idx: int, stmt: Call, block:
|
|
133
|
+
def _handle_Call(self, stmt_idx: int, stmt: Call, block: Block | None):
|
|
134
134
|
if stmt.args:
|
|
135
135
|
for i, arg in enumerate(stmt.args):
|
|
136
136
|
input_loc = self._handle_expr(i, arg, stmt_idx, stmt, block)
|
|
@@ -139,14 +139,14 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
139
139
|
out_loc = self._handle_expr(0, stmt.ret_expr, stmt_idx, stmt, block)
|
|
140
140
|
self._add_or_update_dict(self.outputs_by_stmt, stmt_idx, out_loc)
|
|
141
141
|
|
|
142
|
-
def _handle_Store(self, stmt_idx: int, stmt: Store, block:
|
|
142
|
+
def _handle_Store(self, stmt_idx: int, stmt: Store, block: Block | None):
|
|
143
143
|
out_loc = self._handle_expr(0, stmt.addr, stmt_idx, stmt, block, is_memory=True)
|
|
144
144
|
self._add_or_update_dict(self.outputs_by_stmt, stmt_idx, out_loc)
|
|
145
145
|
|
|
146
146
|
input_loc = self._handle_expr(1, stmt.data, stmt_idx, stmt, block)
|
|
147
147
|
self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input_loc)
|
|
148
148
|
|
|
149
|
-
def _handle_ConditionalJump(self, stmt_idx: int, stmt: ConditionalJump, block:
|
|
149
|
+
def _handle_ConditionalJump(self, stmt_idx: int, stmt: ConditionalJump, block: Block | None):
|
|
150
150
|
input1 = self._handle_expr(0, stmt.condition, stmt_idx, stmt, block)
|
|
151
151
|
input2 = self._handle_expr(1, stmt.true_target, stmt_idx, stmt, block)
|
|
152
152
|
input3 = self._handle_expr(2, stmt.false_target, stmt_idx, stmt, block)
|
|
@@ -154,7 +154,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
154
154
|
self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input2)
|
|
155
155
|
self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input3)
|
|
156
156
|
|
|
157
|
-
def _handle_Return(self, stmt_idx: int, stmt: Return, block:
|
|
157
|
+
def _handle_Return(self, stmt_idx: int, stmt: Return, block: Block | None):
|
|
158
158
|
if stmt.ret_exprs:
|
|
159
159
|
for i, ret_expr in enumerate(stmt.ret_exprs):
|
|
160
160
|
loc = self._handle_expr(i, ret_expr, stmt_idx, stmt, block)
|
|
@@ -170,8 +170,8 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
170
170
|
expr_idx: int,
|
|
171
171
|
expr: Expression,
|
|
172
172
|
stmt_idx: int,
|
|
173
|
-
stmt:
|
|
174
|
-
block:
|
|
173
|
+
stmt: Statement | None,
|
|
174
|
+
block: Block | None,
|
|
175
175
|
is_memory=False,
|
|
176
176
|
) -> Any:
|
|
177
177
|
try:
|
|
@@ -185,14 +185,14 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
185
185
|
|
|
186
186
|
# pylint: disable=unused-argument
|
|
187
187
|
def _handle_Load(
|
|
188
|
-
self, expr_idx: int, expr: Load, stmt_idx: int, stmt: Statement, block:
|
|
188
|
+
self, expr_idx: int, expr: Load, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=True
|
|
189
189
|
):
|
|
190
190
|
load_loc = self._handle_expr(0, expr.addr, stmt_idx, stmt, block, is_memory=True)
|
|
191
191
|
self._add_or_update_dict(self.derefed_at, stmt_idx, load_loc)
|
|
192
192
|
return load_loc
|
|
193
193
|
|
|
194
194
|
def _handle_CallExpr(
|
|
195
|
-
self, expr_idx: int, expr: Call, stmt_idx: int, stmt: Statement, block:
|
|
195
|
+
self, expr_idx: int, expr: Call, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
196
196
|
):
|
|
197
197
|
args = set()
|
|
198
198
|
if expr.args:
|
|
@@ -202,7 +202,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
202
202
|
return args
|
|
203
203
|
|
|
204
204
|
def _handle_BinaryOp(
|
|
205
|
-
self, expr_idx: int, expr: BinaryOp, stmt_idx: int, stmt: Statement, block:
|
|
205
|
+
self, expr_idx: int, expr: BinaryOp, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
206
206
|
):
|
|
207
207
|
input_locs = set()
|
|
208
208
|
self._add_or_update_set(
|
|
@@ -215,17 +215,17 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
215
215
|
return input_locs
|
|
216
216
|
|
|
217
217
|
def _handle_UnaryOp(
|
|
218
|
-
self, expr_idx: int, expr: UnaryOp, stmt_idx: int, stmt: Statement, block:
|
|
218
|
+
self, expr_idx: int, expr: UnaryOp, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
219
219
|
):
|
|
220
220
|
return self._handle_expr(0, expr.operand, stmt_idx, stmt, block, is_memory=is_memory)
|
|
221
221
|
|
|
222
222
|
def _handle_Convert(
|
|
223
|
-
self, expr_idx: int, expr: Convert, stmt_idx: int, stmt: Statement, block:
|
|
223
|
+
self, expr_idx: int, expr: Convert, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
224
224
|
):
|
|
225
225
|
return self._handle_expr(expr_idx, expr.operand, stmt_idx, stmt, block, is_memory=is_memory)
|
|
226
226
|
|
|
227
227
|
def _handle_ITE(
|
|
228
|
-
self, expr_idx: int, expr: ITE, stmt_idx: int, stmt: Statement, block:
|
|
228
|
+
self, expr_idx: int, expr: ITE, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
229
229
|
):
|
|
230
230
|
input_locs = set()
|
|
231
231
|
self._add_or_update_set(
|
|
@@ -249,7 +249,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
249
249
|
|
|
250
250
|
# pylint: disable=unused-argument
|
|
251
251
|
def _handle_Tmp(
|
|
252
|
-
self, expr_idx: int, expr: Tmp, stmt_idx: int, stmt: Statement, block:
|
|
252
|
+
self, expr_idx: int, expr: Tmp, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
253
253
|
):
|
|
254
254
|
if self._as_atom:
|
|
255
255
|
return None
|
|
@@ -258,7 +258,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
258
258
|
|
|
259
259
|
# pylint: disable=unused-argument
|
|
260
260
|
def _handle_Register(
|
|
261
|
-
self, expr_idx: int, expr: Register, stmt_idx: int, stmt: Statement, block:
|
|
261
|
+
self, expr_idx: int, expr: Register, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
262
262
|
):
|
|
263
263
|
if self._as_atom:
|
|
264
264
|
return Register(expr.reg_offset, expr.size)
|
|
@@ -266,7 +266,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
266
266
|
return expr
|
|
267
267
|
|
|
268
268
|
def _handle_Const(
|
|
269
|
-
self, expr_idx: int, expr: Const, stmt_idx: int, stmt: Statement, block:
|
|
269
|
+
self, expr_idx: int, expr: Const, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
|
|
270
270
|
):
|
|
271
271
|
if self._as_atom:
|
|
272
272
|
return MemoryLocation(expr.value, expr.size) if is_memory else ConstantSrc(expr.value, expr.size)
|
|
@@ -283,7 +283,7 @@ class BlockIOFinder(AILBlockWalkerBase):
|
|
|
283
283
|
expr: StackBaseOffset,
|
|
284
284
|
stmt_idx: int,
|
|
285
285
|
stmt: Statement,
|
|
286
|
-
block:
|
|
286
|
+
block: Block | None,
|
|
287
287
|
is_memory=False,
|
|
288
288
|
):
|
|
289
289
|
if self._as_atom:
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Union, Optional, List, Tuple
|
|
2
|
-
|
|
3
1
|
import networkx as nx
|
|
4
2
|
from ailment.block import Block
|
|
5
3
|
from ailment.statement import Statement, ConditionalJump
|
|
@@ -19,7 +17,7 @@ def has_similar_stmt(blk1: Block, blk2: Block):
|
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
def is_similar(
|
|
22
|
-
ail_obj1:
|
|
20
|
+
ail_obj1: Block | Statement, ail_obj2: Block | Statement, graph: nx.DiGraph = None, partial: bool = True
|
|
23
21
|
):
|
|
24
22
|
"""
|
|
25
23
|
Returns True if the two AIL objects are similar, False otherwise.
|
|
@@ -128,7 +126,7 @@ def _kmp_search_ail_obj(search_pattern, stmt_seq, graph=None, partial=True):
|
|
|
128
126
|
yield start_pos
|
|
129
127
|
|
|
130
128
|
|
|
131
|
-
def index_of_similar_stmts(search_stmts, other_stmts, graph=None, all_positions=False) ->
|
|
129
|
+
def index_of_similar_stmts(search_stmts, other_stmts, graph=None, all_positions=False) -> int | None:
|
|
132
130
|
"""
|
|
133
131
|
Returns the index of the first occurrence of the search_stmts (a list of Statement) in other_stmts (a list of
|
|
134
132
|
Statement). If all_positions is True, returns a list of all positions.
|
|
@@ -157,8 +155,8 @@ def in_other(stmts, other, graph=None):
|
|
|
157
155
|
|
|
158
156
|
|
|
159
157
|
def longest_ail_subseq(
|
|
160
|
-
stmts_list:
|
|
161
|
-
) ->
|
|
158
|
+
stmts_list: list[list[Statement]], graph=None
|
|
159
|
+
) -> tuple[list[Statement] | None, list[int] | None]:
|
|
162
160
|
"""
|
|
163
161
|
Given a list of List[Statement], it returns the longest List[Statement] that is a subsequence of all the lists.
|
|
164
162
|
The common List[Statement] most all be in the same order and adjacent to each other. If no common subsequence is
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint:disable=too-many-boolean-expressions
|
|
2
2
|
import logging
|
|
3
|
-
from typing import Optional,
|
|
3
|
+
from typing import Optional, TYPE_CHECKING
|
|
4
|
+
from collections.abc import Iterable
|
|
4
5
|
|
|
5
6
|
from ailment.statement import Statement, Assignment, Call, Store, Jump
|
|
6
7
|
from ailment.expression import Tmp, Load, Const, Register, Convert
|
|
@@ -60,13 +61,13 @@ class BlockSimplifier(Analysis):
|
|
|
60
61
|
def __init__(
|
|
61
62
|
self,
|
|
62
63
|
block: Optional["Block"],
|
|
63
|
-
func_addr:
|
|
64
|
+
func_addr: int | None = None,
|
|
64
65
|
remove_dead_memdefs=False,
|
|
65
66
|
stack_pointer_tracker=None,
|
|
66
|
-
peephole_optimizations:
|
|
67
|
-
Iterable[
|
|
68
|
-
|
|
69
|
-
stack_arg_offsets:
|
|
67
|
+
peephole_optimizations: None | (
|
|
68
|
+
Iterable[type[PeepholeOptimizationStmtBase] | type[PeepholeOptimizationExprBase]]
|
|
69
|
+
) = None,
|
|
70
|
+
stack_arg_offsets: set[tuple[int, int]] | None = None,
|
|
70
71
|
cached_reaching_definitions=None,
|
|
71
72
|
cached_propagator=None,
|
|
72
73
|
):
|
|
@@ -194,14 +195,14 @@ class BlockSimplifier(Analysis):
|
|
|
194
195
|
# propagator
|
|
195
196
|
if nonconstant_stmts >= 2 and has_propagatable_assignments:
|
|
196
197
|
propagator = self._compute_propagation(block)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
new_block = block
|
|
199
|
+
if propagator.model.states:
|
|
200
|
+
prop_state = list(propagator.model.states.values())[0]
|
|
201
|
+
replacements = prop_state._replacements
|
|
202
|
+
if replacements:
|
|
203
|
+
_, new_block = self._replace_and_build(block, replacements, replace_registers=True)
|
|
204
|
+
new_block = self._eliminate_self_assignments(new_block)
|
|
205
|
+
self._clear_cache()
|
|
205
206
|
else:
|
|
206
207
|
# Skipped calling Propagator
|
|
207
208
|
new_block = block
|
|
@@ -218,9 +219,9 @@ class BlockSimplifier(Analysis):
|
|
|
218
219
|
replacements,
|
|
219
220
|
replace_assignment_dsts: bool = False,
|
|
220
221
|
replace_loads: bool = False,
|
|
221
|
-
gp:
|
|
222
|
+
gp: int | None = None,
|
|
222
223
|
replace_registers: bool = True,
|
|
223
|
-
) ->
|
|
224
|
+
) -> tuple[bool, "Block"]:
|
|
224
225
|
new_statements = block.statements[::]
|
|
225
226
|
replaced = False
|
|
226
227
|
|