angr 9.2.114__py3-none-manylinux2014_aarch64.whl → 9.2.116__py3-none-manylinux2014_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/__main__.py +2 -2
- angr/analyses/cfg/cfg_fast.py +1 -1
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2 -2
- angr/analyses/decompiler/decompilation_options.py +2 -12
- angr/analyses/decompiler/decompiler.py +14 -3
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +3 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +0 -3
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +2 -3
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +9 -2
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +2 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +2 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +5 -1
- angr/analyses/decompiler/structured_codegen/c.py +10 -13
- angr/analyses/decompiler/structuring/__init__.py +6 -2
- angr/analyses/decompiler/structuring/dream.py +3 -4
- angr/analyses/decompiler/structuring/phoenix.py +29 -93
- angr/analyses/decompiler/structuring/recursive_structurer.py +0 -3
- angr/analyses/decompiler/structuring/sailr.py +111 -0
- angr/analyses/decompiler/structuring/structurer_base.py +2 -5
- angr/analyses/decompiler/structuring/structurer_nodes.py +3 -3
- angr/analyses/reaching_definitions/dep_graph.py +62 -5
- angr/analyses/reaching_definitions/function_handler.py +11 -1
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +11 -0
- angr/analyses/reaching_definitions/function_handler_library/stdio.py +262 -0
- angr/analyses/reaching_definitions/function_handler_library/stdlib.py +157 -0
- angr/analyses/reaching_definitions/function_handler_library/string.py +93 -0
- angr/analyses/reaching_definitions/function_handler_library/unistd.py +23 -0
- angr/analyses/reaching_definitions/rd_state.py +28 -29
- angr/analyses/variable_recovery/engine_vex.py +0 -9
- angr/analyses/vfg.py +13 -14
- angr/code_location.py +4 -4
- angr/engines/pcode/cc.py +2 -0
- angr/engines/vex/heavy/heavy.py +1 -1
- angr/knowledge_plugins/key_definitions/live_definitions.py +12 -13
- angr/procedures/libc/strlen.py +5 -2
- angr/sim_variable.py +3 -18
- angr/state_plugins/solver.py +3 -9
- angr/storage/memory_mixins/address_concretization_mixin.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +2 -1
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +4 -2
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +5 -5
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +3 -3
- {angr-9.2.114.dist-info → angr-9.2.116.dist-info}/METADATA +7 -7
- {angr-9.2.114.dist-info → angr-9.2.116.dist-info}/RECORD +49 -43
- {angr-9.2.114.dist-info → angr-9.2.116.dist-info}/WHEEL +1 -1
- {angr-9.2.114.dist-info → angr-9.2.116.dist-info}/LICENSE +0 -0
- {angr-9.2.114.dist-info → angr-9.2.116.dist-info}/entry_points.txt +0 -0
- {angr-9.2.114.dist-info → angr-9.2.116.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
import claripy
|
|
6
|
+
|
|
7
|
+
from angr.analyses.reaching_definitions.function_handler import FunctionCallDataUnwrapped, FunctionHandler
|
|
8
|
+
from angr.knowledge_plugins.key_definitions.atoms import Atom
|
|
9
|
+
from angr.knowledge_plugins.key_definitions.live_definitions import DerefSize
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from angr.analyses.reaching_definitions.rd_state import ReachingDefinitionsState
|
|
14
|
+
|
|
15
|
+
# pylint: disable=no-self-use,missing-class-docstring,unused-argument
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class EnvironAtom(Atom):
|
|
19
|
+
def __init__(self, size: int, name: str | None):
|
|
20
|
+
self.name = name
|
|
21
|
+
super().__init__(size)
|
|
22
|
+
|
|
23
|
+
def _identity(self):
|
|
24
|
+
if self.name is not None:
|
|
25
|
+
return (self.name,)
|
|
26
|
+
else:
|
|
27
|
+
return ()
|
|
28
|
+
|
|
29
|
+
def __repr__(self):
|
|
30
|
+
return f'<EnvironAtom {self.name if self.name is not None else "(dynamic)"}>'
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SystemAtom(Atom):
|
|
34
|
+
def __init__(self, size: int = 1):
|
|
35
|
+
self.nonce = random.randint(0, 999999999999)
|
|
36
|
+
super().__init__(size)
|
|
37
|
+
|
|
38
|
+
def _identity(self):
|
|
39
|
+
return (self.nonce,)
|
|
40
|
+
|
|
41
|
+
def __repr__(self):
|
|
42
|
+
return "<SystemAtom>"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ExecveAtom(Atom):
|
|
46
|
+
def __init__(self, nonce: int, idx: int, size: int):
|
|
47
|
+
self.nonce = nonce
|
|
48
|
+
self.idx = idx
|
|
49
|
+
super().__init__(size)
|
|
50
|
+
|
|
51
|
+
def _identity(self):
|
|
52
|
+
return (self.nonce, self.idx)
|
|
53
|
+
|
|
54
|
+
def __repr__(self):
|
|
55
|
+
return f"<ExecveAtom {self.idx}>"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class LibcStdlibHandlers(FunctionHandler):
|
|
59
|
+
@FunctionCallDataUnwrapped.decorate
|
|
60
|
+
def handle_impl_atoi(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
61
|
+
buf_atoms = state.deref(data.args_atoms[0], DerefSize.NULL_TERMINATE)
|
|
62
|
+
buf_value = state.get_concrete_value(buf_atoms, cast_to=bytes)
|
|
63
|
+
if buf_value is not None:
|
|
64
|
+
try:
|
|
65
|
+
buf_value = int(buf_value.decode().strip("\0"))
|
|
66
|
+
except ValueError:
|
|
67
|
+
buf_value = 0
|
|
68
|
+
data.depends(data.ret_atoms, buf_atoms, value=buf_value)
|
|
69
|
+
|
|
70
|
+
@FunctionCallDataUnwrapped.decorate
|
|
71
|
+
def handle_impl_malloc(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
72
|
+
malloc_size = state.get_concrete_value(data.args_atoms[0]) or 48
|
|
73
|
+
heap_ptr = state.heap_allocator.allocate(malloc_size)
|
|
74
|
+
data.depends(data.ret_atoms, value=state.heap_address(heap_ptr))
|
|
75
|
+
|
|
76
|
+
@FunctionCallDataUnwrapped.decorate
|
|
77
|
+
def handle_impl_calloc(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
78
|
+
nmemb = state.get_concrete_value(data.args_atoms[0]) or 48
|
|
79
|
+
size = state.get_concrete_value(data.args_atoms[0]) or 1
|
|
80
|
+
heap_ptr = state.heap_address(state.heap_allocator.allocate(nmemb * size))
|
|
81
|
+
data.depends(state.deref(heap_ptr, nmemb * size), value=0)
|
|
82
|
+
data.depends(data.ret_atoms, value=heap_ptr)
|
|
83
|
+
|
|
84
|
+
@FunctionCallDataUnwrapped.decorate
|
|
85
|
+
def handle_impl_getenv(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
86
|
+
name_atom = state.deref(data.args_atoms[0], DerefSize.NULL_TERMINATE)
|
|
87
|
+
name_value = state.get_concrete_value(name_atom, cast_to=bytes)
|
|
88
|
+
if name_value is not None:
|
|
89
|
+
name_value = name_value.strip(b"\0").decode()
|
|
90
|
+
data.depends(None, name_atom)
|
|
91
|
+
|
|
92
|
+
# store a buffer, registering it as an output of this function
|
|
93
|
+
# we store this two-byte mixed value because we don't want the value to be picked up by get_concrete_value()
|
|
94
|
+
# but also it should be able to be picked up by NULL_TERMINATE reads
|
|
95
|
+
heap_ptr = state.heap_allocator.allocate(2)
|
|
96
|
+
heap_atom = state.deref(heap_ptr, 2)
|
|
97
|
+
heap_value = claripy.BVS("weh", 8).concat(claripy.BVV(0, 8))
|
|
98
|
+
data.depends(heap_atom, EnvironAtom(2, name_value), value=heap_value)
|
|
99
|
+
data.depends(data.ret_atoms, value=state.heap_address(heap_ptr))
|
|
100
|
+
|
|
101
|
+
@FunctionCallDataUnwrapped.decorate
|
|
102
|
+
def handle_impl_setenv(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
103
|
+
name_atom = state.deref(data.args_atoms[0], DerefSize.NULL_TERMINATE)
|
|
104
|
+
name_value = state.get_concrete_value(name_atom, cast_to=bytes)
|
|
105
|
+
if name_value is not None:
|
|
106
|
+
name_value = name_value.strip(b"\0").decode()
|
|
107
|
+
data.depends(None, name_atom)
|
|
108
|
+
|
|
109
|
+
src_atom = state.deref(data.args_atoms[1], DerefSize.NULL_TERMINATE)
|
|
110
|
+
src_value = state.get_values(src_atom)
|
|
111
|
+
data.depends(
|
|
112
|
+
EnvironAtom(len(src_value) // 8 if src_value is not None else 1, name_value), src_atom, value=src_value
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
@FunctionCallDataUnwrapped.decorate
|
|
116
|
+
def handle_impl_system(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
117
|
+
buf_atom = state.deref(data.args_atoms[0], DerefSize.NULL_TERMINATE)
|
|
118
|
+
buf_value = state.get_values(buf_atom)
|
|
119
|
+
data.depends(SystemAtom(len(buf_value) // 8 if buf_value is not None else 1), buf_atom, value=buf_value)
|
|
120
|
+
|
|
121
|
+
handle_impl_popen = handle_impl_execl = handle_impl_system
|
|
122
|
+
|
|
123
|
+
@FunctionCallDataUnwrapped.decorate
|
|
124
|
+
def handle_impl_execve(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
125
|
+
argv_value = state.get_one_value(data.args_atoms[1])
|
|
126
|
+
if argv_value is None:
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
nonce = random.randint(1, 999999999)
|
|
130
|
+
|
|
131
|
+
# Iterate through each pointer in the array to collect argument strings
|
|
132
|
+
idx = 0
|
|
133
|
+
while True:
|
|
134
|
+
# Read the concrete string pointer value
|
|
135
|
+
argv_deref_atom = state.deref(argv_value, state.arch.bytes, state.arch.memory_endness)
|
|
136
|
+
if argv_deref_atom is None:
|
|
137
|
+
# unknown if array continues
|
|
138
|
+
break
|
|
139
|
+
|
|
140
|
+
argv_deref_concrete = state.get_one_value(argv_deref_atom)
|
|
141
|
+
if argv_deref_concrete is None:
|
|
142
|
+
# unknown if array continues
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
if (argv_deref_concrete == 0).is_true():
|
|
146
|
+
# End of array
|
|
147
|
+
break
|
|
148
|
+
|
|
149
|
+
string_atom = state.deref(argv_deref_concrete, DerefSize.NULL_TERMINATE)
|
|
150
|
+
string_val = None if string_atom is None else state.get_values(string_atom)
|
|
151
|
+
|
|
152
|
+
atom = ExecveAtom(nonce, idx, len(string_val) // 8 if string_val is not None else 1)
|
|
153
|
+
data.depends(atom, [] if string_atom is None else [string_atom], value=string_val)
|
|
154
|
+
|
|
155
|
+
# Increment by size of pointer for this arch
|
|
156
|
+
argv_value += state.arch.bytes
|
|
157
|
+
idx += 1
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import archinfo
|
|
2
|
+
from angr.analyses.reaching_definitions.function_handler import FunctionCallDataUnwrapped, FunctionHandler
|
|
3
|
+
from angr.analyses.reaching_definitions.rd_state import ReachingDefinitionsState
|
|
4
|
+
from angr.knowledge_plugins.key_definitions.live_definitions import DerefSize
|
|
5
|
+
|
|
6
|
+
# pylint: disable=no-self-use,missing-class-docstring,unused-argument
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class LibcStringHandlers(FunctionHandler):
|
|
10
|
+
@FunctionCallDataUnwrapped.decorate
|
|
11
|
+
def handle_impl_strcat(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
12
|
+
src0_atom = state.deref(data.args_atoms[0], DerefSize.NULL_TERMINATE)
|
|
13
|
+
src1_atom = state.deref(data.args_atoms[1], DerefSize.NULL_TERMINATE)
|
|
14
|
+
src0_value = state.get_values(src0_atom)
|
|
15
|
+
src1_value = state.get_values(src1_atom)
|
|
16
|
+
if src0_value is not None and src1_value is not None:
|
|
17
|
+
src0_value = src0_value.extract(0, len(src0_value) // 8 - 1, archinfo.Endness.BE)
|
|
18
|
+
dest_value = src0_value.concat(src1_value)
|
|
19
|
+
dest_atom = state.deref(data.args_atoms[0], len(dest_value) // 8, endness=archinfo.Endness.BE)
|
|
20
|
+
else:
|
|
21
|
+
dest_value = None
|
|
22
|
+
dest_atom = src0_atom
|
|
23
|
+
data.depends(dest_atom, src0_atom, src1_atom, value=dest_value)
|
|
24
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=src0_value)
|
|
25
|
+
|
|
26
|
+
handle_impl_strncat = handle_impl_strcat
|
|
27
|
+
|
|
28
|
+
@FunctionCallDataUnwrapped.decorate
|
|
29
|
+
def handle_impl_strlen(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
30
|
+
src_atom = state.deref(data.args_atoms[0], DerefSize.NULL_TERMINATE)
|
|
31
|
+
src_str = state.get_values(src_atom)
|
|
32
|
+
if src_str is not None:
|
|
33
|
+
data.depends(data.ret_atoms, src_atom, value=len(src_str) // 8 - 1)
|
|
34
|
+
else:
|
|
35
|
+
data.depends(data.ret_atoms, src_atom)
|
|
36
|
+
|
|
37
|
+
@FunctionCallDataUnwrapped.decorate
|
|
38
|
+
def handle_impl_strcpy(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
39
|
+
src_atom = state.deref(data.args_atoms[1], DerefSize.NULL_TERMINATE)
|
|
40
|
+
src_str = state.get_values(src_atom)
|
|
41
|
+
if src_str is not None:
|
|
42
|
+
dst_atom = state.deref(data.args_atoms[0], len(src_str) // 8)
|
|
43
|
+
data.depends(dst_atom, src_atom, value=src_str)
|
|
44
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=state.get_values(data.args_atoms[0]))
|
|
45
|
+
|
|
46
|
+
@FunctionCallDataUnwrapped.decorate
|
|
47
|
+
def handle_impl_strncpy(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
48
|
+
n = state.get_concrete_value(data.args_atoms[1])
|
|
49
|
+
src_atom = state.deref(data.args_atoms[2], DerefSize.NULL_TERMINATE if n is None else n)
|
|
50
|
+
src_str = state.get_values(src_atom)
|
|
51
|
+
if src_str is not None:
|
|
52
|
+
dst_atom = state.deref(data.args_atoms[0], len(src_str) // 8)
|
|
53
|
+
data.depends(dst_atom, src_atom, value=src_str)
|
|
54
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=state.get_values(data.args_atoms[0]))
|
|
55
|
+
|
|
56
|
+
@FunctionCallDataUnwrapped.decorate
|
|
57
|
+
def handle_impl_strdup(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
58
|
+
src_atom = state.deref(data.args_atoms[1], DerefSize.NULL_TERMINATE)
|
|
59
|
+
src_str = state.get_values(src_atom)
|
|
60
|
+
if src_str is not None:
|
|
61
|
+
malloc_size = len(src_str) // 8
|
|
62
|
+
else:
|
|
63
|
+
malloc_size = 1
|
|
64
|
+
heap_ptr = state.heap_allocator.allocate(malloc_size)
|
|
65
|
+
dst_atom = state.deref(heap_ptr, malloc_size)
|
|
66
|
+
data.depends(dst_atom, src_atom, value=src_str)
|
|
67
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=state.get_values(data.args_atoms[0]))
|
|
68
|
+
|
|
69
|
+
@FunctionCallDataUnwrapped.decorate
|
|
70
|
+
def handle_impl_memcpy(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
71
|
+
size = state.get_concrete_value(data.args_atoms[2])
|
|
72
|
+
if size is not None:
|
|
73
|
+
src_atom = state.deref(data.args_atoms[1], size)
|
|
74
|
+
dst_atom = state.deref(data.args_atoms[0], size)
|
|
75
|
+
data.depends(dst_atom, src_atom, value=state.get_values(src_atom))
|
|
76
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=state.get_values(data.args_atoms[0]))
|
|
77
|
+
|
|
78
|
+
@FunctionCallDataUnwrapped.decorate
|
|
79
|
+
def handle_impl_memset(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
80
|
+
size = state.get_concrete_value(data.args_atoms[2])
|
|
81
|
+
if size is not None:
|
|
82
|
+
dst_atom = state.deref(data.args_atoms[0], size)
|
|
83
|
+
data.depends(dst_atom, data.args_atoms[1])
|
|
84
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=state.get_values(data.args_atoms[0]))
|
|
85
|
+
|
|
86
|
+
@FunctionCallDataUnwrapped.decorate
|
|
87
|
+
def handle_impl_strtok(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
88
|
+
# stub: just return the haystack pointer
|
|
89
|
+
data.depends(data.ret_atoms, data.args_atoms[0], value=state.get_values(data.args_atoms[0]))
|
|
90
|
+
|
|
91
|
+
handle_impl_strtok_r = handle_impl_strstr = handle_impl_strcasestr = handle_impl_strchr = handle_imple_strrchr = (
|
|
92
|
+
handle_impl_strchrnul
|
|
93
|
+
) = handle_impl_strtok
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from angr.analyses.reaching_definitions.function_handler import FunctionCallDataUnwrapped, FunctionHandler
|
|
2
|
+
from angr.analyses.reaching_definitions.function_handler_library.stdio import StdinAtom, StdoutAtom
|
|
3
|
+
from angr.analyses.reaching_definitions.rd_state import ReachingDefinitionsState
|
|
4
|
+
|
|
5
|
+
# pylint: disable=no-self-use,missing-class-docstring,unused-argument
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LibcUnistdHandlers(FunctionHandler):
|
|
9
|
+
@FunctionCallDataUnwrapped.decorate
|
|
10
|
+
def handle_impl_read(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
11
|
+
size = state.get_concrete_value(data.args_atoms[2]) or 1
|
|
12
|
+
dst_atom = state.deref(data.args_atoms[1], size)
|
|
13
|
+
data.depends(dst_atom, StdinAtom(data.function.name, size))
|
|
14
|
+
|
|
15
|
+
handle_impl_recv = handle_impl_recvfrom = handle_impl_read
|
|
16
|
+
|
|
17
|
+
@FunctionCallDataUnwrapped.decorate
|
|
18
|
+
def handle_impl_write(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
|
|
19
|
+
size = state.get_concrete_value(data.args_atoms[2]) or 1
|
|
20
|
+
src_atom = state.deref(data.args_atoms[1], size)
|
|
21
|
+
data.depends(StdoutAtom(data.function.name, size), src_atom, value=state.get_values(src_atom))
|
|
22
|
+
|
|
23
|
+
handle_impl_send = handle_impl_write
|
|
@@ -9,6 +9,7 @@ from angr.misc.ux import deprecated
|
|
|
9
9
|
from angr.knowledge_plugins.key_definitions.environment import Environment
|
|
10
10
|
from angr.knowledge_plugins.key_definitions.tag import Tag
|
|
11
11
|
from angr.knowledge_plugins.key_definitions.heap_address import HeapAddress
|
|
12
|
+
from angr.knowledge_plugins.key_definitions.definition import A
|
|
12
13
|
from angr.engines.light import SpOffset
|
|
13
14
|
from angr.code_location import CodeLocation
|
|
14
15
|
from ...storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
|
|
@@ -90,7 +91,7 @@ class ReachingDefinitionsState:
|
|
|
90
91
|
heap_allocator: HeapAllocator = None,
|
|
91
92
|
environment: Environment = None,
|
|
92
93
|
sp_adjusted: bool = False,
|
|
93
|
-
all_definitions: set[Definition] | None = None,
|
|
94
|
+
all_definitions: set[Definition[A]] | None = None,
|
|
94
95
|
initializer: Optional["RDAStateInitializer"] = None,
|
|
95
96
|
element_limit: int = 5,
|
|
96
97
|
merge_into_tops: bool = True,
|
|
@@ -106,12 +107,12 @@ class ReachingDefinitionsState:
|
|
|
106
107
|
self._sp_adjusted: bool = sp_adjusted
|
|
107
108
|
self._element_limit: int = element_limit
|
|
108
109
|
|
|
109
|
-
self.all_definitions: set[Definition] = set() if all_definitions is None else all_definitions
|
|
110
|
+
self.all_definitions: set[Definition[A]] = set() if all_definitions is None else all_definitions
|
|
110
111
|
|
|
111
112
|
self.heap_allocator = heap_allocator or HeapAllocator(canonical_size)
|
|
112
113
|
self._environment: Environment = environment or Environment()
|
|
113
114
|
|
|
114
|
-
self.codeloc_uses: set[Definition] = set()
|
|
115
|
+
self.codeloc_uses: set[Definition[A]] = set()
|
|
115
116
|
|
|
116
117
|
# have we observed an exit statement or not during the analysis of the *last instruction* of a block? we should
|
|
117
118
|
# not perform any sp updates if it is the case. this is for handling conditional returns in ARM binaries.
|
|
@@ -189,7 +190,7 @@ class ReachingDefinitionsState:
|
|
|
189
190
|
return n - 2**self.arch.bits
|
|
190
191
|
return n
|
|
191
192
|
|
|
192
|
-
def annotate_with_def(self, symvar: claripy.ast.Base, definition: Definition) -> claripy.ast.Base:
|
|
193
|
+
def annotate_with_def(self, symvar: claripy.ast.Base, definition: Definition[A]) -> claripy.ast.Base:
|
|
193
194
|
"""
|
|
194
195
|
|
|
195
196
|
:param symvar:
|
|
@@ -198,14 +199,14 @@ class ReachingDefinitionsState:
|
|
|
198
199
|
"""
|
|
199
200
|
return self.live_definitions.annotate_with_def(symvar, definition)
|
|
200
201
|
|
|
201
|
-
def annotate_mv_with_def(self, mv: MultiValues, definition: Definition) -> MultiValues:
|
|
202
|
+
def annotate_mv_with_def(self, mv: MultiValues, definition: Definition[A]) -> MultiValues:
|
|
202
203
|
return MultiValues(
|
|
203
204
|
offset_to_values={
|
|
204
205
|
offset: {self.annotate_with_def(value, definition) for value in values} for offset, values in mv.items()
|
|
205
206
|
}
|
|
206
207
|
)
|
|
207
208
|
|
|
208
|
-
def extract_defs(self, symvar: claripy.ast.Base) -> Iterator[Definition]:
|
|
209
|
+
def extract_defs(self, symvar: claripy.ast.Base) -> Iterator[Definition[A]]:
|
|
209
210
|
yield from self.live_definitions.extract_defs(symvar)
|
|
210
211
|
|
|
211
212
|
#
|
|
@@ -364,9 +365,9 @@ class ReachingDefinitionsState:
|
|
|
364
365
|
tags: set[Tag] = None,
|
|
365
366
|
endness=None, # XXX destroy
|
|
366
367
|
annotated: bool = False,
|
|
367
|
-
uses: set[Definition] | None = None,
|
|
368
|
+
uses: set[Definition[A]] | None = None,
|
|
368
369
|
override_codeloc: CodeLocation | None = None,
|
|
369
|
-
) -> tuple[MultiValues | None, set[Definition]]:
|
|
370
|
+
) -> tuple[MultiValues | None, set[Definition[A]]]:
|
|
370
371
|
codeloc = override_codeloc or self.codeloc
|
|
371
372
|
existing_defs = self.live_definitions.get_definitions(atom)
|
|
372
373
|
mv = self.live_definitions.kill_and_add_definition(
|
|
@@ -446,7 +447,7 @@ class ReachingDefinitionsState:
|
|
|
446
447
|
self.codeloc_uses.update(self.get_definitions(atom))
|
|
447
448
|
self.live_definitions.add_use(atom, self.codeloc, expr=expr)
|
|
448
449
|
|
|
449
|
-
def add_use_by_def(self, definition: Definition, expr: Any | None = None) -> None:
|
|
450
|
+
def add_use_by_def(self, definition: Definition[A], expr: Any | None = None) -> None:
|
|
450
451
|
self.codeloc_uses.add(definition)
|
|
451
452
|
self.live_definitions.add_use_by_def(definition, self.codeloc, expr=expr)
|
|
452
453
|
|
|
@@ -455,7 +456,7 @@ class ReachingDefinitionsState:
|
|
|
455
456
|
self.add_tmp_use_by_defs(defs, expr=expr)
|
|
456
457
|
|
|
457
458
|
def add_tmp_use_by_defs(
|
|
458
|
-
self, defs: Iterable[Definition], expr: Any | None = None
|
|
459
|
+
self, defs: Iterable[Definition[A]], expr: Any | None = None
|
|
459
460
|
) -> None: # pylint:disable=unused-argument
|
|
460
461
|
for definition in defs:
|
|
461
462
|
self.codeloc_uses.add(definition)
|
|
@@ -466,7 +467,7 @@ class ReachingDefinitionsState:
|
|
|
466
467
|
defs = self.live_definitions.get_register_definitions(reg_offset, size)
|
|
467
468
|
self.add_register_use_by_defs(defs, expr=expr)
|
|
468
469
|
|
|
469
|
-
def add_register_use_by_defs(self, defs: Iterable[Definition], expr: Any | None = None) -> None:
|
|
470
|
+
def add_register_use_by_defs(self, defs: Iterable[Definition[A]], expr: Any | None = None) -> None:
|
|
470
471
|
for definition in defs:
|
|
471
472
|
self.codeloc_uses.add(definition)
|
|
472
473
|
self.live_definitions.add_register_use_by_def(definition, self.codeloc, expr=expr)
|
|
@@ -475,7 +476,7 @@ class ReachingDefinitionsState:
|
|
|
475
476
|
defs = self.live_definitions.get_stack_definitions(stack_offset, size)
|
|
476
477
|
self.add_stack_use_by_defs(defs, expr=expr)
|
|
477
478
|
|
|
478
|
-
def add_stack_use_by_defs(self, defs: Iterable[Definition], expr: Any | None = None):
|
|
479
|
+
def add_stack_use_by_defs(self, defs: Iterable[Definition[A]], expr: Any | None = None):
|
|
479
480
|
for definition in defs:
|
|
480
481
|
self.codeloc_uses.add(definition)
|
|
481
482
|
self.live_definitions.add_stack_use_by_def(definition, self.codeloc, expr=expr)
|
|
@@ -484,41 +485,39 @@ class ReachingDefinitionsState:
|
|
|
484
485
|
defs = self.live_definitions.get_heap_definitions(heap_offset, size)
|
|
485
486
|
self.add_heap_use_by_defs(defs, expr=expr)
|
|
486
487
|
|
|
487
|
-
def add_heap_use_by_defs(self, defs: Iterable[Definition], expr: Any | None = None):
|
|
488
|
+
def add_heap_use_by_defs(self, defs: Iterable[Definition[A]], expr: Any | None = None):
|
|
488
489
|
for definition in defs:
|
|
489
490
|
self.codeloc_uses.add(definition)
|
|
490
491
|
self.live_definitions.add_heap_use_by_def(definition, self.codeloc, expr=expr)
|
|
491
492
|
|
|
492
|
-
def add_memory_use_by_def(self, definition: Definition, expr: Any | None = None):
|
|
493
|
+
def add_memory_use_by_def(self, definition: Definition[A], expr: Any | None = None):
|
|
493
494
|
self.codeloc_uses.add(definition)
|
|
494
495
|
self.live_definitions.add_memory_use_by_def(definition, self.codeloc, expr=expr)
|
|
495
496
|
|
|
496
|
-
def add_memory_use_by_defs(self, defs: Iterable[Definition], expr: Any | None = None):
|
|
497
|
+
def add_memory_use_by_defs(self, defs: Iterable[Definition[A]], expr: Any | None = None):
|
|
497
498
|
for definition in defs:
|
|
498
499
|
self.codeloc_uses.add(definition)
|
|
499
500
|
self.live_definitions.add_memory_use_by_def(definition, self.codeloc, expr=expr)
|
|
500
501
|
|
|
501
|
-
def get_definitions(self, atom:
|
|
502
|
+
def get_definitions(self, atom: A | Definition[A] | Iterable[A] | Iterable[Definition[A]]) -> set[Definition[A]]:
|
|
502
503
|
return self.live_definitions.get_definitions(atom)
|
|
503
504
|
|
|
504
|
-
def get_values(self, spec:
|
|
505
|
+
def get_values(self, spec: A | Definition[A] | Iterable[A]) -> MultiValues | None:
|
|
505
506
|
return self.live_definitions.get_values(spec)
|
|
506
507
|
|
|
507
|
-
def get_one_value(
|
|
508
|
+
def get_one_value(
|
|
509
|
+
self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], strip_annotations: bool = False
|
|
510
|
+
) -> claripy.ast.bv.BV | None:
|
|
508
511
|
return self.live_definitions.get_one_value(spec, strip_annotations=strip_annotations)
|
|
509
512
|
|
|
510
513
|
@overload
|
|
511
|
-
def get_concrete_value(
|
|
512
|
-
self, spec: Atom | Definition[Atom] | Iterable[Atom], cast_to: type[int] = ...
|
|
513
|
-
) -> int | None: ...
|
|
514
|
+
def get_concrete_value(self, spec: A | Definition[A] | Iterable[A], cast_to: type[int] = ...) -> int | None: ...
|
|
514
515
|
|
|
515
516
|
@overload
|
|
516
|
-
def get_concrete_value(
|
|
517
|
-
self, spec: Atom | Definition[Atom] | Iterable[Atom], cast_to: type[bytes] = ...
|
|
518
|
-
) -> bytes | None: ...
|
|
517
|
+
def get_concrete_value(self, spec: A | Definition[A] | Iterable[A], cast_to: type[bytes] = ...) -> bytes | None: ...
|
|
519
518
|
|
|
520
519
|
def get_concrete_value(
|
|
521
|
-
self, spec:
|
|
520
|
+
self, spec: A | Definition[A] | Iterable[A], cast_to: type[int] | type[bytes] = int
|
|
522
521
|
) -> int | bytes | None:
|
|
523
522
|
return self.live_definitions.get_concrete_value(spec, cast_to)
|
|
524
523
|
|
|
@@ -591,7 +590,7 @@ class ReachingDefinitionsState:
|
|
|
591
590
|
@overload
|
|
592
591
|
def deref(
|
|
593
592
|
self,
|
|
594
|
-
pointer: MultiValues |
|
|
593
|
+
pointer: MultiValues | A | Definition | Iterable[A] | Iterable[Definition[A]],
|
|
595
594
|
size: int | DerefSize,
|
|
596
595
|
endness: str = ...,
|
|
597
596
|
) -> set[MemoryLocation]: ...
|
|
@@ -600,10 +599,10 @@ class ReachingDefinitionsState:
|
|
|
600
599
|
self,
|
|
601
600
|
pointer: (
|
|
602
601
|
MultiValues
|
|
603
|
-
|
|
|
602
|
+
| A
|
|
604
603
|
| Definition
|
|
605
|
-
| Iterable[
|
|
606
|
-
| Iterable[Definition]
|
|
604
|
+
| Iterable[A]
|
|
605
|
+
| Iterable[Definition[A]]
|
|
607
606
|
| int
|
|
608
607
|
| claripy.ast.BV
|
|
609
608
|
| HeapAddress
|
|
@@ -563,15 +563,6 @@ class SimEngineVRVEX(
|
|
|
563
563
|
return RichR(self.state.top(expr_0.data.size()))
|
|
564
564
|
return RichR(self.state.top(expr_0.data.size()))
|
|
565
565
|
|
|
566
|
-
def _handle_Ctz(self, expr):
|
|
567
|
-
arg0 = expr.args[0]
|
|
568
|
-
expr_0 = self._expr(arg0)
|
|
569
|
-
if expr_0 is None:
|
|
570
|
-
return None
|
|
571
|
-
if self.state.is_top(expr_0.data):
|
|
572
|
-
return RichR(self.state.top(expr_0.data.size()))
|
|
573
|
-
return RichR(self.state.top(expr_0.data.size()))
|
|
574
|
-
|
|
575
566
|
_handle_CmpEQ_v = _handle_Cmp_v
|
|
576
567
|
_handle_CmpNE_v = _handle_Cmp_v
|
|
577
568
|
_handle_CmpLE_v = _handle_Cmp_v
|
angr/analyses/vfg.py
CHANGED
|
@@ -1572,11 +1572,11 @@ class VFG(ForwardAnalysis[SimState, VFGNode, VFGJob, BlockID], Analysis): # pyl
|
|
|
1572
1572
|
# FIXME: Now we are assuming the sp is restored to its original value
|
|
1573
1573
|
reg_sp_expr = successor_state.regs.sp
|
|
1574
1574
|
|
|
1575
|
-
if isinstance(reg_sp_expr
|
|
1576
|
-
reg_sp_si = reg_sp_expr
|
|
1575
|
+
if isinstance(claripy.backends.vsa.convert(reg_sp_expr), claripy.vsa.StridedInterval):
|
|
1576
|
+
reg_sp_si = claripy.backends.vsa.convert(reg_sp_expr)
|
|
1577
1577
|
# reg_sp_si.min # reg_sp_val
|
|
1578
|
-
elif isinstance(reg_sp_expr
|
|
1579
|
-
reg_sp_si = next(iter(reg_sp_expr.
|
|
1578
|
+
elif isinstance(claripy.backends.vsa.convert(reg_sp_expr), claripy.vsa.ValueSet):
|
|
1579
|
+
reg_sp_si = next(iter(claripy.backends.vsa.convert(reg_sp_expr).items()))[1]
|
|
1580
1580
|
# reg_sp_si.min # reg_sp_val
|
|
1581
1581
|
# TODO: Finish it!
|
|
1582
1582
|
|
|
@@ -1717,21 +1717,20 @@ class VFG(ForwardAnalysis[SimState, VFGNode, VFGJob, BlockID], Analysis): # pyl
|
|
|
1717
1717
|
reg_sp_offset = arch.sp_offset
|
|
1718
1718
|
reg_sp_expr = successor_state.registers.load(reg_sp_offset, size=arch.bytes, endness=arch.register_endness)
|
|
1719
1719
|
|
|
1720
|
-
|
|
1720
|
+
reg_sp_expr_vsa = claripy.backends.vsa.convert(reg_sp_expr)
|
|
1721
|
+
if isinstance(reg_sp_expr_vsa, claripy.bv.BVV):
|
|
1721
1722
|
reg_sp_val = successor_state.solver.eval(reg_sp_expr)
|
|
1722
1723
|
reg_sp_si = successor_state.solver.SI(to_conv=reg_sp_expr)
|
|
1723
|
-
reg_sp_si = reg_sp_si
|
|
1724
|
-
elif
|
|
1725
|
-
reg_sp_val = reg_sp_expr
|
|
1724
|
+
reg_sp_si = claripy.backends.vsa.convert(reg_sp_si)
|
|
1725
|
+
elif isinstance(reg_sp_expr_vsa, int):
|
|
1726
|
+
reg_sp_val = claripy.backends.vsa.convert(reg_sp_expr)
|
|
1726
1727
|
reg_sp_si = successor_state.solver.SI(bits=successor_state.arch.bits, to_conv=reg_sp_val)
|
|
1727
|
-
reg_sp_si = reg_sp_si
|
|
1728
|
-
elif (
|
|
1729
|
-
|
|
1730
|
-
): # pylint:disable=unidiomatic-typecheck # type: ignore
|
|
1731
|
-
reg_sp_si = reg_sp_expr._model_vsa
|
|
1728
|
+
reg_sp_si = claripy.backends.vsa.convert(reg_sp_si)
|
|
1729
|
+
elif isinstance(reg_sp_expr_vsa, claripy.vsa.StridedInterval):
|
|
1730
|
+
reg_sp_si = reg_sp_expr_vsa
|
|
1732
1731
|
reg_sp_val = reg_sp_si.min
|
|
1733
1732
|
else:
|
|
1734
|
-
reg_sp_si = next(iter(
|
|
1733
|
+
reg_sp_si = next(iter(reg_sp_expr_vsa.items()))[1]
|
|
1735
1734
|
reg_sp_val = reg_sp_si.min
|
|
1736
1735
|
|
|
1737
1736
|
reg_sp_val = reg_sp_val - arch.bytes # TODO: Is it OK?
|
angr/code_location.py
CHANGED
|
@@ -20,12 +20,12 @@ class CodeLocation:
|
|
|
20
20
|
|
|
21
21
|
def __init__(
|
|
22
22
|
self,
|
|
23
|
-
block_addr: int,
|
|
23
|
+
block_addr: int | None,
|
|
24
24
|
stmt_idx: int | None,
|
|
25
25
|
sim_procedure=None,
|
|
26
26
|
ins_addr: int | None = None,
|
|
27
27
|
context: Any = None,
|
|
28
|
-
block_idx: int = None,
|
|
28
|
+
block_idx: int | None = None,
|
|
29
29
|
**kwargs,
|
|
30
30
|
):
|
|
31
31
|
"""
|
|
@@ -41,12 +41,12 @@ class CodeLocation:
|
|
|
41
41
|
:param kwargs: Optional arguments, will be stored, but not used in __eq__ or __hash__.
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
self.block_addr: int = block_addr
|
|
44
|
+
self.block_addr: int | None = block_addr
|
|
45
45
|
self.stmt_idx: int | None = stmt_idx
|
|
46
46
|
self.sim_procedure = sim_procedure
|
|
47
47
|
self.ins_addr: int | None = ins_addr
|
|
48
48
|
self.context: tuple[int] | None = context
|
|
49
|
-
self.block_idx = block_idx
|
|
49
|
+
self.block_idx: int | None = block_idx
|
|
50
50
|
self._hash = None
|
|
51
51
|
|
|
52
52
|
self.info: dict | None = None
|
angr/engines/pcode/cc.py
CHANGED
|
@@ -10,6 +10,7 @@ from ...calling_conventions import (
|
|
|
10
10
|
register_default_cc,
|
|
11
11
|
SimCCUnknown,
|
|
12
12
|
default_cc,
|
|
13
|
+
SimCCO32,
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
|
|
@@ -107,6 +108,7 @@ def register_pcode_arch_default_cc(arch: ArchPcode):
|
|
|
107
108
|
"PowerPC:BE:32:e200": SimCCPowerPC,
|
|
108
109
|
"PowerPC:BE:32:MPC8270": SimCCPowerPC,
|
|
109
110
|
"Xtensa:LE:32:default": SimCCXtensa,
|
|
111
|
+
"MIPS:LE:32:default": SimCCO32,
|
|
110
112
|
}
|
|
111
113
|
if arch.name in manual_cc_mapping:
|
|
112
114
|
# first attempt: manually specified mappings
|
angr/engines/vex/heavy/heavy.py
CHANGED
|
@@ -349,7 +349,7 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
|
|
|
349
349
|
def _perform_vex_expr_Load(self, addr, ty, endness, **kwargs):
|
|
350
350
|
result = super()._perform_vex_expr_Load(addr, ty, endness, **kwargs)
|
|
351
351
|
if o.UNINITIALIZED_ACCESS_AWARENESS in self.state.options:
|
|
352
|
-
if getattr(addr
|
|
352
|
+
if getattr(claripy.backends.vsa.convert(addr), "uninitialized", False):
|
|
353
353
|
raise errors.SimUninitializedAccessError("addr", addr)
|
|
354
354
|
return result
|
|
355
355
|
|
|
@@ -14,6 +14,7 @@ from angr.misc.ux import deprecated
|
|
|
14
14
|
from angr.errors import SimMemoryMissingError, SimMemoryError
|
|
15
15
|
from angr.storage.memory_mixins import MultiValuedMemory
|
|
16
16
|
from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
|
|
17
|
+
from angr.knowledge_plugins.key_definitions.definition import A
|
|
17
18
|
from angr.engines.light import SpOffset
|
|
18
19
|
from angr.code_location import CodeLocation, ExternalCodeLocation
|
|
19
20
|
from .atoms import Atom, Register, MemoryLocation, Tmp, ConstantSrc
|
|
@@ -660,7 +661,7 @@ class LiveDefinitions:
|
|
|
660
661
|
self.other_uses.add_use(definition, code_loc, expr)
|
|
661
662
|
|
|
662
663
|
def get_definitions(
|
|
663
|
-
self, thing:
|
|
664
|
+
self, thing: A | Definition[A] | Iterable[A] | Iterable[Definition[A]] | MultiValues
|
|
664
665
|
) -> set[Definition[Atom]]:
|
|
665
666
|
if isinstance(thing, MultiValues):
|
|
666
667
|
defs = set()
|
|
@@ -693,9 +694,9 @@ class LiveDefinitions:
|
|
|
693
694
|
return self.get_tmp_definitions(thing.tmp_idx)
|
|
694
695
|
else:
|
|
695
696
|
defs = set()
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
697
|
+
mv = self.others.get(thing, None)
|
|
698
|
+
if mv is not None:
|
|
699
|
+
defs |= self.get_definitions(mv)
|
|
699
700
|
return defs
|
|
700
701
|
|
|
701
702
|
def get_tmp_definitions(self, tmp_idx: int) -> set[Definition]:
|
|
@@ -749,7 +750,7 @@ class LiveDefinitions:
|
|
|
749
750
|
return LiveDefinitions.extract_defs_from_annotations(annotations)
|
|
750
751
|
|
|
751
752
|
@deprecated("get_definitions")
|
|
752
|
-
def get_definitions_from_atoms(self, atoms: Iterable[
|
|
753
|
+
def get_definitions_from_atoms(self, atoms: Iterable[A]) -> Iterable[Definition]:
|
|
753
754
|
result = set()
|
|
754
755
|
for atom in atoms:
|
|
755
756
|
result |= self.get_definitions(atom)
|
|
@@ -813,9 +814,7 @@ class LiveDefinitions:
|
|
|
813
814
|
return None
|
|
814
815
|
return r.concrete_value
|
|
815
816
|
|
|
816
|
-
def get_values(
|
|
817
|
-
self, spec: Atom | Definition[Atom] | Iterable[Atom] | Iterable[Definition[Atom]]
|
|
818
|
-
) -> MultiValues | None:
|
|
817
|
+
def get_values(self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]]) -> MultiValues | None:
|
|
819
818
|
if isinstance(spec, Definition):
|
|
820
819
|
atom = spec.atom
|
|
821
820
|
elif isinstance(spec, Atom):
|
|
@@ -874,7 +873,7 @@ class LiveDefinitions:
|
|
|
874
873
|
|
|
875
874
|
def get_one_value(
|
|
876
875
|
self,
|
|
877
|
-
spec:
|
|
876
|
+
spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]],
|
|
878
877
|
strip_annotations: bool = False,
|
|
879
878
|
) -> claripy.ast.bv.BV | None:
|
|
880
879
|
r = self.get_values(spec)
|
|
@@ -884,19 +883,19 @@ class LiveDefinitions:
|
|
|
884
883
|
|
|
885
884
|
@overload
|
|
886
885
|
def get_concrete_value(
|
|
887
|
-
self, spec:
|
|
886
|
+
self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[int] = ...
|
|
888
887
|
) -> int | None: ...
|
|
889
888
|
|
|
890
889
|
@overload
|
|
891
890
|
def get_concrete_value(
|
|
892
891
|
self,
|
|
893
|
-
spec:
|
|
892
|
+
spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]],
|
|
894
893
|
cast_to: type[bytes] = ...,
|
|
895
894
|
) -> bytes | None: ...
|
|
896
895
|
|
|
897
896
|
def get_concrete_value(
|
|
898
897
|
self,
|
|
899
|
-
spec:
|
|
898
|
+
spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]],
|
|
900
899
|
cast_to: type[int] | type[bytes] = int,
|
|
901
900
|
) -> int | bytes | None:
|
|
902
901
|
r = self.get_one_value(spec, strip_annotations=True)
|
|
@@ -983,7 +982,7 @@ class LiveDefinitions:
|
|
|
983
982
|
@overload
|
|
984
983
|
def deref(
|
|
985
984
|
self,
|
|
986
|
-
pointer: MultiValues |
|
|
985
|
+
pointer: MultiValues | A | Definition[A] | Iterable[A] | Iterable[Definition[A]],
|
|
987
986
|
size: int | DerefSize,
|
|
988
987
|
endness: archinfo.Endness = ...,
|
|
989
988
|
) -> set[MemoryLocation]: ...
|