llext: support multiple string and symbol tables
The ELF format allows for multiple string and symbol tables with complex references between them. This is especially evident when debugging information is included. This patch fixes the issues that have been identified with multiple string tables to allow LLEXT to properly parse those files: * The symbol table used by LLEXT (LLEXT_MEM_SYMTAB) is now chosen depending on the loaded file type, and other tables are ignored. This change is also applied to the SLID injection script. * The LLEXT string table (LLEXT_MEM_SYMTAB) is now correctly identified by the symbol table reference, instead of picking the first one. * VMA range checks only make sense for allocated sections. Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This commit is contained in:
parent
61c61a5528
commit
7094eae111
@ -36,20 +36,22 @@ class LLEXTSymtabPreparator():
|
||||
self.elf = ELFFile(self.elf_fd)
|
||||
|
||||
def _find_symtab(self):
|
||||
supported_symtab_sections = [
|
||||
".symtab",
|
||||
".dynsym",
|
||||
]
|
||||
e_type = self.elf.header['e_type']
|
||||
if e_type == 'ET_DYN':
|
||||
symtab_name = ".dynsym"
|
||||
elif e_type == 'ET_REL':
|
||||
symtab_name = ".symtab"
|
||||
else:
|
||||
self.log.error(f"unexpected ELF file type {e_type}")
|
||||
return None
|
||||
|
||||
symtab = None
|
||||
for section_name in supported_symtab_sections:
|
||||
symtab = self.elf.get_section_by_name(section_name)
|
||||
if not isinstance(symtab, SymbolTableSection):
|
||||
self.log.debug(f"section {section_name} not found.")
|
||||
else:
|
||||
self.log.info(f"processing '{section_name}' symbol table...")
|
||||
self.log.debug(f"(symbol table is at file offset 0x{symtab['sh_offset']:X})")
|
||||
break
|
||||
symtab = self.elf.get_section_by_name(symtab_name)
|
||||
if not isinstance(symtab, SymbolTableSection):
|
||||
self.log.debug(f"section {symtab_name} not found.")
|
||||
return None
|
||||
|
||||
self.log.info(f"processing symbol table from '{symtab_name}'...")
|
||||
self.log.debug(f"(symbol table is at file offset 0x{symtab['sh_offset']:X})")
|
||||
return symtab
|
||||
|
||||
def _find_imports_in_symtab(self, symtab):
|
||||
|
||||
@ -152,6 +152,8 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
|
||||
static int llext_find_tables(struct llext_loader *ldr, struct llext *ext)
|
||||
{
|
||||
int table_cnt, i;
|
||||
int shstrtab_ndx = ldr->hdr.e_shstrndx;
|
||||
int strtab_ndx = -1;
|
||||
|
||||
memset(ldr->sects, 0, sizeof(ldr->sects));
|
||||
|
||||
@ -171,28 +173,28 @@ static int llext_find_tables(struct llext_loader *ldr, struct llext *ext)
|
||||
shdr->sh_link,
|
||||
shdr->sh_info);
|
||||
|
||||
switch (shdr->sh_type) {
|
||||
case SHT_SYMTAB:
|
||||
case SHT_DYNSYM:
|
||||
if (shdr->sh_type == SHT_SYMTAB && ldr->hdr.e_type == ET_REL) {
|
||||
LOG_DBG("symtab at %d", i);
|
||||
ldr->sects[LLEXT_MEM_SYMTAB] = *shdr;
|
||||
ldr->sect_map[i].mem_idx = LLEXT_MEM_SYMTAB;
|
||||
strtab_ndx = shdr->sh_link;
|
||||
table_cnt++;
|
||||
break;
|
||||
case SHT_STRTAB:
|
||||
if (ldr->hdr.e_shstrndx == i) {
|
||||
LOG_DBG("shstrtab at %d", i);
|
||||
ldr->sects[LLEXT_MEM_SHSTRTAB] = *shdr;
|
||||
ldr->sect_map[i].mem_idx = LLEXT_MEM_SHSTRTAB;
|
||||
} else {
|
||||
LOG_DBG("strtab at %d", i);
|
||||
ldr->sects[LLEXT_MEM_STRTAB] = *shdr;
|
||||
ldr->sect_map[i].mem_idx = LLEXT_MEM_STRTAB;
|
||||
}
|
||||
} else if (shdr->sh_type == SHT_DYNSYM && ldr->hdr.e_type == ET_DYN) {
|
||||
LOG_DBG("dynsym at %d", i);
|
||||
ldr->sects[LLEXT_MEM_SYMTAB] = *shdr;
|
||||
ldr->sect_map[i].mem_idx = LLEXT_MEM_SYMTAB;
|
||||
strtab_ndx = shdr->sh_link;
|
||||
table_cnt++;
|
||||
} else if (shdr->sh_type == SHT_STRTAB && i == shstrtab_ndx) {
|
||||
LOG_DBG("shstrtab at %d", i);
|
||||
ldr->sects[LLEXT_MEM_SHSTRTAB] = *shdr;
|
||||
ldr->sect_map[i].mem_idx = LLEXT_MEM_SHSTRTAB;
|
||||
table_cnt++;
|
||||
} else if (shdr->sh_type == SHT_STRTAB && i == strtab_ndx) {
|
||||
LOG_DBG("strtab at %d", i);
|
||||
ldr->sects[LLEXT_MEM_STRTAB] = *shdr;
|
||||
ldr->sect_map[i].mem_idx = LLEXT_MEM_STRTAB;
|
||||
table_cnt++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,9 +397,10 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ldr->hdr.e_type == ET_DYN) {
|
||||
if ((ldr->hdr.e_type == ET_DYN) &&
|
||||
(x->sh_flags & SHF_ALLOC) && (y->sh_flags & SHF_ALLOC)) {
|
||||
/*
|
||||
* Test all merged VMA ranges for overlaps
|
||||
* Test regions that have VMA ranges for overlaps
|
||||
*/
|
||||
if ((x->sh_addr <= y->sh_addr &&
|
||||
x->sh_addr + x->sh_size > y->sh_addr) ||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user