Skip to content
Draft
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
11 changes: 11 additions & 0 deletions binfmt/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ static int elf_loadbinary(FAR struct binary_s *binp,

binp->mod.textalloc = (FAR void *)loadinfo.textalloc;
binp->mod.dataalloc = (FAR void *)loadinfo.datastart;
binp->mod.fdpic = loadinfo.fdpic;
binp->mod.gotbase = loadinfo.gotbase;
# ifdef CONFIG_BINFMT_CONSTRUCTORS
binp->mod.initarr = loadinfo.initarr;
binp->mod.finiarr = loadinfo.finiarr;
Expand Down Expand Up @@ -286,6 +288,15 @@ static int elf_loadbinary(FAR struct binary_s *binp,
}
#endif

#ifdef HAVE_LIBC_ELF_PIN
/* Past the last thing that can fail, so the module owns the pin: it is
* given back when the task that runs the module exits.
*/

binp->mod.pinfile = loadinfo.pinfile;
loadinfo.pinfile = NULL;
#endif

libelf_uninitialize(&loadinfo);
return OK;

Expand Down
12 changes: 12 additions & 0 deletions include/nuttx/lib/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,18 @@ struct module_s
uint16_t nsect; /* Number of entries in sectalloc array */
#endif
int dynamic; /* Module is a dynamic shared object */
bool fdpic; /* Module is an FDPIC object: its two
* segments were placed separately and
* the text is media, not an allocation
*/
uintptr_t gotbase; /* An FDPIC object's data base, to
* enter its destructors with
*/
#ifdef HAVE_LIBC_ELF_PIN
FAR struct file *pinfile; /* Holds the XIP pin on the text until
* the module is unloaded
*/
#endif
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
size_t textsize; /* Size of the kernel .text memory allocation */
size_t datasize; /* Size of the kernel .bss/.data memory allocation */
Expand Down
18 changes: 18 additions & 0 deletions libs/libc/elf/elf_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,24 @@ static int libelf_relocatedyn(FAR struct module_s *modp,
case DT_PLTRELSZ:
reldata.relsz[I_PLT] = dyn[i].d_un.d_val;
break;
case DT_NEEDED:

/* Nothing loads DT_NEEDED yet, so refuse the module rather
* than let it fault on its first call into the library.
*/

if (loadinfo->fdpic)
{
berr("ERROR: FDPIC module has a DT_NEEDED entry. Shared "
"libraries are not supported; link it statically.\n");
lib_free(sym);
lib_free(rels);
lib_free(dyn);
return -ENOEXEC;
}

break;

case DT_PLTGOT:

/* The object's data base. Every function descriptor built
Expand Down
37 changes: 36 additions & 1 deletion libs/libc/elf/elf_insert.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <sys/param.h>

#include <nuttx/lib/lib.h>
#include <nuttx/fdpic.h>
#include <nuttx/lib/elf.h>

#include "elf.h"
Expand Down Expand Up @@ -404,6 +405,12 @@ FAR void *libelf_insert(FAR const char *filename, FAR const char *modname)

modp->textalloc = (FAR void *)loadinfo.textalloc;
modp->dataalloc = (FAR void *)loadinfo.datastart;
modp->fdpic = loadinfo.fdpic;
modp->gotbase = loadinfo.gotbase;
#ifdef HAVE_LIBC_ELF_PIN
modp->pinfile = loadinfo.pinfile;
loadinfo.pinfile = NULL;
#endif
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
modp->sectalloc = (FAR void **)loadinfo.sectalloc;
modp->nsect = loadinfo.ehdr.e_shnum;
Expand All @@ -421,11 +428,26 @@ FAR void *libelf_insert(FAR const char *filename, FAR const char *modname)
case ET_REL :
case ET_DYN :

/* Process any preinit_array entries */
/* Process any preinit_array entries. An FDPIC object's
* constructors need its own data base, not the loading thread's.
*/

array = (FAR void (**)(void))loadinfo.preiarr;
for (i = 0; i < loadinfo.nprei; i++)
{
#ifdef CONFIG_FDPIC
if (loadinfo.fdpic)
{
struct fdpic_desc_s desc;

desc.entry = (uintptr_t)array[i];
desc.got = loadinfo.gotbase;

fdpic_invoke(0, &desc);
continue;
}
#endif

array[i]();
}

Expand All @@ -434,6 +456,19 @@ FAR void *libelf_insert(FAR const char *filename, FAR const char *modname)
array = (FAR void (**)(void))loadinfo.initarr;
for (i = 0; i < loadinfo.ninit; i++)
{
#ifdef CONFIG_FDPIC
if (loadinfo.fdpic)
{
struct fdpic_desc_s desc;

desc.entry = (uintptr_t)array[i];
desc.got = loadinfo.gotbase;

fdpic_invoke(0, &desc);
continue;
}
#endif

array[i]();
}

Expand Down
47 changes: 47 additions & 0 deletions libs/libc/elf/elf_remove.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@

#include <nuttx/arch.h>
#include <nuttx/lib/lib.h>
#include <nuttx/fdpic.h>
#include <nuttx/lib/elf.h>

#include "elf/elf.h"

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -64,6 +67,24 @@ int libelf_uninit(FAR struct module_s *modp)
array = (FAR void (**)(void))modp->finiarr;
for (i = 0; i < modp->nfini; i++)
{
/* Like the constructors, an FDPIC object's destructors reach its
* globals through its own data base, which the unloading thread does
* not carry.
*/

#ifdef CONFIG_FDPIC
if (modp->fdpic)
{
struct fdpic_desc_s desc;

desc.entry = (uintptr_t)array[i];
desc.got = modp->gotbase;

fdpic_invoke(0, &desc);
continue;
}
#endif

array[i]();
}

Expand Down Expand Up @@ -93,6 +114,14 @@ int libelf_uninit(FAR struct module_s *modp)
#endif
}

#ifdef HAVE_LIBC_ELF_PIN
/* Give the pin back before the text goes out of use. This does nothing if
* the loader took no pin.
*/

libelf_pinrelease(&modp->pinfile);
#endif

/* Release resources held by the module */

if (modp->textalloc != NULL || modp->dataalloc != NULL)
Expand Down Expand Up @@ -148,6 +177,24 @@ int libelf_uninit(FAR struct module_s *modp)
# endif
#endif
}
else if (modp->fdpic)
{
/* An FDPIC object placed its two segments separately. Free each
* one. If the text stayed on the media, it was never allocated,
* thus leave it.
*/

if (modp->xipbase == 0)
{
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)modp->textalloc);
#else
lib_free((FAR void *)modp->textalloc);
#endif
}

lib_free((FAR void *)modp->dataalloc);
}
else
{
lib_free((FAR void *)modp->textalloc);
Expand Down
Loading