llext: Fix off-by-one in RISC-V truncation check

The RISC-V architecture-specific relocations need to check whether
each required relocation can fit into the modified instruction's
immediate. All immediates in RISC-V are encoded as two's complement.
The current truncation check has an off-by-one error for checking
the maximum negative distance, as two's complement encoding can
represent a negative value that is the maximum positive value plus
one, causing LLEXT to refuse loading valid code.
This commit adds an additional condition to the check that fixes
the aforementioned issue.

Signed-off-by: Eric Ackermann <eric.ackermann@cispa.de>
This commit is contained in:
Eric Ackermann 2024-12-19 09:48:34 +01:00 committed by Benjamin Cabé
commit 2d3390f866

View file

@ -43,6 +43,13 @@ LOG_MODULE_REGISTER(elf, CONFIG_LLEXT_LOG_LEVEL);
static inline int riscv_relocation_fits(long long jump_target, long long max_distance,
elf_word reloc_type)
{
/*
* two's complement encoding
* e.g., [-128=0b10000000, 127=0b01111111] encodable with 8 bits
*/
if (jump_target < 0) {
max_distance++;
}
if (llabs(jump_target) > max_distance) {
LOG_ERR("%lld byte relocation is not possible for type %" PRIu64 " (max %lld)!",
jump_target, (uint64_t)reloc_type, max_distance);