Skip to content

Commit 6c2b5f6

Browse files
pillo79nashif
authored andcommitted
llext: introduce 'enum llext_storage_type'
This patch introduces an 'enum llext_storage_type' that defines the storage type of the ELF data that will be loaded: - LLEXT_STORAGE_TEMPORARY: ELF data is only available during llext_load(); even when the loader supports directly accessing the memory via llext_peek(), the buffer contents will be discarded afterwards. LLEXT will allocate copies of all required data into its heap. - LLEXT_STORAGE_PERSISTENT: ELF data is stored in a *read-only* buffer that is guaranteed to be always accessible for as long as the extension is loaded. LLEXT may directly reuse constant data from the buffer, but may still allocate copies if relocations need to be applied. - LLEXT_STORAGE_WRITABLE: ELF data is stored in a *writable* memory buffer that is guaranteed to be always accessible for as long as the extension is loaded. LLEXT may freely modify and reuse data in the buffer; so, after the extension is unloaded, the contents should be re-initialized before a subsequent llext_load() call. To keep full compatibility with existing code, the storage type of LLEXT_BUF_LOADER is determined by the CONFIG_LLEXT_STORAGE_WRITABLE Kconfig option between LLEXT_STORAGE_PERSISTENT and LLEXT_STORAGE_WRITABLE. Signed-off-by: Luca Burelli <[email protected]>
1 parent 63142a3 commit 6c2b5f6

File tree

5 files changed

+55
-3
lines changed

5 files changed

+55
-3
lines changed

include/zephyr/llext/buf_loader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ void *llext_buf_peek(struct llext_loader *ldr, size_t pos);
5656
.seek = llext_buf_seek, \
5757
.peek = llext_buf_peek, \
5858
.finalize = NULL, \
59+
.storage = IS_ENABLED(CONFIG_LLEXT_STORAGE_WRITABLE) ? \
60+
LLEXT_STORAGE_WRITABLE : \
61+
LLEXT_STORAGE_PERSISTENT, \
5962
}, \
6063
.buf = (_buf), \
6164
.len = (_buf_len), \

include/zephyr/llext/fs_loader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void llext_fs_finalize(struct llext_loader *ldr);
5757
.seek = llext_fs_seek, \
5858
.peek = NULL, \
5959
.finalize = llext_fs_finalize, \
60+
.storage = LLEXT_STORAGE_TEMPORARY, \
6061
}, \
6162
.is_open = false, \
6263
.name = (_filename), \

include/zephyr/llext/loader.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,44 @@ extern "C" {
3232
struct llext_elf_sect_map; /* defined in llext_priv.h */
3333
/** @endcond */
3434

35+
/**
36+
* @brief Storage type for the ELF data to be loaded.
37+
*
38+
* This enum defines the storage type of the ELF data that will be loaded. The
39+
* storage type determines which memory optimizations can be tried by the LLEXT
40+
* subsystem during the load process.
41+
*
42+
* @note Even with the most permissive option, LLEXT might still have to copy
43+
* ELF data into a separate memory region to comply with other restrictions,
44+
* such as hardware memory protection and/or alignment rules.
45+
* Sections such as BSS that have no space in the file will also be allocated
46+
* in the LLEXT heap.
47+
*/
48+
enum llext_storage_type {
49+
/**
50+
* ELF data is only available during llext_load(); even if the loader
51+
* supports directly accessing the memory via llext_peek(), the buffer
52+
* contents will be discarded afterwards.
53+
* LLEXT will allocate copies of all required data into its heap.
54+
*/
55+
LLEXT_STORAGE_TEMPORARY,
56+
/**
57+
* ELF data is stored in a *read-only* buffer that is guaranteed to be
58+
* always accessible for as long as the extension is loaded. LLEXT may
59+
* directly reuse constant data from the buffer, but may still allocate
60+
* copies if relocations need to be applied.
61+
*/
62+
LLEXT_STORAGE_PERSISTENT,
63+
/**
64+
* ELF data is stored in a *writable* memory buffer that is guaranteed
65+
* to be always accessible for as long as the extension is loaded.
66+
* LLEXT may freely modify and reuse data in the buffer; so, after the
67+
* extension is unloaded, the contents should be re-initialized before
68+
* a subsequent llext_load() call.
69+
*/
70+
LLEXT_STORAGE_WRITABLE,
71+
};
72+
3573
/**
3674
* @brief Linkable loadable extension loader context
3775
*
@@ -95,6 +133,11 @@ struct llext_loader {
95133
*/
96134
void (*finalize)(struct llext_loader *ldr);
97135

136+
/**
137+
* @brief Storage type of the underlying data accessed by this loader.
138+
*/
139+
enum llext_storage_type storage;
140+
98141
/** @cond ignore */
99142
elf_ehdr_t hdr;
100143
elf_shdr_t sects[LLEXT_MEM_COUNT];

subsys/llext/llext_link.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,14 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
299299
* beginning of the .text section in the ELF file can be
300300
* applied to the memory location of mem[LLEXT_MEM_TEXT].
301301
*
302-
* This is valid only when CONFIG_LLEXT_STORAGE_WRITABLE=y
303-
* and peek() is usable on the source ELF file.
302+
* This is valid only for LLEXT_STORAGE_WRITABLE loaders
303+
* since the buffer will be directly modified.
304304
*/
305+
if (ldr->storage != LLEXT_STORAGE_WRITABLE) {
306+
LOG_ERR("PLT: cannot link read-only ELF file");
307+
continue;
308+
}
309+
305310
uint8_t *rel_addr = (uint8_t *)ext->mem[LLEXT_MEM_TEXT] -
306311
ldr->sects[LLEXT_MEM_TEXT].sh_offset;
307312

subsys/llext/llext_mem.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static int llext_copy_region(struct llext_loader *ldr, struct llext *ext,
7171
}
7272
ext->mem_size[mem_idx] = region_alloc;
7373

74-
if (IS_ENABLED(CONFIG_LLEXT_STORAGE_WRITABLE)) {
74+
if (ldr->storage == LLEXT_STORAGE_WRITABLE) {
7575
/*
7676
* Try to reuse data areas from the ELF buffer, if possible.
7777
* If any of the following tests fail, a normal allocation

0 commit comments

Comments
 (0)