184c0da04SRouven Czerwinski#!/usr/bin/env python3 2b8c97753SJens Wiklander# SPDX-License-Identifier: BSD-2-Clause 3b8c97753SJens Wiklander# 4b8c97753SJens Wiklander# Copyright (c) 2019, Linaro Limited 5b8c97753SJens Wiklander# 6b8c97753SJens Wiklander 7b8c97753SJens Wiklanderfrom __future__ import print_function 8b8c97753SJens Wiklanderfrom __future__ import division 9b8c97753SJens Wiklander 10b8c97753SJens Wiklanderimport argparse 11b8c97753SJens Wiklanderimport sys 12b8c97753SJens Wiklanderfrom elftools.elf.elffile import ELFFile 13b8c97753SJens Wiklanderfrom elftools.elf.sections import SymbolTableSection 14b8c97753SJens Wiklanderfrom elftools.elf.constants import P_FLAGS 15b8c97753SJens Wiklanderimport struct 16b8c97753SJens Wiklanderimport re 17b8c97753SJens Wiklanderfrom collections import deque 18b8c97753SJens Wiklander 19b8c97753SJens Wiklander 20b8c97753SJens Wiklanderdef round_up(n, m): 21b8c97753SJens Wiklander if n == 0: 22b8c97753SJens Wiklander return 0 23b8c97753SJens Wiklander else: 24b8c97753SJens Wiklander return (((n - 1) // m) + 1) * m 25b8c97753SJens Wiklander 26b8c97753SJens Wiklander 27b8c97753SJens Wiklanderdef emit_load_segments(elffile, outf): 28b8c97753SJens Wiklander load_size = 0 29*d2fb6900SJerome Forissier data_size = 0 30*d2fb6900SJerome Forissier next_rwseg_va = 0 31b8c97753SJens Wiklander n = 0 32b8c97753SJens Wiklander for segment in elffile.iter_segments(): 33b8c97753SJens Wiklander if segment['p_type'] == 'PT_LOAD': 34b8c97753SJens Wiklander if n == 0: 35b8c97753SJens Wiklander if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X): 36b8c97753SJens Wiklander print('Expected first load segment to be read/execute') 37b8c97753SJens Wiklander sys.exit(1) 38b8c97753SJens Wiklander code_size = segment['p_filesz'] 39*d2fb6900SJerome Forissier else: 40b8c97753SJens Wiklander if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W): 41*d2fb6900SJerome Forissier print('Expected load segment to be read/write') 42b8c97753SJens Wiklander sys.exit(1) 43*d2fb6900SJerome Forissier if next_rwseg_va and segment['p_vaddr'] != next_rwseg_va: 44*d2fb6900SJerome Forissier print('Expected contiguous read/write segments') 45*d2fb6900SJerome Forissier print(segment['p_vaddr']) 46*d2fb6900SJerome Forissier print(next_rwseg_va) 47b8c97753SJens Wiklander sys.exit(1) 48*d2fb6900SJerome Forissier data_size += segment['p_filesz'] 49*d2fb6900SJerome Forissier next_rwseg_va = segment['p_vaddr'] + segment['p_filesz'] 50b8c97753SJens Wiklander load_size += segment['p_filesz'] 51b8c97753SJens Wiklander n = n + 1 52b8c97753SJens Wiklander 5384c0da04SRouven Czerwinski outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096)) 5484c0da04SRouven Czerwinski outf.write(b' __aligned(4096) = {\n') 55b8c97753SJens Wiklander i = 0 56b8c97753SJens Wiklander for segment in elffile.iter_segments(): 57b8c97753SJens Wiklander if segment['p_type'] == 'PT_LOAD': 58b8c97753SJens Wiklander data = segment.data() 59b8c97753SJens Wiklander for n in range(segment['p_filesz']): 60b8c97753SJens Wiklander if i % 8 == 0: 6184c0da04SRouven Czerwinski outf.write(b'\t') 6284c0da04SRouven Czerwinski outf.write(b'0x' + '{:02x}'.format(data[n]).encode('utf-8') 6384c0da04SRouven Czerwinski + b',') 64b8c97753SJens Wiklander i = i + 1 65b8c97753SJens Wiklander if i % 8 == 0 or i == load_size: 6684c0da04SRouven Czerwinski outf.write(b'\n') 67b8c97753SJens Wiklander else: 6884c0da04SRouven Czerwinski outf.write(b' ') 6984c0da04SRouven Czerwinski outf.write(b'};\n') 70b8c97753SJens Wiklander 7184c0da04SRouven Czerwinski outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size) 7284c0da04SRouven Czerwinski outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size) 73b8c97753SJens Wiklander 74b8c97753SJens Wiklander 75b8c97753SJens Wiklanderdef get_args(): 76b8c97753SJens Wiklander parser = argparse.ArgumentParser() 77b8c97753SJens Wiklander 78b8c97753SJens Wiklander parser.add_argument('--input', 79b8c97753SJens Wiklander required=True, type=argparse.FileType('rb'), 80b8c97753SJens Wiklander help='The input ldelf.elf') 81b8c97753SJens Wiklander 82b8c97753SJens Wiklander parser.add_argument('--output', 83b8c97753SJens Wiklander required=True, type=argparse.FileType('wb'), 84b8c97753SJens Wiklander help='The output ldelf_hex.c') 85b8c97753SJens Wiklander 86b8c97753SJens Wiklander return parser.parse_args() 87b8c97753SJens Wiklander 88b8c97753SJens Wiklander 89b8c97753SJens Wiklanderdef main(): 90b8c97753SJens Wiklander args = get_args() 91b8c97753SJens Wiklander inf = args.input 92b8c97753SJens Wiklander outf = args.output 93b8c97753SJens Wiklander 94b8c97753SJens Wiklander elffile = ELFFile(inf) 95b8c97753SJens Wiklander 9684c0da04SRouven Czerwinski outf.write(b'/* Automatically generated, do no edit */\n') 9784c0da04SRouven Czerwinski outf.write(b'#include <compiler.h>\n') 9884c0da04SRouven Czerwinski outf.write(b'#include <stdint.h>\n') 99b8c97753SJens Wiklander emit_load_segments(elffile, outf) 10084c0da04SRouven Czerwinski outf.write(b'const unsigned long ldelf_entry = %lu;\n' % 101b8c97753SJens Wiklander elffile.header['e_entry']) 102b8c97753SJens Wiklander 103b8c97753SJens Wiklander inf.close() 104b8c97753SJens Wiklander outf.close() 105b8c97753SJens Wiklander 106b8c97753SJens Wiklander 107b8c97753SJens Wiklanderif __name__ == "__main__": 108b8c97753SJens Wiklander main() 109