When linking and relocations are performed on the ELF object itself
with no copying, also global binding linking can break references.
Disable linking globally for such cases.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Now that section header cache is persistent, it can be used for
finding sections. Add a new function, similar to llext_find_section()
to use it and deprecate llext_find_section().
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Move cached section headers to struct llext from struct llext_loader
to preserve them after llext_load() returns.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Currently when building LLEXT for Xtensa we use the -fPIC compiler
option, but this cannot be used when using detached sections in
extensions. Add a Kconfig option to switch between the two
compilation modes and switch -fPIC off when building relocatable
(partially linked) ELF binaries.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When detached sections are used, STB_GLOBAL relocations also have to
be processed depending on the relocation type. This commit unified
STB_GLOBAL and STB_LOCAL flows by making them use the same relocation
type parser, adds support for R_XTENSA_GLOB_DAT and R_XTENSA_JMP_SLOT
type relocations on Xtensa and fixes STT_SECTION address calculation
for such sections.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Detached sections are used in situ without being copied to or
referenced from ext->mem[] LLEXT region arrays. Their caches must be
synchronised accordingly.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When CONFIG_LLEXT_STORAGE_WRITABLE is selected and .pre_located is
set, the BSS section is allocated by the user too, no need to
allocate it internally.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit introduces architecture-specific ELF relocations for RISC-V,
in accordance with the RISC-V PSABI specification:
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc
Also, the necessary compiler configurations for compiling LLEXT
extensions on RISC-V are added, and the llext tests are executed on
RISC-V targets.
Calling llext extensions from user threads in RISC-V is still
unsupported as of this commit.
Signed-off-by: Eric Ackermann <eric.ackermann@cispa.de>
Some LLEXT objects can include sections, that should not be merged
with other sections of the same type. E.g. when such sections should
be placed into locations, other than the default. Add support for
such sections.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
To simplify LLEXT loader parameter extension pass the whole
struct llext_load_param to final consumers instead of extracting
individual fields from it in the caller function.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
It's more common in the LLEXT code base to call elf_sym_t instances
"sym" and not "sym_tbl." Convert llext_link_plt() to follow this
convention.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Make llext_loaded_sect_ptr() a proper function to be able to call it
from platform LLEXT code.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This change adds a new configuration option, LLEXT_EXPORT_DEVICES, which
enables exporting all devices defined in the device tree to llext
extensions. When enabled, all devices are made available to extensions
via the standard DT_ / DEVICE_* macros.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
There's no reason for the .exported_sym data to always land at one end of a
data region; the order of sections depends on the whim of the compiler and
assembler.
Ignore overlaps between that region and other data regions.
Signed-off-by: Keith Packard <keithp@keithp.com>
Adds support for all relocation type produced by GCC
on AARCH64 platform using partial linking (-r flag) or
shared link (-fpic and -shared flag).
Signed-off-by: Adam Wojasinski <awojasinski@baylibre.com>
Replace use of 32-bit architecture macro to macro arch agnostic that
is resolved in compilation.
Signed-off-by: Adam Wojasinski <awojasinski@baylibre.com>
Some function pointers were being passed via `%p` to LOG_DBG, and this
was causing the following issues in SOF CI with the `sparse` checker:
subsys/llext/llext.c: error: arithmetics on pointers to functions
subsys/llext/llext.c: error: incompatible types for operation (+)
This patch fixes the issue by casting the function pointers to void*.
Also fix a misleading error message in `llext_get_fn_table()`.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Add missing braces to comply with MISRA C:2012 Rule 15.6 and
also following Zephyr's style guideline.
Signed-off-by: Pisit Sawangvonganan <pisit@ndrsolution.com>
llext_bringup() and llext_teardown() are intended to be used to call the
extension's own initialization and cleanup functions, respectively. They
are meant to be called by the developer after loading an extension and
before unloading it. The list of function pointers to be called is
obtained via the new llext_get_fn_table() syscall, so that they are
compatible with user mode.
llext_bootstrap() is intended to be used as the entry point for a thread
created to run an extension, in either user or kernel contexts. It will
call the extension's own initialization functions and then an additional
entry point in the same context (if desired). The same function can also
be called directly in the main thread, if only initialization is
required.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Load the .preinit_array, .init_array and .fini_array sections in ELF
files. These sections are arrays of function pointers that are filled by
the compiler with the addresses of functions that need to be called at
startup or termination by the loader, such as C++ constructors and
destructors.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This patch extends LLEXT shell commands with support for loading
LLEXT from a filesystem. Use of the command requires absolute path
to the llext file.
Example use:
`llext load_llext hello_world /lfs/hello_world.llext`
Signed-off-by: Adam Wojasinski <awojasinski@baylibre.com>
Introducing `llext_prepare()` and `llext_finalize()` APIs
that are invoked and the beginning and the end of the `llext_load()`
function.
The purpose of these functions is to bring possibility of initializing
loader before it is used and uninitialize or clean up when
it is no longer needed. Both functions are optional.
The buffer loader has been aligned to methods introduced in the patch.
Signed-off-by: Adam Wojasinski <awojasinski@baylibre.com>
By default, normal memory is set readable+writable and not executable.
Adjust those permissions according to each region:
LLEXT_MEM_TEXT --> K_MEM_PERM_EXEC
LLEXT_MEM_DATA, LLEXT_MEM_BSS --> K_MEM_PERM_RW
LLEXT_MEM_RODATA --> K_MEM_PERM_RO aka 0
This must be done only at the end of an LLEXT load operation as memory
needs to remain RW for reloc processing, etc.
And while at it, flush/invalidate the cache accordingly.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
When an LLEXT object uses symbols of another such object, it depends
on it. Such dependencies have to be tracked to prevent their
accidental unloading. Ideally we should be able to track arbitrary
numbers of such dependencies, but this is a bit difficult. In this
first implementation we use a fixed-size array, currently consisting
of 8 entries.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When deciding which sections to group together, only the low 3
section attribute bits are relevant, ignore the rest.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
LLEXT objects can also export symbols for use by other such objects.
That means, that when linking an LLEXT object we have to look for
unresolved symbols in previously loaded objects too.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Extensions could have used logging, when log processing is
deferred, the logging thread can run after the extension has
been unloaded and thereby access invalid memory addresses.
Make sure to flush all logs before unloading extensions.
Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add missing braces to comply with MISRA C:2012 Rule 15.6 and
also following Zephyr's style guideline.
Signed-off-by: Pisit Sawangvonganan <pisit@ndrsolution.com>
Review and improve comments in source code to better describe the API
and the functionality provided by the llext library.
No actual code changes are performed in this commit.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The term "section" has a very specific meaning in the ELF file format.
After 709b2e4 ("llext: automatically merge sections by type"), some of
the code that was originally dealing with ELF sections is now handling
"memory regions" made of multiple ELF sections of the same type.
Make sure to use the term "region" consistently in the code and
log messages to avoid confusion with the original ELF sections.
Notable exception to this is the "ldr->sect" array, which is actively
used outside Zephyr and will need to be phased out in the future.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This patch changes the error codes returned by the ELF subsystem to be
more consistent with the standard error descriptions. In particular:
- issues with the ELF file are now reported as -ENOEXEC;
- valid but unsupported edge cases are reported as -ENOTSUP;
- failures in searching for an entry are reported as -ENOENT.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
llext_load() included a check to ensure that the ELF file contains all
the necessary tables, but it was not functional. Add the missing check
and rename the variable to avoid confusion with the total section count.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
From https://mails.dpdk.org/archives/dev/2021-December/231212.html:
Downcasting a void* to struct aesni_gcm_session* caused the session
data to be treated as tainted. Removing the void* temporary variable
and adding a cast avoids this issue.
Try the same approach here to prevent the ldr->sect_hdrs pointer from
being treated as tainted.
May fix#74817.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The function llext_section_by_name() is used only in one place, and it
expects the caller to have the section headers cache available. This
cache is freed after the ELF file is loaded, so the function is not
usable in the context where it is called.
Remove the function and replace the call with a direct search in the
ELF file section headers array, as was done before 08eb314c35.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Currently, the code uses the section name to identify the target section
of a relocation. This is not reliable, as the section name is not
guaranteed to be in a specific format. Instead, use the sh_info field of
the relocation section header to identify the target section.
This is a tricky change, as it requires a workaround for the Xtensa
port, whose code path diverges here into the `link_plt` function and
ultimately different arch-specific code. Avoiding this divergence
will require additional refactorings.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The optimization in llext_load() to avoid using the generic path for
sections that are cached in memory was broken for two reasons:
- it was comparing an ELF section index to LLEXT_MEM_BSS, which is a
llext_mem enum, and
- it was using the wrong section address for the cached sections since
the "merged sections" feature was introduced in 709b2e44bf.
This patch fixes both issues using the new llext_loaded_sect_ptr()
helper function.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The recent changes to the loader code merged related sections together,
making sure the merged sections are self-coherent. This, however, did
not take into account that the original ELF sections are now a _subset_
of the merged section - and might not start from the beginning of the
merged section.
This patch converts the `sect_map` member of `struct llext_loader` to a
structure with two fields:
- mem_idx: the memory area index where the ELF section is mapped
- offset: the offset of the ELF section inside the memory area
The offset is calculated after all sections are merged and the final
groups are defined. This will allow the loader to correctly calculate
the address of symbols and relocations in the merged sections.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This patch sets the default value for LLEXT_STORAGE_WRITABLE to 'y' on
the Xtensa architecture. This is necessary because it does not currently
support the read-only mode for the LLEXT storage.
Make sure the default reflects this instead of asking the user to
manually set it.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The section headers are now available in the loader structure, so we can
use those directly instead of reading them from the ELF file every time.
This commit contains no logic changes; it removes all copies of the
header loading code and replaces them with direct access to the cached
section headers.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This change reads all section headers at once, instead of reading them
one by one. This is more efficient and allows to further simplify the
code downstream.
The section headers are directly accessed from the file buffer if the
llext_peek() function is supported by the loader. Otherwise, they are
read into a buffer allocated on the heap and used only during the
llext_load() function.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The do_llext_load function is responsible for loading an extension from a
file, and for this purpose it calls a number of functions that a) allocate
memory, and b) can fail. This creates the opportunity for memory leaks if
the error paths are not handled correctly.
This commit adds a comment at the beginning of the function to document
the memory management policy that has to be followed in this file:
cleanup is not performed in the error paths, and all memory is freed at
the end of the do_llext_load() function, both in the case of error and of
successful loading.
As an improvement, the symbol table is not freed if the LLEXT log level
is set to debug, so that it can be used, for example, to inspect the
symbols of the loaded extension.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The recent llext_map_sections() rework changed the way debug messages
are output so that the names of most skipped sections are not printed
at all. This makes debugging harder since the section names are useful
to identify the contents at a glance.
Also print a few additional fields from the section header, and use 0x
prefixes for hex numbers.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This commit moves ELF loading and linking code to separate files. This
is done to make the code more manageable and to make it easier to add
new features in the future.
No functional changes are introduced by this commit, except for a few
static functions now made public to allow this file split to occur.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Move all memory management code to a separate file, llext_mem.c, to
allow for better separation of concerns and to make the code more
readable.
No functional changes are introduced by this commit.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This patch moves the initial checks performed on the ELF file, that were
split between llext_load() and do_llext_load(), to the newly defined
llext_load_elf_data() function.
This way:
- only one function deals with ELF internal data checks;
- do_llext_load() is reduced to a list of tasks;
- llext_load() only focuses on the extension management.
One totally misplaced line initializing the number of symbols has been
moved to llext_count_export_syms().
No functional change except that the `struct llext` allocation may be
performed unnecessarily if the ELF file is not valid.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>