-
Notifications
You must be signed in to change notification settings - Fork 58
/
offsets.py
133 lines (106 loc) · 4.36 KB
/
offsets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import pkg_resources
import archinfo
filecache = {}
type_sizes = {"UChar": 1, "UShort": 2, "UInt": 4, "ULong": 8, "ULONG": 8, "U128": 16, "U256": 32}
arch_data = {}
defines = {"VEX_GUEST_PPC32_REDIR_STACK_SIZE": 16 * 2, "VEX_GUEST_PPC64_REDIR_STACK_SIZE": 16 * 2}
def to_int(ival):
if ival in defines:
return defines[ival]
return int(ival, 0)
def load_arch(archh):
if archh not in arch_data:
arch_data[archh] = {}
if archh not in filecache:
filecache[archh] = open(pkg_resources.resource_filename("pyvex", "include/libvex_guest_%s.h" % archh)).read()
return filecache[archh]
a = open(pkg_resources.resource_filename("pyvex", "include/libvex_guest_offsets.h")).read().splitlines()
for line in a:
_, defname, offstr = line.split()
offset = int(offstr, 0)
_, archname, fieldname = defname.split("_", 2)
fieldname = fieldname.lower()
arch_defs = load_arch(archname)
arraylen = None
typename = None
lst = arch_defs.split()
for i, k in enumerate(lst):
if k.lower().split("[")[0].strip(";") == "guest_%s" % fieldname:
typename = lst[i - 1].strip("/*")
if typename not in type_sizes:
continue
if "[" in k:
arraylen = to_int(k.split("[")[1].split("]")[0])
break
else:
raise Exception(f"Could not find field in arch {archname} for {fieldname}")
fieldsize = type_sizes[typename] * (1 if arraylen is None else arraylen)
arch_data[archname][fieldname] = (offset, fieldsize)
def canon_name(archh, offseth):
for some_name, (some_offset, _) in archh.registers.items():
if some_offset == offseth and some_name in arch_data[archh.vex_arch[7:].lower()]:
return some_name
return None
for archname in arch_data:
try:
arch = archinfo.arch_from_id(archname)
except (archinfo.ArchError, RuntimeError):
print("Skipping", archname)
continue
new_register_names = {}
new_registers_reverse = {}
misses = []
for a_offset, a_fieldname in arch.register_names.items():
cname = canon_name(arch, a_offset)
if cname is None:
misses.append((a_offset, a_fieldname))
continue
new_offset, new_size = arch_data[archname][cname]
# deal with picking up subregisters? shouldn't need to, beyond the above...
new_register_names[new_offset] = a_fieldname
for alt_name, (sub_offset, sub_size) in arch.registers.items():
if sub_offset >= a_offset and sub_offset < a_offset + new_size:
new_sub_offset = new_offset + (sub_offset - a_offset)
if new_sub_offset not in new_registers_reverse:
new_registers_reverse[new_sub_offset] = []
new_registers_reverse[new_sub_offset].append((sub_size, alt_name))
for misso, miss in misses:
for dlist in new_registers_reverse.values():
for _, alt_name in dlist:
if alt_name == miss:
new_register_names[misso] = miss
break
else:
continue
break
else:
raise Exception(f"Arch {arch.name}: {miss} has no name that matches vex")
# get ready to write back to archinfo source
arch_fname = "archinfo/%s.py" % arch.__class__.__module__.split(".")[-1]
orig_lines = iter(list(open(arch_fname, "rb")))
file_fp = open(arch_fname, "wb")
# copy initial lines
for line in orig_lines:
if " register_names = " in line:
break
file_fp.write(line)
# discard lines we want to replace
for line in orig_lines:
if " registers = " in line:
break
for line in orig_lines:
if "}" in line:
break
# dump out the new data
file_fp.write(" register_names = {\n")
for new_offset in sorted(list(new_register_names)):
file_fp.write(" %d: '%s',\n" % (new_offset, new_register_names[new_offset]))
file_fp.write(" }\n\n")
file_fp.write(" registers = {\n")
for new_offset, dlist in sorted(new_registers_reverse.items()):
for new_size, new_name in sorted(dlist):
file_fp.write(" '%s': (%d, %d),\n" % (new_name, new_offset, new_size))
file_fp.write(" }\n")
# dump out the rest of the file
for line in orig_lines:
file_fp.write(line)