Skip to content

Commit 325d6b7

Browse files
pillo79kartben
authored andcommitted
llext: add option to keep section data after llext_load
This is required for the functions that inspect the ELF file to work properly. The user must then call llext_free_inspection_data() before calling llext_unload() to free the memory left allocated in the loader and extension memory. Signed-off-by: Luca Burelli <[email protected]>
1 parent 0201683 commit 325d6b7

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

include/zephyr/llext/llext.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ static inline unsigned int llext_section_count(const struct llext *ext)
146146
struct llext_load_param {
147147
/** Perform local relocation */
148148
bool relocate_local;
149+
149150
/**
150151
* Use the virtual symbol addresses from the ELF, not addresses within
151152
* the memory buffer, when calculating relocation targets. It also
@@ -154,12 +155,22 @@ struct llext_load_param {
154155
* allocation and copying internally.
155156
*/
156157
bool pre_located;
158+
157159
/**
158160
* Extensions can implement custom ELF sections to be loaded in specific
159161
* memory regions, detached from other sections of compatible types.
160162
* This optional callback checks whether a section should be detached.
161163
*/
162164
bool (*section_detached)(const elf_shdr_t *shdr);
165+
166+
/**
167+
* Keep the ELF section data in memory after loading the extension. This
168+
* is needed to use some of the functions in @ref llext_inspect_apis.
169+
*
170+
* @note Related memory must be freed by @ref llext_free_inspection_data
171+
* before the extension can be unloaded via @ref llext_unload.
172+
*/
173+
bool keep_section_info;
163174
};
164175

165176
/** Default initializer for @ref llext_load_param */
@@ -211,6 +222,19 @@ int llext_load(struct llext_loader *loader, const char *name, struct llext **ext
211222
*/
212223
int llext_unload(struct llext **ext);
213224

225+
/**
226+
* @brief Free any inspection-related memory for the specified loader and extension.
227+
*
228+
* This is only required if inspection data was requested at load time by
229+
* setting @ref llext_load_param.keep_section_info; otherwise, this call will
230+
* be a no-op.
231+
*
232+
* @param[in] ldr Extension loader
233+
* @param[in] ext Extension
234+
* @returns 0 on success, or a negative error code.
235+
*/
236+
int llext_free_inspection_data(struct llext_loader *ldr, struct llext *ext);
237+
214238
/** @brief Entry point function signature for an extension. */
215239
typedef void (*llext_entry_fn_t)(void *user_data);
216240

subsys/llext/llext_load.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
112112
LOG_ERR("Failed to allocate section map, size %zu", sect_map_sz);
113113
return -ENOMEM;
114114
}
115+
ext->alloc_size += sect_map_sz;
115116
for (int i = 0; i < ext->sect_cnt; i++) {
116117
ldr->sect_map[i].mem_idx = LLEXT_MEM_COUNT;
117118
ldr->sect_map[i].offset = 0;
@@ -759,12 +760,13 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
759760

760761
out:
761762
/*
762-
* Free resources only used during loading. Note that this exploits
763-
* the fact that freeing a NULL pointer has no effect.
763+
* Free resources only used during loading, unless explicitly requested.
764+
* Note that this exploits the fact that freeing a NULL pointer has no effect.
764765
*/
765766

766-
llext_free(ldr->sect_map);
767-
ldr->sect_map = NULL;
767+
if (ret != 0 || !ldr_parm || !ldr_parm->keep_section_info) {
768+
llext_free_inspection_data(ldr, ext);
769+
}
768770

769771
/* Until proper inter-llext linking is implemented, the symbol table is
770772
* not useful outside of the loading process; keep it only if debugging
@@ -796,3 +798,14 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
796798

797799
return ret;
798800
}
801+
802+
int llext_free_inspection_data(struct llext_loader *ldr, struct llext *ext)
803+
{
804+
if (ldr->sect_map) {
805+
ext->alloc_size -= ext->sect_cnt * sizeof(ldr->sect_map[0]);
806+
llext_free(ldr->sect_map);
807+
ldr->sect_map = NULL;
808+
}
809+
810+
return 0;
811+
}

0 commit comments

Comments
 (0)