angr 9.2.135__py3-none-manylinux2014_x86_64.whl → 9.2.137__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/__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/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 +193 -191
- {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
|
@@ -30,8 +30,7 @@ class ClassIdentifier(Analysis):
|
|
|
30
30
|
continue
|
|
31
31
|
col_ind = func.demangled_name.rfind("::")
|
|
32
32
|
class_name = func.demangled_name[:col_ind]
|
|
33
|
-
|
|
34
|
-
class_name = class_name[len("non-virtual thunk for ") :]
|
|
33
|
+
class_name = class_name.removeprefix("non-virtual thunk for ")
|
|
35
34
|
if col_ind != -1:
|
|
36
35
|
if class_name not in self.classes:
|
|
37
36
|
ctor = False
|
|
@@ -208,6 +208,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
208
208
|
self._update_progress(percentage, text=f"{idx + 1}/{total_funcs} - {func.demangled_name}")
|
|
209
209
|
if self._low_priority:
|
|
210
210
|
self._release_gil(idx + 1, 10, 0.000001)
|
|
211
|
+
self._finish_progress()
|
|
211
212
|
|
|
212
213
|
else:
|
|
213
214
|
self._remaining_funcs.value = len(self._func_addrs)
|
|
@@ -298,6 +299,8 @@ class CompleteCallingConventionsAnalysis(Analysis):
|
|
|
298
299
|
for proc in procs:
|
|
299
300
|
proc.join()
|
|
300
301
|
|
|
302
|
+
self._finish_progress()
|
|
303
|
+
|
|
301
304
|
def _worker_routine(self, worker_id: int, initializer: Initializer):
|
|
302
305
|
initializer.initialize()
|
|
303
306
|
idx = 0
|
|
@@ -3,6 +3,8 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
import claripy
|
|
5
5
|
|
|
6
|
+
from angr.errors import AngrIncongruencyError
|
|
7
|
+
from angr.analyses import AnalysesHub
|
|
6
8
|
from . import Analysis
|
|
7
9
|
|
|
8
10
|
l = logging.getLogger(name=__name__)
|
|
@@ -372,7 +374,4 @@ class CongruencyCheck(Analysis):
|
|
|
372
374
|
return True
|
|
373
375
|
|
|
374
376
|
|
|
375
|
-
from angr.errors import AngrIncongruencyError
|
|
376
|
-
from angr.analyses import AnalysesHub
|
|
377
|
-
|
|
378
377
|
AnalysesHub.register_default("CongruencyCheck", CongruencyCheck)
|
|
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|
|
9
9
|
from networkx import DiGraph
|
|
10
10
|
|
|
11
11
|
import claripy
|
|
12
|
-
from claripy.ast
|
|
12
|
+
from claripy.ast import BV
|
|
13
13
|
from .dep_nodes import DepNodeTypes, ConstantDepNode, MemDepNode, VarDepNode, RegDepNode, TmpDepNode
|
|
14
14
|
from .sim_act_location import SimActLocation, DEFAULT_LOCATION, ParsedInstruction
|
|
15
15
|
from angr.analyses import Analysis
|
|
@@ -173,7 +173,7 @@ class DataDependencyGraphAnalysis(Analysis):
|
|
|
173
173
|
self,
|
|
174
174
|
type_: int,
|
|
175
175
|
sim_act: SimActionData,
|
|
176
|
-
val: tuple[BV, int],
|
|
176
|
+
val: tuple[claripy.ast.BV, int],
|
|
177
177
|
*constructor_params,
|
|
178
178
|
) -> BaseDepNode:
|
|
179
179
|
"""
|
angr/analyses/ddg.py
CHANGED
|
@@ -6,8 +6,7 @@ import claripy
|
|
|
6
6
|
import networkx
|
|
7
7
|
import pyvex
|
|
8
8
|
|
|
9
|
-
from . import Analysis
|
|
10
|
-
|
|
9
|
+
from angr.analyses import Analysis, AnalysesHub
|
|
11
10
|
from angr.code_location import CodeLocation
|
|
12
11
|
from angr.errors import SimSolverModeError, SimUnsatError, AngrDDGError
|
|
13
12
|
from angr.sim_variable import (
|
|
@@ -1668,6 +1667,4 @@ class DDG(Analysis):
|
|
|
1668
1667
|
return sources
|
|
1669
1668
|
|
|
1670
1669
|
|
|
1671
|
-
from angr.analyses import AnalysesHub
|
|
1672
|
-
|
|
1673
1670
|
AnalysesHub.register_default("DDG", DDG)
|
|
@@ -207,25 +207,28 @@ class AILSimplifier(Analysis):
|
|
|
207
207
|
# Computing reaching definitions or return the cached one
|
|
208
208
|
if self._reaching_definitions is not None:
|
|
209
209
|
return self._reaching_definitions
|
|
210
|
+
func_args = {vvar for vvar, _ in self._arg_vvars.values()} if self._arg_vvars else set()
|
|
210
211
|
rd = self.project.analyses.SReachingDefinitions(
|
|
211
212
|
subject=self.func,
|
|
212
213
|
func_graph=self.func_graph,
|
|
214
|
+
func_args=func_args,
|
|
213
215
|
# use_callee_saved_regs_at_return=self._use_callee_saved_regs_at_return,
|
|
214
216
|
# track_tmps=True,
|
|
215
217
|
).model
|
|
216
218
|
self._reaching_definitions = rd
|
|
217
219
|
return rd
|
|
218
220
|
|
|
219
|
-
def _compute_propagation(self
|
|
221
|
+
def _compute_propagation(self) -> SPropagatorAnalysis:
|
|
220
222
|
# Propagate expressions or return the existing result
|
|
221
223
|
if self._propagator is not None:
|
|
222
224
|
return self._propagator
|
|
223
|
-
|
|
225
|
+
func_args = {vvar for vvar, _ in self._arg_vvars.values()} if self._arg_vvars else set()
|
|
226
|
+
prop = self.project.analyses[SPropagatorAnalysis].prep(fail_fast=self._fail_fast)(
|
|
224
227
|
subject=self.func,
|
|
225
228
|
func_graph=self.func_graph,
|
|
229
|
+
func_args=func_args,
|
|
226
230
|
# gp=self._gp,
|
|
227
231
|
only_consts=self._only_consts,
|
|
228
|
-
immediate_stmt_removal=immediate_stmt_removal,
|
|
229
232
|
)
|
|
230
233
|
self._propagator = prop
|
|
231
234
|
return prop
|
|
@@ -354,7 +357,7 @@ class AILSimplifier(Analysis):
|
|
|
354
357
|
):
|
|
355
358
|
repeat = False
|
|
356
359
|
narrowable_phivarids = set()
|
|
357
|
-
for def_vvarid
|
|
360
|
+
for def_vvarid in narrowing_candidates:
|
|
358
361
|
if def_vvarid in blacklist_varids:
|
|
359
362
|
continue
|
|
360
363
|
if def_vvarid in rd.phi_vvar_ids:
|
|
@@ -591,7 +594,7 @@ class AILSimplifier(Analysis):
|
|
|
591
594
|
"""
|
|
592
595
|
|
|
593
596
|
# propagator
|
|
594
|
-
propagator = self._compute_propagation(
|
|
597
|
+
propagator = self._compute_propagation()
|
|
595
598
|
replacements = propagator.replacements
|
|
596
599
|
|
|
597
600
|
# take replacements and rebuild the corresponding blocks
|
|
@@ -899,6 +902,13 @@ class AILSimplifier(Analysis):
|
|
|
899
902
|
|
|
900
903
|
to_replace_def = the_def
|
|
901
904
|
|
|
905
|
+
# check: the definition of expression being replaced should not be a phi variable
|
|
906
|
+
if (
|
|
907
|
+
isinstance(to_replace_def.atom, atoms.VirtualVariable)
|
|
908
|
+
and to_replace_def.atom.varid in rd.phi_vvar_ids
|
|
909
|
+
):
|
|
910
|
+
continue
|
|
911
|
+
|
|
902
912
|
# find all uses of this definition
|
|
903
913
|
# we make a copy of the set since we may touch the set (uses) when replacing expressions
|
|
904
914
|
all_uses: set[tuple[CodeLocation, Any]] = set(rd.get_vvar_uses_with_expr(to_replace_def.atom))
|
|
@@ -141,7 +141,7 @@ class BlockSimplifier(Analysis):
|
|
|
141
141
|
|
|
142
142
|
def _compute_propagation(self, block) -> SPropagatorAnalysis:
|
|
143
143
|
if self._propagator is None:
|
|
144
|
-
self._propagator = self.project.analyses[SPropagatorAnalysis].prep()(
|
|
144
|
+
self._propagator = self.project.analyses[SPropagatorAnalysis].prep(fail_fast=self._fail_fast)(
|
|
145
145
|
subject=block,
|
|
146
146
|
func_addr=self.func_addr,
|
|
147
147
|
stack_pointer_tracker=self._stack_pointer_tracker,
|
|
@@ -152,7 +152,7 @@ class BlockSimplifier(Analysis):
|
|
|
152
152
|
if self._reaching_definitions is None:
|
|
153
153
|
self._reaching_definitions = (
|
|
154
154
|
self.project.analyses[SReachingDefinitionsAnalysis]
|
|
155
|
-
.prep()(
|
|
155
|
+
.prep(fail_fast=self._fail_fast)(
|
|
156
156
|
subject=block,
|
|
157
157
|
track_tmps=True,
|
|
158
158
|
func_addr=self.func_addr,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ailment import Expr
|
|
4
|
+
|
|
5
|
+
from angr.engines.vex.claripy.ccall import data
|
|
6
|
+
from .rewriter_base import CCallRewriterBase
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
X86_CondTypes = data["X86"]["CondTypes"]
|
|
10
|
+
X86_OpTypes = data["X86"]["OpTypes"]
|
|
11
|
+
X86_CondBitMasks = data["X86"]["CondBitMasks"]
|
|
12
|
+
X86_CondBitOffsets = data["X86"]["CondBitOffsets"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class X86CCallRewriter(CCallRewriterBase):
|
|
16
|
+
"""
|
|
17
|
+
Implements VEX ccall rewriter for X86.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
__slots__ = ()
|
|
21
|
+
|
|
22
|
+
def _rewrite(self, ccall: Expr.VEXCCallExpression) -> Expr.Expression | None:
|
|
23
|
+
if ccall.callee == "x86g_calculate_condition":
|
|
24
|
+
cond = ccall.operands[0]
|
|
25
|
+
op = ccall.operands[1]
|
|
26
|
+
dep_1 = ccall.operands[2]
|
|
27
|
+
dep_2 = ccall.operands[3]
|
|
28
|
+
if isinstance(cond, Expr.Const) and isinstance(op, Expr.Const):
|
|
29
|
+
cond_v = cond.value
|
|
30
|
+
op_v = op.value
|
|
31
|
+
if cond_v == X86_CondTypes["CondLE"]: # noqa: SIM102
|
|
32
|
+
if op_v in {
|
|
33
|
+
X86_OpTypes["G_CC_OP_SUBB"],
|
|
34
|
+
X86_OpTypes["G_CC_OP_SUBW"],
|
|
35
|
+
X86_OpTypes["G_CC_OP_SUBL"],
|
|
36
|
+
}:
|
|
37
|
+
# dep_1 <=s dep_2
|
|
38
|
+
dep_1 = self._fix_size(
|
|
39
|
+
dep_1,
|
|
40
|
+
op_v,
|
|
41
|
+
X86_OpTypes["G_CC_OP_SUBB"],
|
|
42
|
+
X86_OpTypes["G_CC_OP_SUBW"],
|
|
43
|
+
ccall.tags,
|
|
44
|
+
)
|
|
45
|
+
dep_2 = self._fix_size(
|
|
46
|
+
dep_2,
|
|
47
|
+
op_v,
|
|
48
|
+
X86_OpTypes["G_CC_OP_SUBB"],
|
|
49
|
+
X86_OpTypes["G_CC_OP_SUBW"],
|
|
50
|
+
ccall.tags,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
r = Expr.BinaryOp(ccall.idx, "CmpLE", (dep_1, dep_2), True, **ccall.tags)
|
|
54
|
+
return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def _fix_size(expr, op_v: int, type_8bit, type_16bit, tags):
|
|
59
|
+
if op_v == type_8bit:
|
|
60
|
+
bits = 8
|
|
61
|
+
elif op_v == type_16bit:
|
|
62
|
+
bits = 16
|
|
63
|
+
else:
|
|
64
|
+
bits = 32
|
|
65
|
+
if bits < 32:
|
|
66
|
+
if isinstance(expr, Expr.Const):
|
|
67
|
+
return Expr.Const(expr.idx, None, expr.value & ((1 << bits) - 1), bits, **tags)
|
|
68
|
+
return Expr.Convert(None, 32, bits, False, expr, **tags)
|
|
69
|
+
return expr
|
|
@@ -49,7 +49,6 @@ from .optimization_passes import (
|
|
|
49
49
|
DUPLICATING_OPTS,
|
|
50
50
|
CONDENSING_OPTS,
|
|
51
51
|
)
|
|
52
|
-
from .utils import first_nonlabel_statement_id
|
|
53
52
|
|
|
54
53
|
if TYPE_CHECKING:
|
|
55
54
|
from angr.knowledge_plugins.cfg import CFGModel
|
|
@@ -461,12 +460,12 @@ class Clinic(Analysis):
|
|
|
461
460
|
# Make function arguments
|
|
462
461
|
self._update_progress(33.0, text="Making argument list")
|
|
463
462
|
arg_list = self._make_argument_list()
|
|
464
|
-
arg_vvars =
|
|
465
|
-
|
|
463
|
+
arg_vvars = self._create_function_argument_vvars(arg_list)
|
|
464
|
+
func_args = {arg_vvar for arg_vvar, _ in arg_vvars.values()}
|
|
466
465
|
|
|
467
466
|
# Transform the graph into partial SSA form
|
|
468
467
|
self._update_progress(35.0, text="Transforming to partial-SSA form")
|
|
469
|
-
ail_graph = self._transform_to_ssa_level0(ail_graph)
|
|
468
|
+
ail_graph = self._transform_to_ssa_level0(ail_graph, func_args)
|
|
470
469
|
|
|
471
470
|
# full-function constant-only propagation
|
|
472
471
|
self._update_progress(36.0, text="Constant propagation")
|
|
@@ -521,15 +520,20 @@ class Clinic(Analysis):
|
|
|
521
520
|
)
|
|
522
521
|
|
|
523
522
|
# rewrite (qualified) stack variables into SSA form
|
|
524
|
-
ail_graph = self._transform_to_ssa_level1(ail_graph)
|
|
523
|
+
ail_graph = self._transform_to_ssa_level1(ail_graph, func_args)
|
|
525
524
|
|
|
526
525
|
# clear _blocks_by_addr_and_size so no one can use it again
|
|
527
526
|
# TODO: Totally remove this dict
|
|
528
527
|
self._blocks_by_addr_and_size = None
|
|
529
528
|
|
|
529
|
+
# Rust-specific; only call this on Rust binaries when we can identify language and compiler
|
|
530
|
+
ail_graph = self._rewrite_rust_probestack_call(ail_graph)
|
|
531
|
+
# Windows-specific
|
|
532
|
+
ail_graph = self._rewrite_windows_stkchk_call(ail_graph)
|
|
533
|
+
|
|
530
534
|
# Make call-sites
|
|
531
535
|
self._update_progress(50.0, text="Making callsites")
|
|
532
|
-
_, stackarg_offsets, removed_vvar_ids = self._make_callsites(ail_graph, stack_pointer_tracker=spt)
|
|
536
|
+
_, stackarg_offsets, removed_vvar_ids = self._make_callsites(ail_graph, func_args, stack_pointer_tracker=spt)
|
|
533
537
|
|
|
534
538
|
# Run simplification passes
|
|
535
539
|
self._update_progress(53.0, text="Running simplifications 2")
|
|
@@ -1010,13 +1014,15 @@ class Clinic(Analysis):
|
|
|
1010
1014
|
if node is None:
|
|
1011
1015
|
continue
|
|
1012
1016
|
successors = self._cfg.get_successors(node, excluding_fakeret=True, jumpkind="Ijk_Call")
|
|
1013
|
-
if len(successors) == 1
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1017
|
+
if len(successors) == 1:
|
|
1018
|
+
succ_addr = successors[0].addr
|
|
1019
|
+
if not self.project.is_hooked(succ_addr) or not isinstance(
|
|
1020
|
+
self.project.hooked_by(successors[0].addr), UnresolvableCallTarget
|
|
1021
|
+
):
|
|
1022
|
+
# found a single successor - replace the last statement
|
|
1023
|
+
new_last_stmt = last_stmt.copy()
|
|
1024
|
+
new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
|
|
1025
|
+
block.statements[-1] = new_last_stmt
|
|
1020
1026
|
|
|
1021
1027
|
elif isinstance(last_stmt, ailment.Stmt.Jump) and not isinstance(last_stmt.target, ailment.Expr.Const):
|
|
1022
1028
|
# indirect jump
|
|
@@ -1301,84 +1307,57 @@ class Clinic(Analysis):
|
|
|
1301
1307
|
return ail_graph
|
|
1302
1308
|
|
|
1303
1309
|
@timethis
|
|
1304
|
-
def
|
|
1305
|
-
|
|
1306
|
-
arg_list: list[SimVariable],
|
|
1307
|
-
ail_graph: networkx.DiGraph,
|
|
1308
|
-
arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]],
|
|
1309
|
-
) -> networkx.DiGraph:
|
|
1310
|
-
entrypoint = next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr))
|
|
1311
|
-
new_stmts = []
|
|
1310
|
+
def _create_function_argument_vvars(self, arg_list) -> dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]]:
|
|
1311
|
+
arg_vvars = {}
|
|
1312
1312
|
for arg in arg_list:
|
|
1313
|
-
if
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
# get the full register if needed
|
|
1317
|
-
basereg_offset, basereg_size = self.project.arch.get_base_register(arg.reg, size=arg.size)
|
|
1318
|
-
|
|
1319
|
-
arg_vvar = ailment.Expr.VirtualVariable(
|
|
1320
|
-
self._ail_manager.next_atom(),
|
|
1321
|
-
self.vvar_id_start,
|
|
1322
|
-
arg.bits,
|
|
1323
|
-
ailment.Expr.VirtualVariableCategory.PARAMETER,
|
|
1324
|
-
oident=arg.reg,
|
|
1325
|
-
ins_addr=self.function.addr,
|
|
1326
|
-
vex_block_addr=self.function.addr,
|
|
1327
|
-
)
|
|
1328
|
-
self.vvar_id_start += 1
|
|
1329
|
-
arg_vvars[arg_vvar.varid] = arg_vvar, arg
|
|
1330
|
-
|
|
1331
|
-
if basereg_size != arg.size:
|
|
1332
|
-
# extend the value to the full register
|
|
1333
|
-
arg_vvar = ailment.Expr.Convert(
|
|
1313
|
+
if isinstance(arg, SimRegisterVariable):
|
|
1314
|
+
# get the full register if needed
|
|
1315
|
+
arg_vvar = ailment.Expr.VirtualVariable(
|
|
1334
1316
|
self._ail_manager.next_atom(),
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1317
|
+
self.vvar_id_start,
|
|
1318
|
+
arg.bits,
|
|
1319
|
+
ailment.Expr.VirtualVariableCategory.PARAMETER,
|
|
1320
|
+
oident=(ailment.Expr.VirtualVariableCategory.REGISTER, arg.reg),
|
|
1339
1321
|
ins_addr=self.function.addr,
|
|
1340
1322
|
vex_block_addr=self.function.addr,
|
|
1341
1323
|
)
|
|
1324
|
+
self.vvar_id_start += 1
|
|
1325
|
+
arg_vvars[arg_vvar.varid] = arg_vvar, arg
|
|
1326
|
+
elif isinstance(arg, SimStackVariable):
|
|
1327
|
+
arg_vvar = ailment.Expr.VirtualVariable(
|
|
1328
|
+
self._ail_manager.next_atom(),
|
|
1329
|
+
self.vvar_id_start,
|
|
1330
|
+
arg.bits,
|
|
1331
|
+
ailment.Expr.VirtualVariableCategory.PARAMETER,
|
|
1332
|
+
oident=(ailment.Expr.VirtualVariableCategory.STACK, arg.offset),
|
|
1333
|
+
ins_addr=self.function.addr,
|
|
1334
|
+
vex_block_addr=self.function.addr,
|
|
1335
|
+
)
|
|
1336
|
+
self.vvar_id_start += 1
|
|
1337
|
+
arg_vvars[arg_vvar.varid] = arg_vvar, arg
|
|
1342
1338
|
|
|
1343
|
-
|
|
1344
|
-
self._ail_manager.next_atom(),
|
|
1345
|
-
None,
|
|
1346
|
-
basereg_offset,
|
|
1347
|
-
basereg_size * self.project.arch.byte_width,
|
|
1348
|
-
ins_addr=self.function.addr,
|
|
1349
|
-
vex_block_addr=self.function.addr,
|
|
1350
|
-
)
|
|
1351
|
-
stmt = ailment.Stmt.Assignment(
|
|
1352
|
-
self._ail_manager.next_atom(),
|
|
1353
|
-
fullreg_dst,
|
|
1354
|
-
arg_vvar,
|
|
1355
|
-
ins_addr=self.function.addr,
|
|
1356
|
-
vex_block_addr=self.function.addr,
|
|
1357
|
-
)
|
|
1358
|
-
new_stmts.append(stmt)
|
|
1359
|
-
|
|
1360
|
-
non_label_stmt_idx = first_nonlabel_statement_id(entrypoint)
|
|
1361
|
-
# update the ail block in-place
|
|
1362
|
-
entrypoint.statements = (
|
|
1363
|
-
entrypoint.statements[:non_label_stmt_idx] + new_stmts + entrypoint.statements[non_label_stmt_idx:]
|
|
1364
|
-
)
|
|
1365
|
-
return ail_graph
|
|
1339
|
+
return arg_vvars
|
|
1366
1340
|
|
|
1367
1341
|
@timethis
|
|
1368
|
-
def _transform_to_ssa_level0(
|
|
1342
|
+
def _transform_to_ssa_level0(
|
|
1343
|
+
self, ail_graph: networkx.DiGraph, func_args: set[ailment.Expr.VirtualVariable]
|
|
1344
|
+
) -> networkx.DiGraph:
|
|
1369
1345
|
ssailification = self.project.analyses[Ssailification].prep(fail_fast=self._fail_fast)(
|
|
1370
1346
|
self.function,
|
|
1371
1347
|
ail_graph,
|
|
1372
1348
|
entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
|
|
1373
1349
|
ail_manager=self._ail_manager,
|
|
1374
1350
|
ssa_stackvars=False,
|
|
1351
|
+
func_args=func_args,
|
|
1375
1352
|
vvar_id_start=self.vvar_id_start,
|
|
1376
1353
|
)
|
|
1377
1354
|
self.vvar_id_start = ssailification.max_vvar_id + 1
|
|
1378
1355
|
return ssailification.out_graph
|
|
1379
1356
|
|
|
1380
1357
|
@timethis
|
|
1381
|
-
def _transform_to_ssa_level1(
|
|
1358
|
+
def _transform_to_ssa_level1(
|
|
1359
|
+
self, ail_graph: networkx.DiGraph, func_args: set[ailment.Expr.VirtualVariable]
|
|
1360
|
+
) -> networkx.DiGraph:
|
|
1382
1361
|
ssailification = self.project.analyses.Ssailification(
|
|
1383
1362
|
self.function,
|
|
1384
1363
|
ail_graph,
|
|
@@ -1387,6 +1366,7 @@ class Clinic(Analysis):
|
|
|
1387
1366
|
ail_manager=self._ail_manager,
|
|
1388
1367
|
ssa_tmps=True,
|
|
1389
1368
|
ssa_stackvars=True,
|
|
1369
|
+
func_args=func_args,
|
|
1390
1370
|
vvar_id_start=self.vvar_id_start,
|
|
1391
1371
|
)
|
|
1392
1372
|
self.vvar_id_start = ssailification.max_vvar_id + 1
|
|
@@ -1444,7 +1424,7 @@ class Clinic(Analysis):
|
|
|
1444
1424
|
return []
|
|
1445
1425
|
|
|
1446
1426
|
@timethis
|
|
1447
|
-
def _make_callsites(self, ail_graph, stack_pointer_tracker=None):
|
|
1427
|
+
def _make_callsites(self, ail_graph, func_args: set[ailment.Expr.VirtualVariable], stack_pointer_tracker=None):
|
|
1448
1428
|
"""
|
|
1449
1429
|
Simplify all function call statements.
|
|
1450
1430
|
"""
|
|
@@ -1453,6 +1433,7 @@ class Clinic(Analysis):
|
|
|
1453
1433
|
rd = self.project.analyses.SReachingDefinitions(
|
|
1454
1434
|
subject=self.function,
|
|
1455
1435
|
func_graph=ail_graph,
|
|
1436
|
+
func_args=func_args,
|
|
1456
1437
|
fail_fast=self._fail_fast,
|
|
1457
1438
|
# use_callee_saved_regs_at_return=not self._register_save_areas_removed, FIXME
|
|
1458
1439
|
)
|
|
@@ -1709,6 +1690,9 @@ class Clinic(Analysis):
|
|
|
1709
1690
|
elif stmt_type is ailment.Stmt.ConditionalJump:
|
|
1710
1691
|
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.condition)
|
|
1711
1692
|
|
|
1693
|
+
elif stmt_type is ailment.Stmt.Jump and not isinstance(stmt.target, ailment.Expr.Const):
|
|
1694
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.target)
|
|
1695
|
+
|
|
1712
1696
|
elif stmt_type is ailment.Stmt.Call:
|
|
1713
1697
|
self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, stmt, is_expr=False)
|
|
1714
1698
|
|
|
@@ -2732,6 +2716,69 @@ class Clinic(Analysis):
|
|
|
2732
2716
|
|
|
2733
2717
|
return extra_regs
|
|
2734
2718
|
|
|
2719
|
+
def _rewrite_rust_probestack_call(self, ail_graph):
|
|
2720
|
+
for node in ail_graph:
|
|
2721
|
+
if not node.statements or ail_graph.out_degree[node] != 1:
|
|
2722
|
+
continue
|
|
2723
|
+
last_stmt = node.statements[-1]
|
|
2724
|
+
if isinstance(last_stmt, ailment.Stmt.Call) and isinstance(last_stmt.target, ailment.Expr.Const):
|
|
2725
|
+
func = (
|
|
2726
|
+
self.project.kb.functions.get_by_addr(last_stmt.target.value)
|
|
2727
|
+
if self.project.kb.functions.contains_addr(last_stmt.target.value)
|
|
2728
|
+
else None
|
|
2729
|
+
)
|
|
2730
|
+
if func is not None and func.info.get("is_rust_probestack", False) is True:
|
|
2731
|
+
# get rid of this call
|
|
2732
|
+
node.statements = node.statements[:-1]
|
|
2733
|
+
if self.project.arch.call_pushes_ret and node.statements:
|
|
2734
|
+
last_stmt = node.statements[-1]
|
|
2735
|
+
succ = next(iter(ail_graph.successors(node)))
|
|
2736
|
+
if (
|
|
2737
|
+
isinstance(last_stmt, ailment.Stmt.Store)
|
|
2738
|
+
and isinstance(last_stmt.addr, ailment.Expr.StackBaseOffset)
|
|
2739
|
+
and isinstance(last_stmt.addr.offset, int)
|
|
2740
|
+
and last_stmt.addr.offset < 0
|
|
2741
|
+
and isinstance(last_stmt.data, ailment.Expr.Const)
|
|
2742
|
+
and last_stmt.data.value == succ.addr
|
|
2743
|
+
):
|
|
2744
|
+
# remove the statement that pushes the return address
|
|
2745
|
+
node.statements = node.statements[:-1]
|
|
2746
|
+
break
|
|
2747
|
+
return ail_graph
|
|
2748
|
+
|
|
2749
|
+
def _rewrite_windows_stkchk_call(self, ail_graph) -> networkx.DiGraph:
|
|
2750
|
+
if not (self.project.simos is not None and self.project.simos.name == "Win32"):
|
|
2751
|
+
return ail_graph
|
|
2752
|
+
|
|
2753
|
+
for node in ail_graph:
|
|
2754
|
+
if not node.statements or ail_graph.out_degree[node] != 1:
|
|
2755
|
+
continue
|
|
2756
|
+
last_stmt = node.statements[-1]
|
|
2757
|
+
if isinstance(last_stmt, ailment.Stmt.Call) and isinstance(last_stmt.target, ailment.Expr.Const):
|
|
2758
|
+
func = (
|
|
2759
|
+
self.project.kb.functions.get_by_addr(last_stmt.target.value)
|
|
2760
|
+
if self.project.kb.functions.contains_addr(last_stmt.target.value)
|
|
2761
|
+
else None
|
|
2762
|
+
)
|
|
2763
|
+
if func is not None and func.name == "__chkstk":
|
|
2764
|
+
# get rid of this call
|
|
2765
|
+
node.statements = node.statements[:-1]
|
|
2766
|
+
if self.project.arch.call_pushes_ret and node.statements:
|
|
2767
|
+
last_stmt = node.statements[-1]
|
|
2768
|
+
succ = next(iter(ail_graph.successors(node)))
|
|
2769
|
+
if (
|
|
2770
|
+
isinstance(last_stmt, ailment.Stmt.Store)
|
|
2771
|
+
and isinstance(last_stmt.addr, ailment.Expr.StackBaseOffset)
|
|
2772
|
+
and isinstance(last_stmt.addr.offset, int)
|
|
2773
|
+
and last_stmt.addr.offset < 0
|
|
2774
|
+
and isinstance(last_stmt.data, ailment.Expr.Const)
|
|
2775
|
+
and last_stmt.data.value == succ.addr
|
|
2776
|
+
):
|
|
2777
|
+
# remove the statement that pushes the return address
|
|
2778
|
+
node.statements = node.statements[:-1]
|
|
2779
|
+
break
|
|
2780
|
+
return ail_graph
|
|
2781
|
+
|
|
2735
2782
|
def _rewrite_alloca(self, ail_graph):
|
|
2736
2783
|
# pylint:disable=too-many-boolean-expressions
|
|
2737
2784
|
alloca_node = None
|
|
@@ -368,6 +368,7 @@ class Decompiler(Analysis):
|
|
|
368
368
|
self.cache.clinic = self.clinic
|
|
369
369
|
|
|
370
370
|
self.kb.decompilations[(self.func.addr, self._flavor)] = self.cache
|
|
371
|
+
self._finish_progress()
|
|
371
372
|
|
|
372
373
|
def _recover_regions(self, graph: networkx.DiGraph, condition_processor, update_graph: bool = True):
|
|
373
374
|
return self.project.analyses[RegionIdentifier].prep(kb=self.kb, fail_fast=self._fail_fast)(
|
|
@@ -77,6 +77,8 @@ class DephicationBase(Analysis):
|
|
|
77
77
|
mapped_phivarid = phivarid_to_phivarid.get(phi_varid, phi_varid)
|
|
78
78
|
for varid in varids:
|
|
79
79
|
vvar_to_vvar[varid] = mapped_phivarid
|
|
80
|
+
if phi_varid != mapped_phivarid:
|
|
81
|
+
vvar_to_vvar[phi_varid] = mapped_phivarid
|
|
80
82
|
|
|
81
83
|
return vvar_to_vvar
|
|
82
84
|
|
|
@@ -88,12 +88,14 @@ class SimEngineDephiRewriting(SimEngineNostmtAIL[None, Expression | None, Statem
|
|
|
88
88
|
)
|
|
89
89
|
|
|
90
90
|
if new_dst is not None or new_src is not None:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
# ensure we do not generate vvar_A = vvar_A
|
|
92
|
+
dst = stmt.dst if new_dst is None else new_dst
|
|
93
|
+
src = stmt.src if new_src is None else new_src
|
|
94
|
+
if isinstance(dst, VirtualVariable) and isinstance(src, VirtualVariable) and dst.varid == src.varid:
|
|
95
|
+
# skip it
|
|
96
|
+
return ()
|
|
97
|
+
|
|
98
|
+
return Assignment(stmt.idx, dst, src, **stmt.tags)
|
|
97
99
|
return None
|
|
98
100
|
|
|
99
101
|
def _handle_stmt_Store(self, stmt):
|
|
@@ -5,7 +5,7 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
from ailment.block import Block
|
|
7
7
|
from ailment.statement import Assignment
|
|
8
|
-
from ailment.expression import VirtualVariable, Phi
|
|
8
|
+
from ailment.expression import VirtualVariable, Phi, BinaryOp, UnaryOp
|
|
9
9
|
|
|
10
10
|
import angr
|
|
11
11
|
from angr.utils.ail import is_phi_assignment
|
|
@@ -60,6 +60,9 @@ class SeqNodeRewriter(SequenceWalker):
|
|
|
60
60
|
Block: self._handle_Block,
|
|
61
61
|
# statement handlers
|
|
62
62
|
Assignment: self._handle_Assignment,
|
|
63
|
+
# expression handlers
|
|
64
|
+
BinaryOp: self._handle_BinaryOp,
|
|
65
|
+
UnaryOp: self._handle_UnaryOp,
|
|
63
66
|
}
|
|
64
67
|
)
|
|
65
68
|
|
|
@@ -74,6 +77,12 @@ class SeqNodeRewriter(SequenceWalker):
|
|
|
74
77
|
def _handle_Assignment(self, stmt: Assignment, **kwargs) -> Assignment: # pylint:disable=unused-argument
|
|
75
78
|
return self.engine._handle_stmt_Assignment(stmt)
|
|
76
79
|
|
|
80
|
+
def _handle_BinaryOp(self, expr, **kwargs): # pylint:disable=unused-argument
|
|
81
|
+
return self.engine._handle_expr_BinaryOp(expr)
|
|
82
|
+
|
|
83
|
+
def _handle_UnaryOp(self, expr, **kwargs): # pylint:disable=unused-argument
|
|
84
|
+
return self.engine._handle_expr_UnaryOp(expr)
|
|
85
|
+
|
|
77
86
|
def _handle_Block(self, block: Block, **kwargs) -> Block | None: # pylint:disable=unused-argument
|
|
78
87
|
self.engine.out_block = None
|
|
79
88
|
self.engine.process(None, block=block)
|
|
@@ -304,7 +304,7 @@ class AILMergeGraph:
|
|
|
304
304
|
end_pair_map = {}
|
|
305
305
|
end_pairs = set()
|
|
306
306
|
merge_to_end_pair = {}
|
|
307
|
-
for
|
|
307
|
+
for sblocks in self.merge_blocks_to_originals.values():
|
|
308
308
|
for sblock in sblocks:
|
|
309
309
|
if isinstance(sblock, AILBlockSplit) and sblock.original in self.merge_blocks_to_originals:
|
|
310
310
|
deletable_blocks.add(sblock.original)
|
|
@@ -429,7 +429,7 @@ class AILMergeGraph:
|
|
|
429
429
|
self.original_split_blocks[updated] = self.original_split_blocks[k]
|
|
430
430
|
del self.original_split_blocks[k]
|
|
431
431
|
|
|
432
|
-
for
|
|
432
|
+
for v in self.original_split_blocks.values():
|
|
433
433
|
for sblock in v:
|
|
434
434
|
for attr in ["up_split", "match_split", "down_split"]:
|
|
435
435
|
if getattr(sblock, attr) == original:
|
|
@@ -167,7 +167,7 @@ class DuplicationReverter(StructuringOptimizationPass):
|
|
|
167
167
|
|
|
168
168
|
def _reinsert_merged_candidate(self, ail_merge_graph: AILMergeGraph, candidate: tuple[Block, Block]) -> bool:
|
|
169
169
|
og_succs, og_preds = {}, {}
|
|
170
|
-
for
|
|
170
|
+
for original_blocks in ail_merge_graph.original_blocks.values():
|
|
171
171
|
# collect all the old edges
|
|
172
172
|
for og_block in original_blocks:
|
|
173
173
|
og_succs[og_block] = list(self.write_graph.successors(og_block))
|
|
@@ -364,7 +364,7 @@ class DuplicationReverter(StructuringOptimizationPass):
|
|
|
364
364
|
new_nodes[node] = new_node
|
|
365
365
|
|
|
366
366
|
# fixup every single jump target (before adding them to the graph)
|
|
367
|
-
for src, dst
|
|
367
|
+
for src, dst in graph.edges():
|
|
368
368
|
new_src = new_nodes[src]
|
|
369
369
|
new_dst = new_nodes[dst]
|
|
370
370
|
if new_dst is not dst:
|