1818# file format suitable for flashing onto some embedded devices.
1919#
2020# Usage:
21- # $ elf2hex.py <input> <output> [--symbol-map <output>]
21+ # $ elf2hex.py <input> <output> [--symbol-map <output>] [--relocate-data-segment]
2222#
2323# Example:
2424# $ elf2hex.py ./blink ./blink.hex --symbol-map ./blink.symbols
2525#
26+ # The --relocate-data-segment option expects to be able to locate symbols with names
27+ # - __data_start
28+ # - __flash_data_start
29+ # - __flash_data_len
30+ # and then it physically relocates a segment located at __data_start to
31+ # __flash_data_start, without changing virtual/physical addresses of any ELF
32+ # headers. This means that the .hex file is not validly mapped until a boot-time
33+ # reverse relocation step.
34+ #
35+ # See the linker script used in a particular demo folder for a detailed
36+ # explanation of the linking, packing, and runtime relocation scheme.
37+ #
2638
2739import argparse
2840import json
@@ -36,18 +48,12 @@ def main():
3648 parser .add_argument ('input' )
3749 parser .add_argument ('output' )
3850 parser .add_argument ('--symbol-map' )
39- parser .add_argument ('--relocate' , action = 'append ' )
51+ parser .add_argument ('--relocate-data-segment ' , action = 'store_true ' )
4052 args = parser .parse_args ()
4153
4254 inf = open (args .input , "rb" )
4355 outf = open (args .output , "wb" )
4456
45- relocations = {}
46- if args .relocate is not None :
47- for r in args .relocate :
48- (a , b ) = r .split (":" )
49- relocations [int (a , 16 )] = int (b , 16 )
50-
5157 def emitrecord (record ):
5258 checksum = 0
5359 pos = 0
@@ -77,6 +83,30 @@ def emit(vmaddr, data):
7783 vmaddr += chunklen
7884
7985 elffile = elftools .elf .elffile .ELFFile (inf )
86+
87+ symbol_map = {}
88+ symtab_section = elffile .get_section_by_name (".symtab" )
89+ for s in symtab_section .iter_symbols ():
90+ if s .entry .st_info .type not in ["STT_FUNC" , "STT_NOTYPE" ]:
91+ continue
92+ if s .name == "" :
93+ continue
94+ symbol_map [s .name ] = s .entry .st_value
95+
96+ if args .symbol_map is not None :
97+ pathlib .Path (args .symbol_map ).write_text (json .dumps (symbol_map ))
98+
99+ relocations = {}
100+ if args .relocate_data_segment :
101+ __flash_data_start = symbol_map ["__flash_data_start" ]
102+ __data_start = symbol_map ["__data_start" ]
103+ __flash_data_len = symbol_map ["__flash_data_len" ]
104+ print ("Relocation info:" )
105+ print (f" __flash_data_start = 0x{ __flash_data_start :08x} " )
106+ print (f" __data_start = 0x{ __data_start :08x} " )
107+ print (f" __flash_data_len = 0x{ __flash_data_len :08x} " )
108+ relocations = {__data_start : __flash_data_start }
109+
80110 for segment in elffile .iter_segments ():
81111 if segment .header .p_type != "PT_LOAD" :
82112 continue
@@ -101,20 +131,6 @@ def emit(vmaddr, data):
101131 recordtype = "01" # EOF
102132 emitrecord (f"{ chunklen :02X} { vmaddr :04X} { recordtype } " )
103133
104- symbol_map = {}
105- symtab_section = elffile .get_section_by_name (".symtab" )
106- for s in symtab_section .iter_symbols ():
107- if s .entry .st_info .type not in ["STT_FUNC" , "STT_NOTYPE" ]:
108- continue
109- if s .entry .st_shndx == "SHN_ABS" :
110- continue
111- if s .name == "" :
112- continue
113- symbol_map [s .name ] = s .entry .st_value
114-
115- if args .symbol_map is not None :
116- pathlib .Path (args .symbol_map ).write_text (json .dumps (symbol_map ))
117-
118134 inf .close ()
119135 outf .close ()
120136
0 commit comments