@@ -140,10 +140,12 @@ class ImageSegment(object):
140
140
"""Wrapper class for a segment in an ESP image
141
141
(very similar to a section in an ELFImage also)"""
142
142
143
- def __init__ (self , addr , data , file_offs = None ):
143
+ def __init__ (self , addr , data , file_offs = None , flags = 0 , align = 4 ):
144
144
self .addr = addr
145
145
self .data = data
146
146
self .file_offs = file_offs
147
+ self .flags = flags
148
+ self .align = align
147
149
self .include_in_checksum = True
148
150
if self .addr != 0 :
149
151
self .pad_to_alignment (
@@ -187,13 +189,33 @@ def get_memory_type(self, image):
187
189
def pad_to_alignment (self , alignment ):
188
190
self .data = pad_to (self .data , alignment , b"\x00 " )
189
191
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
+
190
212
191
213
class ELFSection (ImageSegment ):
192
214
"""Wrapper class for a section in an ELF image, has a section
193
215
name as well as the common properties of an ImageSegment."""
194
216
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 )
197
219
self .name = name .decode ("utf-8" )
198
220
199
221
def __repr__ (self ):
@@ -409,6 +431,26 @@ def merge_adjacent_segments(self):
409
431
# merged in
410
432
elem = self .segments [i - 1 ]
411
433
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 )
412
454
if all (
413
455
(
414
456
elem .get_memory_type (self ) == next_elem .get_memory_type (self ),
@@ -832,10 +874,7 @@ def get_alignment_data_needed(segment):
832
874
# Some chips have a non-zero load offset (eg. 0x1000)
833
875
# therefore we shift the ROM segments "-load_offset"
834
876
# 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 :
839
878
# in case pad_len does not fit minimum alignment,
840
879
# pad it to next aligned boundary
841
880
pad_len += self .IROM_ALIGN
@@ -1326,10 +1365,18 @@ def _read_sections(self, f, section_header_offs, section_header_count, shstrndx)
1326
1365
section_header_offsets = range (0 , len (section_header ), self .LEN_SEC_HEADER )
1327
1366
1328
1367
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 )
1333
1380
1334
1381
all_sections = [read_section_header (offs ) for offs in section_header_offsets ]
1335
1382
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):
1338
1385
# search for the string table section
1339
1386
if (shstrndx * self .LEN_SEC_HEADER ) not in section_header_offsets :
1340
1387
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 (
1342
1389
shstrndx * self .LEN_SEC_HEADER
1343
1390
)
1344
1391
if sec_type != ELFFile .SEC_TYPE_STRTAB :
@@ -1358,14 +1405,20 @@ def read_data(offs, size):
1358
1405
return f .read (size )
1359
1406
1360
1407
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
1363
1416
if lma != 0 and size > 0
1364
1417
]
1365
1418
self .sections = prog_sections
1366
1419
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
1369
1422
if lma != 0 and size > 0
1370
1423
]
1371
1424
@@ -1398,7 +1451,7 @@ def read_segment_header(offs):
1398
1451
_flags ,
1399
1452
_align ,
1400
1453
) = 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 )
1402
1455
1403
1456
all_segments = [read_segment_header (offs ) for offs in segment_header_offsets ]
1404
1457
prog_segments = [s for s in all_segments if s [0 ] == ELFFile .SEG_TYPE_LOAD ]
@@ -1408,8 +1461,8 @@ def read_data(offs, size):
1408
1461
return f .read (size )
1409
1462
1410
1463
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
1413
1466
if lma != 0 and size > 0
1414
1467
]
1415
1468
self .segments = prog_segments
0 commit comments