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

Defines

LLEXT_MEM_PARTITIONS
LLEXT_LOAD_PARAM_DEFAULT

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

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.

struct llext_load_param
#include <llext.h>

llext loader parameters

These are parameters, not saved in the permanent llext context, needed only for the loader

Public Members

bool relocate_local

Should local relocation be performed.

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.

Public Members

const char *const name

Name of symbol.

const void *const addr

Address of symbol.

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.

Public Members

const char *name

Name of symbol.

void *addr

Address of symbol.

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.

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.

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.