Skip to content

Commit fb6286d

Browse files
committed
llext: support relocatable objects
Additionally to shared objects, we can now also support relocatable objects (ld -r), which is beneficial for some toolchains. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 21ceaf5 commit fb6286d

File tree

5 files changed

+69
-28
lines changed

5 files changed

+69
-28
lines changed

scripts/llext_link_helper.py

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
# portable way to do that. Therefore we pass the linker path and all the command
88
# line parameters to this script and call the linker directly.
99

10+
import os
1011
import argparse
1112
import subprocess
1213
from elftools.elf.elffile import ELFFile
14+
import re
1315

1416
args = None
1517
def parse_args():
@@ -33,21 +35,53 @@ def main():
3335
elf = ELFFile(open(args.file, 'rb'))
3436

3537
text_addr = int(args.text_addr, 0)
38+
p = re.compile('(^lib|\.so$)')
39+
module = p.sub('', args.file)
3640

37-
text_offset = elf.get_section_by_name('.text').header.sh_offset
38-
rodata_offset = elf.get_section_by_name('.rodata').header.sh_offset
39-
data_offset = elf.get_section_by_name('.data').header.sh_offset
41+
if elf.get_section_by_name('.rodata') != None:
42+
# A shared object type image, it contains segments
43+
sections = ['.text', '.rodata', '.data', '.bss']
44+
alignment = [0x1000, 0x1000, 0x10, 0x1000]
45+
else:
46+
# A relocatable object, need to handle all sections separately
47+
sections = ['.text',
48+
f'._log_const.static.log_const_{module}_',
49+
'.static_uuids', '.z_init_APPLICATION90_0_', '.module',
50+
'.mod_buildinfo', '.data', '.trace_ctx', '.bss']
51+
alignment = [0x1000, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x1000]
4052

41-
upper = rodata_offset - text_offset + text_addr + 0xfff
42-
rodata_addr = upper - (upper % 0x1000)
53+
last_increment = 0
4354

44-
upper = data_offset - rodata_offset + rodata_addr + 0xf
45-
data_addr = upper - (upper % 0x10)
55+
command = [args.command]
56+
57+
for i in range(len(sections)):
58+
try:
59+
offset = elf.get_section_by_name(sections[i]).header.sh_offset
60+
size = elf.get_section_by_name(sections[i]).header.sh_size
61+
except:
62+
continue
63+
64+
if last_increment == 0:
65+
# first section must be .text and it must be successful
66+
if i != 0 or sections[i] != '.text':
67+
break
68+
69+
addresse = text_addr
70+
elif alignment[i] != 0:
71+
upper = offset + last_increment + alignment[i] - 1
72+
addresse = upper - (upper % alignment[i])
73+
else:
74+
addresse = offset + last_increment
75+
76+
last_increment = addresse - offset
77+
78+
if sections[i] == '.text':
79+
command.append(f'-Wl,-Ttext=0x{text_addr:x}')
80+
elif sections[i] == '.data':
81+
command.append(f'-Wl,-Tdata=0x{addresse:x}')
82+
else:
83+
command.append(f'-Wl,--section-start={sections[i]}=0x{addresse:x}')
4684

47-
command = [args.command,
48-
f'-Wl,-Ttext=0x{text_addr:x}',
49-
f'-Wl,--section-start=.rodata=0x{rodata_addr:x}',
50-
f'-Wl,-Tdata=0x{data_addr:x}']
5185
command.extend(args.params)
5286

5387
subprocess.run(command)

src/library_manager/lib_manager.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ static void lib_manager_update_sof_ctx(void *base_addr, uint32_t lib_id)
471471
{
472472
struct ext_library *_ext_lib = ext_lib_get();
473473
/* Never freed, will panic if fails */
474-
struct lib_manager_mod_ctx *ctx = rmalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM,
474+
struct lib_manager_mod_ctx *ctx = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM,
475475
sizeof(*ctx));
476476

477477
ctx->base_addr = base_addr;

src/library_manager/llext_manager.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ static void __sparse_cache *llext_manager_get_bss_address(uint32_t module_id,
142142
static int llext_manager_allocate_module_bss(uint32_t module_id,
143143
const struct sof_man_module *mod)
144144
{
145+
/* FIXME: just map .bss together with .data and simply memset(.bss, 0) */
145146
struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id);
146147
size_t bss_size = ctx->segment_size[SOF_MAN_SEGMENT_BSS];
147148
void __sparse_cache *va_base = llext_manager_get_bss_address(module_id, mod);
@@ -170,13 +171,14 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul
170171
uint32_t module_id, struct module_data *md, const void **buildinfo,
171172
const struct sof_man_module_manifest **mod_manifest)
172173
{
173-
size_t mod_size = desc->header.preload_page_count * PAGE_SZ;
174+
size_t mod_size = desc->header.preload_page_count * PAGE_SZ - 0x8000;
174175
/* FIXME: where does the module begin?? */
175176
struct llext_buf_loader ebl = LLEXT_BUF_LOADER((uint8_t *)desc -
176177
SOF_MAN_ELF_TEXT_OFFSET + 0x8000,
177178
mod_size);
178-
struct llext_load_param ldr_parm = {false};
179179
struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id);
180+
/* Identify if this is the first time loading this module */
181+
struct llext_load_param ldr_parm = {!ctx->segment_size[SOF_MAN_SEGMENT_TEXT]};
180182
int ret = llext_load(&ebl.loader, mod->name, &md->llext, &ldr_parm);
181183

182184
if (ret < 0)
@@ -199,8 +201,7 @@ static int llext_manager_link(struct sof_man_fw_desc *desc, struct sof_man_modul
199201
mod->segment[SOF_MAN_SEGMENT_RODATA].file_offset =
200202
(uintptr_t)md->llext->mem[LLEXT_MEM_RODATA] -
201203
(uintptr_t)desc + SOF_MAN_ELF_TEXT_OFFSET;
202-
ctx->segment_size[SOF_MAN_SEGMENT_RODATA] = mod_size -
203-
ebl.loader.sects[LLEXT_MEM_TEXT].sh_size;
204+
ctx->segment_size[SOF_MAN_SEGMENT_RODATA] = ebl.loader.prog_data_size;
204205

205206
tr_dbg(&lib_manager_tr, ".data: start: %#x size %#x offset %#x",
206207
mod->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr,

src/samples/audio/smart_amp_llext/CMakeLists.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,16 @@ target_compile_options(${MODULE} PRIVATE
5353
-save-temps -O2
5454
)
5555

56+
if("${ZEPHYR_TOOLCHAIN_VARIANT}" STREQUAL "zephyr")
5657
set(MODULE_LINKER_PARAMS -nostdlib -nodefaultlibs)
58+
set(EXTRA_LINKED_PARAMS -shared)
59+
set(COPY_CMD ${CMAKE_STRIP} -R .xt.* -o ${MODULE}_out.so ${MODULE}_llext.so)
60+
else()
61+
set(MODULE_LINKER_PARAMS -nostdlib -nodefaultlibs -r)
62+
set(EXTRA_LINKED_PARAMS)
63+
set(COPY_CMD ${CMAKE_OBJCOPY} -R .xt.* ${MODULE}_llext.so ${MODULE}_out.so)
64+
endif()
65+
5766
target_link_options(${MODULE} PRIVATE
5867
${MODULE_LINKER_PARAMS}
5968
)
@@ -62,9 +71,9 @@ add_custom_command(OUTPUT lib${MODULE}_out.so
6271
DEPENDS ${MODULE}
6372
COMMAND ${SOF_BASE}scripts/llext_link_helper.py
6473
-f lib${MODULE}.so -t "0xa06ca000" ${CMAKE_C_COMPILER} --
65-
${MODULE_LINKER_PARAMS} -shared -fPIC
66-
-o lib${MODULE}_llext.so $<TARGET_OBJECTS:${MODULE}>
67-
COMMAND ${CMAKE_STRIP} -R .xt.* -o lib${MODULE}_out.so lib${MODULE}_llext.so
74+
${MODULE_LINKER_PARAMS} ${EXTRA_LINKED_PARAMS} -fPIC
75+
-o ${MODULE}_llext.so $<TARGET_OBJECTS:${MODULE}>
76+
COMMAND ${COPY_CMD}
6877
COMMAND_EXPAND_LISTS
6978
)
7079

tools/rimage/src/elf_file.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,6 @@ static int elf_header_read(struct elf_file *elf)
132132
if (elf->header.ehsize < sizeof(Elf32_Ehdr))
133133
return elf_error(elf, "Invalid file header size.", EINVAL);
134134

135-
if (elf->header.phoff >= elf->file_size)
136-
return elf_error(elf, "Invalid program header file offset.", EINVAL);
137-
138-
if (elf->header.phentsize < sizeof(Elf32_Phdr))
139-
return elf_error(elf, "Invalid program header size.", EINVAL);
140-
141-
if (elf->header.phoff + elf->header.phnum * sizeof(Elf32_Phdr) > elf->file_size)
142-
return elf_error(elf, "Invalid number of program header entries.", EINVAL);
143-
144135
if (elf->header.shoff >= elf->file_size)
145136
return elf_error(elf, "Invalid section header file offset.", EINVAL);
146137

@@ -250,6 +241,12 @@ static int elf_program_headers_read(struct elf_file *elf)
250241
int i, ret;
251242
size_t offset, count;
252243

244+
if (!elf->header.phnum) {
245+
elf->programs = NULL;
246+
elf->programs_count = 0;
247+
return 0;
248+
}
249+
253250
elf->programs = calloc(elf->header.phnum, sizeof(Elf32_Phdr));
254251
if (!elf->programs)
255252
return elf_error(elf, "Cannot allocate program array.", ENOMEM);

0 commit comments

Comments
 (0)