Skip to content

Commit 3fcd903

Browse files
pillo79nashif
authored andcommitted
llext: optimize allocations for read-only sections
When loading an extension, read-only sections that do not have relocations and whose data is accessible from the ELF buffer can be directly mapped as-is in the extension memory. This avoids the need to allocate and copy unmodified data from the ELF buffer to the LLEXT heap. Signed-off-by: Luca Burelli <[email protected]>
1 parent e559489 commit 3fcd903

File tree

3 files changed

+18
-4
lines changed

3 files changed

+18
-4
lines changed

include/zephyr/llext/elf.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,11 @@ struct elf64_shdr {
211211
#define SHT_PREINIT_ARRAY 0x10 /**< Array of pointers to early init functions */
212212

213213
/** ELF section flags */
214-
#define SHF_WRITE 0x1 /**< Section is writable */
215-
#define SHF_ALLOC 0x2 /**< Section is present in memory */
216-
#define SHF_EXECINSTR 0x4 /**< Section contains executable instructions */
214+
#define SHF_WRITE 0x1 /**< Section is writable */
215+
#define SHF_ALLOC 0x2 /**< Section is present in memory */
216+
#define SHF_EXECINSTR 0x4 /**< Section contains executable instructions */
217+
#define SHF_MASKOS 0x0ff00000 /**< OS specific flags */
218+
#define SHF_LLEXT_HAS_RELOCS 0x00100000 /**< Section is a target for relocations */
217219

218220
#define SHF_BASIC_TYPE_MASK (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)
219221

subsys/llext/llext_load.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,20 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
494494
/*
495495
* Calculate each ELF section's offset inside its memory region. This
496496
* is done as a separate pass so the final regions are already defined.
497+
* Also mark the regions that include relocation targets.
497498
*/
498499
for (i = 0; i < ext->sect_cnt; ++i) {
499500
elf_shdr_t *shdr = ext->sect_hdrs + i;
500501
enum llext_mem mem_idx = ldr->sect_map[i].mem_idx;
501502

503+
if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
504+
enum llext_mem target_region = ldr->sect_map[shdr->sh_info].mem_idx;
505+
506+
if (target_region != LLEXT_MEM_COUNT) {
507+
ldr->sects[target_region].sh_flags |= SHF_LLEXT_HAS_RELOCS;
508+
}
509+
}
510+
502511
if (mem_idx != LLEXT_MEM_COUNT) {
503512
ldr->sect_map[i].offset = shdr->sh_offset - ldr->sects[mem_idx].sh_offset;
504513
}

subsys/llext/llext_mem.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ static int llext_copy_region(struct llext_loader *ldr, struct llext *ext,
9595
}
9696
}
9797

98-
if (ldr->storage == LLEXT_STORAGE_WRITABLE) {
98+
if (ldr->storage == LLEXT_STORAGE_WRITABLE || /* writable storage */
99+
(ldr->storage == LLEXT_STORAGE_PERSISTENT && /* || persistent storage */
100+
!(region->sh_flags & SHF_WRITE) && /* && read-only region */
101+
!(region->sh_flags & SHF_LLEXT_HAS_RELOCS))) { /* && no relocs to apply */
99102
/*
100103
* Try to reuse data areas from the ELF buffer, if possible.
101104
* If any of the following tests fail, a normal allocation

0 commit comments

Comments
 (0)