Linkable Loadable Extensions (LLEXT)
The llext subsystem provides a toolbox for extending the functionality of an application at runtime with linkable loadable code.
Extensions can be loaded from precompiled ELF formatted data which is verified, loaded, and linked with other extensions. Extensions can be manipulated and introspected to some degree, as well as unloaded when no longer needed.
An extension may be loaded using any implementation of a llext_loader
which has a set of function pointers that provide the necessary functionality
to read the ELF data. A loader also provides some minimal context (memory)
needed by the llext_load()
function. An implementation over a buffer
containing an ELF in addressable memory in memory is available as
llext_buf_loader
.
API Reference
- group llext
Linkable loadable extensions.
- Since
3.5
- Version
0.1.0
Enums
-
enum llext_mem
List of ELF regions that are stored or referenced in the llext.
Values:
-
enumerator LLEXT_MEM_TEXT
-
enumerator LLEXT_MEM_DATA
-
enumerator LLEXT_MEM_RODATA
-
enumerator LLEXT_MEM_BSS
-
enumerator LLEXT_MEM_EXPORT
-
enumerator LLEXT_MEM_SYMTAB
-
enumerator LLEXT_MEM_STRTAB
-
enumerator LLEXT_MEM_SHSTRTAB
-
enumerator LLEXT_MEM_COUNT
-
enumerator LLEXT_MEM_TEXT
Functions
-
struct llext *llext_by_name(const char *name)
Find an llext by name.
- Parameters:
name – [in] String name of the llext
- Return values:
NULL – if no llext not found
llext – if llext found
-
int llext_iterate(int (*fn)(struct llext *ext, void *arg), void *arg)
Iterate overall registered llext instances.
Calls a provided callback function for each registered extension or until the callback function returns a non-0 value.
- Parameters:
fn – [in] callback function
arg – [in] a private argument to be provided to the callback function
- Return values:
0 – if no extensions are registered
value – returned by the most recent callback invocation
-
int llext_load(struct llext_loader *loader, const char *name, struct llext **ext, struct llext_load_param *ldr_parm)
Load and link an extension.
Loads relevant ELF data into memory and provides a structure to work with it.
Only relocatable ELF files are currently supported (partially linked).
- Parameters:
loader – [in] An extension loader that provides input data and context
name – [in] A string identifier for the extension
ext – [out] This will hold the pointer to the llext struct
ldr_parm – [in] Loader parameters
- Return values:
0 – Success
> – 0 extension use count
-ENOMEM – Not enough memory
-EINVAL – Invalid ELF stream
-
int llext_unload(struct llext **ext)
Unload an extension.
- Parameters:
ext – [in] Extension to unload
-
const void *llext_find_sym(const struct llext_symtable *sym_table, const char *sym_name)
Find the address for an arbitrary symbol name.
- Parameters:
sym_table – [in] Symbol table to lookup symbol in, if NULL uses base table
sym_name – [in] Symbol name to find
- Return values:
NULL – if no symbol found
addr – Address of symbol in memory if found
-
int llext_call_fn(struct llext *ext, const char *sym_name)
Call a function by name.
Expects a symbol representing a void fn(void) style function exists and may be called.
- Parameters:
ext – [in] Extension to call function in
sym_name – [in] Function name (exported symbol) in the extension
- Return values:
0 – success
-EINVAL – invalid symbol name
-
int llext_add_domain(struct llext *ext, struct k_mem_domain *domain)
Add the known memory partitions of the extension to a memory domain.
Allows an extension to be executed in supervisor or user mode threads when memory protection hardware is enabled.
- Parameters:
ext – [in] Extension to add to a domain
domain – [in] Memory domain to add partitions to
- Return values:
0 – success
-errno – error
-
int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, uintptr_t sym_base_addr, const char *sym_name, uintptr_t load_bias)
Architecture specific function for updating op codes given a relocation.
Elf files contain a series of relocations described in a section. These relocation instructions are architecture specific and each architecture supporting extensions must implement this. They are instructions on how to rewrite opcodes given the actual placement of some symbolic data such as a section, function, or object.
- Parameters:
rel – [in] Relocation data provided by elf
loc – [in] Address of operation to rewrite with relocation
sym_base_addr – [in] Symbol address
sym_name – [in] Symbol name
load_bias – [in] .text load address
- Return values:
0 – success
-ENOEXEC – invalid relocation
-
ssize_t llext_find_section(struct llext_loader *loader, const char *search_name)
Find an ELF section.
- Parameters:
loader – Extension loader data and context
search_name – Section name to search for
- Return values:
Section – offset or a negative error code
-
void arch_elf_relocate_local(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel, const elf_sym_t *sym, size_t got_offset)
Architecture specific function for updating addresses via relocation table.
- Parameters:
loader – [in] Extension loader data and context
ext – [in] Extension to call function in
rel – [in] Relocation data provided by elf
sym – [in] Corresponding symbol table entry
got_offset – [in] Offset within a relocation table
-
struct llext
- #include <llext.h>
Linkable loadable extension.
Public Members
-
char name[16]
Name of the llext.
-
void *mem[LLEXT_MEM_COUNT]
Lookup table of llext memory regions.
-
bool mem_on_heap[LLEXT_MEM_COUNT]
Is the memory for this section allocated on heap?
-
size_t mem_size[LLEXT_MEM_COUNT]
Size of each stored section.
-
size_t alloc_size
Total llext allocation size.
-
struct llext_symtable exp_tab
Exported symbols from the llext, may be linked against by other llext.
-
unsigned int use_count
Extension use counter, prevents unloading while in use.
-
char name[16]
- group llext_symbols
Linkable loadable extension symbol.
Defines
-
EXPORT_SYMBOL(x)
Export a constant symbol to extensions.
Takes a symbol (function or object) by symbolic name and adds the name and address of the symbol to a table of symbols that may be referenced by extensions.
- Parameters:
x – Symbol to export to extensions
-
LL_EXTENSION_SYMBOL(x)
Exports a symbol from an extension to the base image.
This macro can be used in extensions to add a symbol (function or object) to the extension’s exported symbol table, so that it may be referenced by the base image.
- Parameters:
x – Extension symbol to export to the base image
-
struct llext_const_symbol
- #include <symbol.h>
Constant symbols are unchangeable named memory addresses.
Symbols may be named function or global objects that have been exported for linking. These constant symbols are useful in the base image as they may be placed in ROM.
-
struct llext_symbol
- #include <symbol.h>
Symbols are named memory addresses.
Symbols may be named function or global objects that have been exported for linking. These are mutable and should come from extensions where the location may need updating depending on where memory is placed.
-
struct llext_symtable
- #include <symbol.h>
A symbol table.
An array of symbols
Public Members
-
size_t sym_cnt
Number of symbols in the table.
-
struct llext_symbol *syms
Array of symbols.
-
size_t sym_cnt
-
EXPORT_SYMBOL(x)
- group llext_loader
Loader context for llext.
Functions
-
static inline int llext_read(struct llext_loader *l, void *buf, size_t len)
-
static inline int llext_seek(struct llext_loader *l, size_t pos)
-
static inline void *llext_peek(struct llext_loader *l, size_t pos)
-
struct llext_loader
- #include <loader.h>
Linkable loadable extension loader context.
Public Members
-
int (*read)(struct llext_loader *ldr, void *out, size_t len)
Read (copy) from the loader.
Copies len bytes into buf from the current position of the loader.
- Param ldr:
[in] Loader
- Param out:
[in] Output location
- Param len:
[in] Length to copy into the output location
- Retval 0:
Success
- Retval -errno:
Error reading (any errno)
-
int (*seek)(struct llext_loader *ldr, size_t pos)
Seek to a new absolute location.
Changes the location of the loader position to a new absolute given position.
- Param ldr:
[in] Loader
- Param pos:
[in] Position in stream to move loader
- Retval 0:
Success
- Retval -errno:
Error reading (any errno)
-
void *(*peek)(struct llext_loader *ldr, size_t pos)
Peek at an absolute location.
Return a pointer to the buffer at specified offset.
- Param ldr:
[in] Loader
- Param pos:
[in] Position to obtain a pointer to
- Retval pointer:
into the buffer
-
size_t prog_data_size
Total calculated .data size for relocatable extensions.
-
int (*read)(struct llext_loader *ldr, void *out, size_t len)
-
static inline int llext_read(struct llext_loader *l, void *buf, size_t len)
- group llext_buf_loader
LLEXT buffer loader.
Defines
-
LLEXT_BUF_LOADER(_buf, _buf_len)
Initialize an extension buf loader.
- Parameters:
_buf – Buffer containing an ELF binary
_buf_len – Buffer length in bytes
-
struct llext_buf_loader
- #include <buf_loader.h>
An extension loader from a provided buffer containing an ELF.
Public Members
-
struct llext_loader loader
Extension loader.
-
struct llext_loader loader
-
LLEXT_BUF_LOADER(_buf, _buf_len)