forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen_symtab.py
157 lines (119 loc) · 4.84 KB
/
gen_symtab.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python3
#
# Copyright (c) 2024 Meta Platforms
#
# SPDX-License-Identifier: Apache-2.0
import argparse
import sys
import os
import re
from elftools.elf.elffile import ELFFile
from elftools.elf.descriptions import (
describe_symbol_type,
)
class gen_symtab_log:
def __init__(self, debug=False):
self.__debug = debug
def debug(self, text):
"""Print debug message if debugging is enabled.
Note - this function requires config global variable to be initialized.
"""
if self.__debug:
sys.stdout.write(os.path.basename(
sys.argv[0]) + ": " + text + "\n")
@staticmethod
def error(text):
sys.exit(os.path.basename(sys.argv[0]) + ": error: " + text + "\n")
def set_debug(self, state):
self.__debug = state
log = gen_symtab_log()
def parse_args():
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False)
parser.add_argument("-k", "--kernel", required=True,
help="Zephyr kernel image")
parser.add_argument("-o", "--output", required=True,
help="Output source file")
parser.add_argument("-d", "--debug", action="store_true",
help="Print additional debugging information")
return parser.parse_args()
class symtab_entry:
def __init__(self, addr, size, offset, name):
self.addr = addr
self.size = size
self.offset = offset
self.name = name
def __eq__(self, other):
return self.addr == other.addr
first_addr = 0
symtab_list = []
def sanitize_func_name(name):
pattern = r'(^[a-zA-Z_][a-zA-Z0-9_]*)'
match = re.match(pattern, name)
if match:
return match.group(0)
else:
log.error(f"Failed to sanitize function name: {name}")
return name
def main():
args = parse_args()
log.set_debug(args.debug)
with open(args.kernel, "rb") as rf:
elf = ELFFile(rf)
# Find the symbol table.
symtab = elf.get_section_by_name('.symtab')
i = 1
for nsym, symbol in enumerate(symtab.iter_symbols()): # pylint: disable=unused-variable
symbol_type = describe_symbol_type(symbol['st_info']['type'])
symbol_addr = symbol['st_value']
symbol_size = symbol['st_size']
if symbol_type == 'FUNC' and symbol_addr != 0:
symbol_name = sanitize_func_name(symbol.name)
dummy_offset = 0 # offsets will be calculated later after we know the first address
entry = symtab_entry(
symbol_addr, symbol_size, dummy_offset, symbol_name)
# Prevent entries with duplicated addresses
if entry not in symtab_list:
symtab_list.append(entry)
# Sort the address in ascending order
symtab_list.sort(key=lambda x: x.addr, reverse=False)
# Get the address of the first symbol
first_addr = symtab_list[0].addr
for i, entry in enumerate(symtab_list):
# Offset is calculated here
entry.offset = entry.addr - first_addr
# Debug print
log.debug('%6d: %s %s %.25s' % (
i,
hex(entry.addr),
hex(entry.size),
entry.name))
with open(args.output, 'w') as wf:
print("/* AUTO-GENERATED by gen_symtab.py, do not edit! */", file=wf)
print("", file=wf)
print("#include <zephyr/linker/sections.h>", file=wf)
print("#include <zephyr/debug/symtab.h>", file=wf)
print("", file=wf)
print(
f"const struct z_symtab_entry __symtab_entry z_symtab_entries[{len(symtab_list) + 1}] = {{", file=wf)
for i, entry in enumerate(symtab_list):
print(
f"\t/* ADDR: {hex(entry.addr)} SIZE: {hex(entry.size)} */", file=wf)
print(
f"\t[{i}] = {{.offset = {hex(entry.offset)}, .name = \"{entry.name}\"}},", file=wf)
# Append a dummy entry at the end to facilitate the binary search
if symtab_list[-1].size == 0:
dummy_offset = f"{hex(symtab_list[-1].offset)} + sizeof(uintptr_t)"
else:
dummy_offset = f"{hex(symtab_list[-1].offset + symtab_list[-1].size)}"
print("\t/* dummy entry */", file=wf)
print(
f"\t[{len(symtab_list)}] = {{.offset = {dummy_offset}, .name = \"?\"}},", file=wf)
print(f"}};\n", file=wf)
print(f"const struct symtab_info __symtab_info z_symtab = {{", file=wf)
print(f"\t.first_addr = {hex(first_addr)},", file=wf)
print(f"\t.length = {len(symtab_list)},", file=wf)
print(f"\t.entries = z_symtab_entries,", file=wf)
print(f"}};\n", file=wf)
if __name__ == "__main__":
main()