2929#include <zephyr/llext/loader.h>
3030#include <zephyr/llext/llext.h>
3131#include <zephyr/logging/log_ctrl.h>
32+ #include <zephyr/llext/inspect.h>
3233
3334#include <rimage/sof/user/manifest.h>
3435#include <module/module/api_ver.h>
@@ -70,40 +71,38 @@ static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size)
7071 return sys_mm_drv_unmap_region (aligned_vma , ALIGN_UP (pre_pad_size + size , PAGE_SZ ));
7172}
7273
73- static int llext_manager_load_data_from_storage (const struct llext * ext ,
74+ static int llext_manager_load_data_from_storage (const struct llext_loader * ldr ,
75+ const struct llext * ext ,
76+ enum llext_mem region ,
7477 void __sparse_cache * vma ,
75- const uint8_t * load_base ,
7678 size_t size , uint32_t flags )
7779{
7880 unsigned int i ;
81+ const void * region_addr ;
7982 int ret = llext_manager_align_map (vma , size , SYS_MM_MEM_PERM_RW );
80- const elf_shdr_t * shdr ;
8183
8284 if (ret < 0 ) {
8385 tr_err (& lib_manager_tr , "cannot map %u of %p" , size , (__sparse_force void * )vma );
8486 return ret ;
8587 }
8688
87- size_t init_offset = 0 ;
89+ llext_get_region_info ( ldr , ext , region , NULL , & region_addr , NULL ) ;
8890
8991 /* Need to copy sections within regions individually, offsets may differ */
90- for (i = 0 , shdr = llext_section_headers ( ext ) ; i < llext_section_count (ext ); i ++ , shdr ++ ) {
91- if (( uintptr_t ) shdr -> sh_addr < ( uintptr_t ) vma ||
92- ( uintptr_t ) shdr -> sh_addr >= ( uintptr_t ) vma + size )
93- continue ;
92+ for (i = 0 ; i < llext_section_count (ext ); i ++ ) {
93+ const elf_shdr_t * shdr ;
94+ enum llext_mem s_region = LLEXT_MEM_COUNT ;
95+ size_t s_offset = 0 ;
9496
95- if (!init_offset )
96- init_offset = shdr -> sh_offset ;
97+ llext_get_section_info (ldr , ext , i , & shdr , & s_region , & s_offset );
9798
98- /* found a section within the region */
99- size_t offset = shdr -> sh_offset - init_offset ;
99+ if ( s_region != region )
100+ continue ;
100101
101- if (shdr -> sh_type != SHT_NOBITS ) {
102- ret = memcpy_s ((__sparse_force void * )shdr -> sh_addr , size - offset ,
103- load_base + offset , shdr -> sh_size );
104- if (ret < 0 )
105- return ret ;
106- }
102+ ret = memcpy_s ((__sparse_force void * )shdr -> sh_addr , size - s_offset ,
103+ (const uint8_t * )region_addr + s_offset , shdr -> sh_size );
104+ if (ret < 0 )
105+ return ret ;
107106 }
108107
109108 /*
@@ -165,23 +164,24 @@ static int llext_manager_load_module(struct lib_manager_module *mctx)
165164 }
166165 }
167166
167+ const struct llext_loader * ldr = & mctx -> ebl -> loader ;
168168 const struct llext * ext = mctx -> llext ;
169169
170170 /* Copy Code */
171- ret = llext_manager_load_data_from_storage (ext , va_base_text , ext -> mem [ LLEXT_MEM_TEXT ] ,
172- text_size , SYS_MM_MEM_PERM_EXEC );
171+ ret = llext_manager_load_data_from_storage (ldr , ext , LLEXT_MEM_TEXT ,
172+ va_base_text , text_size , SYS_MM_MEM_PERM_EXEC );
173173 if (ret < 0 )
174174 return ret ;
175175
176176 /* Copy read-only data */
177- ret = llext_manager_load_data_from_storage (ext , va_base_rodata , ext -> mem [ LLEXT_MEM_RODATA ] ,
178- rodata_size , 0 );
177+ ret = llext_manager_load_data_from_storage (ldr , ext , LLEXT_MEM_RODATA ,
178+ va_base_rodata , rodata_size , 0 );
179179 if (ret < 0 )
180180 goto e_text ;
181181
182182 /* Copy writable data */
183- ret = llext_manager_load_data_from_storage (ext , va_base_data , ext -> mem [ LLEXT_MEM_DATA ] ,
184- data_size , SYS_MM_MEM_PERM_RW );
183+ ret = llext_manager_load_data_from_storage (ldr , ext , LLEXT_MEM_DATA ,
184+ va_base_data , data_size , SYS_MM_MEM_PERM_RW );
185185 if (ret < 0 )
186186 goto e_rodata ;
187187
@@ -244,6 +244,7 @@ static int llext_manager_link(const char *name,
244244{
245245 struct llext * * llext = & mctx -> llext ;
246246 struct llext_loader * ldr = & mctx -> ebl -> loader ;
247+ const elf_shdr_t * hdr ;
247248 int ret ;
248249
249250 if (* llext && !mctx -> mapped ) {
@@ -267,56 +268,63 @@ static int llext_manager_link(const char *name,
267268 .relocate_local = !* llext ,
268269 .pre_located = true,
269270 .section_detached = llext_manager_section_detached ,
271+ .keep_section_info = true,
270272 };
271273
272274 ret = llext_load (ldr , name , llext , & ldr_parm );
273275 if (ret )
274276 return ret ;
275277 }
276278
277- mctx -> segment [LIB_MANAGER_TEXT ].addr = ldr -> sects [LLEXT_MEM_TEXT ].sh_addr ;
278- mctx -> segment [LIB_MANAGER_TEXT ].size = ldr -> sects [LLEXT_MEM_TEXT ].sh_size ;
279+ /* All code sections */
280+ llext_get_region_info (ldr , * llext , LLEXT_MEM_TEXT , & hdr , NULL , NULL );
281+ mctx -> segment [LIB_MANAGER_TEXT ].addr = hdr -> sh_addr ;
282+ mctx -> segment [LIB_MANAGER_TEXT ].size = hdr -> sh_size ;
279283
280284 tr_dbg (& lib_manager_tr , ".text: start: %#lx size %#x" ,
281285 mctx -> segment [LIB_MANAGER_TEXT ].addr ,
282286 mctx -> segment [LIB_MANAGER_TEXT ].size );
283287
284288 /* All read-only data sections */
285- mctx -> segment [ LIB_MANAGER_RODATA ]. addr =
286- ldr -> sects [ LLEXT_MEM_RODATA ]. sh_addr ;
287- mctx -> segment [LIB_MANAGER_RODATA ].size = ldr -> sects [ LLEXT_MEM_RODATA ]. sh_size ;
289+ llext_get_region_info ( ldr , * llext , LLEXT_MEM_RODATA , & hdr , NULL , NULL );
290+ mctx -> segment [ LIB_MANAGER_RODATA ]. addr = hdr -> sh_addr ;
291+ mctx -> segment [LIB_MANAGER_RODATA ].size = hdr -> sh_size ;
288292
289293 tr_dbg (& lib_manager_tr , ".rodata: start: %#lx size %#x" ,
290294 mctx -> segment [LIB_MANAGER_RODATA ].addr ,
291295 mctx -> segment [LIB_MANAGER_RODATA ].size );
292296
293297 /* All writable data sections */
294- mctx -> segment [ LIB_MANAGER_DATA ]. addr =
295- ldr -> sects [ LLEXT_MEM_DATA ]. sh_addr ;
296- mctx -> segment [LIB_MANAGER_DATA ].size = ldr -> sects [ LLEXT_MEM_DATA ]. sh_size ;
298+ llext_get_region_info ( ldr , * llext , LLEXT_MEM_DATA , & hdr , NULL , NULL );
299+ mctx -> segment [ LIB_MANAGER_DATA ]. addr = hdr -> sh_addr ;
300+ mctx -> segment [LIB_MANAGER_DATA ].size = hdr -> sh_size ;
297301
298302 tr_dbg (& lib_manager_tr , ".data: start: %#lx size %#x" ,
299303 mctx -> segment [LIB_MANAGER_DATA ].addr ,
300304 mctx -> segment [LIB_MANAGER_DATA ].size );
301305
302- mctx -> segment [LIB_MANAGER_BSS ].addr = ldr -> sects [LLEXT_MEM_BSS ].sh_addr ;
303- mctx -> segment [LIB_MANAGER_BSS ].size = ldr -> sects [LLEXT_MEM_BSS ].sh_size ;
306+ /* Writable uninitialized data section */
307+ llext_get_region_info (ldr , * llext , LLEXT_MEM_BSS , & hdr , NULL , NULL );
308+ mctx -> segment [LIB_MANAGER_BSS ].addr = hdr -> sh_addr ;
309+ mctx -> segment [LIB_MANAGER_BSS ].size = hdr -> sh_size ;
304310
305311 tr_dbg (& lib_manager_tr , ".bss: start: %#lx size %#x" ,
306312 mctx -> segment [LIB_MANAGER_BSS ].addr ,
307313 mctx -> segment [LIB_MANAGER_BSS ].size );
308314
309315 * buildinfo = NULL ;
310- ssize_t binfo_o = llext_find_section (ldr , ".mod_buildinfo" );
311-
312- if (binfo_o >= 0 )
313- * buildinfo = llext_peek (ldr , binfo_o );
316+ ret = llext_section_shndx (ldr , * llext , ".mod_buildinfo" );
317+ if (ret >= 0 ) {
318+ llext_get_section_info (ldr , * llext , ret , & hdr , NULL , NULL );
319+ * buildinfo = llext_peek (ldr , hdr -> sh_offset );
320+ }
314321
315322 * mod_manifest = NULL ;
316- ssize_t mod_o = llext_find_section (ldr , ".module" );
317-
318- if (mod_o >= 0 )
319- * mod_manifest = llext_peek (ldr , mod_o );
323+ ret = llext_section_shndx (ldr , * llext , ".module" );
324+ if (ret >= 0 ) {
325+ llext_get_section_info (ldr , * llext , ret , & hdr , NULL , NULL );
326+ * mod_manifest = llext_peek (ldr , hdr -> sh_offset );
327+ }
320328
321329 return * buildinfo && * mod_manifest ? 0 : - EPROTO ;
322330}
@@ -618,7 +626,14 @@ int llext_manager_free_module(const uint32_t component_id)
618626
619627 /* Protected by IPC serialization */
620628 if (mctx -> llext -> use_count > 1 ) {
621- /* llext_unload() will return a positive number */
629+ /*
630+ * At least 2 users: llext_unload() will never actually free
631+ * the extension but only reduce the refcount and return its
632+ * new value (must be a positive number).
633+ * NOTE: if this is modified to allow extension unload, the
634+ * inspection data in the loader must be freed as well by
635+ * calling the llext_free_inspection_data() function.
636+ */
622637 int ret = llext_unload (& mctx -> llext );
623638
624639 if (ret <= 0 ) {
0 commit comments