blob: 3f4a8504927e53c3c5f05b1650fa6a5beab19dd9 [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 +020030import struct
31import re
32from collections import deque
33
34
35def round_up(n, m):
36 if n == 0:
37 return 0
38 else:
39 return (((n - 1) // m) + 1) * m
40
41
42def emit_load_segments(elffile, outf):
43 load_size = 0
Jerome Forissierd2fb6902019-07-04 18:34:47 +020044 data_size = 0
45 next_rwseg_va = 0
Jens Wiklanderb8c97752019-05-23 17:42:09 +020046 n = 0
47 for segment in elffile.iter_segments():
48 if segment['p_type'] == 'PT_LOAD':
49 if n == 0:
50 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X):
51 print('Expected first load segment to be read/execute')
52 sys.exit(1)
53 code_size = segment['p_filesz']
Jerome Forissierd2fb6902019-07-04 18:34:47 +020054 else:
Jens Wiklanderb8c97752019-05-23 17:42:09 +020055 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W):
Jerome Forissierd2fb6902019-07-04 18:34:47 +020056 print('Expected load segment to be read/write')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020057 sys.exit(1)
Jerome Forissierd2fb6902019-07-04 18:34:47 +020058 if next_rwseg_va and segment['p_vaddr'] != next_rwseg_va:
59 print('Expected contiguous read/write segments')
60 print(segment['p_vaddr'])
61 print(next_rwseg_va)
62 sys.exit(1)
63 data_size += segment['p_filesz']
64 next_rwseg_va = segment['p_vaddr'] + segment['p_filesz']
Jens Wiklanderb8c97752019-05-23 17:42:09 +020065 load_size += segment['p_filesz']
66 n = n + 1
67
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020068 outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096))
69 outf.write(b' __aligned(4096) = {\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020070 i = 0
71 for segment in elffile.iter_segments():
72 if segment['p_type'] == 'PT_LOAD':
73 data = segment.data()
74 for n in range(segment['p_filesz']):
75 if i % 8 == 0:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020076 outf.write(b'\t')
77 outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8')
78 + b',')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020079 i = i + 1
80 if i % 8 == 0 or i == load_size:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020081 outf.write(b'\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020082 else:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020083 outf.write(b' ')
84 outf.write(b'};\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020085
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020086 outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size)
87 outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size)
Jens Wiklanderb8c97752019-05-23 17:42:09 +020088
89
90def get_args():
91 parser = argparse.ArgumentParser()
92
93 parser.add_argument('--input',
94 required=True, type=argparse.FileType('rb'),
95 help='The input ldelf.elf')
96
97 parser.add_argument('--output',
98 required=True, type=argparse.FileType('wb'),
99 help='The output ldelf_hex.c')
100
101 return parser.parse_args()
102
103
104def main():
105 args = get_args()
106 inf = args.input
107 outf = args.output
108
109 elffile = ELFFile(inf)
110
Rouven Czerwinski84c0da02019-07-02 11:57:32 +0200111 outf.write(b'/* Automatically generated, do no edit */\n')
112 outf.write(b'#include <compiler.h>\n')
113 outf.write(b'#include <stdint.h>\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +0200114 emit_load_segments(elffile, outf)
Rouven Czerwinski84c0da02019-07-02 11:57:32 +0200115 outf.write(b'const unsigned long ldelf_entry = %lu;\n' %
Jens Wiklanderb8c97752019-05-23 17:42:09 +0200116 elffile.header['e_entry'])
117
118 inf.close()
119 outf.close()
120
121
122if __name__ == "__main__":
123 main()