angr 9.2.61__py3-none-manylinux2014_x86_64.whl → 9.2.63__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/cfg/cfg_fast.py +18 -20
- angr/analyses/decompiler/ail_simplifier.py +15 -30
- angr/analyses/decompiler/block_simplifier.py +11 -7
- angr/analyses/decompiler/clinic.py +144 -0
- angr/analyses/decompiler/condition_processor.py +4 -2
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +2 -0
- angr/analyses/decompiler/structured_codegen/c.py +20 -16
- angr/analyses/decompiler/structuring/phoenix.py +6 -10
- angr/analyses/disassembly.py +7 -11
- angr/analyses/propagator/engine_ail.py +14 -42
- angr/analyses/propagator/outdated_definition_walker.py +17 -53
- angr/analyses/propagator/propagator.py +1 -0
- angr/analyses/reaching_definitions/engine_ail.py +20 -9
- angr/analyses/reaching_definitions/engine_vex.py +20 -5
- angr/analyses/reaching_definitions/function_handler.py +9 -3
- angr/analyses/reaching_definitions/rd_state.py +34 -13
- angr/analyses/reaching_definitions/reaching_definitions.py +92 -16
- angr/analyses/variable_recovery/engine_vex.py +20 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +5 -0
- angr/calling_conventions.py +28 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +15 -5
- angr/knowledge_plugins/key_definitions/liveness.py +94 -0
- angr/knowledge_plugins/key_definitions/rd_model.py +90 -9
- angr/knowledge_plugins/propagations/states.py +3 -0
- angr/knowledge_plugins/variables/variable_manager.py +26 -4
- angr/lib/angr_native.so +0 -0
- angr/project.py +2 -2
- angr/sim_type.py +2 -2
- angr/state_plugins/unicorn_engine.py +9 -1
- angr/storage/memory_mixins/multi_value_merger_mixin.py +7 -2
- angr/utils/timing.py +12 -5
- {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/METADATA +15 -15
- {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/RECORD +37 -36
- {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/WHEEL +1 -1
- {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/LICENSE +0 -0
- {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/top_level.txt +0 -0
angr/calling_conventions.py
CHANGED
|
@@ -158,6 +158,12 @@ def refine_locs_with_struct_type(
|
|
|
158
158
|
for field, field_ty in arg_type.fields.items()
|
|
159
159
|
}
|
|
160
160
|
return SimStructArg(arg_type, locs)
|
|
161
|
+
if isinstance(arg_type, SimUnion):
|
|
162
|
+
# Treat a SimUnion as functionality equivalent to its longest member
|
|
163
|
+
for member in arg_type.members.values():
|
|
164
|
+
if member.size == arg_type.size:
|
|
165
|
+
return refine_locs_with_struct_type(arch, locs, member, offset)
|
|
166
|
+
|
|
161
167
|
raise TypeError("I don't know how to lay out a %s" % arg_type)
|
|
162
168
|
|
|
163
169
|
|
|
@@ -1813,6 +1819,24 @@ class SimCCAArch64LinuxSyscall(SimCCSyscall):
|
|
|
1813
1819
|
return state.regs.x8
|
|
1814
1820
|
|
|
1815
1821
|
|
|
1822
|
+
class SimCCRISCV64LinuxSyscall(SimCCSyscall):
|
|
1823
|
+
# TODO: Make sure all the information is correct
|
|
1824
|
+
ARG_REGS = ["a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7"]
|
|
1825
|
+
FP_ARG_REGS = [] # TODO: ???
|
|
1826
|
+
RETURN_VAL = SimRegArg("a0", 8)
|
|
1827
|
+
RETURN_ADDR = SimRegArg("ip_at_syscall", 4)
|
|
1828
|
+
ARCH = archinfo.ArchRISCV64
|
|
1829
|
+
|
|
1830
|
+
@classmethod
|
|
1831
|
+
def _match(cls, arch, args, sp_delta): # pylint: disable=unused-argument
|
|
1832
|
+
# never appears anywhere except syscalls
|
|
1833
|
+
return False
|
|
1834
|
+
|
|
1835
|
+
@staticmethod
|
|
1836
|
+
def syscall_num(state):
|
|
1837
|
+
return state.regs.a0
|
|
1838
|
+
|
|
1839
|
+
|
|
1816
1840
|
class SimCCO32(SimCC):
|
|
1817
1841
|
ARG_REGS = ["a0", "a1", "a2", "a3"]
|
|
1818
1842
|
FP_ARG_REGS = [
|
|
@@ -2292,6 +2316,10 @@ SYSCALL_CC: Dict[str, Dict[str, Type[SimCCSyscall]]] = {
|
|
|
2292
2316
|
"default": SimCCS390XLinuxSyscall,
|
|
2293
2317
|
"Linux": SimCCS390XLinuxSyscall,
|
|
2294
2318
|
},
|
|
2319
|
+
"RISCV64": {
|
|
2320
|
+
"default": SimCCRISCV64LinuxSyscall,
|
|
2321
|
+
"Linux": SimCCRISCV64LinuxSyscall,
|
|
2322
|
+
},
|
|
2295
2323
|
}
|
|
2296
2324
|
|
|
2297
2325
|
|
|
@@ -196,7 +196,7 @@ class LiveDefinitions:
|
|
|
196
196
|
ctnt += ", %d tmpdefs" % len(self.tmps)
|
|
197
197
|
return "<%s>" % ctnt
|
|
198
198
|
|
|
199
|
-
def copy(self) -> "LiveDefinitions":
|
|
199
|
+
def copy(self, discard_tmpdefs=False) -> "LiveDefinitions":
|
|
200
200
|
rd = LiveDefinitions(
|
|
201
201
|
self.arch,
|
|
202
202
|
track_tmps=self.track_tmps,
|
|
@@ -205,12 +205,12 @@ class LiveDefinitions:
|
|
|
205
205
|
stack_definitions=self.stack_definitions.copy(),
|
|
206
206
|
heap_definitions=self.heap_definitions.copy(),
|
|
207
207
|
memory_definitions=self.memory_definitions.copy(),
|
|
208
|
-
tmps=self.tmps.copy(),
|
|
208
|
+
tmps=self.tmps.copy() if not discard_tmpdefs else None,
|
|
209
209
|
register_uses=self.register_uses.copy(),
|
|
210
210
|
stack_uses=self.stack_uses.copy(),
|
|
211
211
|
heap_uses=self.heap_uses.copy(),
|
|
212
212
|
memory_uses=self.memory_uses.copy(),
|
|
213
|
-
tmp_uses=self.tmp_uses.copy(),
|
|
213
|
+
tmp_uses=self.tmp_uses.copy() if not discard_tmpdefs else None,
|
|
214
214
|
)
|
|
215
215
|
|
|
216
216
|
return rd
|
|
@@ -495,6 +495,9 @@ class LiveDefinitions:
|
|
|
495
495
|
except SimMemoryError:
|
|
496
496
|
l.warning("Failed to store register definition %s at %d.", d, atom.reg_offset, exc_info=True)
|
|
497
497
|
elif isinstance(atom, MemoryLocation):
|
|
498
|
+
if endness is None:
|
|
499
|
+
endness = atom.endness
|
|
500
|
+
|
|
498
501
|
if isinstance(atom.addr, SpOffset):
|
|
499
502
|
if atom.addr.offset is not None:
|
|
500
503
|
stack_addr = self.stack_offset_to_stack_addr(atom.addr.offset)
|
|
@@ -600,8 +603,15 @@ class LiveDefinitions:
|
|
|
600
603
|
size=size,
|
|
601
604
|
endness=endness,
|
|
602
605
|
)
|
|
603
|
-
except SimMemoryMissingError:
|
|
604
|
-
|
|
606
|
+
except SimMemoryMissingError as ex:
|
|
607
|
+
# load values and stop at the missing location
|
|
608
|
+
if ex.missing_addr > reg_offset:
|
|
609
|
+
values: MultiValues = self.register_definitions.load(
|
|
610
|
+
reg_offset, size=ex.missing_addr - reg_offset, endness=endness
|
|
611
|
+
)
|
|
612
|
+
else:
|
|
613
|
+
# nothing we can do
|
|
614
|
+
return
|
|
605
615
|
yield from LiveDefinitions.extract_defs_from_mv(values)
|
|
606
616
|
|
|
607
617
|
def get_stack_values(self, stack_offset: int, size: int, endness: str) -> Optional[MultiValues]:
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from typing import DefaultDict, Optional, List, Set, Tuple, TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
|
|
5
|
+
from .constants import ObservationPointType, OP_BEFORE, OP_AFTER
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .definition import Definition
|
|
9
|
+
from angr.code_location import CodeLocation
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
LocationType = Tuple[int, Optional[int], Optional[int]] # block addr, block ID, stmt ID
|
|
13
|
+
LocationWithPosType = Tuple[
|
|
14
|
+
int, Optional[int], Optional[int], ObservationPointType
|
|
15
|
+
] # block addr, block ID, stmt ID, before/after
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Liveness:
|
|
19
|
+
"""
|
|
20
|
+
This class stores liveness information for each definition.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self):
|
|
24
|
+
self.curr_live_defs: Set["Definition"] = set()
|
|
25
|
+
self.curr_loc: Optional[LocationType] = None
|
|
26
|
+
self.def_to_liveness: DefaultDict["Definition", Set[LocationType]] = defaultdict(set)
|
|
27
|
+
self.loc_to_defs: DefaultDict[LocationWithPosType, Set["Definition"]] = defaultdict(set)
|
|
28
|
+
self._node_max_stmt_id: DefaultDict[Tuple[int, Optional[int]], int] = defaultdict(int)
|
|
29
|
+
|
|
30
|
+
def add_def(self, d: "Definition", code_loc: "CodeLocation") -> None:
|
|
31
|
+
loc = (code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx)
|
|
32
|
+
self.curr_live_defs.add(d)
|
|
33
|
+
self.def_to_liveness[d].add(loc)
|
|
34
|
+
|
|
35
|
+
def kill_def(self, d: "Definition") -> None:
|
|
36
|
+
self.curr_live_defs.discard(d)
|
|
37
|
+
|
|
38
|
+
def complete_loc(self) -> None:
|
|
39
|
+
if self.curr_loc is not None:
|
|
40
|
+
for live_def in self.curr_live_defs:
|
|
41
|
+
self.def_to_liveness[live_def].add(self.curr_loc)
|
|
42
|
+
self.loc_to_defs[self.curr_loc + (OP_AFTER,)] |= self.curr_live_defs
|
|
43
|
+
|
|
44
|
+
def at_new_stmt(self, code_loc: "CodeLocation") -> None:
|
|
45
|
+
"""
|
|
46
|
+
Only support moving from a statement to the next statement within one basic block.
|
|
47
|
+
"""
|
|
48
|
+
self.complete_loc()
|
|
49
|
+
self.curr_loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx
|
|
50
|
+
if (
|
|
51
|
+
code_loc.stmt_idx is not None
|
|
52
|
+
and code_loc.stmt_idx > self._node_max_stmt_id[(code_loc.block_addr, code_loc.block_idx)]
|
|
53
|
+
):
|
|
54
|
+
self._node_max_stmt_id[(code_loc.block_addr, code_loc.block_idx)] = code_loc.stmt_idx
|
|
55
|
+
|
|
56
|
+
def at_new_block(self, code_loc: "CodeLocation", pred_codelocs: List["CodeLocation"]) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Only support moving to a new block from one or more blocks.
|
|
59
|
+
"""
|
|
60
|
+
loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx
|
|
61
|
+
key = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx, OP_BEFORE
|
|
62
|
+
for pred_codeloc in pred_codelocs:
|
|
63
|
+
if pred_codeloc.stmt_idx is None:
|
|
64
|
+
# external code location
|
|
65
|
+
pred_max_stmt_id = None
|
|
66
|
+
else:
|
|
67
|
+
pred_max_stmt_id = self._node_max_stmt_id[(pred_codeloc.block_addr, pred_codeloc.block_idx)]
|
|
68
|
+
pred_key = pred_codeloc.block_addr, pred_codeloc.block_idx, pred_max_stmt_id, OP_AFTER
|
|
69
|
+
pred_defs = self.loc_to_defs[pred_key]
|
|
70
|
+
for pred_def in pred_defs:
|
|
71
|
+
self.def_to_liveness[pred_def].add(loc)
|
|
72
|
+
self.loc_to_defs[key] |= pred_defs
|
|
73
|
+
|
|
74
|
+
self.curr_live_defs = set(self.loc_to_defs[key])
|
|
75
|
+
self.curr_loc = loc
|
|
76
|
+
|
|
77
|
+
def find_defs_at(self, code_loc: "CodeLocation", op: int = OP_BEFORE) -> Set["Definition"]:
|
|
78
|
+
if op == OP_BEFORE:
|
|
79
|
+
if code_loc.stmt_idx != 0:
|
|
80
|
+
loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx - 1, OP_AFTER
|
|
81
|
+
else:
|
|
82
|
+
loc = code_loc.block_addr, code_loc.block_idx, 0, OP_BEFORE
|
|
83
|
+
else:
|
|
84
|
+
loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx, OP_AFTER
|
|
85
|
+
return set() if loc not in self.loc_to_defs else self.loc_to_defs[loc]
|
|
86
|
+
|
|
87
|
+
def copy(self) -> "Liveness":
|
|
88
|
+
o = Liveness()
|
|
89
|
+
o.curr_live_defs = self.curr_live_defs.copy()
|
|
90
|
+
o.curr_loc = self.curr_loc
|
|
91
|
+
o.def_to_liveness = self.def_to_liveness.copy()
|
|
92
|
+
o.loc_to_defs = self.loc_to_defs.copy()
|
|
93
|
+
o._node_max_stmt_id = self._node_max_stmt_id.copy()
|
|
94
|
+
return o
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
from typing import Dict, Tuple, Set, Union, Optional, TYPE_CHECKING, overload
|
|
2
|
-
|
|
3
|
-
from angr.knowledge_plugins.key_definitions.constants import ObservationPointType
|
|
4
|
-
from angr.code_location import CodeLocation
|
|
1
|
+
from typing import Dict, List, Tuple, Set, Union, Optional, TYPE_CHECKING, overload
|
|
5
2
|
|
|
3
|
+
from .atoms import Atom, Register, MemoryLocation, SpOffset
|
|
6
4
|
from .uses import Uses
|
|
7
5
|
from .live_definitions import LiveDefinitions
|
|
6
|
+
from .liveness import Liveness
|
|
7
|
+
from .constants import OP_BEFORE, ObservationPointType
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from angr.knowledge_plugins.key_definitions.definition import Definition
|
|
11
|
+
from angr.code_location import CodeLocation
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
# TODO: Make ReachingDefinitionsModel serializable
|
|
@@ -23,6 +24,7 @@ class ReachingDefinitionsModel:
|
|
|
23
24
|
] = {}
|
|
24
25
|
self.all_definitions: Set["Definition"] = set()
|
|
25
26
|
self.all_uses = Uses()
|
|
27
|
+
self.liveness = Liveness()
|
|
26
28
|
|
|
27
29
|
def __repr__(self):
|
|
28
30
|
return "<RDModel{} with {} observations>".format(
|
|
@@ -30,11 +32,70 @@ class ReachingDefinitionsModel:
|
|
|
30
32
|
len(self.observed_results),
|
|
31
33
|
)
|
|
32
34
|
|
|
35
|
+
def add_def(self, d: "Definition", codeloc: "CodeLocation") -> None:
|
|
36
|
+
self.liveness.add_def(d, codeloc)
|
|
37
|
+
|
|
38
|
+
def kill_def(self, d: "Definition") -> None:
|
|
39
|
+
self.liveness.kill_def(d)
|
|
40
|
+
|
|
41
|
+
def at_new_stmt(self, codeloc: "CodeLocation") -> None:
|
|
42
|
+
self.liveness.at_new_stmt(codeloc)
|
|
43
|
+
|
|
44
|
+
def at_new_block(self, code_loc: "CodeLocation", pred_codelocs: List["CodeLocation"]) -> None:
|
|
45
|
+
self.liveness.at_new_block(code_loc, pred_codelocs)
|
|
46
|
+
|
|
47
|
+
def complete_loc(self) -> None:
|
|
48
|
+
self.liveness.complete_loc()
|
|
49
|
+
|
|
50
|
+
def find_defs_at(self, code_loc: "CodeLocation", op: int = OP_BEFORE) -> Set["Definition"]:
|
|
51
|
+
return self.liveness.find_defs_at(code_loc, op=op)
|
|
52
|
+
|
|
53
|
+
def get_defs(self, atom: Atom, code_loc: "CodeLocation", op: int) -> Set["Definition"]:
|
|
54
|
+
all_defs = self.liveness.find_defs_at(code_loc, op=op)
|
|
55
|
+
defs = None
|
|
56
|
+
if isinstance(atom, Register):
|
|
57
|
+
defs = {
|
|
58
|
+
d
|
|
59
|
+
for d in all_defs
|
|
60
|
+
if isinstance(d.atom, Register)
|
|
61
|
+
and d.atom.reg_offset <= atom.reg_offset < d.atom.reg_offset + d.atom.size
|
|
62
|
+
}
|
|
63
|
+
elif isinstance(atom, MemoryLocation):
|
|
64
|
+
if isinstance(atom.addr, int):
|
|
65
|
+
defs = {
|
|
66
|
+
d
|
|
67
|
+
for d in all_defs
|
|
68
|
+
if isinstance(d.atom, MemoryLocation)
|
|
69
|
+
and isinstance(d.atom.addr, int)
|
|
70
|
+
and (
|
|
71
|
+
d.atom.addr <= atom.addr < d.atom.addr + d.size
|
|
72
|
+
or atom.addr <= d.atom.addr < atom.addr + atom.size
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
elif isinstance(atom.addr, SpOffset):
|
|
76
|
+
defs = {
|
|
77
|
+
d
|
|
78
|
+
for d in all_defs
|
|
79
|
+
if isinstance(d.atom, MemoryLocation)
|
|
80
|
+
and isinstance(d.atom.addr, SpOffset)
|
|
81
|
+
and (
|
|
82
|
+
d.atom.addr.offset <= atom.addr.offset < d.atom.addr.offset + d.size
|
|
83
|
+
or atom.addr.offset <= d.atom.addr.offset < atom.addr.offset + atom.size
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if defs is None:
|
|
88
|
+
# unsupported for now
|
|
89
|
+
defs = set()
|
|
90
|
+
|
|
91
|
+
return defs
|
|
92
|
+
|
|
33
93
|
def copy(self) -> "ReachingDefinitionsModel":
|
|
34
94
|
new = ReachingDefinitionsModel(self.func_addr)
|
|
35
95
|
new.observed_results = self.observed_results.copy()
|
|
36
96
|
new.all_definitions = self.all_definitions.copy()
|
|
37
97
|
new.all_uses = self.all_uses.copy()
|
|
98
|
+
new.liveness = self.liveness.copy()
|
|
38
99
|
return new
|
|
39
100
|
|
|
40
101
|
def merge(self, model: "ReachingDefinitionsModel"):
|
|
@@ -47,9 +108,10 @@ class ReachingDefinitionsModel:
|
|
|
47
108
|
self.observed_results[k] = merged
|
|
48
109
|
self.all_definitions.union(model.all_definitions)
|
|
49
110
|
self.all_uses.merge(model.all_uses)
|
|
111
|
+
# TODO: Merge self.liveness
|
|
50
112
|
|
|
51
113
|
def get_observation_by_insn(
|
|
52
|
-
self, ins_addr: Union[int, CodeLocation], kind: ObservationPointType
|
|
114
|
+
self, ins_addr: Union[int, "CodeLocation"], kind: ObservationPointType
|
|
53
115
|
) -> Optional[LiveDefinitions]:
|
|
54
116
|
if isinstance(ins_addr, int):
|
|
55
117
|
return self.observed_results.get(("insn", ins_addr, kind), None)
|
|
@@ -58,15 +120,21 @@ class ReachingDefinitionsModel:
|
|
|
58
120
|
return self.observed_results.get(("insn", ins_addr.ins_addr, kind))
|
|
59
121
|
|
|
60
122
|
def get_observation_by_node(
|
|
61
|
-
self, node_addr: Union[int, CodeLocation], kind: ObservationPointType
|
|
123
|
+
self, node_addr: Union[int, "CodeLocation"], kind: ObservationPointType, node_idx: Optional[int] = None
|
|
62
124
|
) -> Optional[LiveDefinitions]:
|
|
63
125
|
if isinstance(node_addr, int):
|
|
64
|
-
|
|
126
|
+
key = ("node", node_addr, kind) if node_idx is None else ("node", (node_addr, node_idx), kind)
|
|
127
|
+
return self.observed_results.get(key, None)
|
|
65
128
|
else:
|
|
66
|
-
|
|
129
|
+
key = (
|
|
130
|
+
("node", node_addr.block_addr, kind)
|
|
131
|
+
if node_idx is None
|
|
132
|
+
else ("node", (node_addr.block_addr, node_idx), kind)
|
|
133
|
+
)
|
|
134
|
+
return self.observed_results.get(key, None)
|
|
67
135
|
|
|
68
136
|
@overload
|
|
69
|
-
def get_observation_by_stmt(self, codeloc: CodeLocation, kind: ObservationPointType) -> Optional[LiveDefinitions]:
|
|
137
|
+
def get_observation_by_stmt(self, codeloc: "CodeLocation", kind: ObservationPointType) -> Optional[LiveDefinitions]:
|
|
70
138
|
...
|
|
71
139
|
|
|
72
140
|
@overload
|
|
@@ -88,3 +156,16 @@ class ReachingDefinitionsModel:
|
|
|
88
156
|
return self.observed_results.get(("stmt", (arg1.block_addr, arg1.stmt_idx), arg2), None)
|
|
89
157
|
else:
|
|
90
158
|
return self.observed_results.get(("stmt", (arg1.block_addr, arg1.stmt_idx, block_idx), arg2), None)
|
|
159
|
+
|
|
160
|
+
def get_observation_by_exit(
|
|
161
|
+
self,
|
|
162
|
+
node_addr: int,
|
|
163
|
+
stmt_idx: int,
|
|
164
|
+
src_node_idx: Optional[int] = None,
|
|
165
|
+
) -> Optional[LiveDefinitions]:
|
|
166
|
+
key = (
|
|
167
|
+
("exit", (node_addr, stmt_idx), ObservationPointType.OP_AFTER)
|
|
168
|
+
if src_node_idx is None
|
|
169
|
+
else ("exit", (node_addr, src_node_idx, stmt_idx), ObservationPointType.OP_AFTER)
|
|
170
|
+
)
|
|
171
|
+
return self.observed_results.get(key, None)
|
|
@@ -235,6 +235,9 @@ class PropagatorState:
|
|
|
235
235
|
|
|
236
236
|
return state, merge_occurred
|
|
237
237
|
|
|
238
|
+
def init_replacements(self):
|
|
239
|
+
self._replacements = defaultdict(dict)
|
|
240
|
+
|
|
238
241
|
def add_replacement(self, codeloc, old: CodeLocation, new):
|
|
239
242
|
"""
|
|
240
243
|
Add a replacement record: Replacing expression `old` with `new` at program location `codeloc`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Set, List, Tuple, Dict, Union, Optional, TYPE_CHECKING
|
|
1
|
+
from typing import Set, List, Tuple, Dict, Union, Optional, Literal, TYPE_CHECKING
|
|
2
2
|
import logging
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
from itertools import count, chain
|
|
@@ -591,14 +591,15 @@ class VariableManagerInternal(Serializable):
|
|
|
591
591
|
|
|
592
592
|
return accesses
|
|
593
593
|
|
|
594
|
-
def get_variables(
|
|
594
|
+
def get_variables(
|
|
595
|
+
self, sort: Optional[Literal["stack", "reg"]] = None, collapse_same_ident=False
|
|
596
|
+
) -> List[Union[SimStackVariable, SimRegisterVariable]]:
|
|
595
597
|
"""
|
|
596
598
|
Get a list of variables.
|
|
597
599
|
|
|
598
|
-
:param
|
|
600
|
+
:param sort: Sort of the variable to get.
|
|
599
601
|
:param collapse_same_ident: Whether variables of the same identifier should be collapsed or not.
|
|
600
602
|
:return: A list of variables.
|
|
601
|
-
:rtype: list
|
|
602
603
|
"""
|
|
603
604
|
|
|
604
605
|
variables = []
|
|
@@ -615,6 +616,27 @@ class VariableManagerInternal(Serializable):
|
|
|
615
616
|
|
|
616
617
|
return variables
|
|
617
618
|
|
|
619
|
+
def get_unified_variables(
|
|
620
|
+
self, sort: Optional[Literal["stack", "reg"]] = None
|
|
621
|
+
) -> List[Union[SimStackVariable, SimRegisterVariable]]:
|
|
622
|
+
"""
|
|
623
|
+
Get a list of unified variables.
|
|
624
|
+
|
|
625
|
+
:param sort: Sort of the variable to get.
|
|
626
|
+
:return: A list of variables.
|
|
627
|
+
"""
|
|
628
|
+
|
|
629
|
+
variables = []
|
|
630
|
+
|
|
631
|
+
for var in self._unified_variables:
|
|
632
|
+
if sort == "stack" and not isinstance(var, SimStackVariable):
|
|
633
|
+
continue
|
|
634
|
+
if sort == "reg" and not isinstance(var, SimRegisterVariable):
|
|
635
|
+
continue
|
|
636
|
+
variables.append(var)
|
|
637
|
+
|
|
638
|
+
return variables
|
|
639
|
+
|
|
618
640
|
def get_global_variables(self, addr):
|
|
619
641
|
"""
|
|
620
642
|
Get global variable by the address of the variable.
|
angr/lib/angr_native.so
CHANGED
|
Binary file
|
angr/project.py
CHANGED
|
@@ -268,8 +268,8 @@ class Project:
|
|
|
268
268
|
"""
|
|
269
269
|
Initializes self.analyses using a given preset.
|
|
270
270
|
"""
|
|
271
|
-
self.
|
|
272
|
-
self.
|
|
271
|
+
self._analyses = cast("AnalysesHubWithDefault", AnalysesHub(self))
|
|
272
|
+
self._analyses.use_plugin_preset(self._analyses_preset if self._analyses_preset is not None else "default")
|
|
273
273
|
|
|
274
274
|
def _register_object(self, obj, sim_proc_arch):
|
|
275
275
|
"""
|
angr/sim_type.py
CHANGED
|
@@ -849,7 +849,7 @@ class SimTypeFunction(SimType):
|
|
|
849
849
|
_fields = ("args", "returnty")
|
|
850
850
|
base = False
|
|
851
851
|
|
|
852
|
-
def __init__(self, args, returnty, label=None, arg_names=None, variadic=False):
|
|
852
|
+
def __init__(self, args: List[SimType], returnty: Optional[SimType], label=None, arg_names=None, variadic=False):
|
|
853
853
|
"""
|
|
854
854
|
:param label: The type label
|
|
855
855
|
:param args: A tuple of types representing the arguments to the function
|
|
@@ -857,7 +857,7 @@ class SimTypeFunction(SimType):
|
|
|
857
857
|
:param variadic: Whether the function accepts varargs
|
|
858
858
|
"""
|
|
859
859
|
super().__init__(label=label)
|
|
860
|
-
self.args = args
|
|
860
|
+
self.args: List[SimType] = args
|
|
861
861
|
self.returnty: Optional[SimType] = returnty
|
|
862
862
|
self.arg_names = arg_names if arg_names else ()
|
|
863
863
|
self.variadic = variadic
|
|
@@ -481,6 +481,7 @@ def _load_native():
|
|
|
481
481
|
ctypes.c_uint64,
|
|
482
482
|
ctypes.c_uint32,
|
|
483
483
|
ctypes.c_uint64,
|
|
484
|
+
ctypes.c_uint64,
|
|
484
485
|
ctypes.c_uint32,
|
|
485
486
|
ctypes.c_uint64,
|
|
486
487
|
)
|
|
@@ -1273,7 +1274,14 @@ class Unicorn(SimStatePlugin):
|
|
|
1273
1274
|
)
|
|
1274
1275
|
|
|
1275
1276
|
_UC_NATIVE.set_cgc_syscall_details(
|
|
1276
|
-
self._uc_state,
|
|
1277
|
+
self._uc_state,
|
|
1278
|
+
2,
|
|
1279
|
+
cgc_transmit_addr,
|
|
1280
|
+
3,
|
|
1281
|
+
cgc_receive_addr,
|
|
1282
|
+
self.state.cgc.max_receive_size,
|
|
1283
|
+
7,
|
|
1284
|
+
cgc_random_addr,
|
|
1277
1285
|
)
|
|
1278
1286
|
|
|
1279
1287
|
# set memory map callback so we can call it explicitly
|
|
@@ -21,11 +21,16 @@ class MultiValueMergerMixin(MemoryMixin):
|
|
|
21
21
|
# try to merge it in the traditional way
|
|
22
22
|
if len(values_set) > self._element_limit:
|
|
23
23
|
# strip annotations from each value and see how many raw values there are in total
|
|
24
|
-
|
|
24
|
+
# We have to use cache_key to determine uniqueness here, because if __hash__ collides,
|
|
25
|
+
# python implicitly calls __eq__ to determine if the two objects are actually the same
|
|
26
|
+
# and that just results in a new AST for a BV. Python then tries to convert that AST to a bool
|
|
27
|
+
# which fails with the safeguard in claripy.ast.bool.Bool.__bool__.
|
|
28
|
+
stripped_values_set = {v._apply_to_annotations(lambda alist: None).cache_key for v in values_set}
|
|
25
29
|
if len(stripped_values_set) > 1:
|
|
26
30
|
ret_val = self._top_func(merged_size * self.state.arch.byte_width)
|
|
27
31
|
else:
|
|
28
|
-
|
|
32
|
+
# Get the AST back from the cache_key
|
|
33
|
+
ret_val = next(iter(stripped_values_set)).ast
|
|
29
34
|
# migrate annotations
|
|
30
35
|
annotations = []
|
|
31
36
|
for v in values_set:
|
angr/utils/timing.py
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
# pylint:disable=no-member
|
|
1
|
+
# pylint:disable=no-member,global-statement
|
|
2
|
+
import os
|
|
2
3
|
import time
|
|
3
4
|
from functools import wraps
|
|
4
5
|
from collections import defaultdict
|
|
5
6
|
|
|
6
|
-
TIMING =
|
|
7
|
-
PRINT =
|
|
7
|
+
TIMING = os.environ.get("TIMING", "").lower() not in {"", "no", "0", "false"}
|
|
8
|
+
PRINT = os.environ.get("PRINT", "").lower() not in {"", "no", "0", "false"}
|
|
8
9
|
TIME_DISTRIBUTION = False
|
|
9
10
|
|
|
10
11
|
total_time = defaultdict(float)
|
|
11
12
|
time_distribution = defaultdict(list)
|
|
13
|
+
depth = 0
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
def timethis(func):
|
|
@@ -19,18 +21,23 @@ def timethis(func):
|
|
|
19
21
|
def _t():
|
|
20
22
|
return time.perf_counter_ns() / 1000000
|
|
21
23
|
|
|
24
|
+
global depth
|
|
25
|
+
depth += 1
|
|
26
|
+
|
|
22
27
|
start = _t()
|
|
23
28
|
r = func(*args, **kwargs)
|
|
24
29
|
millisec = _t() - start
|
|
25
30
|
sec = millisec / 1000
|
|
26
31
|
if PRINT:
|
|
32
|
+
indent = " " * ((depth - 1) * 2)
|
|
27
33
|
if sec > 1.0:
|
|
28
|
-
print(f"[timing] {func.__name__} took {sec:f} seconds ({millisec:f} milliseconds).")
|
|
34
|
+
print(f"[timing] {indent}{func.__name__} took {sec:f} seconds ({millisec:f} milliseconds).")
|
|
29
35
|
else:
|
|
30
|
-
print(f"[timing] {func.__name__} took {millisec:f} milliseconds.")
|
|
36
|
+
print(f"[timing] {indent}{func.__name__} took {millisec:f} milliseconds.")
|
|
31
37
|
total_time[func] += millisec
|
|
32
38
|
if TIME_DISTRIBUTION:
|
|
33
39
|
time_distribution[func].append(millisec)
|
|
40
|
+
depth -= 1
|
|
34
41
|
return r
|
|
35
42
|
else:
|
|
36
43
|
return func(*args, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: angr
|
|
3
|
-
Version: 9.2.
|
|
3
|
+
Version: 9.2.63
|
|
4
4
|
Summary: A multi-architecture binary analysis toolkit, with the ability to perform dynamic symbolic execution and various static analyses on binaries
|
|
5
5
|
Home-page: https://github.com/angr/angr
|
|
6
6
|
License: BSD-2-Clause
|
|
@@ -16,27 +16,27 @@ Description-Content-Type: text/markdown
|
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: CppHeaderParser
|
|
18
18
|
Requires-Dist: GitPython
|
|
19
|
-
Requires-Dist: ailment
|
|
20
|
-
Requires-Dist: archinfo
|
|
19
|
+
Requires-Dist: ailment ==9.2.63
|
|
20
|
+
Requires-Dist: archinfo ==9.2.63
|
|
21
21
|
Requires-Dist: cachetools
|
|
22
|
-
Requires-Dist: capstone
|
|
23
|
-
Requires-Dist: cffi
|
|
24
|
-
Requires-Dist: claripy
|
|
25
|
-
Requires-Dist: cle
|
|
22
|
+
Requires-Dist: capstone !=5.0.0rc2,>=3.0.5rc2
|
|
23
|
+
Requires-Dist: cffi >=1.14.0
|
|
24
|
+
Requires-Dist: claripy ==9.2.63
|
|
25
|
+
Requires-Dist: cle ==9.2.63
|
|
26
26
|
Requires-Dist: dpkt
|
|
27
27
|
Requires-Dist: itanium-demangler
|
|
28
28
|
Requires-Dist: mulpyplexer
|
|
29
29
|
Requires-Dist: nampa
|
|
30
|
-
Requires-Dist: networkx
|
|
31
|
-
Requires-Dist: protobuf
|
|
30
|
+
Requires-Dist: networkx !=2.8.1,>=2.0
|
|
31
|
+
Requires-Dist: protobuf >=3.19.0
|
|
32
32
|
Requires-Dist: psutil
|
|
33
|
-
Requires-Dist: pycparser
|
|
34
|
-
Requires-Dist: pyvex
|
|
35
|
-
Requires-Dist: rich
|
|
33
|
+
Requires-Dist: pycparser >=2.18
|
|
34
|
+
Requires-Dist: pyvex ==9.2.63
|
|
35
|
+
Requires-Dist: rich >=13.1.0
|
|
36
36
|
Requires-Dist: rpyc
|
|
37
37
|
Requires-Dist: sortedcontainers
|
|
38
38
|
Requires-Dist: sympy
|
|
39
|
-
Requires-Dist: unicorn
|
|
39
|
+
Requires-Dist: unicorn ==2.0.1.post1
|
|
40
40
|
Requires-Dist: colorama ; platform_system == "Windows"
|
|
41
41
|
Provides-Extra: angrdb
|
|
42
42
|
Requires-Dist: sqlalchemy ; extra == 'angrdb'
|
|
@@ -46,10 +46,10 @@ Requires-Dist: myst-parser ; extra == 'docs'
|
|
|
46
46
|
Requires-Dist: sphinx ; extra == 'docs'
|
|
47
47
|
Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
|
|
48
48
|
Provides-Extra: pcode
|
|
49
|
-
Requires-Dist: pypcode
|
|
49
|
+
Requires-Dist: pypcode >=1.1 ; extra == 'pcode'
|
|
50
50
|
Provides-Extra: testing
|
|
51
51
|
Requires-Dist: keystone-engine ; extra == 'testing'
|
|
52
|
-
Requires-Dist: pypcode
|
|
52
|
+
Requires-Dist: pypcode >=1.1 ; extra == 'testing'
|
|
53
53
|
Requires-Dist: pytest ; extra == 'testing'
|
|
54
54
|
Requires-Dist: pytest-split ; extra == 'testing'
|
|
55
55
|
Requires-Dist: pytest-xdist ; extra == 'testing'
|