angr 9.2.84__py3-none-win_amd64.whl → 9.2.85__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/cfg/cfg_base.py +6 -1
- angr/analyses/cfg/cfg_fast.py +32 -10
- angr/analyses/decompiler/clinic.py +204 -4
- angr/analyses/decompiler/condition_processor.py +8 -2
- angr/analyses/decompiler/decompiler.py +19 -17
- angr/analyses/decompiler/goto_manager.py +34 -51
- angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
- angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
- angr/analyses/decompiler/region_identifier.py +8 -2
- angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
- angr/analyses/decompiler/structured_codegen/c.py +33 -1
- angr/analyses/decompiler/structuring/phoenix.py +3 -1
- angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
- angr/analyses/decompiler/utils.py +50 -0
- angr/analyses/disassembly.py +10 -3
- angr/analyses/propagator/engine_ail.py +125 -0
- angr/analyses/reaching_definitions/engine_ail.py +36 -2
- angr/analyses/reaching_definitions/rd_initializer.py +15 -1
- angr/analyses/reaching_definitions/rd_state.py +9 -4
- angr/analyses/stack_pointer_tracker.py +10 -17
- angr/analyses/variable_recovery/engine_ail.py +27 -1
- angr/angrdb/serializers/loader.py +10 -3
- angr/calling_conventions.py +2 -0
- angr/engines/pcode/behavior.py +7 -2
- angr/engines/pcode/cc.py +1 -0
- angr/engines/pcode/emulate.py +144 -104
- angr/engines/pcode/lifter.py +135 -79
- angr/knowledge_plugins/functions/function_manager.py +5 -3
- angr/knowledge_plugins/propagations/states.py +14 -0
- angr/lib/angr_native.dll +0 -0
- angr/procedures/cgc/deallocate.py +5 -2
- angr/procedures/posix/gethostbyname.py +23 -8
- angr/project.py +4 -0
- angr/simos/__init__.py +2 -0
- angr/simos/simos.py +1 -0
- angr/simos/snimmuc_nxp.py +152 -0
- angr/state_plugins/history.py +3 -1
- angr/utils/graph.py +20 -18
- {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
- {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/RECORD +57 -55
- tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
- tests/analyses/cfg/test_jumptables.py +2 -1
- tests/analyses/decompiler/test_decompiler.py +130 -103
- tests/engines/pcode/test_emulate.py +607 -0
- tests/serialization/test_db.py +30 -0
- angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
- {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
- {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
- {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
- {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/top_level.txt +0 -0
angr/engines/pcode/behavior.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import operator
|
|
2
2
|
from typing import Callable, Iterable, Tuple
|
|
3
3
|
|
|
4
|
-
from pypcode import OpCode
|
|
5
4
|
import claripy
|
|
6
5
|
from claripy.ast.bv import BV
|
|
7
6
|
|
|
8
7
|
from ...errors import AngrError
|
|
9
8
|
|
|
9
|
+
try:
|
|
10
|
+
from pypcode import OpCode
|
|
11
|
+
except ImportError:
|
|
12
|
+
OpCode = None
|
|
13
|
+
|
|
10
14
|
# pylint:disable=abstract-method
|
|
11
15
|
|
|
12
16
|
|
|
@@ -889,7 +893,8 @@ class BehaviorFactory:
|
|
|
889
893
|
|
|
890
894
|
def __init__(self):
|
|
891
895
|
self._behaviors = {}
|
|
892
|
-
|
|
896
|
+
if OpCode:
|
|
897
|
+
self._register_behaviors()
|
|
893
898
|
|
|
894
899
|
def get_behavior_for_opcode(self, opcode: int) -> OpBehavior:
|
|
895
900
|
return self._behaviors[opcode]
|
angr/engines/pcode/cc.py
CHANGED
|
@@ -98,6 +98,7 @@ def register_pcode_arch_default_cc(arch: ArchPcode):
|
|
|
98
98
|
"68000:BE:32:default": SimCCM68k,
|
|
99
99
|
"RISCV:LE:64:RV64G": SimCCRISCV,
|
|
100
100
|
"RISCV:LE:64:RV64GC": SimCCRISCV,
|
|
101
|
+
"sparc:BE:32:default": SimCCSPARC,
|
|
101
102
|
"sparc:BE:64:default": SimCCSPARC,
|
|
102
103
|
"SuperH4:LE:32:default": SimCCSH4,
|
|
103
104
|
"pa-risc:BE:32:default": SimCCPARISC,
|
angr/engines/pcode/emulate.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional
|
|
3
3
|
|
|
4
|
-
from pypcode import OpCode, Varnode, PcodeOp, Translation
|
|
5
4
|
import claripy
|
|
6
5
|
from claripy.ast.bv import BV
|
|
7
6
|
|
|
@@ -12,6 +11,11 @@ from .behavior import OpBehavior
|
|
|
12
11
|
from ...errors import AngrError
|
|
13
12
|
from ...state_plugins.inspect import BP_BEFORE, BP_AFTER
|
|
14
13
|
|
|
14
|
+
try:
|
|
15
|
+
from pypcode import OpCode, Varnode, PcodeOp
|
|
16
|
+
except ImportError:
|
|
17
|
+
pass
|
|
18
|
+
|
|
15
19
|
|
|
16
20
|
l = logging.getLogger(__name__)
|
|
17
21
|
|
|
@@ -21,71 +25,69 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
21
25
|
Mixin for p-code execution.
|
|
22
26
|
"""
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
_current_behavior:
|
|
28
|
+
_current_op: Optional["PcodeOp"]
|
|
29
|
+
_current_op_idx: int
|
|
30
|
+
_current_behavior: Optional[OpBehavior]
|
|
27
31
|
|
|
28
32
|
def __init__(self, *args, **kwargs):
|
|
29
33
|
super().__init__(*args, **kwargs)
|
|
30
|
-
self._current_ins = None
|
|
31
34
|
self._current_op = None
|
|
32
35
|
self._current_behavior = None
|
|
33
|
-
self._special_op_handlers = {
|
|
34
|
-
OpCode.LOAD: self._execute_load,
|
|
35
|
-
OpCode.STORE: self._execute_store,
|
|
36
|
-
OpCode.BRANCH: self._execute_branch,
|
|
37
|
-
OpCode.CBRANCH: self._execute_cbranch,
|
|
38
|
-
OpCode.BRANCHIND: self._execute_branchind,
|
|
39
|
-
OpCode.CALL: self._execute_call,
|
|
40
|
-
OpCode.CALLIND: self._execute_callind,
|
|
41
|
-
OpCode.CALLOTHER: self._execute_callother,
|
|
42
|
-
OpCode.RETURN: self._execute_ret,
|
|
43
|
-
OpCode.MULTIEQUAL: self._execute_multiequal,
|
|
44
|
-
OpCode.INDIRECT: self._execute_indirect,
|
|
45
|
-
OpCode.SEGMENTOP: self._execute_segment_op,
|
|
46
|
-
OpCode.CPOOLREF: self._execute_cpool_ref,
|
|
47
|
-
OpCode.NEW: self._execute_new,
|
|
48
|
-
}
|
|
49
36
|
|
|
50
37
|
def handle_pcode_block(self, irsb: IRSB) -> None:
|
|
51
38
|
"""
|
|
52
|
-
Execute a single IRSB.
|
|
39
|
+
Execute a single P-Code IRSB.
|
|
53
40
|
|
|
54
41
|
:param irsb: Block to be executed.
|
|
55
42
|
"""
|
|
56
43
|
self.irsb = irsb
|
|
44
|
+
|
|
57
45
|
# Hack on a handler here to track whether exit has been handled or not
|
|
58
46
|
# FIXME: Vex models this as a known exit statement, which we should also
|
|
59
47
|
# do here. For now, handle it this way.
|
|
60
48
|
self.state.scratch.exit_handled = False
|
|
49
|
+
self._pcode_tmps = {}
|
|
50
|
+
|
|
51
|
+
fallthru_addr = self.irsb.addr
|
|
52
|
+
self.state.scratch.ins_addr = self.irsb.addr
|
|
53
|
+
last_imark_op_idx = 0
|
|
54
|
+
|
|
55
|
+
# Note: start_op_idx is instruction relative
|
|
56
|
+
start_op_idx = self.state.scratch.statement_offset
|
|
57
|
+
self.state.scratch.statement_offset = 0
|
|
58
|
+
assert start_op_idx == 0, "FIXME: Test statement_offset behavior"
|
|
59
|
+
|
|
60
|
+
for op_idx, op in enumerate(irsb._ops[start_op_idx:]): # FIXME: Shouldn't use protected members of IRSB
|
|
61
|
+
op_idx += start_op_idx
|
|
62
|
+
|
|
63
|
+
if op.opcode == OpCode.IMARK:
|
|
64
|
+
if op_idx > 0:
|
|
65
|
+
# Trigger BP for previous instruction once we reach next IMARK
|
|
66
|
+
self.state._inspect("instruction", BP_AFTER)
|
|
67
|
+
|
|
68
|
+
decode_addr = op.inputs[0].offset
|
|
69
|
+
last_imark_op_idx = op_idx
|
|
70
|
+
|
|
71
|
+
# Note: instruction BP will not be triggered on p-code-relative jumps
|
|
72
|
+
l.debug("Executing machine instruction @ %#x", decode_addr)
|
|
73
|
+
for vn in op.inputs:
|
|
74
|
+
self.state._inspect("instruction", BP_BEFORE, instruction=vn.offset)
|
|
75
|
+
|
|
76
|
+
# FIXME: Hacking this on here but ideally should use "scratch".
|
|
77
|
+
self._pcode_tmps = {} # FIXME: Consider alignment requirements
|
|
78
|
+
self.state.scratch.ins_addr = decode_addr
|
|
79
|
+
fallthru_addr = op.inputs[-1].offset + op.inputs[-1].size
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
self._current_op = op
|
|
83
|
+
self._current_op_idx = op_idx - last_imark_op_idx
|
|
84
|
+
l.debug("Executing P-Code op: %s", self._current_op)
|
|
85
|
+
self._execute_current_op()
|
|
86
|
+
self._current_op = None
|
|
61
87
|
|
|
62
|
-
|
|
63
|
-
for i, ins in enumerate(irsb._instructions):
|
|
64
|
-
l.debug(
|
|
65
|
-
"Executing machine instruction @ %#x (%d of %d)", ins.address.offset, i + 1, len(irsb._instructions)
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
# Execute a single instruction of the emulated machine
|
|
69
|
-
self._current_ins = ins
|
|
70
|
-
self.state.scratch.ins_addr = self._current_ins.address.offset
|
|
71
|
-
|
|
72
|
-
# FIXME: Hacking this on here but ideally should use "scratch".
|
|
73
|
-
self._pcode_tmps = {} # FIXME: Consider alignment requirements
|
|
74
|
-
|
|
75
|
-
self.state._inspect("instruction", BP_BEFORE, instruction=self._current_ins.address.offset)
|
|
76
|
-
offset = self.state.scratch.statement_offset
|
|
77
|
-
self.state.scratch.statement_offset = 0
|
|
78
|
-
for op in self._current_ins.ops[offset:]:
|
|
79
|
-
self._current_op = op
|
|
80
|
-
self._current_behavior = irsb.behaviors.get_behavior_for_opcode(self._current_op.opcode)
|
|
81
|
-
l.debug("Executing p-code op: %s", self._current_op)
|
|
82
|
-
self._execute_current_op()
|
|
88
|
+
if self.state.scratch.statement_offset == 0:
|
|
83
89
|
self.state._inspect("instruction", BP_AFTER)
|
|
84
90
|
|
|
85
|
-
self._current_op = None
|
|
86
|
-
self._current_behavior = None
|
|
87
|
-
fallthru_addr = ins.address.offset + ins.length
|
|
88
|
-
|
|
89
91
|
if not self.state.scratch.exit_handled:
|
|
90
92
|
self.successors.add_successor(
|
|
91
93
|
self.state,
|
|
@@ -100,16 +102,34 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
100
102
|
"""
|
|
101
103
|
Execute the current p-code operation.
|
|
102
104
|
"""
|
|
103
|
-
|
|
105
|
+
self._current_behavior = self.irsb.behaviors.get_behavior_for_opcode(self._current_op.opcode)
|
|
104
106
|
|
|
105
107
|
if self._current_behavior.is_special:
|
|
106
|
-
|
|
108
|
+
handlers = {
|
|
109
|
+
OpCode.LOAD: self._execute_load,
|
|
110
|
+
OpCode.STORE: self._execute_store,
|
|
111
|
+
OpCode.BRANCH: self._execute_branch,
|
|
112
|
+
OpCode.CBRANCH: self._execute_cbranch,
|
|
113
|
+
OpCode.BRANCHIND: self._execute_branchind,
|
|
114
|
+
OpCode.CALL: self._execute_call,
|
|
115
|
+
OpCode.CALLIND: self._execute_callind,
|
|
116
|
+
OpCode.CALLOTHER: self._execute_callother,
|
|
117
|
+
OpCode.RETURN: self._execute_ret,
|
|
118
|
+
OpCode.MULTIEQUAL: self._execute_multiequal,
|
|
119
|
+
OpCode.INDIRECT: self._execute_indirect,
|
|
120
|
+
OpCode.SEGMENTOP: self._execute_segment_op,
|
|
121
|
+
OpCode.CPOOLREF: self._execute_cpool_ref,
|
|
122
|
+
OpCode.NEW: self._execute_new,
|
|
123
|
+
}
|
|
124
|
+
handlers[self._current_behavior.opcode]()
|
|
107
125
|
elif self._current_behavior.is_unary:
|
|
108
126
|
self._execute_unary()
|
|
109
127
|
else:
|
|
110
128
|
self._execute_binary()
|
|
111
129
|
|
|
112
|
-
|
|
130
|
+
self._current_behavior = None
|
|
131
|
+
|
|
132
|
+
def _map_register_name(self, varnode: "Varnode") -> int:
|
|
113
133
|
"""
|
|
114
134
|
Map SLEIGH register offset to ArchInfo register offset based on name.
|
|
115
135
|
|
|
@@ -118,7 +138,7 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
118
138
|
"""
|
|
119
139
|
# FIXME: Will need performance optimization
|
|
120
140
|
# FIXME: Should not get trans object this way. There should be a faster mapping method than going through trans
|
|
121
|
-
reg_name = varnode.
|
|
141
|
+
reg_name = varnode.getRegisterName()
|
|
122
142
|
try:
|
|
123
143
|
reg_offset = self.state.project.arch.get_register_offset(reg_name.lower())
|
|
124
144
|
l.debug("Mapped register '%s' to offset %x", reg_name, reg_offset)
|
|
@@ -143,7 +163,7 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
143
163
|
else:
|
|
144
164
|
return v_in
|
|
145
165
|
|
|
146
|
-
def _set_value(self, varnode: Varnode, value: BV) -> None:
|
|
166
|
+
def _set_value(self, varnode: "Varnode", value: BV) -> None:
|
|
147
167
|
"""
|
|
148
168
|
Store a value for a given varnode.
|
|
149
169
|
|
|
@@ -153,29 +173,28 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
153
173
|
:param varnode: Varnode to store into.
|
|
154
174
|
:param value: Value to store.
|
|
155
175
|
"""
|
|
156
|
-
space_name = varnode.space.name
|
|
157
|
-
|
|
158
176
|
# FIXME: Consider moving into behavior.py
|
|
159
177
|
value = self._adjust_value_size(varnode.size * 8, value)
|
|
160
178
|
assert varnode.size * 8 == value.size()
|
|
161
179
|
|
|
162
|
-
|
|
163
|
-
|
|
180
|
+
space = varnode.space
|
|
181
|
+
l.debug("Storing %s %x %s %d", space.name, varnode.offset, value, varnode.size)
|
|
182
|
+
if space.name == "register":
|
|
164
183
|
self.state.registers.store(
|
|
165
184
|
self._map_register_name(varnode), value, size=varnode.size, endness=self.project.arch.register_endness
|
|
166
185
|
)
|
|
167
186
|
|
|
168
|
-
elif
|
|
187
|
+
elif space.name == "unique":
|
|
169
188
|
self._pcode_tmps[varnode.offset] = value
|
|
170
189
|
|
|
171
|
-
elif
|
|
190
|
+
elif space.name in ("ram", "mem"):
|
|
172
191
|
l.debug("Storing %s to offset %s", value, varnode.offset)
|
|
173
192
|
self.state.memory.store(varnode.offset, value, endness=self.project.arch.memory_endness)
|
|
174
193
|
|
|
175
194
|
else:
|
|
176
|
-
raise AngrError(f"Attempted write to unhandled address space '{
|
|
195
|
+
raise AngrError(f"Attempted write to unhandled address space '{space.name}'")
|
|
177
196
|
|
|
178
|
-
def _get_value(self, varnode: Varnode) -> BV:
|
|
197
|
+
def _get_value(self, varnode: "Varnode") -> BV:
|
|
179
198
|
"""
|
|
180
199
|
Get a value for a given varnode.
|
|
181
200
|
|
|
@@ -218,54 +237,77 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
218
237
|
"""
|
|
219
238
|
Execute the unary behavior of the current op.
|
|
220
239
|
"""
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
out = self._current_behavior.evaluate_unary(self._current_op.output.size, self._current_op.inputs[0].size, in1)
|
|
224
|
-
l.debug("out unary = %s", out)
|
|
240
|
+
in0 = self._get_value(self._current_op.inputs[0])
|
|
241
|
+
out = self._current_behavior.evaluate_unary(self._current_op.output.size, self._current_op.inputs[0].size, in0)
|
|
225
242
|
self._set_value(self._current_op.output, out)
|
|
226
243
|
|
|
227
244
|
def _execute_binary(self) -> None:
|
|
228
245
|
"""
|
|
229
246
|
Execute the binary behavior of the current op.
|
|
230
247
|
"""
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
248
|
+
|
|
249
|
+
# Validate output
|
|
250
|
+
assert self._current_op.output is not None
|
|
251
|
+
if (
|
|
252
|
+
self._current_op.opcode
|
|
253
|
+
in [
|
|
254
|
+
OpCode.INT_LESS,
|
|
255
|
+
OpCode.INT_SLESS,
|
|
256
|
+
OpCode.INT_LESSEQUAL,
|
|
257
|
+
OpCode.INT_SLESSEQUAL,
|
|
258
|
+
OpCode.INT_EQUAL,
|
|
259
|
+
OpCode.INT_NOTEQUAL,
|
|
260
|
+
]
|
|
261
|
+
and self._current_op.output.size != 1
|
|
262
|
+
):
|
|
263
|
+
l.warning(
|
|
264
|
+
"SLEIGH spec states output size for op %s must be 1, but op has %d",
|
|
265
|
+
self._current_op.opcode.__name__,
|
|
266
|
+
self._current_op.output.size,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Validate ops that mandate inputs of equal sizes
|
|
270
|
+
# Validate ops that mandate output of greater size
|
|
271
|
+
|
|
272
|
+
# Validate inputs
|
|
273
|
+
|
|
274
|
+
in0 = self._get_value(self._current_op.inputs[0])
|
|
275
|
+
in1 = self._get_value(self._current_op.inputs[1])
|
|
235
276
|
out = self._current_behavior.evaluate_binary(
|
|
236
|
-
self._current_op.output.size, self._current_op.inputs[0].size,
|
|
277
|
+
self._current_op.output.size, self._current_op.inputs[0].size, in0, in1
|
|
237
278
|
)
|
|
238
|
-
l.debug("out binary = %s", out)
|
|
239
279
|
self._set_value(self._current_op.output, out)
|
|
240
280
|
|
|
241
281
|
def _execute_load(self) -> None:
|
|
242
282
|
"""
|
|
243
283
|
Execute a p-code load operation.
|
|
244
284
|
"""
|
|
245
|
-
|
|
246
|
-
|
|
285
|
+
space = self._current_op.inputs[0].getSpaceFromConst()
|
|
286
|
+
offset = self._get_value(self._current_op.inputs[1])
|
|
247
287
|
out = self._current_op.output
|
|
248
|
-
if
|
|
249
|
-
res = self.state.memory.load(
|
|
250
|
-
elif
|
|
251
|
-
res = self.state.registers.load(
|
|
288
|
+
if space.name in ("ram", "mem"):
|
|
289
|
+
res = self.state.memory.load(offset, out.size, endness=self.project.arch.memory_endness)
|
|
290
|
+
elif space.name in "register":
|
|
291
|
+
res = self.state.registers.load(offset, size=out.size, endness=self.project.arch.register_endness)
|
|
252
292
|
else:
|
|
253
293
|
raise AngrError("Load from unhandled address space")
|
|
254
|
-
l.debug("Loaded %s from offset %s", res,
|
|
294
|
+
l.debug("Loaded %s from offset %s", res, offset)
|
|
255
295
|
self._set_value(out, res)
|
|
256
296
|
|
|
297
|
+
# CHECKME: wordsize condition in cpuid load
|
|
298
|
+
|
|
257
299
|
def _execute_store(self) -> None:
|
|
258
300
|
"""
|
|
259
301
|
Execute a p-code store operation.
|
|
260
302
|
"""
|
|
261
|
-
|
|
262
|
-
|
|
303
|
+
space = self._current_op.inputs[0].getSpaceFromConst()
|
|
304
|
+
offset = self._get_value(self._current_op.inputs[1])
|
|
263
305
|
data = self._get_value(self._current_op.inputs[2])
|
|
264
|
-
l.debug("Storing %s at offset %s", data,
|
|
265
|
-
if
|
|
266
|
-
self.state.memory.store(
|
|
267
|
-
elif
|
|
268
|
-
self.state.registers.store(
|
|
306
|
+
l.debug("Storing %s at offset %s", data, offset)
|
|
307
|
+
if space.name in ("ram", "mem"):
|
|
308
|
+
self.state.memory.store(offset, data, endness=self.project.arch.memory_endness)
|
|
309
|
+
elif space.name == "register":
|
|
310
|
+
self.state.registers.store(offset, data, endness=self.project.arch.register_endness)
|
|
269
311
|
else:
|
|
270
312
|
raise AngrError("Store to unhandled address space")
|
|
271
313
|
|
|
@@ -273,12 +315,13 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
273
315
|
"""
|
|
274
316
|
Execute a p-code branch operation.
|
|
275
317
|
"""
|
|
276
|
-
|
|
277
|
-
if
|
|
318
|
+
dest = self._current_op.inputs[0]
|
|
319
|
+
if dest.space.name == "const":
|
|
320
|
+
# P-Code-relative branch
|
|
278
321
|
expr = self.state.scratch.ins_addr
|
|
279
|
-
self.state.scratch.statement_offset =
|
|
322
|
+
self.state.scratch.statement_offset = self._current_op_idx + dest.offset
|
|
280
323
|
else:
|
|
281
|
-
expr =
|
|
324
|
+
expr = dest.offset
|
|
282
325
|
|
|
283
326
|
self.successors.add_successor(
|
|
284
327
|
self.state,
|
|
@@ -297,13 +340,14 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
297
340
|
"""
|
|
298
341
|
exit_state = self.state.copy()
|
|
299
342
|
cond = self._get_value(self._current_op.inputs[1])
|
|
300
|
-
|
|
343
|
+
dest = self._current_op.inputs[0]
|
|
301
344
|
|
|
302
|
-
if
|
|
345
|
+
if dest.space.name == "const":
|
|
346
|
+
# P-Code-relative branch
|
|
303
347
|
expr = exit_state.scratch.ins_addr
|
|
304
|
-
exit_state.scratch.statement_offset =
|
|
348
|
+
exit_state.scratch.statement_offset = self._current_op_idx + dest.offset
|
|
305
349
|
else:
|
|
306
|
-
expr =
|
|
350
|
+
expr = dest.offset
|
|
307
351
|
|
|
308
352
|
self.successors.add_successor(
|
|
309
353
|
exit_state,
|
|
@@ -323,11 +367,9 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
323
367
|
"""
|
|
324
368
|
Execute a p-code return operation.
|
|
325
369
|
"""
|
|
326
|
-
ret_addr = self._get_value(self._current_op.inputs[0])
|
|
327
|
-
|
|
328
370
|
self.successors.add_successor(
|
|
329
371
|
self.state,
|
|
330
|
-
|
|
372
|
+
self._get_value(self._current_op.inputs[0]),
|
|
331
373
|
self.state.scratch.guard,
|
|
332
374
|
"Ijk_Ret",
|
|
333
375
|
exit_stmt_idx=DEFAULT_STATEMENT,
|
|
@@ -340,11 +382,9 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
340
382
|
"""
|
|
341
383
|
Execute a p-code indirect branch operation.
|
|
342
384
|
"""
|
|
343
|
-
expr = self._get_value(self._current_op.inputs[0])
|
|
344
|
-
|
|
345
385
|
self.successors.add_successor(
|
|
346
386
|
self.state,
|
|
347
|
-
|
|
387
|
+
self._get_value(self._current_op.inputs[0]),
|
|
348
388
|
self.state.scratch.guard,
|
|
349
389
|
"Ijk_Boring",
|
|
350
390
|
exit_stmt_idx=DEFAULT_STATEMENT,
|
|
@@ -357,11 +397,13 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
357
397
|
"""
|
|
358
398
|
Execute a p-code call operation.
|
|
359
399
|
"""
|
|
360
|
-
|
|
400
|
+
|
|
401
|
+
# FIXME: Spec claims CALL is semantically equivalent to BRANCH. But are p-code relative calls allowed? We assume
|
|
402
|
+
# not.
|
|
361
403
|
|
|
362
404
|
self.successors.add_successor(
|
|
363
405
|
self.state.copy(), # FIXME: Check extra processing after call
|
|
364
|
-
|
|
406
|
+
self._current_op.inputs[0].offset,
|
|
365
407
|
self.state.scratch.guard,
|
|
366
408
|
"Ijk_Call",
|
|
367
409
|
exit_stmt_idx=DEFAULT_STATEMENT,
|
|
@@ -374,11 +416,9 @@ class PcodeEmulatorMixin(SimEngineBase):
|
|
|
374
416
|
"""
|
|
375
417
|
Execute a p-code indirect call operation.
|
|
376
418
|
"""
|
|
377
|
-
expr = self._get_value(self._current_op.inputs[0])
|
|
378
|
-
|
|
379
419
|
self.successors.add_successor(
|
|
380
420
|
self.state,
|
|
381
|
-
|
|
421
|
+
self._get_value(self._current_op.inputs[0]),
|
|
382
422
|
self.state.scratch.guard,
|
|
383
423
|
"Ijk_Call",
|
|
384
424
|
exit_stmt_idx=DEFAULT_STATEMENT,
|