angr 9.2.139__py3-none-manylinux2014_x86_64.whl → 9.2.140__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/calling_convention/calling_convention.py +48 -21
- angr/analyses/cfg/cfg_base.py +13 -0
- angr/analyses/cfg/cfg_fast.py +11 -0
- angr/analyses/decompiler/ail_simplifier.py +67 -52
- angr/analyses/decompiler/clinic.py +68 -43
- angr/analyses/decompiler/decompiler.py +17 -7
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +16 -10
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +2 -2
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +259 -108
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +27 -12
- angr/analyses/decompiler/structuring/dream.py +21 -17
- angr/analyses/decompiler/structuring/phoenix.py +152 -40
- angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
- angr/analyses/decompiler/structuring/structurer_base.py +36 -10
- angr/analyses/decompiler/structuring/structurer_nodes.py +4 -1
- angr/analyses/decompiler/utils.py +60 -1
- angr/analyses/deobfuscator/api_obf_finder.py +8 -5
- angr/analyses/deobfuscator/api_obf_type2_finder.py +18 -10
- angr/analyses/deobfuscator/string_obf_finder.py +105 -18
- angr/analyses/forward_analysis/forward_analysis.py +1 -1
- angr/analyses/propagator/top_checker_mixin.py +6 -6
- angr/analyses/reaching_definitions/__init__.py +2 -1
- angr/analyses/reaching_definitions/dep_graph.py +1 -12
- angr/analyses/reaching_definitions/engine_vex.py +36 -31
- angr/analyses/reaching_definitions/function_handler.py +15 -2
- angr/analyses/reaching_definitions/rd_state.py +1 -37
- angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
- angr/analyses/s_propagator.py +6 -41
- angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
- angr/analyses/stack_pointer_tracker.py +36 -22
- angr/analyses/typehoon/simple_solver.py +45 -7
- angr/analyses/typehoon/typeconsts.py +18 -5
- angr/analyses/variable_recovery/engine_base.py +7 -5
- angr/block.py +69 -107
- angr/callable.py +14 -7
- angr/calling_conventions.py +15 -1
- angr/distributed/__init__.py +1 -1
- angr/engines/__init__.py +7 -8
- angr/engines/engine.py +1 -120
- angr/engines/failure.py +2 -2
- angr/engines/hook.py +2 -2
- angr/engines/light/engine.py +2 -2
- angr/engines/pcode/engine.py +2 -14
- angr/engines/procedure.py +2 -2
- angr/engines/soot/engine.py +2 -2
- angr/engines/soot/statements/switch.py +1 -1
- angr/engines/successors.py +124 -11
- angr/engines/syscall.py +2 -2
- angr/engines/unicorn.py +3 -3
- angr/engines/vex/heavy/heavy.py +3 -15
- angr/factory.py +4 -19
- angr/knowledge_plugins/key_definitions/atoms.py +8 -4
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
- angr/sim_type.py +19 -17
- angr/state_plugins/plugin.py +19 -4
- angr/storage/memory_mixins/memory_mixin.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
- angr/utils/ssa/__init__.py +119 -4
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/METADATA +6 -6
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/RECORD +68 -68
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/LICENSE +0 -0
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/WHEEL +0 -0
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/entry_points.txt +0 -0
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/top_level.txt +0 -0
|
@@ -31,7 +31,7 @@ class ClaripyDataEngineMixin(
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _vex_make_comparison(
|
|
34
|
-
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool]
|
|
34
|
+
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool],
|
|
35
35
|
) -> Callable[[ClaripyDataEngineMixin, Binop], claripy.ast.BV]:
|
|
36
36
|
@SimEngineLightVEX.binop_handler
|
|
37
37
|
def inner(self, expr):
|
|
@@ -44,7 +44,7 @@ def _vex_make_comparison(
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def _vex_make_vec_comparison(
|
|
47
|
-
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool]
|
|
47
|
+
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool],
|
|
48
48
|
) -> Callable[[ClaripyDataEngineMixin, int, int, Binop], claripy.ast.BV]:
|
|
49
49
|
@SimEngineLightVEX.binopv_handler
|
|
50
50
|
def inner(self, size, count, expr):
|
|
@@ -56,7 +56,7 @@ def _vex_make_vec_comparison(
|
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
def _vex_make_operation(
|
|
59
|
-
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]
|
|
59
|
+
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV],
|
|
60
60
|
) -> Callable[[ClaripyDataEngineMixin, Binop], claripy.ast.BV]:
|
|
61
61
|
@SimEngineLightVEX.binop_handler
|
|
62
62
|
def inner(self, expr: Binop):
|
|
@@ -70,7 +70,7 @@ def _vex_make_operation(
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
def _vex_make_unary_operation(
|
|
73
|
-
func: Callable[[claripy.ast.BV], claripy.ast.BV]
|
|
73
|
+
func: Callable[[claripy.ast.BV], claripy.ast.BV],
|
|
74
74
|
) -> Callable[[ClaripyDataEngineMixin, Unop], claripy.ast.BV]:
|
|
75
75
|
@SimEngineLightVEX.unop_handler
|
|
76
76
|
def inner(self, expr):
|
|
@@ -84,7 +84,7 @@ def _vex_make_unary_operation(
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
def _vex_make_shift_operation(
|
|
87
|
-
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]
|
|
87
|
+
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV],
|
|
88
88
|
) -> Callable[[ClaripyDataEngineMixin, Binop], claripy.ast.BV]:
|
|
89
89
|
@_vex_make_operation
|
|
90
90
|
def inner(a, b):
|
|
@@ -99,7 +99,7 @@ def _vex_make_shift_operation(
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def _vex_make_vec_operation(
|
|
102
|
-
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]
|
|
102
|
+
func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV],
|
|
103
103
|
) -> Callable[[ClaripyDataEngineMixin, int, int, Binop], claripy.ast.BV]:
|
|
104
104
|
@SimEngineLightVEX.binopv_handler
|
|
105
105
|
def inner(self, size, count, expr):
|
|
@@ -15,7 +15,7 @@ from angr.knowledge_plugins.key_definitions.atoms import (
|
|
|
15
15
|
from angr.knowledge_plugins.key_definitions.definition import Definition
|
|
16
16
|
from angr.analyses import register_analysis
|
|
17
17
|
from .reaching_definitions import ReachingDefinitionsAnalysis, ReachingDefinitionsModel
|
|
18
|
-
from .function_handler import FunctionHandler, FunctionCallData
|
|
18
|
+
from .function_handler import FunctionHandler, FunctionCallData, FunctionCallRelationships
|
|
19
19
|
from .rd_state import ReachingDefinitionsState
|
|
20
20
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
@@ -29,6 +29,7 @@ __all__ = (
|
|
|
29
29
|
"ConstantSrc",
|
|
30
30
|
"Definition",
|
|
31
31
|
"FunctionCallData",
|
|
32
|
+
"FunctionCallRelationships",
|
|
32
33
|
"FunctionHandler",
|
|
33
34
|
"GuardUse",
|
|
34
35
|
"LiveDefinitions",
|
|
@@ -6,7 +6,6 @@ from typing import (
|
|
|
6
6
|
Any,
|
|
7
7
|
)
|
|
8
8
|
from collections.abc import Iterable, Iterator
|
|
9
|
-
from dataclasses import dataclass
|
|
10
9
|
|
|
11
10
|
import networkx
|
|
12
11
|
|
|
@@ -35,16 +34,6 @@ def _is_definition(node):
|
|
|
35
34
|
return isinstance(node, Definition)
|
|
36
35
|
|
|
37
36
|
|
|
38
|
-
@dataclass
|
|
39
|
-
class FunctionCallRelationships: # TODO this doesn't belong in this file anymore
|
|
40
|
-
callsite: CodeLocation
|
|
41
|
-
target: int | None
|
|
42
|
-
args_defns: list[set[Definition]]
|
|
43
|
-
other_input_defns: set[Definition]
|
|
44
|
-
ret_defns: set[Definition]
|
|
45
|
-
other_output_defns: set[Definition]
|
|
46
|
-
|
|
47
|
-
|
|
48
37
|
class DepGraph:
|
|
49
38
|
"""
|
|
50
39
|
The representation of a dependency graph: a directed graph, where nodes are definitions, and edges represent uses.
|
|
@@ -84,7 +73,7 @@ class DepGraph:
|
|
|
84
73
|
"""
|
|
85
74
|
self._graph.add_edge(source, destination, **labels)
|
|
86
75
|
|
|
87
|
-
def nodes(self) ->
|
|
76
|
+
def nodes(self) -> Iterator[Definition]:
|
|
88
77
|
return self._graph.nodes()
|
|
89
78
|
|
|
90
79
|
def predecessors(self, node: Definition) -> Iterator[Definition]:
|
|
@@ -12,7 +12,8 @@ from angr.engines.light import SimEngineNostmtVEX, SpOffset
|
|
|
12
12
|
from angr.engines.vex.claripy.datalayer import value as claripy_value
|
|
13
13
|
from angr.errors import SimEngineError, SimMemoryMissingError
|
|
14
14
|
from angr.utils.constants import DEFAULT_STATEMENT
|
|
15
|
-
from angr.knowledge_plugins.key_definitions.
|
|
15
|
+
from angr.knowledge_plugins.key_definitions.definition import Definition
|
|
16
|
+
from angr.knowledge_plugins.key_definitions.live_definitions import LiveDefinitions
|
|
16
17
|
from angr.knowledge_plugins.key_definitions.tag import LocalVariableTag, ParameterTag, Tag
|
|
17
18
|
from angr.knowledge_plugins.key_definitions.atoms import Atom, Register, MemoryLocation, Tmp
|
|
18
19
|
from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE, OP_AFTER
|
|
@@ -78,11 +79,15 @@ class SimEngineRDVEX(
|
|
|
78
79
|
self._set_codeloc()
|
|
79
80
|
if self.block.vex.jumpkind == "Ijk_Call":
|
|
80
81
|
# it has to be a function
|
|
81
|
-
|
|
82
|
+
block_next = self.block.vex.next
|
|
83
|
+
assert isinstance(block_next, pyvex.expr.IRExpr)
|
|
84
|
+
addr = self._expr_bv(block_next)
|
|
82
85
|
self._handle_function(addr)
|
|
83
86
|
elif self.block.vex.jumpkind == "Ijk_Boring":
|
|
84
87
|
# test if the target addr is a function or not
|
|
85
|
-
|
|
88
|
+
block_next = self.block.vex.next
|
|
89
|
+
assert isinstance(block_next, pyvex.expr.IRExpr)
|
|
90
|
+
addr = self._expr_bv(block_next)
|
|
86
91
|
addr_v = addr.one_value()
|
|
87
92
|
if addr_v is not None and addr_v.concrete:
|
|
88
93
|
addr_int = addr_v.concrete_value
|
|
@@ -550,7 +555,7 @@ class SimEngineRDVEX(
|
|
|
550
555
|
return r
|
|
551
556
|
|
|
552
557
|
@unop_handler
|
|
553
|
-
def _handle_unop_Not(self, expr):
|
|
558
|
+
def _handle_unop_Not(self, expr: pyvex.expr.Unop) -> MultiValues:
|
|
554
559
|
arg0 = expr.args[0]
|
|
555
560
|
expr_0 = self._expr_bv(arg0)
|
|
556
561
|
bits = expr.result_size(self.tyenv)
|
|
@@ -563,7 +568,7 @@ class SimEngineRDVEX(
|
|
|
563
568
|
return MultiValues(self.state.top(bits))
|
|
564
569
|
|
|
565
570
|
@unop_handler
|
|
566
|
-
def _handle_unop_Clz(self, expr):
|
|
571
|
+
def _handle_unop_Clz(self, expr: pyvex.expr.Unop) -> MultiValues:
|
|
567
572
|
arg0 = expr.args[0]
|
|
568
573
|
_ = self._expr(arg0)
|
|
569
574
|
bits = expr.result_size(self.tyenv)
|
|
@@ -571,7 +576,7 @@ class SimEngineRDVEX(
|
|
|
571
576
|
return MultiValues(self.state.top(bits))
|
|
572
577
|
|
|
573
578
|
@unop_handler
|
|
574
|
-
def _handle_unop_Ctz(self, expr):
|
|
579
|
+
def _handle_unop_Ctz(self, expr: pyvex.expr.Unop) -> MultiValues:
|
|
575
580
|
arg0 = expr.args[0]
|
|
576
581
|
_ = self._expr(arg0)
|
|
577
582
|
bits = expr.result_size(self.tyenv)
|
|
@@ -582,19 +587,19 @@ class SimEngineRDVEX(
|
|
|
582
587
|
# Binary operation handlers
|
|
583
588
|
#
|
|
584
589
|
@binop_handler
|
|
585
|
-
def _handle_binop_ExpCmpNE64(self, expr):
|
|
590
|
+
def _handle_binop_ExpCmpNE64(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
586
591
|
_, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
587
592
|
bits = expr.result_size(self.tyenv)
|
|
588
593
|
# Need to actually implement this later
|
|
589
594
|
return MultiValues(self.state.top(bits))
|
|
590
595
|
|
|
591
596
|
@binop_handler
|
|
592
|
-
def _handle_binop_16HLto32(self, expr):
|
|
597
|
+
def _handle_binop_16HLto32(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
593
598
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
594
599
|
return expr0.concat(expr1)
|
|
595
600
|
|
|
596
601
|
@binop_handler
|
|
597
|
-
def _handle_binop_Add(self, expr):
|
|
602
|
+
def _handle_binop_Add(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
598
603
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
599
604
|
bits = expr.result_size(self.tyenv)
|
|
600
605
|
|
|
@@ -625,7 +630,7 @@ class SimEngineRDVEX(
|
|
|
625
630
|
return r
|
|
626
631
|
|
|
627
632
|
@binop_handler
|
|
628
|
-
def _handle_binop_Sub(self, expr):
|
|
633
|
+
def _handle_binop_Sub(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
629
634
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
630
635
|
bits = expr.result_size(self.tyenv)
|
|
631
636
|
|
|
@@ -656,7 +661,7 @@ class SimEngineRDVEX(
|
|
|
656
661
|
return r
|
|
657
662
|
|
|
658
663
|
@binop_handler
|
|
659
|
-
def _handle_binop_Mul(self, expr):
|
|
664
|
+
def _handle_binop_Mul(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
660
665
|
expr0, expr1 = self._expr_pair(expr.args[0], expr.args[1])
|
|
661
666
|
bits = expr.result_size(self.tyenv)
|
|
662
667
|
|
|
@@ -687,13 +692,13 @@ class SimEngineRDVEX(
|
|
|
687
692
|
return r
|
|
688
693
|
|
|
689
694
|
@binop_handler
|
|
690
|
-
def _handle_binop_Mull(self, expr):
|
|
695
|
+
def _handle_binop_Mull(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
691
696
|
_, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
692
697
|
bits = expr.result_size(self.tyenv)
|
|
693
698
|
return MultiValues(self.state.top(bits))
|
|
694
699
|
|
|
695
700
|
@binop_handler
|
|
696
|
-
def _handle_binop_Div(self, expr):
|
|
701
|
+
def _handle_binop_Div(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
697
702
|
expr0, expr1 = self._expr_pair(expr.args[0], expr.args[1])
|
|
698
703
|
bits = expr.result_size(self.tyenv)
|
|
699
704
|
|
|
@@ -727,19 +732,20 @@ class SimEngineRDVEX(
|
|
|
727
732
|
return r
|
|
728
733
|
|
|
729
734
|
@binop_handler
|
|
730
|
-
def _handle_binop_DivMod(self, expr):
|
|
735
|
+
def _handle_binop_DivMod(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
731
736
|
_, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
732
737
|
bits = expr.result_size(self.tyenv)
|
|
733
738
|
|
|
734
739
|
return MultiValues(self.state.top(bits))
|
|
735
740
|
|
|
736
|
-
|
|
741
|
+
@binop_handler
|
|
742
|
+
def _handle_Mod(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
737
743
|
_, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
738
744
|
bits = expr.result_size(self.tyenv)
|
|
739
745
|
return MultiValues(self.state.top(bits))
|
|
740
746
|
|
|
741
747
|
@binop_handler
|
|
742
|
-
def _handle_binop_And(self, expr):
|
|
748
|
+
def _handle_binop_And(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
743
749
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
744
750
|
bits = expr.result_size(self.tyenv)
|
|
745
751
|
|
|
@@ -748,9 +754,8 @@ class SimEngineRDVEX(
|
|
|
748
754
|
expr1_v = expr1.one_value()
|
|
749
755
|
|
|
750
756
|
if expr0_v is not None and expr1_v is not None:
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
r = MultiValues(expr0_v & expr1_v)
|
|
757
|
+
# bitwise-and two single values together
|
|
758
|
+
r = MultiValues(expr0_v & expr1_v)
|
|
754
759
|
elif expr0_v is None and expr1_v is not None:
|
|
755
760
|
# bitwise-and a single value with a multivalue
|
|
756
761
|
if expr0.count() == 1 and 0 in expr0:
|
|
@@ -771,7 +776,7 @@ class SimEngineRDVEX(
|
|
|
771
776
|
return r
|
|
772
777
|
|
|
773
778
|
@binop_handler
|
|
774
|
-
def _handle_binop_Xor(self, expr):
|
|
779
|
+
def _handle_binop_Xor(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
775
780
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
776
781
|
bits = expr.result_size(self.tyenv)
|
|
777
782
|
|
|
@@ -803,7 +808,7 @@ class SimEngineRDVEX(
|
|
|
803
808
|
return r
|
|
804
809
|
|
|
805
810
|
@binop_handler
|
|
806
|
-
def _handle_binop_Or(self, expr):
|
|
811
|
+
def _handle_binop_Or(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
807
812
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
808
813
|
bits = expr.result_size(self.tyenv)
|
|
809
814
|
|
|
@@ -834,7 +839,7 @@ class SimEngineRDVEX(
|
|
|
834
839
|
return r
|
|
835
840
|
|
|
836
841
|
@binop_handler
|
|
837
|
-
def _handle_binop_Sar(self, expr):
|
|
842
|
+
def _handle_binop_Sar(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
838
843
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
839
844
|
bits = expr.result_size(self.tyenv)
|
|
840
845
|
|
|
@@ -877,7 +882,7 @@ class SimEngineRDVEX(
|
|
|
877
882
|
return r
|
|
878
883
|
|
|
879
884
|
@binop_handler
|
|
880
|
-
def _handle_binop_Shr(self, expr):
|
|
885
|
+
def _handle_binop_Shr(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
881
886
|
expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
|
|
882
887
|
bits = expr.result_size(self.tyenv)
|
|
883
888
|
|
|
@@ -918,7 +923,7 @@ class SimEngineRDVEX(
|
|
|
918
923
|
return r
|
|
919
924
|
|
|
920
925
|
@binop_handler
|
|
921
|
-
def _handle_binop_Shl(self, expr):
|
|
926
|
+
def _handle_binop_Shl(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
922
927
|
expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
923
928
|
bits = expr.result_size(self.tyenv)
|
|
924
929
|
|
|
@@ -956,7 +961,7 @@ class SimEngineRDVEX(
|
|
|
956
961
|
return r
|
|
957
962
|
|
|
958
963
|
@binop_handler
|
|
959
|
-
def _handle_binop_CmpEQ(self, expr):
|
|
964
|
+
def _handle_binop_CmpEQ(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
960
965
|
arg0, arg1 = expr.args
|
|
961
966
|
expr_0 = self._expr(arg0)
|
|
962
967
|
expr_1 = self._expr(arg1)
|
|
@@ -974,7 +979,7 @@ class SimEngineRDVEX(
|
|
|
974
979
|
return MultiValues(self.state.top(1))
|
|
975
980
|
|
|
976
981
|
@binop_handler
|
|
977
|
-
def _handle_binop_CmpNE(self, expr):
|
|
982
|
+
def _handle_binop_CmpNE(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
978
983
|
arg0, arg1 = expr.args
|
|
979
984
|
expr_0 = self._expr(arg0)
|
|
980
985
|
expr_1 = self._expr(arg1)
|
|
@@ -989,7 +994,7 @@ class SimEngineRDVEX(
|
|
|
989
994
|
return MultiValues(self.state.top(1))
|
|
990
995
|
|
|
991
996
|
@binop_handler
|
|
992
|
-
def _handle_binop_CmpLT(self, expr):
|
|
997
|
+
def _handle_binop_CmpLT(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
993
998
|
arg0, arg1 = expr.args
|
|
994
999
|
expr_0, expr_1 = self._expr_pair(arg0, arg1)
|
|
995
1000
|
|
|
@@ -1004,7 +1009,7 @@ class SimEngineRDVEX(
|
|
|
1004
1009
|
return MultiValues(self.state.top(1))
|
|
1005
1010
|
|
|
1006
1011
|
@binop_handler
|
|
1007
|
-
def _handle_binop_CmpLE(self, expr):
|
|
1012
|
+
def _handle_binop_CmpLE(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
1008
1013
|
arg0, arg1 = expr.args
|
|
1009
1014
|
expr_0, expr_1 = self._expr_pair(arg0, arg1)
|
|
1010
1015
|
|
|
@@ -1019,7 +1024,7 @@ class SimEngineRDVEX(
|
|
|
1019
1024
|
return MultiValues(self.state.top(1))
|
|
1020
1025
|
|
|
1021
1026
|
@binop_handler
|
|
1022
|
-
def _handle_binop_CmpGT(self, expr):
|
|
1027
|
+
def _handle_binop_CmpGT(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
1023
1028
|
arg0, arg1 = expr.args
|
|
1024
1029
|
expr_0, expr_1 = self._expr_pair(arg0, arg1)
|
|
1025
1030
|
|
|
@@ -1034,7 +1039,7 @@ class SimEngineRDVEX(
|
|
|
1034
1039
|
return MultiValues(self.state.top(1))
|
|
1035
1040
|
|
|
1036
1041
|
@binop_handler
|
|
1037
|
-
def _handle_binop_CmpGE(self, expr):
|
|
1042
|
+
def _handle_binop_CmpGE(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
1038
1043
|
arg0, arg1 = expr.args
|
|
1039
1044
|
expr_0, expr_1 = self._expr_pair(arg0, arg1)
|
|
1040
1045
|
|
|
@@ -1050,7 +1055,7 @@ class SimEngineRDVEX(
|
|
|
1050
1055
|
|
|
1051
1056
|
# ppc only
|
|
1052
1057
|
@binop_handler
|
|
1053
|
-
def _handle_binop_CmpORD(self, expr):
|
|
1058
|
+
def _handle_binop_CmpORD(self, expr: pyvex.expr.Binop) -> MultiValues:
|
|
1054
1059
|
arg0, arg1 = expr.args
|
|
1055
1060
|
expr_0, expr_1 = self._expr_pair(arg0, arg1)
|
|
1056
1061
|
|
|
@@ -16,7 +16,6 @@ from angr.calling_conventions import SimCC
|
|
|
16
16
|
from angr.sim_type import SimTypeFunction
|
|
17
17
|
from angr.knowledge_plugins.key_definitions.definition import Definition
|
|
18
18
|
from angr.knowledge_plugins.functions import Function
|
|
19
|
-
from angr.analyses.reaching_definitions.dep_graph import FunctionCallRelationships
|
|
20
19
|
from angr.code_location import CodeLocation, ExternalCodeLocation
|
|
21
20
|
from angr.knowledge_plugins.key_definitions.constants import ObservationPointType
|
|
22
21
|
from angr import SIM_LIBRARIES, SIM_TYPE_COLLECTIONS
|
|
@@ -246,7 +245,7 @@ class FunctionCallDataUnwrapped(FunctionCallData):
|
|
|
246
245
|
@staticmethod
|
|
247
246
|
@wraps
|
|
248
247
|
def decorate(
|
|
249
|
-
f: Callable[[FunctionHandler, ReachingDefinitionsState, FunctionCallDataUnwrapped], None]
|
|
248
|
+
f: Callable[[FunctionHandler, ReachingDefinitionsState, FunctionCallDataUnwrapped], None],
|
|
250
249
|
) -> Callable[[FunctionHandler, ReachingDefinitionsState, FunctionCallData], None]:
|
|
251
250
|
"""
|
|
252
251
|
Decorate a function handler method with this to make it take a FunctionCallDataUnwrapped instead of a
|
|
@@ -263,6 +262,20 @@ def _mk_wrapper(func, iself):
|
|
|
263
262
|
return lambda *args, **kwargs: func(iself, *args, **kwargs)
|
|
264
263
|
|
|
265
264
|
|
|
265
|
+
@dataclass
|
|
266
|
+
class FunctionCallRelationships:
|
|
267
|
+
"""
|
|
268
|
+
Produced by the function handler, provides associated callsite info and function input/output definitions.
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
callsite: CodeLocation
|
|
272
|
+
target: int | None
|
|
273
|
+
args_defns: list[set[Definition]]
|
|
274
|
+
other_input_defns: set[Definition]
|
|
275
|
+
ret_defns: set[Definition]
|
|
276
|
+
other_output_defns: set[Definition]
|
|
277
|
+
|
|
278
|
+
|
|
266
279
|
# pylint: disable=unused-argument, no-self-use
|
|
267
280
|
class FunctionHandler:
|
|
268
281
|
"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Any, TYPE_CHECKING,
|
|
2
|
+
from typing import Any, TYPE_CHECKING, overload
|
|
3
3
|
from collections.abc import Iterable, Iterator
|
|
4
4
|
import logging
|
|
5
5
|
from typing_extensions import Self
|
|
@@ -7,7 +7,6 @@ from typing_extensions import Self
|
|
|
7
7
|
import archinfo
|
|
8
8
|
import claripy
|
|
9
9
|
|
|
10
|
-
from angr.misc.ux import deprecated
|
|
11
10
|
from angr.knowledge_plugins.key_definitions.environment import Environment
|
|
12
11
|
from angr.knowledge_plugins.key_definitions.tag import Tag
|
|
13
12
|
from angr.knowledge_plugins.key_definitions.heap_address import HeapAddress
|
|
@@ -541,41 +540,6 @@ class ReachingDefinitionsState:
|
|
|
541
540
|
self.all_definitions = set()
|
|
542
541
|
self.live_definitions.reset_uses()
|
|
543
542
|
|
|
544
|
-
@deprecated("deref")
|
|
545
|
-
def pointer_to_atoms(self, pointer: MultiValues, size: int, endness: str) -> set[MemoryLocation]:
|
|
546
|
-
"""
|
|
547
|
-
Given a MultiValues, return the set of atoms that loading or storing to the pointer with that value
|
|
548
|
-
could define or use.
|
|
549
|
-
"""
|
|
550
|
-
result = set()
|
|
551
|
-
for vs in pointer.values():
|
|
552
|
-
for value in vs:
|
|
553
|
-
atom = self.pointer_to_atom(value, size, endness)
|
|
554
|
-
if atom is not None:
|
|
555
|
-
result.add(atom)
|
|
556
|
-
|
|
557
|
-
return result
|
|
558
|
-
|
|
559
|
-
@deprecated("deref")
|
|
560
|
-
def pointer_to_atom(self, value: claripy.ast.BV, size: int, endness: str) -> MemoryLocation | None:
|
|
561
|
-
if self.is_top(value):
|
|
562
|
-
return None
|
|
563
|
-
|
|
564
|
-
stack_offset = self.get_stack_offset(value)
|
|
565
|
-
if stack_offset is not None:
|
|
566
|
-
addr = SpOffset(len(value), stack_offset)
|
|
567
|
-
else:
|
|
568
|
-
heap_offset = self.get_heap_offset(value)
|
|
569
|
-
if heap_offset is not None:
|
|
570
|
-
addr = HeapAddress(heap_offset)
|
|
571
|
-
elif value.op == "BVV":
|
|
572
|
-
addr = cast(int, value.args[0])
|
|
573
|
-
else:
|
|
574
|
-
# cannot resolve
|
|
575
|
-
return None
|
|
576
|
-
|
|
577
|
-
return MemoryLocation(addr, size, endness)
|
|
578
|
-
|
|
579
543
|
@overload
|
|
580
544
|
def deref(
|
|
581
545
|
self,
|
|
@@ -16,7 +16,6 @@ from angr.knowledge_plugins.functions import Function
|
|
|
16
16
|
from angr.knowledge_plugins.key_definitions import ReachingDefinitionsModel, LiveDefinitions
|
|
17
17
|
from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE, OP_AFTER, ObservationPointType, ObservationPoint
|
|
18
18
|
from angr.code_location import CodeLocation, ExternalCodeLocation
|
|
19
|
-
from angr.misc.ux import deprecated
|
|
20
19
|
from angr.analyses.forward_analysis.visitors.graph import NodeType
|
|
21
20
|
from angr.analyses.analysis import Analysis
|
|
22
21
|
from .engine_ail import SimEngineRDAIL
|
|
@@ -50,13 +49,13 @@ class ReachingDefinitionsAnalysis(
|
|
|
50
49
|
|
|
51
50
|
def __init__(
|
|
52
51
|
self,
|
|
53
|
-
subject: Subject | ailment.Block | Block | Function | str
|
|
52
|
+
subject: Subject | ailment.Block | Block | Function | str,
|
|
54
53
|
func_graph=None,
|
|
55
54
|
max_iterations=30,
|
|
56
55
|
track_tmps=False,
|
|
57
56
|
track_consts=True,
|
|
58
57
|
observation_points: Iterable[ObservationPoint] | None = None,
|
|
59
|
-
init_state: ReachingDefinitionsState = None,
|
|
58
|
+
init_state: ReachingDefinitionsState | None = None,
|
|
60
59
|
init_context=None,
|
|
61
60
|
state_initializer: RDAStateInitializer | None = None,
|
|
62
61
|
cc=None,
|
|
@@ -242,10 +241,6 @@ class ReachingDefinitionsAnalysis(
|
|
|
242
241
|
def visited_blocks(self):
|
|
243
242
|
return self._visited_blocks
|
|
244
243
|
|
|
245
|
-
@deprecated(replacement="get_reaching_definitions_by_insn")
|
|
246
|
-
def get_reaching_definitions(self, ins_addr, op_type):
|
|
247
|
-
return self.get_reaching_definitions_by_insn(ins_addr, op_type)
|
|
248
|
-
|
|
249
244
|
def get_reaching_definitions_by_insn(self, ins_addr, op_type):
|
|
250
245
|
key = "insn", ins_addr, op_type
|
|
251
246
|
if key not in self.observed_results:
|
|
@@ -280,29 +275,22 @@ class ReachingDefinitionsAnalysis(
|
|
|
280
275
|
:param node_idx: ID of the node. Used in AIL to differentiate blocks with the same address.
|
|
281
276
|
"""
|
|
282
277
|
|
|
283
|
-
key = None
|
|
284
|
-
|
|
278
|
+
key: ObservationPoint | None = None
|
|
285
279
|
observe = False
|
|
286
280
|
|
|
287
281
|
if self._observe_all:
|
|
288
282
|
observe = True
|
|
289
|
-
key
|
|
290
|
-
("node", node_addr, op_type) if node_idx is None else ("node", (node_addr, node_idx), op_type)
|
|
291
|
-
)
|
|
283
|
+
key = ("node", node_addr, op_type) if node_idx is None else ("node", (node_addr, node_idx), op_type)
|
|
292
284
|
elif self._observation_points is not None:
|
|
293
|
-
key
|
|
294
|
-
("node", node_addr, op_type) if node_idx is None else ("node", (node_addr, node_idx), op_type)
|
|
295
|
-
)
|
|
285
|
+
key = ("node", node_addr, op_type) if node_idx is None else ("node", (node_addr, node_idx), op_type)
|
|
296
286
|
if key in self._observation_points:
|
|
297
287
|
observe = True
|
|
298
288
|
elif self._observe_callback is not None:
|
|
299
289
|
observe = self._observe_callback("node", addr=node_addr, state=state, op_type=op_type, node_idx=node_idx)
|
|
300
290
|
if observe:
|
|
301
|
-
key
|
|
302
|
-
("node", node_addr, op_type) if node_idx is None else ("node", (node_addr, node_idx), op_type)
|
|
303
|
-
)
|
|
291
|
+
key = ("node", node_addr, op_type) if node_idx is None else ("node", (node_addr, node_idx), op_type)
|
|
304
292
|
|
|
305
|
-
if observe:
|
|
293
|
+
if observe and key:
|
|
306
294
|
self.observed_results[key] = state.live_definitions
|
|
307
295
|
|
|
308
296
|
def insn_observe(
|
|
@@ -321,14 +309,14 @@ class ReachingDefinitionsAnalysis(
|
|
|
321
309
|
:param op_type: Type of the observation point. Must be one of the following: OP_BEORE, OP_AFTER.
|
|
322
310
|
"""
|
|
323
311
|
|
|
324
|
-
key = None
|
|
312
|
+
key: ObservationPoint | None = None
|
|
325
313
|
observe = False
|
|
326
314
|
|
|
327
315
|
if self._observe_all:
|
|
328
316
|
observe = True
|
|
329
|
-
key
|
|
317
|
+
key = ("insn", insn_addr, op_type)
|
|
330
318
|
elif self._observation_points is not None:
|
|
331
|
-
key
|
|
319
|
+
key = ("insn", insn_addr, op_type)
|
|
332
320
|
if key in self._observation_points:
|
|
333
321
|
observe = True
|
|
334
322
|
elif self._observe_callback is not None:
|
|
@@ -336,9 +324,9 @@ class ReachingDefinitionsAnalysis(
|
|
|
336
324
|
"insn", addr=insn_addr, stmt=stmt, block=block, state=state, op_type=op_type
|
|
337
325
|
)
|
|
338
326
|
if observe:
|
|
339
|
-
key
|
|
327
|
+
key = ("insn", insn_addr, op_type)
|
|
340
328
|
|
|
341
|
-
if not observe:
|
|
329
|
+
if not (observe and key):
|
|
342
330
|
return
|
|
343
331
|
|
|
344
332
|
if isinstance(stmt, pyvex.stmt.IRStmt):
|
|
@@ -533,6 +521,7 @@ class ReachingDefinitionsAnalysis(
|
|
|
533
521
|
]
|
|
534
522
|
if node.addr == self.subject.content.addr:
|
|
535
523
|
node_parents += [ExternalCodeLocation()]
|
|
524
|
+
assert block is not None
|
|
536
525
|
self.model.at_new_block(
|
|
537
526
|
CodeLocation(block.addr, 0, block_idx=block.idx if isinstance(block, ailment.Block) else None),
|
|
538
527
|
node_parents,
|
angr/analyses/s_propagator.py
CHANGED
|
@@ -35,6 +35,7 @@ from angr.utils.ssa import (
|
|
|
35
35
|
get_tmp_uselocs,
|
|
36
36
|
get_tmp_deflocs,
|
|
37
37
|
phi_assignment_get_src,
|
|
38
|
+
has_store_stmt_in_between_stmts,
|
|
38
39
|
)
|
|
39
40
|
|
|
40
41
|
|
|
@@ -186,6 +187,8 @@ class SPropagatorAnalysis(Analysis):
|
|
|
186
187
|
|
|
187
188
|
# function mode only
|
|
188
189
|
if self.mode == "function":
|
|
190
|
+
assert self.func_graph is not None
|
|
191
|
+
|
|
189
192
|
for vvar, defloc in vvar_deflocs.items():
|
|
190
193
|
if vvar.varid not in vvar_uselocs:
|
|
191
194
|
continue
|
|
@@ -213,7 +216,7 @@ class SPropagatorAnalysis(Analysis):
|
|
|
213
216
|
# }
|
|
214
217
|
can_replace = True
|
|
215
218
|
for _, vvar_useloc in vvar_uselocs[vvar.varid]:
|
|
216
|
-
if self.
|
|
219
|
+
if has_store_stmt_in_between_stmts(self.func_graph, blocks, defloc, vvar_useloc):
|
|
217
220
|
can_replace = False
|
|
218
221
|
|
|
219
222
|
if can_replace:
|
|
@@ -241,8 +244,8 @@ class SPropagatorAnalysis(Analysis):
|
|
|
241
244
|
if vvar.was_reg or vvar.was_parameter:
|
|
242
245
|
if len(vvar_uselocs[vvar.varid]) == 1:
|
|
243
246
|
vvar_used, vvar_useloc = next(iter(vvar_uselocs[vvar.varid]))
|
|
244
|
-
if is_const_vvar_load_assignment(stmt) and not
|
|
245
|
-
blocks, defloc, vvar_useloc
|
|
247
|
+
if is_const_vvar_load_assignment(stmt) and not has_store_stmt_in_between_stmts(
|
|
248
|
+
self.func_graph, blocks, defloc, vvar_useloc
|
|
246
249
|
):
|
|
247
250
|
# we can propagate this load because there is no store between its def and use
|
|
248
251
|
replacements[vvar_useloc][vvar_used] = stmt.src
|
|
@@ -462,44 +465,6 @@ class SPropagatorAnalysis(Analysis):
|
|
|
462
465
|
|
|
463
466
|
return False
|
|
464
467
|
|
|
465
|
-
def has_store_stmt_in_between(
|
|
466
|
-
self, blocks: dict[tuple[int, int | None], Block], defloc: CodeLocation, useloc: CodeLocation
|
|
467
|
-
) -> bool:
|
|
468
|
-
assert defloc.block_addr is not None
|
|
469
|
-
assert defloc.stmt_idx is not None
|
|
470
|
-
assert useloc.block_addr is not None
|
|
471
|
-
assert useloc.stmt_idx is not None
|
|
472
|
-
assert self.func_graph is not None
|
|
473
|
-
|
|
474
|
-
use_block = blocks[(useloc.block_addr, useloc.block_idx)]
|
|
475
|
-
def_block = blocks[(defloc.block_addr, defloc.block_idx)]
|
|
476
|
-
|
|
477
|
-
# traverse the graph, go from use_block until we reach def_block, and look for Store statements
|
|
478
|
-
seen = {use_block}
|
|
479
|
-
queue = [use_block]
|
|
480
|
-
while queue:
|
|
481
|
-
block = queue.pop(0)
|
|
482
|
-
|
|
483
|
-
starting_stmt_idx, ending_stmt_idx = 0, len(block.statements)
|
|
484
|
-
if block is def_block:
|
|
485
|
-
starting_stmt_idx = defloc.stmt_idx + 1
|
|
486
|
-
if block is use_block:
|
|
487
|
-
ending_stmt_idx = useloc.stmt_idx
|
|
488
|
-
|
|
489
|
-
for i in range(starting_stmt_idx, ending_stmt_idx):
|
|
490
|
-
if isinstance(block.statements[i], Store):
|
|
491
|
-
return True
|
|
492
|
-
|
|
493
|
-
if block is def_block:
|
|
494
|
-
continue
|
|
495
|
-
|
|
496
|
-
for pred in self.func_graph.predecessors(block):
|
|
497
|
-
if pred not in seen:
|
|
498
|
-
seen.add(pred)
|
|
499
|
-
queue.append(pred)
|
|
500
|
-
|
|
501
|
-
return False
|
|
502
|
-
|
|
503
468
|
@staticmethod
|
|
504
469
|
def is_vvar_used_for_addr_loading_switch_case(uselocs: set[CodeLocation], blocks) -> bool:
|
|
505
470
|
"""
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
from collections.abc import Generator
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any, Literal, overload
|
|
6
6
|
|
|
7
7
|
from ailment.expression import VirtualVariable, Tmp
|
|
8
8
|
|
|
@@ -48,6 +48,12 @@ class SRDAModel:
|
|
|
48
48
|
s.add(Definition(tmp_atom, CodeLocation(block_loc.block_addr, stmt_idx, block_idx=block_loc.block_idx)))
|
|
49
49
|
return s
|
|
50
50
|
|
|
51
|
+
@overload
|
|
52
|
+
def get_uses_by_location(self, loc: CodeLocation, exprs: Literal[True]) -> set[tuple[Definition, Any | None]]: ...
|
|
53
|
+
|
|
54
|
+
@overload
|
|
55
|
+
def get_uses_by_location(self, loc: CodeLocation, exprs: Literal[False] = ...) -> set[Definition]: ...
|
|
56
|
+
|
|
51
57
|
def get_uses_by_location(
|
|
52
58
|
self, loc: CodeLocation, exprs: bool = False
|
|
53
59
|
) -> set[Definition] | set[tuple[Definition, Any | None]]:
|