Skip to content

Commit f4c989f

Browse files
llext: Refactor symbol lookup logic into function
This commit refactors logic in llext_link.c that resolves a symbol to be imported by an llext into a utility function. Thereby, the logic can be re-used in other functions if needed, e.g., when resolving symbols for indirect relocations. Signed-off-by: Eric Ackermann <[email protected]>
1 parent 2ce2794 commit f4c989f

File tree

1 file changed

+83
-57
lines changed

1 file changed

+83
-57
lines changed

subsys/llext/llext_link.c

Lines changed: 83 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,84 @@ static const void *llext_find_extension_sym(const char *sym_name, struct llext *
142142
return se.addr;
143143
}
144144

145+
/**
146+
* @brief Determine address of a symbol.
147+
*
148+
* @param ext llext extension
149+
* @param ldr llext loader
150+
* @param link_addr (output) resolved address
151+
* @param rel relocation entry
152+
* @param sym symbol entry
153+
* @param name symbol name
154+
* @param shdr section header
155+
*
156+
* @return 0 for OK, negative for error
157+
*/
158+
static int llext_lookup_symbol(struct llext *ext, struct llext_loader *ldr, uintptr_t *link_addr,
159+
const elf_rela_t *rel, const elf_sym_t *sym, const char *name,
160+
const elf_shdr_t *shdr)
161+
{
162+
if (ELF_R_SYM(rel->r_info) == 0) {
163+
/*
164+
* no symbol
165+
* example: R_ARM_V4BX relocation, R_ARM_RELATIVE
166+
*/
167+
*link_addr = 0;
168+
} else if (sym->st_shndx == SHN_UNDEF) {
169+
/* If symbol is undefined, then we need to look it up */
170+
*link_addr = (uintptr_t)llext_find_sym(NULL, SYM_NAME_OR_SLID(name, sym->st_value));
171+
172+
if (*link_addr == 0) {
173+
/* Try loaded tables */
174+
struct llext *dep;
175+
176+
*link_addr = (uintptr_t)llext_find_extension_sym(name, &dep);
177+
if (*link_addr) {
178+
llext_dependency_add(ext, dep);
179+
}
180+
}
181+
182+
if (*link_addr == 0) {
183+
LOG_ERR("Undefined symbol with no entry in "
184+
"symbol table %s, offset %zd, link section %d",
185+
name, (size_t)rel->r_offset, shdr->sh_link);
186+
return -ENODATA;
187+
}
188+
189+
LOG_INF("found symbol %s at 0x%lx", name, *link_addr);
190+
} else if (sym->st_shndx == SHN_ABS) {
191+
/* Absolute symbol */
192+
*link_addr = sym->st_value;
193+
} else if ((sym->st_shndx < ldr->hdr.e_shnum) &&
194+
!IN_RANGE(sym->st_shndx, SHN_LORESERVE, SHN_HIRESERVE)) {
195+
/* This check rejects all relocations whose target symbol has a section index higher
196+
* than the maximum possible in this ELF file, or belongs in the reserved range:
197+
* they will be caught by the `else` below and cause an error to be returned. This
198+
* aborts the LLEXT's loading and prevents execution of improperly relocated code,
199+
* which is dangerous.
200+
*
201+
* Note that the unsupported SHN_COMMON section is rejected as part of this check.
202+
* Also note that SHN_ABS would be rejected as well, but we want to handle it
203+
* properly: for this reason, this check must come AFTER handling the case where the
204+
* symbol's section index is SHN_ABS!
205+
*
206+
*
207+
* For regular symbols, the link address is obtained by adding st_value to the start
208+
* address of the section in which the target symbol resides.
209+
*/
210+
*link_addr =
211+
(uintptr_t)llext_loaded_sect_ptr(ldr, ext, sym->st_shndx) + sym->st_value;
212+
} else {
213+
LOG_ERR("cannot apply relocation: "
214+
"target symbol has unexpected section index %d (0x%X)",
215+
sym->st_shndx, sym->st_shndx);
216+
return -ENOEXEC;
217+
}
218+
219+
return 0;
220+
}
221+
222+
145223
static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr_t *shdr,
146224
const struct llext_load_param *ldr_parm, elf_shdr_t *tgt)
147225
{
@@ -407,64 +485,12 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
407485

408486
op_loc = sect_base + rel.r_offset;
409487

410-
if (ELF_R_SYM(rel.r_info) == 0) {
411-
/* no symbol ex: R_ARM_V4BX relocation, R_ARM_RELATIVE */
412-
link_addr = 0;
413-
} else if (sym.st_shndx == SHN_UNDEF) {
414-
/* If symbol is undefined, then we need to look it up */
415-
link_addr = (uintptr_t)llext_find_sym(NULL,
416-
SYM_NAME_OR_SLID(name, sym.st_value));
417-
418-
if (link_addr == 0) {
419-
/* Try loaded tables */
420-
struct llext *dep;
421-
422-
link_addr = (uintptr_t)llext_find_extension_sym(name, &dep);
423-
if (link_addr) {
424-
llext_dependency_add(ext, dep);
425-
}
426-
}
427-
428-
if (link_addr == 0) {
429-
LOG_ERR("Undefined symbol with no entry in "
430-
"symbol table %s, offset %zd, link section %d",
431-
name, (size_t)rel.r_offset, shdr->sh_link);
432-
return -ENODATA;
433-
}
488+
ret = llext_lookup_symbol(ext, ldr, &link_addr, &rel, &sym, name, shdr);
434489

435-
LOG_INF("found symbol %s at 0x%lx", name, link_addr);
436-
} else if (sym.st_shndx == SHN_ABS) {
437-
/* Absolute symbol */
438-
link_addr = sym.st_value;
439-
} else if ((sym.st_shndx < ldr->hdr.e_shnum) &&
440-
!IN_RANGE(sym.st_shndx, SHN_LORESERVE, SHN_HIRESERVE)) {
441-
/* This check rejects all relocations whose target symbol
442-
* has a section index higher than the maximum possible
443-
* in this ELF file, or belongs in the reserved range:
444-
* they will be caught by the `else` below and cause an
445-
* error to be returned. This aborts the LLEXT's loading
446-
* and prevents execution of improperly relocated code,
447-
* which is dangerous.
448-
*
449-
* Note that the unsupported SHN_COMMON section is rejected
450-
* as part of this check. Also note that SHN_ABS would be
451-
* rejected as well, but we want to handle it properly:
452-
* for this reason, this check must come AFTER handling
453-
* the case where the symbol's section index is SHN_ABS!
454-
*
455-
*
456-
* For regular symbols, the link address is obtained by
457-
* adding st_value to the start address of the section
458-
* in which the target symbol resides.
459-
*/
460-
link_addr = (uintptr_t)llext_loaded_sect_ptr(ldr, ext,
461-
sym.st_shndx)
462-
+ sym.st_value;
463-
} else {
464-
LOG_ERR("rela section %d, entry %d: cannot apply relocation: "
465-
"target symbol has unexpected section index %d (0x%X)",
466-
i, j, sym.st_shndx, sym.st_shndx);
467-
return -ENOEXEC;
490+
if (ret != 0) {
491+
LOG_ERR("Failed to lookup symbol in rela section %d entry %d!", i,
492+
j);
493+
return ret;
468494
}
469495

470496
LOG_INF("writing relocation symbol %s type %zd sym %zd at addr 0x%lx "

0 commit comments

Comments
 (0)