1#!/usr/bin/env python 2# 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 29 n = 0 30 for segment in elffile.iter_segments(): 31 if segment['p_type'] == 'PT_LOAD': 32 if n == 0: 33 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_X): 34 print('Expected first load segment to be read/execute') 35 sys.exit(1) 36 code_size = segment['p_filesz'] 37 if n == 1: 38 if segment['p_flags'] != (P_FLAGS.PF_R | P_FLAGS.PF_W): 39 print('Expected second load segment to be read/write') 40 sys.exit(1) 41 data_size = segment['p_filesz'] 42 if n > 1: 43 print('Only expected two load segments') 44 sys.exit(1) 45 load_size += segment['p_filesz'] 46 n = n + 1 47 48 outf.write('const uint8_t ldelf_data[%d]' % round_up(load_size, 4096)) 49 outf.write(' __aligned(4096) = {\n') 50 i = 0 51 for segment in elffile.iter_segments(): 52 if segment['p_type'] == 'PT_LOAD': 53 data = segment.data() 54 for n in range(segment['p_filesz']): 55 if i % 8 == 0: 56 outf.write('\t') 57 outf.write('0x' + '{:02x}'.format(ord(data[n])) + ',') 58 i = i + 1 59 if i % 8 == 0 or i == load_size: 60 outf.write('\n') 61 else: 62 outf.write(' ') 63 outf.write('};\n') 64 65 outf.write('const unsigned int ldelf_code_size = %d;\n' % code_size) 66 outf.write('const unsigned int ldelf_data_size = %d;\n' % data_size) 67 68 69def get_args(): 70 parser = argparse.ArgumentParser() 71 72 parser.add_argument('--input', 73 required=True, type=argparse.FileType('rb'), 74 help='The input ldelf.elf') 75 76 parser.add_argument('--output', 77 required=True, type=argparse.FileType('wb'), 78 help='The output ldelf_hex.c') 79 80 return parser.parse_args() 81 82 83def main(): 84 args = get_args() 85 inf = args.input 86 outf = args.output 87 88 elffile = ELFFile(inf) 89 90 outf.write('/* Automatically generated, do no edit */\n') 91 outf.write('#include <compiler.h>\n') 92 outf.write('#include <stdint.h>\n') 93 emit_load_segments(elffile, outf) 94 outf.write('const unsigned long ldelf_entry = %lu;\n' % 95 elffile.header['e_entry']) 96 97 inf.close() 98 outf.close() 99 100 101if __name__ == "__main__": 102 main() 103