diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h index 48a611a3f59..80176daa26b 100644 --- a/include/zephyr/llext/elf.h +++ b/include/zephyr/llext/elf.h @@ -211,9 +211,11 @@ struct elf64_shdr { #define SHT_PREINIT_ARRAY 0x10 /**< Array of pointers to early init functions */ /** ELF section flags */ -#define SHF_WRITE 0x1 /**< Section is writable */ -#define SHF_ALLOC 0x2 /**< Section is present in memory */ -#define SHF_EXECINSTR 0x4 /**< Section contains executable instructions */ +#define SHF_WRITE 0x1 /**< Section is writable */ +#define SHF_ALLOC 0x2 /**< Section is present in memory */ +#define SHF_EXECINSTR 0x4 /**< Section contains executable instructions */ +#define SHF_MASKOS 0x0ff00000 /**< OS specific flags */ +#define SHF_LLEXT_HAS_RELOCS 0x00100000 /**< Section is a target for relocations */ #define SHF_BASIC_TYPE_MASK (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR) diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 623aa4c4730..c4c0b26c35e 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -494,11 +494,20 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext, /* * Calculate each ELF section's offset inside its memory region. This * is done as a separate pass so the final regions are already defined. + * Also mark the regions that include relocation targets. */ for (i = 0; i < ext->sect_cnt; ++i) { elf_shdr_t *shdr = ext->sect_hdrs + i; enum llext_mem mem_idx = ldr->sect_map[i].mem_idx; + if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) { + enum llext_mem target_region = ldr->sect_map[shdr->sh_info].mem_idx; + + if (target_region != LLEXT_MEM_COUNT) { + ldr->sects[target_region].sh_flags |= SHF_LLEXT_HAS_RELOCS; + } + } + if (mem_idx != LLEXT_MEM_COUNT) { ldr->sect_map[i].offset = shdr->sh_offset - ldr->sects[mem_idx].sh_offset; } diff --git a/subsys/llext/llext_mem.c b/subsys/llext/llext_mem.c index 2cde2593795..34599bcddac 100644 --- a/subsys/llext/llext_mem.c +++ b/subsys/llext/llext_mem.c @@ -95,7 +95,10 @@ static int llext_copy_region(struct llext_loader *ldr, struct llext *ext, } } - if (ldr->storage == LLEXT_STORAGE_WRITABLE) { + if (ldr->storage == LLEXT_STORAGE_WRITABLE || /* writable storage */ + (ldr->storage == LLEXT_STORAGE_PERSISTENT && /* || persistent storage */ + !(region->sh_flags & SHF_WRITE) && /* && read-only region */ + !(region->sh_flags & SHF_LLEXT_HAS_RELOCS))) { /* && no relocs to apply */ /* * Try to reuse data areas from the ELF buffer, if possible. * If any of the following tests fail, a normal allocation