.. zephyr:code-sample:: llext-shell-loader
   :name: Linkable loadable extensions shell module
   :relevant-api: llext_apis

   Manage loadable extensions using shell commands.

Overview
********

This example provides shell access to the :ref:`llext` system and provides the
ability to manage loadable code extensions in the shell.

Requirements
************

A board with a supported LLEXT architecture and shell capable console. The
following example uses an ARMv7 CPU, but the same instructions can be adapted
to any LLEXT-supported target.

Building
********

The following command will build the main shell application:

.. zephyr-app-commands::
   :zephyr-app: samples/subsys/llext/shell_loader
   :board: robokit1
   :goals: build
   :compact:

.. note::

   You may need to disable memory protection for the sample to work (e.g.
   ``CONFIG_ARM_MPU=n``). See the full list of similar flags in
   :zephyr_file:`tests/subsys/llext/no_mem_protection.conf`.

This sample also includes the source for a very basic extension,
:zephyr_file:`samples/subsys/llext/shell_loader/hello_world.c`, which can be
used to test the LLEXT features.

It can be compiled to :file:`build/hello_world.llext` using the Zephyr build
system like this:

.. code-block:: console

   $ ninja -C build -vvv hello_world_ext

On a host machine with the Zephyr SDK and the ``arm-zephyr-eabi`` toolchain in
``PATH``, you can also obtain the same result directly with ``gcc``:

.. code-block:: console

   $ arm-zephyr-eabi-gcc -mlong-calls -mthumb -c -o build/hello_world.llext samples/subsys/llext/shell/hello_world.c

.. note::

   LLEXT by default only imports symbols that have been explicitly exported by
   the extension via the :c:macro:`EXPORT_SYMBOL` macro. Compiling with this
   macro requires using the full Zephyr build system, or at least the
   :ref:`LLEXT EDK <llext_build_edk>`.

   To avoid this complexity, this sample configures Zephyr to use all global
   symbols defined in the extension ELF file via the Kconfig option
   :kconfig:option:`CONFIG_LLEXT_IMPORT_ALL_GLOBALS`. This is not recommended
   for large extensions as the memory usage increases significantly.

The compiled extension can be inspected with the usual binutils utilities to
see symbols, sections, and relocations. Then, using additional tools, converted
to a hex string usable by the ``llext load_hex`` shell command:

.. code-block:: console

  $ arm-zephyr-eabi-objdump -r -d -x build/hello_world.llext

	hello_world.elf:     file format elf32-littlearm
	hello_world.elf
	architecture: armv4t, flags 0x00000011:
	HAS_RELOC, HAS_SYMS
	start address 0x00000000
	private flags = 0x5000000: [Version5 EABI]

	Sections:
	Idx Name          Size      VMA       LMA       File off  Algn
	  0 .text         00000038  00000000  00000000  00000034  2**2
	                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
	  1 .data         00000000  00000000  00000000  0000006c  2**0
	                  CONTENTS, ALLOC, LOAD, DATA
	  2 .bss          00000000  00000000  00000000  0000006c  2**0
	                  ALLOC
	  3 .rodata       00000025  00000000  00000000  0000006c  2**2
	                  CONTENTS, ALLOC, LOAD, READONLY, DATA
	  4 .comment      00000021  00000000  00000000  00000091  2**0
	                  CONTENTS, READONLY
	  5 .ARM.attributes 0000002a  00000000  00000000  000000b2  2**0
	                  CONTENTS, READONLY
	SYMBOL TABLE:
	00000000 l    df *ABS*	00000000 hello_world.c
	00000000 l    d  .text	00000000 .text
	00000000 l    d  .data	00000000 .data
	00000000 l    d  .bss	00000000 .bss
	00000000 l    d  .rodata	00000000 .rodata
	00000000 l     O .rodata	00000004 number
	00000000 l    d  .comment	00000000 .comment
	00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
	00000000 g     F .text	00000034 hello_world
	00000000         *UND*	00000000 printk



	Disassembly of section .text:

	00000000 <hello_world>:
	   0:	b580      	push	{r7, lr}
	   2:	af00      	add	r7, sp, #0
	   4:	4b08      	ldr	r3, [pc, #32]	; (28 <hello_world+0x28>)
	   6:	0018      	movs	r0, r3
	   8:	4b08      	ldr	r3, [pc, #32]	; (2c <hello_world+0x2c>)
	   a:	f000 f813 	bl	34 <hello_world+0x34>
	   e:	222a      	movs	r2, #42	; 0x2a
	  10:	4b07      	ldr	r3, [pc, #28]	; (30 <hello_world+0x30>)
	  12:	0011      	movs	r1, r2
	  14:	0018      	movs	r0, r3
	  16:	4b05      	ldr	r3, [pc, #20]	; (2c <hello_world+0x2c>)
	  18:	f000 f80c 	bl	34 <hello_world+0x34>
	  1c:	46c0      	nop			; (mov r8, r8)
	  1e:	46bd      	mov	sp, r7
	  20:	bc80      	pop	{r7}
	  22:	bc01      	pop	{r0}
	  24:	4700      	bx	r0
	  26:	46c0      	nop			; (mov r8, r8)
	  28:	00000004 	.word	0x00000004
				28: R_ARM_ABS32	.rodata
	  2c:	00000000 	.word	0x00000000
				2c: R_ARM_ABS32	printk
	  30:	00000014 	.word	0x00000014
				30: R_ARM_ABS32	.rodata
	  34:	4718      	bx	r3
	  36:	46c0      	nop			; (mov r8, r8)

  $ xxd -p build/hello_world.llext | tr -d '\n'
  7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000

In this sample there are 3 absolute (``R_ARM_ABS32``) relocations, 2 of which
are meant to hold addresses into the ``.rodata`` sections where the strings are
located. A third is an address of where the ``printk`` function (symbol) can be
found. At load time LLEXT replaces the values in the ``.text`` section with
real memory addresses so that ``printk`` works as expected with the strings
included in the hello world sample.

Running
*******

Once the board has booted, you will be presented with a shell prompt.
All the LLEXT system related commands are available as sub-commands of
``llext``, and can be seen with ``llext help``:

.. code-block:: console

  uart:~$ llext help
  llext - Loadable extension commands
  Subcommands:
    list          :List loaded extensions and their size in memory
    load_hex      :Load an elf file encoded in hex directly from the shell input.
                   Syntax:
                   <ext_name> <ext_hex_string>
    unload        :Unload an extension by name. Syntax:
                   <ext_name>
    list_symbols  :List extension symbols. Syntax:
                   <ext_name>
    call_fn       :Call extension function with prototype void fn(void). Syntax:
                   <ext_name> <function_name>

The hex string generated above can be used to load the extension:

.. code-block:: console

  uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000

This extension can then be seen in the list of loaded extensions (``list``), its symbols printed
(``list_symbols``), and the hello_world function which the extension exports can be called and
run (``call_fn``).

.. code-block:: console

  uart:~$ llext call_fn hello_world hello_world
  hello world