pyvex 9.2.189__cp312-cp312-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.
Files changed (60) 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/pyvex.dll +0 -0
  31. pyvex/lib/pyvex.lib +0 -0
  32. pyvex/lifting/__init__.py +18 -0
  33. pyvex/lifting/gym/README.md +7 -0
  34. pyvex/lifting/gym/__init__.py +5 -0
  35. pyvex/lifting/gym/aarch64_spotter.py +40 -0
  36. pyvex/lifting/gym/arm_spotter.py +427 -0
  37. pyvex/lifting/gym/x86_spotter.py +129 -0
  38. pyvex/lifting/libvex.py +117 -0
  39. pyvex/lifting/lift_function.py +304 -0
  40. pyvex/lifting/lifter.py +124 -0
  41. pyvex/lifting/post_processor.py +16 -0
  42. pyvex/lifting/util/__init__.py +14 -0
  43. pyvex/lifting/util/instr_helper.py +422 -0
  44. pyvex/lifting/util/lifter_helper.py +154 -0
  45. pyvex/lifting/util/syntax_wrapper.py +312 -0
  46. pyvex/lifting/util/vex_helper.py +301 -0
  47. pyvex/lifting/zerodivision.py +71 -0
  48. pyvex/native.py +63 -0
  49. pyvex/py.typed +1 -0
  50. pyvex/stmt.py +740 -0
  51. pyvex/types.py +48 -0
  52. pyvex/utils.py +63 -0
  53. pyvex/vex_ffi.py +1452 -0
  54. pyvex-9.2.189.dist-info/METADATA +181 -0
  55. pyvex-9.2.189.dist-info/RECORD +60 -0
  56. pyvex-9.2.189.dist-info/WHEEL +5 -0
  57. pyvex-9.2.189.dist-info/licenses/LICENSE +24 -0
  58. pyvex-9.2.189.dist-info/licenses/pyvex_c/LICENSE +339 -0
  59. pyvex-9.2.189.dist-info/licenses/vex/LICENSE.GPL +340 -0
  60. pyvex-9.2.189.dist-info/licenses/vex/LICENSE.README +23 -0
pyvex/const.py ADDED
@@ -0,0 +1,426 @@
1
+ # pylint:disable=missing-class-docstring,raise-missing-from,not-callable
2
+ import re
3
+ from abc import ABC
4
+
5
+ from .enums import VEXObject, get_enum_from_int
6
+ from .errors import PyVEXError
7
+ from .native import ffi, pvc
8
+
9
+
10
+ # IRConst hierarchy
11
+ class IRConst(VEXObject, ABC):
12
+ __slots__ = ["_value"]
13
+
14
+ type: str
15
+ size: int
16
+ tag: str
17
+ c_constructor = None
18
+ _value: int
19
+
20
+ def pp(self):
21
+ print(str(self))
22
+
23
+ @property
24
+ def value(self) -> int:
25
+ return self._value
26
+
27
+ @staticmethod
28
+ def _from_c(c_const):
29
+ if c_const[0] == ffi.NULL:
30
+ return None
31
+
32
+ tag = get_enum_from_int(c_const.tag)
33
+
34
+ try:
35
+ return tag_to_const_class(tag)._from_c(c_const)
36
+ except KeyError:
37
+ raise PyVEXError("Unknown/unsupported IRConstTag %s\n" % tag)
38
+
39
+ _translate = _from_c
40
+
41
+ @classmethod
42
+ def _to_c(cls, const):
43
+ # libvex throws an exception when constructing a U1 with a value other than 0 or 1
44
+ if const.tag == "Ico_U1" and const.value not in (0, 1):
45
+ raise PyVEXError("Invalid U1 value: %d" % const.value)
46
+
47
+ try:
48
+ return cls.c_constructor(const.value)
49
+ except KeyError:
50
+ raise PyVEXError("Unknown/unsupported IRConstTag %s]n" % const.tag)
51
+
52
+ def __eq__(self, other):
53
+ if not isinstance(other, type(self)):
54
+ return False
55
+ return self._value == other._value
56
+
57
+ def __hash__(self):
58
+ return hash((type(self), self._value))
59
+
60
+
61
+ class U1(IRConst):
62
+ __slots__: list[str] = []
63
+
64
+ type = "Ity_I1"
65
+ size = 1
66
+ tag = "Ico_U1"
67
+ op_format = "1"
68
+ c_constructor = pvc.IRConst_U1
69
+
70
+ def __init__(self, value):
71
+ self._value = value
72
+
73
+ def __str__(self):
74
+ return "%d" % self.value
75
+
76
+ @staticmethod
77
+ def _from_c(c_const):
78
+ return U1(c_const.Ico.U1)
79
+
80
+
81
+ class U8(IRConst):
82
+ __slots__: list[str] = []
83
+
84
+ type = "Ity_I8"
85
+ size = 8
86
+ tag = "Ico_U8"
87
+ op_format = "8"
88
+ c_constructor = pvc.IRConst_U8
89
+
90
+ def __init__(self, value):
91
+ self._value = value
92
+
93
+ def __str__(self):
94
+ return "0x%02x" % self.value
95
+
96
+ @staticmethod
97
+ def _from_c(c_const):
98
+ return _U8_POOL[c_const.Ico.U8]
99
+
100
+
101
+ _U8_POOL = [U8(i) for i in range(256)]
102
+
103
+
104
+ class U16(IRConst):
105
+ __slots__: list[str] = []
106
+
107
+ type = "Ity_I16"
108
+ size = 16
109
+ tag = "Ico_U16"
110
+ op_format = "16"
111
+ c_constructor = pvc.IRConst_U16
112
+
113
+ def __init__(self, value):
114
+ self._value = value
115
+
116
+ def __str__(self):
117
+ return "0x%04x" % self.value
118
+
119
+ @staticmethod
120
+ def _from_c(c_const):
121
+ val = c_const.Ico.U16
122
+ if val < 1024:
123
+ return _U16_POOL[val]
124
+ if val >= 0xFC00:
125
+ return _U16_POOL[val - 0xFC00 + 1024]
126
+ return U16(val)
127
+
128
+
129
+ _U16_POOL = [U16(i) for i in range(1024)] + [U16(i) for i in range(0xFC00, 0xFFFF + 1)]
130
+
131
+
132
+ class U32(IRConst):
133
+ __slots__: list[str] = []
134
+
135
+ type = "Ity_I32"
136
+ size = 32
137
+ tag = "Ico_U32"
138
+ op_format = "32"
139
+ c_constructor = pvc.IRConst_U32
140
+
141
+ def __init__(self, value: int):
142
+ self._value = value
143
+
144
+ def __str__(self):
145
+ return "0x%08x" % self.value
146
+
147
+ @staticmethod
148
+ def _from_c(c_const):
149
+ val = c_const.Ico.U32
150
+ if val < 1024:
151
+ return _U32_POOL[val]
152
+ if val >= 0xFFFFFC00:
153
+ return _U32_POOL[val - 0xFFFFFC00 + 1024]
154
+ return U32(val)
155
+
156
+
157
+ _U32_POOL = [U32(i) for i in range(1024)] + [U32(i) for i in range(0xFFFFFC00, 0xFFFFFFFF + 1)]
158
+
159
+
160
+ class U64(IRConst):
161
+ __slots__: list[str] = []
162
+
163
+ type = "Ity_I64"
164
+ size = 64
165
+ tag = "Ico_U64"
166
+ op_format = "64"
167
+ c_constructor = pvc.IRConst_U64
168
+
169
+ def __init__(self, value):
170
+ self._value = value
171
+
172
+ def __str__(self):
173
+ return "0x%016x" % self.value
174
+
175
+ @staticmethod
176
+ def _from_c(c_const):
177
+ val = c_const.Ico.U64
178
+ if val < 1024:
179
+ return _U64_POOL[val]
180
+ if val >= 0xFFFFFFFFFFFFFC00:
181
+ return _U64_POOL[val - 0xFFFFFFFFFFFFFC00 + 1024]
182
+ return U64(val)
183
+
184
+
185
+ _U64_POOL = [U64(i) for i in range(1024)] + [U64(i) for i in range(0xFFFFFFFFFFFFFC00, 0xFFFFFFFFFFFFFFFF + 1)]
186
+
187
+ # Integer Type Imagination
188
+ class_cache = {1: U1, 8: U8, 16: U16, 32: U32, 64: U64}
189
+
190
+
191
+ def vex_int_class(size):
192
+ try:
193
+ return class_cache[size]
194
+ except KeyError:
195
+
196
+ class VexInt(IRConst):
197
+ type = "Ity_I%d" % size
198
+ tag = "Ico_U%d" % size
199
+ op_format = str(size)
200
+
201
+ def __init__(self, value):
202
+ IRConst.__init__(self)
203
+ self._value = value
204
+
205
+ def __str__(self):
206
+ return f"(0x{self.value:x} :: {self.type})"
207
+
208
+ VexInt.__name__ = "U%d" % size
209
+ class_cache[size] = VexInt
210
+ return VexInt
211
+
212
+
213
+ class F32(IRConst):
214
+ __slots__: list[str] = []
215
+
216
+ type = "Ity_F32"
217
+ tag = "Ico_F32"
218
+ op_format = "F32"
219
+ c_constructor = pvc.IRConst_F32
220
+ size = 32
221
+
222
+ def __init__(self, value):
223
+ self._value = value
224
+
225
+ def __str__(self):
226
+ return "%f" % self.value
227
+
228
+ @staticmethod
229
+ def _from_c(c_const):
230
+ return F32(c_const.Ico.F32)
231
+
232
+
233
+ class F32i(IRConst):
234
+ __slots__: list[str] = []
235
+
236
+ type = "Ity_F32"
237
+ tag = "Ico_F32i"
238
+ op_format = "F32"
239
+ c_constructor = pvc.IRConst_F32i
240
+ size = 32
241
+
242
+ def __init__(self, value):
243
+ self._value = value
244
+
245
+ def __str__(self):
246
+ return "%f" % self.value
247
+
248
+ @staticmethod
249
+ def _from_c(c_const):
250
+ return F32i(c_const.Ico.F32)
251
+
252
+
253
+ class F64(IRConst):
254
+ __slots__: list[str] = []
255
+
256
+ type = "Ity_F64"
257
+ tag = "Ico_F64"
258
+ op_format = "F64"
259
+ c_constructor = pvc.IRConst_F64
260
+ size = 64
261
+
262
+ def __init__(self, value):
263
+ self._value = value
264
+
265
+ def __str__(self):
266
+ return "%f" % self.value
267
+
268
+ @staticmethod
269
+ def _from_c(c_const):
270
+ return F64(c_const.Ico.F64)
271
+
272
+
273
+ class F64i(IRConst):
274
+ __slots__: list[str] = []
275
+
276
+ type = "Ity_F64"
277
+ tag = "Ico_F64i"
278
+ op_format = "F64"
279
+ c_constructor = pvc.IRConst_F64i
280
+ size = 64
281
+
282
+ def __init__(self, value):
283
+ self._value = value
284
+
285
+ def __str__(self):
286
+ return "%f" % self.value
287
+
288
+ @staticmethod
289
+ def _from_c(c_const):
290
+ return F64i(c_const.Ico.F64)
291
+
292
+
293
+ class V128(IRConst):
294
+ __slots__: list[str] = []
295
+
296
+ type = "Ity_V128"
297
+ tag = "Ico_V128"
298
+ op_format = "V128"
299
+ c_constructor = pvc.IRConst_V128
300
+ size = 128
301
+
302
+ def __init__(self, value):
303
+ self._value = value
304
+
305
+ def __str__(self):
306
+ return "%x" % self.value
307
+
308
+ # vex doesn't store a full 128 bit constant, instead it stores 1 bit per 8 bits of data
309
+ # and duplicates each bit 8 times
310
+ @staticmethod
311
+ def _from_c(c_const):
312
+ base_const = c_const.Ico.V128
313
+ real_const = 0
314
+ for i in range(16):
315
+ if (base_const >> i) & 1 == 1:
316
+ real_const |= 0xFF << (8 * i)
317
+ return V128(real_const)
318
+
319
+
320
+ class V256(IRConst):
321
+ __slots__: list[str] = []
322
+
323
+ type = "Ity_V256"
324
+ tag = "Ico_V256"
325
+ op_format = "V256"
326
+ c_constructor = pvc.IRConst_V256
327
+ size = 256
328
+
329
+ def __init__(self, value):
330
+ self._value = value
331
+
332
+ def __str__(self):
333
+ return "%x" % self.value
334
+
335
+ # see above
336
+ @staticmethod
337
+ def _from_c(c_const):
338
+ base_const = c_const.Ico.V256
339
+ real_const = 0
340
+ for i in range(32):
341
+ if (base_const >> i) & 1 == 1:
342
+ real_const |= 0xFF << (8 * i)
343
+ return V256(real_const)
344
+
345
+
346
+ predefined_types = [U1, U8, U16, U32, U64, F32, F32i, F64, F64i, V128, V256]
347
+ predefined_types_map = {c.type: c for c in predefined_types}
348
+ predefined_classes_map = {c.tag: c for c in predefined_types}
349
+
350
+ # precompiled regexes
351
+ int_ty_re = re.compile(r"Ity_I\d+")
352
+ int_tag_re = re.compile(r"Ico_U\d+")
353
+ tag_size_re = re.compile(r"Ico_[UFV](?P<size>\d+)i?")
354
+
355
+
356
+ def is_int_ty(ty):
357
+ m = int_ty_re.match(ty)
358
+ return m is not None
359
+
360
+
361
+ def is_int_tag(tag):
362
+ m = int_tag_re.match(tag)
363
+ return m is not None
364
+
365
+
366
+ def get_tag_size(tag):
367
+ m = tag_size_re.match(tag)
368
+ if m is None:
369
+ raise ValueError("Tag %s does not have size" % tag)
370
+ return int(m.group("size"))
371
+
372
+
373
+ type_str_re = re.compile(r"Ity_[IFDV](?P<size>\d+)")
374
+ type_tag_str_re = re.compile(r"[IFDV]?(?P<size>\d+)[SU]?")
375
+
376
+
377
+ def get_type_size(ty):
378
+ """
379
+ Returns the size, in BITS, of a VEX type specifier
380
+ e.g., Ity_I16 -> 16
381
+
382
+ :param ty:
383
+ :return:
384
+ """
385
+ m = type_str_re.match(ty)
386
+ if m is None:
387
+ raise ValueError("Type %s does not have size" % ty)
388
+ return int(m.group("size"))
389
+
390
+
391
+ def get_type_spec_size(ty):
392
+ """
393
+ Get the width of a "type specifier"
394
+ like I16U
395
+ or F16
396
+ or just 16
397
+ (Yes, this really just takes the int out. If we must special-case, do it here.
398
+ :param tyspec:
399
+ :return:
400
+ """
401
+ m = type_tag_str_re.match(ty)
402
+ if m is None:
403
+ raise ValueError("Type specifier %s does not have size" % ty)
404
+ return int(m.group("size"))
405
+
406
+
407
+ def ty_to_const_class(ty):
408
+ try:
409
+ return predefined_types_map[ty]
410
+ except KeyError:
411
+ if is_int_ty(ty):
412
+ size = get_type_size(ty)
413
+ return vex_int_class(size)
414
+ else:
415
+ raise ValueError("Type %s does not exist" % ty)
416
+
417
+
418
+ def tag_to_const_class(tag):
419
+ try:
420
+ return predefined_classes_map[tag]
421
+ except KeyError:
422
+ if is_int_tag(tag):
423
+ size = get_tag_size(tag)
424
+ return vex_int_class(size)
425
+ else:
426
+ raise ValueError("Tag %s does not exist" % tag)
pyvex/const_val.py ADDED
@@ -0,0 +1,26 @@
1
+ class ConstVal:
2
+ """
3
+ A constant value object. Indicates a constant value assignment to a VEX tmp variable.
4
+
5
+ :ivar tmp: The tmp variable being assigned to.
6
+ :ivar value: The value of the tmp variable.
7
+ :ivar stmt_idx: The IRSB statement index containing the data access
8
+ """
9
+
10
+ __slots__ = (
11
+ "tmp",
12
+ "value",
13
+ "stmt_idx",
14
+ )
15
+
16
+ def __init__(self, tmp: int, value: int, stmt_idx: int):
17
+ self.tmp = tmp
18
+ self.value = value
19
+ self.stmt_idx = stmt_idx
20
+
21
+ def __repr__(self):
22
+ return f"<ConstVal {self.tmp} = {self.value:#x} @ {self.stmt_idx}>"
23
+
24
+ @classmethod
25
+ def from_c(cls, r):
26
+ return cls(r.tmp, r.value, r.stmt_idx)
pyvex/data_ref.py ADDED
@@ -0,0 +1,55 @@
1
+ def data_ref_type_str(dref_enum):
2
+ """
3
+ Translate an ``enum DataRefTypes`` value into a string representation.
4
+ """
5
+ if dref_enum == 0x9000:
6
+ return "unknown"
7
+ elif dref_enum == 0x9001:
8
+ return "integer"
9
+ elif dref_enum == 0x9002:
10
+ return "fp"
11
+ elif dref_enum == 0x9003:
12
+ return "integer(store)"
13
+ else:
14
+ return "INVALID"
15
+
16
+
17
+ class DataRef:
18
+ """
19
+ A data reference object. Indicates a data access in an IRSB.
20
+
21
+ :ivar data_addr: The address of the data being accessed
22
+ :ivar data_size: The size of the data being accessed, in bytes
23
+ :ivar data_type: The type of the data, a DataRefTypes enum.
24
+ :ivar stmt_idx: The IRSB statement index containing the data access
25
+ :ivar ins_addr: The address of the instruction performing the data access
26
+ """
27
+
28
+ __slots__ = ("data_addr", "data_size", "data_type", "stmt_idx", "ins_addr")
29
+
30
+ def __init__(self, data_addr, data_size, data_type, stmt_idx, ins_addr):
31
+ self.data_addr = data_addr
32
+ self.data_size = data_size
33
+ self.data_type = data_type
34
+ self.stmt_idx = stmt_idx
35
+ self.ins_addr = ins_addr
36
+
37
+ @property
38
+ def data_type_str(self):
39
+ """
40
+ The data ref type as a string, "unknown" "integer" "fp" or "INVALID"
41
+ """
42
+ return data_ref_type_str(self.data_type)
43
+
44
+ def __repr__(self):
45
+ return "<DataRef accessing %#x %s:%d at %#x:%d>" % (
46
+ self.data_addr,
47
+ data_ref_type_str(self.data_type),
48
+ self.data_size,
49
+ self.ins_addr,
50
+ self.stmt_idx,
51
+ )
52
+
53
+ @classmethod
54
+ def from_c(cls, r):
55
+ return cls(r.data_addr, r.size, r.data_type, r.stmt_idx, r.ins_addr)
pyvex/enums.py ADDED
@@ -0,0 +1,156 @@
1
+ from typing import Any
2
+
3
+ from .native import ffi, pvc
4
+ from .utils import stable_hash
5
+
6
+
7
+ class VEXObject:
8
+ """
9
+ The base class for Vex types.
10
+ """
11
+
12
+ __slots__: list[str] = []
13
+
14
+ def __eq__(self, other):
15
+ if not isinstance(other, type(self)):
16
+ return False
17
+ # compare values in slots
18
+ for slot in self.__slots__:
19
+ if getattr(self, slot) != getattr(other, slot):
20
+ return False
21
+ return True
22
+
23
+ def __hash__(self):
24
+ values = [getattr(self, slot) for slot in self.__slots__]
25
+ for i, lst_val in enumerate(values):
26
+ if isinstance(lst_val, list):
27
+ values[i] = tuple(lst_val)
28
+ return stable_hash(tuple([type(self)] + values))
29
+
30
+
31
+ class IRCallee(VEXObject):
32
+ """
33
+ Describes a helper function to call.
34
+ """
35
+
36
+ __slots__ = ["regparms", "name", "mcx_mask"]
37
+
38
+ def __init__(self, regparms, name, mcx_mask):
39
+ VEXObject.__init__(self)
40
+ self.regparms = regparms
41
+ self.name = name
42
+ self.mcx_mask = mcx_mask
43
+
44
+ def __str__(self):
45
+ return str(self.name)
46
+
47
+ @staticmethod
48
+ def _from_c(c_callee):
49
+ return IRCallee(
50
+ c_callee.regparms,
51
+ ffi.string(c_callee.name).decode(),
52
+ # NO. #int(ffi.cast("unsigned long long", c_callee.addr)),
53
+ c_callee.mcx_mask,
54
+ )
55
+
56
+ @staticmethod
57
+ def _to_c(callee): # pylint: disable=unused-argument
58
+ raise TypeError(
59
+ "This doesn't work! Please invent a way to get the correct address for the named function from pyvex_c."
60
+ )
61
+ # c_callee = pvc.mkIRCallee(callee.regparms,
62
+ # callee.name.encode(),
63
+ # ffi.cast("void *", callee.addr))
64
+ # c_callee.mcx_mask = callee.mcx_mask
65
+ # return c_callee
66
+
67
+
68
+ class IRRegArray(VEXObject):
69
+ """
70
+ A section of the guest state that we want te be able to index at run time, so as to be able to describe indexed or
71
+ rotating register files on the guest.
72
+
73
+ :ivar int base: The offset into the state that this array starts
74
+ :ivar str elemTy: The types of the elements in this array, as VEX enum strings
75
+ :ivar int nElems: The number of elements in this array
76
+ """
77
+
78
+ __slots__ = ["base", "elemTy", "nElems"]
79
+
80
+ def __init__(self, base, elemTy, nElems):
81
+ VEXObject.__init__(self)
82
+ self.base = base
83
+ self.elemTy = elemTy
84
+ self.nElems = nElems
85
+
86
+ def __str__(self):
87
+ return "%s:%sx%d" % (self.base, self.elemTy[4:], self.nElems)
88
+
89
+ @staticmethod
90
+ def _from_c(c_arr):
91
+ return IRRegArray(c_arr.base, ints_to_enums[c_arr.elemTy], c_arr.nElems)
92
+
93
+ @staticmethod
94
+ def _to_c(arr):
95
+ return pvc.mkIRRegArray(arr.base, get_int_from_enum(arr.elemTy), arr.nElems)
96
+
97
+
98
+ ints_to_enums: dict[int, str] = {}
99
+ enums_to_ints: dict[str, int] = {}
100
+ irop_enums_to_ints: dict[str, int] = {}
101
+ will_be_overwritten = ["Ircr_GT", "Ircr_LT"]
102
+
103
+
104
+ def get_enum_from_int(i):
105
+ return ints_to_enums[i]
106
+
107
+
108
+ def get_int_from_enum(e):
109
+ return enums_to_ints[e]
110
+
111
+
112
+ _add_enum_counter = 0
113
+
114
+
115
+ def _add_enum(s, i=None): # TODO get rid of this
116
+ global _add_enum_counter # pylint: disable=global-statement
117
+ if i is None:
118
+ while _add_enum_counter in ints_to_enums:
119
+ _add_enum_counter += 1
120
+ i = _add_enum_counter
121
+ _add_enum_counter += 1 # Update for the next iteration
122
+ if i in ints_to_enums:
123
+ if ints_to_enums[i] not in will_be_overwritten:
124
+ raise ValueError("Enum with intkey %d already present" % i)
125
+ enums_to_ints[s] = i
126
+ ints_to_enums[i] = s
127
+ if s.startswith("Iop_"):
128
+ irop_enums_to_ints[s] = i
129
+
130
+
131
+ for attr in dir(pvc):
132
+ if attr[0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and hasattr(pvc, attr) and isinstance(getattr(pvc, attr), int):
133
+ _add_enum(attr, getattr(pvc, attr))
134
+
135
+
136
+ def vex_endness_from_string(endness_str):
137
+ return getattr(pvc, endness_str)
138
+
139
+
140
+ def default_vex_archinfo() -> dict[str, Any]:
141
+ return {
142
+ "hwcaps": 0,
143
+ "endness": vex_endness_from_string("VexEndnessLE"),
144
+ "ppc_icache_line_szB": 0,
145
+ "ppc_dcbz_szB": 0,
146
+ "ppc_dcbzl_szB": 0,
147
+ "arm64_dMinLine_lg2_szB": 0,
148
+ "arm64_iMinLine_lg2_szB": 0,
149
+ "hwcache_info": {
150
+ "num_levels": 0,
151
+ "num_caches": 0,
152
+ "caches": None,
153
+ "icaches_maintain_coherence": True,
154
+ },
155
+ "x86_cr0": 0xFFFFFFFF,
156
+ }
pyvex/errors.py ADDED
@@ -0,0 +1,31 @@
1
+ class PyVEXError(Exception):
2
+ pass
3
+
4
+
5
+ class SkipStatementsError(PyVEXError):
6
+ pass
7
+
8
+
9
+ #
10
+ # Exceptions and notifications that post-processors can raise
11
+ #
12
+
13
+
14
+ class LiftingException(Exception):
15
+ pass
16
+
17
+
18
+ class NeedStatementsNotification(LiftingException):
19
+ """
20
+ A post-processor may raise a NeedStatementsNotification if it needs to work with statements, but the current IRSB
21
+ is generated without any statement available (skip_stmts=True). The lifter will re-lift the current block with
22
+ skip_stmts=False upon catching a NeedStatementsNotification, and re-run the post-processors.
23
+
24
+ It's worth noting that if a post-processor always raises this notification for every basic block without statements,
25
+ it will essentially disable the skipping statement optimization, and it is bad for performance (especially for
26
+ CFGFast, which heavily relies on this optimization). Post-processor authors are encouraged to at least filter the
27
+ IRSBs based on available properties (jumpkind, next, etc.). If a post-processor must work with statements for the
28
+ majority of IRSBs, the author should implement it in PyVEX in C for the sake of a better performance.
29
+ """
30
+
31
+ pass