mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 14:53:47 +08:00
addrenv interface changes: up_addrenv_create() may need to create .text and .bss/.data separately because of differing access privileges (read/execute vs read/write). And, as a consequence, up_addrenv_vaddr() needs to be split into up_addrenv_vtext(0 and up_addrenv_vdata().
This commit is contained in:
@@ -208,11 +208,11 @@ int exec_module(FAR const struct binary_s *binp)
|
||||
/* Assign the address environment to the new task group */
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
ret = up_addrenv_assign(binp->addrenv, tcb->cmn.group);
|
||||
ret = up_addrenv_assign(&binp->addrenv, tcb->cmn.group);
|
||||
if (ret < 0)
|
||||
{
|
||||
err = -ret;
|
||||
bdbg("up_addrenv_assign() failed: %d\n", ret);
|
||||
bdbg("ERROR: up_addrenv_assign() failed: %d\n", ret);
|
||||
goto errout_with_stack;
|
||||
}
|
||||
#endif
|
||||
|
||||
+13
-9
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* binfmt/libelf/libelf.h
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -264,23 +264,27 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo);
|
||||
* Name: elf_addrenv_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate memory for the ELF image (elfalloc). If CONFIG_ARCH_ADDRENV=n,
|
||||
* elfalloc will be allocated using kzalloc(). If CONFIG_ARCH_ADDRENV-y, then
|
||||
* elfalloc will be allocated using up_addrenv_create(). In either case,
|
||||
* there will be a unique instance of elfalloc (and stack) for each
|
||||
* instance of a process.
|
||||
* Allocate memory for the ELF image (textalloc and dataalloc). If
|
||||
* CONFIG_ARCH_ADDRENV=n, textalloc will be allocated using kzalloc() and
|
||||
* dataalloc will be a offset from textalloc. If CONFIG_ARCH_ADDRENV-y, then
|
||||
* textalloc and dataalloc will be allocated using up_addrenv_create(). In
|
||||
* either case, there will be a unique instance of textalloc and dataalloc
|
||||
* (and stack) for each instance of a process.
|
||||
*
|
||||
* Input Parameters:
|
||||
* loadinfo - Load state information
|
||||
* envsize - The size (in bytes) of the address environment needed for the
|
||||
* ELF image.
|
||||
* textsize - The size (in bytes) of the .text address environment needed
|
||||
* for the ELF image (read/execute).
|
||||
* datasize - The size (in bytes) of the .bss/.data address environment
|
||||
* needed for the ELF image (read/write).
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t envsize);
|
||||
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
|
||||
size_t datasize);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elf_addrenv_select
|
||||
|
||||
@@ -67,31 +67,36 @@
|
||||
* Name: elf_addrenv_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate memory for the ELF image (elfalloc). If CONFIG_ARCH_ADDRENV=n,
|
||||
* elfalloc will be allocated using kuzalloc(). If CONFIG_ARCH_ADDRENV-y, then
|
||||
* elfalloc will be allocated using up_addrenv_create(). In either case,
|
||||
* there will be a unique instance of elfalloc (and stack) for each
|
||||
* instance of a process.
|
||||
* Allocate memory for the ELF image (textalloc and dataalloc). If
|
||||
* CONFIG_ARCH_ADDRENV=n, textalloc will be allocated using kzalloc() and
|
||||
* dataalloc will be a offset from textalloc. If CONFIG_ARCH_ADDRENV-y, then
|
||||
* textalloc and dataalloc will be allocated using up_addrenv_create(). In
|
||||
* either case, there will be a unique instance of textalloc and dataalloc
|
||||
* (and stack) for each instance of a process.
|
||||
*
|
||||
* Input Parameters:
|
||||
* loadinfo - Load state information
|
||||
* envsize - The size (in bytes) of the address environment needed for the
|
||||
* ELF image.
|
||||
* textsize - The size (in bytes) of the .text address environment needed
|
||||
* for the ELF image (read/execute).
|
||||
* datasize - The size (in bytes) of the .bss/.data address environment
|
||||
* needed for the ELF image (read/write).
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t envsize)
|
||||
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
|
||||
size_t datasize)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
FAR void *vaddr;
|
||||
FAR void *vtext;
|
||||
FAR void *vdata;
|
||||
int ret;
|
||||
|
||||
/* Create an address environment for the new ELF task */
|
||||
|
||||
ret = up_addrenv_create(envsize, &loadinfo->addrenv);
|
||||
ret = up_addrenv_create(textsize, datasize, &loadinfo->addrenv);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
|
||||
@@ -104,24 +109,33 @@ int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t envsize)
|
||||
* selected.
|
||||
*/
|
||||
|
||||
ret = up_addrenv_vaddr(loadinfo->addrenv, &vaddr);
|
||||
ret = up_addrenv_vtext(loadinfo->addrenv, &vtext);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("ERROR: up_addrenv_vaddr failed: %d\n", ret);
|
||||
bdbg("ERROR: up_addrenv_vtext failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
loadinfo->elfalloc = (uintptr_t)vaddr;
|
||||
ret = up_addrenv_vdata(loadinfo->addrenv, textsize, &vdata);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("ERROR: up_adup_addrenv_vdatadrenv_vtext failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
loadinfo->textalloc = (uintptr_t)vaddr;
|
||||
loadinfo->dataalloc = (uintptr_t)vdata;
|
||||
return OK;
|
||||
#else
|
||||
/* Allocate memory to hold the ELF image */
|
||||
|
||||
loadinfo->elfalloc = (uintptr_t)kuzalloc(envsize);
|
||||
if (!loadinfo->elfalloc)
|
||||
loadinfo->textalloc = (uintptr_t)kuzalloc(textsize + datasize);
|
||||
if (!loadinfo->textalloc)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
loadinfo->dataalloc = loadinfo->textalloc + textsize;
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
@@ -159,18 +173,22 @@ void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo)
|
||||
|
||||
/* Clear out all indications of the allocated address environment */
|
||||
|
||||
loadinfo->elfalloc = 0;
|
||||
loadinfo->elfsize = 0;
|
||||
loadinfo->addrenv = 0;
|
||||
loadinfo->textalloc = 0;
|
||||
loadinfo->dataalloc = 0;
|
||||
loadinfo->textsize = 0;
|
||||
loadinfo->datasize = 0;
|
||||
loadinfo->addrenv = 0;
|
||||
#else
|
||||
/* If there is an allocation for the ELF image, free it */
|
||||
|
||||
if (loadinfo->elfalloc != 0)
|
||||
if (loadinfo->textalloc != 0)
|
||||
{
|
||||
kufree((FAR void *)loadinfo->elfalloc);
|
||||
loadinfo->elfalloc = 0;
|
||||
kufree((FAR void *)loadinfo->textalloc);
|
||||
}
|
||||
|
||||
loadinfo->elfsize = 0;
|
||||
loadinfo->textalloc = 0;
|
||||
loadinfo->dataalloc = 0;
|
||||
loadinfo->textsize = 0;
|
||||
loadinfo->datasize = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo,
|
||||
/* Flush the instruction cache before starting the newly loaded module */
|
||||
|
||||
#ifdef CONFIG_ELF_ICACHE
|
||||
arch_flushicache((FAR void*)loadinfo->elfalloc, loadinfo->elfsize);
|
||||
arch_flushicache((FAR void*)loadinfo->textalloc, loadinfo->textsize);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -192,9 +192,10 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
|
||||
FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]);
|
||||
|
||||
bvdbg("ctor %d: %08lx + %08lx = %08lx\n",
|
||||
i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc);
|
||||
i, *ptr, (unsigned long)loadinfo->txtalloc,
|
||||
(unsigned long)(*ptr + loadinfo->txtalloc));
|
||||
|
||||
*ptr += loadinfo->elfalloc;
|
||||
*ptr += loadinfo->txtalloc;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -192,9 +192,10 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
|
||||
FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->dtors)[i]);
|
||||
|
||||
bvdbg("dtor %d: %08lx + %08lx = %08lx\n",
|
||||
i, *ptr, loadinfo->elfalloc, *ptr + loadinfo->elfalloc);
|
||||
i, *ptr, (unsigned long)loadinfo->textalloc,
|
||||
(unsigned long)(*ptr + loadinfo->textalloc));
|
||||
|
||||
*ptr += loadinfo->elfalloc;
|
||||
*ptr += loadinfo->textalloc;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+47
-14
@@ -88,12 +88,15 @@
|
||||
|
||||
static void elf_elfsize(struct elf_loadinfo_s *loadinfo)
|
||||
{
|
||||
size_t elfsize;
|
||||
size_t textsize;
|
||||
size_t datasize;
|
||||
int i;
|
||||
|
||||
/* Accumulate the size each section into memory that is marked SHF_ALLOC */
|
||||
|
||||
elfsize = 0;
|
||||
textsize = 0;
|
||||
datasize = 0;
|
||||
|
||||
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
||||
{
|
||||
FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
|
||||
@@ -104,13 +107,25 @@ static void elf_elfsize(struct elf_loadinfo_s *loadinfo)
|
||||
|
||||
if ((shdr->sh_flags & SHF_ALLOC) != 0)
|
||||
{
|
||||
elfsize += ELF_ALIGNUP(shdr->sh_size);
|
||||
/* SHF_WRITE indicates that the section address space is write-
|
||||
* able
|
||||
*/
|
||||
|
||||
if ((shdr->sh_flags & SHF_WRITE) != 0)
|
||||
{
|
||||
datasize += ELF_ALIGNUP(shdr->sh_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
textsize += ELF_ALIGNUP(shdr->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the allocation size */
|
||||
|
||||
loadinfo->elfsize = elfsize;
|
||||
loadinfo->textsize = textsize;
|
||||
loadinfo->datasize = datasize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -129,13 +144,15 @@ static void elf_elfsize(struct elf_loadinfo_s *loadinfo)
|
||||
|
||||
static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
{
|
||||
FAR uint8_t *dest;
|
||||
FAR uint8_t *text;
|
||||
FAR uint8_t *data;
|
||||
FAR uint8_t **pptr;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Allocate (and zero) memory for the ELF file. */
|
||||
|
||||
ret = elf_addrenv_alloc(loadinfo, loadinfo->elfsize);
|
||||
ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("ERROR: elf_addrenv_alloc() failed: %d\n", ret);
|
||||
@@ -145,7 +162,8 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
/* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
|
||||
|
||||
bvdbg("Loaded sections:\n");
|
||||
dest = (FAR uint8_t*)loadinfo->elfalloc;
|
||||
text = (FAR uint8_t*)loadinfo->textalloc;
|
||||
data = (FAR uint8_t*)loadinfo->dataalloc;
|
||||
|
||||
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
||||
{
|
||||
@@ -165,8 +183,21 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
|
||||
if (shdr->sh_type != SHT_NOBITS)
|
||||
{
|
||||
/* If CONFIG_ARCH_ADDRENV=y, then 'dest' lies in a virtual address space
|
||||
* that may not be in place now. elf_addrenv_select() will
|
||||
/* SHF_WRITE indicates that the section address space is write-
|
||||
* able
|
||||
*/
|
||||
|
||||
if ((shdr->sh_flags & SHF_WRITE) != 0)
|
||||
{
|
||||
pptr = &data;
|
||||
}
|
||||
else
|
||||
{
|
||||
pptr = &text;
|
||||
}
|
||||
|
||||
/* If CONFIG_ARCH_ADDRENV=y, then 'text' lies in a virtual address
|
||||
* space that may not be in place now. elf_addrenv_select() will
|
||||
* temporarily instantiate that address space.
|
||||
*/
|
||||
|
||||
@@ -179,9 +210,9 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read the section data from sh_offset to dest */
|
||||
/* Read the section data from sh_offset to the memory region */
|
||||
|
||||
ret = elf_read(loadinfo, dest, shdr->sh_size, shdr->sh_offset);
|
||||
ret = elf_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("Failed to read section %d: %d\n", i, ret);
|
||||
@@ -202,12 +233,14 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
|
||||
/* Update sh_addr to point to copy in memory */
|
||||
|
||||
bvdbg("%d. %08x->%08x\n", i, (long)shdr->sh_addr, (long)dest);
|
||||
shdr->sh_addr = (uintptr_t)dest;
|
||||
bvdbg("%d. %08lx->%08lx\n", i,
|
||||
(unsigned long)shdr->sh_addr, (unsigned long)*pptr);
|
||||
|
||||
shdr->sh_addr = (uintptr_t)*pptr;
|
||||
|
||||
/* Setup the memory pointer for the next time through the loop */
|
||||
|
||||
dest += ELF_ALIGNUP(shdr->sh_size);
|
||||
*pptr += ELF_ALIGNUP(shdr->sh_size);
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
@@ -59,11 +59,9 @@
|
||||
* Name: nxflat_addrenv_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate memory for the ELF image (elfalloc). If CONFIG_ARCH_ADDRENV=n,
|
||||
* elfalloc will be allocated using kzalloc(). If CONFIG_ARCH_ADDRENV-y, then
|
||||
* elfalloc will be allocated using up_addrenv_create(). In either case,
|
||||
* there will be a unique instance of elfalloc (and stack) for each
|
||||
* instance of a process.
|
||||
* Allocate data memory for the NXFLAT image. If CONFIG_ARCH_ADDRENV=n,
|
||||
* memory will be allocated using kzalloc(). If CONFIG_ARCH_ADDRENV-y,
|
||||
* then memory will be allocated using up_addrenv_create().
|
||||
*
|
||||
* Input Parameters:
|
||||
* loadinfo - Load state information
|
||||
|
||||
@@ -68,11 +68,9 @@
|
||||
* Name: nxflat_addrenv_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate memory for the ELF image (elfalloc). If CONFIG_ARCH_ADDRENV=n,
|
||||
* elfalloc will be allocated using kuzalloc(). If CONFIG_ARCH_ADDRENV-y, then
|
||||
* elfalloc will be allocated using up_addrenv_create(). In either case,
|
||||
* there will be a unique instance of elfalloc (and stack) for each
|
||||
* instance of a process.
|
||||
* Allocate data memory for the NXFLAT image. If CONFIG_ARCH_ADDRENV=n,
|
||||
* memory will be allocated using kzalloc(). If CONFIG_ARCH_ADDRENV-y,
|
||||
* then memory will be allocated using up_addrenv_create().
|
||||
*
|
||||
* Input Parameters:
|
||||
* loadinfo - Load state information
|
||||
@@ -88,7 +86,7 @@ int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
|
||||
{
|
||||
FAR struct dspace_s *dspace;
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
FAR void *vaddr;
|
||||
FAR void *vdata;
|
||||
save_addrenv_t oldenv;
|
||||
int ret;
|
||||
#endif
|
||||
@@ -120,10 +118,10 @@ int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
|
||||
* selected.
|
||||
*/
|
||||
|
||||
ret = up_addrenv_vaddr(loadinfo->addrenv, &vaddr);
|
||||
ret = up_addrenv_vdata(loadinfo->addrenv, 0, &vdata);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("ERROR: up_addrenv_vaddr failed: %d\n", ret);
|
||||
bdbg("ERROR: up_addrenv_vdata failed: %d\n", ret);
|
||||
goto errout_with_addrenv;
|
||||
}
|
||||
|
||||
@@ -138,7 +136,7 @@ int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
|
||||
goto errout_with_addrenv;
|
||||
}
|
||||
|
||||
memset(vaddr, 0, envsize);
|
||||
memset(vdata, 0, envsize);
|
||||
|
||||
ret = up_addrenv_restore(oldenv);
|
||||
if (ret < 0)
|
||||
@@ -151,7 +149,7 @@ int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
|
||||
|
||||
loadinfo->dspace = dspace;
|
||||
dspace->crefs = 1;
|
||||
dspace->region = (FAR uint8_t *)vaddr;
|
||||
dspace->region = (FAR uint8_t *)vdata;
|
||||
return OK;
|
||||
|
||||
errout_with_addrenv:
|
||||
|
||||
Reference in New Issue
Block a user