1.. zephyr:code-sample:: llext-shell-loader 2 :name: Linkable loadable extensions shell module 3 :relevant-api: llext_apis 4 5 Manage loadable extensions using shell commands. 6 7Overview 8******** 9 10This example provides shell access to the :ref:`llext` system and provides the 11ability to manage loadable code extensions in the shell. 12 13Requirements 14************ 15 16A board with a supported LLEXT architecture and shell capable console. The 17following example uses an ARMv7 CPU, but the same instructions can be adapted 18to any LLEXT-supported target. 19 20Building 21******** 22 23The following command will build the main shell application: 24 25.. zephyr-app-commands:: 26 :zephyr-app: samples/subsys/llext/shell_loader 27 :board: robokit1 28 :goals: build 29 :compact: 30 31.. note:: 32 33 You may need to disable memory protection for the sample to work (e.g. 34 ``CONFIG_ARM_MPU=n``). See the full list of similar flags in 35 :zephyr_file:`tests/subsys/llext/no_mem_protection.conf`. 36 37This sample also includes the source for a very basic extension, 38:zephyr_file:`samples/subsys/llext/shell_loader/hello_world.c`, which can be 39used to test the LLEXT features. 40 41It can be compiled to :file:`build/hello_world.llext` using the Zephyr build 42system like this: 43 44.. code-block:: console 45 46 $ ninja -C build -vvv hello_world_ext 47 48On a host machine with the Zephyr SDK and the ``arm-zephyr-eabi`` toolchain in 49``PATH``, you can also obtain the same result directly with ``gcc``: 50 51.. code-block:: console 52 53 $ arm-zephyr-eabi-gcc -mlong-calls -mthumb -c -o build/hello_world.llext samples/subsys/llext/shell/hello_world.c 54 55.. note:: 56 57 LLEXT by default only imports symbols that have been explicitly exported by 58 the extension via the :c:macro:`EXPORT_SYMBOL` macro. Compiling with this 59 macro requires using the full Zephyr build system, or at least the 60 :ref:`LLEXT EDK <llext_build_edk>`. 61 62 To avoid this complexity, this sample configures Zephyr to use all global 63 symbols defined in the extension ELF file via the Kconfig option 64 :kconfig:option:`CONFIG_LLEXT_IMPORT_ALL_GLOBALS`. This is not recommended 65 for large extensions as the memory usage increases significantly. 66 67The compiled extension can be inspected with the usual binutils utilities to 68see symbols, sections, and relocations. Then, using additional tools, converted 69to a hex string usable by the ``llext load_hex`` shell command: 70 71.. code-block:: console 72 73 $ arm-zephyr-eabi-objdump -r -d -x build/hello_world.llext 74 75 hello_world.elf: file format elf32-littlearm 76 hello_world.elf 77 architecture: armv4t, flags 0x00000011: 78 HAS_RELOC, HAS_SYMS 79 start address 0x00000000 80 private flags = 0x5000000: [Version5 EABI] 81 82 Sections: 83 Idx Name Size VMA LMA File off Algn 84 0 .text 00000038 00000000 00000000 00000034 2**2 85 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 86 1 .data 00000000 00000000 00000000 0000006c 2**0 87 CONTENTS, ALLOC, LOAD, DATA 88 2 .bss 00000000 00000000 00000000 0000006c 2**0 89 ALLOC 90 3 .rodata 00000025 00000000 00000000 0000006c 2**2 91 CONTENTS, ALLOC, LOAD, READONLY, DATA 92 4 .comment 00000021 00000000 00000000 00000091 2**0 93 CONTENTS, READONLY 94 5 .ARM.attributes 0000002a 00000000 00000000 000000b2 2**0 95 CONTENTS, READONLY 96 SYMBOL TABLE: 97 00000000 l df *ABS* 00000000 hello_world.c 98 00000000 l d .text 00000000 .text 99 00000000 l d .data 00000000 .data 100 00000000 l d .bss 00000000 .bss 101 00000000 l d .rodata 00000000 .rodata 102 00000000 l O .rodata 00000004 number 103 00000000 l d .comment 00000000 .comment 104 00000000 l d .ARM.attributes 00000000 .ARM.attributes 105 00000000 g F .text 00000034 hello_world 106 00000000 *UND* 00000000 printk 107 108 109 110 Disassembly of section .text: 111 112 00000000 <hello_world>: 113 0: b580 push {r7, lr} 114 2: af00 add r7, sp, #0 115 4: 4b08 ldr r3, [pc, #32] ; (28 <hello_world+0x28>) 116 6: 0018 movs r0, r3 117 8: 4b08 ldr r3, [pc, #32] ; (2c <hello_world+0x2c>) 118 a: f000 f813 bl 34 <hello_world+0x34> 119 e: 222a movs r2, #42 ; 0x2a 120 10: 4b07 ldr r3, [pc, #28] ; (30 <hello_world+0x30>) 121 12: 0011 movs r1, r2 122 14: 0018 movs r0, r3 123 16: 4b05 ldr r3, [pc, #20] ; (2c <hello_world+0x2c>) 124 18: f000 f80c bl 34 <hello_world+0x34> 125 1c: 46c0 nop ; (mov r8, r8) 126 1e: 46bd mov sp, r7 127 20: bc80 pop {r7} 128 22: bc01 pop {r0} 129 24: 4700 bx r0 130 26: 46c0 nop ; (mov r8, r8) 131 28: 00000004 .word 0x00000004 132 28: R_ARM_ABS32 .rodata 133 2c: 00000000 .word 0x00000000 134 2c: R_ARM_ABS32 printk 135 30: 00000014 .word 0x00000014 136 30: R_ARM_ABS32 .rodata 137 34: 4718 bx r3 138 36: 46c0 nop ; (mov r8, r8) 139 140 $ xxd -p build/hello_world.llext | tr -d '\n' 141 7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000 142 143In this sample there are 3 absolute (``R_ARM_ABS32``) relocations, 2 of which 144are meant to hold addresses into the ``.rodata`` sections where the strings are 145located. A third is an address of where the ``printk`` function (symbol) can be 146found. At load time LLEXT replaces the values in the ``.text`` section with 147real memory addresses so that ``printk`` works as expected with the strings 148included in the hello world sample. 149 150Running 151******* 152 153Once the board has booted, you will be presented with a shell prompt. 154All the LLEXT system related commands are available as sub-commands of 155``llext``, and can be seen with ``llext help``: 156 157.. code-block:: console 158 159 uart:~$ llext help 160 llext - Loadable extension commands 161 Subcommands: 162 list :List loaded extensions and their size in memory 163 load_hex :Load an elf file encoded in hex directly from the shell input. 164 Syntax: 165 <ext_name> <ext_hex_string> 166 unload :Unload an extension by name. Syntax: 167 <ext_name> 168 list_symbols :List extension symbols. Syntax: 169 <ext_name> 170 call_fn :Call extension function with prototype void fn(void). Syntax: 171 <ext_name> <function_name> 172 173The hex string generated above can be used to load the extension: 174 175.. code-block:: console 176 177 uart:~$ llext load_hex hello_world 7f454c4601010100000000000000000001002800010000000000000000000000680200000000000534000000000028000b000a0080b500af084b1800084b00f013f82a22074b11001800054b00f00cf8c046bd4680bc01bc0047c0460400000000000000140000001847c0462a00000068656c6c6f20776f726c640a0000000041206e756d62657220697320256c750a00004743433a20285a65706879722053444b20302e31362e31292031322e322e30004129000000616561626900011f000000053454000602080109011204140115011703180119011a011e06000000000000000000000000000000000100000000000000000000000400f1ff000000000000000000000000030001000000000000000000000000000300030000000000000000000000000003000400000000000000000000000000030005000f00000000000000000000000000050012000000000000000400000001000500190000000000000000000000000001000f0000002800000000000000000001001900000034000000000000000000010000000000000000000000000003000600000000000000000000000000030007001c000000010000003400000012000100280000000000000000000000100000000068656c6c6f5f776f726c642e63002464006e756d6265720024740068656c6c6f5f776f726c64007072696e746b000028000000020500002c000000020e00003000000002050000002e73796d746162002e737472746162002e7368737472746162002e72656c2e74657874002e64617461002e627373002e726f64617461002e636f6d6d656e74002e41524d2e6174747269627574657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000100000006000000000000003400000038000000000000000000000004000000000000001b000000090000004000000000000000fc0100001800000008000000010000000400000008000000250000000100000003000000000000006c00000000000000000000000000000001000000000000002b0000000800000003000000000000006c0000000000000000000000000000000100000000000000300000000100000002000000000000006c00000025000000000000000000000004000000000000003800000001000000300000000000000091000000210000000000000000000000010000000100000041000000030000700000000000000000b20000002a0000000000000000000000010000000000000001000000020000000000000000000000dc000000f0000000090000000d000000040000001000000009000000030000000000000000000000cc0100002f0000000000000000000000010000000000000011000000030000000000000000000000140200005100000000000000000000000100000000000000 178 179This extension can then be seen in the list of loaded extensions (``list``), its symbols printed 180(``list_symbols``), and the hello_world function which the extension exports can be called and 181run (``call_fn``). 182 183.. code-block:: console 184 185 uart:~$ llext call_fn hello_world hello_world 186 hello world 187