Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

llext: use the new inspection API #9823

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 86 additions & 44 deletions src/library_manager/llext_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <zephyr/llext/buf_loader.h>
#include <zephyr/llext/loader.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/inspect.h>

#include <rimage/sof/user/manifest.h>
#include <module/module/api_ver.h>
Expand Down Expand Up @@ -69,21 +70,25 @@ 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;
int ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW);
const elf_shdr_t *shdr;
const void *region_addr;
int ret;

ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW);
if (ret < 0) {
tr_err(&lib_manager_tr, "cannot map %u of %p", size, (__sparse_force void *)vma);
return ret;
}

/* DEBUG */
size_t init_offset = 0;
const elf_shdr_t *shdr;

/* 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++) {
Expand All @@ -97,8 +102,29 @@ static int llext_manager_load_data_from_storage(const struct llext *ext,
/* found a section within the region */
size_t offset = shdr->sh_offset - init_offset;

ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - offset,
load_base + offset, shdr->sh_size);
tr_info(&lib_manager_tr, "old %u: %p -> %p, %u", i,
(void *)shdr->sh_addr,
(const uint8_t *)ext->mem[region] + offset, shdr->sh_size);
}

llext_get_region_info(ldr, ext, region, NULL, &region_addr, NULL);

/* Need to copy sections within regions individually, offsets may differ */
for (i = 0; i < llext_section_count(ext); i++) {
enum llext_mem s_region = LLEXT_MEM_COUNT;
size_t s_offset = 0;

llext_get_section_info(ldr, ext, i, &shdr, &s_region, &s_offset);

if (s_region != region)
continue;

tr_info(&lib_manager_tr, "%u: %p -> %p, %u", i,
(void *)shdr->sh_addr,
(const uint8_t *)region_addr + s_offset, shdr->sh_size);

ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - s_offset,
(const uint8_t *)region_addr + s_offset, shdr->sh_size);
if (ret < 0)
return ret;
}
Expand All @@ -119,6 +145,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;
Expand All @@ -136,8 +166,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 */
Expand All @@ -150,7 +180,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 {
Expand All @@ -162,20 +192,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;

Expand Down Expand Up @@ -239,48 +269,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,
};
int ret = llext_load(&ebl->loader, name, llext, &ldr_parm);
const elf_shdr_t *hdr;
int ret;

ret = llext_load(&ebl->loader, name, 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, *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);
tr_info(&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, *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);
tr_info(&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;

tr_dbg(&lib_manager_tr, ".data: start: %#lx size %#x",
mctx->segment[LIB_MANAGER_DATA].addr,
mctx->segment[LIB_MANAGER_DATA].size);

ssize_t binfo_o = llext_find_section(&ebl->loader, ".mod_buildinfo");

if (binfo_o >= 0)
*buildinfo = llext_peek(&ebl->loader, binfo_o);

ssize_t mod_o = llext_find_section(&ebl->loader, ".module");
llext_get_region_info(&ebl->loader, *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_info(&lib_manager_tr, ".data: start: %#lx size %#x",
mctx->segment[LIB_MANAGER_DATA].addr,
mctx->segment[LIB_MANAGER_DATA].size);

*buildinfo = NULL;
ret = llext_section_shndx(&ebl->loader, *llext, ".mod_buildinfo");
if (ret >= 0) {
llext_get_section_info(&ebl->loader, *llext, ret, &hdr, NULL, NULL);
*buildinfo = llext_peek(&ebl->loader, hdr->sh_offset);
}

if (mod_o >= 0)
*mod_manifest = llext_peek(&ebl->loader, mod_o);
*mod_manifest = NULL;
ret = llext_section_shndx(&ebl->loader, *llext, ".module");
if (ret >= 0) {
llext_get_section_info(&ebl->loader, *llext, ret, &hdr, NULL, NULL);
*mod_manifest = llext_peek(&ebl->loader, hdr->sh_offset);
}

return binfo_o >= 0 && mod_o >= 0 ? 0 : -EPROTO;
return *buildinfo && *mod_manifest ? 0 : -EPROTO;
}

static int llext_manager_mod_init(struct lib_manager_mod_ctx *ctx,
Expand Down
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ manifest:

- name: zephyr
repo-path: zephyr
revision: 42701fdb27298d20b4040cea5cde375b72c27cfc
revision: pull/85498/head
remote: zephyrproject

# Import some projects listed in zephyr/west.yml@revision
Expand Down
Loading