summaryrefslogtreecommitdiff
path: root/nuttx/binfmt
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-08-24 11:54:14 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-08-24 11:54:14 -0600
commit3db6a65a749d241ce39e0028951b48f814e09dd4 (patch)
treee70d159d637d57ee436b6d204018d666517f7c37 /nuttx/binfmt
parent112e979b453108400d12c5825d0ed05336142e56 (diff)
downloadnuttx-3db6a65a749d241ce39e0028951b48f814e09dd4.tar.gz
nuttx-3db6a65a749d241ce39e0028951b48f814e09dd4.tar.bz2
nuttx-3db6a65a749d241ce39e0028951b48f814e09dd4.zip
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().
Diffstat (limited to 'nuttx/binfmt')
-rw-r--r--nuttx/binfmt/binfmt_execmodule.c4
-rw-r--r--nuttx/binfmt/libelf/libelf.h22
-rw-r--r--nuttx/binfmt/libelf/libelf_addrenv.c62
-rw-r--r--nuttx/binfmt/libelf/libelf_bind.c2
-rw-r--r--nuttx/binfmt/libelf/libelf_ctors.c5
-rw-r--r--nuttx/binfmt/libelf/libelf_dtors.c5
-rw-r--r--nuttx/binfmt/libelf/libelf_load.c61
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat.h8
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_addrenv.c18
9 files changed, 120 insertions, 67 deletions
diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c
index 0a2a15577..f415bccac 100644
--- a/nuttx/binfmt/binfmt_execmodule.c
+++ b/nuttx/binfmt/binfmt_execmodule.c
@@ -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
diff --git a/nuttx/binfmt/libelf/libelf.h b/nuttx/binfmt/libelf/libelf.h
index d407a31ae..8763e0808 100644
--- a/nuttx/binfmt/libelf/libelf.h
+++ b/nuttx/binfmt/libelf/libelf.h
@@ -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
diff --git a/nuttx/binfmt/libelf/libelf_addrenv.c b/nuttx/binfmt/libelf/libelf_addrenv.c
index ea400a325..b112d869f 100644
--- a/nuttx/binfmt/libelf/libelf_addrenv.c
+++ b/nuttx/binfmt/libelf/libelf_addrenv.c
@@ -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
}
diff --git a/nuttx/binfmt/libelf/libelf_bind.c b/nuttx/binfmt/libelf/libelf_bind.c
index 9fd0fb73d..4d3d27f04 100644
--- a/nuttx/binfmt/libelf/libelf_bind.c
+++ b/nuttx/binfmt/libelf/libelf_bind.c
@@ -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;
diff --git a/nuttx/binfmt/libelf/libelf_ctors.c b/nuttx/binfmt/libelf/libelf_ctors.c
index 0dfe64449..6cf35a62a 100644
--- a/nuttx/binfmt/libelf/libelf_ctors.c
+++ b/nuttx/binfmt/libelf/libelf_ctors.c
@@ -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
diff --git a/nuttx/binfmt/libelf/libelf_dtors.c b/nuttx/binfmt/libelf/libelf_dtors.c
index 5cbba4851..e42ba6abf 100644
--- a/nuttx/binfmt/libelf/libelf_dtors.c
+++ b/nuttx/binfmt/libelf/libelf_dtors.c
@@ -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
diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c
index 600f85805..9f33abb40 100644
--- a/nuttx/binfmt/libelf/libelf_load.c
+++ b/nuttx/binfmt/libelf/libelf_load.c
@@ -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;
diff --git a/nuttx/binfmt/libnxflat/libnxflat.h b/nuttx/binfmt/libnxflat/libnxflat.h
index b9a00dde8..5c020414b 100644
--- a/nuttx/binfmt/libnxflat/libnxflat.h
+++ b/nuttx/binfmt/libnxflat/libnxflat.h
@@ -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
diff --git a/nuttx/binfmt/libnxflat/libnxflat_addrenv.c b/nuttx/binfmt/libnxflat/libnxflat_addrenv.c
index 7f3e35176..825135fc5 100644
--- a/nuttx/binfmt/libnxflat/libnxflat_addrenv.c
+++ b/nuttx/binfmt/libnxflat/libnxflat_addrenv.c
@@ -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: