blob: dfc9e06735617c4c791d6cae5120a03d3af2e33f [file] [log] [blame]
Rouven Czerwinski84c0da02019-07-02 11:57:32 +02001#!/usr/bin/env python3
Jens Wiklanderb8c97752019-05-23 17:42:09 +02002# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2019, Linaro Limited
5#
6
7from __future__ import print_function
8from __future__ import division
9
10import argparse
11import sys
Volodymyr Babchuk7ba36df2019-08-01 21:48:30 +030012try:
13 from elftools.elf.elffile import ELFFile
14 from elftools.elf.sections import SymbolTableSection
15 from elftools.elf.constants import P_FLAGS
16except ImportError:
17 print("""
18***
19Can't find elftools module. Probably it is not installed on your system.
20You can install this module with
21
22$ apt install python3-pyelftools
23
24if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in
25your package manager if you are using some other distribution.
26***
27""")
28 raise
29
Jens Wiklanderb8c97752019-05-23 17:42:09 +020030
31def round_up(n, m):
32 if n == 0:
33 return 0
34 else:
35 return (((n - 1) // m) + 1) * m
36
37
38def emit_load_segments(elffile, outf):
39 load_size = 0
Jerome Forissierd2fb6902019-07-04 18:34:47 +020040 data_size = 0
41 next_rwseg_va = 0
Jens Wiklanderb8c97752019-05-23 17:42:09 +020042 n = 0
43 for segment in elffile.iter_segments():
44 if segment['p_type'] == 'PT_LOAD':
45 if n == 0:
46 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X):
47 print('Expected first load segment to be read/execute')
48 sys.exit(1)
49 code_size = segment['p_filesz']
Jerome Forissierd2fb6902019-07-04 18:34:47 +020050 else:
Jens Wiklanderb8c97752019-05-23 17:42:09 +020051 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W):
Jerome Forissierd2fb6902019-07-04 18:34:47 +020052 print('Expected load segment to be read/write')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020053 sys.exit(1)
Jerome Forissierd2fb6902019-07-04 18:34:47 +020054 if next_rwseg_va and segment['p_vaddr'] != next_rwseg_va:
55 print('Expected contiguous read/write segments')
56 print(segment['p_vaddr'])
57 print(next_rwseg_va)
58 sys.exit(1)
59 data_size += segment['p_filesz']
60 next_rwseg_va = segment['p_vaddr'] + segment['p_filesz']
Jens Wiklanderb8c97752019-05-23 17:42:09 +020061 load_size += segment['p_filesz']
62 n = n + 1
63
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020064 outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096))
65 outf.write(b' __aligned(4096) = {\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020066 i = 0
67 for segment in elffile.iter_segments():
68 if segment['p_type'] == 'PT_LOAD':
69 data = segment.data()
70 for n in range(segment['p_filesz']):
71 if i % 8 == 0:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020072 outf.write(b'\t')
73 outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8')
74 + b',')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020075 i = i + 1
76 if i % 8 == 0 or i == load_size:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020077 outf.write(b'\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020078 else:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020079 outf.write(b' ')
80 outf.write(b'};\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020081
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020082 outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size)
83 outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size)
Jens Wiklanderb8c97752019-05-23 17:42:09 +020084
85
86def get_args():
87 parser = argparse.ArgumentParser()
88
89 parser.add_argument('--input',
90 required=True, type=argparse.FileType('rb'),
91 help='The input ldelf.elf')
92
93 parser.add_argument('--output',
94 required=True, type=argparse.FileType('wb'),
95 help='The output ldelf_hex.c')
96
97 return parser.parse_args()
98
99
100def main():
101 args = get_args()
102 inf = args.input
103 outf = args.output
104
105 elffile = ELFFile(inf)
106
Rouven Czerwinski84c0da02019-07-02 11:57:32 +0200107 outf.write(b'/* Automatically generated, do no edit */\n')
108 outf.write(b'#include <compiler.h>\n')
109 outf.write(b'#include <stdint.h>\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +0200110 emit_load_segments(elffile, outf)
Rouven Czerwinski84c0da02019-07-02 11:57:32 +0200111 outf.write(b'const unsigned long ldelf_entry = %lu;\n' %
Jens Wiklanderb8c97752019-05-23 17:42:09 +0200112 elffile.header['e_entry'])
113
114 inf.close()
115 outf.close()
116
117
118if __name__ == "__main__":
119 main()