29
29
#include <zephyr/llext/loader.h>
30
30
#include <zephyr/llext/llext.h>
31
31
#include <zephyr/logging/log_ctrl.h>
32
+ #include <zephyr/llext/inspect.h>
32
33
33
34
#include <rimage/sof/user/manifest.h>
34
35
#include <module/module/api_ver.h>
@@ -70,41 +71,39 @@ static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size)
70
71
return sys_mm_drv_unmap_region (aligned_vma , ALIGN_UP (pre_pad_size + size , PAGE_SZ ));
71
72
}
72
73
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 ,
74
77
void __sparse_cache * vma ,
75
- const uint8_t * load_base ,
76
78
size_t size , uint32_t flags )
77
79
{
78
80
unsigned int i ;
81
+ const void * region_addr ;
79
82
int ret ;
80
- const elf_shdr_t * shdr ;
81
83
82
84
ret = llext_manager_align_map (vma , size , SYS_MM_MEM_PERM_RW );
83
85
if (ret < 0 ) {
84
86
tr_err (& lib_manager_tr , "cannot map %u of %p" , size , (__sparse_force void * )vma );
85
87
return ret ;
86
88
}
87
89
88
- size_t init_offset = 0 ;
90
+ llext_get_region_info ( ldr , ext , region , NULL , & region_addr , NULL ) ;
89
91
90
92
/* Need to copy sections within regions individually, offsets may differ */
91
- for (i = 0 , shdr = llext_section_headers ( ext ) ; i < llext_section_count (ext ); i ++ , shdr ++ ) {
92
- if (( uintptr_t ) shdr -> sh_addr < ( uintptr_t ) vma ||
93
- ( uintptr_t ) shdr -> sh_addr >= ( uintptr_t ) vma + size )
94
- continue ;
93
+ for (i = 0 ; i < llext_section_count (ext ); i ++ ) {
94
+ const elf_shdr_t * shdr ;
95
+ enum llext_mem s_region = LLEXT_MEM_COUNT ;
96
+ size_t s_offset = 0 ;
95
97
96
- if (!init_offset )
97
- init_offset = shdr -> sh_offset ;
98
+ llext_get_section_info (ldr , ext , i , & shdr , & s_region , & s_offset );
98
99
99
- /* found a section within the region */
100
- size_t offset = shdr -> sh_offset - init_offset ;
100
+ if ( s_region != region )
101
+ continue ;
101
102
102
- if (shdr -> sh_type != SHT_NOBITS ) {
103
- ret = memcpy_s ((__sparse_force void * )shdr -> sh_addr , size - offset ,
104
- load_base + offset , shdr -> sh_size );
105
- if (ret < 0 )
106
- return ret ;
107
- }
103
+ ret = memcpy_s ((__sparse_force void * )shdr -> sh_addr , size - s_offset ,
104
+ (const uint8_t * )region_addr + s_offset , shdr -> sh_size );
105
+ if (ret < 0 )
106
+ return ret ;
108
107
}
109
108
110
109
/*
@@ -166,29 +165,31 @@ static int llext_manager_load_module(struct lib_manager_module *mctx)
166
165
}
167
166
}
168
167
168
+ const struct llext_loader * ldr = & mctx -> ebl -> loader ;
169
169
const struct llext * ext = mctx -> llext ;
170
170
171
171
/* Copy Code */
172
- ret = llext_manager_load_data_from_storage (ext , va_base_text , ext -> mem [ LLEXT_MEM_TEXT ] ,
173
- text_size , SYS_MM_MEM_PERM_EXEC );
172
+ ret = llext_manager_load_data_from_storage (ldr , ext , LLEXT_MEM_TEXT ,
173
+ va_base_text , text_size , SYS_MM_MEM_PERM_EXEC );
174
174
if (ret < 0 )
175
175
return ret ;
176
176
177
177
/* Copy read-only data */
178
- ret = llext_manager_load_data_from_storage (ext , va_base_rodata , ext -> mem [ LLEXT_MEM_RODATA ] ,
179
- rodata_size , 0 );
178
+ ret = llext_manager_load_data_from_storage (ldr , ext , LLEXT_MEM_RODATA ,
179
+ va_base_rodata , rodata_size , 0 );
180
180
if (ret < 0 )
181
181
goto e_text ;
182
182
183
183
/* Copy writable data */
184
- ret = llext_manager_load_data_from_storage (ext , va_base_data , ext -> mem [ LLEXT_MEM_DATA ] ,
185
- data_size , SYS_MM_MEM_PERM_RW );
184
+ ret = llext_manager_load_data_from_storage (ldr , ext , LLEXT_MEM_DATA ,
185
+ va_base_data , data_size , SYS_MM_MEM_PERM_RW );
186
186
if (ret < 0 )
187
187
goto e_rodata ;
188
188
189
+ /* Clear uninitialized data */
189
190
memset ((__sparse_force void * )bss_addr , 0 , bss_size );
190
- mctx -> mapped = true;
191
191
192
+ mctx -> mapped = true;
192
193
return 0 ;
193
194
194
195
e_rodata :
@@ -245,6 +246,7 @@ static int llext_manager_link(const char *name,
245
246
{
246
247
struct llext * * llext = & mctx -> llext ;
247
248
struct llext_loader * ldr = & mctx -> ebl -> loader ;
249
+ const elf_shdr_t * hdr ;
248
250
int ret ;
249
251
250
252
if (* llext && !mctx -> mapped ) {
@@ -268,56 +270,63 @@ static int llext_manager_link(const char *name,
268
270
.relocate_local = !* llext ,
269
271
.pre_located = true,
270
272
.section_detached = llext_manager_section_detached ,
273
+ .keep_section_info = true,
271
274
};
272
275
273
276
ret = llext_load (ldr , name , llext , & ldr_parm );
274
277
if (ret )
275
278
return ret ;
276
279
}
277
280
278
- mctx -> segment [LIB_MANAGER_TEXT ].addr = ldr -> sects [LLEXT_MEM_TEXT ].sh_addr ;
279
- mctx -> segment [LIB_MANAGER_TEXT ].size = ldr -> sects [LLEXT_MEM_TEXT ].sh_size ;
281
+ /* All code sections */
282
+ llext_get_region_info (ldr , * llext , LLEXT_MEM_TEXT , & hdr , NULL , NULL );
283
+ mctx -> segment [LIB_MANAGER_TEXT ].addr = hdr -> sh_addr ;
284
+ mctx -> segment [LIB_MANAGER_TEXT ].size = hdr -> sh_size ;
280
285
281
286
tr_dbg (& lib_manager_tr , ".text: start: %#lx size %#x" ,
282
287
mctx -> segment [LIB_MANAGER_TEXT ].addr ,
283
288
mctx -> segment [LIB_MANAGER_TEXT ].size );
284
289
285
290
/* All read-only data sections */
286
- mctx -> segment [ LIB_MANAGER_RODATA ]. addr =
287
- ldr -> sects [ LLEXT_MEM_RODATA ]. sh_addr ;
288
- mctx -> segment [LIB_MANAGER_RODATA ].size = ldr -> sects [ LLEXT_MEM_RODATA ]. sh_size ;
291
+ llext_get_region_info ( ldr , * llext , LLEXT_MEM_RODATA , & hdr , NULL , NULL );
292
+ mctx -> segment [ LIB_MANAGER_RODATA ]. addr = hdr -> sh_addr ;
293
+ mctx -> segment [LIB_MANAGER_RODATA ].size = hdr -> sh_size ;
289
294
290
295
tr_dbg (& lib_manager_tr , ".rodata: start: %#lx size %#x" ,
291
296
mctx -> segment [LIB_MANAGER_RODATA ].addr ,
292
297
mctx -> segment [LIB_MANAGER_RODATA ].size );
293
298
294
299
/* All writable data sections */
295
- mctx -> segment [ LIB_MANAGER_DATA ]. addr =
296
- ldr -> sects [ LLEXT_MEM_DATA ]. sh_addr ;
297
- mctx -> segment [LIB_MANAGER_DATA ].size = ldr -> sects [ LLEXT_MEM_DATA ]. sh_size ;
300
+ llext_get_region_info ( ldr , * llext , LLEXT_MEM_DATA , & hdr , NULL , NULL );
301
+ mctx -> segment [ LIB_MANAGER_DATA ]. addr = hdr -> sh_addr ;
302
+ mctx -> segment [LIB_MANAGER_DATA ].size = hdr -> sh_size ;
298
303
299
304
tr_dbg (& lib_manager_tr , ".data: start: %#lx size %#x" ,
300
305
mctx -> segment [LIB_MANAGER_DATA ].addr ,
301
306
mctx -> segment [LIB_MANAGER_DATA ].size );
302
307
303
- mctx -> segment [LIB_MANAGER_BSS ].addr = ldr -> sects [LLEXT_MEM_BSS ].sh_addr ;
304
- mctx -> segment [LIB_MANAGER_BSS ].size = ldr -> sects [LLEXT_MEM_BSS ].sh_size ;
308
+ /* Writable uninitialized data section */
309
+ llext_get_region_info (ldr , * llext , LLEXT_MEM_BSS , & hdr , NULL , NULL );
310
+ mctx -> segment [LIB_MANAGER_BSS ].addr = hdr -> sh_addr ;
311
+ mctx -> segment [LIB_MANAGER_BSS ].size = hdr -> sh_size ;
305
312
306
313
tr_dbg (& lib_manager_tr , ".bss: start: %#lx size %#x" ,
307
314
mctx -> segment [LIB_MANAGER_BSS ].addr ,
308
315
mctx -> segment [LIB_MANAGER_BSS ].size );
309
316
310
317
* buildinfo = NULL ;
311
- ssize_t binfo_o = llext_find_section (ldr , ".mod_buildinfo" );
312
-
313
- if (binfo_o >= 0 )
314
- * buildinfo = llext_peek (ldr , binfo_o );
318
+ ret = llext_section_shndx (ldr , * llext , ".mod_buildinfo" );
319
+ if (ret >= 0 ) {
320
+ llext_get_section_info (ldr , * llext , ret , & hdr , NULL , NULL );
321
+ * buildinfo = llext_peek (ldr , hdr -> sh_offset );
322
+ }
315
323
316
324
* mod_manifest = NULL ;
317
- ssize_t mod_o = llext_find_section (ldr , ".module" );
318
-
319
- if (mod_o >= 0 )
320
- * mod_manifest = llext_peek (ldr , mod_o );
325
+ ret = llext_section_shndx (ldr , * llext , ".module" );
326
+ if (ret >= 0 ) {
327
+ llext_get_section_info (ldr , * llext , ret , & hdr , NULL , NULL );
328
+ * mod_manifest = llext_peek (ldr , hdr -> sh_offset );
329
+ }
321
330
322
331
return * buildinfo && * mod_manifest ? 0 : - EPROTO ;
323
332
}
@@ -622,7 +631,14 @@ int llext_manager_free_module(const uint32_t component_id)
622
631
623
632
/* Protected by IPC serialization */
624
633
if (mctx -> llext -> use_count > 1 ) {
625
- /* llext_unload() will return a positive number */
634
+ /*
635
+ * At least 2 users: llext_unload() will never actually free
636
+ * the extension but only reduce the refcount and return its
637
+ * new value (must be a positive number).
638
+ * NOTE: if this is modified to allow extension unload, the
639
+ * inspection data in the loader must be freed as well by
640
+ * calling the llext_free_inspection_data() function.
641
+ */
626
642
int ret = llext_unload (& mctx -> llext );
627
643
628
644
if (ret <= 0 ) {
0 commit comments