Skip to content

Commit c678f25

Browse files
teburdfabiobaltieri
authored andcommitted
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 <[email protected]>
1 parent 7e8953e commit c678f25

File tree

3 files changed

+83
-52
lines changed

3 files changed

+83
-52
lines changed

samples/subsys/llext/shell_loader/README.rst

+73-44
Original file line numberDiff line numberDiff line change
@@ -61,60 +61,89 @@ On a host machine with the zephyr sdk setup and the arm toolchain in PATH
6161
.. code-block:: console
6262
6363
$ arm-zephyr-eabi-gcc -mlong-calls -mthumb -c -o hello_world.elf tests/subsys/llext/hello_world/hello_world.c
64-
$ arm-zephyr-eabi-objdump -x -t hello_world.elf
65-
66-
hello_world.elf: file format elf32-littlearm
67-
hello_world.elf
68-
architecture: armv4t, flags 0x00000011:
69-
HAS_RELOC, HAS_SYMS
70-
start address 0x00000000
71-
private flags = 0x5000000: [Version5 EABI]
72-
73-
Sections:
74-
Idx Name Size VMA LMA File off Algn
75-
0 .text 00000024 00000000 00000000 00000034 2**2
76-
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
77-
1 .data 00000000 00000000 00000000 00000058 2**0
78-
CONTENTS, ALLOC, LOAD, DATA
79-
2 .bss 00000000 00000000 00000000 00000058 2**0
80-
ALLOC
81-
3 .rodata 0000000d 00000000 00000000 00000058 2**2
82-
CONTENTS, ALLOC, LOAD, READONLY, DATA
83-
4 .comment 00000021 00000000 00000000 00000065 2**0
84-
CONTENTS, READONLY
85-
5 .ARM.attributes 0000002a 00000000 00000000 00000086 2**0
86-
CONTENTS, READONLY
87-
arm-zephyr-eabi-objdump: hello_world.elf: not a dynamic object
88-
SYMBOL TABLE:
89-
00000000 l df *ABS* 00000000 hello_world.c
90-
00000000 l d .text 00000000 .text
91-
00000000 l d .data 00000000 .data
92-
00000000 l d .bss 00000000 .bss
93-
00000000 l d .rodata 00000000 .rodata
94-
00000000 l d .comment 00000000 .comment
95-
00000000 l d .ARM.attributes 00000000 .ARM.attributes
96-
00000000 g F .text 00000020 hello_world
97-
00000000 *UND* 00000000 printk
98-
99-
100-
RELOCATION RECORDS FOR [.text]:
101-
OFFSET TYPE VALUE
102-
00000018 R_ARM_ABS32 .rodata
103-
0000001c R_ARM_ABS32 printk
64+
$ arm-zephyr-eabi-objdump -r -d -x hello_world.elf
65+
66+
hello_world.elf: file format elf32-littlearm
67+
hello_world.elf
68+
architecture: armv4t, flags 0x00000011:
69+
HAS_RELOC, HAS_SYMS
70+
start address 0x00000000
71+
private flags = 0x5000000: [Version5 EABI]
72+
73+
Sections:
74+
Idx Name Size VMA LMA File off Algn
75+
0 .text 00000038 00000000 00000000 00000034 2**2
76+
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
77+
1 .data 00000000 00000000 00000000 0000006c 2**0
78+
CONTENTS, ALLOC, LOAD, DATA
79+
2 .bss 00000000 00000000 00000000 0000006c 2**0
80+
ALLOC
81+
3 .rodata 00000025 00000000 00000000 0000006c 2**2
82+
CONTENTS, ALLOC, LOAD, READONLY, DATA
83+
4 .comment 00000021 00000000 00000000 00000091 2**0
84+
CONTENTS, READONLY
85+
5 .ARM.attributes 0000002a 00000000 00000000 000000b2 2**0
86+
CONTENTS, READONLY
87+
SYMBOL TABLE:
88+
00000000 l df *ABS* 00000000 hello_world.c
89+
00000000 l d .text 00000000 .text
90+
00000000 l d .data 00000000 .data
91+
00000000 l d .bss 00000000 .bss
92+
00000000 l d .rodata 00000000 .rodata
93+
00000000 l O .rodata 00000004 number
94+
00000000 l d .comment 00000000 .comment
95+
00000000 l d .ARM.attributes 00000000 .ARM.attributes
96+
00000000 g F .text 00000034 hello_world
97+
00000000 *UND* 00000000 printk
98+
99+
100+
101+
Disassembly of section .text:
102+
103+
00000000 <hello_world>:
104+
0: b580 push {r7, lr}
105+
2: af00 add r7, sp, #0
106+
4: 4b08 ldr r3, [pc, #32] ; (28 <hello_world+0x28>)
107+
6: 0018 movs r0, r3
108+
8: 4b08 ldr r3, [pc, #32] ; (2c <hello_world+0x2c>)
109+
a: f000 f813 bl 34 <hello_world+0x34>
110+
e: 222a movs r2, #42 ; 0x2a
111+
10: 4b07 ldr r3, [pc, #28] ; (30 <hello_world+0x30>)
112+
12: 0011 movs r1, r2
113+
14: 0018 movs r0, r3
114+
16: 4b05 ldr r3, [pc, #20] ; (2c <hello_world+0x2c>)
115+
18: f000 f80c bl 34 <hello_world+0x34>
116+
1c: 46c0 nop ; (mov r8, r8)
117+
1e: 46bd mov sp, r7
118+
20: bc80 pop {r7}
119+
22: bc01 pop {r0}
120+
24: 4700 bx r0
121+
26: 46c0 nop ; (mov r8, r8)
122+
28: 00000004 .word 0x00000004
123+
28: R_ARM_ABS32 .rodata
124+
2c: 00000000 .word 0x00000000
125+
2c: R_ARM_ABS32 printk
126+
30: 00000014 .word 0x00000014
127+
30: R_ARM_ABS32 .rodata
128+
34: 4718 bx r3
129+
36: 46c0 nop ; (mov r8, r8)
104130
105131
$ xxd -p hello_world.elf | tr -d '\n'
106132
107-
108133
The resulting hex string can be used to load the extension.
109134

110135
.. code-block:: console
111136
112-
uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000180200000000000534000000000028000b000a0080b500af044b1800044b00f009f8c046bd4680bc01bc004700000000000000001847c04668656c6c6f20776f726c640a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff00000000000000000000000003000100000000000000000000000000030003000000000000000000000000000300040000000000000000000000000003000500090000000000000000000000000005000c000000000000000000000000000100090000001800000000000000000001000c00000020000000000000000000010000000000000000000000000003000600000000000000000000000000030007000f0000000100000020000000120001001b0000000000000000000000100000000068656c6c6f2e630024640024740068656c6c6f5f776f726c64007072696e746b00000018000000020500001c000000020d0000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000024000000000000000000000004000000000000001b000000090000004000000000000000b40100001000000008000000010000000400000008000000250000000100000003000000000000005800000000000000000000000000000001000000000000002b00000008000000030000000000000058000000000000000000000000000000010000000000000030000000010000000200000000000000580000000d000000000000000000000004000000000000003800000001000000300000000000000065000000210000000000000000000000010000000100000041000000030000700000000000000000860000002a0000000000000000000000010000000000000001000000020000000000000000000000b0000000e0000000090000000c00000004000000100000000900000003000000000000000000000090010000220000000000000000000000010000000000000011000000030000000000000000000000c40100005100000000000000000000000100000000000000
137+
uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000
113138
114-
This extension can then be seen in the list of loaded extensions (`list`), its symbols printed (`list_symbols`), and the hello_world
115-
function which the extension exports can be called and run (`call_fn`).
139+
This extension can then be seen in the list of loaded extensions (`list`), its symbols printed
140+
(`list_symbols`), and the hello_world function which the extension exports can be called and
141+
run (`call_fn`).
116142

117143
.. code-block:: console
118144
119145
uart:~$ llext call_fn hello_world hello_world
120146
hello world
147+
A number is 42
148+
149+
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.

subsys/llext/llext.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,8 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext)
508508

509509
uintptr_t link_addr, op_loc, op_code;
510510

511+
op_loc = loc + rel.r_offset;
512+
511513
/* If symbol is undefined, then we need to look it up */
512514
if (sym.st_shndx == SHN_UNDEF) {
513515
link_addr = (uintptr_t)llext_find_sym(NULL, name);
@@ -525,16 +527,17 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext)
525527
name, link_addr, op_code);
526528
}
527529
} else if (ELF_ST_TYPE(sym.st_info) == STT_SECTION) {
528-
link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]];
530+
/* Current relocation location holds an offset into the section */
531+
link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]]
532+
+ sym.st_value
533+
+ *((uintptr_t *)op_loc);
529534

530535
LOG_INF("found section symbol %s addr 0x%lx", name, link_addr);
531536
} else {
532537
/* Nothing to relocate here */
533538
continue;
534539
}
535540

536-
op_loc = loc + rel.r_offset;
537-
538541
LOG_INF("relocating (linking) symbol %s type %d binding %d ndx %d offset "
539542
"%d link section %d",
540543
name, ELF_ST_TYPE(sym.st_info), ELF_ST_BIND(sym.st_info),

tests/subsys/llext/hello_world/hello_world.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@
1111
* a function.
1212
*/
1313

14-
/* Various build options should be documented here to generate the test elf for
15-
* each architecture.
16-
*
17-
* armv7-thumb: -mlong-call -mthumb -c -o hello_world_armv7_thumb.elf hello_world.c
18-
*/
14+
#include <stdint.h>
1915

2016
extern void printk(char *fmt, ...);
2117

18+
static const uint32_t number = 42;
19+
2220
extern void hello_world(void)
2321
{
2422
printk("hello world\n");
23+
printk("A number is %lu\n", number);
2524
}

0 commit comments

Comments
 (0)