angr 9.2.131__py3-none-manylinux2014_aarch64.whl → 9.2.133__py3-none-manylinux2014_aarch64.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 +128 -128
- angr/analyses/__init__.py +38 -38
- angr/analyses/analysis.py +6 -2
- angr/analyses/backward_slice.py +3 -4
- angr/analyses/binary_optimizer.py +5 -12
- angr/analyses/bindiff.py +3 -6
- angr/analyses/calling_convention.py +3 -4
- angr/analyses/cfg/__init__.py +3 -3
- angr/analyses/cfg/cfg_base.py +1 -1
- angr/analyses/cfg/cfg_emulated.py +5 -5
- angr/analyses/cfg/cfg_fast.py +19 -17
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +5 -5
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +148 -101
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
- angr/analyses/data_dep/__init__.py +4 -4
- angr/analyses/datagraph_meta.py +1 -1
- angr/analyses/ddg.py +16 -17
- angr/analyses/decompiler/__init__.py +12 -12
- angr/analyses/decompiler/ail_simplifier.py +24 -12
- angr/analyses/decompiler/block_similarity.py +2 -4
- angr/analyses/decompiler/block_simplifier.py +10 -21
- angr/analyses/decompiler/callsite_maker.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
- angr/analyses/decompiler/clinic.py +122 -41
- angr/analyses/decompiler/condition_processor.py +57 -39
- angr/analyses/decompiler/counters/__init__.py +3 -3
- angr/analyses/decompiler/decompilation_cache.py +7 -7
- angr/analyses/decompiler/dephication/__init__.py +1 -1
- angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +11 -3
- angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
- angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/graph_region.py +8 -8
- angr/analyses/decompiler/optimization_passes/__init__.py +20 -20
- angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +1 -2
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +1 -3
- angr/analyses/decompiler/optimization_passes/engine_base.py +262 -84
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +175 -39
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +2 -5
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +5 -5
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +12 -3
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +42 -19
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +9 -5
- angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/base.py +6 -6
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +2 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
- angr/analyses/decompiler/presets/__init__.py +1 -1
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +3 -3
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +8 -12
- angr/analyses/decompiler/ssailification/rewriting.py +1 -2
- angr/analyses/decompiler/ssailification/rewriting_engine.py +139 -56
- angr/analyses/decompiler/ssailification/ssailification.py +2 -1
- angr/analyses/decompiler/ssailification/traversal.py +4 -6
- angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
- angr/analyses/decompiler/structured_codegen/__init__.py +5 -5
- angr/analyses/decompiler/structured_codegen/base.py +3 -3
- angr/analyses/decompiler/structured_codegen/c.py +39 -40
- angr/analyses/decompiler/structuring/__init__.py +3 -3
- angr/analyses/decompiler/structuring/phoenix.py +45 -29
- angr/analyses/decompiler/structuring/structurer_base.py +2 -2
- angr/analyses/decompiler/structuring/structurer_nodes.py +23 -14
- angr/analyses/deobfuscator/__init__.py +3 -3
- angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
- angr/analyses/deobfuscator/string_obf_finder.py +2 -2
- angr/analyses/deobfuscator/string_obf_opt_passes.py +1 -1
- angr/analyses/disassembly.py +4 -4
- angr/analyses/forward_analysis/__init__.py +1 -1
- angr/analyses/forward_analysis/visitors/graph.py +6 -6
- angr/analyses/init_finder.py +47 -22
- angr/analyses/loop_analysis.py +1 -1
- angr/analyses/loopfinder.py +1 -1
- angr/analyses/propagator/engine_base.py +21 -14
- angr/analyses/propagator/engine_vex.py +149 -179
- angr/analyses/propagator/outdated_definition_walker.py +12 -6
- angr/analyses/propagator/propagator.py +10 -28
- angr/analyses/propagator/top_checker_mixin.py +211 -5
- angr/analyses/propagator/vex_vars.py +4 -4
- angr/analyses/reaching_definitions/__init__.py +9 -9
- angr/analyses/reaching_definitions/call_trace.py +2 -2
- angr/analyses/reaching_definitions/dep_graph.py +1 -1
- angr/analyses/reaching_definitions/engine_ail.py +304 -329
- angr/analyses/reaching_definitions/engine_vex.py +243 -229
- angr/analyses/reaching_definitions/function_handler.py +3 -3
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +1 -1
- angr/analyses/reaching_definitions/rd_state.py +47 -42
- angr/analyses/reassembler.py +26 -31
- angr/analyses/s_liveness.py +8 -0
- angr/analyses/s_propagator.py +18 -3
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -5
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
- angr/analyses/stack_pointer_tracker.py +4 -4
- angr/analyses/typehoon/simple_solver.py +14 -14
- angr/analyses/typehoon/translator.py +10 -2
- angr/analyses/typehoon/typeconsts.py +11 -3
- angr/analyses/typehoon/typevars.py +26 -26
- angr/analyses/unpacker/__init__.py +1 -1
- angr/analyses/variable_recovery/engine_ail.py +299 -259
- angr/analyses/variable_recovery/engine_base.py +138 -121
- angr/analyses/variable_recovery/engine_vex.py +175 -185
- angr/analyses/variable_recovery/irsb_scanner.py +49 -38
- angr/analyses/variable_recovery/variable_recovery.py +28 -5
- angr/analyses/variable_recovery/variable_recovery_base.py +33 -34
- angr/analyses/variable_recovery/variable_recovery_fast.py +4 -8
- angr/analyses/veritesting.py +2 -2
- angr/analyses/vfg.py +5 -5
- angr/analyses/xrefs.py +46 -19
- angr/angrdb/serializers/__init__.py +1 -1
- angr/annocfg.py +20 -15
- angr/blade.py +2 -2
- angr/block.py +20 -25
- angr/calling_conventions.py +12 -14
- angr/code_location.py +6 -10
- angr/codenode.py +3 -3
- angr/engines/__init__.py +12 -14
- angr/engines/engine.py +24 -61
- angr/engines/light/__init__.py +13 -5
- angr/engines/light/data.py +1 -1
- angr/engines/light/engine.py +1003 -1185
- angr/engines/pcode/__init__.py +1 -1
- angr/engines/pcode/behavior.py +1 -1
- angr/engines/pcode/cc.py +2 -0
- angr/engines/pcode/lifter.py +13 -15
- angr/engines/soot/expressions/__init__.py +12 -12
- angr/engines/soot/statements/__init__.py +6 -6
- angr/engines/soot/values/__init__.py +6 -6
- angr/engines/soot/values/arrayref.py +2 -2
- angr/engines/soot/values/constants.py +1 -1
- angr/engines/soot/values/instancefieldref.py +1 -1
- angr/engines/soot/values/paramref.py +1 -1
- angr/engines/soot/values/staticfieldref.py +1 -1
- angr/engines/successors.py +15 -14
- angr/engines/vex/__init__.py +5 -5
- angr/engines/vex/claripy/ccall.py +2 -2
- angr/engines/vex/claripy/datalayer.py +1 -1
- angr/engines/vex/claripy/irop.py +19 -19
- angr/engines/vex/heavy/__init__.py +2 -2
- angr/engines/vex/heavy/actions.py +1 -3
- angr/engines/vex/heavy/heavy.py +4 -6
- angr/engines/vex/lifter.py +2 -4
- angr/engines/vex/light/light.py +0 -2
- angr/engines/vex/light/slicing.py +5 -5
- angr/exploration_techniques/__init__.py +19 -142
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +1 -1
- angr/exploration_techniques/dfs.py +3 -1
- angr/exploration_techniques/director.py +2 -3
- angr/exploration_techniques/driller_core.py +1 -1
- angr/exploration_techniques/explorer.py +4 -2
- angr/exploration_techniques/lengthlimiter.py +2 -1
- angr/exploration_techniques/local_loop_seer.py +2 -1
- angr/exploration_techniques/loop_seer.py +5 -5
- angr/exploration_techniques/manual_mergepoint.py +2 -1
- angr/exploration_techniques/memory_watcher.py +3 -1
- angr/exploration_techniques/oppologist.py +4 -5
- angr/exploration_techniques/slicecutor.py +4 -2
- angr/exploration_techniques/spiller.py +1 -1
- angr/exploration_techniques/stochastic.py +2 -1
- angr/exploration_techniques/stub_stasher.py +2 -1
- angr/exploration_techniques/suggestions.py +3 -1
- angr/exploration_techniques/symbion.py +3 -1
- angr/exploration_techniques/tech_builder.py +2 -1
- angr/exploration_techniques/threading.py +2 -11
- angr/exploration_techniques/timeout.py +4 -2
- angr/exploration_techniques/tracer.py +4 -3
- angr/exploration_techniques/unique.py +3 -2
- angr/exploration_techniques/veritesting.py +1 -1
- angr/factory.py +36 -6
- angr/keyed_region.py +4 -4
- angr/knowledge_base.py +1 -1
- angr/knowledge_plugins/__init__.py +11 -11
- angr/knowledge_plugins/cfg/__init__.py +5 -5
- angr/knowledge_plugins/cfg/cfg_manager.py +2 -2
- angr/knowledge_plugins/cfg/cfg_model.py +8 -8
- angr/knowledge_plugins/cfg/cfg_node.py +19 -19
- angr/knowledge_plugins/cfg/indirect_jump.py +6 -6
- angr/knowledge_plugins/cfg/memory_data.py +5 -7
- angr/knowledge_plugins/functions/function.py +48 -52
- angr/knowledge_plugins/functions/function_parser.py +4 -4
- angr/knowledge_plugins/key_definitions/__init__.py +3 -3
- angr/knowledge_plugins/key_definitions/atoms.py +8 -8
- angr/knowledge_plugins/key_definitions/definition.py +1 -1
- angr/knowledge_plugins/key_definitions/live_definitions.py +30 -27
- angr/knowledge_plugins/labels.py +1 -1
- angr/knowledge_plugins/propagations/__init__.py +1 -1
- angr/knowledge_plugins/propagations/prop_value.py +2 -2
- angr/knowledge_plugins/propagations/propagation_model.py +7 -8
- angr/knowledge_plugins/propagations/states.py +44 -39
- angr/knowledge_plugins/variables/variable_access.py +2 -2
- angr/knowledge_plugins/variables/variable_manager.py +24 -10
- angr/knowledge_plugins/xrefs/xref.py +5 -8
- angr/misc/__init__.py +4 -4
- angr/misc/hookset.py +4 -5
- angr/misc/loggers.py +2 -2
- angr/misc/telemetry.py +1 -1
- angr/procedures/__init__.py +1 -1
- angr/procedures/cgc/fdwait.py +2 -2
- angr/procedures/definitions/__init__.py +2 -2
- angr/procedures/definitions/linux_kernel.py +0 -1
- angr/procedures/definitions/parse_syscalls_from_local_system.py +1 -1
- angr/procedures/definitions/parse_win32json.py +0 -1
- angr/procedures/ntdll/exceptions.py +1 -1
- angr/procedures/stubs/format_parser.py +3 -3
- angr/procedures/win32/dynamic_loading.py +1 -1
- angr/protos/__init__.py +3 -3
- angr/sim_manager.py +3 -5
- angr/sim_state.py +40 -42
- angr/sim_state_options.py +3 -3
- angr/sim_type.py +15 -14
- angr/sim_variable.py +42 -45
- angr/simos/__init__.py +4 -4
- angr/simos/cgc.py +1 -1
- angr/simos/simos.py +1 -1
- angr/simos/userland.py +1 -1
- angr/slicer.py +4 -7
- angr/state_plugins/__init__.py +34 -34
- angr/state_plugins/callstack.py +5 -12
- angr/state_plugins/heap/__init__.py +2 -2
- angr/state_plugins/heap/heap_brk.py +2 -4
- angr/state_plugins/heap/heap_ptmalloc.py +1 -1
- angr/state_plugins/jni_references.py +3 -2
- angr/state_plugins/scratch.py +1 -1
- angr/state_plugins/sim_action.py +1 -4
- angr/state_plugins/sim_event.py +1 -1
- angr/state_plugins/solver.py +7 -9
- angr/state_plugins/uc_manager.py +1 -1
- angr/state_plugins/view.py +2 -2
- angr/storage/__init__.py +1 -1
- angr/storage/file.py +10 -10
- angr/storage/memory_mixins/__init__.py +46 -46
- angr/storage/memory_mixins/default_filler_mixin.py +1 -3
- angr/storage/memory_mixins/javavm_memory_mixin.py +2 -2
- angr/storage/memory_mixins/name_resolution_mixin.py +2 -2
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -3
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +6 -6
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/multi_values.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/regioned_memory/__init__.py +3 -3
- angr/storage/memory_mixins/regioned_memory/region_data.py +5 -5
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +7 -9
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +4 -4
- angr/storage/memory_object.py +4 -4
- angr/utils/__init__.py +3 -3
- angr/utils/bits.py +12 -0
- angr/utils/dynamic_dictlist.py +1 -1
- angr/utils/graph.py +1 -1
- angr/utils/orderedset.py +4 -1
- angr/utils/segment_list.py +2 -2
- angr/utils/ssa/__init__.py +33 -8
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/METADATA +6 -6
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/RECORD +262 -263
- angr/analyses/propagator/engine_ail.py +0 -1562
- angr/storage/memory_mixins/__init__.pyi +0 -48
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/LICENSE +0 -0
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/WHEEL +0 -0
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/entry_points.txt +0 -0
- {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/top_level.txt +0 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
# pylint:disable=arguments-renamed,too-many-boolean-expressions,no-self-use
|
|
1
|
+
# pylint:disable=arguments-renamed,too-many-boolean-expressions,no-self-use,unused-argument
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
from typing import Any
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from collections import defaultdict
|
|
5
6
|
|
|
6
7
|
from archinfo import Endness
|
|
7
8
|
from ailment.expression import (
|
|
8
9
|
Const,
|
|
9
10
|
Register,
|
|
10
|
-
|
|
11
|
+
Expression,
|
|
11
12
|
StackBaseOffset,
|
|
12
13
|
Convert,
|
|
13
14
|
BinaryOp,
|
|
@@ -19,7 +20,8 @@ from ailment.expression import (
|
|
|
19
20
|
from ailment.statement import ConditionalJump, Jump, Assignment
|
|
20
21
|
import claripy
|
|
21
22
|
|
|
22
|
-
from angr.
|
|
23
|
+
from angr.utils.bits import zeroextend_on_demand
|
|
24
|
+
from angr.engines.light import SimEngineNostmtAIL
|
|
23
25
|
from angr.storage.memory_mixins import (
|
|
24
26
|
SimpleInterfaceMixin,
|
|
25
27
|
DefaultFillerMixin,
|
|
@@ -31,6 +33,19 @@ from angr.errors import SimMemoryMissingError
|
|
|
31
33
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
def _make_binop(compute: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]):
|
|
37
|
+
def inner(self, expr: BinaryOp) -> claripy.ast.BV | None:
|
|
38
|
+
a, b = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
39
|
+
if a is None or b is None:
|
|
40
|
+
return None
|
|
41
|
+
try:
|
|
42
|
+
return compute(a, b)
|
|
43
|
+
except (ZeroDivisionError, claripy.ClaripyZeroDivisionError):
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
return inner
|
|
47
|
+
|
|
48
|
+
|
|
34
49
|
class FasterMemory(
|
|
35
50
|
SimpleInterfaceMixin,
|
|
36
51
|
DefaultFillerMixin,
|
|
@@ -61,12 +76,12 @@ class InlinedStringTransformationState:
|
|
|
61
76
|
def _get_weakref(self):
|
|
62
77
|
return self
|
|
63
78
|
|
|
64
|
-
def reg_store(self, reg: Register, value: claripy.ast.
|
|
79
|
+
def reg_store(self, reg: Register, value: claripy.ast.BV) -> None:
|
|
65
80
|
self.registers.store(
|
|
66
81
|
reg.reg_offset, value, size=value.size() // self.arch.byte_width, endness=str(self.arch.register_endness)
|
|
67
82
|
)
|
|
68
83
|
|
|
69
|
-
def reg_load(self, reg: Register) -> claripy.ast.
|
|
84
|
+
def reg_load(self, reg: Register) -> claripy.ast.BV | None:
|
|
70
85
|
try:
|
|
71
86
|
return self.registers.load(
|
|
72
87
|
reg.reg_offset, size=reg.size, endness=self.arch.register_endness, fill_missing=False
|
|
@@ -77,7 +92,7 @@ class InlinedStringTransformationState:
|
|
|
77
92
|
def mem_store(self, addr: int, value: claripy.ast.Bits, endness: str) -> None:
|
|
78
93
|
self.memory.store(addr, value, size=value.size() // self.arch.byte_width, endness=endness)
|
|
79
94
|
|
|
80
|
-
def mem_load(self, addr: int, size: int, endness) -> claripy.ast.
|
|
95
|
+
def mem_load(self, addr: int, size: int, endness) -> claripy.ast.BV | None:
|
|
81
96
|
try:
|
|
82
97
|
return self.memory.load(addr, size=size, endness=str(endness), fill_missing=False)
|
|
83
98
|
except SimMemoryMissingError:
|
|
@@ -86,21 +101,21 @@ class InlinedStringTransformationState:
|
|
|
86
101
|
def vvar_store(self, vvar: VirtualVariable, value: claripy.ast.Bits | None) -> None:
|
|
87
102
|
self.virtual_variables[vvar.varid] = value
|
|
88
103
|
|
|
89
|
-
def vvar_load(self, vvar: VirtualVariable) -> claripy.ast.
|
|
104
|
+
def vvar_load(self, vvar: VirtualVariable) -> claripy.ast.BV | None:
|
|
90
105
|
if vvar.varid in self.virtual_variables:
|
|
91
106
|
return self.virtual_variables[vvar.varid]
|
|
92
107
|
return None
|
|
93
108
|
|
|
94
109
|
|
|
95
|
-
class InlinedStringTransformationAILEngine(
|
|
110
|
+
class InlinedStringTransformationAILEngine(
|
|
111
|
+
SimEngineNostmtAIL[InlinedStringTransformationState, claripy.ast.BV | None, None, None],
|
|
112
|
+
):
|
|
96
113
|
"""
|
|
97
114
|
A simple AIL execution engine
|
|
98
115
|
"""
|
|
99
116
|
|
|
100
117
|
def __init__(self, project, nodes: dict[int, Any], start: int, end: int, step_limit: int):
|
|
101
|
-
super().__init__()
|
|
102
|
-
|
|
103
|
-
self.arch = project.arch
|
|
118
|
+
super().__init__(project)
|
|
104
119
|
self.nodes: dict[int, Any] = nodes
|
|
105
120
|
self.start: int = start
|
|
106
121
|
self.end: int = end
|
|
@@ -121,7 +136,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
121
136
|
# jumped to a node that we do not know about
|
|
122
137
|
break
|
|
123
138
|
block = self.nodes[self.pc]
|
|
124
|
-
self._process(state,
|
|
139
|
+
self._process(state, block=block, whitelist=None)
|
|
125
140
|
if self.pc is None:
|
|
126
141
|
# not sure where to jump...
|
|
127
142
|
break
|
|
@@ -131,8 +146,18 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
131
146
|
break
|
|
132
147
|
i += 1
|
|
133
148
|
|
|
134
|
-
def
|
|
149
|
+
def _top(self, bits):
|
|
150
|
+
assert False, "Should not be reachable"
|
|
151
|
+
|
|
152
|
+
def _is_top(self, expr):
|
|
153
|
+
assert False, "Should not be reachable"
|
|
154
|
+
|
|
155
|
+
def _process_block_end(self, block, stmt_data, whitelist):
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
def _process_address(self, addr: Expression) -> tuple[int, str] | None:
|
|
135
159
|
if isinstance(addr, Const):
|
|
160
|
+
assert isinstance(addr.value, int)
|
|
136
161
|
return addr.value, "mem"
|
|
137
162
|
if isinstance(addr, StackBaseOffset):
|
|
138
163
|
return (addr.offset + self.STACK_BASE) & self.MASK, "stack"
|
|
@@ -145,7 +170,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
145
170
|
return (v0 + v1.concrete_value) & self.MASK, "stack"
|
|
146
171
|
return None
|
|
147
172
|
|
|
148
|
-
def
|
|
173
|
+
def _handle_stmt_Assignment(self, stmt):
|
|
149
174
|
if isinstance(stmt.dst, VirtualVariable):
|
|
150
175
|
if stmt.dst.was_reg:
|
|
151
176
|
val = self._expr(stmt.src)
|
|
@@ -163,7 +188,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
163
188
|
byte_off = val.size() // self.arch.byte_width - i - 1
|
|
164
189
|
self.stack_accesses[addr + i].append(("store", self._codeloc(), val.get_byte(byte_off)))
|
|
165
190
|
|
|
166
|
-
def
|
|
191
|
+
def _handle_stmt_Store(self, stmt):
|
|
167
192
|
addr_and_type = self._process_address(stmt.addr)
|
|
168
193
|
if addr_and_type is not None:
|
|
169
194
|
addr, addr_type = addr_and_type
|
|
@@ -178,14 +203,14 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
178
203
|
byte_off = val.size() // self.arch.byte_width - i - 1
|
|
179
204
|
self.stack_accesses[addr + i].append(("store", self._codeloc(), val.get_byte(byte_off)))
|
|
180
205
|
|
|
181
|
-
def
|
|
206
|
+
def _handle_stmt_Jump(self, stmt):
|
|
182
207
|
self.last_pc = self.pc
|
|
183
208
|
if isinstance(stmt.target, Const):
|
|
184
209
|
self.pc = stmt.target.value
|
|
185
210
|
else:
|
|
186
211
|
self.pc = None
|
|
187
212
|
|
|
188
|
-
def
|
|
213
|
+
def _handle_stmt_ConditionalJump(self, stmt):
|
|
189
214
|
self.last_pc = self.pc
|
|
190
215
|
self.pc = None
|
|
191
216
|
if isinstance(stmt.true_target, Const) and isinstance(stmt.false_target, Const):
|
|
@@ -196,10 +221,12 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
196
221
|
elif isinstance(cond, claripy.ast.Bits) and cond.concrete_value == 0:
|
|
197
222
|
self.pc = stmt.false_target.value
|
|
198
223
|
|
|
199
|
-
def
|
|
200
|
-
|
|
224
|
+
def _handle_expr_Const(self, expr):
|
|
225
|
+
if isinstance(expr.value, int):
|
|
226
|
+
return claripy.BVV(expr.value, expr.bits)
|
|
227
|
+
return None
|
|
201
228
|
|
|
202
|
-
def
|
|
229
|
+
def _handle_expr_Load(self, expr):
|
|
203
230
|
addr_and_type = self._process_address(expr.addr)
|
|
204
231
|
if addr_and_type is not None:
|
|
205
232
|
addr, addr_type = addr_and_type
|
|
@@ -214,14 +241,14 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
214
241
|
return v
|
|
215
242
|
return None
|
|
216
243
|
|
|
217
|
-
def
|
|
244
|
+
def _handle_expr_Register(self, expr: Register):
|
|
218
245
|
return self.state.reg_load(expr)
|
|
219
246
|
|
|
220
|
-
def
|
|
247
|
+
def _handle_expr_VirtualVariable(self, expr: VirtualVariable):
|
|
221
248
|
if expr.was_stack:
|
|
222
249
|
addr = (expr.stack_offset + self.STACK_BASE) & self.MASK
|
|
223
250
|
v = self.state.mem_load(addr, expr.size, self.arch.memory_endness)
|
|
224
|
-
if
|
|
251
|
+
if v is not None:
|
|
225
252
|
# log it
|
|
226
253
|
for i in range(expr.size):
|
|
227
254
|
byte_off = i
|
|
@@ -233,25 +260,43 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
233
260
|
return self.state.vvar_load(expr)
|
|
234
261
|
return None
|
|
235
262
|
|
|
236
|
-
def
|
|
263
|
+
def _handle_expr_Phi(self, expr: Phi):
|
|
237
264
|
for src, vvar in expr.src_and_vvars:
|
|
238
265
|
if src[0] == self.last_pc and vvar is not None:
|
|
239
266
|
return self.state.vvar_load(vvar)
|
|
240
267
|
return None
|
|
241
268
|
|
|
242
|
-
def
|
|
269
|
+
def _handle_unop_Neg(self, expr: UnaryOp):
|
|
243
270
|
v = self._expr(expr.operand)
|
|
244
271
|
if isinstance(v, claripy.ast.Bits):
|
|
245
272
|
return -v
|
|
246
273
|
return None
|
|
247
274
|
|
|
248
|
-
def
|
|
275
|
+
def _handle_unop_Not(self, expr: UnaryOp):
|
|
276
|
+
v = self._expr(expr.operand)
|
|
277
|
+
if isinstance(v, claripy.ast.Bits):
|
|
278
|
+
return ~v
|
|
279
|
+
return None
|
|
280
|
+
|
|
281
|
+
def _handle_unop_BitwiseNeg(self, expr: UnaryOp):
|
|
249
282
|
v = self._expr(expr.operand)
|
|
250
283
|
if isinstance(v, claripy.ast.Bits):
|
|
251
284
|
return ~v
|
|
252
285
|
return None
|
|
253
286
|
|
|
254
|
-
def
|
|
287
|
+
def _handle_unop_Default(self, expr: UnaryOp):
|
|
288
|
+
return None
|
|
289
|
+
|
|
290
|
+
_handle_unop_Clz = _handle_unop_Default
|
|
291
|
+
_handle_unop_Ctz = _handle_unop_Default
|
|
292
|
+
_handle_unop_Dereference = _handle_unop_Default
|
|
293
|
+
_handle_unop_Reference = _handle_unop_Default
|
|
294
|
+
_handle_unop_GetMSBs = _handle_unop_Default
|
|
295
|
+
_handle_unop_unpack = _handle_unop_Default
|
|
296
|
+
_handle_unop_Sqrt = _handle_unop_Default
|
|
297
|
+
_handle_unop_RSqrtEst = _handle_unop_Default
|
|
298
|
+
|
|
299
|
+
def _handle_expr_Convert(self, expr: Convert):
|
|
255
300
|
v = self._expr(expr.operand)
|
|
256
301
|
if isinstance(v, claripy.ast.Bits):
|
|
257
302
|
if expr.to_bits > expr.from_bits:
|
|
@@ -263,48 +308,139 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
263
308
|
return v
|
|
264
309
|
return None
|
|
265
310
|
|
|
266
|
-
def
|
|
311
|
+
def _handle_binop_CmpEQ(self, expr):
|
|
267
312
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
268
313
|
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
269
314
|
return claripy.BVV(1, 1) if op0.concrete_value == op1.concrete_value else claripy.BVV(0, 1)
|
|
270
315
|
return None
|
|
271
316
|
|
|
272
|
-
def
|
|
317
|
+
def _handle_binop_CmpNE(self, expr):
|
|
273
318
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
274
319
|
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
275
320
|
return claripy.BVV(1, 1) if op0.concrete_value != op1.concrete_value else claripy.BVV(0, 1)
|
|
276
321
|
return None
|
|
277
322
|
|
|
278
|
-
def
|
|
323
|
+
def _handle_binop_CmpLT(self, expr):
|
|
279
324
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
280
325
|
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
281
326
|
return claripy.BVV(1, 1) if op0.concrete_value < op1.concrete_value else claripy.BVV(0, 1)
|
|
282
327
|
return None
|
|
283
328
|
|
|
284
|
-
def
|
|
329
|
+
def _handle_binop_CmpLE(self, expr):
|
|
285
330
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
286
331
|
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
287
332
|
return claripy.BVV(1, 1) if op0.concrete_value <= op1.concrete_value else claripy.BVV(0, 1)
|
|
288
333
|
return None
|
|
289
334
|
|
|
290
|
-
def
|
|
335
|
+
def _handle_binop_CmpGT(self, expr):
|
|
291
336
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
292
337
|
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
293
338
|
return claripy.BVV(1, 1) if op0.concrete_value > op1.concrete_value else claripy.BVV(0, 1)
|
|
294
339
|
return None
|
|
295
340
|
|
|
296
|
-
def
|
|
341
|
+
def _handle_binop_CmpGE(self, expr):
|
|
297
342
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
298
343
|
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
299
344
|
return claripy.BVV(1, 1) if op0.concrete_value >= op1.concrete_value else claripy.BVV(0, 1)
|
|
300
345
|
return None
|
|
301
346
|
|
|
302
|
-
def
|
|
347
|
+
def _handle_stmt_Call(self, stmt):
|
|
303
348
|
pass
|
|
304
349
|
|
|
305
|
-
def
|
|
350
|
+
def _handle_expr_Call(self, expr):
|
|
306
351
|
pass
|
|
307
352
|
|
|
353
|
+
def _handle_expr_BasePointerOffset(self, expr):
|
|
354
|
+
return None
|
|
355
|
+
|
|
356
|
+
def _handle_expr_DirtyExpression(self, expr):
|
|
357
|
+
return None
|
|
358
|
+
|
|
359
|
+
def _handle_expr_ITE(self, expr):
|
|
360
|
+
return None
|
|
361
|
+
|
|
362
|
+
def _handle_expr_MultiStatementExpression(self, expr):
|
|
363
|
+
return None
|
|
364
|
+
|
|
365
|
+
def _handle_expr_Reinterpret(self, expr):
|
|
366
|
+
return None
|
|
367
|
+
|
|
368
|
+
def _handle_expr_StackBaseOffset(self, expr):
|
|
369
|
+
return None
|
|
370
|
+
|
|
371
|
+
def _handle_expr_Tmp(self, expr):
|
|
372
|
+
try:
|
|
373
|
+
return self.tmps[expr.tmp_idx]
|
|
374
|
+
except KeyError:
|
|
375
|
+
return None
|
|
376
|
+
|
|
377
|
+
def _handle_expr_VEXCCallExpression(self, expr):
|
|
378
|
+
return None
|
|
379
|
+
|
|
380
|
+
def _handle_binop_Default(self, expr):
|
|
381
|
+
self._expr(expr.operands[0])
|
|
382
|
+
self._expr(expr.operands[1])
|
|
383
|
+
|
|
384
|
+
_handle_binop_Add = _make_binop(lambda a, b: a + b)
|
|
385
|
+
_handle_binop_And = _make_binop(lambda a, b: a & b)
|
|
386
|
+
_handle_binop_Concat = _make_binop(lambda a, b: a.concat(b))
|
|
387
|
+
_handle_binop_Div = _make_binop(lambda a, b: a // b)
|
|
388
|
+
_handle_binop_LogicalAnd = _make_binop(lambda a, b: a & b)
|
|
389
|
+
_handle_binop_LogicalOr = _make_binop(lambda a, b: a | b)
|
|
390
|
+
_handle_binop_Mod = _make_binop(lambda a, b: a % b)
|
|
391
|
+
_handle_binop_Mul = _make_binop(lambda a, b: a * b)
|
|
392
|
+
_handle_binop_Or = _make_binop(lambda a, b: a | b)
|
|
393
|
+
_handle_binop_Rol = _make_binop(lambda a, b: claripy.RotateLeft(a, zeroextend_on_demand(a, b)))
|
|
394
|
+
_handle_binop_Ror = _make_binop(lambda a, b: claripy.RotateRight(a, zeroextend_on_demand(a, b)))
|
|
395
|
+
_handle_binop_Sar = _make_binop(lambda a, b: a >> zeroextend_on_demand(a, b))
|
|
396
|
+
_handle_binop_Shl = _make_binop(lambda a, b: a << zeroextend_on_demand(a, b))
|
|
397
|
+
_handle_binop_Shr = _make_binop(lambda a, b: a.LShR(zeroextend_on_demand(a, b)))
|
|
398
|
+
_handle_binop_Sub = _make_binop(lambda a, b: a - b)
|
|
399
|
+
_handle_binop_Xor = _make_binop(lambda a, b: a ^ b)
|
|
400
|
+
|
|
401
|
+
def _handle_binop_Mull(self, expr):
|
|
402
|
+
a, b = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
403
|
+
if a is None or b is None:
|
|
404
|
+
return None
|
|
405
|
+
xt = a.size()
|
|
406
|
+
if expr.signed:
|
|
407
|
+
return a.sign_extend(xt) * b.sign_extend(xt)
|
|
408
|
+
return a.zero_extend(xt) * b.zero_extend(xt)
|
|
409
|
+
|
|
410
|
+
_handle_binop_AddF = _handle_binop_Default
|
|
411
|
+
_handle_binop_AddV = _handle_binop_Default
|
|
412
|
+
_handle_binop_Carry = _handle_binop_Default
|
|
413
|
+
_handle_binop_CmpF = _handle_binop_Default
|
|
414
|
+
_handle_binop_DivF = _handle_binop_Default
|
|
415
|
+
_handle_binop_DivV = _handle_binop_Default
|
|
416
|
+
_handle_binop_InterleaveLOV = _handle_binop_Default
|
|
417
|
+
_handle_binop_InterleaveHIV = _handle_binop_Default
|
|
418
|
+
_handle_binop_CasCmpEQ = _handle_binop_Default
|
|
419
|
+
_handle_binop_CasCmpNE = _handle_binop_Default
|
|
420
|
+
_handle_binop_ExpCmpNE = _handle_binop_Default
|
|
421
|
+
_handle_binop_SarNV = _handle_binop_Default
|
|
422
|
+
_handle_binop_ShrNV = _handle_binop_Default
|
|
423
|
+
_handle_binop_ShlNV = _handle_binop_Default
|
|
424
|
+
_handle_binop_CmpEQV = _handle_binop_Default
|
|
425
|
+
_handle_binop_CmpNEV = _handle_binop_Default
|
|
426
|
+
_handle_binop_CmpGEV = _handle_binop_Default
|
|
427
|
+
_handle_binop_CmpGTV = _handle_binop_Default
|
|
428
|
+
_handle_binop_CmpLEV = _handle_binop_Default
|
|
429
|
+
_handle_binop_CmpLTV = _handle_binop_Default
|
|
430
|
+
_handle_binop_MulF = _handle_binop_Default
|
|
431
|
+
_handle_binop_MulV = _handle_binop_Default
|
|
432
|
+
_handle_binop_MulHiV = _handle_binop_Default
|
|
433
|
+
_handle_binop_SBorrow = _handle_binop_Default
|
|
434
|
+
_handle_binop_SCarry = _handle_binop_Default
|
|
435
|
+
_handle_binop_SubF = _handle_binop_Default
|
|
436
|
+
_handle_binop_SubV = _handle_binop_Default
|
|
437
|
+
_handle_binop_MinV = _handle_binop_Default
|
|
438
|
+
_handle_binop_MaxV = _handle_binop_Default
|
|
439
|
+
_handle_binop_QAddV = _handle_binop_Default
|
|
440
|
+
_handle_binop_QNarrowBinV = _handle_binop_Default
|
|
441
|
+
_handle_binop_PermV = _handle_binop_Default
|
|
442
|
+
_handle_binop_Set = _handle_binop_Default
|
|
443
|
+
|
|
308
444
|
|
|
309
445
|
class InlineStringTransformationDescriptor:
|
|
310
446
|
"""
|
|
@@ -387,6 +523,7 @@ class InlinedStringTransformationSimplifier(OptimizationPass):
|
|
|
387
523
|
|
|
388
524
|
# remote the loop node
|
|
389
525
|
# since the loop node has exactly one external predecessor and one external successor, we can get rid of it
|
|
526
|
+
assert self.out_graph is not None
|
|
390
527
|
pred = next(iter(nn for nn in self.out_graph.predecessors(desc.loop_body) if nn is not desc.loop_body))
|
|
391
528
|
succ = next(iter(nn for nn in self.out_graph.successors(desc.loop_body) if nn is not desc.loop_body))
|
|
392
529
|
|
|
@@ -404,16 +541,15 @@ class InlinedStringTransformationSimplifier(OptimizationPass):
|
|
|
404
541
|
def _find_string_transformation_loops(self):
|
|
405
542
|
# find self loops
|
|
406
543
|
self_loops = []
|
|
544
|
+
assert self._graph is not None
|
|
407
545
|
for node in self._graph.nodes:
|
|
408
546
|
preds = list(self._graph.predecessors(node))
|
|
409
547
|
succs = list(self._graph.successors(node))
|
|
410
548
|
if len(preds) == 2 and len(succs) == 2 and node in preds and node in succs:
|
|
411
549
|
pred = next(iter(nn for nn in preds if nn is not node))
|
|
412
550
|
succ = next(iter(nn for nn in succs if nn is not node))
|
|
413
|
-
if (
|
|
414
|
-
self._graph.out_degree[pred] ==
|
|
415
|
-
and self._graph.in_degree[succ] == 1
|
|
416
|
-
or self._graph.out_degree[pred] == 2
|
|
551
|
+
if (self._graph.out_degree[pred] == 1 and self._graph.in_degree[succ] == 1) or (
|
|
552
|
+
self._graph.out_degree[pred] == 2
|
|
417
553
|
and self._graph.in_degree[succ] == 2
|
|
418
554
|
and self._graph.has_edge(pred, succ)
|
|
419
555
|
):
|
|
@@ -314,9 +314,6 @@ class ITERegionConverter(OptimizationPass):
|
|
|
314
314
|
|
|
315
315
|
@staticmethod
|
|
316
316
|
def _is_assigning_to_vvar(stmt: Statement) -> bool:
|
|
317
|
-
return (
|
|
318
|
-
isinstance(stmt,
|
|
319
|
-
and isinstance(stmt.dst, VirtualVariable)
|
|
320
|
-
or isinstance(stmt, Call)
|
|
321
|
-
and isinstance(stmt.ret_expr, VirtualVariable)
|
|
317
|
+
return (isinstance(stmt, Assignment) and isinstance(stmt.dst, VirtualVariable)) or (
|
|
318
|
+
isinstance(stmt, Call) and isinstance(stmt.ret_expr, VirtualVariable)
|
|
322
319
|
)
|
|
@@ -31,14 +31,14 @@ class Case:
|
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
33
|
__slots__ = (
|
|
34
|
-
"original_node",
|
|
35
|
-
"node_type",
|
|
36
|
-
"variable_hash",
|
|
37
34
|
"expr",
|
|
38
|
-
"
|
|
35
|
+
"next_addr",
|
|
36
|
+
"node_type",
|
|
37
|
+
"original_node",
|
|
39
38
|
"target",
|
|
40
39
|
"target_idx",
|
|
41
|
-
"
|
|
40
|
+
"value",
|
|
41
|
+
"variable_hash",
|
|
42
42
|
)
|
|
43
43
|
|
|
44
44
|
def __init__(
|
|
@@ -12,7 +12,7 @@ _l.addFilter(UniqueLogFilter())
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ModSimplifierAILEngine(SimplifierAILEngine):
|
|
15
|
-
def
|
|
15
|
+
def _handle_binop_Sub(self, expr):
|
|
16
16
|
operand_0 = self._expr(expr.operands[0])
|
|
17
17
|
operand_1 = self._expr(expr.operands[1])
|
|
18
18
|
|
|
@@ -41,7 +41,15 @@ class ModSimplifierAILEngine(SimplifierAILEngine):
|
|
|
41
41
|
c_0 = operand_1.operands[1]
|
|
42
42
|
c_1 = operand_1.operands[0].operand.operands[1]
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
# pylint: disable=too-many-boolean-expressions
|
|
45
|
+
if (
|
|
46
|
+
x_0 is not None
|
|
47
|
+
and x_1 is not None
|
|
48
|
+
and c_0 is not None
|
|
49
|
+
and c_1 is not None
|
|
50
|
+
and x_0.likes(x_1)
|
|
51
|
+
and c_0.value == c_1.value
|
|
52
|
+
):
|
|
45
53
|
return Expr.BinaryOp(expr.idx, "Mod", [x_0, c_0], expr.signed, **expr.tags)
|
|
46
54
|
|
|
47
55
|
if (operand_0, operand_1) != (expr.operands[0], expr.operands[1]):
|
|
@@ -70,7 +78,7 @@ class ModSimplifier(OptimizationPass):
|
|
|
70
78
|
super().__init__(func, **kwargs)
|
|
71
79
|
|
|
72
80
|
self.state = SimplifierAILState(self.project.arch)
|
|
73
|
-
self.engine = ModSimplifierAILEngine()
|
|
81
|
+
self.engine = ModSimplifierAILEngine(self.project)
|
|
74
82
|
|
|
75
83
|
self.analyze()
|
|
76
84
|
|
|
@@ -78,6 +86,7 @@ class ModSimplifier(OptimizationPass):
|
|
|
78
86
|
return True, None
|
|
79
87
|
|
|
80
88
|
def _analyze(self, cache=None):
|
|
89
|
+
assert self._graph is not None
|
|
81
90
|
for block in list(self._graph.nodes()):
|
|
82
91
|
new_block = block
|
|
83
92
|
old_block = None
|
|
@@ -5,15 +5,17 @@ from typing import Any, TYPE_CHECKING
|
|
|
5
5
|
from collections.abc import Generator
|
|
6
6
|
from enum import Enum
|
|
7
7
|
|
|
8
|
-
import networkx
|
|
8
|
+
import networkx
|
|
9
|
+
|
|
9
10
|
import ailment
|
|
10
11
|
|
|
11
12
|
from angr.analyses.decompiler import RegionIdentifier
|
|
12
13
|
from angr.analyses.decompiler.condition_processor import ConditionProcessor
|
|
13
|
-
from angr.analyses.decompiler.goto_manager import GotoManager
|
|
14
|
+
from angr.analyses.decompiler.goto_manager import Goto, GotoManager
|
|
14
15
|
from angr.analyses.decompiler.structuring import RecursiveStructurer, SAILRStructurer
|
|
15
16
|
from angr.analyses.decompiler.utils import add_labels
|
|
16
17
|
from angr.analyses.decompiler.counters import ControlFlowStructureCounter
|
|
18
|
+
from angr.project import Project
|
|
17
19
|
|
|
18
20
|
if TYPE_CHECKING:
|
|
19
21
|
from angr.knowledge_plugins.functions import Function
|
|
@@ -60,8 +62,10 @@ class BaseOptimizationPass:
|
|
|
60
62
|
|
|
61
63
|
ARCHES = [] # strings of supported architectures
|
|
62
64
|
PLATFORMS = [] # strings of supported platforms. Can be one of the following: "win32", "linux"
|
|
63
|
-
STAGE:
|
|
64
|
-
STRUCTURING: str | None =
|
|
65
|
+
STAGE: OptimizationPassStage # Specifies when this optimization pass should be executed
|
|
66
|
+
STRUCTURING: list[str] | None = (
|
|
67
|
+
None # specifies if this optimization pass is specific to a certain structuring algorithm
|
|
68
|
+
)
|
|
65
69
|
NAME = "N/A"
|
|
66
70
|
DESCRIPTION = "N/A"
|
|
67
71
|
|
|
@@ -69,7 +73,8 @@ class BaseOptimizationPass:
|
|
|
69
73
|
self._func: Function = func
|
|
70
74
|
|
|
71
75
|
@property
|
|
72
|
-
def project(self):
|
|
76
|
+
def project(self) -> Project:
|
|
77
|
+
assert self._func.project is not None
|
|
73
78
|
return self._func.project
|
|
74
79
|
|
|
75
80
|
@property
|
|
@@ -115,17 +120,18 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
115
120
|
variable_kb=None,
|
|
116
121
|
region_identifier=None,
|
|
117
122
|
reaching_definitions=None,
|
|
118
|
-
vvar_id_start=
|
|
123
|
+
vvar_id_start: int = 0,
|
|
119
124
|
entry_node_addr=None,
|
|
120
125
|
scratch: dict[str, Any] | None = None,
|
|
121
126
|
force_loop_single_exit: bool = True,
|
|
122
127
|
complete_successors: bool = False,
|
|
128
|
+
avoid_vvar_ids: set[int] | None = None,
|
|
123
129
|
**kwargs,
|
|
124
130
|
):
|
|
125
131
|
super().__init__(func)
|
|
126
132
|
# self._blocks is just a cache
|
|
127
|
-
self._blocks_by_addr: dict[int, set[ailment.Block]] = blocks_by_addr
|
|
128
|
-
self._blocks_by_addr_and_idx: dict[tuple[int, int | None], ailment.Block] = blocks_by_addr_and_idx
|
|
133
|
+
self._blocks_by_addr: dict[int, set[ailment.Block]] = blocks_by_addr or {}
|
|
134
|
+
self._blocks_by_addr_and_idx: dict[tuple[int, int | None], ailment.Block] = blocks_by_addr_and_idx or {}
|
|
129
135
|
self._graph: networkx.DiGraph | None = graph
|
|
130
136
|
self._variable_kb = variable_kb
|
|
131
137
|
self._ri = region_identifier
|
|
@@ -138,6 +144,7 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
138
144
|
)
|
|
139
145
|
self._force_loop_single_exit = force_loop_single_exit
|
|
140
146
|
self._complete_successors = complete_successors
|
|
147
|
+
self._avoid_vvar_ids = avoid_vvar_ids or set()
|
|
141
148
|
|
|
142
149
|
# output
|
|
143
150
|
self.out_graph: networkx.DiGraph | None = None
|
|
@@ -164,10 +171,23 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
164
171
|
self._new_block_addrs.add(new_addr)
|
|
165
172
|
return new_addr
|
|
166
173
|
|
|
167
|
-
def _get_block(self, addr,
|
|
174
|
+
def _get_block(self, addr, **kwargs) -> ailment.Block | None:
|
|
175
|
+
"""
|
|
176
|
+
Get exactly one block by its address and optionally, also considering its block ID. An exception,
|
|
177
|
+
MultipleBlocksException, will be raised if there are more than one block satisfying the specified criteria.
|
|
178
|
+
|
|
179
|
+
:param addr: The address of the block.
|
|
180
|
+
:param kwargs: Optionally, you can specify "idx" to consider the block ID. If "idx" is not specified, this
|
|
181
|
+
method will return the only block at the specified address, None if there is no block at
|
|
182
|
+
that address, or raise an exception if there are more than one block at that address.
|
|
183
|
+
:return: The requested block or None if no block matching the specified criteria exists.
|
|
184
|
+
"""
|
|
185
|
+
|
|
168
186
|
if not self._blocks_by_addr:
|
|
169
187
|
return None
|
|
170
|
-
|
|
188
|
+
idx_specified = "idx" in kwargs
|
|
189
|
+
idx = kwargs.get("idx")
|
|
190
|
+
if not idx_specified:
|
|
171
191
|
blocks = self._blocks_by_addr.get(addr, None)
|
|
172
192
|
else:
|
|
173
193
|
blocks = [self._blocks_by_addr_and_idx.get((addr, idx), None)]
|
|
@@ -175,8 +195,12 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
175
195
|
return None
|
|
176
196
|
if len(blocks) == 1:
|
|
177
197
|
return next(iter(blocks))
|
|
198
|
+
if idx_specified:
|
|
199
|
+
raise MultipleBlocksException(
|
|
200
|
+
f"There are {len(blocks)} blocks at address {addr:#x}.{idx} but only one is requested."
|
|
201
|
+
)
|
|
178
202
|
raise MultipleBlocksException(
|
|
179
|
-
"There are
|
|
203
|
+
f"There are {len(blocks)} blocks at address {addr:#x} (block ID ignored) but only one is requested."
|
|
180
204
|
)
|
|
181
205
|
|
|
182
206
|
def _get_blocks(self, addr, idx=None) -> Generator[ailment.Block]:
|
|
@@ -195,6 +219,7 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
195
219
|
def _update_block(self, old_block, new_block):
|
|
196
220
|
if self.out_graph is None:
|
|
197
221
|
self.out_graph = self._graph # we do not make copy here for performance reasons. we can change it if needed
|
|
222
|
+
assert self.out_graph is not None
|
|
198
223
|
|
|
199
224
|
if old_block not in self.out_graph:
|
|
200
225
|
return
|
|
@@ -220,6 +245,7 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
220
245
|
def _remove_block(self, block):
|
|
221
246
|
if self.out_graph is None:
|
|
222
247
|
self.out_graph = self._graph
|
|
248
|
+
assert self.out_graph is not None
|
|
223
249
|
|
|
224
250
|
if block in self.out_graph:
|
|
225
251
|
self.out_graph.remove_node(block)
|
|
@@ -244,6 +270,7 @@ class OptimizationPass(BaseOptimizationPass):
|
|
|
244
270
|
func_graph=graph,
|
|
245
271
|
use_callee_saved_regs_at_return=False,
|
|
246
272
|
gp=self._func.info.get("gp", None) if self.project.arch.name in {"MIPS32", "MIPS64"} else None,
|
|
273
|
+
avoid_vvar_ids=self._avoid_vvar_ids,
|
|
247
274
|
)
|
|
248
275
|
if simp.simplified:
|
|
249
276
|
graph = simp.func_graph
|
|
@@ -270,10 +297,6 @@ class SequenceOptimizationPass(BaseOptimizationPass):
|
|
|
270
297
|
The base class for any sequence node optimization pass.
|
|
271
298
|
"""
|
|
272
299
|
|
|
273
|
-
ARCHES = [] # strings of supported architectures
|
|
274
|
-
PLATFORMS = [] # strings of supported platforms. Can be one of the following: "win32", "linux"
|
|
275
|
-
STAGE: int = None # Specifies when this optimization pass should be executed
|
|
276
|
-
|
|
277
300
|
def __init__(self, func, seq=None, **kwargs):
|
|
278
301
|
super().__init__(func)
|
|
279
302
|
self.seq = seq
|
|
@@ -298,6 +321,10 @@ class StructuringOptimizationPass(OptimizationPass):
|
|
|
298
321
|
STRUCTURING = [SAILRStructurer.NAME]
|
|
299
322
|
STAGE = OptimizationPassStage.DURING_REGION_IDENTIFICATION
|
|
300
323
|
|
|
324
|
+
_initial_gotos: set[Goto]
|
|
325
|
+
_goto_manager: GotoManager
|
|
326
|
+
_prev_graph: networkx.DiGraph
|
|
327
|
+
|
|
301
328
|
def __init__(
|
|
302
329
|
self,
|
|
303
330
|
func,
|
|
@@ -321,10 +348,6 @@ class StructuringOptimizationPass(OptimizationPass):
|
|
|
321
348
|
self._must_improve_rel_quality = must_improve_rel_quality
|
|
322
349
|
self._readd_labels = readd_labels
|
|
323
350
|
|
|
324
|
-
self._initial_gotos = None
|
|
325
|
-
self._goto_manager: GotoManager | None = None
|
|
326
|
-
self._prev_graph: networkx.DiGraph | None = None
|
|
327
|
-
|
|
328
351
|
# relative quality metrics (excludes gotos)
|
|
329
352
|
self._initial_structure_counter = None
|
|
330
353
|
self._current_structure_counter = None
|