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
(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.data = data
self.file_offs = file_offs
self.flags = flags
self.include_in_checksum = True
if self.addr != 0:
self.pad_to_alignment(
@@ -167,8 +168,8 @@ class ELFSection(ImageSegment):
"""Wrapper class for a section in an ELF image, has a section
name as well as the common properties of an ImageSegment."""
def __init__(self, name, addr, data):
super(ELFSection, self).__init__(addr, data)
def __init__(self, name, addr, data, flags):
super(ELFSection, self).__init__(addr, data, flags=flags)
self.name = name.decode("utf-8")
def __repr__(self):
@@ -178,6 +179,9 @@ class ELFSection(ImageSegment):
class BaseFirmwareImage(object):
SEG_HEADER_LEN = 8
SHA256_DIGEST_LEN = 32
ELF_FLAG_WRITE = 0x1
ELF_FLAG_READ = 0x2
ELF_FLAG_EXEC = 0x4
""" 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.include_in_checksum == next_elem.include_in_checksum,
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,
@@ -1276,7 +1282,7 @@ class ELFFile(object):
name_offs, sec_type, _flags, lma, sec_offs, size = struct.unpack_from(
"<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]
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
if (shstrndx * self.LEN_SEC_HEADER) not in section_header_offsets:
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
)
if sec_type != ELFFile.SEC_TYPE_STRTAB:
@@ -1307,14 +1313,14 @@ class ELFFile(object):
return f.read(size)
prog_sections = [
ELFSection(lookup_string(n_offs), lma, read_data(offs, size))
for (n_offs, _type, lma, size, offs) in prog_sections
ELFSection(lookup_string(n_offs), lma, read_data(offs, size), flags=_flags)
for (n_offs, _type, lma, size, offs, _flags) in prog_sections
if lma != 0 and size > 0
]
self.sections = prog_sections
self.nobits_sections = [
ELFSection(lookup_string(n_offs), lma, b"")
for (n_offs, _type, lma, size, offs) in nobits_secitons
ELFSection(lookup_string(n_offs), lma, b"", flags=_flags)
for (n_offs, _type, lma, size, offs, _flags) in nobits_secitons
if lma != 0 and size > 0
]
@@ -1347,7 +1353,7 @@ class ELFFile(object):
_flags,
_align,
) = 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]
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)
prog_segments = [
ELFSection(b"PHDR", lma, read_data(offs, size))
for (_type, lma, size, offs) in prog_segments
ELFSection(b"PHDR", lma, read_data(offs, size), flags=_flags)
for (_type, lma, size, offs, _flags) in prog_segments
if lma != 0 and size > 0
]
self.segments = prog_segments

View File

@@ -697,7 +697,7 @@ def write_flash(esp, args):
print("Flash md5: %s" % res)
print(
"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!")
else:
@@ -1383,7 +1383,7 @@ def merge_bin(args):
def pad_to(flash_offs):
# 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:
pad_to(addr)

View File

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