smallworld-re 1.0.0__py3-none-any.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.
- smallworld/__init__.py +35 -0
- smallworld/analyses/__init__.py +14 -0
- smallworld/analyses/analysis.py +88 -0
- smallworld/analyses/code_coverage.py +31 -0
- smallworld/analyses/colorizer.py +682 -0
- smallworld/analyses/colorizer_summary.py +100 -0
- smallworld/analyses/field_detection/__init__.py +14 -0
- smallworld/analyses/field_detection/field_analysis.py +536 -0
- smallworld/analyses/field_detection/guards.py +26 -0
- smallworld/analyses/field_detection/hints.py +133 -0
- smallworld/analyses/field_detection/malloc.py +211 -0
- smallworld/analyses/forced_exec/__init__.py +3 -0
- smallworld/analyses/forced_exec/forced_exec.py +87 -0
- smallworld/analyses/underlays/__init__.py +4 -0
- smallworld/analyses/underlays/basic.py +13 -0
- smallworld/analyses/underlays/underlay.py +31 -0
- smallworld/analyses/unstable/__init__.py +4 -0
- smallworld/analyses/unstable/angr/__init__.py +0 -0
- smallworld/analyses/unstable/angr/base.py +12 -0
- smallworld/analyses/unstable/angr/divergence.py +274 -0
- smallworld/analyses/unstable/angr/model.py +383 -0
- smallworld/analyses/unstable/angr/nwbt.py +63 -0
- smallworld/analyses/unstable/angr/typedefs.py +170 -0
- smallworld/analyses/unstable/angr/utils.py +25 -0
- smallworld/analyses/unstable/angr/visitor.py +315 -0
- smallworld/analyses/unstable/angr_nwbt.py +106 -0
- smallworld/analyses/unstable/code_coverage.py +54 -0
- smallworld/analyses/unstable/code_reachable.py +44 -0
- smallworld/analyses/unstable/control_flow_tracer.py +71 -0
- smallworld/analyses/unstable/pointer_finder.py +90 -0
- smallworld/arch/__init__.py +0 -0
- smallworld/arch/aarch64_arch.py +286 -0
- smallworld/arch/amd64_arch.py +86 -0
- smallworld/arch/i386_arch.py +44 -0
- smallworld/emulators/__init__.py +14 -0
- smallworld/emulators/angr/__init__.py +7 -0
- smallworld/emulators/angr/angr.py +1652 -0
- smallworld/emulators/angr/default.py +15 -0
- smallworld/emulators/angr/exceptions.py +7 -0
- smallworld/emulators/angr/exploration/__init__.py +9 -0
- smallworld/emulators/angr/exploration/bounds.py +27 -0
- smallworld/emulators/angr/exploration/default.py +17 -0
- smallworld/emulators/angr/exploration/terminate.py +22 -0
- smallworld/emulators/angr/factory.py +55 -0
- smallworld/emulators/angr/machdefs/__init__.py +35 -0
- smallworld/emulators/angr/machdefs/aarch64.py +292 -0
- smallworld/emulators/angr/machdefs/amd64.py +192 -0
- smallworld/emulators/angr/machdefs/arm.py +387 -0
- smallworld/emulators/angr/machdefs/i386.py +221 -0
- smallworld/emulators/angr/machdefs/machdef.py +138 -0
- smallworld/emulators/angr/machdefs/mips.py +184 -0
- smallworld/emulators/angr/machdefs/mips64.py +189 -0
- smallworld/emulators/angr/machdefs/ppc.py +101 -0
- smallworld/emulators/angr/machdefs/riscv.py +261 -0
- smallworld/emulators/angr/machdefs/xtensa.py +255 -0
- smallworld/emulators/angr/memory/__init__.py +7 -0
- smallworld/emulators/angr/memory/default.py +10 -0
- smallworld/emulators/angr/memory/fixups.py +43 -0
- smallworld/emulators/angr/memory/memtrack.py +105 -0
- smallworld/emulators/angr/scratch.py +43 -0
- smallworld/emulators/angr/simos.py +53 -0
- smallworld/emulators/angr/utils.py +70 -0
- smallworld/emulators/emulator.py +1013 -0
- smallworld/emulators/hookable.py +252 -0
- smallworld/emulators/panda/__init__.py +5 -0
- smallworld/emulators/panda/machdefs/__init__.py +28 -0
- smallworld/emulators/panda/machdefs/aarch64.py +93 -0
- smallworld/emulators/panda/machdefs/amd64.py +71 -0
- smallworld/emulators/panda/machdefs/arm.py +89 -0
- smallworld/emulators/panda/machdefs/i386.py +36 -0
- smallworld/emulators/panda/machdefs/machdef.py +86 -0
- smallworld/emulators/panda/machdefs/mips.py +94 -0
- smallworld/emulators/panda/machdefs/mips64.py +91 -0
- smallworld/emulators/panda/machdefs/ppc.py +79 -0
- smallworld/emulators/panda/panda.py +575 -0
- smallworld/emulators/unicorn/__init__.py +13 -0
- smallworld/emulators/unicorn/machdefs/__init__.py +28 -0
- smallworld/emulators/unicorn/machdefs/aarch64.py +310 -0
- smallworld/emulators/unicorn/machdefs/amd64.py +326 -0
- smallworld/emulators/unicorn/machdefs/arm.py +321 -0
- smallworld/emulators/unicorn/machdefs/i386.py +137 -0
- smallworld/emulators/unicorn/machdefs/machdef.py +117 -0
- smallworld/emulators/unicorn/machdefs/mips.py +202 -0
- smallworld/emulators/unicorn/unicorn.py +684 -0
- smallworld/exceptions/__init__.py +5 -0
- smallworld/exceptions/exceptions.py +85 -0
- smallworld/exceptions/unstable/__init__.py +1 -0
- smallworld/exceptions/unstable/exceptions.py +25 -0
- smallworld/extern/__init__.py +4 -0
- smallworld/extern/ctypes.py +94 -0
- smallworld/extern/unstable/__init__.py +1 -0
- smallworld/extern/unstable/ghidra.py +129 -0
- smallworld/helpers.py +107 -0
- smallworld/hinting/__init__.py +8 -0
- smallworld/hinting/hinting.py +214 -0
- smallworld/hinting/hints.py +427 -0
- smallworld/hinting/unstable/__init__.py +2 -0
- smallworld/hinting/utils.py +19 -0
- smallworld/instructions/__init__.py +18 -0
- smallworld/instructions/aarch64.py +20 -0
- smallworld/instructions/arm.py +18 -0
- smallworld/instructions/bsid.py +67 -0
- smallworld/instructions/instructions.py +258 -0
- smallworld/instructions/mips.py +21 -0
- smallworld/instructions/x86.py +100 -0
- smallworld/logging.py +90 -0
- smallworld/platforms.py +95 -0
- smallworld/py.typed +0 -0
- smallworld/state/__init__.py +6 -0
- smallworld/state/cpus/__init__.py +32 -0
- smallworld/state/cpus/aarch64.py +563 -0
- smallworld/state/cpus/amd64.py +676 -0
- smallworld/state/cpus/arm.py +630 -0
- smallworld/state/cpus/cpu.py +71 -0
- smallworld/state/cpus/i386.py +239 -0
- smallworld/state/cpus/mips.py +374 -0
- smallworld/state/cpus/mips64.py +372 -0
- smallworld/state/cpus/powerpc.py +229 -0
- smallworld/state/cpus/riscv.py +357 -0
- smallworld/state/cpus/xtensa.py +80 -0
- smallworld/state/memory/__init__.py +7 -0
- smallworld/state/memory/code.py +70 -0
- smallworld/state/memory/elf/__init__.py +3 -0
- smallworld/state/memory/elf/elf.py +564 -0
- smallworld/state/memory/elf/rela/__init__.py +32 -0
- smallworld/state/memory/elf/rela/aarch64.py +27 -0
- smallworld/state/memory/elf/rela/amd64.py +32 -0
- smallworld/state/memory/elf/rela/arm.py +51 -0
- smallworld/state/memory/elf/rela/i386.py +32 -0
- smallworld/state/memory/elf/rela/mips.py +45 -0
- smallworld/state/memory/elf/rela/ppc.py +45 -0
- smallworld/state/memory/elf/rela/rela.py +63 -0
- smallworld/state/memory/elf/rela/riscv64.py +27 -0
- smallworld/state/memory/elf/rela/xtensa.py +15 -0
- smallworld/state/memory/elf/structs.py +55 -0
- smallworld/state/memory/heap.py +85 -0
- smallworld/state/memory/memory.py +181 -0
- smallworld/state/memory/stack/__init__.py +31 -0
- smallworld/state/memory/stack/aarch64.py +22 -0
- smallworld/state/memory/stack/amd64.py +42 -0
- smallworld/state/memory/stack/arm.py +66 -0
- smallworld/state/memory/stack/i386.py +22 -0
- smallworld/state/memory/stack/mips.py +34 -0
- smallworld/state/memory/stack/mips64.py +34 -0
- smallworld/state/memory/stack/ppc.py +34 -0
- smallworld/state/memory/stack/riscv.py +22 -0
- smallworld/state/memory/stack/stack.py +127 -0
- smallworld/state/memory/stack/xtensa.py +34 -0
- smallworld/state/models/__init__.py +6 -0
- smallworld/state/models/mmio.py +186 -0
- smallworld/state/models/model.py +163 -0
- smallworld/state/models/posix.py +455 -0
- smallworld/state/models/x86/__init__.py +2 -0
- smallworld/state/models/x86/microsoftcdecl.py +35 -0
- smallworld/state/models/x86/systemv.py +240 -0
- smallworld/state/state.py +962 -0
- smallworld/state/unstable/__init__.py +0 -0
- smallworld/state/unstable/elf.py +393 -0
- smallworld/state/x86_registers.py +30 -0
- smallworld/utils.py +935 -0
- smallworld_re-1.0.0.dist-info/LICENSE.txt +21 -0
- smallworld_re-1.0.0.dist-info/METADATA +189 -0
- smallworld_re-1.0.0.dist-info/RECORD +166 -0
- smallworld_re-1.0.0.dist-info/WHEEL +5 -0
- smallworld_re-1.0.0.dist-info/entry_points.txt +2 -0
- smallworld_re-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
import typing
|
2
|
+
|
3
|
+
import angr
|
4
|
+
import archinfo
|
5
|
+
|
6
|
+
from ....platforms import Architecture, Byteorder
|
7
|
+
from .machdef import AngrMachineDef
|
8
|
+
|
9
|
+
# angr has no default calling convention for RISCV64
|
10
|
+
# Let's fix that.
|
11
|
+
|
12
|
+
|
13
|
+
class SimCCRISCV64(angr.calling_conventions.SimCC):
|
14
|
+
ARG_REGS = ["a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7"]
|
15
|
+
FP_ARG_REGS = ["fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7"]
|
16
|
+
RETURN_VAL = angr.calling_conventions.SimRegArg("a0", 8)
|
17
|
+
RETURN_ADDR = angr.calling_conventions.SimRegArg("ra", 8)
|
18
|
+
# angr doesn't type this field correctly
|
19
|
+
ARCH = archinfo.ArchRISCV64 # type: ignore[assignment]
|
20
|
+
|
21
|
+
|
22
|
+
angr.calling_conventions.register_default_cc("RISCV64", SimCCRISCV64)
|
23
|
+
|
24
|
+
# angr ALSO has no default syscall calling convention for RISCV64
|
25
|
+
# Let's fix that
|
26
|
+
|
27
|
+
|
28
|
+
class SimCCRISCV64LinuxSyscall(angr.calling_conventions.SimCCSyscall):
|
29
|
+
# Since the RISCV peeps don't seem to have written their kernel ABI,
|
30
|
+
# I RE'd the syscall convention from glibc.
|
31
|
+
# It looks like they use the same arg and return regs,
|
32
|
+
# except that they repurpose a7 as the syscall number.
|
33
|
+
ARG_REGS = ["a0", "a1", "a2", "a3", "a4", "a5", "a6"]
|
34
|
+
FP_ARG_REGS: typing.List[str] = []
|
35
|
+
RETURN_VAL = angr.calling_conventions.SimRegArg("a0", 8)
|
36
|
+
RETURN_ADDR = angr.calling_conventions.SimRegArg("ip_at_syscall", 4)
|
37
|
+
# angr doesn't type this field correctly
|
38
|
+
ARCH = archinfo.ArchRISCV64 # type: ignore[assignment]
|
39
|
+
|
40
|
+
@classmethod
|
41
|
+
def _match(cls, arch, args, sp_data):
|
42
|
+
# Never match; only occurs durring syscalls
|
43
|
+
return False
|
44
|
+
|
45
|
+
@staticmethod
|
46
|
+
def syscall_num(state):
|
47
|
+
return state.regs.a7
|
48
|
+
|
49
|
+
|
50
|
+
angr.calling_conventions.register_syscall_cc(
|
51
|
+
"RISCV64", "default", SimCCRISCV64LinuxSyscall
|
52
|
+
)
|
53
|
+
|
54
|
+
|
55
|
+
class RISCV64MachineDef(AngrMachineDef):
|
56
|
+
arch = Architecture.RISCV64
|
57
|
+
byteorder = Byteorder.LITTLE
|
58
|
+
|
59
|
+
angr_arch = archinfo.ArchRISCV64()
|
60
|
+
|
61
|
+
pc_reg = "pc"
|
62
|
+
|
63
|
+
_registers = {
|
64
|
+
# *** General-Purpose Registers ***
|
65
|
+
# x0 is wired to 0, and aliased as "zero"
|
66
|
+
"x0": "x0",
|
67
|
+
"zero": "zero",
|
68
|
+
# x1 acts as the link register
|
69
|
+
# NOTE: ra is the official name; lr might be an angr invention.
|
70
|
+
"x1": "x1",
|
71
|
+
"ra": "ra",
|
72
|
+
# x2 acts as the stack pointer
|
73
|
+
"x2": "x2",
|
74
|
+
"sp": "sp",
|
75
|
+
# x3 acts as the global pointer
|
76
|
+
"x3": "x3",
|
77
|
+
"gp": "gp",
|
78
|
+
# x4 acts as the thread pointer
|
79
|
+
"x4": "x4",
|
80
|
+
"tp": "tp",
|
81
|
+
# x5 is a temporary register
|
82
|
+
"x5": "x5",
|
83
|
+
"t0": "t0",
|
84
|
+
# x6 is a temporary register
|
85
|
+
"x6": "x6",
|
86
|
+
"t1": "t1",
|
87
|
+
# x7 is a temporary register
|
88
|
+
"x7": "x7",
|
89
|
+
"t2": "t2",
|
90
|
+
# x8 is a callee-saved register
|
91
|
+
"x8": "x8",
|
92
|
+
"s0": "s0",
|
93
|
+
# x9 is a callee-saved register
|
94
|
+
"x9": "x9",
|
95
|
+
"s1": "s1",
|
96
|
+
# x10 is argument 0
|
97
|
+
"x10": "x10",
|
98
|
+
"a0": "a0",
|
99
|
+
# x11 is argument 1
|
100
|
+
"x11": "x11",
|
101
|
+
"a1": "a1",
|
102
|
+
# x12 is argument 2
|
103
|
+
"x12": "x12",
|
104
|
+
"a2": "a2",
|
105
|
+
# x13 is argument 3
|
106
|
+
"x13": "x13",
|
107
|
+
"a3": "a3",
|
108
|
+
# x14 is argument 4
|
109
|
+
"x14": "x14",
|
110
|
+
"a4": "a4",
|
111
|
+
# x15 is argument 5
|
112
|
+
"x15": "x15",
|
113
|
+
"a5": "a5",
|
114
|
+
# x16 is argument 6
|
115
|
+
"x16": "x16",
|
116
|
+
"a6": "a6",
|
117
|
+
# x17 is argument 7
|
118
|
+
"x17": "x17",
|
119
|
+
"a7": "a7",
|
120
|
+
# x18 is a callee-saved register
|
121
|
+
"x18": "x18",
|
122
|
+
"s2": "s2",
|
123
|
+
# x19 is a callee-saved register
|
124
|
+
"x19": "x19",
|
125
|
+
"s3": "s3",
|
126
|
+
# x20 is a callee-saved register
|
127
|
+
"x20": "x20",
|
128
|
+
"s4": "s4",
|
129
|
+
# x21 is a callee-saved register
|
130
|
+
"x21": "x21",
|
131
|
+
"s5": "s5",
|
132
|
+
# x22 is a callee-saved register
|
133
|
+
"x22": "x22",
|
134
|
+
"s6": "s6",
|
135
|
+
# x23 is a callee-saved register
|
136
|
+
"x23": "x23",
|
137
|
+
"s7": "s7",
|
138
|
+
# x24 is a callee-saved register
|
139
|
+
"x24": "x24",
|
140
|
+
"s8": "s8",
|
141
|
+
# x25 is a callee-saved register
|
142
|
+
"x25": "x25",
|
143
|
+
"s9": "s9",
|
144
|
+
# x26 is a callee-saved register
|
145
|
+
"x26": "x26",
|
146
|
+
"s10": "s10",
|
147
|
+
# x27 is a callee-saved register
|
148
|
+
"x27": "x27",
|
149
|
+
"s11": "s11",
|
150
|
+
# x28 is a temporary register
|
151
|
+
"x28": "x28",
|
152
|
+
"t3": "t3",
|
153
|
+
# x29 is a temporary register
|
154
|
+
"x29": "x29",
|
155
|
+
"t4": "t4",
|
156
|
+
# x30 is a temporary register
|
157
|
+
"x30": "x30",
|
158
|
+
"t5": "t5",
|
159
|
+
# x31 is a temporary register
|
160
|
+
"x31": "x31",
|
161
|
+
"t6": "t6",
|
162
|
+
# *** Program Counter ***
|
163
|
+
"pc": "pc",
|
164
|
+
# *** Floating-Point Registers ***
|
165
|
+
# f0 is a temporary register
|
166
|
+
"f0": "f0",
|
167
|
+
"ft0": "ft0",
|
168
|
+
# f1 is a temporary register
|
169
|
+
"f1": "f1",
|
170
|
+
"ft1": "ft1",
|
171
|
+
# f2 is a temporary register
|
172
|
+
"f2": "f2",
|
173
|
+
"ft2": "ft2",
|
174
|
+
# f3 is a temporary register
|
175
|
+
"f3": "f3",
|
176
|
+
"ft3": "ft3",
|
177
|
+
# f4 is a temporary register
|
178
|
+
"f4": "f4",
|
179
|
+
"ft4": "ft4",
|
180
|
+
# f5 is a temporary register
|
181
|
+
"f5": "f5",
|
182
|
+
"ft5": "ft5",
|
183
|
+
# f6 is a temporary register
|
184
|
+
"f6": "f6",
|
185
|
+
"ft6": "ft6",
|
186
|
+
# f7 is a temporary register
|
187
|
+
"f7": "f7",
|
188
|
+
"ft7": "ft7",
|
189
|
+
# f8 is a callee saved register
|
190
|
+
"f8": "f8",
|
191
|
+
"fs0": "fs0",
|
192
|
+
# f9 is a callee saved register
|
193
|
+
"f9": "f9",
|
194
|
+
"fs1": "fs1",
|
195
|
+
# f10 is argument 0
|
196
|
+
"f10": "f10",
|
197
|
+
"a0": "a0",
|
198
|
+
# f11 is argument 1
|
199
|
+
"f11": "f11",
|
200
|
+
"a1": "a1",
|
201
|
+
# f12 is argument 2
|
202
|
+
"f12": "f12",
|
203
|
+
"a2": "a2",
|
204
|
+
# f13 is argument 3
|
205
|
+
"f13": "f13",
|
206
|
+
"a3": "a3",
|
207
|
+
# f14 is argument 4
|
208
|
+
"f14": "f14",
|
209
|
+
"a4": "a4",
|
210
|
+
# f15 is argument 5
|
211
|
+
"f15": "f15",
|
212
|
+
"a5": "a5",
|
213
|
+
# f16 is argument 6
|
214
|
+
"f16": "f16",
|
215
|
+
"a6": "a6",
|
216
|
+
# f7 is argument 7
|
217
|
+
"f17": "f17",
|
218
|
+
"a7": "a7",
|
219
|
+
# f18 is a callee-saved register
|
220
|
+
"f18": "f18",
|
221
|
+
"fs2": "fs2",
|
222
|
+
# f19 is a callee-saved register
|
223
|
+
"f19": "f19",
|
224
|
+
"fs3": "fs3",
|
225
|
+
# f20 is a callee-saved register
|
226
|
+
"f20": "f20",
|
227
|
+
"fs4": "fs4",
|
228
|
+
# f21 is a callee-saved register
|
229
|
+
"f21": "f21",
|
230
|
+
"fs5": "fs5",
|
231
|
+
# f22 is a callee-saved register
|
232
|
+
"f22": "f22",
|
233
|
+
"fs6": "fs6",
|
234
|
+
# f23 is a callee-saved register
|
235
|
+
"f23": "f23",
|
236
|
+
"fs7": "fs7",
|
237
|
+
# f24 is a callee-saved register
|
238
|
+
"f24": "f24",
|
239
|
+
"fs8": "fs8",
|
240
|
+
# f25 is a callee-saved register
|
241
|
+
"f25": "f25",
|
242
|
+
"fs9": "fs9",
|
243
|
+
# f26 is a callee-saved register
|
244
|
+
"f26": "f26",
|
245
|
+
"fs10": "fs10",
|
246
|
+
# f27 is a callee-saved register
|
247
|
+
"f27": "f27",
|
248
|
+
"fs11": "fs11",
|
249
|
+
# f28 is a temporary register
|
250
|
+
"f28": "f28",
|
251
|
+
"ft8": "ft8",
|
252
|
+
# f29 is a temporary register
|
253
|
+
"f29": "f29",
|
254
|
+
"ft9": "ft9",
|
255
|
+
# f30 is a temporary register
|
256
|
+
"f30": "f30",
|
257
|
+
"ft10": "ft10",
|
258
|
+
# f31 is a temporary register
|
259
|
+
"f31": "f31",
|
260
|
+
"ft11": "ft11",
|
261
|
+
}
|
@@ -0,0 +1,255 @@
|
|
1
|
+
import enum
|
2
|
+
import typing
|
3
|
+
|
4
|
+
import angr
|
5
|
+
import pypcode
|
6
|
+
|
7
|
+
from ....exceptions import EmulationError
|
8
|
+
from ....platforms import Architecture, Byteorder
|
9
|
+
from .machdef import PcodeMachineDef
|
10
|
+
|
11
|
+
|
12
|
+
def handle_nop(irsb, i):
|
13
|
+
# This op has no impact on user-facing machine state.
|
14
|
+
irsb._ops.pop(i)
|
15
|
+
return i
|
16
|
+
|
17
|
+
|
18
|
+
def handle_sigtrap(irsb, i):
|
19
|
+
# This op should terminate this block with SIGTRAP
|
20
|
+
next_addr = irsb._ops[i - 1].inputs[0].offset + 3
|
21
|
+
irsb._ops = irsb._ops[0:i]
|
22
|
+
irsb.next = next_addr
|
23
|
+
irsb._size = next_addr - irsb.addr
|
24
|
+
irsb._instruction_addresses = list(
|
25
|
+
filter(lambda x: x < next_addr, irsb._instruction_addresses)
|
26
|
+
)
|
27
|
+
irsb.jumpkind = "Ijk_SigTRAP"
|
28
|
+
return i
|
29
|
+
|
30
|
+
|
31
|
+
def handle_sigill(irsb, i):
|
32
|
+
# This op should terminate this block with SIGILL
|
33
|
+
next_addr = irsb._ops[i - 1].inputs[0].offset + 3
|
34
|
+
irsb._ops = irsb._ops[0:i]
|
35
|
+
irsb.next = next_addr
|
36
|
+
irsb._size = next_addr - irsb.addr
|
37
|
+
irsb._instruction_addresses = list(
|
38
|
+
filter(lambda x: x < next_addr, irsb._instruction_addresses)
|
39
|
+
)
|
40
|
+
irsb.jumpkind = "Ijk_SigILL"
|
41
|
+
return i
|
42
|
+
|
43
|
+
|
44
|
+
def handle_syscall(irsb, i):
|
45
|
+
# This op should terminate this block with a syscall
|
46
|
+
next_addr = irsb._ops[i - 1].inputs[0].offset + 3
|
47
|
+
irsb._ops = irsb._ops[0:i]
|
48
|
+
irsb.next = next_addr
|
49
|
+
irsb._size = next_addr - irsb.addr
|
50
|
+
irsb._instruction_addresses = list(
|
51
|
+
filter(lambda x: x < next_addr, irsb._instruction_addresses)
|
52
|
+
)
|
53
|
+
irsb.jumpkind = "Ijk_Sys_syscall"
|
54
|
+
|
55
|
+
return i
|
56
|
+
|
57
|
+
|
58
|
+
def handle_nope(irsb, i):
|
59
|
+
# This op cannot be handled by angr
|
60
|
+
userop = XtensaUserOp(irsb._ops[i].inputs[0].offset)
|
61
|
+
raise EmulationError(f"Unhandled user op {userop!r}")
|
62
|
+
|
63
|
+
|
64
|
+
def handle_unimpl(irsb, i):
|
65
|
+
# I don't know what this op does yet
|
66
|
+
userop = XtensaUserOp(irsb._ops[i].inputs[0].offset)
|
67
|
+
raise EmulationError(f"Unimplemented user op {userop!r}")
|
68
|
+
|
69
|
+
|
70
|
+
class UpdatedEnumMeta(enum.EnumMeta):
|
71
|
+
def __contains__(cls, obj):
|
72
|
+
if isinstance(obj, int):
|
73
|
+
return obj in cls._value2member_map_
|
74
|
+
return enum.EnumMeta.__contains__(enum.EnumMeta, obj)
|
75
|
+
|
76
|
+
|
77
|
+
class XtensaUserOp(enum.IntEnum, metaclass=UpdatedEnumMeta):
|
78
|
+
def __new__(
|
79
|
+
cls, val: int, name: str = "", handler: typing.Any = None, desc: str = ""
|
80
|
+
):
|
81
|
+
obj = int.__new__(cls, val)
|
82
|
+
obj._value_ = val
|
83
|
+
obj.short_name = name
|
84
|
+
obj.handler = handler
|
85
|
+
obj.description = desc
|
86
|
+
return obj
|
87
|
+
|
88
|
+
def __init__(
|
89
|
+
self, val: int, name: str = "", handler: typing.Any = None, desc: str = ""
|
90
|
+
):
|
91
|
+
self._value_: int = val
|
92
|
+
self.short_name: str = name
|
93
|
+
self.handler: typing.Any = handler
|
94
|
+
self.description: str = desc
|
95
|
+
|
96
|
+
def __repr__(self):
|
97
|
+
return f"{hex(self.value)}: {self.short_name} - {self.description}"
|
98
|
+
|
99
|
+
BREAKPOINT = 0x00, "breakpoint", handle_sigtrap, "Breakpoint Instruction"
|
100
|
+
DHI = 0x01, "dhi", handle_nop, "Data Cache Hit Invalidate"
|
101
|
+
DHU = 0x02, "dhu", handle_nop, "Data Cache Hit Unlock"
|
102
|
+
DHWB = 0x03, "dhwb", handle_nop, "Data Cache Hit Writeback"
|
103
|
+
DHWBI = 0x04, "dhwbi", handle_nop, "Data Cache Hit Writeback Invalidate"
|
104
|
+
DII = 0x05, "dii", handle_nop, "Data Cache Index Invalidate"
|
105
|
+
DIU = 0x06, "diu", handle_nop, "Data Cache Index Unlock"
|
106
|
+
DIWB = 0x07, "diwb", handle_nop, "Data Cache Index Writeback"
|
107
|
+
DIWBI = 0x08, "diwbi", handle_nop, "Data Cache Index Writeback Invalidate"
|
108
|
+
DPFL = 0x09, "dpfl", handle_nop, "Data Cache Prefetch And Lock"
|
109
|
+
DPFR = 0x0A, "dpfr", handle_nop, "Data Cache Prefetch For Read"
|
110
|
+
DPFRO = 0x0B, "dpfro", handle_nop, "Data Cache Prefetch For Read Once"
|
111
|
+
DPFW = 0x0C, "dpfw", handle_nop, "Data Cache Prefetch For Write"
|
112
|
+
DPFWO = 0x0D, "dpfwo", handle_nop, "Data Cache Prefetch For Write Once"
|
113
|
+
DSYNC = 0x0E, "dsync", handle_nop, "Load/Store Synchronize"
|
114
|
+
ESYNC = 0x0F, "esync", handle_nop, "Execute Synchronize"
|
115
|
+
EXCW = 0x10, "excw", handle_sigtrap, "Exception Wait"
|
116
|
+
EXTW = 0x11, "extw", handle_sigtrap, "External Wait"
|
117
|
+
IDTLB = 0x12, "idtlb", handle_nop, "Invalidate Data TLB Entry"
|
118
|
+
IHI = 0x13, "ihi", handle_nop, "Instruction Cache Hit Invalidate"
|
119
|
+
IHU = 0x14, "ihu", handle_nop, "Instruction Cache Hit Unlock"
|
120
|
+
III = 0x15, "iii", handle_nop, "Instruction Cache Index Invalidate"
|
121
|
+
IITLB = 0x16, "iitlb", handle_nop, "Invalidate Instruction TLB Entry"
|
122
|
+
IIU = 0x17, "iiu", handle_nop, "Instruction Cache Index Unlock"
|
123
|
+
ILL = 0x18, "ill", handle_sigill, "Illegal Instruction"
|
124
|
+
IPF = 0x19, "ipf", handle_nop, "Instruction Cache Prefetch"
|
125
|
+
IPFL = 0x1A, "ipfl", handle_nop, "Instruction Cache Prefetch And Lock"
|
126
|
+
ISYNC = 0x1B, "isync", handle_nop, "Instruction Fetch Synchronize"
|
127
|
+
ACQUIRE = 0x1C, "acquire", handle_unimpl, "???"
|
128
|
+
LDCT = 0x1D, "ldct", handle_nope, "Load Data Cache Tag"
|
129
|
+
LICT = 0x1E, "lict", handle_nope, "Load Instruction Cache Tag"
|
130
|
+
LICW = 0x1F, "licw", handle_nope, "Load Instruction Cache Word"
|
131
|
+
MEMW = 0x20, "memw", handle_sigtrap, "Memory Wait"
|
132
|
+
NSA = 0x21, "nsa", handle_unimpl, "Normalization Shift Amount"
|
133
|
+
NSAU = 0x22, "nsau", handle_unimpl, "Normalization Shift Amount Unsigned"
|
134
|
+
PDTLB = 0x23, "pdtlb", handle_nope, "Probe Data TLB"
|
135
|
+
PITLB = 0x24, "pitlb", handle_nope, "Probe Instruction TLB"
|
136
|
+
RDTLB0 = 0x25, "rdtlb0", handle_nope, "Read Data TLB Entry Virtual"
|
137
|
+
RDTLB1 = 0x26, "rdtlb1", handle_nope, "Read Data TLB Entry Translation"
|
138
|
+
RER = 0x27, "rer", handle_nope, "Read External Register"
|
139
|
+
RESTORE4 = 0x28, "restore4", handle_unimpl, "???"
|
140
|
+
RESTORE8 = 0x29, "restore8", handle_unimpl, "???"
|
141
|
+
RESTORE12 = 0x2A, "restore12", handle_unimpl, "???"
|
142
|
+
RFDD = 0x2B, "rfdd", handle_nope, "Return from Debug and Dispatch"
|
143
|
+
RFDE = 0x2C, "rfde", handle_nope, "Return from Double Exception"
|
144
|
+
RFDO = 0x2D, "rfdo", handle_nope, "Return from Debug Operation"
|
145
|
+
RFE = 0x2E, "rfe", handle_nope, "Return from Exception"
|
146
|
+
RFI = 0x2F, "rfi", handle_nope, "Return from Interrupt"
|
147
|
+
RFME = 0x30, "rfme", handle_nope, "Return from Memory Error"
|
148
|
+
RFUE = 0x31, "rfue", handle_nope, "Return from User Exception"
|
149
|
+
RFWO = 0x32, "rfwo", handle_nope, "Return from Window Overflow"
|
150
|
+
RFWU = 0x33, "rfwu", handle_nope, "Return from Window Underflow"
|
151
|
+
RITLB0 = 0x34, "ritlb0", handle_nope, "Read Instruction TLB Entry Virtual"
|
152
|
+
RITLB1 = 0x35, "ritlb1", handle_nope, "Read Instruction TLB Entry Translation"
|
153
|
+
RSIL = 0x36, "rsil", handle_nope, "Read and Set Interrupt Level"
|
154
|
+
RSR = 0x37, "rsr", handle_unimpl, "Read Special Register"
|
155
|
+
RSYNC = 0x38, "rsync", handle_nop, "Register Read Synchronize"
|
156
|
+
RUR = 0x39, "rur", handle_unimpl, "Read User Register"
|
157
|
+
S32C1I = 0x3A, "s32c1i", handle_unimpl, "Store 32-bit compare conditional"
|
158
|
+
RELEASE = 0x3B, "release", handle_unimpl, "???"
|
159
|
+
RESTOREREGWINDOW = 0x3C, "restoreregwindow", handle_unimpl, "???"
|
160
|
+
ROTATEREGWINDOW = 0x3D, "rotateregwindow", handle_unimpl, "???"
|
161
|
+
SDCT = 0x3E, "sdct", handle_nope, "Store Data Cache Tag"
|
162
|
+
SICT = 0x3F, "sict", handle_nope, "Store Instruction Cache Tag"
|
163
|
+
SICW = 0x40, "sicw", handle_nope, "Store Instruction Cache Word"
|
164
|
+
SIMCALL = 0x41, "simcall", handle_nop, "Simulator Call"
|
165
|
+
SYSCALL = 0x42, "syscall", handle_syscall, "System Call"
|
166
|
+
SWAP4 = 0x43, "swap4", handle_unimpl, "???"
|
167
|
+
SWAP8 = 0x44, "swap8", handle_unimpl, "???"
|
168
|
+
SWAP12 = 0x45, "swap12", handle_unimpl, "???"
|
169
|
+
WAITI = 0x46, "waiti", handle_sigtrap, "Wait for Interrupt"
|
170
|
+
WDTLB = 0x47, "wdtlb", handle_nop, "Write Data TLB Entry"
|
171
|
+
WER = 0x48, "wer", handle_nop, "Write External Register"
|
172
|
+
WITLB = 0x49, "witlb", handle_nop, "Write Instruction TLB Entry"
|
173
|
+
WSR = 0x4A, "wsr", handle_unimpl, "Write Special Register"
|
174
|
+
WUR = 0x4B, "wur", handle_unimpl, "Write User Register"
|
175
|
+
XSR = 0x4C, "xsr", handle_unimpl, "Exchange Special Register"
|
176
|
+
|
177
|
+
|
178
|
+
# Angr doesn't have a syscall calling convention for xtensa.
|
179
|
+
# Remedy that situation.
|
180
|
+
class SimCCXtensaLinuxSyscall(angr.calling_conventions.SimCCSyscall):
|
181
|
+
ARG_REGS = ["a6", "a3", "a4", "a5", "a8", "a9"]
|
182
|
+
FP_ARG_REGS: typing.List[str] = []
|
183
|
+
RETURN_VAL = angr.calling_conventions.SimRegArg("a2", 4)
|
184
|
+
RETURN_ADDR = angr.calling_conventions.SimRegArg("ip_at_syscall", 4)
|
185
|
+
ARCH = None
|
186
|
+
|
187
|
+
@classmethod
|
188
|
+
def _match(cls, arch, args, sp_data):
|
189
|
+
# Never match; only occurs durring syscalls
|
190
|
+
return False
|
191
|
+
|
192
|
+
@staticmethod
|
193
|
+
def syscall_num(state):
|
194
|
+
return state.regs.a2
|
195
|
+
|
196
|
+
|
197
|
+
angr.calling_conventions.register_syscall_cc(
|
198
|
+
"Xtensa:LE:32:default", "default", SimCCXtensaLinuxSyscall
|
199
|
+
)
|
200
|
+
|
201
|
+
|
202
|
+
class XTensaMachineDef(PcodeMachineDef):
|
203
|
+
arch = Architecture.XTENSA
|
204
|
+
_registers = {f"a{i}": f"a{i}" for i in range(0, 16)} | {"pc": "pc", "sar": "sar"}
|
205
|
+
pc_reg = "pc"
|
206
|
+
|
207
|
+
def successors(self, state: angr.SimState, **kwargs) -> typing.Any:
|
208
|
+
# xtensa includes a _LOT_ of custom pcode operations.
|
209
|
+
|
210
|
+
# Fetch or compute the IR block for our state
|
211
|
+
if "irsb" in kwargs and kwargs["irsb"] is not None:
|
212
|
+
# Someone's already specified an IR block.
|
213
|
+
irsb = kwargs["irsb"]
|
214
|
+
else:
|
215
|
+
# Disable optimization; it doesn't work
|
216
|
+
kwargs["opt_level"] = 0
|
217
|
+
|
218
|
+
# Compute the block from the state.
|
219
|
+
# Pray to the Powers that kwargs are compatible.
|
220
|
+
irsb = state.block(**kwargs).vex
|
221
|
+
|
222
|
+
i = 0
|
223
|
+
while i < len(irsb._ops):
|
224
|
+
op = irsb._ops[i]
|
225
|
+
if op.opcode == pypcode.OpCode.CALLOTHER:
|
226
|
+
# This is a user-defined Pcode op.
|
227
|
+
# Alter irsb to mimic its behavior, if we can.
|
228
|
+
opnum = op.inputs[0].offset
|
229
|
+
|
230
|
+
if opnum not in XtensaUserOp:
|
231
|
+
# Not a userop.
|
232
|
+
raise EmulationError(f"Undefined user op {hex(opnum)}")
|
233
|
+
# get the enum struct
|
234
|
+
userop = XtensaUserOp(opnum)
|
235
|
+
|
236
|
+
# Invoke the handler
|
237
|
+
i = userop.handler(irsb, i)
|
238
|
+
else:
|
239
|
+
i += 1
|
240
|
+
|
241
|
+
# Force the engine to use our IR block
|
242
|
+
kwargs["irsb"] = irsb
|
243
|
+
|
244
|
+
# Turn the crank on the engine
|
245
|
+
return super().successors(state, **kwargs)
|
246
|
+
|
247
|
+
|
248
|
+
class XTensaELMachineDef(XTensaMachineDef):
|
249
|
+
byteorder = Byteorder.LITTLE
|
250
|
+
pcode_language = "Xtensa:LE:32:default"
|
251
|
+
|
252
|
+
|
253
|
+
class XTensaBEMachineDef(XTensaMachineDef):
|
254
|
+
byteorder = Byteorder.BIG
|
255
|
+
pcode_language = "Xtensa:BE:32:default"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from angr.storage.memory_mixins.memory_mixin import MemoryMixin
|
2
|
+
|
3
|
+
|
4
|
+
class FixupMemoryMixin(MemoryMixin):
|
5
|
+
"""Mixin providing some basic bug-fixed/feature improvements
|
6
|
+
|
7
|
+
angr doesn't always behave as I'd expect.
|
8
|
+
This mixin helps things a little.
|
9
|
+
"""
|
10
|
+
|
11
|
+
def _concretize_addr(self, supercall, addr, strategies=None, condition=None):
|
12
|
+
# Handle potential errors durring concretization
|
13
|
+
# This works the same for reads and writes, so why duplicate code?
|
14
|
+
|
15
|
+
if not self.state.solver.satisfiable():
|
16
|
+
# This state isn't satisfiable; concretization is impossible, but irrelevant.
|
17
|
+
#
|
18
|
+
# Under some conditions of which I'm uncertain,
|
19
|
+
# the concretizer will try to run even if the state is already unsat.
|
20
|
+
# Since the concretizer relies on the solver,
|
21
|
+
# it fails with a big ole' fatal exception.
|
22
|
+
#
|
23
|
+
# The successor computation will eventually kill these states anyway,
|
24
|
+
# so just return a dummy value to keep things running.
|
25
|
+
return [0xDEAD0000]
|
26
|
+
|
27
|
+
return supercall(addr, strategies=strategies, condition=condition)
|
28
|
+
|
29
|
+
def concretize_read_addr(self, addr, strategies=None, condition=None):
|
30
|
+
return self._concretize_addr(
|
31
|
+
super().concretize_read_addr,
|
32
|
+
addr,
|
33
|
+
strategies=strategies,
|
34
|
+
condition=condition,
|
35
|
+
)
|
36
|
+
|
37
|
+
def concretize_write_addr(self, addr, strategies=None, condition=None):
|
38
|
+
return self._concretize_addr(
|
39
|
+
super().concretize_write_addr,
|
40
|
+
addr,
|
41
|
+
strategies=strategies,
|
42
|
+
condition=condition,
|
43
|
+
)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
from angr.storage.memory_mixins.memory_mixin import MemoryMixin
|
4
|
+
|
5
|
+
from ..utils import reg_name_from_offset
|
6
|
+
|
7
|
+
log = logging.getLogger(__name__)
|
8
|
+
|
9
|
+
|
10
|
+
class TrackerMemoryMixin(MemoryMixin):
|
11
|
+
"""Memory mixin for tracking used data.
|
12
|
+
|
13
|
+
Printing every AMD64 register is a pain,
|
14
|
+
and finding used memory in angr is a pain.
|
15
|
+
This tracks which parts of memory are in use,
|
16
|
+
mostly to avoid overprinting.
|
17
|
+
|
18
|
+
NOTE: This class needs to go in a pretty specific place in a memory mixin hierarchy.
|
19
|
+
|
20
|
+
It needs to go above anything that overrides _default_value(),
|
21
|
+
or else it will pick up defaulting addresses before they are defined,
|
22
|
+
possibly resulting in recursive calls if you try to use pp().
|
23
|
+
|
24
|
+
Conversely, it should go below anything that alters
|
25
|
+
what is actually getting passed to the default memory mixins,
|
26
|
+
such as changes to address concretization.
|
27
|
+
"""
|
28
|
+
|
29
|
+
def __init__(self, **kwargs):
|
30
|
+
super().__init__(**kwargs)
|
31
|
+
self.dirty = dict()
|
32
|
+
self.dirty_addrs = set()
|
33
|
+
|
34
|
+
@MemoryMixin.memo
|
35
|
+
def copy(self, memo):
|
36
|
+
o = super().copy(memo)
|
37
|
+
o.dirty = dict()
|
38
|
+
o.dirty.update(self.dirty)
|
39
|
+
o.dirty_addrs = set()
|
40
|
+
o.dirty_addrs.update(self.dirty_addrs)
|
41
|
+
return o
|
42
|
+
|
43
|
+
def _track_memory(self, addr, size):
|
44
|
+
"""Mark a memory range as 'in-use'"""
|
45
|
+
# TODO: Make this more efficient
|
46
|
+
# Detecting overlapping ranges is a pain.
|
47
|
+
# This implementation is easy, but its memory usage
|
48
|
+
# and runtime cost will explode violently
|
49
|
+
# if large amounts of memory are in use.
|
50
|
+
track = False
|
51
|
+
for i in range(0, size):
|
52
|
+
if not track and addr + i not in self.dirty_addrs:
|
53
|
+
track = True
|
54
|
+
self.dirty[addr] = size
|
55
|
+
self.dirty_addrs.add(addr + i)
|
56
|
+
if track:
|
57
|
+
log.debug(f"Tracking {addr:x}, {size}")
|
58
|
+
|
59
|
+
def _default_value(self, addr, size, **kwargs):
|
60
|
+
out = super()._default_value(addr, size, **kwargs)
|
61
|
+
self._track_memory(addr, size)
|
62
|
+
return out
|
63
|
+
|
64
|
+
def _store_one_addr(
|
65
|
+
self, concrete_addr, data, trivial, addr, condition, size, **kwargs
|
66
|
+
):
|
67
|
+
out = super()._store_one_addr(
|
68
|
+
concrete_addr, data, trivial, addr, condition, size, **kwargs
|
69
|
+
)
|
70
|
+
self._track_memory(concrete_addr, size)
|
71
|
+
return out
|
72
|
+
|
73
|
+
def pp(self, log):
|
74
|
+
addrs = list(self.dirty.keys())
|
75
|
+
addrs.sort()
|
76
|
+
for addr in addrs:
|
77
|
+
code = False
|
78
|
+
size = self.dirty[addr]
|
79
|
+
if self.id == "reg":
|
80
|
+
name = reg_name_from_offset(self.state.arch, addr, size)
|
81
|
+
else:
|
82
|
+
name = f"0x{addr:x}"
|
83
|
+
if code:
|
84
|
+
log(f"\t{name}: <code [{hex(size)} bytes]>")
|
85
|
+
else:
|
86
|
+
val = self.load(addr, size, disable_actions=True)
|
87
|
+
log(f"\t{name}: {val}")
|
88
|
+
|
89
|
+
def create_hint(self):
|
90
|
+
if self.id == "reg":
|
91
|
+
return {
|
92
|
+
reg_name_from_offset(self.state.arch, addr, self.dirty[addr]): str(
|
93
|
+
self.load(addr, self.dirty[addr], disable_actions=True)
|
94
|
+
)
|
95
|
+
for addr in list(self.dirty.keys())
|
96
|
+
}
|
97
|
+
else:
|
98
|
+
return {
|
99
|
+
addr: str(
|
100
|
+
self.load(
|
101
|
+
addr, self.dirty[addr], disable_actions=True, inspect=False
|
102
|
+
)
|
103
|
+
)
|
104
|
+
for addr in list(self.dirty.keys())
|
105
|
+
}
|