-
Notifications
You must be signed in to change notification settings - Fork 11
/
objdump.py
141 lines (120 loc) · 3.82 KB
/
objdump.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
134
135
136
137
138
139
140
#
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
#
# SPDX-License-Identifier: BSD-2-Clause
#
# parsing code for objdump files. used on a symtab dump to build a python
# symbol table and on a disassembly of the .rodata section to build a
# summary of the read-only data
import re
def build_syms (symtab):
syms = {}
for line in symtab:
bits = line.split ()
try:
addr = int (bits[0], 16)
size = int (bits[-2], 16)
section = bits[-3]
syms[bits[-1]] = (addr, size, section)
except ValueError:
pass
except IndexError:
pass
sections = {}
for (addr, size, section) in syms.itervalues ():
if not size:
continue
(start, end) = sections.get (section, (addr, addr))
start = min (addr, start)
end = max (addr + size - 1, end)
sections[section] = (start, end)
return (syms, sections)
def install_syms (symtab):
(syms, sects) = build_syms (symtab)
import target_objects
target_objects.symbols.update (syms)
target_objects.sections.update (sects)
is_rodata_line = re.compile('^\s*[0-9a-fA-F]+:\s+[0-9a-fA-F]+\s+')
def build_rodata (rodata_stream, rodata_ranges = [('Section', '.rodata')]):
from syntax import structs, fresh_name, Struct, mk_word32
import syntax
from target_objects import symbols, sections, trace
act_rodata_ranges = []
for (kind, nm) in rodata_ranges:
if kind == 'Symbol':
(addr, size, _) = symbols[nm]
act_rodata_ranges.append ((addr, addr + size - 1))
elif kind == 'Section':
if nm in sections:
act_rodata_ranges.append (sections[nm])
else:
# it's reasonable to supply .rodata as the
# expected section only for it to be missing
trace ('No %r section in objdump.' % nm)
else:
assert kind in ['Symbol', 'Section'], rodata_ranges
comb_ranges = []
for (start, end) in sorted (act_rodata_ranges):
if comb_ranges and comb_ranges[-1][1] + 1 == start:
(start, _) = comb_ranges[-1]
comb_ranges[-1] = (start, end)
else:
comb_ranges.append ((start, end))
rodata = {}
for line in rodata_stream:
if not is_rodata_line.match (line):
continue
bits = line.split ()
(addr, v) = (int (bits[0][:-1], 16), int (bits[1], 16))
if [1 for (start, end) in comb_ranges
if start <= addr and addr <= end]:
assert addr % 4 == 0, addr
rodata[addr] = v
if len (comb_ranges) == 1:
rodata_names = ['rodata_struct']
else:
rodata_names = ['rodata_struct_%d' % (i + 1)
for (i, _) in enumerate (comb_ranges)]
rodata_ptrs = []
for ((start, end), name) in zip (comb_ranges, rodata_names):
struct_name = fresh_name (name, structs)
struct = Struct (struct_name, (end - start) + 1, 1)
structs[struct_name] = struct
typ = syntax.get_global_wrapper (struct.typ)
rodata_ptrs.append ((mk_word32 (start), typ))
return (rodata, comb_ranges, rodata_ptrs)
def install_rodata (rodata_stream, rodata_ranges = [('Section', '.rodata')]):
import target_objects
rodata = build_rodata (rodata_stream, rodata_ranges)
target_objects.rodata[:] = rodata
# the prunes file isn't really an objdump file, but this seems the best place
non_var_re = re.compile('[(),\s\[\]]+')
def parse_prunes (prune_stream):
prunes = {}
for l in prune_stream:
[lname, rhs] = l.split ('from [')
bits = lname.split ()
assert bits[:3] == ['Pruned', 'inputs', 'of']
name = bits[3]
[lvars, rvars] = rhs.split ('] to [')
lvars = [v for v in non_var_re.split (lvars) if v]
rvars = [v for v in non_var_re.split (rvars) if v]
if not (lvars[-2:] == ['dm', 'm']
and rvars[-2:] == ['dm', 'm']):
continue
lvars = lvars[:-2]
rvars = rvars[:-2]
prunes['DecompiledFuns.' + name + '_step'] = (lvars, rvars)
return prunes
# likewise the signatures produced by the c-parser
def parse_sigs (sig_stream):
sigs = {}
for l in sig_stream:
bits = l.split ()
if not bits:
continue
ret = int (bits[0])
nm = bits[1]
args = [int(bit) for bit in bits[2:]]
sigs[nm] = (args, ret)
return sigs