Skip to content

Commit 111f46e

Browse files
committed
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 9e505ae commit 111f46e

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-3
lines changed

subsys/llext/llext_load.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,15 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
216216
int i, j;
217217
const char *name;
218218

219+
/* early loop to mark sections where relocations will be applied */
220+
for (i = 0; i < ldr->sect_cnt; ++i) {
221+
elf_shdr_t *shdr = ldr->sect_hdrs + i;
222+
223+
if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
224+
ldr->sect_map[shdr->sh_info].has_relocs = true;
225+
}
226+
}
227+
219228
for (i = 0; i < ldr->sect_cnt; ++i) {
220229
elf_shdr_t *shdr = ldr->sect_hdrs + i;
221230

@@ -301,6 +310,7 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
301310
* region descriptor.
302311
*/
303312
memcpy(region, shdr, sizeof(*region));
313+
region->sh_info = 0; /* reuse for relocation status */
304314
} else {
305315
/* Make sure this section is compatible with the region */
306316
if ((shdr->sh_flags & SHF_BASIC_TYPE_MASK) !=
@@ -360,6 +370,9 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
360370
region->sh_offset = bot_ofs;
361371
region->sh_size = top_ofs - bot_ofs;
362372
}
373+
374+
/* Update this region's relocation status */
375+
region->sh_info |= ldr->sect_map[i].has_relocs;
363376
}
364377

365378
/*

subsys/llext/llext_mem.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,13 @@ static int llext_copy_region(struct llext_loader *ldr, struct llext *ext,
6969
}
7070
ext->mem_size[mem_idx] = region->sh_size;
7171

72-
if (region->sh_type != SHT_NOBITS &&
73-
!IS_ENABLED(CONFIG_LLEXT_HW_MEMORY_CHECKS) &&
74-
ldr->storage == LLEXT_STORAGE_WRITABLE) {
72+
if (region->sh_type != SHT_NOBITS && /* region has data in the ELF */
73+
!IS_ENABLED(CONFIG_LLEXT_HW_MEMORY_CHECKS) && /* && no mem protection rules */
74+
(ldr->storage == LLEXT_STORAGE_WRITABLE || /* && writable storage */
75+
(ldr->storage == LLEXT_STORAGE_PERSISTENT && /* || persistent storage */
76+
!(region->sh_flags & SHF_WRITE) && /* && read-only region */
77+
!region->sh_info)) /* && no relocs to apply */
78+
) {
7579
/* Directly use data from the ELF buffer */
7680
ext->mem[mem_idx] = llext_peek(ldr, region->sh_offset);
7781
if (ext->mem[mem_idx]) {

subsys/llext/llext_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
struct llext_elf_sect_map {
1414
enum llext_mem mem_idx;
1515
size_t offset;
16+
bool has_relocs;
1617
};
1718

1819
/*

0 commit comments

Comments
 (0)