binfmt:use modlib api inside of elf api [1/2]

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao
2024-07-09 23:30:04 +08:00
committed by Xiang Xiao
parent 2931d1e85f
commit 1fc2cd7816
20 changed files with 81 additions and 343 deletions

View File

@@ -51,12 +51,17 @@ config ELF
default n
select BINFMT_LOADABLE
select LIBC_ARCH_ELF
select LIBC_MODLIB
select ARCH_USE_TEXT_HEAP if ARCH_HAVE_TEXT_HEAP
---help---
Enable support for the ELF binary format. Default: n
if ELF
source "binfmt/libelf/Kconfig"
config ELF_STACKSIZE
int "ELF Stack Size"
default DEFAULT_TASK_STACKSIZE
---help---
This is the default stack size that will be used when starting ELF binaries.
endif
endif

View File

@@ -57,7 +57,6 @@ endif
# Add configured binary modules
include libnxflat/Make.defs
include libelf/Make.defs
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)sched

View File

@@ -61,13 +61,6 @@ int binfmt_dumpmodule(FAR const struct binary_s *bin)
binfo("Module:\n");
binfo(" entrypt: %p\n", bin->entrypt);
binfo(" mapped: %p size=%zd\n", bin->mapped, bin->mapsize);
binfo(" alloc: %p %p %p\n", bin->alloc[0],
bin->alloc[1],
bin->alloc[2]);
#ifdef CONFIG_BINFMT_CONSTRUCTORS
binfo(" ctors: %p nctors=%d\n", bin->ctors, bin->nctors);
binfo(" dtors: %p ndtors=%d\n", bin->dtors, bin->ndtors);
#endif
#ifdef CONFIG_ARCH_ADDRENV
binfo(" addrenv: %p\n", bin->addrenv);
#endif

View File

@@ -86,12 +86,12 @@
static void exec_ctors(FAR void *arg)
{
FAR const struct binary_s *binp = (FAR const struct binary_s *)arg;
binfmt_ctor_t *ctor = binp->ctors;
binfmt_ctor_t *ctor = (CODE binfmt_ctor_t *)binp->mod.initarr;
int i;
/* Execute each constructor */
for (i = 0; i < binp->nctors; i++)
for (i = 0; i < binp->mod.ninit; i++)
{
binfo("Calling ctor %d at %p\n", i, ctor);
@@ -338,7 +338,7 @@ int exec_module(FAR struct binary_s *binp,
* must be the first allocated address space.
*/
tcb->cmn.dspace = binp->alloc[0];
tcb->cmn.dspace = binp->picbase;
/* Re-initialize the task's initial state to account for the new PIC base */
@@ -362,7 +362,7 @@ int exec_module(FAR struct binary_s *binp,
* until the new task has been started.
*/
if (binp->nctors > 0)
if (binp->mod.ninit > 0)
{
nxtask_starthook(tcb, exec_ctors, binp);
}

View File

@@ -44,61 +44,6 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: exec_dtors
*
* Description:
* Execute C++ static destructors.
*
* Input Parameters:
* binp - Load state information
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
#ifdef CONFIG_BINFMT_CONSTRUCTORS
static inline int exec_dtors(FAR struct binary_s *binp)
{
binfmt_dtor_t *dtor = binp->dtors;
#ifdef CONFIG_ARCH_ADDRENV
int ret;
#endif
int i;
/* Instantiate the address environment containing the destructors */
#ifdef CONFIG_ARCH_ADDRENV
ret = addrenv_select(binp->addrenv, &binp->oldenv);
if (ret < 0)
{
berr("ERROR: addrenv_select() failed: %d\n", ret);
return ret;
}
#endif
/* Execute each destructor */
for (i = 0; i < binp->ndtors; i++)
{
binfo("Calling dtor %d at %p\n", i, dtor);
(*dtor)();
dtor++;
}
/* Restore the address environment */
#ifdef CONFIG_ARCH_ADDRENV
return addrenv_restore(binp->oldenv);
#else
return OK;
#endif
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -125,7 +70,6 @@ static inline int exec_dtors(FAR struct binary_s *binp)
int unload_module(FAR struct binary_s *binp)
{
int ret;
int i;
if (binp)
{
@@ -141,17 +85,6 @@ int unload_module(FAR struct binary_s *binp)
}
}
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/* Execute C++ destructors */
ret = exec_dtors(binp);
if (ret < 0)
{
berr("exec_ctors() failed: %d\n", ret);
return ret;
}
#endif
/* Unmap mapped address spaces */
if (binp->mapped)
@@ -161,60 +94,6 @@ int unload_module(FAR struct binary_s *binp)
file_munmap(binp->mapped, binp->mapsize);
}
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
for (i = 0; binp->sectalloc[i] != NULL && i < binp->nsect; i++)
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
if (up_textheap_heapmember(binp->sectalloc[i]))
{
up_textheap_free(binp->sectalloc[i]);
}
else
# endif
# ifdef CONFIG_ARCH_USE_DATA_HEAP
if (up_dataheap_heapmember(binp->sectalloc[i]))
{
up_dataheap_free(binp->sectalloc[i]);
}
else
# endif
{
kumm_free(binp->sectalloc[i]);
}
}
binp->alloc[0] = NULL;
binp->alloc[1] = NULL;
#endif
/* Free allocated address spaces */
for (i = 0; i < BINFMT_NALLOC; i++)
{
if (binp->alloc[i])
{
binfo("Freeing alloc[%d]: %p\n", i, binp->alloc[i]);
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
if (i == 0)
{
up_textheap_free(binp->alloc[i]);
}
else
#endif
#if defined(CONFIG_ARCH_USE_DATA_HEAP)
if (i == 1)
{
up_dataheap_free(binp->alloc[i]);
}
else
#endif
{
kumm_free(binp->alloc[i]);
}
}
}
/* Notice that the address environment is not destroyed. This should
* happen automatically when the task exits.
*/

View File

@@ -44,23 +44,17 @@
****************************************************************************/
/* CONFIG_DEBUG_FEATURES, CONFIG_DEBUG_INFO, and CONFIG_DEBUG_BINFMT
* have to be defined or CONFIG_ELF_DUMPBUFFER does nothing.
* have to be defined or CONFIG_MODLIB_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_INFO) || !defined(CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
# undef CONFIG_MODLIB_DUMPBUFFER
#endif
#ifndef CONFIG_ELF_STACKSIZE
# define CONFIG_ELF_STACKSIZE 2048
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
# define elf_dumpbuffer(m,b,n) binfodumpbuffer(m,b,n)
#else
# define elf_dumpbuffer(m,b,n)
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -69,9 +63,8 @@ static int elf_loadbinary(FAR struct binary_s *binp,
FAR const char *filename,
FAR const struct symtab_s *exports,
int nexports);
#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_BINFMT)
static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo);
#endif
static int elf_unloadbinary(FAR struct binary_s *binp);
/****************************************************************************
* Private Data
@@ -81,148 +74,13 @@ static struct binfmt_s g_elfbinfmt =
{
NULL, /* next */
elf_loadbinary, /* load */
NULL, /* unload */
elf_unloadbinary, /* unload */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: elf_dumploadinfo
****************************************************************************/
#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_BINFMT)
static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
{
int i;
binfo("LOAD_INFO:\n");
binfo(" textalloc: %08lx\n", (long)loadinfo->textalloc);
binfo(" dataalloc: %08lx\n", (long)loadinfo->dataalloc);
binfo(" textsize: %ld\n", (long)loadinfo->textsize);
binfo(" datasize: %ld\n", (long)loadinfo->datasize);
binfo(" textalign: %zu\n", loadinfo->textalign);
binfo(" dataalign: %zu\n", loadinfo->dataalign);
binfo(" filelen: %ld\n", (long)loadinfo->filelen);
#ifdef CONFIG_BINFMT_CONSTRUCTORS
binfo(" ctoralloc: %08lx\n", (long)loadinfo->ctoralloc);
binfo(" ctors: %08lx\n", (long)loadinfo->ctors);
binfo(" nctors: %d\n", loadinfo->nctors);
binfo(" dtoralloc: %08lx\n", (long)loadinfo->dtoralloc);
binfo(" dtors: %08lx\n", (long)loadinfo->dtors);
binfo(" ndtors: %d\n", loadinfo->ndtors);
#endif
binfo(" symtabidx: %d\n", loadinfo->symtabidx);
binfo(" strtabidx: %d\n", loadinfo->strtabidx);
binfo("ELF Header:\n");
binfo(" e_ident: %02x %02x %02x %02x\n",
loadinfo->ehdr.e_ident[0], loadinfo->ehdr.e_ident[1],
loadinfo->ehdr.e_ident[2], loadinfo->ehdr.e_ident[3]);
binfo(" e_type: %04x\n", loadinfo->ehdr.e_type);
binfo(" e_machine: %04x\n", loadinfo->ehdr.e_machine);
binfo(" e_version: %08x\n", loadinfo->ehdr.e_version);
binfo(" e_entry: %08lx\n", (long)loadinfo->ehdr.e_entry);
binfo(" e_phoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_phoff);
binfo(" e_shoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_shoff);
binfo(" e_flags: %08x\n" , loadinfo->ehdr.e_flags);
binfo(" e_ehsize: %d\n", loadinfo->ehdr.e_ehsize);
binfo(" e_phentsize: %d\n", loadinfo->ehdr.e_phentsize);
binfo(" e_phnum: %d\n", loadinfo->ehdr.e_phnum);
binfo(" e_shentsize: %d\n", loadinfo->ehdr.e_shentsize);
binfo(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
binfo(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
if (loadinfo->phdr && loadinfo->ehdr.e_phnum > 0)
{
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
{
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
binfo("Programs %d:\n", i);
binfo(" p_type: %08jx\n", (uintmax_t)phdr->p_type);
binfo(" p_offset: %08jx\n", (uintmax_t)phdr->p_offset);
binfo(" p_vaddr: %08jx\n", (uintmax_t)phdr->p_vaddr);
binfo(" p_paddr: %08jx\n", (uintmax_t)phdr->p_paddr);
binfo(" p_filesz: %08jx\n", (uintmax_t)phdr->p_filesz);
binfo(" p_memsz: %08jx\n", (uintmax_t)phdr->p_memsz);
binfo(" p_flags: %08jx\n", (uintmax_t)phdr->p_flags);
binfo(" p_align: %08x\n", phdr->p_align);
}
}
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
{
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type == ET_REL)
{
binfo(" sh_alloc: %08jx\n",
(uintmax_t)loadinfo->sectalloc[i]);
}
# endif
binfo("Sections %d:\n", i);
binfo(" sh_name: %08x\n", shdr->sh_name);
binfo(" sh_type: %08x\n", shdr->sh_type);
binfo(" sh_flags: %08jx\n", (uintmax_t)shdr->sh_flags);
binfo(" sh_addr: %08jx\n", (uintmax_t)shdr->sh_addr);
binfo(" sh_offset: %ju\n", (uintmax_t)shdr->sh_offset);
binfo(" sh_size: %ju\n", (uintmax_t)shdr->sh_size);
binfo(" sh_link: %d\n", shdr->sh_link);
binfo(" sh_info: %d\n", shdr->sh_info);
binfo(" sh_addralign: %ju\n", (uintmax_t)shdr->sh_addralign);
binfo(" sh_entsize: %ju\n", (uintmax_t)shdr->sh_entsize);
}
}
}
#else
# define elf_dumploadinfo(i)
#endif
/****************************************************************************
* Name: elf_dumpentrypt
****************************************************************************/
#ifdef CONFIG_ELF_DUMPBUFFER
static void elf_dumpentrypt(FAR struct binary_s *binp,
FAR struct elf_loadinfo_s *loadinfo)
{
#ifdef CONFIG_ARCH_ADDRENV
int ret;
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_addrenv_select() failed: %d\n", ret);
return;
}
#endif
elf_dumpbuffer("Entry code", (FAR const uint8_t *)binp->entrypt,
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the original address environment */
ret = elf_addrenv_restore(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_addrenv_restore() failed: %d\n", ret);
}
#endif
}
#else
# define elf_dumpentrypt(b,l)
#endif
/****************************************************************************
* Name: elf_loadbinary
*
@@ -237,25 +95,25 @@ static int elf_loadbinary(FAR struct binary_s *binp,
FAR const struct symtab_s *exports,
int nexports)
{
struct elf_loadinfo_s loadinfo; /* Contains globals for libelf */
int ret;
struct mod_loadinfo_s loadinfo;
int ret;
binfo("Loading file: %s\n", filename);
/* Initialize the ELF library to load the program binary. */
ret = elf_init(filename, &loadinfo);
elf_dumploadinfo(&loadinfo);
ret = modlib_initialize(filename, &loadinfo);
modlib_dumploadinfo(&loadinfo);
if (ret != 0)
{
berr("Failed to initialize for load of ELF program: %d\n", ret);
goto errout_with_init;
berr("Failed to initialize to load ELF program binary: %d\n", ret);
return ret;
}
/* Load the program binary */
ret = elf_load(&loadinfo);
elf_dumploadinfo(&loadinfo);
ret = modlib_load_with_addrenv(&loadinfo);
modlib_dumploadinfo(&loadinfo);
if (ret != 0)
{
berr("Failed to load ELF program binary: %d\n", ret);
@@ -266,7 +124,7 @@ static int elf_loadbinary(FAR struct binary_s *binp,
if (loadinfo.ehdr.e_type == ET_REL)
{
ret = elf_bind(&loadinfo, exports, nexports);
ret = modlib_bind(&binp->mod, &loadinfo, exports, nexports);
if (ret != 0)
{
berr("Failed to bind symbols program binary: %d\n", ret);
@@ -320,27 +178,27 @@ static int elf_loadbinary(FAR struct binary_s *binp,
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo.ehdr.e_type == ET_REL)
{
binp->sectalloc = (FAR void *)loadinfo.sectalloc;
binp->nsect = loadinfo.ehdr.e_shnum;
binp->mod.sectalloc = (FAR void *)loadinfo.sectalloc;
binp->mod.nsect = loadinfo.ehdr.e_shnum;
}
# endif
binp->alloc[0] = (FAR void *)loadinfo.textalloc;
binp->alloc[1] = (FAR void *)loadinfo.dataalloc;
binp->mod.textalloc = (FAR void *)loadinfo.textalloc;
binp->mod.dataalloc = (FAR void *)loadinfo.datastart;
# ifdef CONFIG_BINFMT_CONSTRUCTORS
binp->alloc[2] = loadinfo.ctoralloc;
binp->alloc[3] = loadinfo.dtoralloc;
binp->mod.initarr = loadinfo.initarr;
binp->mod.finiarr = loadinfo.finiarr;
# endif
#endif
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/* Save information about constructors and destructors. */
binp->ctors = loadinfo.ctors;
binp->nctors = loadinfo.nctors;
binp->mod.initarr = loadinfo.initarr;
binp->mod.ninit = loadinfo.ninit;
binp->dtors = loadinfo.dtors;
binp->ndtors = loadinfo.ndtors;
binp->mod.finiarr = loadinfo.finiarr;
binp->mod.nfini = loadinfo.nfini;
#endif
#ifdef CONFIG_SCHED_USER_IDENTITY
@@ -351,17 +209,33 @@ static int elf_loadbinary(FAR struct binary_s *binp,
binp->mode = loadinfo.filemode;
#endif
elf_dumpentrypt(binp, &loadinfo);
elf_uninit(&loadinfo);
modlib_dumpentrypt(&loadinfo);
modlib_uninitialize(&loadinfo);
return OK;
errout_with_load:
elf_unload(&loadinfo);
modlib_unload(&loadinfo);
errout_with_init:
elf_uninit(&loadinfo);
modlib_uninitialize(&loadinfo);
return ret;
}
/****************************************************************************
* Name: elf_unloadbinary
*
* Description:
* Unload the ELF binary that was loaded into memory by elf_loadbinary.
*
****************************************************************************/
static int elf_unloadbinary(FAR struct binary_s *binp)
{
binfo("Unloading %p\n", binp);
modlib_uninit(&binp->mod);
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@@ -193,7 +193,7 @@ static int nxflat_loadbinary(FAR struct binary_s *binp,
#ifdef CONFIG_ARCH_ADDRENV
# warning "REVISIT"
#else
binp->alloc[0] = (FAR void *)loadinfo.dspace;
binp->picbase = (FAR void *)loadinfo.dspace;
#endif
#ifdef CONFIG_ARCH_ADDRENV
@@ -229,7 +229,7 @@ errout:
static int nxflat_unloadbinary(FAR struct binary_s *binp)
{
FAR struct dspace_s *dspace = (FAR struct dspace_s *)binp->alloc[0];
FAR struct dspace_s *dspace = (FAR struct dspace_s *)binp->picbase;
/* Check if this is the last reference to dspace. It may still be needed
* by other threads. In that case, it must persist after this thread
@@ -243,9 +243,9 @@ static int nxflat_unloadbinary(FAR struct binary_s *binp)
kumm_free(dspace->region);
dspace->region = NULL;
/* Mark alloc[0] (dspace) as freed */
/* Mark picbase (dspace) as freed */
binp->alloc[0] = NULL;
binp->picbase = NULL;
/* The reference count will be decremented to zero and the dspace
* container will be freed in sched/nxsched_release_tcb.c