fix(elf2image): add ELF flags to merge condition

Improve the condition upon the segments being merged in the
elf2image command. Covering the cases when comparing adjacent
segment addresses and types is not enough.

Signed-off-by: Marek Matej <marek.matej@espressif.com>
This commit is contained in:
Marek Matej
2024-05-20 15:12:23 +02:00
parent 4394a658c4
commit e87cc3ec62
3 changed files with 22 additions and 16 deletions

View File

@@ -115,10 +115,11 @@ class ImageSegment(object):
"""Wrapper class for a segment in an ESP image """Wrapper class for a segment in an ESP image
(very similar to a section in an ELFImage also)""" (very similar to a section in an ELFImage also)"""
def __init__(self, addr, data, file_offs=None): def __init__(self, addr, data, file_offs=None, flags=0):
self.addr = addr self.addr = addr
self.data = data self.data = data
self.file_offs = file_offs self.file_offs = file_offs
self.flags = flags
self.include_in_checksum = True self.include_in_checksum = True
if self.addr != 0: if self.addr != 0:
self.pad_to_alignment( self.pad_to_alignment(
@@ -167,8 +168,8 @@ class ELFSection(ImageSegment):
"""Wrapper class for a section in an ELF image, has a section """Wrapper class for a section in an ELF image, has a section
name as well as the common properties of an ImageSegment.""" name as well as the common properties of an ImageSegment."""
def __init__(self, name, addr, data): def __init__(self, name, addr, data, flags):
super(ELFSection, self).__init__(addr, data) super(ELFSection, self).__init__(addr, data, flags=flags)
self.name = name.decode("utf-8") self.name = name.decode("utf-8")
def __repr__(self): def __repr__(self):
@@ -178,6 +179,9 @@ class ELFSection(ImageSegment):
class BaseFirmwareImage(object): class BaseFirmwareImage(object):
SEG_HEADER_LEN = 8 SEG_HEADER_LEN = 8
SHA256_DIGEST_LEN = 32 SHA256_DIGEST_LEN = 32
ELF_FLAG_WRITE = 0x1
ELF_FLAG_READ = 0x2
ELF_FLAG_EXEC = 0x4
""" Base class with common firmware image functions """ """ Base class with common firmware image functions """
@@ -373,6 +377,8 @@ class BaseFirmwareImage(object):
elem.get_memory_type(self) == next_elem.get_memory_type(self), elem.get_memory_type(self) == next_elem.get_memory_type(self),
elem.include_in_checksum == next_elem.include_in_checksum, elem.include_in_checksum == next_elem.include_in_checksum,
next_elem.addr == elem.addr + len(elem.data), next_elem.addr == elem.addr + len(elem.data),
next_elem.flags & self.ELF_FLAG_EXEC
== elem.flags & self.ELF_FLAG_EXEC,
) )
): ):
# Merge any segment that ends where the next one starts, # Merge any segment that ends where the next one starts,
@@ -1276,7 +1282,7 @@ class ELFFile(object):
name_offs, sec_type, _flags, lma, sec_offs, size = struct.unpack_from( name_offs, sec_type, _flags, lma, sec_offs, size = struct.unpack_from(
"<LLLLLL", section_header[offs:] "<LLLLLL", section_header[offs:]
) )
return (name_offs, sec_type, lma, size, sec_offs) return (name_offs, sec_type, lma, size, sec_offs, _flags)
all_sections = [read_section_header(offs) for offs in section_header_offsets] all_sections = [read_section_header(offs) for offs in section_header_offsets]
prog_sections = [s for s in all_sections if s[1] in ELFFile.PROG_SEC_TYPES] prog_sections = [s for s in all_sections if s[1] in ELFFile.PROG_SEC_TYPES]
@@ -1285,7 +1291,7 @@ class ELFFile(object):
# search for the string table section # search for the string table section
if (shstrndx * self.LEN_SEC_HEADER) not in section_header_offsets: if (shstrndx * self.LEN_SEC_HEADER) not in section_header_offsets:
raise FatalError("ELF file has no STRTAB section at shstrndx %d" % shstrndx) raise FatalError("ELF file has no STRTAB section at shstrndx %d" % shstrndx)
_, sec_type, _, sec_size, sec_offs = read_section_header( _, sec_type, _, sec_size, sec_offs, _ = read_section_header(
shstrndx * self.LEN_SEC_HEADER shstrndx * self.LEN_SEC_HEADER
) )
if sec_type != ELFFile.SEC_TYPE_STRTAB: if sec_type != ELFFile.SEC_TYPE_STRTAB:
@@ -1307,14 +1313,14 @@ class ELFFile(object):
return f.read(size) return f.read(size)
prog_sections = [ prog_sections = [
ELFSection(lookup_string(n_offs), lma, read_data(offs, size)) ELFSection(lookup_string(n_offs), lma, read_data(offs, size), flags=_flags)
for (n_offs, _type, lma, size, offs) in prog_sections for (n_offs, _type, lma, size, offs, _flags) in prog_sections
if lma != 0 and size > 0 if lma != 0 and size > 0
] ]
self.sections = prog_sections self.sections = prog_sections
self.nobits_sections = [ self.nobits_sections = [
ELFSection(lookup_string(n_offs), lma, b"") ELFSection(lookup_string(n_offs), lma, b"", flags=_flags)
for (n_offs, _type, lma, size, offs) in nobits_secitons for (n_offs, _type, lma, size, offs, _flags) in nobits_secitons
if lma != 0 and size > 0 if lma != 0 and size > 0
] ]
@@ -1347,7 +1353,7 @@ class ELFFile(object):
_flags, _flags,
_align, _align,
) = struct.unpack_from("<LLLLLLLL", segment_header[offs:]) ) = struct.unpack_from("<LLLLLLLL", segment_header[offs:])
return (seg_type, lma, size, seg_offs) return (seg_type, lma, size, seg_offs, _flags)
all_segments = [read_segment_header(offs) for offs in segment_header_offsets] all_segments = [read_segment_header(offs) for offs in segment_header_offsets]
prog_segments = [s for s in all_segments if s[0] == ELFFile.SEG_TYPE_LOAD] prog_segments = [s for s in all_segments if s[0] == ELFFile.SEG_TYPE_LOAD]
@@ -1357,8 +1363,8 @@ class ELFFile(object):
return f.read(size) return f.read(size)
prog_segments = [ prog_segments = [
ELFSection(b"PHDR", lma, read_data(offs, size)) ELFSection(b"PHDR", lma, read_data(offs, size), flags=_flags)
for (_type, lma, size, offs) in prog_segments for (_type, lma, size, offs, _flags) in prog_segments
if lma != 0 and size > 0 if lma != 0 and size > 0
] ]
self.segments = prog_segments self.segments = prog_segments

View File

@@ -697,7 +697,7 @@ def write_flash(esp, args):
print("Flash md5: %s" % res) print("Flash md5: %s" % res)
print( print(
"MD5 of 0xFF is %s" "MD5 of 0xFF is %s"
% (hashlib.md5(b"\xFF" * uncsize).hexdigest()) % (hashlib.md5(b"\xff" * uncsize).hexdigest())
) )
raise FatalError("MD5 of file does not match data in flash!") raise FatalError("MD5 of file does not match data in flash!")
else: else:
@@ -1383,7 +1383,7 @@ def merge_bin(args):
def pad_to(flash_offs): def pad_to(flash_offs):
# account for output file offset if there is any # account for output file offset if there is any
of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell())) of.write(b"\xff" * (flash_offs - args.target_offset - of.tell()))
for addr, argfile in input_files: for addr, argfile in input_files:
pad_to(addr) pad_to(addr)

View File

@@ -326,8 +326,8 @@ class TestESP32Image(BaseTestCase):
# this ELF will produce 8 segments in the bin # this ELF will produce 8 segments in the bin
image = self._test_elf2image(ELF, BIN) image = self._test_elf2image(ELF, BIN)
# Adjacent sections are now merged, len(image.segments) should # Adjacent sections are now merged, len(image.segments) should
# equal 4 (instead of 8). # equal 5 (instead of 8).
assert len(image.segments) == 4 assert len(image.segments) == 5
# --use_segments uses ELF segments(phdrs), produces just 2 segments in the bin # --use_segments uses ELF segments(phdrs), produces just 2 segments in the bin
image = self._test_elf2image(ELF, BIN, ["--use_segments"]) image = self._test_elf2image(ELF, BIN, ["--use_segments"])