Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/zephyr/llext/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ struct elf64_shdr {
#define SHT_NOBITS 0x8 /**< Program data with no file image */
#define SHT_REL 0x9 /**< Relocation entries without addends */
#define SHT_DYNSYM 0xB /**< Dynamic linking symbol table */
#define SHT_INIT_ARRAY 0xe /**< Array of pointers to init functions */
#define SHT_FINI_ARRAY 0xf /**< Array of pointers to termination functions */
#define SHT_PREINIT_ARRAY 0x10 /**< Array of pointers to early init functions */

/** ELF section flags */
#define SHF_WRITE 0x1 /**< Section is writable */
Expand Down
3 changes: 3 additions & 0 deletions include/zephyr/llext/llext.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ enum llext_mem {
LLEXT_MEM_SYMTAB, /**< Symbol table */
LLEXT_MEM_STRTAB, /**< Symbol name strings */
LLEXT_MEM_SHSTRTAB, /**< Section name strings */
LLEXT_MEM_PREINIT, /**< Array of early setup functions */
LLEXT_MEM_INIT, /**< Array of setup functions */
LLEXT_MEM_FINI, /**< Array of cleanup functions */

LLEXT_MEM_COUNT, /**< Number of regions managed by LLEXT */
};
Expand Down
42 changes: 41 additions & 1 deletion subsys/llext/llext_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext)

name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name);

if (ldr->sect_map[i].mem_idx != LLEXT_MEM_COUNT) {
LOG_DBG("section %d name %s already mapped to region %d",
i, name, ldr->sect_map[i].mem_idx);
continue;
}

/* Identify the section type by its flags */
enum llext_mem mem_idx;

Expand All @@ -224,6 +230,15 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext)
mem_idx = LLEXT_MEM_RODATA;
}
break;
case SHT_PREINIT_ARRAY:
mem_idx = LLEXT_MEM_PREINIT;
break;
case SHT_INIT_ARRAY:
mem_idx = LLEXT_MEM_INIT;
break;
case SHT_FINI_ARRAY:
mem_idx = LLEXT_MEM_FINI;
break;
default:
mem_idx = LLEXT_MEM_COUNT;
break;
Expand All @@ -241,6 +256,19 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext)
continue;
}

switch (mem_idx) {
case LLEXT_MEM_PREINIT:
case LLEXT_MEM_INIT:
case LLEXT_MEM_FINI:
if (shdr->sh_entsize != sizeof(void *) ||
shdr->sh_size % shdr->sh_entsize != 0) {
LOG_ERR("Invalid %s array in section %d", name, i);
return -ENOEXEC;
}
default:
break;
}

LOG_DBG("section %d name %s maps to region %d", i, name, mem_idx);

ldr->sect_map[i].mem_idx = mem_idx;
Expand All @@ -261,14 +289,26 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext)
return -ENOEXEC;
}

if (mem_idx == LLEXT_MEM_BSS) {
/* Check if this region type is extendable */
switch (mem_idx) {
case LLEXT_MEM_BSS:
/* SHT_NOBITS sections cannot be merged properly:
* as they use no space in the file, the logic
* below does not work; they must be treated as
* independent entities.
*/
LOG_ERR("Multiple SHT_NOBITS sections are not supported");
return -ENOTSUP;
case LLEXT_MEM_PREINIT:
case LLEXT_MEM_INIT:
case LLEXT_MEM_FINI:
/* These regions are not extendable and must be
* referenced at most once in the ELF file.
*/
LOG_ERR("Region %d redefined", mem_idx);
return -ENOEXEC;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't this be caught in line 211?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, line 211 checks that the ELF section (ldr->sect_map[shndx]) was assigned a region before entering llext_map_sections - I added that log so the whole function prints a full ELF section table, including reserved sections found by llext_find_tables.
This is instead checking if the region has been already defined (ie. ldr->sects[mem_idx] - the array that really should be renamed ldr->regions...).

default:
break;
}

if (ldr->hdr.e_type == ET_DYN) {
Expand Down