angr 9.2.138__py3-none-macosx_11_0_arm64.whl → 9.2.139__py3-none-macosx_11_0_arm64.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 (59) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/calling_convention/fact_collector.py +59 -12
  3. angr/analyses/calling_convention/utils.py +2 -2
  4. angr/analyses/cfg/cfg_fast.py +12 -4
  5. angr/analyses/decompiler/ail_simplifier.py +14 -3
  6. angr/analyses/decompiler/block_simplifier.py +0 -2
  7. angr/analyses/decompiler/callsite_maker.py +80 -14
  8. angr/analyses/decompiler/clinic.py +31 -37
  9. angr/analyses/decompiler/condition_processor.py +2 -2
  10. angr/analyses/decompiler/decompiler.py +2 -0
  11. angr/analyses/decompiler/dephication/rewriting_engine.py +16 -7
  12. angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
  13. angr/analyses/decompiler/optimization_passes/condition_constprop.py +149 -0
  14. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +12 -3
  15. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +1 -1
  16. angr/analyses/decompiler/optimization_passes/optimization_pass.py +5 -2
  17. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +15 -7
  18. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +7 -10
  19. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +12 -1
  20. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +61 -25
  21. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +50 -1
  22. angr/analyses/decompiler/presets/fast.py +2 -0
  23. angr/analyses/decompiler/presets/full.py +2 -0
  24. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +4 -0
  25. angr/analyses/decompiler/ssailification/rewriting_engine.py +20 -2
  26. angr/analyses/decompiler/ssailification/traversal_engine.py +4 -3
  27. angr/analyses/decompiler/structured_codegen/c.py +10 -3
  28. angr/analyses/decompiler/structuring/dream.py +7 -2
  29. angr/analyses/decompiler/structuring/phoenix.py +101 -49
  30. angr/analyses/decompiler/structuring/structurer_base.py +85 -36
  31. angr/analyses/decompiler/structuring/structurer_nodes.py +3 -1
  32. angr/analyses/deobfuscator/api_obf_finder.py +6 -1
  33. angr/analyses/deobfuscator/api_obf_type2_finder.py +158 -0
  34. angr/analyses/s_propagator.py +127 -50
  35. angr/analyses/s_reaching_definitions/s_rda_view.py +2 -2
  36. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -1
  37. angr/analyses/variable_recovery/engine_ail.py +1 -1
  38. angr/analyses/variable_recovery/engine_base.py +55 -62
  39. angr/analyses/variable_recovery/engine_vex.py +1 -1
  40. angr/analyses/variable_recovery/irsb_scanner.py +2 -2
  41. angr/calling_conventions.py +66 -9
  42. angr/engines/engine.py +2 -18
  43. angr/engines/light/engine.py +3 -8
  44. angr/engines/pcode/emulate.py +2 -2
  45. angr/engines/pcode/lifter.py +2 -2
  46. angr/engines/successors.py +1 -8
  47. angr/engines/vex/lifter.py +2 -2
  48. angr/engines/vex/light/light.py +2 -2
  49. angr/knowledge_plugins/cfg/cfg_model.py +3 -2
  50. angr/knowledge_plugins/labels.py +2 -2
  51. angr/knowledge_plugins/obfuscations.py +1 -0
  52. angr/knowledge_plugins/xrefs/xref_manager.py +4 -0
  53. angr/lib/angr_native.dylib +0 -0
  54. {angr-9.2.138.dist-info → angr-9.2.139.dist-info}/METADATA +6 -6
  55. {angr-9.2.138.dist-info → angr-9.2.139.dist-info}/RECORD +59 -57
  56. {angr-9.2.138.dist-info → angr-9.2.139.dist-info}/LICENSE +0 -0
  57. {angr-9.2.138.dist-info → angr-9.2.139.dist-info}/WHEEL +0 -0
  58. {angr-9.2.138.dist-info → angr-9.2.139.dist-info}/entry_points.txt +0 -0
  59. {angr-9.2.138.dist-info → angr-9.2.139.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import Any, TYPE_CHECKING, Generic, TypeVar, cast
2
+ from typing import Any, Generic, TypeVar, cast
3
3
  import contextlib
4
4
  import logging
5
5
 
@@ -16,8 +16,6 @@ from angr.code_location import CodeLocation
16
16
  from angr.analyses.typehoon import typevars, typeconsts
17
17
  from angr.analyses.typehoon.typevars import TypeVariable, DerivedTypeVariable, AddN, SubN, Load, Store
18
18
 
19
- if TYPE_CHECKING:
20
- from angr.knowledge_plugins.variables.variable_manager import VariableManager
21
19
 
22
20
  #
23
21
  # The base engine used in VariableRecoveryFast
@@ -72,8 +70,6 @@ class SimEngineVRBase(
72
70
  and storing data.
73
71
  """
74
72
 
75
- variable_manager: VariableManager
76
-
77
73
  def __init__(self, project, kb):
78
74
  super().__init__(project)
79
75
 
@@ -86,10 +82,6 @@ class SimEngineVRBase(
86
82
  return None
87
83
  return self.state.function.addr
88
84
 
89
- def process(self, state, *args, **kwargs):
90
- self.variable_manager = state.variable_manager
91
- super().process(state, *args, **kwargs)
92
-
93
85
  def _top(self, bits):
94
86
  return RichR(self.state.top(bits))
95
87
 
@@ -130,9 +122,9 @@ class SimEngineVRBase(
130
122
  if abs_offset.op == "__lshift__" and cast(claripy.ast.BV, abs_offset.args[1]).concrete:
131
123
  offset = cast(claripy.ast.BV, abs_offset.args[0])
132
124
  elem_size = 2 ** cast(claripy.ast.BV, abs_offset.args[1]).concrete_value
133
- elif abs_offset.op == "__mul__" and abs_offset.args[1].concrete:
134
- offset = abs_offset.args[0]
135
- elem_size = abs_offset.args[1].concrete_value
125
+ elif abs_offset.op == "__mul__" and cast(claripy.ast.BV, abs_offset.args[1]).concrete:
126
+ offset = cast(claripy.ast.BV, abs_offset.args[0])
127
+ elem_size = cast(claripy.ast.BV, abs_offset.args[1]).concrete_value
136
128
 
137
129
  if base_addr is not None and offset is not None and elem_size is not None:
138
130
  return base_addr, offset, elem_size
@@ -152,7 +144,7 @@ class SimEngineVRBase(
152
144
  # extract stack offset
153
145
  stack_offset: int | None = self.state.get_stack_offset(data)
154
146
 
155
- variable_manager = self.variable_manager[self.func_addr]
147
+ variable_manager = self.state.variable_manager[self.func_addr]
156
148
  var_candidates: list[tuple[SimVariable, int]] = variable_manager.find_variables_by_stmt(
157
149
  self.block.addr, self.stmt_idx, "memory"
158
150
  )
@@ -190,10 +182,10 @@ class SimEngineVRBase(
190
182
  stack_offset,
191
183
  lea_size,
192
184
  base="bp",
193
- ident=self.variable_manager[self.func_addr].next_variable_ident("stack"),
185
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("stack"),
194
186
  region=self.func_addr,
195
187
  )
196
- self.variable_manager[self.func_addr].add_variable("stack", stack_offset, variable)
188
+ self.state.variable_manager[self.func_addr].add_variable("stack", stack_offset, variable)
197
189
  l.debug("Identified a new stack variable %s at %#x.", variable, self.ins_addr)
198
190
  existing_vars.append((variable, 0))
199
191
 
@@ -212,7 +204,7 @@ class SimEngineVRBase(
212
204
  # this is probably an address for a global variable
213
205
  global_var_addr = data.concrete_value
214
206
 
215
- variable_manager = self.variable_manager["global"]
207
+ variable_manager = self.state.variable_manager["global"]
216
208
 
217
209
  # special case for global variables: find existing variable by base address
218
210
  existing_vars = [(var, 0) for var in variable_manager.get_global_variables(global_var_addr)]
@@ -249,7 +241,7 @@ class SimEngineVRBase(
249
241
  # extract stack offset
250
242
  stack_offset: int | None = self.state.get_stack_offset(data)
251
243
 
252
- variable_manager = self.variable_manager[self.func_addr]
244
+ variable_manager = self.state.variable_manager[self.func_addr]
253
245
  var_candidates: list[tuple[SimVariable, int]] = variable_manager.find_variables_by_stmt(
254
246
  self.block.addr,
255
247
  self.stmt_idx,
@@ -265,7 +257,7 @@ class SimEngineVRBase(
265
257
  elif self.state.is_global_variable_address(data):
266
258
  # this is probably an address for a global variable
267
259
  global_var_addr = data.concrete_value
268
- variable_manager = self.variable_manager["global"]
260
+ variable_manager = self.state.variable_manager["global"]
269
261
  # special case for global variables: find existing variable by base address
270
262
  existing_vars = [(var, 0) for var in variable_manager.get_global_variables(global_var_addr)]
271
263
  else:
@@ -319,9 +311,9 @@ class SimEngineVRBase(
319
311
  # handle register writes
320
312
 
321
313
  # first check if there is an existing variable for the atom at this location already
322
- existing_vars: set[tuple[SimVariable, int]] = self.variable_manager[self.func_addr].find_variables_by_atom(
323
- self.block.addr, self.stmt_idx, dst
324
- )
314
+ existing_vars: set[tuple[SimVariable, int]] = self.state.variable_manager[
315
+ self.func_addr
316
+ ].find_variables_by_atom(self.block.addr, self.stmt_idx, dst)
325
317
  if not existing_vars:
326
318
  # next check if we are overwriting *part* of an existing variable that is not an input variable
327
319
  addr_and_variables = set()
@@ -334,7 +326,7 @@ class SimEngineVRBase(
334
326
  addr_and_variables.update(self.state.extract_variables(value))
335
327
  except SimMemoryMissingError:
336
328
  pass
337
- input_vars = self.variable_manager[self.func_addr].input_variables()
329
+ input_vars = self.state.variable_manager[self.func_addr].input_variables()
338
330
  existing_vars = {
339
331
  (av[1], av[0]) for av in addr_and_variables if av[1] not in input_vars and av[1].size > size
340
332
  }
@@ -343,10 +335,10 @@ class SimEngineVRBase(
343
335
  variable = SimRegisterVariable(
344
336
  offset,
345
337
  size,
346
- ident=self.variable_manager[self.func_addr].next_variable_ident("register"),
338
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("register"),
347
339
  region=self.func_addr,
348
340
  )
349
- self.variable_manager[self.func_addr].add_variable("register", offset, variable)
341
+ self.state.variable_manager[self.func_addr].add_variable("register", offset, variable)
350
342
  else:
351
343
  variable, _ = next(iter(existing_vars))
352
344
 
@@ -355,7 +347,7 @@ class SimEngineVRBase(
355
347
  v = MultiValues(annotated_data)
356
348
  self.state.register_region.store(offset, v)
357
349
  # register with the variable manager
358
- self.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
350
+ self.state.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
359
351
 
360
352
  if richr.typevar is not None:
361
353
  if not self.state.typevars.has_type_variable_for(variable, codeloc):
@@ -397,9 +389,9 @@ class SimEngineVRBase(
397
389
  self._reference(richr, codeloc)
398
390
 
399
391
  # first check if there is an existing variable for the atom at this location already
400
- existing_vars: set[tuple[SimVariable, int]] = self.variable_manager[self.func_addr].find_variables_by_atom(
401
- self.block.addr, self.stmt_idx, dst
402
- )
392
+ existing_vars: set[tuple[SimVariable, int]] = self.state.variable_manager[
393
+ self.func_addr
394
+ ].find_variables_by_atom(self.block.addr, self.stmt_idx, dst)
403
395
  if not existing_vars:
404
396
  # next check if there is already a variable for the vvar ID
405
397
  addr_and_variables = set()
@@ -415,33 +407,33 @@ class SimEngineVRBase(
415
407
  variable = SimRegisterVariable(
416
408
  vvar.reg_offset,
417
409
  vvar.size,
418
- ident=self.variable_manager[self.func_addr].next_variable_ident("register"),
410
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("register"),
419
411
  region=self.func_addr,
420
412
  )
421
- self.variable_manager[self.func_addr].add_variable("register", vvar.reg_offset, variable)
413
+ self.state.variable_manager[self.func_addr].add_variable("register", vvar.reg_offset, variable)
422
414
  elif vvar.was_stack:
423
415
  variable = SimStackVariable(
424
416
  vvar.stack_offset,
425
417
  vvar.size,
426
- ident=self.variable_manager[self.func_addr].next_variable_ident("stack"),
418
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("stack"),
427
419
  region=self.func_addr,
428
420
  )
429
- self.variable_manager[self.func_addr].add_variable("stack", vvar.stack_offset, variable)
421
+ self.state.variable_manager[self.func_addr].add_variable("stack", vvar.stack_offset, variable)
430
422
  elif vvar.was_parameter:
431
423
  # FIXME: we assume all parameter vvars were registers
432
424
  variable = SimRegisterVariable(
433
425
  vvar.reg_offset,
434
426
  vvar.size,
435
- ident=self.variable_manager[self.func_addr].next_variable_ident("register"),
427
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("register"),
436
428
  region=self.func_addr,
437
429
  )
438
- self.variable_manager[self.func_addr].add_variable("register", vvar.oident, variable)
430
+ self.state.variable_manager[self.func_addr].add_variable("register", vvar.oident, variable)
439
431
  elif vvar.was_tmp:
440
432
  # FIXME: we treat all tmp vvars as registers
441
433
  variable = SimRegisterVariable(
442
434
  4096 + vvar.tmp_idx,
443
435
  vvar.size,
444
- ident=self.variable_manager[self.func_addr].next_variable_ident("register"),
436
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("register"),
445
437
  region=self.func_addr,
446
438
  )
447
439
  else:
@@ -452,7 +444,7 @@ class SimEngineVRBase(
452
444
  # FIXME: The offset does not have to be 0
453
445
  annotated_data = self.state.annotate_with_variables(data, [(0, variable)])
454
446
  self.vvar_region[vvar_id] = annotated_data
455
- self.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
447
+ self.state.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
456
448
 
457
449
  if richr.typevar is not None:
458
450
  if not self.state.typevars.has_type_variable_for(variable, codeloc):
@@ -502,13 +494,13 @@ class SimEngineVRBase(
502
494
 
503
495
  if not stored:
504
496
  # remove existing variables linked to this statement
505
- existing_vars = self.variable_manager[self.func_addr].find_variables_by_stmt(
497
+ existing_vars = self.state.variable_manager[self.func_addr].find_variables_by_stmt(
506
498
  self.block.addr, self.stmt_idx, "memory"
507
499
  )
508
500
  codeloc = self._codeloc()
509
501
  if existing_vars:
510
502
  for existing_var, _ in list(existing_vars):
511
- self.variable_manager[self.func_addr].remove_variable_by_atom(codeloc, existing_var, atom)
503
+ self.state.variable_manager[self.func_addr].remove_variable_by_atom(codeloc, existing_var, atom)
512
504
 
513
505
  # storing to a location specified by a pointer whose value cannot be determined at this point
514
506
  self._store_to_variable(richr_addr, size)
@@ -517,11 +509,11 @@ class SimEngineVRBase(
517
509
  self, stack_offset, data: RichR[claripy.ast.BV | claripy.ast.FP], size, offset=0, atom=None, endness=None
518
510
  ):
519
511
  if atom is None:
520
- existing_vars = self.variable_manager[self.func_addr].find_variables_by_stmt(
512
+ existing_vars = self.state.variable_manager[self.func_addr].find_variables_by_stmt(
521
513
  self.block.addr, self.stmt_idx, "memory"
522
514
  )
523
515
  else:
524
- existing_vars = self.variable_manager[self.func_addr].find_variables_by_atom(
516
+ existing_vars = self.state.variable_manager[self.func_addr].find_variables_by_atom(
525
517
  self.block.addr, self.stmt_idx, atom
526
518
  )
527
519
  if not existing_vars:
@@ -529,12 +521,12 @@ class SimEngineVRBase(
529
521
  stack_offset,
530
522
  size,
531
523
  base="bp",
532
- ident=self.variable_manager[self.func_addr].next_variable_ident("stack"),
524
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("stack"),
533
525
  region=self.func_addr,
534
526
  )
535
527
  variable_offset = offset
536
528
  if isinstance(stack_offset, int):
537
- self.variable_manager[self.func_addr].set_variable("stack", stack_offset, variable)
529
+ self.state.variable_manager[self.func_addr].set_variable("stack", stack_offset, variable)
538
530
  l.debug("Identified a new stack variable %s at %#x.", variable, self.ins_addr)
539
531
 
540
532
  else:
@@ -562,7 +554,7 @@ class SimEngineVRBase(
562
554
  offset_into_var = var_offset
563
555
  if offset_into_var == 0:
564
556
  offset_into_var = None
565
- self.variable_manager[self.func_addr].write_to(
557
+ self.state.variable_manager[self.func_addr].write_to(
566
558
  var,
567
559
  offset_into_var,
568
560
  codeloc,
@@ -589,7 +581,7 @@ class SimEngineVRBase(
589
581
  offset: claripy.ast.BV | None = None,
590
582
  elem_size: int | None = None,
591
583
  ):
592
- variable_manager = self.variable_manager["global"]
584
+ variable_manager = self.state.variable_manager["global"]
593
585
  if stmt is None:
594
586
  existing_vars = variable_manager.find_variables_by_stmt(self.block.addr, self.stmt_idx, "memory")
595
587
  else:
@@ -696,9 +688,6 @@ class SimEngineVRBase(
696
688
  base_typevar = typevar
697
689
  field_offset = 0
698
690
 
699
- # if addr_variable is not None:
700
- # self.variable_manager[self.func_addr].reference_at(addr_variable, field_offset, codeloc, atom=stmt)
701
-
702
691
  store_typevar = self._create_access_typevar(base_typevar, True, size, field_offset)
703
692
  if addr_variable is not None:
704
693
  self.state.typevars.add_type_variable(addr_variable, codeloc, typevar)
@@ -766,16 +755,18 @@ class SimEngineVRBase(
766
755
  all_vars.add((var_offset, var_))
767
756
 
768
757
  if not all_vars and concrete_offset is not None:
769
- variables = self.variable_manager[self.func_addr].find_variables_by_stack_offset(concrete_offset)
758
+ variables = self.state.variable_manager[self.func_addr].find_variables_by_stack_offset(
759
+ concrete_offset
760
+ )
770
761
  if not variables:
771
762
  variable = SimStackVariable(
772
763
  concrete_offset,
773
764
  size,
774
765
  base="bp",
775
- ident=self.variable_manager[self.func_addr].next_variable_ident("stack"),
766
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("stack"),
776
767
  region=self.func_addr,
777
768
  )
778
- self.variable_manager[self.func_addr].add_variable("stack", concrete_offset, variable)
769
+ self.state.variable_manager[self.func_addr].add_variable("stack", concrete_offset, variable)
779
770
  variables = {variable}
780
771
  l.debug("Identified a new stack variable %s at %#x.", variable, self.ins_addr)
781
772
  for variable in variables:
@@ -814,7 +805,7 @@ class SimEngineVRBase(
814
805
  var_offset,
815
806
  ),
816
807
  )
817
- self.variable_manager[self.func_addr].read_from(
808
+ self.state.variable_manager[self.func_addr].read_from(
818
809
  var,
819
810
  offset_into_variable,
820
811
  codeloc,
@@ -864,12 +855,12 @@ class SimEngineVRBase(
864
855
  if v is None and expr is not None:
865
856
  # failed to map the address to a known variable
866
857
  # remove existing variables linked to this variable
867
- existing_vars = self.variable_manager[self.func_addr].find_variables_by_atom(
858
+ existing_vars = self.state.variable_manager[self.func_addr].find_variables_by_atom(
868
859
  self.block.addr, self.stmt_idx, expr
869
860
  )
870
861
  if existing_vars:
871
862
  for existing_var, _ in list(existing_vars):
872
- self.variable_manager[self.func_addr].remove_variable_by_atom(codeloc, existing_var, expr)
863
+ self.state.variable_manager[self.func_addr].remove_variable_by_atom(codeloc, existing_var, expr)
873
864
 
874
865
  # Loading data from a pointer
875
866
  if richr_addr.type_constraints:
@@ -901,7 +892,7 @@ class SimEngineVRBase(
901
892
  offset: claripy.ast.BV | None = None,
902
893
  elem_size: int | None = None,
903
894
  ) -> RichR[claripy.ast.BV]:
904
- variable_manager = self.variable_manager["global"]
895
+ variable_manager = self.state.variable_manager["global"]
905
896
  if expr is None:
906
897
  existing_vars = variable_manager.find_variables_by_stmt(self.block.addr, self.stmt_idx, "memory")
907
898
  else:
@@ -992,11 +983,11 @@ class SimEngineVRBase(
992
983
  variable = SimRegisterVariable(
993
984
  offset,
994
985
  size if force_variable_size is None else force_variable_size,
995
- ident=self.variable_manager[self.func_addr].next_variable_ident("register"),
986
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("register"),
996
987
  region=self.func_addr,
997
988
  )
998
989
  value = self.state.annotate_with_variables(value, [(0, variable)])
999
- self.variable_manager[self.func_addr].add_variable("register", offset, variable)
990
+ self.state.variable_manager[self.func_addr].add_variable("register", offset, variable)
1000
991
  self.state.register_region.store(offset, value)
1001
992
  value_list = [{value}]
1002
993
  else:
@@ -1006,7 +997,9 @@ class SimEngineVRBase(
1006
997
  for value_set in value_list:
1007
998
  for value in value_set:
1008
999
  for _, var in self.state.extract_variables(value):
1009
- self.variable_manager[self.func_addr].read_from(var, None, codeloc, atom=expr, overwrite=False)
1000
+ self.state.variable_manager[self.func_addr].read_from(
1001
+ var, None, codeloc, atom=expr, overwrite=False
1002
+ )
1010
1003
  variable_set.add(var)
1011
1004
 
1012
1005
  if offset == self.project.arch.sp_offset:
@@ -1078,20 +1071,20 @@ class SimEngineVRBase(
1078
1071
  variable = SimRegisterVariable(
1079
1072
  vvar.reg_offset,
1080
1073
  vvar.size,
1081
- ident=self.variable_manager[self.func_addr].next_variable_ident("register"),
1074
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("register"),
1082
1075
  region=self.func_addr,
1083
1076
  )
1084
1077
  value = self.state.annotate_with_variables(value, [(0, variable)])
1085
- self.variable_manager[self.func_addr].add_variable("register", vvar.reg_offset, variable)
1078
+ self.state.variable_manager[self.func_addr].add_variable("register", vvar.reg_offset, variable)
1086
1079
  elif vvar.category == ailment.Expr.VirtualVariableCategory.STACK:
1087
1080
  variable = SimStackVariable(
1088
1081
  vvar.stack_offset,
1089
1082
  vvar.size,
1090
- ident=self.variable_manager[self.func_addr].next_variable_ident("stack"),
1083
+ ident=self.state.variable_manager[self.func_addr].next_variable_ident("stack"),
1091
1084
  region=self.func_addr,
1092
1085
  )
1093
1086
  value = self.state.annotate_with_variables(value, [(0, variable)])
1094
- self.variable_manager[self.func_addr].add_variable("stack", vvar.stack_offset, variable)
1087
+ self.state.variable_manager[self.func_addr].add_variable("stack", vvar.stack_offset, variable)
1095
1088
  elif vvar.category == ailment.Expr.VirtualVariableCategory.PARAMETER:
1096
1089
  raise KeyError(f"Missing virtual variable for parameter {vvar}")
1097
1090
  elif vvar.category == ailment.Expr.VirtualVariableCategory.TMP:
@@ -1104,7 +1097,7 @@ class SimEngineVRBase(
1104
1097
 
1105
1098
  variable_set = set()
1106
1099
  for _, var in self.state.extract_variables(value):
1107
- self.variable_manager[self.func_addr].read_from(var, None, codeloc, atom=expr, overwrite=False)
1100
+ self.state.variable_manager[self.func_addr].read_from(var, None, codeloc, atom=expr, overwrite=False)
1108
1101
  variable_set.add(var)
1109
1102
 
1110
1103
  if (
@@ -51,7 +51,7 @@ class SimEngineVRVEX(
51
51
 
52
52
  def _process_block(self, whitelist=None):
53
53
  scanner = VEXIRSBScanner(self.project, logger=self.l)
54
- scanner._process(None, block=self.block)
54
+ scanner.process(None, block=self.block)
55
55
  self.stmts_to_lower = scanner.stmts_to_lower
56
56
  self.reg_read_stmts_to_ignore = scanner.reg_read_stmts_to_ignore
57
57
 
@@ -39,12 +39,12 @@ class VEXIRSBScanner(SimEngineLightVEX[None, None, None, None]):
39
39
  def _is_top(self, expr) -> bool:
40
40
  return True
41
41
 
42
- def _process(self, state, *, block=None, whitelist=None, **kwargs):
42
+ def process(self, state, *, block=None, whitelist=None, **kwargs):
43
43
  self.tmps_with_64bit_regs = set()
44
44
  self.tmps_assignment_stmtidx = {}
45
45
  self.tmps_converted_to_32bit = set()
46
46
 
47
- super()._process(state, block=block, whitelist=whitelist, **kwargs)
47
+ super().process(state, block=block, whitelist=whitelist, **kwargs)
48
48
 
49
49
  self.stmts_to_lower = {self.tmps_assignment_stmtidx[i] for i in self.tmps_converted_to_32bit}
50
50
 
@@ -11,6 +11,7 @@ import archinfo
11
11
  from archinfo import RegisterName
12
12
  from unique_log_filter import UniqueLogFilter
13
13
 
14
+ import angr
14
15
  from .errors import AngrTypeError
15
16
  from .sim_type import (
16
17
  SimType,
@@ -33,7 +34,6 @@ from .sim_type import (
33
34
  SimTypeReference,
34
35
  )
35
36
  from .state_plugins.sim_action_object import SimActionObject
36
- from .engines.soot.engine import SootMixin
37
37
 
38
38
  l = logging.getLogger(name=__name__)
39
39
  l.addFilter(UniqueLogFilter())
@@ -307,7 +307,7 @@ class SimRegArg(SimFunctionArgument):
307
307
  def __hash__(self):
308
308
  return hash((self.size, self.reg_name, self.reg_offset))
309
309
 
310
- def check_offset(self, arch):
310
+ def check_offset(self, arch) -> int:
311
311
  return arch.registers[self.reg_name][0] + self.reg_offset
312
312
 
313
313
  def set_value(self, state, value, **kwargs): # pylint: disable=unused-argument,arguments-differ
@@ -582,7 +582,12 @@ class SimCC:
582
582
  FP_RETURN_VAL: SimFunctionArgument | None = (
583
583
  None # The location where floating-point argument return values are stored
584
584
  )
585
- ARCH = None # The archinfo.Arch class that this CC must be used for, if relevant
585
+ ARCH: type[archinfo.Arch] | None = (
586
+ None # The archinfo.Arch class for which this CC is most likely relevant, if related
587
+ )
588
+ # archinfo.Arch classes for which this CC is relevant, in addition to self.ARCH.
589
+ # you should access cls.arches() to get a list of all arches for which this CC is relevant
590
+ EXTRA_ARCHES: tuple[type[archinfo.Arch], ...] = ()
586
591
  CALLEE_CLEANUP = False # Whether the callee has to deallocate the stack space for the arguments
587
592
 
588
593
  STACK_ALIGNMENT = 1 # the alignment requirement of the stack pointer at function start BEFORE call
@@ -1082,8 +1087,8 @@ class SimCC:
1082
1087
 
1083
1088
  @classmethod
1084
1089
  def _match(cls, arch, args: list, sp_delta):
1085
- if cls.ARCH is not None and not isinstance(
1086
- arch, cls.ARCH
1090
+ if (
1091
+ cls.arches() is not None and ":" not in arch.name and not isinstance(arch, cls.arches())
1087
1092
  ): # pylint:disable=isinstance-second-argument-not-valid-type
1088
1093
  return False
1089
1094
  if sp_delta != cls.STACKARG_SP_DIFF:
@@ -1149,6 +1154,12 @@ class SimCC:
1149
1154
  return cc_cls(arch)
1150
1155
  return None
1151
1156
 
1157
+ @classmethod
1158
+ def arches(cls) -> tuple[type[archinfo.Arch], ...]:
1159
+ if cls.ARCH is not None:
1160
+ return (cls.ARCH, *cls.EXTRA_ARCHES)
1161
+ return cls.EXTRA_ARCHES
1162
+
1152
1163
  def get_arg_info(self, state, prototype):
1153
1164
  """
1154
1165
  This is just a simple wrapper that collects the information from various locations
@@ -1444,7 +1455,7 @@ class SimCCSystemVAMD64(SimCC):
1444
1455
 
1445
1456
  @classmethod
1446
1457
  def _match(cls, arch, args, sp_delta):
1447
- if cls.ARCH is not None and not isinstance(arch, cls.ARCH):
1458
+ if cls.ARCH is not None and ":" not in arch.name and not isinstance(arch, cls.ARCH):
1448
1459
  return False
1449
1460
  # if sp_delta != cls.STACKARG_SP_DIFF:
1450
1461
  # return False
@@ -1789,8 +1800,54 @@ class SimCCARMHF(SimCCARM):
1789
1800
  FP_RETURN_VAL = SimRegArg("s0", 32)
1790
1801
  CALLER_SAVED_REGS = []
1791
1802
  RETURN_ADDR = SimRegArg("lr", 4)
1792
- RETURN_VAL = SimRegArg("r0", 4) # TODO Return val can also include reg r1
1803
+ RETURN_VAL = SimRegArg("r0", 4)
1804
+ OVERFLOW_RETURN_VAL = SimRegArg("r1", 4)
1793
1805
  ARCH = archinfo.ArchARMHF
1806
+ EXTRA_ARCHES = (archinfo.ArchARMCortexM,)
1807
+
1808
+ def next_arg(self, session, arg_type):
1809
+ if isinstance(arg_type, (SimTypeArray, SimTypeFixedSizeArray)): # hack
1810
+ arg_type = SimTypePointer(arg_type.elem_type).with_arch(self.arch)
1811
+ state = session.getstate()
1812
+ classification = self._classify(arg_type)
1813
+ try:
1814
+ mapped_classes = []
1815
+ for cls in classification:
1816
+ if cls == "DOUBLEP":
1817
+ if session.getstate()[1] % 2 == 1: # doubles must start on an even register
1818
+ next(session.int_iter)
1819
+
1820
+ if session.getstate()[1] == len(self.ARG_REGS) - 2:
1821
+ mapped_classes.append(next(session.int_iter))
1822
+ mapped_classes.append(next(session.both_iter))
1823
+ else:
1824
+ try:
1825
+ mapped_classes.append(next(session.int_iter))
1826
+ mapped_classes.append(next(session.int_iter))
1827
+ except StopIteration:
1828
+ mapped_classes.append(next(session.both_iter))
1829
+ mapped_classes.append(next(session.both_iter))
1830
+ elif cls == "NO_CLASS":
1831
+ raise NotImplementedError("Bug. Report to @rhelmot")
1832
+ elif cls == "MEMORY":
1833
+ mapped_classes.append(next(session.both_iter))
1834
+ elif cls == "INTEGER":
1835
+ try:
1836
+ mapped_classes.append(next(session.int_iter))
1837
+ except StopIteration:
1838
+ mapped_classes.append(next(session.both_iter))
1839
+ elif cls == "SINGLEP":
1840
+ try:
1841
+ mapped_classes.append(next(session.fp_iter))
1842
+ except StopIteration:
1843
+ mapped_classes.append(next(session.both_iter))
1844
+ else:
1845
+ raise NotImplementedError("Bug. Report to @rhelmot")
1846
+ except StopIteration:
1847
+ session.setstate(state)
1848
+ mapped_classes = [next(session.both_iter) for _ in classification]
1849
+
1850
+ return refine_locs_with_struct_type(self.arch, mapped_classes, arg_type)
1794
1851
 
1795
1852
 
1796
1853
  class SimCCARMLinuxSyscall(SimCCSyscall):
@@ -2122,7 +2179,7 @@ class SimCCSoot(SimCC):
2122
2179
  ARG_REGS = []
2123
2180
 
2124
2181
  def setup_callsite(self, state, ret_addr, args, prototype, stack_base=None, alloc_base=None, grow_like_stack=True):
2125
- SootMixin.setup_callsite(state, args, ret_addr)
2182
+ angr.engines.SootMixin.setup_callsite(state, args, ret_addr)
2126
2183
 
2127
2184
  @staticmethod
2128
2185
  def guess_prototype(args, prototype=None):
@@ -2226,7 +2283,7 @@ DEFAULT_CC: dict[str, dict[str, type[SimCC]]] = {
2226
2283
  "X86": {"Linux": SimCCCdecl, "CGC": SimCCCdecl, "Win32": SimCCMicrosoftCdecl},
2227
2284
  "ARMEL": {"Linux": SimCCARM},
2228
2285
  "ARMHF": {"Linux": SimCCARMHF},
2229
- "ARMCortexM": {"Linux": SimCCARM},
2286
+ "ARMCortexM": {"Linux": SimCCARMHF},
2230
2287
  "MIPS32": {"Linux": SimCCO32},
2231
2288
  "MIPS64": {"Linux": SimCCN64},
2232
2289
  "PPC32": {"Linux": SimCCPowerPC},
angr/engines/engine.py CHANGED
@@ -24,10 +24,9 @@ DataType_co = TypeVar("DataType_co", covariant=True)
24
24
  HeavyState = SimState[int | SootAddressDescriptor, claripy.ast.BV | SootAddressDescriptor]
25
25
 
26
26
 
27
- class SimEngineBase(Generic[StateType]):
27
+ class SimEngine(Generic[StateType, ResultType], metaclass=abc.ABCMeta):
28
28
  """
29
- Even more basey of a base class for SimEngine. Used as a base by mixins which want access to the project but for
30
- which having method `process` (contained in `SimEngine`) doesn't make sense
29
+ A SimEngine is a type which understands how to perform execution on a state.
31
30
  """
32
31
 
33
32
  state: StateType
@@ -43,21 +42,6 @@ class SimEngineBase(Generic[StateType]):
43
42
  self.project = state[0]
44
43
 
45
44
 
46
- class SimEngine(Generic[StateType, ResultType], SimEngineBase[StateType], metaclass=abc.ABCMeta):
47
- """
48
- A SimEngine is a class which understands how to perform execution on a state. This is a base class.
49
- """
50
-
51
- @abc.abstractmethod
52
- def process(self, state: StateType, **kwargs) -> ResultType:
53
- """
54
- The main entry point for an engine. Should take a state and return a result.
55
-
56
- :param state: The state to proceed from
57
- :return: The result. Whatever you want ;)
58
- """
59
-
60
-
61
45
  class SuccessorsMixin(SimEngine[HeavyState, SimSuccessors]):
62
46
  """
63
47
  A mixin for SimEngine which implements ``process`` to perform common operations related to symbolic execution
@@ -64,13 +64,8 @@ class SimEngineLight(Generic[StateType, DataType_co, BlockType, ResultType], Sim
64
64
  self.l = logger or logging.getLogger(self.__module__ + "." + self.__class__.__name__)
65
65
  super().__init__(project)
66
66
 
67
- # there's two of these to support the mixin pattern - mixins can override process while there must be some base
68
- # class that provides _process
69
- def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType:
70
- return self._process(state, block=block, **kwargs)
71
-
72
67
  @abstractmethod
73
- def _process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType: ...
68
+ def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType: ...
74
69
 
75
70
  def lift(self, state: StateType) -> BlockType:
76
71
  raise TypeError(f"{type(self)} requires `block` to be passed to `process`")
@@ -267,7 +262,7 @@ class SimEngineLightVEX(
267
262
  if name.startswith("_handle_dirty_")
268
263
  }
269
264
 
270
- def _process(
265
+ def process(
271
266
  self, state: StateType, *, block: Block | None = None, whitelist: set[int] | None = None, **kwargs
272
267
  ) -> ResultType:
273
268
  # initialize local variables
@@ -640,7 +635,7 @@ class SimEngineLightAIL(
640
635
  }
641
636
  super().__init__(*args, **kwargs)
642
637
 
643
- def _process(
638
+ def process(
644
639
  self, state: StateType, *, block: ailment.Block | None = None, whitelist: set[int] | None = None, **kwargs
645
640
  ) -> ResultType:
646
641
  self.tmps = {}
@@ -4,7 +4,7 @@ import logging
4
4
  import claripy
5
5
  from claripy.ast.bv import BV
6
6
 
7
- from angr.engines.engine import SimEngineBase
7
+ from angr.engines.engine import SimEngine
8
8
  from angr.utils.constants import DEFAULT_STATEMENT
9
9
  from .lifter import IRSB
10
10
  from .behavior import OpBehavior
@@ -19,7 +19,7 @@ with contextlib.suppress(ImportError):
19
19
  l = logging.getLogger(__name__)
20
20
 
21
21
 
22
- class PcodeEmulatorMixin(SimEngineBase):
22
+ class PcodeEmulatorMixin(SimEngine):
23
23
  """
24
24
  Mixin for p-code execution.
25
25
  """
@@ -20,7 +20,7 @@ from cachetools import LRUCache
20
20
  from pyvex.errors import PyVEXError, SkipStatementsError, LiftingException
21
21
 
22
22
  from .behavior import BehaviorFactory
23
- from angr.engines.engine import SimEngineBase
23
+ from angr.engines.engine import SimEngine
24
24
  from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
25
25
  from angr.sim_state import SimState
26
26
  from angr.misc.ux import once
@@ -981,7 +981,7 @@ class PcodeLifter(Lifter):
981
981
  raise LiftingException(f"pypcode: could not decode any instructions @ 0x{self.addr:x}")
982
982
 
983
983
 
984
- class PcodeLifterEngineMixin(SimEngineBase):
984
+ class PcodeLifterEngineMixin(SimEngine):
985
985
  """
986
986
  Lifter mixin to lift from machine code to P-Code.
987
987
  """