Returned values are copies, so trying to "const" return values cannot
have any effect.
Fixes the following compiler warning:
```
llext.h:165: warning: type qualifiers ignored on function return type
```
Fixes commit 41e0a4a371 ("llext: Linkable loadable extensions")
Signed-off-by: Marc Herbert <marc.herbert@intel.com>
This commit adds support for building relocatable (partially linked)
ELF files as the binary object type for the llext subsystem.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Add a new Kconfig option to select the binary object type for the llext
subsystem. This will allow to fully decouple the architecture type from
the kind of binary object that is expected by the loader.
The defaults have been chosen to match the current behavior of the ARM
and Xtensa architectures, but developers can now more easily experiment
with other object types.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Adds support for all relocation type produced by GCC
on ARM platform using partial linking (-r flag) or
shared link (-fpic and -shared flag).
Signed-off-by: Cedric Lescop <cedric.lescop@se.com>
Some toolchains cannot create shared objects for Xtensa, with them we
have to use relocatable objects. Add support for them to llext.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
In addition to flushing the dcache, to ensure that the new code is
actually read by the CPU when loading an extension, the icache must
be invalidated as well.
Without this, some tests are failing in hardware because the CPU is
executing stale code from its instruction cache.
Fixes#70906 on arduino_giga_r1/stm32h747xx/m7.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
commit 67bb6db3f8 ("syscall: Export all emitted syscalls, enabling
them for extensions") exports all emitted syscalls, however, it does
that only for the `z_mrsh` symbols, effectively only available for
userspace. If an extension running at kernel level tries to use a
syscall, it will fail to load.
This patch fixes that by exposing the `z_impl` symbols instead. However,
this is not as straightforward as the `z_mrsh` ones. As, in their
signatures, they can basically contain any type, it's not just a matter
of emitting `EXPORT_SYMBOL(z_impl_<syscall>)`, as the compiler will
complain about the undefined types. Here, there are a few approaches.
One of them is to have the `EXPORT_SYMBOL` being generated on the same
files where the syscall is implemented - injecting it there would allow
it to access all known symbols. But changing a lot of files is
undesirable, and it was one of the nice points of first patch.
Another one would be to reconstruct - or simply use the absolute path -
for the includes where the syscalls are defined. Reconstruct the paths
seems fragile and I'm not sure using absolute paths is portable.
Finally, the approach used in this patch is to declare, on a different
generated file, all `z_impl_` symbols as `void *` - after all, only the
address (and the name) to the function is relevant to EXPORT_SYMBOL. By
living in an compilation unit that doesn't include any header which
would expose any of the syscalls, there shouldn't be any conflicts. And
to account for the possibility that a syscall is not compiled - due
being configured out via Kconfig - all those symbols are also weak
aliases to a pointer to NULL. This file is then included in
`llext_export.c` (which should naturally not include any conflicting
header).
Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
The opval argument of arch_elf_relocate() was modified by
adding the value stored at opaddr before passing it to
arch_elf_relocate(). This presumed that the addend would
always be stored as a raw value at opaddr, which is not the
case for all relocation types.
This PR modifies opval to be the absolute address of opval,
and moves the addition of the addend from llext_link_plt()
to the implementation of arch_elf_relocate().
Signed-off-by: Bjarki Arge Andreasen <bjarki@arge-andreasen.me>
Fixes commit a9a82d557c ("llext: use elf_rela_t instead of elf_rel_t")
Also switch sign of (unused?) `r_addend` to unsigned.
https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.reloc.html
Issue found thanks to the following warnings when compiling in 64bits:
```
/__w/zephyr/zephyr/include/zephyr/llext/elf.h:349:29: error:
right shift count >= width of type [-Werror=shift-count-overflow]
349 | #define ELF64_R_SYM(i) ((i) >> 32)
```
The name `elf64_word` was admittedly confusing.
Signed-off-by: Marc Herbert <marc.herbert@intel.com>
Note `elf64_addr` and friends are defined as uint64_t which is defined
as `long long unsigned` which is for some reason different from
`size_t`. So they all require a cast.
Signed-off-by: Marc Herbert <marc.herbert@intel.com>
Sets up memory partitions and allows for the partitions to be added to a
memory domain after loading an extension. This allows for applying
memory protection attributes to all of the needed memory regions an
extension requires to execute code correctly.
Currently only works when usermode is enabled as otherwise memory
protection APIs are unavailable.
Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
clangd like to automatically add include directives, this one slipped by
and made its way in the tree. Remove it.
Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
The only difference in the two enums are some entries related to
relocation sections. However, these entries are not used in the
code, so they can be safely removed, along with the mapping function.
Use LLEXT_MEM_* to avoid confusion with low-level "section" names.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Targets that have a data cache must enable CACHE_MANAGEMENT to allow the
llext API to flush it when loading an extension. This patch forces the
flag to be enabled when the target has a data cache.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
The arch_* functions are architecture-specific and may not be defined in
all targets. Use the global alias defined in the Cache API instead.
Fixes#66382.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Dynamic command handlers should be fully initialized to avoid undefined
behavior. Also, fix the number of arguments required by each command,
since llext_call_fn requires both the llext and the name of the function
to be called.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
On architectures that have separate data and instruction caches, such as
the Cortex-M7, it is required to flush the reloc changes to the actual RAM
storage before trying to execute any code from the newly loaded llext.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
It is not safe to assume that on entry to llext_load, *ext contains
either NULL or a previous reference to the same ext being loaded. For
example, the shell sample was passing an uninitialized value.
Initialize *ext from a search of the llext by name. If NULL, it is the
first instance of this llext (and on load error, it stays that way). If
not NULL, increment use count and return.
Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
When using the LLEXT buffer loader we now avoid copying extensions
from storage to allocated memory by pointing directly into the stored
image. We then also perform linking and relocation in that memory,
which modifies its contents. However, this is impossible if that
storage is read-only. Add a Kconfig flag to distinguish between
writable and read-only storage types. Also use that flag to decide,
whether the extension image in test_llext_simple.c should be defined
as const or not.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
a new llext object is completely initialised with zeros after
allocation, no need to additionally set members of an embedded into
it array to NULL.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
llext_list() is an exported function that returns a pointer to the
llext internal extension list. That list should only be accessible
directly inside llext, while holding a lock. Remove the function.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
The llext list should be internal to llext.c, remove its scanning
from shell.c, export a function for that instead.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Use an element size explicitly when calculating the array size and
use the calculated size for memset().
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Extensions should be able to selectively export their global symbols.
Add a LL_EXTENSION_SYMBOL() macro for that. Change the present
.sym_tab to be a temporary symbol table of all global symbols in an
extensions, used only during linking for internal purposes. Add a new
.exp_tab symbol table to store symbols, exported by an extension
permanently.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
If a function fails it should release all the resources it has
managed to acquire. Fix llext_load() to free memory that it has
allocated in case of an error.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Extend the llext_load() / llext_unload() API to let it be called
repeatedly for the same extension to increment or decrement its
reference counter respectively. We use a mutex to protect the counter
and make both llext_load() and llext_unload() return the use-count to
let the caller identify when the first loading and the last unloading
took place.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Loadable modules can contain global (not "static") functions, even if
they aren't exported for use by other modules, e.g. when a module is
built from multiple .c files. Such functions are then also included
in link tables and have to be re-linked.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
llext_seek(), llext_read() and llext_peek() are needed outside of the
extension code too, move them to a header.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Some applications can decide to link their loadable objects for
exactly the same addresses, where they will be loaded. In those cases
local relocations aren't needed any more and can in fact break the
object if applied while the object is in a temporary storage. Add a
parameter to skip such local relocations.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Export some symbols for loadable modules. Also add an
EXPORT_SYSCALL() helper macro for exporting system calls by their
official names.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Applications can use custom ELF sections for their own purposes, add
a function for finding them.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add support for relocating local symbols, as specified in the
.rela.dyn section.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add support for linking PIC shared object, which only require
linking, using their PLT and GOT lists and don't need any relocation
otherwise.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Symbopl tables of ELF objects of type ET_REL contain offsets instead
of addresses as for ET_DYN.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
A common pattern is used throughout llext.c:
ext->mem[ldr->sect_map[sym.st_shndx]]
where ldr->sect_map[sym.st_shndx] actually contains indices from
enum llext_section but ext->mem[] is indexed, using enum llext_mem
values. Fix this by changing ldr->sect_map[] to actually contain
enum llext_mem values.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
The symbol count in struct llext_loader is redundant, we already have
one in struct llext_symtable, accessible via struct llext. Remove the
redundant copy.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Simplify llext_copy_symbols() by using a local variable to store a
pointer.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
str_cnt in llext_find_tables() is actually used to count sections,
rename it to better match that usage.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Use .sh_entsize instead of sizeof(elf_rel_t) to make code suitable
for both REL and RELA types.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Several cosmetic changes with no change in functionality:
The pos variable in multiple functions is used as a loop variable -
it's initialised before the loop starts and then it's incremented for
each loop iteration. Move it to the loop header for readability.
"return ret" is clearer than "goto out" where the "out" label does
nothing but "out: return ret" because one sees immediately that the
function is terminated at that location with no further actions
without the need to check the "out" label.
k_heap_free(heap, NULL) is valid, no need to check the address to be
freed for NULL.
Object counters can be simple (unsigned) integers, no need to make
them size_t or elf_word.
"return 0" is simpler than "return ret" because it shows the return
value immediately without the need to check what it can be at that
location.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Try to use llext_peek() for section pointers. If it's supported and
succeeds we don't need to allocate buffers.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
The only way so far to access extension images is via a memory
buffer. Since this, supposedly, will also be a rather common method,
it makes sense to add a method to access extension data quickly by
obtaining a pointer instead of copying data into local buffers. Add a
llext_peek() method for that.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
elf_rela_t contains elf_rel_t exactly and contains an additional
field at the end. Therefore pointers of that type can be used for
both types, making the code generic.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>