@@ -140,10 +140,12 @@ class ImageSegment(object):
140140 """Wrapper class for a segment in an ESP image
141141 (very similar to a section in an ELFImage also)"""
142142
143- def __init__ (self , addr , data , file_offs = None ):
143+ def __init__ (self , addr , data , file_offs = None , flags = 0 , align = 4 ):
144144 self .addr = addr
145145 self .data = data
146146 self .file_offs = file_offs
147+ self .flags = flags
148+ self .align = align
147149 self .include_in_checksum = True
148150 if self .addr != 0 :
149151 self .pad_to_alignment (
@@ -187,13 +189,33 @@ def get_memory_type(self, image):
187189 def pad_to_alignment (self , alignment ):
188190 self .data = pad_to (self .data , alignment , b"\x00 " )
189191
192+ def end_addr_if_aligned (self , alignment ):
193+ """
194+ Return the segment end address as it would be if
195+ aligned as requested by the argument.
196+ """
197+ end_addr = self .addr + len (self .data )
198+ addr_mod = end_addr % alignment
199+ if addr_mod != 0 :
200+ end_addr += alignment - addr_mod
201+ return end_addr
202+
203+ def pad_until_addr (self , addr ):
204+ """
205+ Pad the segment with `0x00` starting with segment address
206+ until the address given by the argument.
207+ """
208+ pad = addr - (self .addr + len (self .data ))
209+ if pad > 0 :
210+ self .data += b"\x00 " * pad
211+
190212
191213class ELFSection (ImageSegment ):
192214 """Wrapper class for a section in an ELF image, has a section
193215 name as well as the common properties of an ImageSegment."""
194216
195- def __init__ (self , name , addr , data ):
196- super (ELFSection , self ).__init__ (addr , data )
217+ def __init__ (self , name , addr , data , flags , align = 4 ):
218+ super (ELFSection , self ).__init__ (addr , data , flags = flags , align = align )
197219 self .name = name .decode ("utf-8" )
198220
199221 def __repr__ (self ):
@@ -409,6 +431,26 @@ def merge_adjacent_segments(self):
409431 # merged in
410432 elem = self .segments [i - 1 ]
411433 next_elem = self .segments [i ]
434+
435+ # When creating the images from 3rd-party frameworks ELFs, the merging
436+ # could bring together segments with incompatible alignment requirements.
437+ # At this point, we add padding so the resulting placement respects the
438+ # original alignment requirements of those segments.
439+ if self .ROM_LOADER != ESP8266ROM and self .ram_only_header :
440+ elem_pad_addr = elem .end_addr_if_aligned (next_elem .align )
441+
442+ if (
443+ elem_pad_addr != elem .addr + len (elem .data )
444+ and elem_pad_addr == next_elem .addr
445+ ):
446+ log .info (
447+ "Inserting {} bytes padding between {} and {}" .format (
448+ next_elem .addr - (elem .addr + len (elem .data )),
449+ elem .name ,
450+ next_elem .name ,
451+ )
452+ )
453+ elem .pad_until_addr (elem_pad_addr )
412454 if all (
413455 (
414456 elem .get_memory_type (self ) == next_elem .get_memory_type (self ),
@@ -832,10 +874,7 @@ def get_alignment_data_needed(segment):
832874 # Some chips have a non-zero load offset (eg. 0x1000)
833875 # therefore we shift the ROM segments "-load_offset"
834876 # so it will be aligned properly after it is flashed
835- align_min = (
836- self .ROM_LOADER .BOOTLOADER_FLASH_OFFSET - self .SEG_HEADER_LEN
837- )
838- if pad_len < align_min :
877+ if pad_len < self .ROM_LOADER .BOOTLOADER_FLASH_OFFSET :
839878 # in case pad_len does not fit minimum alignment,
840879 # pad it to next aligned boundary
841880 pad_len += self .IROM_ALIGN
@@ -1326,10 +1365,18 @@ def _read_sections(self, f, section_header_offs, section_header_count, shstrndx)
13261365 section_header_offsets = range (0 , len (section_header ), self .LEN_SEC_HEADER )
13271366
13281367 def read_section_header (offs ):
1329- name_offs , sec_type , _flags , lma , sec_offs , size = struct .unpack_from (
1330- "<LLLLLL" , section_header [offs :]
1331- )
1332- return (name_offs , sec_type , lma , size , sec_offs )
1368+ (
1369+ name_offs ,
1370+ sec_type ,
1371+ _flags ,
1372+ lma ,
1373+ sec_offs ,
1374+ size ,
1375+ _ ,
1376+ _ ,
1377+ align ,
1378+ ) = struct .unpack_from ("<LLLLLLLLL" , section_header [offs :])
1379+ return (name_offs , sec_type , lma , size , sec_offs , _flags , align )
13331380
13341381 all_sections = [read_section_header (offs ) for offs in section_header_offsets ]
13351382 prog_sections = [s for s in all_sections if s [1 ] in ELFFile .PROG_SEC_TYPES ]
@@ -1338,7 +1385,7 @@ def read_section_header(offs):
13381385 # search for the string table section
13391386 if (shstrndx * self .LEN_SEC_HEADER ) not in section_header_offsets :
13401387 raise FatalError (f"ELF file has no STRTAB section at shstrndx { shstrndx } " )
1341- _ , sec_type , _ , sec_size , sec_offs = read_section_header (
1388+ _ , sec_type , _ , sec_size , sec_offs , _flags , align = read_section_header (
13421389 shstrndx * self .LEN_SEC_HEADER
13431390 )
13441391 if sec_type != ELFFile .SEC_TYPE_STRTAB :
@@ -1358,14 +1405,20 @@ def read_data(offs, size):
13581405 return f .read (size )
13591406
13601407 prog_sections = [
1361- ELFSection (lookup_string (n_offs ), lma , read_data (offs , size ))
1362- for (n_offs , _type , lma , size , offs ) in prog_sections
1408+ ELFSection (
1409+ lookup_string (n_offs ),
1410+ lma ,
1411+ read_data (offs , size ),
1412+ flags = _flags ,
1413+ align = align ,
1414+ )
1415+ for (n_offs , _type , lma , size , offs , _flags , align ) in prog_sections
13631416 if lma != 0 and size > 0
13641417 ]
13651418 self .sections = prog_sections
13661419 self .nobits_sections = [
1367- ELFSection (lookup_string (n_offs ), lma , b"" )
1368- for (n_offs , _type , lma , size , offs ) in nobits_secitons
1420+ ELFSection (lookup_string (n_offs ), lma , b"" , flags = _flags , align = align )
1421+ for (n_offs , _type , lma , size , offs , _flags , align ) in nobits_secitons
13691422 if lma != 0 and size > 0
13701423 ]
13711424
@@ -1398,7 +1451,7 @@ def read_segment_header(offs):
13981451 _flags ,
13991452 _align ,
14001453 ) = struct .unpack_from ("<LLLLLLLL" , segment_header [offs :])
1401- return (seg_type , lma , size , seg_offs )
1454+ return (seg_type , lma , size , seg_offs , _flags , _align )
14021455
14031456 all_segments = [read_segment_header (offs ) for offs in segment_header_offsets ]
14041457 prog_segments = [s for s in all_segments if s [0 ] == ELFFile .SEG_TYPE_LOAD ]
@@ -1408,8 +1461,8 @@ def read_data(offs, size):
14081461 return f .read (size )
14091462
14101463 prog_segments = [
1411- ELFSection (b"PHDR" , lma , read_data (offs , size ))
1412- for (_type , lma , size , offs ) in prog_segments
1464+ ELFSection (b"PHDR" , lma , read_data (offs , size ), flags = _flags , align = _align )
1465+ for (_type , lma , size , offs , _flags , _align ) in prog_segments
14131466 if lma != 0 and size > 0
14141467 ]
14151468 self .segments = prog_segments
0 commit comments