angr 9.2.83__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.

Files changed (62) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_base.py +6 -1
  3. angr/analyses/cfg/cfg_fast.py +32 -10
  4. angr/analyses/decompiler/clinic.py +204 -4
  5. angr/analyses/decompiler/condition_processor.py +8 -2
  6. angr/analyses/decompiler/decompilation_options.py +10 -0
  7. angr/analyses/decompiler/decompiler.py +19 -17
  8. angr/analyses/decompiler/goto_manager.py +34 -51
  9. angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
  10. angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
  11. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
  12. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
  13. angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
  14. angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
  15. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
  16. angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
  17. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
  18. angr/analyses/decompiler/region_identifier.py +8 -2
  19. angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
  20. angr/analyses/decompiler/structured_codegen/c.py +66 -5
  21. angr/analyses/decompiler/structuring/phoenix.py +3 -1
  22. angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
  23. angr/analyses/decompiler/utils.py +50 -0
  24. angr/analyses/disassembly.py +10 -3
  25. angr/analyses/propagator/engine_ail.py +125 -0
  26. angr/analyses/reaching_definitions/engine_ail.py +36 -2
  27. angr/analyses/reaching_definitions/rd_initializer.py +15 -1
  28. angr/analyses/reaching_definitions/rd_state.py +9 -4
  29. angr/analyses/stack_pointer_tracker.py +10 -17
  30. angr/analyses/variable_recovery/engine_ail.py +27 -1
  31. angr/angrdb/serializers/loader.py +10 -3
  32. angr/calling_conventions.py +2 -0
  33. angr/engines/pcode/behavior.py +7 -2
  34. angr/engines/pcode/cc.py +1 -0
  35. angr/engines/pcode/emulate.py +144 -104
  36. angr/engines/pcode/lifter.py +135 -79
  37. angr/knowledge_plugins/functions/function.py +28 -0
  38. angr/knowledge_plugins/functions/function_manager.py +48 -5
  39. angr/knowledge_plugins/propagations/states.py +14 -0
  40. angr/lib/angr_native.dll +0 -0
  41. angr/procedures/cgc/deallocate.py +5 -2
  42. angr/procedures/posix/gethostbyname.py +23 -8
  43. angr/project.py +4 -0
  44. angr/simos/__init__.py +2 -0
  45. angr/simos/simos.py +1 -0
  46. angr/simos/snimmuc_nxp.py +152 -0
  47. angr/state_plugins/history.py +3 -1
  48. angr/utils/graph.py +20 -18
  49. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
  50. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/RECORD +61 -59
  51. tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
  52. tests/analyses/cfg/test_jumptables.py +2 -1
  53. tests/analyses/decompiler/test_decompiler.py +155 -103
  54. tests/engines/pcode/test_emulate.py +607 -0
  55. tests/engines/test_java.py +609 -663
  56. tests/knowledge_plugins/functions/test_function_manager.py +13 -0
  57. tests/serialization/test_db.py +30 -0
  58. angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
  59. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
  60. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
  61. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
  62. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/top_level.txt +0 -0
@@ -2,8 +2,9 @@
2
2
  from typing import Optional, TYPE_CHECKING
3
3
  import logging
4
4
 
5
- import claripy
6
5
  import ailment
6
+ import claripy
7
+ from unique_log_filter import UniqueLogFilter
7
8
 
8
9
  from ...calling_conventions import SimRegArg
9
10
  from ...sim_type import SimTypeFunction
@@ -17,6 +18,7 @@ if TYPE_CHECKING:
17
18
 
18
19
 
19
20
  l = logging.getLogger(name=__name__)
21
+ l.addFilter(UniqueLogFilter())
20
22
 
21
23
 
22
24
  class SimEngineVRAIL(
@@ -610,6 +612,30 @@ class SimEngineVRAIL(
610
612
  r = self.state.top(expr.bits)
611
613
  return RichR(r, typevar=r0.typevar)
612
614
 
615
+ def _ail_handle_LogicalAnd(self, expr):
616
+ arg0, arg1 = expr.operands
617
+
618
+ r0 = self._expr(arg0)
619
+ _ = self._expr(arg1)
620
+ r = self.state.top(expr.bits)
621
+ return RichR(r, typevar=r0.typevar)
622
+
623
+ def _ail_handle_LogicalOr(self, expr):
624
+ arg0, arg1 = expr.operands
625
+
626
+ r0 = self._expr(arg0)
627
+ _ = self._expr(arg1)
628
+ r = self.state.top(expr.bits)
629
+ return RichR(r, typevar=r0.typevar)
630
+
631
+ def _ail_handle_LogicalXor(self, expr):
632
+ arg0, arg1 = expr.operands
633
+
634
+ r0 = self._expr(arg0)
635
+ _ = self._expr(arg1)
636
+ r = self.state.top(expr.bits)
637
+ return RichR(r, typevar=r0.typevar)
638
+
613
639
  def _ail_handle_Rol(self, expr):
614
640
  arg0, arg1 = expr.operands
615
641
 
@@ -3,7 +3,7 @@ from typing import List
3
3
 
4
4
  import cle
5
5
 
6
- from ...errors import AngrCorruptDBError
6
+ from ...errors import AngrCorruptDBError, AngrDBError
7
7
  from ..models import DbObject
8
8
 
9
9
 
@@ -34,13 +34,20 @@ class LoaderSerializer:
34
34
  # it exists. skip.
35
35
  continue
36
36
 
37
- # FIXME: We assume the binary and its libraries all still exist on the disk
37
+ try:
38
+ content = obj.cached_content if hasattr(obj, "cached_content") else None
39
+ if content is None:
40
+ # fall back to loading the file again from disk
41
+ with open(obj.binary, "rb") as the_file:
42
+ content = the_file.read()
43
+ except OSError as ex:
44
+ raise AngrDBError(f"Failed to load content for file {obj.binary}.") from ex
38
45
 
39
46
  # save the object
40
47
  o = DbObject(
41
48
  main_object=loader.main_object is obj,
42
49
  path=obj.binary,
43
- content=open(obj.binary, "rb").read(),
50
+ content=content,
44
51
  backend=LoaderSerializer.backend2name.get(obj.__class__),
45
52
  backend_args="", # TODO: We will need support from CLE to store loader arguments
46
53
  )
@@ -6,6 +6,7 @@ from collections import defaultdict
6
6
  import claripy
7
7
  import archinfo
8
8
  from archinfo import RegisterName
9
+ from unique_log_filter import UniqueLogFilter
9
10
 
10
11
  from .errors import AngrTypeError
11
12
  from .sim_type import (
@@ -32,6 +33,7 @@ from .state_plugins.sim_action_object import SimActionObject
32
33
  from .engines.soot.engine import SootMixin
33
34
 
34
35
  l = logging.getLogger(name=__name__)
36
+ l.addFilter(UniqueLogFilter())
35
37
 
36
38
 
37
39
  class PointerWrapper:
@@ -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
- self._register_behaviors()
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,
@@ -1,7 +1,6 @@
1
1
  import logging
2
- from typing import Union
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
- _current_ins: Union[Translation, None]
25
- _current_op: Union[PcodeOp, None]
26
- _current_behavior: Union[OpBehavior, None]
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
- fallthru_addr = None
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
- assert self._current_behavior is not None
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
- self._special_op_handlers[self._current_behavior.opcode]()
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
- def _map_register_name(self, varnode: Varnode) -> int:
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.get_register_name()
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
- l.debug("Storing %s %x %s %d", space_name, varnode.offset, value, varnode.size)
163
- if space_name == "register":
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 space_name == "unique":
187
+ elif space.name == "unique":
169
188
  self._pcode_tmps[varnode.offset] = value
170
189
 
171
- elif space_name in ("ram", "mem"):
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 '{space_name}'")
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
- in1 = self._get_value(self._current_op.inputs[0])
222
- l.debug("in1 = %s", in1)
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
- in1 = self._get_value(self._current_op.inputs[0])
232
- in2 = self._get_value(self._current_op.inputs[1])
233
- l.debug("in1 = %s", in1)
234
- l.debug("in2 = %s", in2)
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, in1, in2
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
- spc = self._current_op.inputs[0].get_space_from_const()
246
- off = self._get_value(self._current_op.inputs[1])
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 spc.name in ("ram", "mem"):
249
- res = self.state.memory.load(off, out.size, endness=self.project.arch.memory_endness)
250
- elif spc.name in "register":
251
- res = self.state.registers.load(off, size=out.size, endness=self.project.arch.register_endness)
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, off)
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
- spc = self._current_op.inputs[0].get_space_from_const()
262
- off = self._get_value(self._current_op.inputs[1])
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, off)
265
- if spc.name in ("ram", "mem"):
266
- self.state.memory.store(off, data, endness=self.project.arch.memory_endness)
267
- elif spc.name == "register":
268
- self.state.registers.store(off, data, endness=self.project.arch.register_endness)
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
- dest_addr = self._current_op.inputs[0].get_addr()
277
- if dest_addr.is_constant:
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 = dest_addr.offset + self._current_op.seq.uniq
322
+ self.state.scratch.statement_offset = self._current_op_idx + dest.offset
280
323
  else:
281
- expr = dest_addr.offset
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
- dest_addr = self._current_op.inputs[0].get_addr()
343
+ dest = self._current_op.inputs[0]
301
344
 
302
- if dest_addr.is_constant:
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 = dest_addr.offset + self._current_op.seq.uniq
348
+ exit_state.scratch.statement_offset = self._current_op_idx + dest.offset
305
349
  else:
306
- expr = dest_addr.offset
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
- ret_addr,
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
- expr,
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
- expr = self._current_op.inputs[0].get_addr().offset
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
- expr,
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
- expr,
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,