pyvex 9.2.193__cp310-cp310-macosx_10_12_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.
Files changed (59) hide show
  1. pyvex/__init__.py +92 -0
  2. pyvex/_register_info.py +1800 -0
  3. pyvex/arches.py +94 -0
  4. pyvex/block.py +697 -0
  5. pyvex/const.py +426 -0
  6. pyvex/const_val.py +26 -0
  7. pyvex/data_ref.py +55 -0
  8. pyvex/enums.py +156 -0
  9. pyvex/errors.py +31 -0
  10. pyvex/expr.py +974 -0
  11. pyvex/include/libvex.h +1029 -0
  12. pyvex/include/libvex_basictypes.h +236 -0
  13. pyvex/include/libvex_emnote.h +142 -0
  14. pyvex/include/libvex_guest_amd64.h +252 -0
  15. pyvex/include/libvex_guest_arm.h +224 -0
  16. pyvex/include/libvex_guest_arm64.h +203 -0
  17. pyvex/include/libvex_guest_mips32.h +175 -0
  18. pyvex/include/libvex_guest_mips64.h +173 -0
  19. pyvex/include/libvex_guest_offsets.h +941 -0
  20. pyvex/include/libvex_guest_ppc32.h +298 -0
  21. pyvex/include/libvex_guest_ppc64.h +343 -0
  22. pyvex/include/libvex_guest_riscv64.h +148 -0
  23. pyvex/include/libvex_guest_s390x.h +201 -0
  24. pyvex/include/libvex_guest_tilegx.h +149 -0
  25. pyvex/include/libvex_guest_x86.h +322 -0
  26. pyvex/include/libvex_ir.h +3113 -0
  27. pyvex/include/libvex_s390x_common.h +123 -0
  28. pyvex/include/libvex_trc_values.h +99 -0
  29. pyvex/include/pyvex.h +96 -0
  30. pyvex/lib/libpyvex.dylib +0 -0
  31. pyvex/lifting/__init__.py +18 -0
  32. pyvex/lifting/gym/README.md +7 -0
  33. pyvex/lifting/gym/__init__.py +5 -0
  34. pyvex/lifting/gym/aarch64_spotter.py +40 -0
  35. pyvex/lifting/gym/arm_spotter.py +427 -0
  36. pyvex/lifting/gym/x86_spotter.py +129 -0
  37. pyvex/lifting/libvex.py +117 -0
  38. pyvex/lifting/lift_function.py +304 -0
  39. pyvex/lifting/lifter.py +124 -0
  40. pyvex/lifting/post_processor.py +16 -0
  41. pyvex/lifting/util/__init__.py +14 -0
  42. pyvex/lifting/util/instr_helper.py +422 -0
  43. pyvex/lifting/util/lifter_helper.py +154 -0
  44. pyvex/lifting/util/syntax_wrapper.py +312 -0
  45. pyvex/lifting/util/vex_helper.py +301 -0
  46. pyvex/lifting/zerodivision.py +71 -0
  47. pyvex/native.py +63 -0
  48. pyvex/py.typed +1 -0
  49. pyvex/stmt.py +740 -0
  50. pyvex/types.py +48 -0
  51. pyvex/utils.py +63 -0
  52. pyvex/vex_ffi.py +1453 -0
  53. pyvex-9.2.193.dist-info/METADATA +181 -0
  54. pyvex-9.2.193.dist-info/RECORD +59 -0
  55. pyvex-9.2.193.dist-info/WHEEL +6 -0
  56. pyvex-9.2.193.dist-info/licenses/LICENSE +24 -0
  57. pyvex-9.2.193.dist-info/licenses/pyvex_c/LICENSE +339 -0
  58. pyvex-9.2.193.dist-info/licenses/vex/LICENSE.GPL +340 -0
  59. pyvex-9.2.193.dist-info/licenses/vex/LICENSE.README +23 -0
@@ -0,0 +1,427 @@
1
+ import logging
2
+
3
+ import bitstring
4
+
5
+ from pyvex.lifting.util import JumpKind, Type
6
+ from pyvex.lifting.util.instr_helper import Instruction, ParseError
7
+ from pyvex.lifting.util.lifter_helper import GymratLifter
8
+ from pyvex.types import Arch
9
+
10
+ log = logging.getLogger(__name__)
11
+
12
+
13
+ class ARMInstruction(Instruction): # pylint: disable=abstract-method
14
+ # NOTE: WARNING: There is no CPSR in VEX's ARM implementation
15
+ # You must use straight nasty hacks instead.
16
+
17
+ # NOTE 2: Something is goofy w/r/t archinfo and VEX; cc_op3 is used in ccalls, but there's
18
+ # no cc_op3 in archinfo, angr itself uses cc_depn instead. We do the same.
19
+
20
+ def match_instruction(self, data, bitstrm):
21
+ """
22
+ ARM Instructions are pretty dense, so let's do what we can to weed them out
23
+ """
24
+ if "c" not in data or data["c"] == "1111":
25
+ raise ParseError("Invalid ARM Instruction")
26
+
27
+ def get_N(self):
28
+ cc_op = self.get("cc_op", Type.int_32)
29
+ cc_dep1 = self.get("cc_dep1", Type.int_32)
30
+ cc_dep2 = self.get("cc_dep2", Type.int_32)
31
+ cc_depn = self.get("cc_ndep", Type.int_32)
32
+ return self.ccall(Type.int_32, "armg_calculate_flag_n", [cc_op, cc_dep1, cc_dep2, cc_depn])
33
+
34
+ def get_C(self):
35
+ cc_op = self.get("cc_op", Type.int_32)
36
+ cc_dep1 = self.get("cc_dep1", Type.int_32)
37
+ cc_dep2 = self.get("cc_dep2", Type.int_32)
38
+ cc_depn = self.get("cc_ndep", Type.int_32)
39
+ return self.ccall(Type.int_32, "armg_calculate_flag_c", [cc_op, cc_dep1, cc_dep2, cc_depn])
40
+
41
+ def get_V(self):
42
+ cc_op = self.get("cc_op", Type.int_32)
43
+ cc_dep1 = self.get("cc_dep1", Type.int_32)
44
+ cc_dep2 = self.get("cc_dep2", Type.int_32)
45
+ cc_depn = self.get("cc_ndep", Type.int_32)
46
+ return self.ccall(Type.int_32, "armg_calculate_flag_v", [cc_op, cc_dep1, cc_dep2, cc_depn])
47
+
48
+ def get_Z(self):
49
+ cc_op = self.get("cc_op", Type.int_32)
50
+ cc_dep1 = self.get("cc_dep1", Type.int_32)
51
+ cc_dep2 = self.get("cc_dep2", Type.int_32)
52
+ cc_depn = self.get("cc_ndep", Type.int_32)
53
+ return self.ccall(Type.int_32, "armg_calculate_flag_z", [cc_op.rdt, cc_dep1.rdt, cc_dep2.rdt, cc_depn.rdt])
54
+
55
+ def evaluate_condition(self):
56
+ # condition codes should be in 'c'
57
+ cond = self.data["c"]
58
+ if cond == "0000":
59
+ # equal, z set
60
+ return self.get_Z() == 1
61
+ elif cond == "0001":
62
+ # not equal, Z clear
63
+ return self.get_Z() == 0
64
+ elif cond == "0010":
65
+ # Carry, C set
66
+ return self.get_C() == 1
67
+ elif cond == "0011":
68
+ # Carry Clear, C clear
69
+ return self.get_C() == 0
70
+ elif cond == "0100":
71
+ # MI / neagative / N set
72
+ return self.get_N() == 1
73
+ elif cond == "0101":
74
+ # PL / plus / positive / N clear
75
+ return self.get_N() == 0
76
+ elif cond == "0110":
77
+ # VS / V set / Overflow
78
+ return self.get_V() == 1
79
+ elif cond == "0111":
80
+ # VC / V Clear / no overflow
81
+ return self.get_V() == 0
82
+ elif cond == "1000":
83
+ # Hi / unsigned higher / C set, Z clear
84
+ return (self.get_C() == 1) & (self.get_Z() == 0)
85
+ elif cond == "1001":
86
+ # LS / C clear, Z set
87
+ return (self.get_C() == 0) & (self.get_Z() == 1)
88
+ elif cond == "1011":
89
+ # LT / Less than / N != V
90
+ return self.get_N() != self.get_V()
91
+ elif cond == "1100":
92
+ # GT / greater than / Z clear and (n == v)
93
+ return (self.get_Z() == 1) & (self.get_N() != self.get_V())
94
+ elif cond == "1101":
95
+ # LE / less than or equal to / Z set OR (N != V)
96
+ return (self.get_Z() == 1) | (self.get_N() != self.get_V())
97
+ else:
98
+ # No condition
99
+ return None
100
+
101
+ def _load_le_instr(self, bitstream: bitstring.ConstBitStream, numbits: int) -> str:
102
+ # THUMB mode instructions swap endianness every two bytes!
103
+ if (self.addr & 1) == 1 and numbits > 16:
104
+ chunk = ""
105
+ oldpos = bitstream.pos
106
+ try:
107
+ for _ in range(0, numbits, 16):
108
+ chunk += bitstring.Bits(uint=bitstream.peek("uintle:%d" % 16), length=16).bin
109
+ bitstream.pos += 16
110
+ finally:
111
+ bitstream.pos = oldpos
112
+ return chunk
113
+ return super()._load_le_instr(bitstream, numbits)
114
+
115
+
116
+ class Instruction_MRC(ARMInstruction):
117
+ name = "MRC"
118
+ bin_format = "cccc1110CCC1nnnnddddppppOOOOOOOO"
119
+ # 11101110000100010001111100010000
120
+ # c = cond
121
+ # C = Coprocessor operation mode
122
+ # d = CPd
123
+ # O = Offset
124
+ # p = CP#
125
+
126
+ def compute_result(self): # pylint: disable=arguments-differ
127
+ # TODO at least look at the conditionals
128
+ # TODO Clobber the dst reg of MCR
129
+ # TODO maybe treat coproc regs as simple storage (even though they are very much not)
130
+ log.debug("Ignoring MRC instruction at %#x.", self.addr)
131
+
132
+
133
+ class Instruction_MCR(ARMInstruction):
134
+ name = "MCR"
135
+ bin_format = "cccc1110CCC0nnnnddddppppOOOOOOOO"
136
+ # 11101110000000010000111100010000
137
+ # c = cond
138
+ # C = Coprocessor operation mode
139
+ # d = CPd
140
+ # O = Offset
141
+ # p = CP#
142
+
143
+ def compute_result(self): # pylint: disable=arguments-differ
144
+ # TODO at least look at the conditionals
145
+ # TODO Clobber the dst reg of MCR
146
+ # TODO maybe treat coproc regs as simple storage (even though they are very much not)
147
+ log.debug("Ignoring MCR instruction at %#x.", self.addr)
148
+
149
+
150
+ class Instruction_MSR(ARMInstruction):
151
+ name = "MSR"
152
+ bin_format = "cccc00i10d10xxxj1111ssssssssssss"
153
+ # 11100011001000011111000010010001
154
+ # 11100001011011111111000000000001
155
+
156
+ def compute_result(self): # pylint: disable=arguments-differ
157
+ log.debug(
158
+ "Ignoring MSR instruction at %#x. VEX cannot support this instruction. "
159
+ "See pyvex/lifting/gym/arm_spotter.py",
160
+ self.addr,
161
+ )
162
+
163
+
164
+ class Instruction_MRS(ARMInstruction):
165
+ name = "MRS"
166
+ bin_format = "cccc00010s001111dddd000000000000"
167
+
168
+ def compute_result(self): # pylint: disable=arguments-differ
169
+ log.debug(
170
+ "Ignoring MRS instruction at %#x. VEX cannot support this instruction. "
171
+ "See pyvex/lifting/gym/arm_spotter.py",
172
+ self.addr,
173
+ )
174
+
175
+
176
+ class Instruction_STM(ARMInstruction):
177
+ name = "STM"
178
+ bin_format = "cccc100pu1w0bbbbrrrrrrrrrrrrrrrr"
179
+
180
+ def match_instruction(self, data, bitstrm):
181
+ # If we don't push anything, that's not real
182
+ if int(data["r"]) == 0:
183
+ raise ParseError("Invalid STM instruction")
184
+ return True
185
+
186
+ def compute_result(self): # pylint: disable=arguments-differ
187
+ log.debug(
188
+ "Ignoring STMxx ^ instruction at %#x. This mode is not implemented by VEX! "
189
+ "See pyvex/lifting/gym/arm_spotter.py",
190
+ self.addr,
191
+ )
192
+
193
+
194
+ class Instruction_LDM(ARMInstruction):
195
+ name = "LDM"
196
+ bin_format = "cccc100PU1W1bbbbrrrrrrrrrrrrrrrr"
197
+
198
+ def match_instruction(self, data, bitstrm):
199
+ # If we don't push anything, that's not real
200
+ if int(data["r"]) == 0:
201
+ raise ParseError("Invalid LDM instruction")
202
+ return True
203
+
204
+ def compute_result(self): # pylint: disable=arguments-differ
205
+ # test if PC will be set. If so, the jumpkind of this block should be Ijk_Ret
206
+ log.debug("Spotting an LDM instruction at %#x. This is not fully tested. Prepare for errors.", self.addr)
207
+
208
+ src_n = f"r{int(self.data['b'], 2)}"
209
+ src = self.get(src_n, Type.int_32)
210
+
211
+ for reg_num, bit in enumerate(self.data["r"]):
212
+ reg_num = 15 - reg_num
213
+ if bit == "1":
214
+ if self.data["P"] == "1":
215
+ if self.data["U"] == "0":
216
+ src += 4
217
+ else:
218
+ src -= 4
219
+ val = self.load(src, Type.int_32)
220
+ self.put(val, f"r{reg_num}")
221
+ if self.data["P"] == "0":
222
+ if self.data["U"] == "0":
223
+ src += 4
224
+ else:
225
+ src -= 4
226
+ # If we touch PC, we're doing a RET!
227
+ if reg_num == 15 and bit == "1":
228
+ cond = self.evaluate_condition()
229
+ if cond is not None:
230
+ self.jump(cond, val, JumpKind.Ret)
231
+ else:
232
+ self.jump(None, val, JumpKind.Ret)
233
+ # Write-back
234
+ if self.data["W"] == "1":
235
+ self.put(src, src_n)
236
+
237
+
238
+ class Instruction_STC(ARMInstruction):
239
+ name = "STC"
240
+ bin_format = "cccc110PUNW0nnnnddddppppOOOOOOOO"
241
+
242
+ def compute_result(self): # pylint: disable=arguments-differ
243
+ # TODO At least look at the conditionals
244
+ log.debug("Ignoring STC instruction at %#x.", self.addr)
245
+
246
+
247
+ class Instruction_STC_THUMB(ARMInstruction):
248
+ name = "STC"
249
+ bin_format = "111c110PUNW0nnnnddddppppOOOOOOOO"
250
+
251
+ def compute_result(self): # pylint: disable=arguments-differ
252
+ # TODO At least look at the conditionals
253
+ log.debug("Ignoring STC instruction at %#x.", self.addr)
254
+
255
+
256
+ class Instruction_LDC(ARMInstruction):
257
+ name = "LDC"
258
+ bin_format = "cccc110PUNW1nnnnddddppppOOOOOOOO"
259
+
260
+ def compute_result(self): # pylint: disable=arguments-differ
261
+ # TODO At least look at the conditionals
262
+ # TODO Clobber the dest reg of LDC
263
+ # TODO Maybe clobber the dst reg of CDP, if we're really adventurous
264
+ log.debug("Ignoring LDC instruction at %#x.", self.addr)
265
+
266
+
267
+ class Instruction_LDC_THUMB(ARMInstruction):
268
+ name = "LDC"
269
+ bin_format = "111c110PUNW1nnnnddddppppOOOOOOOO"
270
+
271
+ def compute_result(self): # pylint: disable=arguments-differ
272
+ # TODO At least look at the conditionals
273
+ # TODO Clobber the dest reg of LDC
274
+ # TODO Maybe clobber the dst reg of CDP, if we're really adventurous
275
+ log.debug("Ignoring LDC instruction at %#x.", self.addr)
276
+
277
+
278
+ class Instruction_CDP(Instruction):
279
+ name = "CDP"
280
+ bin_format = "cccc1110oooonnnnddddppppPPP0mmmm"
281
+ # c = cond
282
+ # d = CPd
283
+ # O = Offset
284
+ # p = CP#
285
+
286
+ def compute_result(self): # pylint: disable=arguments-differ
287
+ # TODO At least look at the conditionals
288
+ # TODO Maybe clobber the dst reg of CDP, if we're really adventurous
289
+ log.debug("Ignoring CDP instruction at %#x.", self.addr)
290
+
291
+
292
+ ##
293
+ ## Thumb! (ugh)
294
+ ##
295
+
296
+
297
+ class ThumbInstruction(Instruction): # pylint: disable=abstract-method
298
+ def mark_instruction_start(self):
299
+ self.irsb_c.imark(self.addr - 1, self.bytewidth, 1)
300
+
301
+
302
+ class Instruction_tCPSID(ThumbInstruction):
303
+ name = "CPSID"
304
+ bin_format = "101101x0011x0010"
305
+
306
+ def compute_result(self): # pylint: disable=arguments-differ
307
+ # TODO haha lol yeah right
308
+ log.debug("[thumb] Ignoring CPS instruction at %#x.", self.addr)
309
+
310
+
311
+ class Instruction_tMSR(ThumbInstruction):
312
+ name = "tMSR"
313
+ bin_format = "10x0mmmmxxxxxxxx11110011100Rrrrr"
314
+
315
+ def compute_result(self): # pylint: disable=arguments-differ
316
+ dest_spec_reg = int(self.data["x"], 2)
317
+ src_reg = f"r{int(self.data['r'], 2)}"
318
+
319
+ # If 0, do not write the SPSR
320
+ if self.data["R"] == "0":
321
+ if dest_spec_reg == 8: # msp
322
+ src = self.get(src_reg, Type.int_32)
323
+ self.put(src, "sp")
324
+ elif dest_spec_reg == 16: # primask
325
+ src = self.get(src_reg, Type.int_32)
326
+ self.put(src, "primask")
327
+ else:
328
+ log.debug(
329
+ "[thumb] FIXME: tMSR at %#x is writing into an unsupported special register %#x. "
330
+ "Ignoring the instruction.",
331
+ self.addr,
332
+ dest_spec_reg,
333
+ )
334
+ else:
335
+ log.debug("[thumb] tMSR at %#x is writing SPSR. Ignoring the instruction. FixMe.", self.addr)
336
+ log.debug(
337
+ "[thumb] Spotting an tMSR instruction at %#x. This is not fully tested. Prepare for errors.", self.addr
338
+ )
339
+
340
+
341
+ class Instruction_tMRS(ThumbInstruction):
342
+ name = "tMRS"
343
+ bin_format = "10x0mmmmxxxxxxxx11110011111Rrrrr"
344
+
345
+ def compute_result(self): # pylint: disable=arguments-differ
346
+ spec_reg = int(self.data["x"], 2)
347
+ dest_reg = f"r{int(self.data['m'], 2)}"
348
+
349
+ # Reading from CPSR
350
+ if self.data["R"] == "0":
351
+ # See special registers constants here:
352
+ # https://github.com/aquynh/capstone/blob/45bec1a691e455b864f7e4d394711a467e5493dc/arch/ARM/ARMInstPrinter.c#L1654
353
+ if spec_reg == 8:
354
+ # We move the SP and call it a day.
355
+ src = self.get("sp", Type.int_32)
356
+ self.put(src, dest_reg)
357
+ elif spec_reg == 16:
358
+ src = self.get("primask", Type.int_32)
359
+ self.put(src, dest_reg)
360
+ else:
361
+ log.debug(
362
+ "[thumb] FIXME: tMRS at %#x is using the unsupported special register %#x. "
363
+ "Ignoring the instruction.",
364
+ self.addr,
365
+ spec_reg,
366
+ )
367
+ else:
368
+ log.debug("[thumb] tMRS at %#x is reading from SPSR. Ignoring the instruction. FixMe.", self.addr)
369
+ log.debug("[thumb] Ignoring tMRS instruction at %#x.", self.addr)
370
+ log.debug(
371
+ "[thumb] Spotting an tMRS instruction at %#x. This is not fully tested. Prepare for errors.", self.addr
372
+ )
373
+
374
+
375
+ class Instruction_tDMB(ThumbInstruction):
376
+ name = "DMB"
377
+ bin_format = "100011110101xxxx1111001110111111"
378
+
379
+ def compute_result(self): # pylint: disable=arguments-differ
380
+ # TODO haha lol yeah right
381
+ log.debug("[thumb] Ignoring DMB instruction at %#x.", self.addr)
382
+
383
+
384
+ class Instruction_WFI(ThumbInstruction):
385
+ name = "WFI"
386
+ bin_format = "10111111001a0000"
387
+ # 1011111100110000
388
+
389
+ def compute_result(self): # pylint: disable=arguments-differ
390
+ log.debug("[thumb] Ignoring WFI instruction at %#x.", self.addr)
391
+
392
+
393
+ class ARMSpotter(GymratLifter):
394
+ arm_instrs = [
395
+ Instruction_MRC,
396
+ Instruction_MCR,
397
+ Instruction_MSR,
398
+ Instruction_MRS,
399
+ Instruction_STM,
400
+ Instruction_LDM,
401
+ Instruction_STC,
402
+ Instruction_LDC,
403
+ Instruction_CDP,
404
+ ]
405
+ thumb_instrs = [
406
+ Instruction_tCPSID,
407
+ Instruction_tMSR,
408
+ Instruction_tMRS,
409
+ Instruction_WFI,
410
+ Instruction_tDMB,
411
+ Instruction_STC_THUMB,
412
+ Instruction_LDC_THUMB,
413
+ ]
414
+
415
+ def __init__(self, arch: Arch, addr: int):
416
+ super().__init__(arch, addr)
417
+ self.thumb: bool = False
418
+
419
+ def _lift(self):
420
+ if self.irsb.addr & 1:
421
+ # Thumb!
422
+ self.instrs = self.thumb_instrs
423
+ self.thumb = True
424
+ else:
425
+ self.instrs = self.arm_instrs
426
+ self.thumb = False
427
+ super()._lift()
@@ -0,0 +1,129 @@
1
+ import logging
2
+
3
+ from pyvex.lifting.util import GymratLifter, Instruction, JumpKind, Type
4
+
5
+ log = logging.getLogger(__name__)
6
+
7
+ # pylint: disable=missing-class-docstring
8
+
9
+
10
+ class Instruction_SWAPGS(Instruction):
11
+ name = "SWAPGS"
12
+ bin_format = "000011110000000111111000" # 0f 01 f8
13
+
14
+ def compute_result(self, *args):
15
+ pass # TODO check for priv mode
16
+
17
+
18
+ class Instruction_SYSRET(Instruction):
19
+ name = "SYSRET"
20
+ bin_format = "010010000000111100000111" # 48 04 07
21
+
22
+ def compute_result(self, *args):
23
+ result = self.dirty(Type.int_64, "%sg_dirtyhelper_SYSRET" % self.arch.name.lower(), ())
24
+ self.jump(None, result, JumpKind.Ret)
25
+
26
+
27
+ class Instruction_IRETQ(Instruction):
28
+ name = "IRETQ"
29
+ bin_format = "0100100011001111" # 48 cf
30
+
31
+ def compute_result(self, *args):
32
+ result = self.dirty(Type.int_64, "%sg_dirtyhelper_IRETQ" % self.arch.name.lower(), ())
33
+ self.jump(None, result, JumpKind.Ret)
34
+
35
+
36
+ class Instruction_RDMSR(Instruction):
37
+ name = "RDMSR"
38
+ bin_format = "0000111100110010" # 0f 32
39
+
40
+ def compute_result(self, *args):
41
+ ecx = self.get("ecx", Type.int_32)
42
+ result = self.dirty(Type.int_64, "%sg_dirtyhelper_RDMSR" % self.arch.name.lower(), (ecx,))
43
+ edx = result.narrow_high(Type.int_32)
44
+ eax = result.narrow_low(Type.int_32)
45
+ if self.arch.bits == 32:
46
+ self.put(eax, "eax")
47
+ self.put(edx, "edx")
48
+ else:
49
+ self.put(eax.widen_unsigned(Type.int_64), "rax")
50
+ self.put(edx.widen_unsigned(Type.int_64), "rdx")
51
+
52
+
53
+ class Instruction_XGETBV(Instruction):
54
+ name = "XGETBV"
55
+ bin_format = "000011110000000111010000" # 0f 01 d0
56
+
57
+ def compute_result(self, *args):
58
+ ecx = self.get("ecx", Type.int_32)
59
+ result = self.dirty(Type.int_64, "%sg_dirtyhelper_XGETBV" % self.arch.name.lower(), (ecx,))
60
+ edx = result.narrow_high(Type.int_32)
61
+ eax = result.narrow_low(Type.int_32)
62
+ if self.arch.bits == 32:
63
+ self.put(eax, "eax")
64
+ self.put(edx, "edx")
65
+ else:
66
+ self.put(eax.widen_unsigned(Type.int_64), "rax")
67
+ self.put(edx.widen_unsigned(Type.int_64), "rdx")
68
+
69
+
70
+ class Instruction_AAM(Instruction):
71
+ name = "AAM"
72
+ bin_format = "11010100iiiiiiii"
73
+
74
+ # From https://www.felixcloutier.com/x86/aam
75
+ def compute_result(self): # pylint: disable=arguments-differ
76
+ base = self.constant(int(self.data["i"], 2), Type.int_8)
77
+ temp_al = self.get("al", Type.int_8)
78
+ temp_ah = temp_al // base
79
+ temp_al = temp_al % base
80
+ self.put(temp_ah, "ah")
81
+ self.put(temp_al, "al")
82
+ log.debug(
83
+ "The generalized AAM instruction is not supported by VEX, and is handled specially by pyvex."
84
+ " It has no flag handling at present. See pyvex/lifting/gym/x86_spotter.py for details"
85
+ )
86
+
87
+ # TODO: Flags
88
+
89
+
90
+ class Instruction_AAD(Instruction):
91
+ name = "AAD"
92
+ bin_format = "11010101iiiiiiii"
93
+
94
+ # From https://www.felixcloutier.com/x86/aad
95
+ def compute_result(self): # pylint: disable=arguments-differ
96
+ base = self.constant(int(self.data["i"], 2), Type.int_8)
97
+ temp_al = self.get("al", Type.int_8)
98
+ temp_ah = self.get("ah", Type.int_8)
99
+ temp_al = (temp_al + (temp_ah * base)) & 0xFF
100
+ temp_ah = self.constant(0, Type.int_8)
101
+ self.put(temp_ah, "ah")
102
+ self.put(temp_al, "al")
103
+ log.debug(
104
+ "The generalized AAD instruction is not supported by VEX, and is handled specially by pyvex."
105
+ " It has no flag handling at present. See pyvex/lifting/gym/x86_spotter.py for details"
106
+ )
107
+
108
+ # TODO: Flags
109
+
110
+
111
+ class AMD64Spotter(GymratLifter):
112
+ instrs = [
113
+ Instruction_RDMSR,
114
+ Instruction_XGETBV,
115
+ Instruction_AAD,
116
+ Instruction_AAM,
117
+ Instruction_SWAPGS,
118
+ Instruction_IRETQ,
119
+ Instruction_SYSRET,
120
+ ]
121
+
122
+
123
+ class X86Spotter(GymratLifter):
124
+ instrs = [
125
+ Instruction_RDMSR,
126
+ Instruction_XGETBV,
127
+ Instruction_AAD,
128
+ Instruction_AAM,
129
+ ]
@@ -0,0 +1,117 @@
1
+ import logging
2
+ import threading
3
+ from typing import TYPE_CHECKING
4
+
5
+ from pyvex.errors import LiftingException
6
+ from pyvex.native import ffi, pvc
7
+ from pyvex.types import CLiftSource, LibvexArch
8
+
9
+ from .lift_function import Lifter
10
+
11
+ log = logging.getLogger("pyvex.lifting.libvex")
12
+
13
+ _libvex_lock = threading.Lock()
14
+
15
+ LIBVEX_SUPPORTED_ARCHES = {
16
+ "X86",
17
+ "AMD64",
18
+ "MIPS32",
19
+ "MIPS64",
20
+ "ARM",
21
+ "ARMEL",
22
+ "ARMHF",
23
+ "ARMCortexM",
24
+ "AARCH64",
25
+ "PPC32",
26
+ "PPC64",
27
+ "S390X",
28
+ "RISCV64",
29
+ }
30
+
31
+ VEX_MAX_INSTRUCTIONS = 99
32
+ VEX_MAX_BYTES = 5000
33
+
34
+
35
+ class VexRegisterUpdates:
36
+ VexRegUpd_INVALID = 0x700
37
+ VexRegUpdSpAtMemAccess = 0x701
38
+ VexRegUpdUnwindregsAtMemAccess = 0x702
39
+ VexRegUpdAllregsAtMemAccess = 0x703
40
+ VexRegUpdAllregsAtEachInsn = 0x704
41
+ VexRegUpdLdAllregsAtEachInsn = 0x705
42
+
43
+
44
+ class LibVEXLifter(Lifter):
45
+ __slots__ = ()
46
+
47
+ REQUIRE_DATA_C = True
48
+
49
+ @staticmethod
50
+ def get_vex_log():
51
+ return bytes(ffi.buffer(pvc.msg_buffer, pvc.msg_current_size)).decode() if pvc.msg_buffer != ffi.NULL else None
52
+
53
+ def _lift(self):
54
+ if TYPE_CHECKING:
55
+ assert isinstance(self.irsb.arch, LibvexArch)
56
+ assert isinstance(self.data, CLiftSource)
57
+ try:
58
+ _libvex_lock.acquire()
59
+
60
+ pvc.log_level = log.getEffectiveLevel()
61
+ vex_arch = getattr(pvc, self.irsb.arch.vex_arch, None)
62
+ assert vex_arch is not None
63
+
64
+ if self.bytes_offset is None:
65
+ self.bytes_offset = 0
66
+
67
+ if self.max_bytes is None or self.max_bytes > VEX_MAX_BYTES:
68
+ max_bytes = VEX_MAX_BYTES
69
+ else:
70
+ max_bytes = self.max_bytes
71
+
72
+ if self.max_inst is None or self.max_inst > VEX_MAX_INSTRUCTIONS:
73
+ max_inst = VEX_MAX_INSTRUCTIONS
74
+ else:
75
+ max_inst = self.max_inst
76
+
77
+ strict_block_end = self.strict_block_end
78
+ if strict_block_end is None:
79
+ strict_block_end = True
80
+
81
+ if self.cross_insn_opt:
82
+ px_control = VexRegisterUpdates.VexRegUpdUnwindregsAtMemAccess
83
+ else:
84
+ px_control = VexRegisterUpdates.VexRegUpdLdAllregsAtEachInsn
85
+
86
+ self.irsb.arch.vex_archinfo["hwcache_info"]["caches"] = ffi.NULL
87
+ lift_r = pvc.vex_lift(
88
+ vex_arch,
89
+ self.irsb.arch.vex_archinfo,
90
+ self.data + self.bytes_offset,
91
+ self.irsb.addr,
92
+ max_inst,
93
+ max_bytes,
94
+ self.opt_level,
95
+ self.traceflags,
96
+ self.allow_arch_optimizations,
97
+ strict_block_end,
98
+ 1 if self.collect_data_refs else 0,
99
+ 1 if self.load_from_ro_regions else 0,
100
+ 1 if self.const_prop else 0,
101
+ px_control,
102
+ self.bytes_offset,
103
+ )
104
+ log_str = self.get_vex_log()
105
+ if lift_r == ffi.NULL:
106
+ raise LiftingException("libvex: unknown error" if log_str is None else log_str)
107
+ else:
108
+ if log_str is not None:
109
+ log.debug(log_str)
110
+
111
+ self.irsb._from_c(lift_r, skip_stmts=self.skip_stmts)
112
+ if self.irsb.size == 0:
113
+ log.debug("raising lifting exception")
114
+ raise LiftingException("libvex: could not decode any instructions @ 0x%x" % self.addr)
115
+ finally:
116
+ _libvex_lock.release()
117
+ self.irsb.arch.vex_archinfo["hwcache_info"]["caches"] = None