angr 9.2.76__py3-none-win_amd64.whl → 9.2.77__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/indirect_jump_resolvers/amd64_pe_iat.py +7 -1
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +7 -1
- angr/analyses/decompiler/clinic.py +4 -1
- angr/analyses/decompiler/condition_processor.py +4 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +4 -3
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +3 -0
- angr/analyses/propagator/engine_ail.py +1 -1
- angr/analyses/reaching_definitions/engine_ail.py +3 -6
- angr/analyses/reaching_definitions/engine_vex.py +32 -2
- angr/analyses/reaching_definitions/function_handler.py +1 -1
- angr/analyses/reaching_definitions/rd_initializer.py +6 -6
- angr/analyses/reaching_definitions/rd_state.py +9 -11
- angr/analyses/typehoon/typevars.py +19 -29
- angr/analyses/variable_recovery/variable_recovery_fast.py +33 -31
- angr/engines/light/engine.py +1 -1
- angr/keyed_region.py +19 -3
- angr/knowledge_plugins/functions/function.py +8 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +53 -44
- angr/knowledge_plugins/key_definitions/liveness.py +102 -34
- angr/knowledge_plugins/key_definitions/rd_model.py +4 -4
- angr/knowledge_plugins/propagations/states.py +3 -1
- angr/knowledge_plugins/variables/variable_manager.py +51 -25
- angr/lib/angr_native.dll +0 -0
- angr/misc/bug_report.py +2 -2
- angr/storage/memory_mixins/__init__.py +3 -2
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +63 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +5 -0
- {angr-9.2.76.dist-info → angr-9.2.77.dist-info}/METADATA +6 -6
- {angr-9.2.76.dist-info → angr-9.2.77.dist-info}/RECORD +37 -36
- tests/analyses/decompiler/test_decompiler.py +5 -1
- tests/analyses/test_flirt.py +3 -1
- tests/procedures/libc/test_string.py +2 -1
- {angr-9.2.76.dist-info → angr-9.2.77.dist-info}/LICENSE +0 -0
- {angr-9.2.76.dist-info → angr-9.2.77.dist-info}/WHEEL +0 -0
- {angr-9.2.76.dist-info → angr-9.2.77.dist-info}/top_level.txt +0 -0
|
@@ -370,6 +370,14 @@ class LiveDefinitions:
|
|
|
370
370
|
if isinstance(anno, DefinitionAnnotation):
|
|
371
371
|
yield anno.definition
|
|
372
372
|
|
|
373
|
+
@staticmethod
|
|
374
|
+
def extract_defs_from_annotations(annos: Iterable["Annotation"]) -> Set[Definition]:
|
|
375
|
+
defs = set()
|
|
376
|
+
for anno in annos:
|
|
377
|
+
if isinstance(anno, DefinitionAnnotation):
|
|
378
|
+
defs.add(anno.definition)
|
|
379
|
+
return defs
|
|
380
|
+
|
|
373
381
|
@staticmethod
|
|
374
382
|
def extract_defs_from_mv(mv: MultiValues) -> Generator[Definition, None, None]:
|
|
375
383
|
for vs in mv.values():
|
|
@@ -614,64 +622,60 @@ class LiveDefinitions:
|
|
|
614
622
|
|
|
615
623
|
def get_definitions(
|
|
616
624
|
self, thing: Union[Atom, Definition[Atom], Iterable[Atom], Iterable[Definition[Atom]], MultiValues]
|
|
617
|
-
) ->
|
|
625
|
+
) -> Set[Definition[Atom]]:
|
|
618
626
|
if isinstance(thing, MultiValues):
|
|
627
|
+
defs = set()
|
|
619
628
|
for vs in thing.values():
|
|
620
629
|
for v in vs:
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
yield anno.definition
|
|
624
|
-
return
|
|
630
|
+
defs.update(LiveDefinitions.extract_defs_from_annotations(v.annotations))
|
|
631
|
+
return defs
|
|
625
632
|
elif isinstance(thing, Atom):
|
|
626
633
|
pass
|
|
627
634
|
elif isinstance(thing, Definition):
|
|
628
635
|
thing = thing.atom
|
|
629
636
|
else:
|
|
637
|
+
defs = set()
|
|
630
638
|
for atom2 in thing:
|
|
631
|
-
|
|
632
|
-
return
|
|
639
|
+
defs |= self.get_definitions(atom2)
|
|
640
|
+
return defs
|
|
633
641
|
|
|
634
642
|
if isinstance(thing, Register):
|
|
635
|
-
|
|
643
|
+
return self.get_register_definitions(thing.reg_offset, thing.size)
|
|
636
644
|
elif isinstance(thing, MemoryLocation):
|
|
637
645
|
if isinstance(thing.addr, SpOffset):
|
|
638
|
-
|
|
646
|
+
return self.get_stack_definitions(thing.addr.offset, thing.size)
|
|
639
647
|
elif isinstance(thing.addr, HeapAddress):
|
|
640
|
-
|
|
648
|
+
return self.get_heap_definitions(thing.addr.value, size=thing.size)
|
|
641
649
|
elif isinstance(thing.addr, int):
|
|
642
|
-
|
|
650
|
+
return self.get_memory_definitions(thing.addr, thing.size)
|
|
643
651
|
else:
|
|
644
|
-
return
|
|
652
|
+
return set()
|
|
645
653
|
elif isinstance(thing, Tmp):
|
|
646
|
-
|
|
654
|
+
return self.get_tmp_definitions(thing.tmp_idx)
|
|
647
655
|
else:
|
|
656
|
+
defs = set()
|
|
648
657
|
for mvs in self.others.get(thing, {}).values():
|
|
649
658
|
for mv in mvs:
|
|
650
|
-
|
|
659
|
+
defs |= self.get_definitions(mv)
|
|
660
|
+
return defs
|
|
651
661
|
|
|
652
|
-
def get_tmp_definitions(self, tmp_idx: int) ->
|
|
662
|
+
def get_tmp_definitions(self, tmp_idx: int) -> Set[Definition]:
|
|
653
663
|
if tmp_idx in self.tmps:
|
|
654
|
-
|
|
664
|
+
return self.tmps[tmp_idx]
|
|
655
665
|
else:
|
|
656
|
-
return
|
|
666
|
+
return set()
|
|
657
667
|
|
|
658
|
-
def get_register_definitions(self, reg_offset: int, size: int
|
|
668
|
+
def get_register_definitions(self, reg_offset: int, size: int) -> Set[Definition]:
|
|
659
669
|
try:
|
|
660
|
-
|
|
661
|
-
reg_offset,
|
|
662
|
-
size=size,
|
|
663
|
-
endness=endness,
|
|
664
|
-
)
|
|
670
|
+
annotations = self.registers.load_annotations(reg_offset, size)
|
|
665
671
|
except SimMemoryMissingError as ex:
|
|
666
|
-
# load values and stop at the missing location
|
|
667
672
|
if ex.missing_addr > reg_offset:
|
|
668
|
-
|
|
669
|
-
reg_offset, size=ex.missing_addr - reg_offset, endness=endness
|
|
670
|
-
)
|
|
673
|
+
annotations = self.registers.load_annotations(reg_offset, ex.missing_addr - reg_offset)
|
|
671
674
|
else:
|
|
672
675
|
# nothing we can do
|
|
673
|
-
return
|
|
674
|
-
|
|
676
|
+
return set()
|
|
677
|
+
|
|
678
|
+
return LiveDefinitions.extract_defs_from_annotations(annotations)
|
|
675
679
|
|
|
676
680
|
def get_stack_values(self, stack_offset: int, size: int, endness: str) -> Optional[MultiValues]:
|
|
677
681
|
stack_addr = self.stack_offset_to_stack_addr(stack_offset)
|
|
@@ -680,31 +684,36 @@ class LiveDefinitions:
|
|
|
680
684
|
except SimMemoryMissingError:
|
|
681
685
|
return None
|
|
682
686
|
|
|
683
|
-
def get_stack_definitions(self, stack_offset: int, size: int
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
687
|
+
def get_stack_definitions(self, stack_offset: int, size: int) -> Set[Definition]:
|
|
688
|
+
try:
|
|
689
|
+
stack_addr = self.stack_offset_to_stack_addr(stack_offset)
|
|
690
|
+
annotations = self.stack.load_annotations(stack_addr, size)
|
|
691
|
+
except SimMemoryMissingError:
|
|
692
|
+
return set()
|
|
688
693
|
|
|
689
|
-
|
|
694
|
+
return LiveDefinitions.extract_defs_from_annotations(annotations)
|
|
695
|
+
|
|
696
|
+
def get_heap_definitions(self, heap_addr: int, size: int) -> Set[Definition]:
|
|
690
697
|
try:
|
|
691
|
-
|
|
698
|
+
annotations = self.heap.load_annotations(heap_addr, size)
|
|
692
699
|
except SimMemoryMissingError:
|
|
693
|
-
return
|
|
694
|
-
|
|
700
|
+
return set()
|
|
701
|
+
|
|
702
|
+
return LiveDefinitions.extract_defs_from_annotations(annotations)
|
|
695
703
|
|
|
696
|
-
def get_memory_definitions(self, addr: int, size: int
|
|
704
|
+
def get_memory_definitions(self, addr: int, size: int) -> Set[Definition]:
|
|
697
705
|
try:
|
|
698
|
-
|
|
706
|
+
annotations = self.memory.load_annotations(addr, size)
|
|
699
707
|
except SimMemoryMissingError:
|
|
700
|
-
return
|
|
701
|
-
|
|
708
|
+
return set()
|
|
709
|
+
|
|
710
|
+
return LiveDefinitions.extract_defs_from_annotations(annotations)
|
|
702
711
|
|
|
703
712
|
@deprecated("get_definitions")
|
|
704
713
|
def get_definitions_from_atoms(self, atoms: Iterable[Atom]) -> Iterable[Definition]:
|
|
705
714
|
result = set()
|
|
706
715
|
for atom in atoms:
|
|
707
|
-
result |=
|
|
716
|
+
result |= self.get_definitions(atom)
|
|
708
717
|
return result
|
|
709
718
|
|
|
710
719
|
@deprecated("get_values")
|
|
@@ -905,7 +914,7 @@ class LiveDefinitions:
|
|
|
905
914
|
|
|
906
915
|
def add_memory_use(self, atom: MemoryLocation, code_loc: CodeLocation, expr: Optional[Any] = None) -> None:
|
|
907
916
|
# get all current definitions
|
|
908
|
-
current_defs:
|
|
917
|
+
current_defs: Set[Definition] = self.get_definitions(atom)
|
|
909
918
|
|
|
910
919
|
for current_def in current_defs:
|
|
911
920
|
self.add_memory_use_by_def(current_def, code_loc, expr=expr)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from typing import DefaultDict, Optional, List, Set, Tuple, TYPE_CHECKING
|
|
1
|
+
from typing import DefaultDict, Optional, List, Set, Tuple, Dict, TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
|
+
from itertools import chain
|
|
4
5
|
|
|
6
|
+
from angr.utils.constants import DEFAULT_STATEMENT
|
|
5
7
|
from angr.knowledge_plugins.key_definitions.atoms import Tmp
|
|
6
8
|
|
|
7
9
|
from .constants import ObservationPointType, OP_BEFORE, OP_AFTER
|
|
@@ -15,6 +17,7 @@ LocationType = Tuple[int, Optional[int], Optional[int]] # block addr, block ID,
|
|
|
15
17
|
LocationWithPosType = Tuple[
|
|
16
18
|
int, Optional[int], Optional[int], ObservationPointType
|
|
17
19
|
] # block addr, block ID, stmt ID, before/after
|
|
20
|
+
BlockAddrType = Tuple[int, Optional[int]] # block addr, block ID
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
class Liveness:
|
|
@@ -25,30 +28,37 @@ class Liveness:
|
|
|
25
28
|
def __init__(self):
|
|
26
29
|
self.curr_live_defs: Set["Definition"] = set()
|
|
27
30
|
self.curr_loc: Optional[LocationType] = None
|
|
28
|
-
self.
|
|
29
|
-
self.
|
|
30
|
-
self.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
self.curr_block: Optional[BlockAddrType] = None
|
|
32
|
+
self.curr_stmt_idx: Optional[int] = None
|
|
33
|
+
self.blockstart_to_defs: DefaultDict[BlockAddrType, Set["Definition"]] = defaultdict(set)
|
|
34
|
+
self.blockend_to_defs: DefaultDict[BlockAddrType, Set["Definition"]] = defaultdict(set)
|
|
35
|
+
self.loc_to_killed_defs: DefaultDict[BlockAddrType, Dict[int, Set["Definition"]]] = defaultdict(dict)
|
|
36
|
+
self.loc_to_added_defs: DefaultDict[BlockAddrType, Dict[int, Set["Definition"]]] = defaultdict(dict)
|
|
37
|
+
self._node_max_stmt_id: DefaultDict[BlockAddrType, int] = defaultdict(int)
|
|
38
|
+
|
|
39
|
+
def add_def(self, d: "Definition") -> None:
|
|
34
40
|
self.curr_live_defs.add(d)
|
|
35
|
-
self.
|
|
41
|
+
if self.curr_stmt_idx not in self.loc_to_added_defs[self.curr_block]:
|
|
42
|
+
self.loc_to_added_defs[self.curr_block][self.curr_stmt_idx] = set()
|
|
43
|
+
self.loc_to_added_defs[self.curr_block][self.curr_stmt_idx].add(d)
|
|
36
44
|
|
|
37
45
|
def kill_def(self, d: "Definition") -> None:
|
|
38
46
|
self.curr_live_defs.discard(d)
|
|
47
|
+
if self.curr_stmt_idx not in self.loc_to_killed_defs[self.curr_block]:
|
|
48
|
+
self.loc_to_killed_defs[self.curr_block][self.curr_stmt_idx] = set()
|
|
49
|
+
self.loc_to_killed_defs[self.curr_block][self.curr_stmt_idx].add(d)
|
|
39
50
|
|
|
40
|
-
def
|
|
41
|
-
if self.
|
|
42
|
-
|
|
43
|
-
self.def_to_liveness[live_def].add(self.curr_loc)
|
|
44
|
-
self.loc_to_defs[self.curr_loc + (OP_AFTER,)] |= self.curr_live_defs
|
|
51
|
+
def make_liveness_snapshot(self) -> None:
|
|
52
|
+
if self.curr_block is not None:
|
|
53
|
+
self.blockend_to_defs[self.curr_block] |= self.curr_live_defs
|
|
45
54
|
|
|
46
55
|
def at_new_stmt(self, code_loc: "CodeLocation") -> None:
|
|
47
56
|
"""
|
|
48
57
|
Only support moving from a statement to the next statement within one basic block.
|
|
49
58
|
"""
|
|
50
|
-
self.complete_loc()
|
|
51
59
|
self.curr_loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx
|
|
60
|
+
self.curr_block = code_loc.block_addr, code_loc.block_idx
|
|
61
|
+
self.curr_stmt_idx = code_loc.stmt_idx
|
|
52
62
|
if (
|
|
53
63
|
code_loc.stmt_idx is not None
|
|
54
64
|
and code_loc.stmt_idx > self._node_max_stmt_id[(code_loc.block_addr, code_loc.block_idx)]
|
|
@@ -59,44 +69,102 @@ class Liveness:
|
|
|
59
69
|
"""
|
|
60
70
|
Only support moving to a new block from one or more blocks.
|
|
61
71
|
"""
|
|
72
|
+
self.make_liveness_snapshot()
|
|
73
|
+
|
|
62
74
|
loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx
|
|
63
|
-
key = code_loc.block_addr, code_loc.block_idx
|
|
75
|
+
key = code_loc.block_addr, code_loc.block_idx
|
|
64
76
|
for pred_codeloc in pred_codelocs:
|
|
65
|
-
|
|
66
|
-
# external code location
|
|
67
|
-
pred_max_stmt_id = None
|
|
68
|
-
else:
|
|
69
|
-
pred_max_stmt_id = self._node_max_stmt_id[(pred_codeloc.block_addr, pred_codeloc.block_idx)]
|
|
70
|
-
pred_key = pred_codeloc.block_addr, pred_codeloc.block_idx, pred_max_stmt_id, OP_AFTER
|
|
71
|
-
all_pred_defs = self.loc_to_defs[pred_key]
|
|
77
|
+
all_pred_defs = self.blockend_to_defs[pred_codeloc.block_addr, pred_codeloc.block_idx]
|
|
72
78
|
|
|
73
79
|
# remove tmp defs
|
|
74
80
|
pred_defs = set()
|
|
75
81
|
for pred_def in all_pred_defs:
|
|
76
82
|
if not isinstance(pred_def.atom, Tmp):
|
|
77
83
|
pred_defs.add(pred_def)
|
|
78
|
-
|
|
79
|
-
self.def_to_liveness[pred_def].add(loc)
|
|
80
|
-
self.loc_to_defs[key] |= pred_defs
|
|
84
|
+
self.blockstart_to_defs[key] |= pred_defs
|
|
81
85
|
|
|
82
|
-
self.curr_live_defs =
|
|
86
|
+
self.curr_live_defs = self.blockstart_to_defs[key].copy()
|
|
83
87
|
self.curr_loc = loc
|
|
88
|
+
self.curr_stmt_idx = 0
|
|
84
89
|
|
|
85
90
|
def find_defs_at(self, code_loc: "CodeLocation", op: int = OP_BEFORE) -> Set["Definition"]:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
return self.find_defs_at_raw(code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx, op=op)
|
|
92
|
+
|
|
93
|
+
def find_defs_at_raw(
|
|
94
|
+
self, block_addr: int, block_idx: Optional[int], stmt_idx: Optional[int], op: int = OP_BEFORE
|
|
95
|
+
) -> Set["Definition"]:
|
|
96
|
+
block: BlockAddrType = block_addr, block_idx
|
|
97
|
+
if block not in self.blockstart_to_defs:
|
|
98
|
+
defs = set()
|
|
99
|
+
else:
|
|
100
|
+
defs = self.blockstart_to_defs[block].copy()
|
|
101
|
+
|
|
102
|
+
if stmt_idx is None:
|
|
103
|
+
return defs
|
|
104
|
+
|
|
105
|
+
added_defs = self.loc_to_added_defs[block] if block in self.loc_to_added_defs else None
|
|
106
|
+
killed_defs = self.loc_to_killed_defs[block] if block in self.loc_to_added_defs else None
|
|
107
|
+
|
|
108
|
+
if stmt_idx == DEFAULT_STATEMENT:
|
|
109
|
+
end_stmt_idx = self._node_max_stmt_id[block] + 1
|
|
110
|
+
else:
|
|
111
|
+
if op == OP_BEFORE:
|
|
112
|
+
end_stmt_idx = stmt_idx
|
|
89
113
|
else:
|
|
90
|
-
|
|
114
|
+
end_stmt_idx = stmt_idx + 1
|
|
115
|
+
|
|
116
|
+
if added_defs is not None and killed_defs is not None:
|
|
117
|
+
indices = chain(added_defs, killed_defs)
|
|
118
|
+
elif added_defs is None and killed_defs is not None:
|
|
119
|
+
indices = killed_defs
|
|
120
|
+
elif added_defs is not None and killed_defs is None:
|
|
121
|
+
indices = added_defs
|
|
91
122
|
else:
|
|
92
|
-
|
|
93
|
-
|
|
123
|
+
indices = []
|
|
124
|
+
|
|
125
|
+
tmp_indices = []
|
|
126
|
+
if killed_defs is not None and None in killed_defs:
|
|
127
|
+
# External codeloc
|
|
128
|
+
defs.difference_update(killed_defs[None])
|
|
129
|
+
for idx in indices:
|
|
130
|
+
if idx is not None:
|
|
131
|
+
tmp_indices.append(idx)
|
|
132
|
+
indices = tmp_indices
|
|
133
|
+
|
|
134
|
+
tmp_indices = []
|
|
135
|
+
if added_defs is not None and None in added_defs:
|
|
136
|
+
# External codeloc
|
|
137
|
+
defs.update(added_defs[None])
|
|
138
|
+
for idx in indices:
|
|
139
|
+
if idx is not None:
|
|
140
|
+
tmp_indices.append(idx)
|
|
141
|
+
indices = tmp_indices
|
|
142
|
+
|
|
143
|
+
for idx in sorted(indices):
|
|
144
|
+
if idx >= end_stmt_idx:
|
|
145
|
+
break
|
|
146
|
+
if killed_defs is not None and idx in killed_defs:
|
|
147
|
+
defs.difference_update(killed_defs[idx])
|
|
148
|
+
if added_defs is not None and idx in added_defs:
|
|
149
|
+
defs.update(added_defs[idx])
|
|
150
|
+
|
|
151
|
+
if stmt_idx == DEFAULT_STATEMENT and op == OP_AFTER:
|
|
152
|
+
if killed_defs is not None and DEFAULT_STATEMENT in killed_defs:
|
|
153
|
+
defs.difference_update(killed_defs[DEFAULT_STATEMENT])
|
|
154
|
+
if added_defs is not None and DEFAULT_STATEMENT in added_defs:
|
|
155
|
+
defs.update(added_defs[DEFAULT_STATEMENT])
|
|
156
|
+
|
|
157
|
+
return defs
|
|
94
158
|
|
|
95
159
|
def copy(self) -> "Liveness":
|
|
96
160
|
o = Liveness()
|
|
97
161
|
o.curr_live_defs = self.curr_live_defs.copy()
|
|
98
162
|
o.curr_loc = self.curr_loc
|
|
99
|
-
o.
|
|
100
|
-
o.
|
|
163
|
+
o.curr_block = self.curr_block
|
|
164
|
+
o.curr_stmt_idx = self.curr_stmt_idx
|
|
165
|
+
o.blockstart_to_defs = self.blockstart_to_defs.copy()
|
|
166
|
+
o.blockend_to_defs = self.blockend_to_defs.copy()
|
|
167
|
+
o.loc_to_added_defs = self.loc_to_added_defs.copy()
|
|
168
|
+
o.loc_to_killed_defs = self.loc_to_killed_defs.copy()
|
|
101
169
|
o._node_max_stmt_id = self._node_max_stmt_id.copy()
|
|
102
170
|
return o
|
|
@@ -32,9 +32,9 @@ class ReachingDefinitionsModel:
|
|
|
32
32
|
len(self.observed_results),
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
def add_def(self, d: "Definition"
|
|
35
|
+
def add_def(self, d: "Definition") -> None:
|
|
36
36
|
if self.liveness is not None:
|
|
37
|
-
self.liveness.add_def(d
|
|
37
|
+
self.liveness.add_def(d)
|
|
38
38
|
|
|
39
39
|
def kill_def(self, d: "Definition") -> None:
|
|
40
40
|
if self.liveness is not None:
|
|
@@ -48,9 +48,9 @@ class ReachingDefinitionsModel:
|
|
|
48
48
|
if self.liveness is not None:
|
|
49
49
|
self.liveness.at_new_block(code_loc, pred_codelocs)
|
|
50
50
|
|
|
51
|
-
def
|
|
51
|
+
def make_liveness_snapshot(self) -> None:
|
|
52
52
|
if self.liveness is not None:
|
|
53
|
-
self.liveness.
|
|
53
|
+
self.liveness.make_liveness_snapshot()
|
|
54
54
|
|
|
55
55
|
def find_defs_at(self, code_loc: "CodeLocation", op: int = OP_BEFORE) -> Set["Definition"]:
|
|
56
56
|
return self.liveness.find_defs_at(code_loc, op=op)
|
|
@@ -808,7 +808,9 @@ class PropagatorAILState(PropagatorState):
|
|
|
808
808
|
or isinstance(old, ailment.Expr.Register)
|
|
809
809
|
and (old.reg_offset == self.arch.sp_offset or (not bp_as_gpr and old.reg_offset == self.arch.bp_offset))
|
|
810
810
|
):
|
|
811
|
-
self._replacements[codeloc][old] =
|
|
811
|
+
self._replacements[codeloc][old] = (
|
|
812
|
+
new if stmt_to_remove is None else {"expr": new, "stmt_to_remove": stmt_to_remove}
|
|
813
|
+
)
|
|
812
814
|
replaced = True
|
|
813
815
|
else:
|
|
814
816
|
prop_count = 0
|
|
@@ -90,6 +90,7 @@ class VariableManagerInternal(Serializable):
|
|
|
90
90
|
self._atom_to_variable: Dict[
|
|
91
91
|
Union[Tuple[int, int], Tuple[int, int, int]], Dict[int, Set[Tuple[SimVariable, int]]]
|
|
92
92
|
] = defaultdict(_defaultdict_set)
|
|
93
|
+
self._ident_to_variable: Dict[str, SimVariable] = {}
|
|
93
94
|
self._variable_counters = {
|
|
94
95
|
"register": count(),
|
|
95
96
|
"stack": count(),
|
|
@@ -109,6 +110,9 @@ class VariableManagerInternal(Serializable):
|
|
|
109
110
|
self.variable_to_types: Dict[SimVariable, SimType] = {}
|
|
110
111
|
self.variables_with_manual_types = set()
|
|
111
112
|
|
|
113
|
+
# optimization
|
|
114
|
+
self._variables_without_writes = set()
|
|
115
|
+
|
|
112
116
|
self.ret_val_size = None
|
|
113
117
|
|
|
114
118
|
#
|
|
@@ -241,6 +245,7 @@ class VariableManagerInternal(Serializable):
|
|
|
241
245
|
model._phi_variables[var] = set()
|
|
242
246
|
else:
|
|
243
247
|
model._variables.add(var)
|
|
248
|
+
model._ident_to_variable[var.ident] = var
|
|
244
249
|
|
|
245
250
|
# variable accesses
|
|
246
251
|
for varaccess_pb2 in cmsg.accesses:
|
|
@@ -314,6 +319,8 @@ class VariableManagerInternal(Serializable):
|
|
|
314
319
|
|
|
315
320
|
region.add_variable(offset, var)
|
|
316
321
|
|
|
322
|
+
model._variables_without_writes = model.get_variables_without_writes()
|
|
323
|
+
|
|
317
324
|
return model
|
|
318
325
|
|
|
319
326
|
#
|
|
@@ -338,7 +345,7 @@ class VariableManagerInternal(Serializable):
|
|
|
338
345
|
ident = "i%s_%d" % (prefix, next(self._variable_counters[sort]))
|
|
339
346
|
return ident
|
|
340
347
|
|
|
341
|
-
def add_variable(self, sort, start, variable):
|
|
348
|
+
def add_variable(self, sort, start, variable: SimVariable):
|
|
342
349
|
if sort == "stack":
|
|
343
350
|
region = self._stack_region
|
|
344
351
|
elif sort == "register":
|
|
@@ -347,17 +354,17 @@ class VariableManagerInternal(Serializable):
|
|
|
347
354
|
region = self._global_region
|
|
348
355
|
else:
|
|
349
356
|
raise ValueError("Unsupported sort %s in add_variable()." % sort)
|
|
350
|
-
|
|
351
|
-
if
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
variable.
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
pass
|
|
357
|
+
|
|
358
|
+
# find if there is already an existing variable with the same identifier
|
|
359
|
+
if variable.ident in self._ident_to_variable:
|
|
360
|
+
existing_var = self._ident_to_variable[variable.ident]
|
|
361
|
+
if existing_var.name is not None and not variable.renamed:
|
|
362
|
+
variable.name = existing_var.name
|
|
363
|
+
variable.renamed = existing_var.renamed
|
|
364
|
+
self._ident_to_variable[variable.ident] = variable
|
|
359
365
|
region.add_variable(start, variable)
|
|
360
366
|
self._variables.add(variable)
|
|
367
|
+
self._variables_without_writes.add(variable)
|
|
361
368
|
|
|
362
369
|
def set_variable(self, sort, start, variable: SimVariable):
|
|
363
370
|
if sort == "stack":
|
|
@@ -368,17 +375,15 @@ class VariableManagerInternal(Serializable):
|
|
|
368
375
|
region = self._global_region
|
|
369
376
|
else:
|
|
370
377
|
raise ValueError("Unsupported sort %s in set_variable()." % sort)
|
|
371
|
-
|
|
372
|
-
if
|
|
373
|
-
|
|
374
|
-
if
|
|
375
|
-
variable.name =
|
|
376
|
-
variable.renamed =
|
|
377
|
-
else:
|
|
378
|
-
# implicitly overwrite or add I guess
|
|
379
|
-
pass
|
|
378
|
+
# find if there is already an existing variable with the same identifier
|
|
379
|
+
if variable.ident in self._ident_to_variable:
|
|
380
|
+
existing_var = self._ident_to_variable[variable.ident]
|
|
381
|
+
if existing_var.name is not None and not variable.renamed:
|
|
382
|
+
variable.name = existing_var.name
|
|
383
|
+
variable.renamed = existing_var.renamed
|
|
380
384
|
region.set_variable(start, variable)
|
|
381
385
|
self._variables.add(variable)
|
|
386
|
+
self._variables_without_writes.add(variable)
|
|
382
387
|
|
|
383
388
|
def write_to(self, variable, offset, location, overwrite=False, atom=None):
|
|
384
389
|
self._record_variable_access(
|
|
@@ -404,17 +409,19 @@ class VariableManagerInternal(Serializable):
|
|
|
404
409
|
overwrite=False,
|
|
405
410
|
atom=None,
|
|
406
411
|
):
|
|
407
|
-
# TODO can this line be removed, should we be only adding to _variables in add_variable?
|
|
408
|
-
self._variables.add(variable)
|
|
409
412
|
atom_hash = (hash(atom) & 0xFFFF_FFFF) if atom is not None else None
|
|
410
413
|
if overwrite:
|
|
411
414
|
self._variable_accesses[variable] = {VariableAccess(variable, sort, location, offset, atom_hash=atom_hash)}
|
|
412
415
|
else:
|
|
413
416
|
self._variable_accesses[variable].add(VariableAccess(variable, sort, location, offset, atom_hash=atom_hash))
|
|
414
417
|
self.record_variable(location, variable, offset, overwrite=overwrite, atom=atom)
|
|
418
|
+
if sort == VariableAccessSort.WRITE and variable in self._variables_without_writes:
|
|
419
|
+
self._variables_without_writes.discard(variable)
|
|
415
420
|
|
|
416
421
|
def record_variable(self, location: "CodeLocation", variable, offset, overwrite=False, atom=None):
|
|
417
|
-
self.
|
|
422
|
+
if variable.ident not in self._ident_to_variable:
|
|
423
|
+
self._ident_to_variable[variable.ident] = variable
|
|
424
|
+
self._variables.add(variable)
|
|
418
425
|
var_and_offset = variable, offset
|
|
419
426
|
atom_hash = (hash(atom) & 0xFFFF_FFFF) if atom is not None else None
|
|
420
427
|
key = (
|
|
@@ -693,7 +700,7 @@ class VariableManagerInternal(Serializable):
|
|
|
693
700
|
variables[phi] = self._phi_variables[phi]
|
|
694
701
|
return variables
|
|
695
702
|
|
|
696
|
-
def
|
|
703
|
+
def get_variables_without_writes(self) -> List[SimVariable]:
|
|
697
704
|
"""
|
|
698
705
|
Get all variables that have never been written to.
|
|
699
706
|
|
|
@@ -703,16 +710,35 @@ class VariableManagerInternal(Serializable):
|
|
|
703
710
|
def has_write_access(accesses):
|
|
704
711
|
return any(acc for acc in accesses if acc.access_type == VariableAccessSort.WRITE)
|
|
705
712
|
|
|
713
|
+
input_variables = []
|
|
714
|
+
|
|
715
|
+
for variable, accesses in self._variable_accesses.items():
|
|
716
|
+
if variable in self._phi_variables:
|
|
717
|
+
# a phi variable is definitely not an input variable
|
|
718
|
+
continue
|
|
719
|
+
if not has_write_access(accesses):
|
|
720
|
+
input_variables.append(variable)
|
|
721
|
+
|
|
722
|
+
return input_variables
|
|
723
|
+
|
|
724
|
+
def input_variables(self, exclude_specials: bool = True):
|
|
725
|
+
"""
|
|
726
|
+
Get all variables that have never been written to.
|
|
727
|
+
|
|
728
|
+
:return: A list of variables that are never written to.
|
|
729
|
+
"""
|
|
730
|
+
|
|
706
731
|
def has_read_access(accesses):
|
|
707
732
|
return any(acc for acc in accesses if acc.access_type == VariableAccessSort.READ)
|
|
708
733
|
|
|
709
734
|
input_variables = []
|
|
710
735
|
|
|
711
|
-
for variable
|
|
736
|
+
for variable in self._variables_without_writes:
|
|
712
737
|
if variable in self._phi_variables:
|
|
713
738
|
# a phi variable is definitely not an input variable
|
|
714
739
|
continue
|
|
715
|
-
|
|
740
|
+
accesses = self._variable_accesses[variable]
|
|
741
|
+
if has_read_access(accesses):
|
|
716
742
|
if not exclude_specials or not variable.category:
|
|
717
743
|
input_variables.append(variable)
|
|
718
744
|
|
angr/lib/angr_native.dll
CHANGED
|
Binary file
|
angr/misc/bug_report.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import importlib
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
4
|
import datetime
|
|
@@ -41,7 +41,7 @@ def print_versions():
|
|
|
41
41
|
for m in angr_modules:
|
|
42
42
|
print("######## %s #########" % m)
|
|
43
43
|
try:
|
|
44
|
-
|
|
44
|
+
python_filename = importlib.util.find_spec(m).origin
|
|
45
45
|
except ImportError:
|
|
46
46
|
print("Python could not find " + m)
|
|
47
47
|
continue
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pylint:disable=abstract-method
|
|
1
|
+
# pylint:disable=abstract-method,wrong-import-position,unused-argument,missing-class-docstring,arguments-differ
|
|
2
2
|
from typing import Iterable, Tuple, Dict, Any, Optional
|
|
3
3
|
|
|
4
4
|
import claripy
|
|
@@ -114,7 +114,6 @@ class MemoryMixin(SimStatePlugin):
|
|
|
114
114
|
|
|
115
115
|
The ``inspect``, ``events``, and ``key`` parameters are for ``state.solver.Unconstrained``, if it is used.
|
|
116
116
|
"""
|
|
117
|
-
pass
|
|
118
117
|
|
|
119
118
|
def _merge_values(self, values: Iterable[Tuple[Any, Any]], merged_size: int, **kwargs) -> Optional[Any]:
|
|
120
119
|
"""
|
|
@@ -187,6 +186,7 @@ from .paged_memory.paged_memory_mixin import (
|
|
|
187
186
|
)
|
|
188
187
|
from .paged_memory.privileged_mixin import PrivilegedPagingMixin
|
|
189
188
|
from .paged_memory.stack_allocation_mixin import StackAllocationMixin
|
|
189
|
+
from .paged_memory.paged_memory_multivalue_mixin import PagedMemoryMultiValueMixin
|
|
190
190
|
from .paged_memory.pages import *
|
|
191
191
|
|
|
192
192
|
from .slotted_memory import SlottedMemoryMixin
|
|
@@ -353,6 +353,7 @@ class MultiValuedMemory(
|
|
|
353
353
|
DefaultFillerMixin,
|
|
354
354
|
MultiValueMergerMixin,
|
|
355
355
|
PagedMemoryMixin,
|
|
356
|
+
PagedMemoryMultiValueMixin,
|
|
356
357
|
):
|
|
357
358
|
def _default_value(self, addr, size, **kwargs):
|
|
358
359
|
# TODO: Make _default_value() a separate Mixin
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from .. import MemoryMixin
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PagedMemoryMultiValueMixin(MemoryMixin):
|
|
5
|
+
"""
|
|
6
|
+
Implement optimizations and fast accessors for the MultiValues-variant of Paged Memory.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
def load_annotations(self, addr: int, size: int, **kwargs):
|
|
10
|
+
if not isinstance(size, int):
|
|
11
|
+
raise TypeError("Need size to be resolved to an int by this point")
|
|
12
|
+
|
|
13
|
+
if not isinstance(addr, int):
|
|
14
|
+
raise TypeError("Need addr to be resolved to an int by this point")
|
|
15
|
+
|
|
16
|
+
pageno, pageoff = self._divide_addr(addr)
|
|
17
|
+
|
|
18
|
+
annotations = set()
|
|
19
|
+
|
|
20
|
+
# fasttrack basic case
|
|
21
|
+
if pageoff + size <= self.page_size:
|
|
22
|
+
page = self._get_page(pageno, False, **kwargs)
|
|
23
|
+
loaded = page.load(
|
|
24
|
+
pageoff,
|
|
25
|
+
size=size,
|
|
26
|
+
page_addr=pageno * self.page_size,
|
|
27
|
+
memory=self,
|
|
28
|
+
cooperate=True,
|
|
29
|
+
**kwargs,
|
|
30
|
+
)
|
|
31
|
+
for _, mos in loaded:
|
|
32
|
+
if isinstance(mos, set):
|
|
33
|
+
for mo in mos:
|
|
34
|
+
annotations.update(mo.object.annotations)
|
|
35
|
+
else:
|
|
36
|
+
annotations.update(mos.object.annotations)
|
|
37
|
+
|
|
38
|
+
else:
|
|
39
|
+
max_pageno = (1 << self.state.arch.bits) // self.page_size
|
|
40
|
+
bytes_done = 0
|
|
41
|
+
while bytes_done < size:
|
|
42
|
+
page = self._get_page(pageno, False, **kwargs)
|
|
43
|
+
sub_size = min(self.page_size - pageoff, size - bytes_done)
|
|
44
|
+
loaded = page.load(
|
|
45
|
+
pageoff,
|
|
46
|
+
size=sub_size,
|
|
47
|
+
page_addr=pageno * self.page_size,
|
|
48
|
+
memory=self,
|
|
49
|
+
cooperate=True,
|
|
50
|
+
**kwargs,
|
|
51
|
+
)
|
|
52
|
+
for _, mos in loaded:
|
|
53
|
+
if isinstance(mos, set):
|
|
54
|
+
for mo in mos:
|
|
55
|
+
annotations.update(mo.object.annotations)
|
|
56
|
+
else:
|
|
57
|
+
annotations.update(mos.object.annotations)
|
|
58
|
+
|
|
59
|
+
bytes_done += sub_size
|
|
60
|
+
pageno = (pageno + 1) % max_pageno
|
|
61
|
+
pageoff = 0
|
|
62
|
+
|
|
63
|
+
return annotations
|