-
Notifications
You must be signed in to change notification settings - Fork 7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
llext: Support non-paired RISC-V PCREL Relocation #82799
base: main
Are you sure you want to change the base?
llext: Support non-paired RISC-V PCREL Relocation #82799
Conversation
f18fd43
to
60c3614
Compare
60c3614
to
d642674
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some clean up around function return codes and arguments is needed, some further comments are optional
subsys/llext/llext_link.c
Outdated
*link_addr = 0; | ||
|
||
if (ELF_R_SYM(rel->r_info) == 0) { | ||
/* no symbol ex: R_ARM_V4BX relocation, R_ARM_RELATIVE */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that this is the original text just moved by you, but maybe we can make the guess that "ex" stands for "example" to help future readers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the comment
subsys/llext/llext_link.c
Outdated
*/ | ||
static int llext_lookup_symbol(uintptr_t *link_addr, const elf_rela_t *rel, const elf_sym_t *sym, | ||
struct llext *ext, struct llext_loader *ldr, const char *name, | ||
const elf_shdr_t *shdr, int section_idx, int entry_idx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by convention LLEXT functions have ldr
and ext
as their first parameters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed it accordingly in both new functions
subsys/llext/llext_link.c
Outdated
elf_word rel_cnt, uintptr_t sect_base, int section_idx, | ||
int entry_idx, struct llext *ext, const elf_sym_t *sym, | ||
struct llext_loader *ldr, uintptr_t *link_addr_out, | ||
int *last_rel_idx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same about argument order and removing section_idx
and entry_idx
. In general this looks like quite a large number of arguments, it often means, that some can be eliminated relatively easily
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed the parameters that can be computed efficiently.
subsys/llext/llext_link.c
Outdated
return -ENODATA; | ||
} | ||
ret = llext_lookup_symbol(&link_addr, &rel, &sym, ext, ldr, name, shdr, i, | ||
j); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it fit within 100 characters if you join the two lines? You need to check the error code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the error check and reformatted the line
subsys/llext/llext_link.c
Outdated
} else { | ||
LOG_ERR("rela section %d, entry %d: cannot apply relocation: " | ||
"target symbol has unexpected section index %d (0x%X)", | ||
section_idx, entry_idx, sym->st_shndx, sym->st_shndx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
section_idx
and entry_idx
are only used in this print. Move it out of the function and remove the function arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
subsys/llext/llext_link.c
Outdated
struct llext *dep; | ||
|
||
*link_addr = (uintptr_t)llext_find_extension_sym(name, &dep); | ||
if (link_addr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing dereference asterisk *
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added *
subsys/llext/llext_link.c
Outdated
struct llext *ext, struct llext_loader *ldr, const char *name, | ||
const elf_shdr_t *shdr, int section_idx, int entry_idx) | ||
{ | ||
*link_addr = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this isn't in the original code and is superfluous - as long as you add an error check in the caller
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with all comments from @lyakh.
Also, for easier review, can you split the refactor that creates llext_lookup_symbol
in a separate commit? Thanks!
d642674
to
3647645
Compare
I have split the refactor into a separate commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the refactor!
This PR adds a lot of RISCV-specific stuff to the common LLEXT code; I think it's a pity and I'm not yet convinced this is necessary.
If the llext_lookup_symbol()
function was exported in include/llext/llext_internal.h
, it should be possible to move the whole llext_riscv_find_sym_pcrel()
function to the arch-specific arch/riscv/core/elf.c
and only invoke it when those relocations are encountered.
But I am probably missing something big! 🙂
I can move the new |
I believe the RISC-V PSABI breaks one of the fundamental assumptions that were made when originally designing the API: the |
My original code used the assumption that the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of the new llext_text_start
but otherwise LGTM, thanks for your efforts!
I will try to build a regression test for this feature, similar to the one in #83198. I have not yet understood how to trigger the edge case from C reliably, so I will use another assembly listing for this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we now have the symbol table accessible to us from the loader, perhaps giving an index into the symbol table is enough rather than the elf_sym_t, sym_name, and sym_base_addr?
Those things could be obtained via accessors/helper functions.
ff5ce27
to
9e03dd1
Compare
I have added a commit with this test. I have verified manually that it fails with the changes from this PR not applied and that that it passes when the changes are applied. |
9e03dd1
to
3f6c93f
Compare
I will eliminate the |
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]>
Tests an edge case in the RISC-V PSABI: In the medany and the medlow code models, the compiler emits auipc/lui (U-type) and ld/sw (I-type/S-type) instruction pairs for accessing a non-local symbol. The U-type instruction sets the upper 20 bits, the I/S-type the lower 12. The U-type and I-type/S-type instruction pairs are often adjacent in code. This is also what the current llext architecture-specific relocations expect. However, this need not be the case - compilers can re-use the upper 20 bits set by the U-type instruction with multiple I/S-type instructions, which is a useful optimization for multiple loads/stores of or within the same symbol. This commit adds a unit test for this behavior, which currently fails for RISC-V. Signed-off-by: Eric Ackermann <[email protected]>
3f6c93f
to
1d23f53
Compare
Thanks for noticing, did not realize RISC-V was disabled in Twister! (why?) |
RISC-V tests currently do not run because of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments on the new functions in llext_internal.h
should be addressed IMO.
Not blocking since the latest changes were requested by Tom, but I feel that this will bring LLEXT to a more fragmented situation and I would like to avoid that if possible.
LOG_DBG("relocation %d:%d info 0x%zx (type %zd, sym %zd) offset %zd " | ||
"sym_name %s sym_type %d sym_bind %d sym_ndx %d", | ||
i, j, (size_t)rel.r_info, (size_t)ELF_R_TYPE(rel.r_info), | ||
(size_t)ELF_R_SYM(rel.r_info), (size_t)rel.r_offset, | ||
name, ELF_ST_TYPE(sym.st_info), | ||
ELF_ST_BIND(sym.st_info), sym.st_shndx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the following "writing relocation symbol" LOG_DBG
s have provided very useful information when trying to debug linker issues, and are now lost to arch-specific code.
IMHO losing this common part will make LLEXT more fragmented and difficult to debug in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can still be done but would require calling the accessors (cheap). The LOG_DBG and lookups can be wrapped in an ifdef CONFIG_LLEXT_LOG_LEVEL_DBG to avoid doing stuff we don't need to when its not debug logging.
I agree having these log messages can be invaluable in debugging relocation/linking issues. Please do try and maintain common log messages, if needed as noted here wrap a block in an ifdef.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have kept these log messages (at the expense of extra load calls when LOG_INF/LOG_DBG is enabled).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Patch set looks really nice now, thank you for the hard work!
1d23f53
to
55b0f45
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks awesome. Thank you for your efforts, much appreciated! 🙇
The RISC-V port of llext requires additional parameters for handling non-adjacent HI20/LO12 relocations in arch_elf_relocate(): the current extension (struct llext), the current extension loader (struct llext_loader), the current section header (elf_shdr_t) and the current symbol (elf_sym_t). This changes the signature of arch_elf_relocate accordingly. Signed-off-by: Eric Ackermann <[email protected]>
Currently, RISC-V's architecture-specific relocations assume that all relocations of type R_RISCV_PCREL_LO12_I and _S are processed immediately after the R_RISCV_PCREL_HI20 relocation that they share a relocation target with. While this is the case most of the time, the RISC-V PSABI specification does not guarantee that. This commit corrects this by determining the R_RISCV_PCREL_HI20 relocation based on the symbol value of the R_RISCV_PCREL_LO12 relocation, as specified in the PSABI. Signed-off-by: Eric Ackermann <[email protected]>
55b0f45
to
69baa40
Compare
I added an |
Currently, RISC-V's architecture-specific relocations assume that all relocations of type
R_RISCV_PCREL_LO12_I
and_S
are processed immediately after theR_RISCV_PCREL_HI20
relocation that they share a relocation target with. While this is the case most of the time, the RISC-V PSABI specification does not guarantee that. This commit corrects this by determining theR_RISCV_PCREL_HI20
relocation based on the symbol value of theR_RISCV_PCREL_LO12
relocation, as specified in the PSABI.