diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 402cc0219304..8447f2c7d822 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -69,12 +70,15 @@ static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size) return sys_mm_drv_unmap_region(aligned_vma, ALIGN_UP(pre_pad_size + size, PAGE_SZ)); } -static int llext_manager_load_data_from_storage(const struct llext *ext, +static int llext_manager_load_data_from_storage(const struct llext_loader *ldr, + const struct llext *ext, + enum llext_mem region, void __sparse_cache *vma, - const uint8_t *load_base, size_t size, uint32_t flags) { unsigned int i; + void *region_addr; + size_t region_size; int ret; ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW); @@ -83,22 +87,21 @@ static int llext_manager_load_data_from_storage(const struct llext *ext, return ret; } - size_t init_offset = 0; + llext_get_region_info(ldr, ext, region, NULL, ®ion_addr, ®ion_size); /* Need to copy sections within regions individually, offsets may differ */ - for (i = 0, shdr = llext_section_headers(ext); i < llext_section_count(ext); i++, shdr++) { - if ((uintptr_t)shdr->sh_addr < (uintptr_t)vma || - (uintptr_t)shdr->sh_addr >= (uintptr_t)vma + size) - continue; + for (i = 0; i < llext_section_count(ext); i++) { + const elf_shdr_t *shdr; + enum llext_mem s_region = LLEXT_MEM_COUNT; + size_t s_offset = 0; - if (!init_offset) - init_offset = shdr->sh_offset; + llext_get_section_info(ldr, ext, i, &shdr, &s_region, &s_offset); - /* found a section within the region */ - size_t offset = shdr->sh_offset - init_offset; + if (s_region != region) + continue; - ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - offset, - load_base + offset, shdr->sh_size); + ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - s_offset, + (uint8_t *)region_addr + s_offset, shdr->sh_size); if (ret < 0) return ret; } @@ -119,6 +122,10 @@ static int llext_manager_load_data_from_storage(const struct llext *ext, static int llext_manager_load_module(const struct llext *ext, const struct llext_buf_loader *ebl, const struct lib_manager_module *mctx) { + const elf_shdr_t *bss_hdr; + + llext_get_region_info(&ebl->loader, ext, LLEXT_MEM_BSS, &bss_hdr, NULL, NULL); + /* Executable code (.text) */ void __sparse_cache *va_base_text = (void __sparse_cache *) mctx->segment[LIB_MANAGER_TEXT].addr; @@ -136,8 +143,8 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext /* .bss, should be within writable data above */ void __sparse_cache *bss_addr = (void __sparse_cache *) - ebl->loader.sects[LLEXT_MEM_BSS].sh_addr; - size_t bss_size = ebl->loader.sects[LLEXT_MEM_BSS].sh_size; + bss_hdr->sh_addr; + size_t bss_size = bss_hdr->sh_size; int ret; /* Check, that .bss is within .data */ @@ -150,7 +157,7 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext va_base_data = bss_addr; data_size += bss_size; } else if ((uintptr_t)bss_addr == (uintptr_t)va_base_data + - ALIGN_UP(data_size, ebl->loader.sects[LLEXT_MEM_BSS].sh_addralign)) { + ALIGN_UP(data_size, bss_hdr->sh_addralign)) { /* .bss directly behind writable data, append */ data_size += bss_size; } else { @@ -162,20 +169,20 @@ static int llext_manager_load_module(const struct llext *ext, const struct llext } /* Copy Code */ - ret = llext_manager_load_data_from_storage(ext, va_base_text, ext->mem[LLEXT_MEM_TEXT], - text_size, SYS_MM_MEM_PERM_EXEC); + ret = llext_manager_load_data_from_storage(&ebl->loader, ext, LLEXT_MEM_TEXT, + va_base_text, text_size, SYS_MM_MEM_PERM_EXEC); if (ret < 0) return ret; /* Copy read-only data */ - ret = llext_manager_load_data_from_storage(ext, va_base_rodata, ext->mem[LLEXT_MEM_RODATA], - rodata_size, 0); + ret = llext_manager_load_data_from_storage(&ebl->loader, ext, LLEXT_MEM_RODATA, + va_base_rodata, rodata_size, 0); if (ret < 0) goto e_text; /* Copy writable data */ - ret = llext_manager_load_data_from_storage(ext, va_base_data, ext->mem[LLEXT_MEM_DATA], - data_size, SYS_MM_MEM_PERM_RW); + ret = llext_manager_load_data_from_storage(&ebl->loader, ext, LLEXT_MEM_DATA, + va_base_data, data_size, SYS_MM_MEM_PERM_RW); if (ret < 0) goto e_rodata; @@ -239,49 +246,60 @@ static int llext_manager_link(struct llext_buf_loader *ebl, const char *name, .relocate_local = !mctx->segment[LIB_MANAGER_TEXT].size, .pre_located = true, .section_detached = llext_manager_section_detached, + .keep_section_info = true, }; + const elf_shdr_t *hdr; int ret; ret = llext_load(&ebl->loader, name, &md->llext, &ldr_parm); if (ret) return ret; - mctx->segment[LIB_MANAGER_TEXT].addr = ebl->loader.sects[LLEXT_MEM_TEXT].sh_addr; - mctx->segment[LIB_MANAGER_TEXT].size = ebl->loader.sects[LLEXT_MEM_TEXT].sh_size; + /* All code sections */ + llext_get_region_info(&ebl->loader, md->llext, LLEXT_MEM_TEXT, + &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_TEXT].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_TEXT].size = hdr->sh_size; tr_dbg(&lib_manager_tr, ".text: start: %#lx size %#x", mctx->segment[LIB_MANAGER_TEXT].addr, mctx->segment[LIB_MANAGER_TEXT].size); /* All read-only data sections */ - mctx->segment[LIB_MANAGER_RODATA].addr = - ebl->loader.sects[LLEXT_MEM_RODATA].sh_addr; - mctx->segment[LIB_MANAGER_RODATA].size = ebl->loader.sects[LLEXT_MEM_RODATA].sh_size; + llext_get_region_info(&ebl->loader, md->llext, LLEXT_MEM_RODATA, + &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_RODATA].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_RODATA].size = hdr->sh_size; tr_dbg(&lib_manager_tr, ".rodata: start: %#lx size %#x", mctx->segment[LIB_MANAGER_RODATA].addr, mctx->segment[LIB_MANAGER_RODATA].size); /* All writable data sections */ - mctx->segment[LIB_MANAGER_DATA].addr = - ebl->loader.sects[LLEXT_MEM_DATA].sh_addr; - mctx->segment[LIB_MANAGER_DATA].size = ebl->loader.sects[LLEXT_MEM_DATA].sh_size; + llext_get_region_info(&ebl->loader, md->llext, LLEXT_MEM_DATA, + &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_DATA].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_DATA].size = hdr->sh_size; tr_dbg(&lib_manager_tr, ".data: start: %#lx size %#x", mctx->segment[LIB_MANAGER_DATA].addr, mctx->segment[LIB_MANAGER_DATA].size); *buildinfo = NULL; - ssize_t binfo_o = llext_find_section(&ebl->loader, ".mod_buildinfo"); - - if (binfo_o >= 0) - *buildinfo = llext_peek(&ebl->loader, binfo_o); + ret = llext_section_shndx(&ebl->loader, md->llext, ".mod_buildinfo"); + if (ret >= 0) { + llext_get_section_info(&ebl->loader, md->llext, ret, &hdr, NULL, NULL); + *buildinfo = llext_peek(&ebl->loader, hdr->sh_offset); + } *mod_manifest = NULL; - ssize_t mod_o = llext_find_section(&ebl->loader, ".module"); + ret = llext_section_shndx(&ebl->loader, md->llext, ".module"); + if (ret >= 0) { + llext_get_section_info(&ebl->loader, md->llext, ret, &hdr, NULL, NULL); + *mod_manifest = llext_peek(&ebl->loader, hdr->sh_offset); + } - if (mod_o >= 0) - *mod_manifest = llext_peek(&ebl->loader, mod_o); + llext_free_inspection_data(&ebl->loader, md->llext); return buildinfo && mod_manifest ? 0 : -EPROTO; }