forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gen_kobject_placeholders.py
executable file
·139 lines (108 loc) · 4.2 KB
/
gen_kobject_placeholders.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
#!/usr/bin/env python3
#
# Copyright (c) 2021 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
"""
Process ELF file to generate placeholders for kobject
hash table and lookup functions produced by gperf,
since their sizes depend on how many kobjects have
been declared. The output header files will be used
during linking for intermediate output binaries so
that the addresses of these kobjects would remain
the same during later stages of linking.
"""
import sys
import argparse
import os
from distutils.version import LooseVersion
import elftools
from elftools.elf.elffile import ELFFile
if LooseVersion(elftools.__version__) < LooseVersion('0.24'):
sys.exit("pyelftools is out of date, need version 0.24 or later")
def write_define(out_fp, prefix, name, value):
"""Write the #define to output file"""
define_name = f"KOBJECT_{prefix}_{name}"
out_fp.write(f"#ifndef {define_name}\n")
out_fp.write(f"#define {define_name} {value}\n")
out_fp.write("#endif\n\n")
def output_simple_header(one_sect):
"""Write the header for kobject section"""
out_fn = os.path.join(args.outdir,
f"linker-kobject-prebuilt-{one_sect['name']}.h")
out_fp = open(out_fn, "w")
if one_sect['exists']:
align = one_sect['align']
size = one_sect['size']
prefix = one_sect['define_prefix']
write_define(out_fp, prefix, 'ALIGN', align)
write_define(out_fp, prefix, 'SZ', size)
out_fp.close()
def generate_linker_headers(obj):
"""Generate linker header files to be included by the linker script"""
# Sections we are interested in
sections = {
".data": {
"name": "data",
"define_prefix": "DATA",
"exists": False,
"multiplier": int(args.datapct) + 100,
},
".rodata": {
"name": "rodata",
"define_prefix": "RODATA",
"exists": False,
"extra_bytes": args.rodata,
},
".priv_stacks.noinit": {
"name": "priv-stacks",
"define_prefix": "PRIV_STACKS",
"exists": False,
},
}
for one_sect in obj.iter_sections():
# REALLY NEED to match exact type as all other sections
# (symbol, debug, etc.) are descendants where
# isinstance() would match.
if type(one_sect) is not elftools.elf.sections.Section: # pylint: disable=unidiomatic-typecheck
continue
name = one_sect.name
if name in sections.keys():
# Need section alignment and size
sections[name]['align'] = one_sect['sh_addralign']
sections[name]['size'] = one_sect['sh_size']
sections[name]['exists'] = True
if "multiplier" in sections[name]:
sections[name]['size'] *= sections[name]['multiplier'] / 100
sections[name]['size'] = int(sections[name]['size'])
if "extra_bytes" in sections[name]:
sections[name]['size'] += int(sections[name]['extra_bytes'])
for one_sect in sections:
output_simple_header(sections[one_sect])
def parse_args():
"""Parse command line arguments"""
global args
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--object", required=True,
help="Points to kobject_prebuilt_hash.c.obj")
parser.add_argument("--outdir", required=True,
help="Output directory (<build_dir>/include/generated)")
parser.add_argument("--datapct", required=True,
help="Multipler to the size of reserved space for DATA region")
parser.add_argument("--rodata", required=True,
help="Extra bytes to reserve for RODATA region")
parser.add_argument("-v", "--verbose", action="store_true",
help="Verbose messages")
args = parser.parse_args()
if "VERBOSE" in os.environ:
args.verbose = 1
def main():
"""Main program"""
parse_args()
with open(args.object, "rb") as obj_fp:
obj = ELFFile(obj_fp)
generate_linker_headers(obj)
if __name__ == "__main__":
main()