blob: 2a8c22aa89317f9d8aaa2f04e5f35d4a207a5a1a [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
12from elftools.elf.elffile import ELFFile
13from elftools.elf.sections import SymbolTableSection
14from elftools.elf.constants import P_FLAGS
15import struct
16import re
17from collections import deque
18
19
20def round_up(n, m):
21 if n == 0:
22 return 0
23 else:
24 return (((n - 1) // m) + 1) * m
25
26
27def emit_load_segments(elffile, outf):
28 load_size = 0
Jerome Forissierd2fb6902019-07-04 18:34:47 +020029 data_size = 0
30 next_rwseg_va = 0
Jens Wiklanderb8c97752019-05-23 17:42:09 +020031 n = 0
32 for segment in elffile.iter_segments():
33 if segment['p_type'] == 'PT_LOAD':
34 if n == 0:
35 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X):
36 print('Expected first load segment to be read/execute')
37 sys.exit(1)
38 code_size = segment['p_filesz']
Jerome Forissierd2fb6902019-07-04 18:34:47 +020039 else:
Jens Wiklanderb8c97752019-05-23 17:42:09 +020040 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W):
Jerome Forissierd2fb6902019-07-04 18:34:47 +020041 print('Expected load segment to be read/write')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020042 sys.exit(1)
Jerome Forissierd2fb6902019-07-04 18:34:47 +020043 if next_rwseg_va and segment['p_vaddr'] != next_rwseg_va:
44 print('Expected contiguous read/write segments')
45 print(segment['p_vaddr'])
46 print(next_rwseg_va)
47 sys.exit(1)
48 data_size += segment['p_filesz']
49 next_rwseg_va = segment['p_vaddr'] + segment['p_filesz']
Jens Wiklanderb8c97752019-05-23 17:42:09 +020050 load_size += segment['p_filesz']
51 n = n + 1
52
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020053 outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096))
54 outf.write(b' __aligned(4096) = {\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020055 i = 0
56 for segment in elffile.iter_segments():
57 if segment['p_type'] == 'PT_LOAD':
58 data = segment.data()
59 for n in range(segment['p_filesz']):
60 if i % 8 == 0:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020061 outf.write(b'\t')
62 outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8')
63 + b',')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020064 i = i + 1
65 if i % 8 == 0 or i == load_size:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020066 outf.write(b'\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020067 else:
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020068 outf.write(b' ')
69 outf.write(b'};\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020070
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020071 outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size)
72 outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size)
Jens Wiklanderb8c97752019-05-23 17:42:09 +020073
74
75def get_args():
76 parser = argparse.ArgumentParser()
77
78 parser.add_argument('--input',
79 required=True, type=argparse.FileType('rb'),
80 help='The input ldelf.elf')
81
82 parser.add_argument('--output',
83 required=True, type=argparse.FileType('wb'),
84 help='The output ldelf_hex.c')
85
86 return parser.parse_args()
87
88
89def main():
90 args = get_args()
91 inf = args.input
92 outf = args.output
93
94 elffile = ELFFile(inf)
95
Rouven Czerwinski84c0da02019-07-02 11:57:32 +020096 outf.write(b'/* Automatically generated, do no edit */\n')
97 outf.write(b'#include <compiler.h>\n')
98 outf.write(b'#include <stdint.h>\n')
Jens Wiklanderb8c97752019-05-23 17:42:09 +020099 emit_load_segments(elffile, outf)
Rouven Czerwinski84c0da02019-07-02 11:57:32 +0200100 outf.write(b'const unsigned long ldelf_entry = %lu;\n' %
Jens Wiklanderb8c97752019-05-23 17:42:09 +0200101 elffile.header['e_entry'])
102
103 inf.close()
104 outf.close()
105
106
107if __name__ == "__main__":
108 main()