angr 9.2.132__py3-none-win_amd64.whl → 9.2.133__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 +128 -128
- angr/analyses/__init__.py +38 -38
- 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_fast.py +17 -15
- 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 +9 -7
- angr/analyses/data_dep/__init__.py +4 -4
- angr/analyses/datagraph_meta.py +1 -1
- angr/analyses/ddg.py +2 -6
- angr/analyses/decompiler/__init__.py +12 -12
- angr/analyses/decompiler/ail_simplifier.py +21 -10
- angr/analyses/decompiler/block_similarity.py +2 -4
- angr/analyses/decompiler/callsite_maker.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
- angr/analyses/decompiler/clinic.py +14 -7
- angr/analyses/decompiler/condition_processor.py +45 -29
- 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_vvar_mapping.py +11 -3
- 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/deadblock_remover.py +1 -2
- 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 +1 -1
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +2 -4
- 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 +9 -3
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +3 -0
- 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/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_engine.py +1 -1
- 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 +34 -37
- angr/analyses/decompiler/structuring/__init__.py +3 -3
- angr/analyses/decompiler/structuring/phoenix.py +19 -20
- angr/analyses/decompiler/structuring/structurer_base.py +2 -2
- angr/analyses/decompiler/structuring/structurer_nodes.py +14 -14
- angr/analyses/deobfuscator/__init__.py +3 -3
- 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/loop_analysis.py +1 -1
- angr/analyses/loopfinder.py +1 -1
- angr/analyses/propagator/outdated_definition_walker.py +12 -6
- angr/analyses/propagator/vex_vars.py +3 -3
- angr/analyses/reaching_definitions/__init__.py +9 -9
- angr/analyses/reaching_definitions/call_trace.py +2 -2
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +1 -1
- angr/analyses/reaching_definitions/rd_state.py +10 -10
- angr/analyses/reassembler.py +26 -31
- angr/analyses/s_liveness.py +8 -0
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -5
- angr/analyses/stack_pointer_tracker.py +4 -4
- angr/analyses/typehoon/simple_solver.py +7 -9
- angr/analyses/typehoon/translator.py +2 -2
- angr/analyses/typehoon/typeconsts.py +1 -1
- angr/analyses/typehoon/typevars.py +17 -19
- angr/analyses/unpacker/__init__.py +1 -1
- angr/analyses/variable_recovery/engine_base.py +3 -4
- angr/analyses/variable_recovery/variable_recovery_base.py +1 -1
- angr/analyses/variable_recovery/variable_recovery_fast.py +2 -6
- angr/analyses/veritesting.py +2 -2
- angr/analyses/vfg.py +5 -5
- angr/angrdb/serializers/__init__.py +1 -1
- angr/annocfg.py +1 -1
- angr/blade.py +2 -2
- angr/block.py +16 -16
- angr/calling_conventions.py +11 -13
- angr/code_location.py +6 -10
- angr/codenode.py +3 -3
- angr/engines/__init__.py +12 -14
- angr/engines/engine.py +1 -54
- angr/engines/light/__init__.py +4 -4
- angr/engines/light/data.py +1 -1
- angr/engines/pcode/__init__.py +1 -1
- angr/engines/pcode/behavior.py +1 -1
- 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 +2 -5
- angr/engines/vex/__init__.py +5 -5
- angr/engines/vex/claripy/ccall.py +2 -2
- angr/engines/vex/claripy/irop.py +18 -18
- 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 +3 -3
- angr/exploration_techniques/__init__.py +18 -18
- angr/exploration_techniques/threading.py +0 -6
- 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 +6 -6
- angr/knowledge_plugins/key_definitions/definition.py +1 -1
- angr/knowledge_plugins/key_definitions/live_definitions.py +14 -14
- 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 +31 -31
- angr/knowledge_plugins/variables/variable_access.py +2 -2
- angr/knowledge_plugins/variables/variable_manager.py +1 -1
- angr/knowledge_plugins/xrefs/xref.py +5 -8
- angr/lib/angr_native.dll +0 -0
- 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 +2 -2
- angr/sim_state.py +1 -1
- angr/sim_state_options.py +3 -3
- angr/sim_type.py +10 -14
- angr/sim_variable.py +13 -17
- 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/dynamic_dictlist.py +1 -1
- angr/utils/graph.py +1 -1
- angr/utils/segment_list.py +2 -2
- angr/utils/ssa/__init__.py +12 -5
- {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/METADATA +6 -6
- {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/RECORD +203 -203
- {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/LICENSE +0 -0
- {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/WHEEL +0 -0
- {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/entry_points.txt +0 -0
- {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/top_level.txt +0 -0
|
@@ -143,10 +143,10 @@ class ConstantValueManager:
|
|
|
143
143
|
"""
|
|
144
144
|
|
|
145
145
|
__slots__ = (
|
|
146
|
-
"project",
|
|
147
|
-
"kb",
|
|
148
146
|
"func",
|
|
147
|
+
"kb",
|
|
149
148
|
"mapping",
|
|
149
|
+
"project",
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
def __init__(self, project: Project, kb, func: Function):
|
|
@@ -240,13 +240,13 @@ class JumpTableProcessorState:
|
|
|
240
240
|
"""
|
|
241
241
|
|
|
242
242
|
__slots__ = (
|
|
243
|
-
"arch",
|
|
244
243
|
"_registers",
|
|
245
244
|
"_stack",
|
|
246
245
|
"_tmpvar_source",
|
|
246
|
+
"arch",
|
|
247
247
|
"is_jumptable",
|
|
248
|
-
"stmts_to_instrument",
|
|
249
248
|
"regs_to_initialize",
|
|
249
|
+
"stmts_to_instrument",
|
|
250
250
|
)
|
|
251
251
|
|
|
252
252
|
def __init__(self, arch):
|
|
@@ -2175,10 +2175,12 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2175
2175
|
stmt_taken = i in stmt_ids
|
|
2176
2176
|
display = stmt_taken if in_slice_stmts_only else True
|
|
2177
2177
|
if display:
|
|
2178
|
-
s =
|
|
2179
|
-
|
|
2178
|
+
s = (
|
|
2179
|
+
f"{'+' if stmt_taken else ' '} {addr:x}:{i:02d} | "
|
|
2180
|
+
f"{stmt.pp_str(arch=self.project.arch, tyenv=irsb.tyenv)} "
|
|
2181
|
+
)
|
|
2180
2182
|
if stmt_taken:
|
|
2181
|
-
s += "IN:
|
|
2183
|
+
s += f"IN: {blade.slice.in_degree((addr, i))}"
|
|
2182
2184
|
print(s)
|
|
2183
2185
|
|
|
2184
2186
|
# the default exit
|
|
@@ -5,12 +5,12 @@ from .dep_nodes import DepNodeTypes, BaseDepNode, VarDepNode, MemDepNode, Consta
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
__all__ = (
|
|
8
|
+
"BaseDepNode",
|
|
9
|
+
"ConstantDepNode",
|
|
8
10
|
"DataDependencyGraphAnalysis",
|
|
9
11
|
"DepNodeTypes",
|
|
10
|
-
"BaseDepNode",
|
|
11
|
-
"VarDepNode",
|
|
12
12
|
"MemDepNode",
|
|
13
|
-
"ConstantDepNode",
|
|
14
|
-
"TmpDepNode",
|
|
15
13
|
"RegDepNode",
|
|
14
|
+
"TmpDepNode",
|
|
15
|
+
"VarDepNode",
|
|
16
16
|
)
|
angr/analyses/datagraph_meta.py
CHANGED
|
@@ -51,7 +51,7 @@ class DataGraphMeta:
|
|
|
51
51
|
pp = []
|
|
52
52
|
for stmt in e:
|
|
53
53
|
# true case is a SimProcedure
|
|
54
|
-
s = "(0x
|
|
54
|
+
s = f"(0x{stmt[0]:x}, {stmt[1]})" if imarks is False or stmt[1] == -1 else f"[0x{self._imarks[stmt]:x}]"
|
|
55
55
|
pp.append(s)
|
|
56
56
|
|
|
57
57
|
print(pp[0] + " -> " + pp[1] + " : " + str(data))
|
angr/analyses/ddg.py
CHANGED
|
@@ -95,7 +95,7 @@ class DDGJob:
|
|
|
95
95
|
self.call_depth = call_depth
|
|
96
96
|
|
|
97
97
|
def __repr__(self):
|
|
98
|
-
return "<DDGJob
|
|
98
|
+
return f"<DDGJob {self.cfg_node}, call_depth {self.call_depth}>"
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
class LiveDefinitions:
|
|
@@ -342,11 +342,7 @@ class DDGViewItem:
|
|
|
342
342
|
return None
|
|
343
343
|
|
|
344
344
|
def __repr__(self):
|
|
345
|
-
return "[
|
|
346
|
-
self._variable,
|
|
347
|
-
len(self.dependents),
|
|
348
|
-
len(self.depends_on),
|
|
349
|
-
)
|
|
345
|
+
return f"[{self._variable}, {len(self.dependents)} dependents, depends on {len(self.depends_on)}]"
|
|
350
346
|
|
|
351
347
|
def __eq__(self, other):
|
|
352
348
|
return (
|
|
@@ -20,22 +20,22 @@ StructuredCodeGenerator = CStructuredCodeGenerator
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
__all__ = (
|
|
23
|
-
"
|
|
23
|
+
"DECOMPILATION_PRESETS",
|
|
24
|
+
"AILSimplifier",
|
|
25
|
+
"BlockSimplifier",
|
|
24
26
|
"CStructuredCodeGenerator",
|
|
25
|
-
"
|
|
27
|
+
"CallSiteMaker",
|
|
26
28
|
"Clinic",
|
|
27
|
-
"RegionSimplifier",
|
|
28
29
|
"Decompiler",
|
|
29
|
-
"options",
|
|
30
|
-
"options_by_category",
|
|
31
|
-
"BlockSimplifier",
|
|
32
|
-
"CallSiteMaker",
|
|
33
|
-
"AILSimplifier",
|
|
34
|
-
"Ssailification",
|
|
35
30
|
"GraphDephication",
|
|
31
|
+
"ImportSourceCode",
|
|
32
|
+
"RegionIdentifier",
|
|
33
|
+
"RegionSimplifier",
|
|
36
34
|
"SeqNodeDephication",
|
|
37
|
-
"
|
|
38
|
-
"structuring",
|
|
39
|
-
"optimization_passes",
|
|
35
|
+
"Ssailification",
|
|
40
36
|
"StructuredCodeGenerator",
|
|
37
|
+
"optimization_passes",
|
|
38
|
+
"options",
|
|
39
|
+
"options_by_category",
|
|
40
|
+
"structuring",
|
|
41
41
|
)
|
|
@@ -97,6 +97,7 @@ class AILSimplifier(Analysis):
|
|
|
97
97
|
rewrite_ccalls=True,
|
|
98
98
|
removed_vvar_ids: set[int] | None = None,
|
|
99
99
|
arg_vvars: dict[int, tuple[VirtualVariable, SimVariable]] | None = None,
|
|
100
|
+
avoid_vvar_ids: set[int] | None = None,
|
|
100
101
|
):
|
|
101
102
|
self.func = func
|
|
102
103
|
self.func_graph = func_graph if func_graph is not None else func.graph
|
|
@@ -115,6 +116,7 @@ class AILSimplifier(Analysis):
|
|
|
115
116
|
self._should_rewrite_ccalls = rewrite_ccalls
|
|
116
117
|
self._removed_vvar_ids = removed_vvar_ids if removed_vvar_ids is not None else set()
|
|
117
118
|
self._arg_vvars = arg_vvars
|
|
119
|
+
self._avoid_vvar_ids = avoid_vvar_ids
|
|
118
120
|
|
|
119
121
|
self._calls_to_remove: set[CodeLocation] = set()
|
|
120
122
|
self._assignments_to_remove: set[CodeLocation] = set()
|
|
@@ -552,7 +554,9 @@ class AILSimplifier(Analysis):
|
|
|
552
554
|
if (
|
|
553
555
|
first_op.op == "And"
|
|
554
556
|
and isinstance(first_op.operands[1], Const)
|
|
555
|
-
and (
|
|
557
|
+
and (
|
|
558
|
+
second_op is None or (isinstance(second_op, BinaryOp) and isinstance(second_op.operands[1], Const))
|
|
559
|
+
)
|
|
556
560
|
):
|
|
557
561
|
mask = first_op.operands[1].value
|
|
558
562
|
if mask == 0xFF:
|
|
@@ -615,6 +619,17 @@ class AILSimplifier(Analysis):
|
|
|
615
619
|
stmt.ins_addr for stmt in block.statements
|
|
616
620
|
}.intersection(insn_addrs_using_stack_args)
|
|
617
621
|
|
|
622
|
+
# remove virtual variables in the avoid list
|
|
623
|
+
if self._avoid_vvar_ids:
|
|
624
|
+
filtered_reps = {}
|
|
625
|
+
for loc, rep_dict in reps.items():
|
|
626
|
+
filtered_reps[loc] = {
|
|
627
|
+
k: v
|
|
628
|
+
for k, v in rep_dict.items()
|
|
629
|
+
if not (isinstance(k, VirtualVariable) and k.varid in self._avoid_vvar_ids)
|
|
630
|
+
}
|
|
631
|
+
reps = filtered_reps
|
|
632
|
+
|
|
618
633
|
r, new_block = BlockSimplifier._replace_and_build(block, reps, gp=self._gp, replace_loads=replace_loads)
|
|
619
634
|
replaced |= r
|
|
620
635
|
self.blocks[block] = new_block
|
|
@@ -748,10 +763,8 @@ class AILSimplifier(Analysis):
|
|
|
748
763
|
# the definition is in a callee function
|
|
749
764
|
continue
|
|
750
765
|
|
|
751
|
-
if (
|
|
752
|
-
isinstance(
|
|
753
|
-
or isinstance(eq.atom1, VirtualVariable)
|
|
754
|
-
and eq.atom1.was_parameter
|
|
766
|
+
if isinstance(the_def.codeloc, ExternalCodeLocation) or (
|
|
767
|
+
isinstance(eq.atom1, VirtualVariable) and eq.atom1.was_parameter
|
|
755
768
|
):
|
|
756
769
|
# this is a function argument. we enter a slightly different logic and try to eliminate copies of this
|
|
757
770
|
# argument if
|
|
@@ -765,10 +778,8 @@ class AILSimplifier(Analysis):
|
|
|
765
778
|
|
|
766
779
|
if defs and len(defs) == 1:
|
|
767
780
|
arg_copy_def = defs[0]
|
|
768
|
-
if (
|
|
769
|
-
isinstance(arg_copy_def.atom, atoms.VirtualVariable)
|
|
770
|
-
and arg_copy_def.atom.was_stack
|
|
771
|
-
or (isinstance(arg_copy_def.atom, atoms.VirtualVariable) and arg_copy_def.atom.was_reg)
|
|
781
|
+
if (isinstance(arg_copy_def.atom, atoms.VirtualVariable) and arg_copy_def.atom.was_stack) or (
|
|
782
|
+
isinstance(arg_copy_def.atom, atoms.VirtualVariable) and arg_copy_def.atom.was_reg
|
|
772
783
|
):
|
|
773
784
|
# found the copied definition (either a stack variable or a register variable)
|
|
774
785
|
|
|
@@ -919,7 +930,7 @@ class AILSimplifier(Analysis):
|
|
|
919
930
|
continue
|
|
920
931
|
block = addr_and_idx_to_block[(use_loc.block_addr, use_loc.block_idx)]
|
|
921
932
|
stmt = block.statements[use_loc.stmt_idx]
|
|
922
|
-
if isinstance(stmt, Assignment) or isinstance(replace_with, Load) and isinstance(stmt, Store):
|
|
933
|
+
if isinstance(stmt, Assignment) or (isinstance(replace_with, Load) and isinstance(stmt, Store)):
|
|
923
934
|
assignment_ctr += 1
|
|
924
935
|
if assignment_ctr > 1:
|
|
925
936
|
continue
|
|
@@ -127,10 +127,8 @@ def _kmp_search_ail_obj(search_pattern, stmt_seq, graph=None, partial=True):
|
|
|
127
127
|
start_pos = 0
|
|
128
128
|
match_len = 0
|
|
129
129
|
for c in stmt_seq:
|
|
130
|
-
while (
|
|
131
|
-
match_len
|
|
132
|
-
or match_len >= 0
|
|
133
|
-
and not is_similar(search_pattern[match_len], c, graph=graph, partial=partial)
|
|
130
|
+
while match_len == len(search_pattern) or (
|
|
131
|
+
match_len >= 0 and not is_similar(search_pattern[match_len], c, graph=graph, partial=partial)
|
|
134
132
|
):
|
|
135
133
|
start_pos += shifts[match_len]
|
|
136
134
|
match_len -= shifts[match_len]
|
|
@@ -392,7 +392,7 @@ class CallSiteMaker(Analysis):
|
|
|
392
392
|
return s
|
|
393
393
|
|
|
394
394
|
def _determine_variadic_arguments(self, func: Function | None, cc: SimCC, call_stmt) -> int | None:
|
|
395
|
-
if func is not None and "printf" in func.name or "scanf" in func.name:
|
|
395
|
+
if (func is not None and "printf" in func.name) or "scanf" in func.name:
|
|
396
396
|
return self._determine_variadic_arguments_for_format_strings(func, cc, call_stmt)
|
|
397
397
|
return None
|
|
398
398
|
|
|
@@ -600,7 +600,7 @@ class Clinic(Analysis):
|
|
|
600
600
|
arg_list.append(arg_vvars[idx][1])
|
|
601
601
|
|
|
602
602
|
# Get virtual variable mapping that can de-phi the SSA representation
|
|
603
|
-
vvar2vvar = self._collect_dephi_vvar_mapping_and_rewrite_blocks(ail_graph)
|
|
603
|
+
vvar2vvar, copied_vvar_ids = self._collect_dephi_vvar_mapping_and_rewrite_blocks(ail_graph, arg_vvars)
|
|
604
604
|
|
|
605
605
|
# Recover variables on AIL blocks
|
|
606
606
|
self._update_progress(80.0, text="Recovering variables")
|
|
@@ -608,7 +608,11 @@ class Clinic(Analysis):
|
|
|
608
608
|
|
|
609
609
|
# Run simplification passes
|
|
610
610
|
self._update_progress(85.0, text="Running simplifications 4")
|
|
611
|
-
ail_graph = self._run_simplification_passes(
|
|
611
|
+
ail_graph = self._run_simplification_passes(
|
|
612
|
+
ail_graph,
|
|
613
|
+
stage=OptimizationPassStage.AFTER_VARIABLE_RECOVERY,
|
|
614
|
+
avoid_vvar_ids=copied_vvar_ids,
|
|
615
|
+
)
|
|
612
616
|
|
|
613
617
|
# Make function prototype
|
|
614
618
|
self._update_progress(90.0, text="Making function prototype")
|
|
@@ -1389,16 +1393,19 @@ class Clinic(Analysis):
|
|
|
1389
1393
|
return ssailification.out_graph
|
|
1390
1394
|
|
|
1391
1395
|
@timethis
|
|
1392
|
-
def _collect_dephi_vvar_mapping_and_rewrite_blocks(
|
|
1396
|
+
def _collect_dephi_vvar_mapping_and_rewrite_blocks(
|
|
1397
|
+
self, ail_graph: networkx.DiGraph, arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]]
|
|
1398
|
+
) -> tuple[dict[int, int], set[int]]:
|
|
1393
1399
|
dephication = self.project.analyses.GraphDephicationVVarMapping(
|
|
1394
1400
|
self.function,
|
|
1395
1401
|
ail_graph,
|
|
1396
1402
|
fail_fast=self._fail_fast,
|
|
1397
1403
|
entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
|
|
1398
1404
|
vvar_id_start=self.vvar_id_start,
|
|
1405
|
+
arg_vvars=[arg_vvar for arg_vvar, _ in arg_vvars.values()],
|
|
1399
1406
|
)
|
|
1400
1407
|
self.vvar_id_start = dephication.vvar_id_start + 1
|
|
1401
|
-
return dephication.vvar_to_vvar_mapping
|
|
1408
|
+
return dephication.vvar_to_vvar_mapping, dephication.copied_vvar_ids
|
|
1402
1409
|
|
|
1403
1410
|
@timethis
|
|
1404
1411
|
def _make_argument_list(self) -> list[SimVariable]:
|
|
@@ -1412,7 +1419,7 @@ class Clinic(Analysis):
|
|
|
1412
1419
|
argvar = SimRegisterVariable(
|
|
1413
1420
|
self.project.arch.registers[arg.reg_name][0],
|
|
1414
1421
|
arg.size,
|
|
1415
|
-
ident="arg_
|
|
1422
|
+
ident=f"arg_{idx}",
|
|
1416
1423
|
name=arg_names[idx],
|
|
1417
1424
|
region=self.function.addr,
|
|
1418
1425
|
)
|
|
@@ -1421,13 +1428,13 @@ class Clinic(Analysis):
|
|
|
1421
1428
|
arg.stack_offset,
|
|
1422
1429
|
arg.size,
|
|
1423
1430
|
base="bp",
|
|
1424
|
-
ident="arg_
|
|
1431
|
+
ident=f"arg_{idx}",
|
|
1425
1432
|
name=arg_names[idx],
|
|
1426
1433
|
region=self.function.addr,
|
|
1427
1434
|
)
|
|
1428
1435
|
else:
|
|
1429
1436
|
argvar = SimVariable(
|
|
1430
|
-
ident="arg_
|
|
1437
|
+
ident=f"arg_{idx}",
|
|
1431
1438
|
name=arg_names[idx],
|
|
1432
1439
|
region=self.function.addr,
|
|
1433
1440
|
size=arg.size,
|
|
@@ -113,41 +113,53 @@ _ail2claripy_op_mapping = {
|
|
|
113
113
|
"LogicalOr": lambda expr, conv, _, ia: claripy.Or(
|
|
114
114
|
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
115
115
|
),
|
|
116
|
-
"CmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
117
|
-
|
|
118
|
-
"
|
|
116
|
+
"CmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
117
|
+
== conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
118
|
+
"CmpNE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
119
|
+
!= conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
120
|
+
"CmpLE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
121
|
+
<= conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
119
122
|
"CmpLE (signed)": lambda expr, conv, _, ia: claripy.SLE(
|
|
120
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
123
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
121
124
|
),
|
|
122
|
-
"CmpLT": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
125
|
+
"CmpLT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
126
|
+
< conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
123
127
|
"CmpLT (signed)": lambda expr, conv, _, ia: claripy.SLT(
|
|
124
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
128
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
125
129
|
),
|
|
126
|
-
"CmpGE": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
130
|
+
"CmpGE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
131
|
+
>= conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
127
132
|
"CmpGE (signed)": lambda expr, conv, _, ia: claripy.SGE(
|
|
128
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
133
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
129
134
|
),
|
|
130
|
-
"CmpGT": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
135
|
+
"CmpGT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
136
|
+
> conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
131
137
|
"CmpGT (signed)": lambda expr, conv, _, ia: claripy.SGT(
|
|
132
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
138
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
133
139
|
),
|
|
134
|
-
"CasCmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
135
|
-
|
|
136
|
-
"
|
|
140
|
+
"CasCmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
141
|
+
== conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
142
|
+
"CasCmpNE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
143
|
+
!= conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
144
|
+
"CasCmpLE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
145
|
+
<= conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
137
146
|
"CasCmpLE (signed)": lambda expr, conv, _, ia: claripy.SLE(
|
|
138
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
147
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
139
148
|
),
|
|
140
|
-
"CasCmpLT": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
149
|
+
"CasCmpLT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
150
|
+
< conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
141
151
|
"CasCmpLT (signed)": lambda expr, conv, _, ia: claripy.SLT(
|
|
142
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
152
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
143
153
|
),
|
|
144
|
-
"CasCmpGE": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
154
|
+
"CasCmpGE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
155
|
+
>= conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
145
156
|
"CasCmpGE (signed)": lambda expr, conv, _, ia: claripy.SGE(
|
|
146
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
157
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
147
158
|
),
|
|
148
|
-
"CasCmpGT": lambda expr, conv, _, ia: conv(expr.operands[0],
|
|
159
|
+
"CasCmpGT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
160
|
+
> conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
149
161
|
"CasCmpGT (signed)": lambda expr, conv, _, ia: claripy.SGT(
|
|
150
|
-
conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
|
|
162
|
+
conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
|
|
151
163
|
),
|
|
152
164
|
"Add": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
|
|
153
165
|
+ conv(expr.operands[1], nobool=True, ins_addr=ia),
|
|
@@ -802,9 +814,13 @@ class ConditionProcessor:
|
|
|
802
814
|
f"Condition variable {cond} has an unsupported operator {cond.op}. Consider implementing."
|
|
803
815
|
)
|
|
804
816
|
|
|
805
|
-
def claripy_ast_from_ail_condition(
|
|
817
|
+
def claripy_ast_from_ail_condition(
|
|
818
|
+
self, condition, nobool: bool = False, *, ins_addr: int = 0
|
|
819
|
+
) -> claripy.ast.Bool | claripy.ast.Bits:
|
|
806
820
|
# Unpack a condition all the way to the leaves
|
|
807
|
-
if isinstance(
|
|
821
|
+
if isinstance(
|
|
822
|
+
condition, (claripy.ast.Bits, claripy.ast.Bool)
|
|
823
|
+
): # pylint:disable=isinstance-second-argument-not-valid-type
|
|
808
824
|
return condition
|
|
809
825
|
|
|
810
826
|
if isinstance(
|
|
@@ -832,11 +848,11 @@ class ConditionProcessor:
|
|
|
832
848
|
# convert is special. if it generates a 1-bit variable, it should be treated as a BoolS
|
|
833
849
|
if condition.to_bits == 1:
|
|
834
850
|
var_ = self.claripy_ast_from_ail_condition(condition.operands[0], ins_addr=ins_addr)
|
|
835
|
-
name = "ailcond_Conv(
|
|
851
|
+
name = f"ailcond_Conv({condition.from_bits}->{condition.to_bits}, {hash(var_)})"
|
|
836
852
|
var = claripy.BoolS(name, explicit_name=True)
|
|
837
853
|
else:
|
|
838
854
|
var_ = self.claripy_ast_from_ail_condition(condition.operands[0], ins_addr=ins_addr)
|
|
839
|
-
name = "ailexpr_Conv(
|
|
855
|
+
name = f"ailexpr_Conv({condition.from_bits}->{condition.to_bits}, {hash(var_)})"
|
|
840
856
|
var = claripy.BVS(name, condition.to_bits, explicit_name=True)
|
|
841
857
|
self._condition_mapping[var.args[0]] = condition
|
|
842
858
|
return var
|
|
@@ -851,17 +867,17 @@ class ConditionProcessor:
|
|
|
851
867
|
if isinstance(condition, ailment.Expr.Tmp):
|
|
852
868
|
l.warning("Left-over ailment.Tmp variable %s.", condition)
|
|
853
869
|
if condition.bits == 1:
|
|
854
|
-
var = claripy.BoolS("ailtmp_
|
|
870
|
+
var = claripy.BoolS(f"ailtmp_{condition.tmp_idx}", explicit_name=True)
|
|
855
871
|
else:
|
|
856
|
-
var = claripy.BVS("ailtmp_
|
|
872
|
+
var = claripy.BVS(f"ailtmp_{condition.tmp_idx}", condition.bits, explicit_name=True)
|
|
857
873
|
self._condition_mapping[var.args[0]] = condition
|
|
858
874
|
return var
|
|
859
875
|
if isinstance(condition, ailment.Expr.MultiStatementExpression):
|
|
860
876
|
# just cache it
|
|
861
877
|
if condition.bits == 1:
|
|
862
|
-
var = claripy.BoolS("mstmtexpr_
|
|
878
|
+
var = claripy.BoolS(f"mstmtexpr_{hash(condition)}", explicit_name=True)
|
|
863
879
|
else:
|
|
864
|
-
var = claripy.BVS("mstmtexpr_
|
|
880
|
+
var = claripy.BVS(f"mstmtexpr_{hash(condition)}", condition.bits, explicit_name=True)
|
|
865
881
|
self._condition_mapping[var.args[0]] = condition
|
|
866
882
|
return var
|
|
867
883
|
|
|
@@ -885,7 +901,7 @@ class ConditionProcessor:
|
|
|
885
901
|
self._condition_mapping[r.args[0]] = condition
|
|
886
902
|
|
|
887
903
|
if r is NotImplemented:
|
|
888
|
-
if condition.bits == 1:
|
|
904
|
+
if condition.bits == 1 and not nobool:
|
|
889
905
|
r = claripy.BoolS(f"ailexpr_{condition!r}", explicit_name=True)
|
|
890
906
|
else:
|
|
891
907
|
r = claripy.BVS(f"ailexpr_{condition!r}", condition.bits, explicit_name=True)
|
|
@@ -7,10 +7,10 @@ from .expression_counters import SingleExpressionCounter, RegisterExpressionCoun
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
__all__ = (
|
|
10
|
-
"BooleanCounter",
|
|
11
10
|
"AILBlockCallCounter",
|
|
11
|
+
"BooleanCounter",
|
|
12
12
|
"ControlFlowStructureCounter",
|
|
13
|
-
"SingleExpressionCounter",
|
|
14
|
-
"RegisterExpressionCounter",
|
|
15
13
|
"OperatorCounter",
|
|
14
|
+
"RegisterExpressionCounter",
|
|
15
|
+
"SingleExpressionCounter",
|
|
16
16
|
)
|
|
@@ -14,16 +14,16 @@ class DecompilationCache:
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
__slots__ = (
|
|
17
|
-
"parameters",
|
|
18
17
|
"addr",
|
|
19
|
-
"type_constraints",
|
|
20
|
-
"func_typevar",
|
|
21
|
-
"var_to_typevar",
|
|
22
|
-
"codegen",
|
|
23
|
-
"clinic",
|
|
24
|
-
"ite_exprs",
|
|
25
18
|
"binop_operators",
|
|
19
|
+
"clinic",
|
|
20
|
+
"codegen",
|
|
26
21
|
"errors",
|
|
22
|
+
"func_typevar",
|
|
23
|
+
"ite_exprs",
|
|
24
|
+
"parameters",
|
|
25
|
+
"type_constraints",
|
|
26
|
+
"var_to_typevar",
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
def __init__(self, addr):
|
|
@@ -3,4 +3,4 @@ from .graph_vvar_mapping import GraphDephicationVVarMapping
|
|
|
3
3
|
from .graph_dephication import GraphDephication
|
|
4
4
|
from .seqnode_dephication import SeqNodeDephication
|
|
5
5
|
|
|
6
|
-
__all__ = ["
|
|
6
|
+
__all__ = ["GraphDephication", "GraphDephicationVVarMapping", "SeqNodeDephication"]
|
|
@@ -10,7 +10,7 @@ from angr.analyses import Analysis
|
|
|
10
10
|
from angr.analyses.s_reaching_definitions import SRDAModel
|
|
11
11
|
from angr.knowledge_plugins.functions import Function
|
|
12
12
|
from angr.analyses import register_analysis
|
|
13
|
-
from angr.utils.ssa import is_phi_assignment
|
|
13
|
+
from angr.utils.ssa import is_phi_assignment, DEPHI_VVAR_REG_OFFSET
|
|
14
14
|
|
|
15
15
|
l = logging.getLogger(name=__name__)
|
|
16
16
|
|
|
@@ -30,6 +30,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
30
30
|
ail_graph,
|
|
31
31
|
entry=None,
|
|
32
32
|
vvar_id_start: int = 0,
|
|
33
|
+
arg_vvars: list[VirtualVariable] | None = None,
|
|
33
34
|
):
|
|
34
35
|
"""
|
|
35
36
|
:param func: The subject of the analysis: a function, or a single basic block
|
|
@@ -49,8 +50,10 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
49
50
|
self._vvar_defloc = {}
|
|
50
51
|
self.vvar_id_start = vvar_id_start
|
|
51
52
|
self._stmts_to_prepend = defaultdict(list)
|
|
53
|
+
self._arg_vvars = arg_vvars or []
|
|
52
54
|
|
|
53
55
|
self.vvar_to_vvar_mapping = None
|
|
56
|
+
self.copied_vvar_ids: set[int] = set()
|
|
54
57
|
self._rd: SRDAModel = self.project.analyses.SReachingDefinitions(
|
|
55
58
|
subject=self._function, func_graph=self._graph
|
|
56
59
|
).model
|
|
@@ -74,7 +77,9 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
74
77
|
phi_congruence_class[varid] = {varid}
|
|
75
78
|
|
|
76
79
|
# compute liveness
|
|
77
|
-
liveness = self.project.analyses.SLiveness(
|
|
80
|
+
liveness = self.project.analyses.SLiveness(
|
|
81
|
+
self._function, func_graph=self._graph, entry=self._entry, arg_vvars=self._arg_vvars
|
|
82
|
+
)
|
|
78
83
|
|
|
79
84
|
live_ins = liveness.model.live_ins
|
|
80
85
|
live_outs = liveness.model.live_outs
|
|
@@ -136,6 +141,8 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
136
141
|
|
|
137
142
|
if insertion_type == 0:
|
|
138
143
|
for src, old_vvar_id, new_vvar_id in new_vvar_ids:
|
|
144
|
+
self.copied_vvar_ids.add(new_vvar_id)
|
|
145
|
+
|
|
139
146
|
phi_congruence_class[new_vvar_id] = {new_vvar_id}
|
|
140
147
|
live_outs[src].add(new_vvar_id)
|
|
141
148
|
|
|
@@ -153,6 +160,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
153
160
|
|
|
154
161
|
else: # insertion_type == 1
|
|
155
162
|
phi_block_loc, old_phi_varid, new_phi_varid = next(iter(new_vvar_ids))
|
|
163
|
+
self.copied_vvar_ids.add(new_phi_varid)
|
|
156
164
|
|
|
157
165
|
phi_congruence_class[new_phi_varid] = {new_phi_varid}
|
|
158
166
|
|
|
@@ -217,7 +225,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
|
|
|
217
225
|
# it's a parameter, so we copy the variable into a dummy register vvar
|
|
218
226
|
# a parameter vvar should never be assigned to
|
|
219
227
|
new_category = VirtualVariableCategory.REGISTER
|
|
220
|
-
new_oident =
|
|
228
|
+
new_oident = DEPHI_VVAR_REG_OFFSET
|
|
221
229
|
else:
|
|
222
230
|
new_category = vvar.category
|
|
223
231
|
new_oident = vvar.oident
|
|
@@ -23,15 +23,15 @@ class GraphRegion:
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
__slots__ = (
|
|
26
|
-
"head",
|
|
27
|
-
"graph",
|
|
28
|
-
"successors",
|
|
29
|
-
"graph_with_successors",
|
|
30
|
-
"cyclic",
|
|
31
|
-
"full_graph",
|
|
32
|
-
"cyclic_ancestor",
|
|
33
26
|
"_node_to_replaced_regions",
|
|
34
27
|
"_replaced_regions",
|
|
28
|
+
"cyclic",
|
|
29
|
+
"cyclic_ancestor",
|
|
30
|
+
"full_graph",
|
|
31
|
+
"graph",
|
|
32
|
+
"graph_with_successors",
|
|
33
|
+
"head",
|
|
34
|
+
"successors",
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
def __init__(
|
|
@@ -74,7 +74,7 @@ class GraphRegion:
|
|
|
74
74
|
if addrs:
|
|
75
75
|
s = f": {min(addrs):#x}-{max(addrs):#x}"
|
|
76
76
|
|
|
77
|
-
return "<GraphRegion
|
|
77
|
+
return f"<GraphRegion {self.head!r} of {self.graph.number_of_nodes()} nodes{s}>"
|
|
78
78
|
|
|
79
79
|
def copy(self) -> GraphRegion:
|
|
80
80
|
return GraphRegion(
|