Skip to content

Commit

Permalink
LLEXT: add support for detached executable sections
Browse files Browse the repository at this point in the history
With this commit functions can be marked to be placed in custom
sections, e.g. by adding __attribute__((section(".text.dram"))) to
them. Those sections will then become "detached," i.e. they won't be
linked into the main address space of the module. Instead they will
be linked at a low address, after which Zephyr LLEXT linked will
prepare them to be used at their original location, e.g. in DRAM.
This commit modifies the SOF LLEXT link helper to use low addresses
for linking of such sections.

Signed-off-by: Guennadi Liakhovetski <[email protected]>
  • Loading branch information
lyakh authored and lgirdwood committed Nov 27, 2024
1 parent 362a43d commit 4a59b2a
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions scripts/llext_link_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,12 @@ def main():

command = [args.command]

executable = []
writable = []
readonly = []

text_found = False

elf = ELFFile(open(args.file, 'rb'))

# Create an object file with sections grouped by their properties,
Expand All @@ -102,13 +105,13 @@ def main():
# In general additional executable sections are possible, e.g.
# .init. In the future support for arbitrary such sections can be
# added, similar to writable and read-only data below.
if s_name != '.text':
print(f"Warning! Non-standard executable section {s_name}")

text_addr = max_alignment(text_addr, 0x1000, s_alignment)
text_size = s_size

command.append(f'-Wl,-Ttext=0x{text_addr:x}')
if s_name == '.text':
text_found = True
text_addr = max_alignment(text_addr, 0x1000, s_alignment)
text_size = s_size
command.append(f'-Wl,-Ttext=0x{text_addr:x}')
else:
executable.append(section)

continue

Expand All @@ -122,6 +125,36 @@ def main():
# .rodata or other read-only sections
readonly.append(section)

if not text_found:
raise RuntimeError('No .text section found in the object file')

# The original LLEXT support in SOF linked all LLEXT modules with pre-
# calculated addresses. Such modules can only be used at those exact
# addresses, so we map memory buffers for such modules to those
# addresses and copy them there.
# Now we also need to be able to re-link parts of modules at run-time to
# run at arbitrary memory locations. One of the use-cases is running
# parts of the module directly in DRAM - sacrificing performance but
# saving scarce SRAM. We achieve this by placing non-performance
# critical functions in a .text.dram ELF section. When compiling and
# linking such functions, an additional .literal.dram section is
# automatically created. Note, that for some reason the compiler also
# marks that section as executable.
# This script links those sections at address 0. We could hard-code
# section names, but so far we choose to only link .text the "original"
# way and all other executable sections we link at 0.
exe_addr = 0

for section in executable:
s_alignment = section.header['sh_addralign']
s_name = section.name

exe_addr = align_up(exe_addr, s_alignment)

command.append(f'-Wl,--section-start={s_name}=0x{exe_addr:x}')

exe_addr += section.header['sh_size']

start_addr = align_up(text_addr + text_size, 0x1000)

for section in readonly:
Expand Down

0 comments on commit 4a59b2a

Please sign in to comment.