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.

Files changed (27) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_base.py +14 -1
  3. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +10 -6
  4. angr/analyses/decompiler/optimization_passes/__init__.py +2 -0
  5. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +380 -0
  6. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +4 -1
  7. angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -0
  8. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +71 -3
  9. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +162 -0
  10. angr/analyses/decompiler/structured_codegen/__init__.py +1 -1
  11. angr/analyses/decompiler/structured_codegen/c.py +72 -99
  12. angr/analyses/decompiler/utils.py +5 -1
  13. angr/analyses/propagator/engine_vex.py +15 -0
  14. angr/analyses/reaching_definitions/engine_vex.py +6 -0
  15. angr/analyses/variable_recovery/engine_vex.py +6 -0
  16. angr/analyses/variable_recovery/irsb_scanner.py +12 -0
  17. angr/engines/light/engine.py +126 -15
  18. angr/knowledge_plugins/functions/function.py +4 -0
  19. angr/storage/memory_mixins/paged_memory/pages/list_page.py +20 -5
  20. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +2 -1
  21. angr/storage/memory_mixins/simple_interface_mixin.py +4 -0
  22. {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/METADATA +6 -6
  23. {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/RECORD +27 -25
  24. {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/LICENSE +0 -0
  25. {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/WHEEL +0 -0
  26. {angr-9.2.97.dist-info → angr-9.2.98.dist-info}/entry_points.txt +0 -0
  27. {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
- @classmethod
3558
- def handle(cls, obj):
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
- @classmethod
3563
- def handle_default(cls, obj):
3561
+ def handle_default(self, obj):
3564
3562
  return obj
3565
3563
 
3566
- @classmethod
3567
- def handle_CFunction(cls, obj):
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
- @classmethod
3572
- def handle_CStatements(cls, obj):
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
- @classmethod
3577
- def handle_CWhileLoop(cls, obj):
3578
- obj.condition = cls.handle(obj.condition)
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
- @classmethod
3583
- def handle_CDoWhileLoop(cls, obj):
3584
- obj.condition = cls.handle(obj.condition)
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
- @classmethod
3589
- def handle_CForLoop(cls, obj):
3590
- obj.initializer = cls.handle(obj.initializer)
3591
- obj.condition = cls.handle(obj.condition)
3592
- obj.iterator = cls.handle(obj.iterator)
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
- @classmethod
3597
- def handle_CIfElse(cls, obj):
3589
+ def handle_CIfElse(self, obj):
3598
3590
  obj.condition_and_nodes = [
3599
- (cls.handle(condition), cls.handle(node)) for condition, node in obj.condition_and_nodes
3591
+ (self.handle(condition), self.handle(node)) for condition, node in obj.condition_and_nodes
3600
3592
  ]
3601
- obj.else_node = cls.handle(obj.else_node)
3593
+ obj.else_node = self.handle(obj.else_node)
3602
3594
  return obj
3603
3595
 
3604
- @classmethod
3605
- def handle_CIfBreak(cls, obj):
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
- @classmethod
3610
- def handle_CSwitchCase(cls, obj):
3611
- obj.switch = cls.handle(obj.switch)
3612
- obj.cases = [(case, cls.handle(body)) for case, body in obj.cases]
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
- @classmethod
3617
- def handle_CAssignment(cls, obj):
3618
- obj.lhs = cls.handle(obj.lhs)
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
- @classmethod
3623
- def handle_CFunctionCall(cls, obj):
3624
- obj.callee_target = cls.handle(obj.callee_target)
3625
- obj.args = [cls.handle(arg) for arg in obj.args]
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
- @classmethod
3630
- def handle_CReturn(cls, obj):
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
- @classmethod
3635
- def handle_CGoto(cls, obj):
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
- @classmethod
3640
- def handle_CIndexedVariable(cls, obj):
3641
- obj.variable = cls.handle(obj.variable)
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
- @classmethod
3646
- def handle_CVariableField(cls, obj):
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
- @classmethod
3651
- def handle_CUnaryOp(cls, obj):
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
- @classmethod
3656
- def handle_CBinaryOp(cls, obj):
3657
- obj.lhs = cls.handle(obj.lhs)
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
- @classmethod
3662
- def handle_CTypeCast(cls, obj):
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
- @classmethod
3667
- def handle_CITE(cls, obj):
3668
- obj.cond = cls.handle(obj.cond)
3669
- obj.iftrue = cls.handle(obj.iftrue)
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
- @classmethod
3706
- def handle_CAssignment(cls, obj):
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
- @classmethod
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] = cls.collapse(arg_ty, c_arg)
3691
+ obj.args[i] = self.collapse(arg_ty, c_arg)
3714
3692
  return super().handle_CFunctionCall(obj)
3715
3693
 
3716
- @classmethod
3717
- def handle_CReturn(cls, obj: CReturn):
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
- @classmethod
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 = cls.collapse(obj.common_type, obj.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 = cls.collapse(obj.common_type, obj.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
- @classmethod
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 = cls.collapse(obj.dst_type, obj.expr)
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
- @classmethod
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 cls.handle(obj)
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
- @classmethod
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
- for stmt_idx, stmt in enumerate(block.statements):
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)