llext: Fix a bug in section linking
When relocating section symbol addresses the value where the relocation is to be written is an offset into the section to load. Simply rewriting it with the section address is not enough, we need to write the address of the section with the offset into it. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
parent
7e8953ed7f
commit
c678f25bc1
|
@ -61,60 +61,89 @@ On a host machine with the zephyr sdk setup and the arm toolchain in PATH
|
|||
.. code-block:: console
|
||||
|
||||
$ arm-zephyr-eabi-gcc -mlong-calls -mthumb -c -o hello_world.elf tests/subsys/llext/hello_world/hello_world.c
|
||||
$ arm-zephyr-eabi-objdump -x -t hello_world.elf
|
||||
$ arm-zephyr-eabi-objdump -r -d -x hello_world.elf
|
||||
|
||||
hello_world.elf: file format elf32-littlearm
|
||||
hello_world.elf
|
||||
architecture: armv4t, flags 0x00000011:
|
||||
HAS_RELOC, HAS_SYMS
|
||||
start address 0x00000000
|
||||
private flags = 0x5000000: [Version5 EABI]
|
||||
hello_world.elf: file format elf32-littlearm
|
||||
hello_world.elf
|
||||
architecture: armv4t, flags 0x00000011:
|
||||
HAS_RELOC, HAS_SYMS
|
||||
start address 0x00000000
|
||||
private flags = 0x5000000: [Version5 EABI]
|
||||
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn
|
||||
0 .text 00000024 00000000 00000000 00000034 2**2
|
||||
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||
1 .data 00000000 00000000 00000000 00000058 2**0
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
2 .bss 00000000 00000000 00000000 00000058 2**0
|
||||
ALLOC
|
||||
3 .rodata 0000000d 00000000 00000000 00000058 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
4 .comment 00000021 00000000 00000000 00000065 2**0
|
||||
CONTENTS, READONLY
|
||||
5 .ARM.attributes 0000002a 00000000 00000000 00000086 2**0
|
||||
CONTENTS, READONLY
|
||||
arm-zephyr-eabi-objdump: hello_world.elf: not a dynamic object
|
||||
SYMBOL TABLE:
|
||||
00000000 l df *ABS* 00000000 hello_world.c
|
||||
00000000 l d .text 00000000 .text
|
||||
00000000 l d .data 00000000 .data
|
||||
00000000 l d .bss 00000000 .bss
|
||||
00000000 l d .rodata 00000000 .rodata
|
||||
00000000 l d .comment 00000000 .comment
|
||||
00000000 l d .ARM.attributes 00000000 .ARM.attributes
|
||||
00000000 g F .text 00000020 hello_world
|
||||
00000000 *UND* 00000000 printk
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn
|
||||
0 .text 00000038 00000000 00000000 00000034 2**2
|
||||
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
|
||||
1 .data 00000000 00000000 00000000 0000006c 2**0
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
2 .bss 00000000 00000000 00000000 0000006c 2**0
|
||||
ALLOC
|
||||
3 .rodata 00000025 00000000 00000000 0000006c 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
4 .comment 00000021 00000000 00000000 00000091 2**0
|
||||
CONTENTS, READONLY
|
||||
5 .ARM.attributes 0000002a 00000000 00000000 000000b2 2**0
|
||||
CONTENTS, READONLY
|
||||
SYMBOL TABLE:
|
||||
00000000 l df *ABS* 00000000 hello_world.c
|
||||
00000000 l d .text 00000000 .text
|
||||
00000000 l d .data 00000000 .data
|
||||
00000000 l d .bss 00000000 .bss
|
||||
00000000 l d .rodata 00000000 .rodata
|
||||
00000000 l O .rodata 00000004 number
|
||||
00000000 l d .comment 00000000 .comment
|
||||
00000000 l d .ARM.attributes 00000000 .ARM.attributes
|
||||
00000000 g F .text 00000034 hello_world
|
||||
00000000 *UND* 00000000 printk
|
||||
|
||||
|
||||
RELOCATION RECORDS FOR [.text]:
|
||||
OFFSET TYPE VALUE
|
||||
00000018 R_ARM_ABS32 .rodata
|
||||
0000001c R_ARM_ABS32 printk
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
00000000 <hello_world>:
|
||||
0: b580 push {r7, lr}
|
||||
2: af00 add r7, sp, #0
|
||||
4: 4b08 ldr r3, [pc, #32] ; (28 <hello_world+0x28>)
|
||||
6: 0018 movs r0, r3
|
||||
8: 4b08 ldr r3, [pc, #32] ; (2c <hello_world+0x2c>)
|
||||
a: f000 f813 bl 34 <hello_world+0x34>
|
||||
e: 222a movs r2, #42 ; 0x2a
|
||||
10: 4b07 ldr r3, [pc, #28] ; (30 <hello_world+0x30>)
|
||||
12: 0011 movs r1, r2
|
||||
14: 0018 movs r0, r3
|
||||
16: 4b05 ldr r3, [pc, #20] ; (2c <hello_world+0x2c>)
|
||||
18: f000 f80c bl 34 <hello_world+0x34>
|
||||
1c: 46c0 nop ; (mov r8, r8)
|
||||
1e: 46bd mov sp, r7
|
||||
20: bc80 pop {r7}
|
||||
22: bc01 pop {r0}
|
||||
24: 4700 bx r0
|
||||
26: 46c0 nop ; (mov r8, r8)
|
||||
28: 00000004 .word 0x00000004
|
||||
28: R_ARM_ABS32 .rodata
|
||||
2c: 00000000 .word 0x00000000
|
||||
2c: R_ARM_ABS32 printk
|
||||
30: 00000014 .word 0x00000014
|
||||
30: R_ARM_ABS32 .rodata
|
||||
34: 4718 bx r3
|
||||
36: 46c0 nop ; (mov r8, r8)
|
||||
|
||||
$ xxd -p hello_world.elf | tr -d '\n'
|
||||
|
||||
|
||||
The resulting hex string can be used to load the extension.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000180200000000000534000000000028000b000a0080b500af044b1800044b00f009f8c046bd4680bc01bc004700000000000000001847c04668656c6c6f20776f726c640a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff00000000000000000000000003000100000000000000000000000000030003000000000000000000000000000300040000000000000000000000000003000500090000000000000000000000000005000c000000000000000000000000000100090000001800000000000000000001000c00000020000000000000000000010000000000000000000000000003000600000000000000000000000000030007000f0000000100000020000000120001001b0000000000000000000000100000000068656c6c6f2e630024640024740068656c6c6f5f776f726c64007072696e746b00000018000000020500001c000000020d0000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000024000000000000000000000004000000000000001b000000090000004000000000000000b40100001000000008000000010000000400000008000000250000000100000003000000000000005800000000000000000000000000000001000000000000002b00000008000000030000000000000058000000000000000000000000000000010000000000000030000000010000000200000000000000580000000d000000000000000000000004000000000000003800000001000000300000000000000065000000210000000000000000000000010000000100000041000000030000700000000000000000860000002a0000000000000000000000010000000000000001000000020000000000000000000000b0000000e0000000090000000c00000004000000100000000900000003000000000000000000000090010000220000000000000000000000010000000000000011000000030000000000000000000000c40100005100000000000000000000000100000000000000
|
||||
uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000
|
||||
|
||||
This extension can then be seen in the list of loaded extensions (`list`), its symbols printed (`list_symbols`), and the hello_world
|
||||
function which the extension exports can be called and run (`call_fn`).
|
||||
This extension can then be seen in the list of loaded extensions (`list`), its symbols printed
|
||||
(`list_symbols`), and the hello_world function which the extension exports can be called and
|
||||
run (`call_fn`).
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
uart:~$ llext call_fn hello_world hello_world
|
||||
hello world
|
||||
A number is 42
|
||||
|
||||
In this sample there are 3 absolute (R_ARM_ABS32) relocations, 2 of which are meant to hold addresses into the .rodata sections where the strings are located. A third is an address of where the printk function (symbol) can be found. At load time llext replaces the values in the .text section with real memory addresses so that printk works as expected with the strings included in the hello world sample.
|
||||
|
|
|
@ -508,6 +508,8 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext)
|
|||
|
||||
uintptr_t link_addr, op_loc, op_code;
|
||||
|
||||
op_loc = loc + rel.r_offset;
|
||||
|
||||
/* If symbol is undefined, then we need to look it up */
|
||||
if (sym.st_shndx == SHN_UNDEF) {
|
||||
link_addr = (uintptr_t)llext_find_sym(NULL, name);
|
||||
|
@ -525,7 +527,10 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext)
|
|||
name, link_addr, op_code);
|
||||
}
|
||||
} else if (ELF_ST_TYPE(sym.st_info) == STT_SECTION) {
|
||||
link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]];
|
||||
/* Current relocation location holds an offset into the section */
|
||||
link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]]
|
||||
+ sym.st_value
|
||||
+ *((uintptr_t *)op_loc);
|
||||
|
||||
LOG_INF("found section symbol %s addr 0x%lx", name, link_addr);
|
||||
} else {
|
||||
|
@ -533,8 +538,6 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext)
|
|||
continue;
|
||||
}
|
||||
|
||||
op_loc = loc + rel.r_offset;
|
||||
|
||||
LOG_INF("relocating (linking) symbol %s type %d binding %d ndx %d offset "
|
||||
"%d link section %d",
|
||||
name, ELF_ST_TYPE(sym.st_info), ELF_ST_BIND(sym.st_info),
|
||||
|
|
|
@ -11,15 +11,14 @@
|
|||
* a function.
|
||||
*/
|
||||
|
||||
/* Various build options should be documented here to generate the test elf for
|
||||
* each architecture.
|
||||
*
|
||||
* armv7-thumb: -mlong-call -mthumb -c -o hello_world_armv7_thumb.elf hello_world.c
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
extern void printk(char *fmt, ...);
|
||||
|
||||
static const uint32_t number = 42;
|
||||
|
||||
extern void hello_world(void)
|
||||
{
|
||||
printk("hello world\n");
|
||||
printk("A number is %lu\n", number);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue