angr 9.2.97__py3-none-manylinux2014_x86_64.whl → 9.2.98__py3-none-manylinux2014_x86_64.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 +14 -1
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +10 -6
- angr/analyses/decompiler/optimization_passes/__init__.py +2 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +380 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +4 -1
- angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +71 -3
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +162 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +72 -99
- angr/analyses/decompiler/utils.py +5 -1
- angr/analyses/propagator/engine_vex.py +15 -0
- angr/analyses/reaching_definitions/engine_vex.py +6 -0
- angr/analyses/variable_recovery/engine_vex.py +6 -0
- angr/analyses/variable_recovery/irsb_scanner.py +12 -0
- angr/engines/light/engine.py +126 -15
- angr/knowledge_plugins/functions/function.py +4 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +20 -5
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +2 -1
- angr/storage/memory_mixins/simple_interface_mixin.py +4 -0
- {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/METADATA +6 -6
- {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/RECORD +27 -25
- {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/LICENSE +0 -0
- {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/WHEEL +0 -0
- {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/entry_points.txt +0 -0
- {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# pylint:disable=arguments-differ
|
|
2
|
+
from typing import Tuple, Optional, Dict, List
|
|
3
|
+
import string
|
|
4
|
+
|
|
5
|
+
from archinfo import Endness
|
|
6
|
+
|
|
7
|
+
from ailment.expression import Const, StackBaseOffset
|
|
8
|
+
from ailment.statement import Call, Store
|
|
9
|
+
|
|
10
|
+
from .base import PeepholeOptimizationStmtBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
ASCII_PRINTABLES = set(string.printable)
|
|
14
|
+
ASCII_DIGITS = set(string.digits)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InlinedWstrcpy(PeepholeOptimizationStmtBase):
|
|
18
|
+
"""
|
|
19
|
+
Simplifies inlined wide string copying logic into calls to wstrcpy.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__slots__ = ()
|
|
23
|
+
|
|
24
|
+
NAME = "Simplifying inlined wstrcpy"
|
|
25
|
+
stmt_classes = (Store,)
|
|
26
|
+
|
|
27
|
+
def optimize(self, stmt: Store, stmt_idx: int = None, block=None, **kwargs):
|
|
28
|
+
if isinstance(stmt.data, Const):
|
|
29
|
+
r, s = self.is_integer_likely_a_wide_string(stmt.data.value, stmt.data.size, stmt.endness)
|
|
30
|
+
if r:
|
|
31
|
+
# replace it with a call to strncpy
|
|
32
|
+
str_id = self.kb.custom_strings.allocate(s.encode("ascii"))
|
|
33
|
+
return Call(
|
|
34
|
+
stmt.idx,
|
|
35
|
+
"wstrncpy",
|
|
36
|
+
args=[
|
|
37
|
+
stmt.addr,
|
|
38
|
+
Const(None, None, str_id, stmt.addr.bits, custom_string=True),
|
|
39
|
+
Const(None, None, len(s), self.project.arch.bits),
|
|
40
|
+
],
|
|
41
|
+
**stmt.tags,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# scan forward in the current block to find all consecutive constant stores
|
|
45
|
+
if block is not None and stmt_idx is not None:
|
|
46
|
+
all_constant_stores: Dict[int, Tuple[int, Optional[Const]]] = self.collect_constant_stores(
|
|
47
|
+
block, stmt_idx
|
|
48
|
+
)
|
|
49
|
+
if all_constant_stores:
|
|
50
|
+
offsets = sorted(all_constant_stores.keys())
|
|
51
|
+
next_offset = min(offsets)
|
|
52
|
+
stride = []
|
|
53
|
+
for offset in offsets:
|
|
54
|
+
if next_offset is not None and offset != next_offset:
|
|
55
|
+
next_offset = None
|
|
56
|
+
stride = []
|
|
57
|
+
stmt_idx_, v = all_constant_stores[offset]
|
|
58
|
+
if v is not None:
|
|
59
|
+
stride.append((offset, stmt_idx_, v))
|
|
60
|
+
next_offset = offset + v.size
|
|
61
|
+
else:
|
|
62
|
+
next_offset = None
|
|
63
|
+
stride = []
|
|
64
|
+
|
|
65
|
+
integer, size = self.stride_to_int(stride)
|
|
66
|
+
r, s = self.is_integer_likely_a_wide_string(integer, size, Endness.BE)
|
|
67
|
+
if r:
|
|
68
|
+
# we remove all involved statements whose statement IDs are greater than the current one
|
|
69
|
+
for _, stmt_idx_, _ in reversed(stride):
|
|
70
|
+
if stmt_idx_ <= stmt_idx:
|
|
71
|
+
continue
|
|
72
|
+
block.statements[stmt_idx_] = None
|
|
73
|
+
block.statements = [ss for ss in block.statements if ss is not None]
|
|
74
|
+
|
|
75
|
+
str_id = self.kb.custom_strings.allocate(s.encode("ascii"))
|
|
76
|
+
return Call(
|
|
77
|
+
stmt.idx,
|
|
78
|
+
"wstrncpy",
|
|
79
|
+
args=[
|
|
80
|
+
stmt.addr,
|
|
81
|
+
Const(None, None, str_id, stmt.addr.bits, custom_string=True),
|
|
82
|
+
Const(None, None, len(s), self.project.arch.bits),
|
|
83
|
+
],
|
|
84
|
+
**stmt.tags,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def stride_to_int(stride: List[Tuple[int, int, Const]]) -> Tuple[int, int]:
|
|
91
|
+
stride = sorted(stride, key=lambda x: x[0])
|
|
92
|
+
n = 0
|
|
93
|
+
size = 0
|
|
94
|
+
for _, _, v in stride:
|
|
95
|
+
size += v.size
|
|
96
|
+
n <<= v.bits
|
|
97
|
+
n |= v.value
|
|
98
|
+
return n, size
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def collect_constant_stores(block, starting_stmt_idx: int) -> Dict[int, Tuple[int, Optional[Const]]]:
|
|
102
|
+
r = {}
|
|
103
|
+
for idx, stmt in enumerate(block.statements):
|
|
104
|
+
if idx < starting_stmt_idx:
|
|
105
|
+
continue
|
|
106
|
+
if isinstance(stmt, Store) and isinstance(stmt.addr, StackBaseOffset) and isinstance(stmt.addr.offset, int):
|
|
107
|
+
if isinstance(stmt.data, Const):
|
|
108
|
+
r[stmt.addr.offset] = idx, stmt.data
|
|
109
|
+
else:
|
|
110
|
+
r[stmt.addr.offset] = idx, None
|
|
111
|
+
|
|
112
|
+
return r
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def even_offsets_are_zero(lst: List[str]) -> bool:
|
|
116
|
+
return all(ch == "\x00" for i, ch in enumerate(lst) if i % 2 == 0)
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def odd_offsets_are_zero(lst: List[str]) -> bool:
|
|
120
|
+
return all(ch == "\x00" for i, ch in enumerate(lst) if i % 2 == 1)
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def is_integer_likely_a_wide_string(
|
|
124
|
+
v: int, size: int, endness: Endness, min_length: int = 4
|
|
125
|
+
) -> Tuple[bool, Optional[str]]:
|
|
126
|
+
# we need at least four bytes of printable characters
|
|
127
|
+
|
|
128
|
+
chars = []
|
|
129
|
+
if endness == Endness.LE:
|
|
130
|
+
while v != 0:
|
|
131
|
+
byt = v & 0xFF
|
|
132
|
+
if byt != 0 and chr(byt) not in ASCII_PRINTABLES:
|
|
133
|
+
return False, None
|
|
134
|
+
chars.append(chr(byt))
|
|
135
|
+
v >>= 8
|
|
136
|
+
|
|
137
|
+
elif endness == Endness.BE:
|
|
138
|
+
for _ in range(size):
|
|
139
|
+
byt = v & 0xFF
|
|
140
|
+
v >>= 8
|
|
141
|
+
if byt != 0 and chr(byt) not in ASCII_PRINTABLES:
|
|
142
|
+
return False, None
|
|
143
|
+
chars.append(chr(byt))
|
|
144
|
+
chars = chars[::-1]
|
|
145
|
+
else:
|
|
146
|
+
# unsupported endness
|
|
147
|
+
return False, None
|
|
148
|
+
|
|
149
|
+
if InlinedWstrcpy.even_offsets_are_zero(chars):
|
|
150
|
+
chars = [ch for i, ch in enumerate(chars) if i % 2 == 1]
|
|
151
|
+
elif InlinedWstrcpy.odd_offsets_are_zero(chars):
|
|
152
|
+
chars = [ch for i, ch in enumerate(chars) if i % 2 == 0]
|
|
153
|
+
else:
|
|
154
|
+
return False, None
|
|
155
|
+
|
|
156
|
+
if chars and chars[-1] == "\x00":
|
|
157
|
+
chars = chars[:-1]
|
|
158
|
+
if len(chars) >= min_length and all(ch in ASCII_PRINTABLES for ch in chars):
|
|
159
|
+
if len(chars) <= 4 and all(ch in ASCII_DIGITS for ch in chars):
|
|
160
|
+
return False, None
|
|
161
|
+
return True, "".join(chars)
|
|
162
|
+
return False, None
|
|
@@ -5,6 +5,6 @@ from .base import (
|
|
|
5
5
|
PositionMappingElement,
|
|
6
6
|
PositionMapping,
|
|
7
7
|
)
|
|
8
|
-
from .c import CStructuredCodeGenerator
|
|
8
|
+
from .c import CStructuredCodeGenerator, CStructuredCodeWalker
|
|
9
9
|
from .dwarf_import import ImportSourceCode
|
|
10
10
|
from .dummy import DummyStructuredCodeGenerator
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument
|
|
1
|
+
# pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument,no-self-use
|
|
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
|
|
@@ -2524,9 +2524,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2524
2524
|
codegen=self,
|
|
2525
2525
|
omit_header=self.omit_func_header,
|
|
2526
2526
|
)
|
|
2527
|
-
self.cfunc = FieldReferenceCleanup.handle(self.cfunc)
|
|
2528
|
-
self.cfunc = PointerArithmeticFixer.handle(self.cfunc)
|
|
2529
|
-
self.cfunc = MakeTypecastsImplicit.handle(self.cfunc)
|
|
2527
|
+
self.cfunc = FieldReferenceCleanup().handle(self.cfunc)
|
|
2528
|
+
self.cfunc = PointerArithmeticFixer().handle(self.cfunc)
|
|
2529
|
+
self.cfunc = MakeTypecastsImplicit().handle(self.cfunc)
|
|
2530
2530
|
|
|
2531
2531
|
# TODO store extern fallback size somewhere lol
|
|
2532
2532
|
self.cexterns = {
|
|
@@ -3554,120 +3554,100 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3554
3554
|
|
|
3555
3555
|
|
|
3556
3556
|
class CStructuredCodeWalker:
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
handler = getattr(cls, "handle_" + type(obj).__name__, cls.handle_default)
|
|
3557
|
+
def handle(self, obj):
|
|
3558
|
+
handler = getattr(self, "handle_" + type(obj).__name__, self.handle_default)
|
|
3560
3559
|
return handler(obj)
|
|
3561
3560
|
|
|
3562
|
-
|
|
3563
|
-
def handle_default(cls, obj):
|
|
3561
|
+
def handle_default(self, obj):
|
|
3564
3562
|
return obj
|
|
3565
3563
|
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
obj.statements = cls.handle(obj.statements)
|
|
3564
|
+
def handle_CFunction(self, obj):
|
|
3565
|
+
obj.statements = self.handle(obj.statements)
|
|
3569
3566
|
return obj
|
|
3570
3567
|
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
obj.statements = [cls.handle(stmt) for stmt in obj.statements]
|
|
3568
|
+
def handle_CStatements(self, obj):
|
|
3569
|
+
obj.statements = [self.handle(stmt) for stmt in obj.statements]
|
|
3574
3570
|
return obj
|
|
3575
3571
|
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
obj.
|
|
3579
|
-
obj.body = cls.handle(obj.body)
|
|
3572
|
+
def handle_CWhileLoop(self, obj):
|
|
3573
|
+
obj.condition = self.handle(obj.condition)
|
|
3574
|
+
obj.body = self.handle(obj.body)
|
|
3580
3575
|
return obj
|
|
3581
3576
|
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
obj.
|
|
3585
|
-
obj.body = cls.handle(obj.body)
|
|
3577
|
+
def handle_CDoWhileLoop(self, obj):
|
|
3578
|
+
obj.condition = self.handle(obj.condition)
|
|
3579
|
+
obj.body = self.handle(obj.body)
|
|
3586
3580
|
return obj
|
|
3587
3581
|
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
obj.
|
|
3591
|
-
obj.
|
|
3592
|
-
obj.
|
|
3593
|
-
obj.body = cls.handle(obj.body)
|
|
3582
|
+
def handle_CForLoop(self, obj):
|
|
3583
|
+
obj.initializer = self.handle(obj.initializer)
|
|
3584
|
+
obj.condition = self.handle(obj.condition)
|
|
3585
|
+
obj.iterator = self.handle(obj.iterator)
|
|
3586
|
+
obj.body = self.handle(obj.body)
|
|
3594
3587
|
return obj
|
|
3595
3588
|
|
|
3596
|
-
|
|
3597
|
-
def handle_CIfElse(cls, obj):
|
|
3589
|
+
def handle_CIfElse(self, obj):
|
|
3598
3590
|
obj.condition_and_nodes = [
|
|
3599
|
-
(
|
|
3591
|
+
(self.handle(condition), self.handle(node)) for condition, node in obj.condition_and_nodes
|
|
3600
3592
|
]
|
|
3601
|
-
obj.else_node =
|
|
3593
|
+
obj.else_node = self.handle(obj.else_node)
|
|
3602
3594
|
return obj
|
|
3603
3595
|
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
obj.condition = cls.handle(obj.condition)
|
|
3596
|
+
def handle_CIfBreak(self, obj):
|
|
3597
|
+
obj.condition = self.handle(obj.condition)
|
|
3607
3598
|
return obj
|
|
3608
3599
|
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
obj.
|
|
3612
|
-
obj.
|
|
3613
|
-
obj.default = cls.handle(obj.default)
|
|
3600
|
+
def handle_CSwitchCase(self, obj):
|
|
3601
|
+
obj.switch = self.handle(obj.switch)
|
|
3602
|
+
obj.cases = [(case, self.handle(body)) for case, body in obj.cases]
|
|
3603
|
+
obj.default = self.handle(obj.default)
|
|
3614
3604
|
return obj
|
|
3615
3605
|
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
obj.
|
|
3619
|
-
obj.rhs = cls.handle(obj.rhs)
|
|
3606
|
+
def handle_CAssignment(self, obj):
|
|
3607
|
+
obj.lhs = self.handle(obj.lhs)
|
|
3608
|
+
obj.rhs = self.handle(obj.rhs)
|
|
3620
3609
|
return obj
|
|
3621
3610
|
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
obj.
|
|
3625
|
-
obj.
|
|
3626
|
-
obj.ret_expr = cls.handle(obj.ret_expr)
|
|
3611
|
+
def handle_CFunctionCall(self, obj):
|
|
3612
|
+
obj.callee_target = self.handle(obj.callee_target)
|
|
3613
|
+
obj.args = [self.handle(arg) for arg in obj.args]
|
|
3614
|
+
obj.ret_expr = self.handle(obj.ret_expr)
|
|
3627
3615
|
return obj
|
|
3628
3616
|
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
obj.retval = cls.handle(obj.retval)
|
|
3617
|
+
def handle_CReturn(self, obj):
|
|
3618
|
+
obj.retval = self.handle(obj.retval)
|
|
3632
3619
|
return obj
|
|
3633
3620
|
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
obj.target = cls.handle(obj.target)
|
|
3621
|
+
def handle_CGoto(self, obj):
|
|
3622
|
+
obj.target = self.handle(obj.target)
|
|
3637
3623
|
return obj
|
|
3638
3624
|
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
obj.
|
|
3642
|
-
obj.index = cls.handle(obj.index)
|
|
3625
|
+
def handle_CIndexedVariable(self, obj):
|
|
3626
|
+
obj.variable = self.handle(obj.variable)
|
|
3627
|
+
obj.index = self.handle(obj.index)
|
|
3643
3628
|
return obj
|
|
3644
3629
|
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
obj.variable = cls.handle(obj.variable)
|
|
3630
|
+
def handle_CVariableField(self, obj):
|
|
3631
|
+
obj.variable = self.handle(obj.variable)
|
|
3648
3632
|
return obj
|
|
3649
3633
|
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
obj.operand = cls.handle(obj.operand)
|
|
3634
|
+
def handle_CUnaryOp(self, obj):
|
|
3635
|
+
obj.operand = self.handle(obj.operand)
|
|
3653
3636
|
return obj
|
|
3654
3637
|
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
obj.
|
|
3658
|
-
obj.rhs = cls.handle(obj.rhs)
|
|
3638
|
+
def handle_CBinaryOp(self, obj):
|
|
3639
|
+
obj.lhs = self.handle(obj.lhs)
|
|
3640
|
+
obj.rhs = self.handle(obj.rhs)
|
|
3659
3641
|
return obj
|
|
3660
3642
|
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
obj.expr = cls.handle(obj.expr)
|
|
3643
|
+
def handle_CTypeCast(self, obj):
|
|
3644
|
+
obj.expr = self.handle(obj.expr)
|
|
3664
3645
|
return obj
|
|
3665
3646
|
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
obj.
|
|
3669
|
-
obj.
|
|
3670
|
-
obj.iffalse = cls.handle(obj.iffalse)
|
|
3647
|
+
def handle_CITE(self, obj):
|
|
3648
|
+
obj.cond = self.handle(obj.cond)
|
|
3649
|
+
obj.iftrue = self.handle(obj.iftrue)
|
|
3650
|
+
obj.iffalse = self.handle(obj.iffalse)
|
|
3671
3651
|
return obj
|
|
3672
3652
|
|
|
3673
3653
|
|
|
@@ -3702,34 +3682,30 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3702
3682
|
return cls.collapse(dst_ty, result)
|
|
3703
3683
|
return result
|
|
3704
3684
|
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
obj.rhs = cls.collapse(obj.lhs.type, obj.rhs)
|
|
3685
|
+
def handle_CAssignment(self, obj):
|
|
3686
|
+
obj.rhs = self.collapse(obj.lhs.type, obj.rhs)
|
|
3708
3687
|
return super().handle_CAssignment(obj)
|
|
3709
3688
|
|
|
3710
|
-
|
|
3711
|
-
def handle_CFunctionCall(cls, obj: CFunctionCall):
|
|
3689
|
+
def handle_CFunctionCall(self, obj: CFunctionCall):
|
|
3712
3690
|
for i, (c_arg, arg_ty) in enumerate(zip(obj.args, obj.prototype.args)):
|
|
3713
|
-
obj.args[i] =
|
|
3691
|
+
obj.args[i] = self.collapse(arg_ty, c_arg)
|
|
3714
3692
|
return super().handle_CFunctionCall(obj)
|
|
3715
3693
|
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
obj.retval = cls.collapse(obj.codegen._func.prototype.returnty, obj.retval)
|
|
3694
|
+
def handle_CReturn(self, obj: CReturn):
|
|
3695
|
+
obj.retval = self.collapse(obj.codegen._func.prototype.returnty, obj.retval)
|
|
3719
3696
|
return super().handle_CReturn(obj)
|
|
3720
3697
|
|
|
3721
|
-
|
|
3722
|
-
def handle_CBinaryOp(cls, obj: CBinaryOp):
|
|
3698
|
+
def handle_CBinaryOp(self, obj: CBinaryOp):
|
|
3723
3699
|
obj = super().handle_CBinaryOp(obj)
|
|
3724
3700
|
while True:
|
|
3725
|
-
new_lhs =
|
|
3701
|
+
new_lhs = self.collapse(obj.common_type, obj.lhs)
|
|
3726
3702
|
if (
|
|
3727
3703
|
new_lhs is not obj.lhs
|
|
3728
3704
|
and CBinaryOp.compute_common_type(obj.op, new_lhs.type, obj.rhs.type) == obj.common_type
|
|
3729
3705
|
):
|
|
3730
3706
|
obj.lhs = new_lhs
|
|
3731
3707
|
else:
|
|
3732
|
-
new_rhs =
|
|
3708
|
+
new_rhs = self.collapse(obj.common_type, obj.rhs)
|
|
3733
3709
|
if (
|
|
3734
3710
|
new_rhs is not obj.rhs
|
|
3735
3711
|
and CBinaryOp.compute_common_type(obj.op, obj.lhs.type, new_rhs.type) == obj.common_type
|
|
@@ -3739,11 +3715,10 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3739
3715
|
break
|
|
3740
3716
|
return obj
|
|
3741
3717
|
|
|
3742
|
-
|
|
3743
|
-
def handle_CTypeCast(cls, obj: CTypeCast):
|
|
3718
|
+
def handle_CTypeCast(self, obj: CTypeCast):
|
|
3744
3719
|
# note that the expression that this method returns may no longer be a CTypeCast
|
|
3745
3720
|
obj = super().handle_CTypeCast(obj)
|
|
3746
|
-
inner =
|
|
3721
|
+
inner = self.collapse(obj.dst_type, obj.expr)
|
|
3747
3722
|
if inner is not obj.expr:
|
|
3748
3723
|
obj.src_type = inner.type
|
|
3749
3724
|
obj.expr = inner
|
|
@@ -3753,12 +3728,11 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3753
3728
|
|
|
3754
3729
|
|
|
3755
3730
|
class FieldReferenceCleanup(CStructuredCodeWalker):
|
|
3756
|
-
|
|
3757
|
-
def handle_CTypeCast(cls, obj):
|
|
3731
|
+
def handle_CTypeCast(self, obj):
|
|
3758
3732
|
if isinstance(obj.dst_type, SimTypePointer) and not isinstance(obj.dst_type.pts_to, SimTypeBottom):
|
|
3759
3733
|
obj = obj.codegen._access_reference(obj.expr, obj.dst_type.pts_to)
|
|
3760
3734
|
if not isinstance(obj, CTypeCast):
|
|
3761
|
-
return
|
|
3735
|
+
return self.handle(obj)
|
|
3762
3736
|
return super().handle_CTypeCast(obj)
|
|
3763
3737
|
|
|
3764
3738
|
|
|
@@ -3776,8 +3750,7 @@ class PointerArithmeticFixer(CStructuredCodeWalker):
|
|
|
3776
3750
|
a_ptr = a_ptr + 1.
|
|
3777
3751
|
"""
|
|
3778
3752
|
|
|
3779
|
-
|
|
3780
|
-
def handle_CBinaryOp(cls, obj):
|
|
3753
|
+
def handle_CBinaryOp(self, obj):
|
|
3781
3754
|
obj: CBinaryOp = super().handle_CBinaryOp(obj)
|
|
3782
3755
|
if (
|
|
3783
3756
|
obj.op in ("Add", "Sub")
|
|
@@ -569,7 +569,10 @@ def peephole_optimize_stmts(block, stmt_opts):
|
|
|
569
569
|
statements = []
|
|
570
570
|
|
|
571
571
|
# run statement optimizers
|
|
572
|
-
|
|
572
|
+
# note that an optimizer may optionally edit or remove statements whose statement IDs are greater than stmt_idx
|
|
573
|
+
stmt_idx = 0
|
|
574
|
+
while stmt_idx < len(block.statements):
|
|
575
|
+
stmt = block.statements[stmt_idx]
|
|
573
576
|
old_stmt = stmt
|
|
574
577
|
redo = True
|
|
575
578
|
while redo:
|
|
@@ -587,6 +590,7 @@ def peephole_optimize_stmts(block, stmt_opts):
|
|
|
587
590
|
any_update = True
|
|
588
591
|
else:
|
|
589
592
|
statements.append(old_stmt)
|
|
593
|
+
stmt_idx += 1
|
|
590
594
|
|
|
591
595
|
return statements, any_update
|
|
592
596
|
|
|
@@ -163,6 +163,9 @@ class SimEnginePropagatorVEX(
|
|
|
163
163
|
self.state.store_register(stmt.offset, size, data)
|
|
164
164
|
self.state.add_replacement(self._codeloc(block_only=False), VEXReg(stmt.offset, size), data)
|
|
165
165
|
|
|
166
|
+
def _handle_PutI(self, stmt):
|
|
167
|
+
self._expr(stmt.data)
|
|
168
|
+
|
|
166
169
|
def _store_data(self, addr, data, size, endness):
|
|
167
170
|
# pylint: disable=unused-argument,no-self-use
|
|
168
171
|
if isinstance(addr, claripy.ast.Base):
|
|
@@ -260,6 +263,9 @@ class SimEnginePropagatorVEX(
|
|
|
260
263
|
size = expr.result_size(self.tyenv) // self.arch.byte_width
|
|
261
264
|
return self.state.load_register(expr.offset, size)
|
|
262
265
|
|
|
266
|
+
def _handle_GetI(self, expr):
|
|
267
|
+
return self.state.top(expr.result_size(self.tyenv))
|
|
268
|
+
|
|
263
269
|
def _handle_Load(self, expr):
|
|
264
270
|
addr = self._expr(expr.addr)
|
|
265
271
|
if addr is None or type(addr) in (Top, Bottom):
|
|
@@ -278,6 +284,13 @@ class SimEnginePropagatorVEX(
|
|
|
278
284
|
# print(expr.op, r)
|
|
279
285
|
return r
|
|
280
286
|
|
|
287
|
+
def _handle_Triop(self, expr: pyvex.IRExpr.Triop):
|
|
288
|
+
if not self.state.do_binops:
|
|
289
|
+
return self.state.top(expr.result_size(self.tyenv))
|
|
290
|
+
|
|
291
|
+
r = super()._handle_Triop(expr)
|
|
292
|
+
return r
|
|
293
|
+
|
|
281
294
|
def _handle_Conversion(self, expr):
|
|
282
295
|
expr_ = self._expr(expr.args[0])
|
|
283
296
|
to_size = expr.result_size(self.tyenv)
|
|
@@ -311,3 +324,5 @@ class SimEnginePropagatorVEX(
|
|
|
311
324
|
self.state.block_initial_reg_values[self.block.addr, dst.concrete_value].append(v)
|
|
312
325
|
|
|
313
326
|
super()._handle_Exit(stmt)
|
|
327
|
+
|
|
328
|
+
_handle_CmpF = _handle_CmpEQ
|
|
@@ -176,6 +176,9 @@ class SimEngineRDVEX(
|
|
|
176
176
|
return
|
|
177
177
|
self.state.kill_and_add_definition(reg, data)
|
|
178
178
|
|
|
179
|
+
def _handle_PutI(self, stmt):
|
|
180
|
+
pass
|
|
181
|
+
|
|
179
182
|
# e.g. STle(t6) = t21, t6 and/or t21 might include multiple values
|
|
180
183
|
def _handle_Store(self, stmt):
|
|
181
184
|
addr = self._expr(stmt.addr)
|
|
@@ -404,6 +407,9 @@ class SimEngineRDVEX(
|
|
|
404
407
|
|
|
405
408
|
return values
|
|
406
409
|
|
|
410
|
+
def _handle_GetI(self, expr: pyvex.IRExpr.GetI) -> MultiValues:
|
|
411
|
+
return MultiValues(self.state.top(expr.result_size(self.tyenv)))
|
|
412
|
+
|
|
407
413
|
# e.g. t27 = LDle:I64(t9), t9 might include multiple values
|
|
408
414
|
# caution: Is also called from StoreG
|
|
409
415
|
def _handle_Load(self, expr) -> MultiValues:
|
|
@@ -61,6 +61,9 @@ class SimEngineVRVEX(
|
|
|
61
61
|
return
|
|
62
62
|
self._assign_to_register(offset, r, size)
|
|
63
63
|
|
|
64
|
+
def _handle_PutI(self, stmt):
|
|
65
|
+
pass
|
|
66
|
+
|
|
64
67
|
def _handle_Store(self, stmt):
|
|
65
68
|
addr_r = self._expr(stmt.addr)
|
|
66
69
|
size = stmt.data.result_size(self.tyenv) // 8
|
|
@@ -159,6 +162,9 @@ class SimEngineVRVEX(
|
|
|
159
162
|
create_variable=self.stmt_idx not in self.reg_read_stmts_to_ignore,
|
|
160
163
|
)
|
|
161
164
|
|
|
165
|
+
def _handle_GetI(self, expr: pyvex.IRExpr.GetI):
|
|
166
|
+
return RichR(self.state.top(expr.result_size(self.tyenv)))
|
|
167
|
+
|
|
162
168
|
def _handle_Load(self, expr: pyvex.IRExpr.Load) -> RichR:
|
|
163
169
|
addr = self._expr(expr.addr)
|
|
164
170
|
size = expr.result_size(self.tyenv) // 8
|
|
@@ -33,6 +33,12 @@ class VEXIRSBScanner(SimEngineLightVEXMixin):
|
|
|
33
33
|
self.reg_read_stmt_id: Dict[int, int] = {}
|
|
34
34
|
self.reg_read_stmts_to_ignore: Set[int] = set()
|
|
35
35
|
|
|
36
|
+
def _top(self, size: int):
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
def _is_top(self, expr) -> bool:
|
|
40
|
+
return True
|
|
41
|
+
|
|
36
42
|
def _process_Stmt(self, whitelist=None):
|
|
37
43
|
self.tmps_with_64bit_regs = set()
|
|
38
44
|
self.tmps_assignment_stmtidx = {}
|
|
@@ -55,6 +61,9 @@ class VEXIRSBScanner(SimEngineLightVEXMixin):
|
|
|
55
61
|
self.reg_read_stmts_to_ignore.add(self.reg_read_stmt_id[old_reg_offset])
|
|
56
62
|
self.reg_with_reg_as_value[stmt.offset] = self.tmp_with_reg_as_value[stmt.data.tmp]
|
|
57
63
|
|
|
64
|
+
def _handle_PutI(self, stmt):
|
|
65
|
+
pass
|
|
66
|
+
|
|
58
67
|
def _handle_Load(self, expr):
|
|
59
68
|
pass
|
|
60
69
|
|
|
@@ -85,6 +94,9 @@ class VEXIRSBScanner(SimEngineLightVEXMixin):
|
|
|
85
94
|
if expr.offset in self.reg_with_reg_as_value:
|
|
86
95
|
del self.reg_with_reg_as_value[expr.offset]
|
|
87
96
|
|
|
97
|
+
def _handle_GetI(self, expr):
|
|
98
|
+
pass
|
|
99
|
+
|
|
88
100
|
def _handle_RdTmp(self, expr):
|
|
89
101
|
if expr.tmp in self.tmps_converted_to_32bit:
|
|
90
102
|
self.tmps_converted_to_32bit.remove(expr.tmp)
|