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
|
@@ -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
|
|
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 =
|
|
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 = []
|
angr/analyses/disassembly.py
CHANGED
|
@@ -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
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
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,
|
|
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
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
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
|
)
|
angr/calling_conventions.py
CHANGED
|
@@ -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:
|