Skip to content

Commit b11d6d8

Browse files
committed
LLEXT: preserve section headers
Move cached section headers to struct llext from struct llext_loader to preserve them after llext_load() returns. Signed-off-by: Guennadi Liakhovetski <[email protected]>
1 parent e0b2e4d commit b11d6d8

File tree

5 files changed

+46
-38
lines changed

5 files changed

+46
-38
lines changed

include/zephyr/llext/llext.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,24 @@ struct llext {
120120

121121
/** Array of extensions, whose symbols this extension accesses */
122122
struct llext *dependency[LLEXT_MAX_DEPENDENCIES];
123+
124+
/** @cond ignore */
125+
unsigned int sect_cnt;
126+
elf_shdr_t *sect_hdrs;
127+
bool sect_hdrs_on_heap;
128+
/** @endcond */
123129
};
124130

131+
static inline const elf_shdr_t *llext_section_headers(const struct llext *ext)
132+
{
133+
return ext->sect_hdrs;
134+
}
135+
136+
static inline unsigned int llext_section_count(const struct llext *ext)
137+
{
138+
return ext->sect_cnt;
139+
}
140+
125141
/**
126142
* @brief Advanced llext_load parameters
127143
*

include/zephyr/llext/loader.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@ struct llext_loader {
9898
/** @cond ignore */
9999
elf_ehdr_t hdr;
100100
elf_shdr_t sects[LLEXT_MEM_COUNT];
101-
elf_shdr_t *sect_hdrs;
102-
bool sect_hdrs_on_heap;
103101
struct llext_elf_sect_map *sect_map;
104-
uint32_t sect_cnt;
105102
/** @endcond */
106103
};
107104

subsys/llext/llext.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ static struct k_mutex llext_lock = Z_MUTEX_INITIALIZER(llext_lock);
2525

2626
ssize_t llext_find_section(struct llext_loader *ldr, const char *search_name)
2727
{
28-
/* Note that this API is used after llext_load(), so the ldr->sect_hdrs
29-
* cache is already freed. A direct search covers all situations.
30-
*/
31-
3228
elf_shdr_t *shdr;
3329
unsigned int i;
3430
size_t pos;
@@ -253,6 +249,10 @@ int llext_unload(struct llext **ext)
253249
*ext = NULL;
254250
k_mutex_unlock(&llext_lock);
255251

252+
if (tmp->sect_hdrs_on_heap) {
253+
llext_free(tmp->sect_hdrs);
254+
}
255+
256256
llext_free_regions(tmp);
257257
llext_free(tmp->sym_tab.syms);
258258
llext_free(tmp->exp_tab.syms);

subsys/llext/llext_link.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
280280
const char *name;
281281
int i, ret;
282282

283-
for (i = 0; i < ldr->sect_cnt; ++i) {
284-
elf_shdr_t *shdr = ldr->sect_hdrs + i;
283+
for (i = 0; i < ext->sect_cnt; ++i) {
284+
elf_shdr_t *shdr = ext->sect_hdrs + i;
285285

286286
/* find proper relocation sections */
287287
switch (shdr->sh_type) {
@@ -308,7 +308,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
308308
continue;
309309
}
310310

311-
if (shdr->sh_info >= ldr->sect_cnt ||
311+
if (shdr->sh_info >= ext->sect_cnt ||
312312
shdr->sh_size % shdr->sh_entsize != 0) {
313313
LOG_ERR("Sanity checks failed for section %d "
314314
"(info %zd, size %zd, entsize %zd)", i,
@@ -340,7 +340,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
340340
* section .X to local or global symbols. They point to entries
341341
* in the symbol table, describing respective symbols
342342
*/
343-
tgt = ldr->sect_hdrs + shdr->sh_info;
343+
tgt = ext->sect_hdrs + shdr->sh_info;
344344
}
345345

346346
llext_link_plt(ldr, ext, shdr, ldr_parm, tgt);
@@ -481,8 +481,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
481481

482482
/* Detached section caches should be synchronized in place */
483483
if (ldr_parm->section_detached) {
484-
for (i = 0; i < ldr->sect_cnt; ++i) {
485-
elf_shdr_t *shdr = ldr->sect_hdrs + i;
484+
for (i = 0; i < ext->sect_cnt; ++i) {
485+
elf_shdr_t *shdr = ext->sect_hdrs + i;
486486

487487
if (ldr_parm->section_detached(shdr)) {
488488
void *base = llext_peek(ldr, shdr->sh_offset);

subsys/llext/llext_load.c

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -103,29 +103,29 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
103103
return -ENOEXEC;
104104
}
105105

106-
ldr->sect_cnt = ldr->hdr.e_shnum;
106+
ext->sect_cnt = ldr->hdr.e_shnum;
107107

108-
size_t sect_map_sz = ldr->sect_cnt * sizeof(ldr->sect_map[0]);
108+
size_t sect_map_sz = ext->sect_cnt * sizeof(ldr->sect_map[0]);
109109

110110
ldr->sect_map = llext_alloc(sect_map_sz);
111111
if (!ldr->sect_map) {
112112
LOG_ERR("Failed to allocate section map, size %zu", sect_map_sz);
113113
return -ENOMEM;
114114
}
115-
for (int i = 0; i < ldr->sect_cnt; i++) {
115+
for (int i = 0; i < ext->sect_cnt; i++) {
116116
ldr->sect_map[i].mem_idx = LLEXT_MEM_COUNT;
117117
ldr->sect_map[i].offset = 0;
118118
}
119119

120-
ldr->sect_hdrs = (elf_shdr_t *) llext_peek(ldr, ldr->hdr.e_shoff);
121-
if (ldr->sect_hdrs) {
122-
ldr->sect_hdrs_on_heap = false;
120+
ext->sect_hdrs = (elf_shdr_t *)llext_peek(ldr, ldr->hdr.e_shoff);
121+
if (ext->sect_hdrs) {
122+
ext->sect_hdrs_on_heap = false;
123123
} else {
124-
size_t sect_hdrs_sz = ldr->sect_cnt * sizeof(ldr->sect_hdrs[0]);
124+
size_t sect_hdrs_sz = ext->sect_cnt * sizeof(ext->sect_hdrs[0]);
125125

126-
ldr->sect_hdrs_on_heap = true;
127-
ldr->sect_hdrs = llext_alloc(sect_hdrs_sz);
128-
if (!ldr->sect_hdrs) {
126+
ext->sect_hdrs_on_heap = true;
127+
ext->sect_hdrs = llext_alloc(sect_hdrs_sz);
128+
if (!ext->sect_hdrs) {
129129
LOG_ERR("Failed to allocate section headers, size %zu", sect_hdrs_sz);
130130
return -ENOMEM;
131131
}
@@ -136,7 +136,7 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
136136
return ret;
137137
}
138138

139-
ret = llext_read(ldr, ldr->sect_hdrs, sect_hdrs_sz);
139+
ret = llext_read(ldr, ext->sect_hdrs, sect_hdrs_sz);
140140
if (ret != 0) {
141141
LOG_ERR("Failed to read section headers");
142142
return ret;
@@ -149,15 +149,15 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
149149
/*
150150
* Find all relevant string and symbol tables
151151
*/
152-
static int llext_find_tables(struct llext_loader *ldr)
152+
static int llext_find_tables(struct llext_loader *ldr, struct llext *ext)
153153
{
154154
int table_cnt, i;
155155

156156
memset(ldr->sects, 0, sizeof(ldr->sects));
157157

158158
/* Find symbol and string tables */
159-
for (i = 0, table_cnt = 0; i < ldr->sect_cnt && table_cnt < 3; ++i) {
160-
elf_shdr_t *shdr = ldr->sect_hdrs + i;
159+
for (i = 0, table_cnt = 0; i < ext->sect_cnt && table_cnt < 3; ++i) {
160+
elf_shdr_t *shdr = ext->sect_hdrs + i;
161161

162162
LOG_DBG("section %d at 0x%zx: name %d, type %d, flags 0x%zx, "
163163
"addr 0x%zx, size %zd, link %d, info %d",
@@ -216,8 +216,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
216216
int i, j;
217217
const char *name;
218218

219-
for (i = 0; i < ldr->sect_cnt; ++i) {
220-
elf_shdr_t *shdr = ldr->sect_hdrs + i;
219+
for (i = 0; i < ext->sect_cnt; ++i) {
220+
elf_shdr_t *shdr = ext->sect_hdrs + i;
221221

222222
name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name);
223223

@@ -437,8 +437,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
437437
* Calculate each ELF section's offset inside its memory region. This
438438
* is done as a separate pass so the final regions are already defined.
439439
*/
440-
for (i = 0; i < ldr->sect_cnt; ++i) {
441-
elf_shdr_t *shdr = ldr->sect_hdrs + i;
440+
for (i = 0; i < ext->sect_cnt; ++i) {
441+
elf_shdr_t *shdr = ext->sect_hdrs + i;
442442
enum llext_mem mem_idx = ldr->sect_map[i].mem_idx;
443443

444444
if (mem_idx != LLEXT_MEM_COUNT) {
@@ -585,7 +585,7 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext,
585585

586586
sym_tab->syms[j].name = name;
587587

588-
elf_shdr_t *shdr = ldr->sect_hdrs + shndx;
588+
elf_shdr_t *shdr = ext->sect_hdrs + shndx;
589589
uintptr_t section_addr = shdr->sh_addr;
590590

591591
if (ldr_parm->pre_located &&
@@ -664,7 +664,7 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
664664
#endif
665665

666666
LOG_DBG("Finding ELF tables...");
667-
ret = llext_find_tables(ldr);
667+
ret = llext_find_tables(ldr, ext);
668668
if (ret != 0) {
669669
LOG_ERR("Failed to find important ELF tables, ret %d", ret);
670670
goto out;
@@ -736,11 +736,6 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
736736
llext_free(ldr->sect_map);
737737
ldr->sect_map = NULL;
738738

739-
if (ldr->sect_hdrs_on_heap) {
740-
llext_free(ldr->sect_hdrs);
741-
}
742-
ldr->sect_hdrs = NULL;
743-
744739
/* Until proper inter-llext linking is implemented, the symbol table is
745740
* not useful outside of the loading process; keep it only if debugging
746741
* is enabled and no error is detected.

0 commit comments

Comments
 (0)