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.

Files changed (58) 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/decompiler.py +19 -17
  7. angr/analyses/decompiler/goto_manager.py +34 -51
  8. angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
  9. angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
  10. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
  11. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
  12. angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
  13. angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
  14. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
  15. angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
  16. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
  17. angr/analyses/decompiler/region_identifier.py +8 -2
  18. angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
  19. angr/analyses/decompiler/structured_codegen/c.py +33 -1
  20. angr/analyses/decompiler/structuring/phoenix.py +3 -1
  21. angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
  22. angr/analyses/decompiler/utils.py +50 -0
  23. angr/analyses/disassembly.py +10 -3
  24. angr/analyses/propagator/engine_ail.py +125 -0
  25. angr/analyses/reaching_definitions/engine_ail.py +36 -2
  26. angr/analyses/reaching_definitions/rd_initializer.py +15 -1
  27. angr/analyses/reaching_definitions/rd_state.py +9 -4
  28. angr/analyses/stack_pointer_tracker.py +10 -17
  29. angr/analyses/variable_recovery/engine_ail.py +27 -1
  30. angr/angrdb/serializers/loader.py +10 -3
  31. angr/calling_conventions.py +2 -0
  32. angr/engines/pcode/behavior.py +7 -2
  33. angr/engines/pcode/cc.py +1 -0
  34. angr/engines/pcode/emulate.py +144 -104
  35. angr/engines/pcode/lifter.py +135 -79
  36. angr/knowledge_plugins/functions/function_manager.py +5 -3
  37. angr/knowledge_plugins/propagations/states.py +14 -0
  38. angr/lib/angr_native.dll +0 -0
  39. angr/procedures/cgc/deallocate.py +5 -2
  40. angr/procedures/posix/gethostbyname.py +23 -8
  41. angr/project.py +4 -0
  42. angr/simos/__init__.py +2 -0
  43. angr/simos/simos.py +1 -0
  44. angr/simos/snimmuc_nxp.py +152 -0
  45. angr/state_plugins/history.py +3 -1
  46. angr/utils/graph.py +20 -18
  47. {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
  48. {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/RECORD +57 -55
  49. tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
  50. tests/analyses/cfg/test_jumptables.py +2 -1
  51. tests/analyses/decompiler/test_decompiler.py +130 -103
  52. tests/engines/pcode/test_emulate.py +607 -0
  53. tests/serialization/test_db.py +30 -0
  54. angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
  55. {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
  56. {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
  57. {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
  58. {angr-9.2.84.dist-info → angr-9.2.85.dist-info}/top_level.txt +0 -0
@@ -2,10 +2,12 @@
2
2
  from typing import Optional, Dict, List, Tuple, Set, Any, Union, TYPE_CHECKING, Callable
3
3
  from collections import defaultdict
4
4
  import logging
5
+ import struct
5
6
  from functools import reduce
6
7
 
7
8
  from ailment import Block, Expr, Stmt, Tmp
8
9
  from ailment.expression import StackBaseOffset, BinaryOp
10
+ from unique_log_filter import UniqueLogFilter
9
11
 
10
12
  from ....sim_type import (
11
13
  SimTypeLongLong,
@@ -57,6 +59,8 @@ if TYPE_CHECKING:
57
59
 
58
60
 
59
61
  l = logging.getLogger(name=__name__)
62
+ l.addFilter(UniqueLogFilter())
63
+
60
64
 
61
65
  INDENT_DELTA = 4
62
66
 
@@ -1728,6 +1732,7 @@ class CBinaryOp(CExpression):
1728
1732
  # lowest precedence
1729
1733
  ["Concat"],
1730
1734
  ["LogicalOr"],
1735
+ ["LogicalXor"],
1731
1736
  ["LogicalAnd"],
1732
1737
  ["Or"],
1733
1738
  ["Xor"],
@@ -1737,6 +1742,7 @@ class CBinaryOp(CExpression):
1737
1742
  ["Shl", "Shr", "Sar"],
1738
1743
  ["Add", "Sub"],
1739
1744
  ["Mul", "Div"],
1745
+ ["SBorrow", "SCarry", "Carry"],
1740
1746
  # highest precedence
1741
1747
  ]
1742
1748
  for i, sublist in enumerate(precedence_list):
@@ -1765,6 +1771,7 @@ class CBinaryOp(CExpression):
1765
1771
  "Sar": self._c_repr_chunks_sar,
1766
1772
  "LogicalAnd": self._c_repr_chunks_logicaland,
1767
1773
  "LogicalOr": self._c_repr_chunks_logicalor,
1774
+ "LogicalXor": self._c_repr_chunks_logicalxor,
1768
1775
  "CmpLE": self._c_repr_chunks_cmple,
1769
1776
  "CmpLEs": self._c_repr_chunks_cmple,
1770
1777
  "CmpLT": self._c_repr_chunks_cmplt,
@@ -1784,7 +1791,7 @@ class CBinaryOp(CExpression):
1784
1791
  if handler is not None:
1785
1792
  yield from handler()
1786
1793
  else:
1787
- yield "BinaryOp %s" % (self.op), self
1794
+ yield from self._c_repr_chunks_opfirst(self.op)
1788
1795
 
1789
1796
  def _has_const_null_rhs(self) -> bool:
1790
1797
  return isinstance(self.rhs, CConstant) and self.rhs.value == 0
@@ -1825,6 +1832,15 @@ class CBinaryOp(CExpression):
1825
1832
  else:
1826
1833
  yield from self._try_c_repr_chunks(self.rhs)
1827
1834
 
1835
+ def _c_repr_chunks_opfirst(self, op):
1836
+ yield op, self
1837
+ paren = CClosingObject("(")
1838
+ yield "(", paren
1839
+ yield from self._try_c_repr_chunks(self.lhs)
1840
+ yield ", ", None
1841
+ yield from self._try_c_repr_chunks(self.rhs)
1842
+ yield ")", paren
1843
+
1828
1844
  def _c_repr_chunks_add(self):
1829
1845
  yield from self._c_repr_chunks(" + ")
1830
1846
 
@@ -1870,6 +1886,9 @@ class CBinaryOp(CExpression):
1870
1886
  def _c_repr_chunks_logicalor(self):
1871
1887
  yield from self._c_repr_chunks(" || ")
1872
1888
 
1889
+ def _c_repr_chunks_logicalxor(self):
1890
+ yield from self._c_repr_chunks(" ^ ")
1891
+
1873
1892
  def _c_repr_chunks_cmple(self):
1874
1893
  yield from self._c_repr_chunks(" <= ")
1875
1894
 
@@ -2030,6 +2049,14 @@ class CConstant(CExpression):
2030
2049
  def fmt_char(self, v: bool):
2031
2050
  self._fmt_setter["char"] = v
2032
2051
 
2052
+ @property
2053
+ def fmt_float(self):
2054
+ return self.fmt.get("float", False)
2055
+
2056
+ @fmt_float.setter
2057
+ def fmt_float(self, v: bool):
2058
+ self._fmt_setter["float"] = v
2059
+
2033
2060
  @property
2034
2061
  def type(self):
2035
2062
  return self._type
@@ -2114,6 +2141,11 @@ class CConstant(CExpression):
2114
2141
  :return: The formatted string.
2115
2142
  """
2116
2143
 
2144
+ if self.fmt_float:
2145
+ if 0 < value <= 0xFFFF_FFFF:
2146
+ str_value = str(struct.unpack("f", struct.pack("I", value))[0])
2147
+ return str_value
2148
+
2117
2149
  if self.fmt_neg:
2118
2150
  if value > 0:
2119
2151
  value = value - 2**self._type.size
@@ -114,6 +114,8 @@ class PhoenixStructurer(StructurerBase):
114
114
  self._edge_virtualization_hints = []
115
115
 
116
116
  self._use_multistmtexprs = use_multistmtexprs
117
+ if not self._phoenix_improved:
118
+ self._use_multistmtexprs = MultiStmtExprMode.NEVER
117
119
 
118
120
  self._analyze()
119
121
 
@@ -2141,7 +2143,7 @@ class PhoenixStructurer(StructurerBase):
2141
2143
  pass
2142
2144
  else:
2143
2145
  # insert a Jump at the end
2144
- stmt_addr = last_stmt.ins_addr if last_stmt is not None else src.addr
2146
+ stmt_addr = src.addr
2145
2147
  goto_node = Block(
2146
2148
  stmt_addr,
2147
2149
  0,
@@ -3,6 +3,7 @@ from typing import List, Tuple, Any, Optional, Union, OrderedDict as ODict
3
3
 
4
4
  import claripy
5
5
  import ailment
6
+ import ailment.utils
6
7
 
7
8
 
8
9
  INDENT_DELTA = 2
@@ -387,11 +388,7 @@ class IncompleteSwitchCaseHeadStatement(ailment.statement.Statement):
387
388
  Describes a switch-case head. This is only created by LoweredSwitchSimplifier.
388
389
  """
389
390
 
390
- __slots__ = (
391
- "addr",
392
- "switch_variable",
393
- "case_addrs",
394
- )
391
+ __slots__ = ("addr", "switch_variable", "case_addrs", "_case_addrs_str")
395
392
 
396
393
  def __init__(self, idx, switch_variable, case_addrs, **kwargs):
397
394
  super().__init__(idx, **kwargs)
@@ -399,9 +396,18 @@ class IncompleteSwitchCaseHeadStatement(ailment.statement.Statement):
399
396
  # original cmp node, case value | "default", address of the case node, idx of the case node,
400
397
  # address of the next cmp node
401
398
  self.case_addrs: List[Tuple[ailment.Block, Union[int, str], int, Optional[int], int]] = case_addrs
399
+ # a string representation of the addresses of all cases, used for hashing
400
+ self._case_addrs_str = str(sorted([c[0].addr for c in self.case_addrs if c[0] is not None]))
402
401
 
403
402
  def __repr__(self):
404
403
  return f"SwitchCaseHead: switch {self.switch_variable} with {len(self.case_addrs)} cases"
405
404
 
406
405
  def __str__(self):
407
406
  return f"switch ({str(self.switch_variable)}): {len(self.case_addrs)} cases"
407
+
408
+ __hash__ = ailment.statement.TaggedObject.__hash__
409
+
410
+ def _hash_core(self):
411
+ return ailment.utils.stable_hash(
412
+ (IncompleteSwitchCaseHeadStatement, self.idx, self.switch_variable, self._case_addrs_str)
413
+ )
@@ -1,4 +1,6 @@
1
+ # pylint:disable=wrong-import-position
1
2
  import pathlib
3
+ import copy
2
4
  from typing import Optional, Tuple, Any, Union, List, Iterable
3
5
  import logging
4
6
 
@@ -378,6 +380,30 @@ def remove_labels(graph: networkx.DiGraph):
378
380
  return new_graph
379
381
 
380
382
 
383
+ def add_labels(graph: networkx.DiGraph):
384
+ new_graph = networkx.DiGraph()
385
+ nodes_map = {}
386
+ for node in graph:
387
+ lbl = ailment.Stmt.Label(None, f"LABEL_{node.addr:x}", node.addr, block_idx=node.idx)
388
+ node_copy = node.copy()
389
+ node_copy.statements = [lbl] + node_copy.statements
390
+ nodes_map[node] = node_copy
391
+
392
+ new_graph.add_nodes_from(nodes_map.values())
393
+ for src, dst in graph.edges:
394
+ new_graph.add_edge(nodes_map[src], nodes_map[dst])
395
+
396
+ return new_graph
397
+
398
+
399
+ def update_labels(graph: networkx.DiGraph):
400
+ """
401
+ A utility function to recreate the labels for every node in an AIL graph. This useful when you are working with
402
+ a graph where only _some_ of the nodes have labels.
403
+ """
404
+ return add_labels(remove_labels(graph))
405
+
406
+
381
407
  def structured_node_is_simple_return(node: Union["SequenceNode", "MultiNode"], graph: networkx.DiGraph) -> bool:
382
408
  """
383
409
  Will check if a "simple return" is contained within the node a simple returns looks like this:
@@ -510,6 +536,30 @@ def peephole_optimize_expr(expr, expr_opts):
510
536
  return new_expr
511
537
 
512
538
 
539
+ def copy_graph(graph: networkx.DiGraph):
540
+ """
541
+ Copy AIL Graph.
542
+
543
+ :return: A copy of the AIl graph.
544
+ """
545
+ graph_copy = networkx.DiGraph()
546
+ block_mapping = {}
547
+ # copy all blocks
548
+ for block in graph.nodes():
549
+ new_block = copy.copy(block)
550
+ new_stmts = copy.copy(block.statements)
551
+ new_block.statements = new_stmts
552
+ block_mapping[block] = new_block
553
+ graph_copy.add_node(new_block)
554
+
555
+ # copy all edges
556
+ for src, dst, data in graph.edges(data=True):
557
+ new_src = block_mapping[src]
558
+ new_dst = block_mapping[dst]
559
+ graph_copy.add_edge(new_src, new_dst, **data)
560
+ return graph_copy
561
+
562
+
513
563
  def peephole_optimize_stmts(block, stmt_opts):
514
564
  any_update = False
515
565
  statements = []
@@ -133,6 +133,8 @@ class IROp(DisassemblyPiece):
133
133
  self.irsb = irsb
134
134
 
135
135
  def __str__(self):
136
+ if pcode and isinstance(self.obj, pypcode.PcodeOp):
137
+ return pypcode.PcodePrettyPrinter.fmt_op(self.obj)
136
138
  return str(self.obj)
137
139
 
138
140
  def _render(self, formatting): # pylint:disable=unused-argument
@@ -1078,9 +1080,14 @@ class Disassembly(Analysis):
1078
1080
 
1079
1081
  if irsb.statements is not None:
1080
1082
  if pcode is not None and isinstance(self.project.factory.default_engine, pcode.HeavyPcodeMixin):
1081
- for ins in irsb._instructions:
1082
- addr = ins.address.offset
1083
- addr_to_ops_map[addr].extend([IROp(addr, op.seq.uniq, op, irsb) for op in ins.ops])
1083
+ addr = None
1084
+ stmt_idx = 0
1085
+ for op in irsb._ops:
1086
+ if op.opcode == pypcode.OpCode.IMARK:
1087
+ addr = op.inputs[0].offset
1088
+ else:
1089
+ addr_to_ops_map[addr].append(IROp(addr, stmt_idx, op, irsb))
1090
+ stmt_idx += 1
1084
1091
  else:
1085
1092
  for seq, stmt in enumerate(irsb.statements):
1086
1093
  if isinstance(stmt, pyvex.stmt.IMark):
@@ -4,6 +4,7 @@ import logging
4
4
 
5
5
  import claripy
6
6
  from ailment import Stmt, Expr
7
+ from unique_log_filter import UniqueLogFilter
7
8
 
8
9
  from angr.knowledge_plugins.propagations.prop_value import PropValue, Detail
9
10
  from angr.knowledge_plugins.key_definitions.atoms import Register
@@ -20,6 +21,7 @@ if TYPE_CHECKING:
20
21
  from angr.code_location import CodeLocation
21
22
 
22
23
  l = logging.getLogger(name=__name__)
24
+ l.addFilter(UniqueLogFilter())
23
25
 
24
26
 
25
27
  class SimEnginePropagatorAIL(
@@ -1268,6 +1270,129 @@ class SimEnginePropagatorAIL(
1268
1270
  )
1269
1271
  return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
1270
1272
 
1273
+ def _ail_handle_LogicalOr(self, expr: Expr.BinaryOp):
1274
+ o0_value = self._expr(expr.operands[0])
1275
+ o1_value = self._expr(expr.operands[1])
1276
+
1277
+ value = self.state.top(expr.bits)
1278
+ if o0_value is None or o1_value is None:
1279
+ new_expr = expr
1280
+ else:
1281
+ o0_expr = o0_value.one_expr
1282
+ o1_expr = o1_value.one_expr
1283
+
1284
+ value = self.state.top(expr.bits)
1285
+ new_expr = Expr.BinaryOp(
1286
+ expr.idx,
1287
+ "LogicalOr",
1288
+ [
1289
+ o0_expr if o0_expr is not None else expr.operands[0],
1290
+ o1_expr if o1_expr is not None else expr.operands[1],
1291
+ ],
1292
+ expr.signed,
1293
+ **expr.tags,
1294
+ )
1295
+ return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
1296
+
1297
+ def _ail_handle_LogicalXor(self, expr: Expr.BinaryOp):
1298
+ o0_value = self._expr(expr.operands[0])
1299
+ o1_value = self._expr(expr.operands[1])
1300
+
1301
+ value = self.state.top(expr.bits)
1302
+ if o0_value is None or o1_value is None:
1303
+ new_expr = expr
1304
+ else:
1305
+ o0_expr = o0_value.one_expr
1306
+ o1_expr = o1_value.one_expr
1307
+
1308
+ value = self.state.top(expr.bits)
1309
+ new_expr = Expr.BinaryOp(
1310
+ expr.idx,
1311
+ "LogicalXor",
1312
+ [
1313
+ o0_expr if o0_expr is not None else expr.operands[0],
1314
+ o1_expr if o1_expr is not None else expr.operands[1],
1315
+ ],
1316
+ expr.signed,
1317
+ **expr.tags,
1318
+ )
1319
+ return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
1320
+
1321
+ def _ail_handle_Carry(self, expr: Expr.BinaryOp):
1322
+ o0_value = self._expr(expr.operands[0])
1323
+ o1_value = self._expr(expr.operands[1])
1324
+
1325
+ value = self.state.top(expr.bits)
1326
+ if o0_value is None or o1_value is None:
1327
+ new_expr = expr
1328
+ else:
1329
+ o0_expr = o0_value.one_expr
1330
+ o1_expr = o1_value.one_expr
1331
+ new_expr = Expr.BinaryOp(
1332
+ expr.idx,
1333
+ "Carry",
1334
+ [
1335
+ o0_expr if o0_expr is not None else expr.operands[0],
1336
+ o1_expr if o1_expr is not None else expr.operands[1],
1337
+ ],
1338
+ expr.signed,
1339
+ bits=expr.bits,
1340
+ floating_point=expr.floating_point,
1341
+ rounding_mode=expr.rounding_mode,
1342
+ **expr.tags,
1343
+ )
1344
+ return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
1345
+
1346
+ def _ail_handle_SCarry(self, expr: Expr.BinaryOp):
1347
+ o0_value = self._expr(expr.operands[0])
1348
+ o1_value = self._expr(expr.operands[1])
1349
+
1350
+ value = self.state.top(expr.bits)
1351
+ if o0_value is None or o1_value is None:
1352
+ new_expr = expr
1353
+ else:
1354
+ o0_expr = o0_value.one_expr
1355
+ o1_expr = o1_value.one_expr
1356
+ new_expr = Expr.BinaryOp(
1357
+ expr.idx,
1358
+ "SCarry",
1359
+ [
1360
+ o0_expr if o0_expr is not None else expr.operands[0],
1361
+ o1_expr if o1_expr is not None else expr.operands[1],
1362
+ ],
1363
+ expr.signed,
1364
+ bits=expr.bits,
1365
+ floating_point=expr.floating_point,
1366
+ rounding_mode=expr.rounding_mode,
1367
+ **expr.tags,
1368
+ )
1369
+ return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
1370
+
1371
+ def _ail_handle_SBorrow(self, expr: Expr.BinaryOp):
1372
+ o0_value = self._expr(expr.operands[0])
1373
+ o1_value = self._expr(expr.operands[1])
1374
+
1375
+ value = self.state.top(expr.bits)
1376
+ if o0_value is None or o1_value is None:
1377
+ new_expr = expr
1378
+ else:
1379
+ o0_expr = o0_value.one_expr
1380
+ o1_expr = o1_value.one_expr
1381
+ new_expr = Expr.BinaryOp(
1382
+ expr.idx,
1383
+ "SBorrow",
1384
+ [
1385
+ o0_expr if o0_expr is not None else expr.operands[0],
1386
+ o1_expr if o1_expr is not None else expr.operands[1],
1387
+ ],
1388
+ expr.signed,
1389
+ bits=expr.bits,
1390
+ floating_point=expr.floating_point,
1391
+ rounding_mode=expr.rounding_mode,
1392
+ **expr.tags,
1393
+ )
1394
+ return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
1395
+
1271
1396
  def _ail_handle_TernaryOp(self, expr: Expr.TernaryOp):
1272
1397
  o0_value = self._expr(expr.operands[0])
1273
1398
  o1_value = self._expr(expr.operands[1])
@@ -981,7 +981,6 @@ class SimEngineRDAIL(
981
981
  expr1: MultiValues = self._expr(expr.operands[1])
982
982
  bits = expr.bits
983
983
 
984
- r = None
985
984
  expr0_v = expr0.one_value()
986
985
  expr1_v = expr1.one_value()
987
986
 
@@ -999,7 +998,6 @@ class SimEngineRDAIL(
999
998
  expr1: MultiValues = self._expr(expr.operands[1])
1000
999
  bits = expr.bits
1001
1000
 
1002
- r = None
1003
1001
  expr0_v = expr0.one_value()
1004
1002
  expr1_v = expr1.one_value()
1005
1003
 
@@ -1010,6 +1008,21 @@ class SimEngineRDAIL(
1010
1008
  r = MultiValues(claripy.If(expr0_v != 0, expr0_v, expr1_v))
1011
1009
  return r
1012
1010
 
1011
+ def _ail_handle_LogicalXor(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
1012
+ expr0: MultiValues = self._expr(expr.operands[0])
1013
+ expr1: MultiValues = self._expr(expr.operands[1])
1014
+ bits = expr.bits
1015
+
1016
+ expr0_v = expr0.one_value()
1017
+ expr1_v = expr1.one_value()
1018
+
1019
+ if expr0_v is None or expr1_v is None:
1020
+ r = MultiValues(self.state.top(bits))
1021
+ return r
1022
+
1023
+ r = MultiValues(claripy.If(expr0_v != 0, expr1_v, expr0_v))
1024
+ return r
1025
+
1013
1026
  def _ail_handle_Xor(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
1014
1027
  expr0: MultiValues = self._expr(expr.operands[0])
1015
1028
  expr1: MultiValues = self._expr(expr.operands[1])
@@ -1042,6 +1055,27 @@ class SimEngineRDAIL(
1042
1055
 
1043
1056
  return r
1044
1057
 
1058
+ def _ail_handle_Carry(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
1059
+ _ = self._expr(expr.operands[0])
1060
+ _ = self._expr(expr.operands[1])
1061
+ bits = expr.bits
1062
+ r = MultiValues(self.state.top(bits))
1063
+ return r
1064
+
1065
+ def _ail_handle_SCarry(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
1066
+ _ = self._expr(expr.operands[0])
1067
+ _ = self._expr(expr.operands[1])
1068
+ bits = expr.bits
1069
+ r = MultiValues(self.state.top(bits))
1070
+ return r
1071
+
1072
+ def _ail_handle_SBorrow(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
1073
+ _ = self._expr(expr.operands[0])
1074
+ _ = self._expr(expr.operands[1])
1075
+ bits = expr.bits
1076
+ r = MultiValues(self.state.top(bits))
1077
+ return r
1078
+
1045
1079
  def _ail_handle_Concat(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
1046
1080
  expr0: MultiValues = self._expr(expr.operands[0])
1047
1081
  expr1: MultiValues = self._expr(expr.operands[1])
@@ -33,8 +33,9 @@ class RDAStateInitializer:
33
33
 
34
34
  """
35
35
 
36
- def __init__(self, arch: Arch):
36
+ def __init__(self, arch: Arch, project=None):
37
37
  self.arch: Arch = arch
38
+ self.project = project
38
39
 
39
40
  def initialize_function_state(
40
41
  self, state: "ReachingDefinitionsState", cc: Optional[SimCC], func_addr: int, rtoc_value: Optional[int] = None
@@ -171,6 +172,19 @@ class RDAStateInitializer:
171
172
  t9 = state.annotate_with_def(claripy.BVV(func_addr, self.arch.bits), t9_def)
172
173
  state.registers.store(t9_offset, t9)
173
174
 
175
+ # project-specific initialization
176
+ if self.project is not None:
177
+ if self.project.simos is not None and self.project.simos.function_initial_registers:
178
+ for reg_name, reg_value in self.project.simos.function_initial_registers.items():
179
+ reg_offset = self.arch.registers[reg_name][0]
180
+ reg_atom = Register(reg_offset, self.arch.registers[reg_name][1])
181
+ reg_def = Definition(reg_atom, ex_loc, tags={InitialValueTag()})
182
+ state.all_definitions.add(reg_def)
183
+ if state.analysis is not None:
184
+ state.analysis.model.add_def(reg_def)
185
+ reg = state.annotate_with_def(claripy.BVV(reg_value, self.arch.registers[reg_name][1]), reg_def)
186
+ state.registers.store(reg_offset, reg)
187
+
174
188
  def _initialize_function_argument_register(
175
189
  self,
176
190
  state: "ReachingDefinitionsState",
@@ -124,10 +124,11 @@ class ReachingDefinitionsState:
124
124
  self.live_definitions = LiveDefinitions(
125
125
  self.arch, track_tmps=self._track_tmps, canonical_size=canonical_size
126
126
  )
127
- self._set_initialization_values(subject, rtoc_value, initializer=initializer)
128
-
129
127
  if self.analysis is not None:
130
128
  self.live_definitions.project = self.analysis.project
129
+ self._set_initialization_values(
130
+ subject, rtoc_value, initializer=initializer, project=self.live_definitions.project
131
+ )
131
132
  else:
132
133
  # this state is a copy from a previous state. skip the initialization
133
134
  self.live_definitions = live_definitions
@@ -269,10 +270,14 @@ class ReachingDefinitionsState:
269
270
  return "{%s}" % ctnt
270
271
 
271
272
  def _set_initialization_values(
272
- self, subject: Subject, rtoc_value: Optional[int] = None, initializer: Optional[RDAStateInitializer] = None
273
+ self,
274
+ subject: Subject,
275
+ rtoc_value: Optional[int] = None,
276
+ initializer: Optional[RDAStateInitializer] = None,
277
+ project=None,
273
278
  ):
274
279
  if initializer is None:
275
- initializer = RDAStateInitializer(self.arch)
280
+ initializer = RDAStateInitializer(self.arch, project=project)
276
281
 
277
282
  if subject.type == SubjectType.Function:
278
283
  if isinstance(self.arch, archinfo.arch_ppc64.ArchPPC64) and not rtoc_value:
@@ -695,28 +695,21 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
695
695
  else:
696
696
  raise CouldNotResolveException()
697
697
 
698
- for instr in pcode_irsb._instructions:
699
- if curr_stmt_start_addr is not None:
700
- # we've reached a new instruction. Time to store the post state
701
- self._set_post_state(curr_stmt_start_addr, state.freeze())
702
- curr_stmt_start_addr = instr.address.offset
703
- self._set_pre_state(curr_stmt_start_addr, state.freeze())
704
-
705
- for op in instr.ops:
706
- op: "pypcode.PcodeOp"
698
+ is_call = False
699
+ for op in pcode_irsb._ops:
700
+ if op.opcode == pypcode.OpCode.IMARK:
701
+ if curr_stmt_start_addr is not None:
702
+ # we've reached a new instruction. Time to store the post state
703
+ self._set_post_state(curr_stmt_start_addr, state.freeze())
704
+ curr_stmt_start_addr = op.inputs[0].offset
705
+ self._set_pre_state(curr_stmt_start_addr, state.freeze())
706
+ else:
707
707
  try:
708
708
  resolve_op(op)
709
709
  except CouldNotResolveException:
710
710
  pass
711
711
 
712
- # examine the last instruction and determine if this is a call instruction
713
- is_call = False
714
- if pcode_irsb._instructions:
715
- last_instr = pcode_irsb._instructions[-1]
716
- if last_instr.ops:
717
- last_op = last_instr.ops[-1]
718
- if last_op.opcode == pypcode.OpCode.CALL:
719
- is_call = True
712
+ is_call |= op.opcode == pypcode.OpCode.CALL
720
713
 
721
714
  # stack pointer adjustment
722
715
  if self.project.arch.sp_offset in self.reg_offsets and is_call:
@@ -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: