diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html
index e76b2ce0a5..f67ccdc0d3 100644
--- a/Documentation/NuttxPortingGuide.html
+++ b/Documentation/NuttxPortingGuide.html
@@ -12,7 +12,7 @@
NuttX RTOS Porting Guide
- Last Updated: August 22, 2014
+ Last Updated: August 24, 2014
@@ -108,12 +108,13 @@
4.5 APIs Exported by NuttX to Architecture-Specific Logic
@@ -2968,12 +2973,12 @@ VxWorks provides the following comparable interface:
@@ -2983,7 +2988,7 @@ VxWorks provides the following comparable interface:
Function Prototype:
- int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv);
+ int up_addrenv_create(size_t textsize, size_t datasize, FAR group_addrenv_t *addrenv);
Description:
@@ -2992,7 +2997,8 @@ VxWorks provides the following comparable interface:
Input Parameters:
- envsize
: The size (in bytes) of the address environment needed by the task.
+ textsize
: The size (in bytes) of the .text
address environment needed by the task. This region may be read/execute only.
+ datasize
: The size (in bytes) of the .bss/.data
address environment needed by the task. This region may be read/write only.
addrenv
: The location to return the representation of the task address environment.
Returned Value:
@@ -3018,27 +3024,48 @@ VxWorks provides the following comparable interface:
Zero (OK
) on success; a negated errno
value on failure.
-
+
Function Prototype:
- int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr);
+ int up_addrenv_vtext(FAR group_addrenv_t addrenv, FAR void **vtext);
Description:
- Return the virtual address associated with the newly create address environment.
+ Return the virtual .text
address associated with the newly create address environment.
This function is used by the binary loaders in order get an address that can be used to initialize the new task.
Input Parameters:
addrenv
: The representation of the task address environment previously returned by up_addrenv_create.
- vaddr
: The location to return the virtual address.
+ vtext
: The location to return the virtual address.
Returned Value:
Zero (OK
) on success; a negated errno
value on failure.
-
+
+Function Prototype:
+
+ int up_addrenv_vdata(FAR group_addrenv_t addrenv, size_t textsize, FAR void **vdata);
+
+Description:
+
+ Return the virtual .text
address associated with the newly create address environment.
+ This function is used by the binary loaders in order get an address that can be used to initialize the new task.
+
+Input Parameters:
+
+ addrenv
: The representation of the task address environment previously returned by up_addrenv_create.
+ textsize
: For some implementations, the text and data will be saved in the same memory region (read/write/execute) and, in this case, the virtual address of the data just lies at this offset into the common region.
+ vdata
: The location to return the virtual address.
+
+Returned Value:
+
+ Zero (OK
) on success; a negated errno
value on failure.
+
+
+
Function Prototype:
int up_addrenv_select(group_addrenv_t addrenv, save_addrenv_t *oldenv);
@@ -3062,7 +3089,7 @@ VxWorks provides the following comparable interface:
Zero (OK
) on success; a negated errno
value on failure.
-
+
Function Prototype:
int up_addrenv_restore(save_addrenv_t oldenv);
@@ -3081,10 +3108,10 @@ VxWorks provides the following comparable interface:
Zero (OK
) on success; a negated errno
value on failure.
-
+
Function Prototype:
- int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group);
+ int up_addrenv_assign(FAR const group_addrenv_t *addrenv, FAR struct task_group_s *group);
Description:
@@ -3100,7 +3127,7 @@ VxWorks provides the following comparable interface:
Zero (OK
) on success; a negated errno
value on failure.
-
+
Function Prototype:
int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
@@ -3126,7 +3153,7 @@ VxWorks provides the following comparable interface:
Zero (OK
) on success; a negated errno
value on failure.
-
+
Function Prototype:
int up_addrenv_detach(FAR struct task_group_s *group, FAR struct task_group_s *tcb);
diff --git a/arch/arm/src/armv7-a/arm_addrenv.c b/arch/arm/src/armv7-a/arm_addrenv.c
index 5aa21aa6c5..d575a68c86 100644
--- a/arch/arm/src/armv7-a/arm_addrenv.c
+++ b/arch/arm/src/armv7-a/arm_addrenv.c
@@ -42,8 +42,10 @@
*
* up_addrenv_create - Create an address environment
* up_addrenv_destroy - Destroy an address environment.
- * up_addrenv_vaddr - Returns the virtual base address of the address
- * environment
+ * up_addrenv_vtext - Returns the virtual base address of the .text
+ * address environment
+ * up_addrenv_vdata - Returns the virtual base address of the .bss/.data
+ * address environment
* up_addrenv_select - Instantiate an address environment
* up_addrenv_restore - Restore an address environment
* up_addrenv_assign - Assign an address environment to a group
@@ -67,6 +69,7 @@
#include
+#include
#include
#include
@@ -102,8 +105,10 @@
* memory for the new task.
*
* Input Parameters:
- * envsize - The size (in bytes) of the address environment needed by the
- * task.
+ * textsize - The size (in bytes) of the .text address environment needed
+ * by the task. This region may be read/execute only.
+ * datasize - The size (in bytes) of the .data/.bss address environment
+ * needed by the task. This region may be read/write only.
* addrenv - The location to return the representation of the task address
* environment.
*
@@ -112,7 +117,8 @@
*
****************************************************************************/
-int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv)
+int up_addrenv_create(size_t textsize, size_t datasize,
+ FAR group_addrenv_t *addrenv)
{
#warning Missing logic
return -ENOSYS;
@@ -141,27 +147,62 @@ int up_addrenv_destroy(group_addrenv_t addrenv)
}
/****************************************************************************
- * Name: up_addrenv_vaddr
+ * Name: up_addrenv_vtext
*
* Description:
- * Return the virtual address associated with the newly create address
- * environment. This function is used by the binary loaders in order
- * get an address that can be used to initialize the new task.
+ * Return the virtual address associated with the newly create .text
+ * address environment. This function is used by the binary loaders in
+ * order get an address that can be used to initialize the new task.
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
- * vaddr - The location to return the virtual address.
+ * vtext - The location to return the virtual address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
-int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr)
+int up_addrenv_vtext(FAR group_addrenv_t addrenv, FAR void **vtext)
{
-#warning Missing logic
- return -ENOSYS;
+ /* Not much to do in this case */
+
+ DEBUGASSERT(addrenv && vtext);
+ *vtext = (FAR void *)CONFIG_ARCH_TEXT_VBASE;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_addrenv_vdata
+ *
+ * Description:
+ * Return the virtual address associated with the newly create .text
+ * address environment. This function is used by the binary loaders in
+ * order get an address that can be used to initialize the new task.
+ *
+ * Input Parameters:
+ * addrenv - The representation of the task address environment previously
+ * returned by up_addrenv_create.
+ * textsize - For some implementations, the text and data will be saved
+ * in the same memory region (read/write/execute) and, in this case,
+ * the virtual address of the data just lies at this offset into the
+ * common region.
+ * vdata - The location to return the virtual address.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int up_addrenv_vdata(FAR group_addrenv_t addrenv, uintptr_t textsize,
+ FAR void **vdata)
+{
+ /* Not much to do in this case */
+
+ DEBUGASSERT(addrenv && vdata);
+ *vdata = (FAR void *)CONFIG_ARCH_DATA_VBASE;
+ return OK;
}
/****************************************************************************
@@ -181,8 +222,8 @@ int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr)
* The address environment that was in place before up_addrenv_select().
* This may be used with up_addrenv_restore() to restore the original
* address environment that was in place before up_addrenv_select() was
- * called. Note that this may be a task agnostic, hardware
- * representation that is different from group_addrenv_t.
+ * called. Note that this may be a task agnostic, platform-specific
+ * representation that may or may not be different from group_addrenv_t.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
@@ -204,7 +245,7 @@ int up_addrenv_select(group_addrenv_t addrenv, save_addrenv_t *oldenv)
* original address environment.
*
* Input Parameters:
- * oldenv - The hardware representation of the address environment
+ * oldenv - The platform-specific representation of the address environment
* previously returned by up_addrenv_select.
*
* Returned Value:
@@ -234,10 +275,15 @@ int up_addrenv_restore(save_addrenv_t oldenv)
*
****************************************************************************/
-int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group)
+int up_addrenv_assign(FAR const group_addrenv_t *addrenv,
+ FAR struct task_group_s *group)
{
-#warning Missing logic
- return -ENOSYS;
+ DEBUGASSERT(addrenv && group);
+
+ /* Just copy the addess environment into the group */
+
+ memcpy(&group->addrenv, addrenv, sizeof(group_addrenv_t));
+ return OK;
}
/****************************************************************************
@@ -263,8 +309,9 @@ int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group)
int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb)
{
-#warning Missing logic
- return -ENOSYS;
+ /* Nothing needs to be done in this implementation */
+
+ return OK;
}
/****************************************************************************
@@ -293,8 +340,9 @@ int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb)
int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb)
{
-#warning Missing logic
- return -ENOSYS;
+ /* Nothing needs to be done in this implementation */
+
+ return OK;
}
#endif /* CONFIG_ARCH_ADDRENV */
diff --git a/arch/z80/src/z180/z180_mmu.c b/arch/z80/src/z180/z180_mmu.c
index 5f788859f1..cdf5c84057 100644
--- a/arch/z80/src/z180/z180_mmu.c
+++ b/arch/z80/src/z180/z180_mmu.c
@@ -186,8 +186,10 @@ return g_physhandle ? OK : -ENOMEM;
*
* up_addrenv_create - Create an address environment
* up_addrenv_destroy - Destroy an address environment.
- * up_addrenv_vaddr - Returns the virtual base address of the address
- * environment
+ * up_addrenv_vtext - Returns the virtual base address of the .text
+ * address environment
+ * up_addrenv_vdata - Returns the virtual base address of the .bss/.data
+ * address environment
* up_addrenv_select - Instantiate an address environment
* up_addrenv_restore - Restore an address environment
* up_addrenv_assign - Assign an address environment to a group
@@ -214,8 +216,10 @@ return g_physhandle ? OK : -ENOMEM;
* memory for the new task.
*
* Input Parameters:
- * envsize - The size (in bytes) of the address environment needed by the
- * task.
+ * textsize - The size (in bytes) of the .text address environment needed
+ * by the task. This region may be read/execute only.
+ * datasize - The size (in bytes) of the .data/.bss address environment
+ * needed by the task. This region may be read/write only.
* addrenv - The location to return the representation of the task address
* environment.
*
@@ -224,17 +228,20 @@ return g_physhandle ? OK : -ENOMEM;
*
****************************************************************************/
-int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv)
+int up_addrenv_create(size_t textsize, size_t datasize,
+ FAR group_addrenv_t *addrenv)
{
FAR struct z180_cbr_s *cbr;
irqstate_t flags;
+ size_t envsize;
uintptr_t alloc;
unsigned int npages;
int ret;
/* Convert the size from bytes to numbers of pages */
- npages = PHYS_ALIGNUP(envsize);
+ envsize = textsize + datasize;
+ npages = PHYS_ALIGNUP(envsize);
if (npages < 1)
{
/* No address environment... but I suppose that is not an error */
@@ -331,28 +338,56 @@ int up_addrenv_destroy(group_addrenv_t addrenv)
}
/****************************************************************************
- * Name: up_addrenv_vaddr
+ * Name: up_addrenv_vtext
*
* Description:
- * Return the virtual address associated with the newly create address
- * environment. This function is used by the binary loaders in order
- * get an address that can be used to initialize the new task..
+ * Return the virtual address associated with the newly create .text
+ * address environment. This function is used by the binary loaders in
+ * order get an address that can be used to initialize the new task.
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
- * vaddr - The location to return the virtual address.
+ * vtext - The location to return the virtual address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
-int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr)
+int up_addrenv_vtext(FAR group_addrenv_t addrenv, FAR void **vtext)
{
return CONFIG_Z180_COMMON1AREA_VIRTBASE;
}
+/****************************************************************************
+ * Name: up_addrenv_vdata
+ *
+ * Description:
+ * Return the virtual address associated with the newly create .text
+ * address environment. This function is used by the binary loaders in
+ * order get an address that can be used to initialize the new task.
+ *
+ * Input Parameters:
+ * addrenv - The representation of the task address environment previously
+ * returned by up_addrenv_create.
+ * textsize - For some implementations, the text and data will be saved
+ * in the same memory region (read/write/execute) and, in this case,
+ * the virtual address of the data just lies at this offset into the
+ * common region.
+ * vdata - The location to return the virtual address.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int up_addrenv_vdata(FAR group_addrenv_t addrenv, uintptr_t textsize,
+ FAR void **vdata)
+{
+ return CONFIG_Z180_COMMON1AREA_VIRTBASE + textsize;
+}
+
/****************************************************************************
* Name: up_addrenv_select
*
@@ -436,7 +471,8 @@ int up_addrenv_restore(save_addrenv_t oldenv)
*
****************************************************************************/
-int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group)
+int up_addrenv_assign(FAR const group_addrenv_t *addrenv,
+ FAR struct task_group_s *group)
{
/* Make sure that there is no address environment in place on this TCB */
@@ -446,7 +482,7 @@ int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group)
* special precautions should be needed.
*/
- group->addrenv = addrenv;
+ group->addrenv = *addrenv;
return OK;
}
diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c
index 0a2a155772..f415bccacb 100644
--- a/binfmt/binfmt_execmodule.c
+++ b/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/binfmt/libelf/libelf.h b/binfmt/libelf/libelf.h
index d407a31aee..8763e0808e 100644
--- a/binfmt/libelf/libelf.h
+++ b/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
*
* 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/binfmt/libelf/libelf_addrenv.c b/binfmt/libelf/libelf_addrenv.c
index ea400a325f..b112d869fe 100644
--- a/binfmt/libelf/libelf_addrenv.c
+++ b/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/binfmt/libelf/libelf_bind.c b/binfmt/libelf/libelf_bind.c
index 9fd0fb73d1..4d3d27f041 100644
--- a/binfmt/libelf/libelf_bind.c
+++ b/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/binfmt/libelf/libelf_ctors.c b/binfmt/libelf/libelf_ctors.c
index 0dfe64449b..6cf35a62a4 100644
--- a/binfmt/libelf/libelf_ctors.c
+++ b/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/binfmt/libelf/libelf_dtors.c b/binfmt/libelf/libelf_dtors.c
index 5cbba4851f..e42ba6abff 100644
--- a/binfmt/libelf/libelf_dtors.c
+++ b/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/binfmt/libelf/libelf_load.c b/binfmt/libelf/libelf_load.c
index 600f85805b..9f33abb402 100644
--- a/binfmt/libelf/libelf_load.c
+++ b/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/binfmt/libnxflat/libnxflat.h b/binfmt/libnxflat/libnxflat.h
index b9a00dde86..5c020414bb 100644
--- a/binfmt/libnxflat/libnxflat.h
+++ b/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/binfmt/libnxflat/libnxflat_addrenv.c b/binfmt/libnxflat/libnxflat_addrenv.c
index 7f3e351766..825135fc59 100644
--- a/binfmt/libnxflat/libnxflat_addrenv.c
+++ b/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:
diff --git a/include/nuttx/addrenv.h b/include/nuttx/addrenv.h
index 6460e22138..b5373880db 100644
--- a/include/nuttx/addrenv.h
+++ b/include/nuttx/addrenv.h
@@ -152,8 +152,10 @@
*
* up_addrenv_create - Create an address environment
* up_addrenv_destroy - Destroy an address environment.
- * up_addrenv_vaddr - Returns the virtual base address of the address
- * environment
+ * up_addrenv_vtext - Returns the virtual base address of the .text
+ * address environment
+ * up_addrenv_vdata - Returns the virtual base address of the .bss/.data
+ * address environment
* up_addrenv_select - Instantiate an address environment
* up_addrenv_restore - Restore an address environment
* up_addrenv_assign - Assign an address environment to a group
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index 951d959fe1..81847acd20 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -675,8 +675,10 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size);
*
* up_addrenv_create - Create an address environment
* up_addrenv_destroy - Destroy an address environment.
- * up_addrenv_vaddr - Returns the virtual base address of the address
- * environment
+ * up_addrenv_vtext - Returns the virtual base address of the .text
+ * address environment
+ * up_addrenv_vdata - Returns the virtual base address of the .bss/.data
+ * address environment
* up_addrenv_select - Instantiate an address environment
* up_addrenv_restore - Restore an address environment
* up_addrenv_assign - Assign an address environment to a group
@@ -703,8 +705,10 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size);
* memory for the new task.
*
* Input Parameters:
- * envsize - The size (in bytes) of the address environment needed by the
- * task.
+ * textsize - The size (in bytes) of the .text address environment needed
+ * by the task. This region may be read/execute only.
+ * datasize - The size (in bytes) of the .data/.bss address environment
+ * needed by the task. This region may be read/write only.
* addrenv - The location to return the representation of the task address
* environment.
*
@@ -714,7 +718,8 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size);
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
-int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv);
+int up_addrenv_create(size_t textsize, size_t datasize,
+ FAR group_addrenv_t *addrenv);
#endif
/****************************************************************************
@@ -738,17 +743,17 @@ int up_addrenv_destroy(group_addrenv_t addrenv);
#endif
/****************************************************************************
- * Name: up_addrenv_vaddr
+ * Name: up_addrenv_vtext
*
* Description:
- * Return the virtual address associated with the newly create address
- * environment. This function is used by the binary loaders in order
- * get an address that can be used to initialize the new task.
+ * Return the virtual address associated with the newly create .text
+ * address environment. This function is used by the binary loaders in
+ * order get an address that can be used to initialize the new task.
*
* Input Parameters:
* addrenv - The representation of the task address environment previously
* returned by up_addrenv_create.
- * vaddr - The location to return the virtual address.
+ * vtext - The location to return the virtual address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
@@ -756,7 +761,34 @@ int up_addrenv_destroy(group_addrenv_t addrenv);
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
-int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr);
+int up_addrenv_vtext(FAR group_addrenv_t addrenv, FAR void **vtext);
+#endif
+
+/****************************************************************************
+ * Name: up_addrenv_vdata
+ *
+ * Description:
+ * Return the virtual address associated with the newly create .text
+ * address environment. This function is used by the binary loaders in
+ * order get an address that can be used to initialize the new task.
+ *
+ * Input Parameters:
+ * addrenv - The representation of the task address environment previously
+ * returned by up_addrenv_create.
+ * textsize - For some implementations, the text and data will be saved
+ * in the same memory region (read/write/execute) and, in this case,
+ * the virtual address of the data just lies at this offset into the
+ * common region.
+ * vdata - The location to return the virtual address.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+int up_addrenv_vdata(FAR group_addrenv_t addrenv, uintptr_t textsize,
+ FAR void **vdata);
#endif
/****************************************************************************
@@ -826,7 +858,8 @@ int up_addrenv_restore(save_addrenv_t oldenv);
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
-int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group);
+int up_addrenv_assign(FAR const group_addrenv_t *addrenv,
+ FAR struct task_group_s *group);
#endif
/****************************************************************************
diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h
index ec79ffb48f..71c7aa2821 100644
--- a/include/nuttx/binfmt/elf.h
+++ b/include/nuttx/binfmt/elf.h
@@ -104,8 +104,10 @@ struct elf_loadinfo_s
* the ELF module has been loaded.
*/
- uintptr_t elfalloc; /* Memory allocated when ELF file was loaded */
- size_t elfsize; /* Size of the ELF memory allocation */
+ uintptr_t textalloc; /* .text memory allocated when ELF file was loaded */
+ uintptr_t dataalloc; /* .bss/.data memory allocated when ELF file was loaded */
+ size_t textsize; /* Size of the ELF .text memory allocation */
+ size_t datasize; /* Size of the ELF .bss/.data memory allocation */
off_t filelen; /* Length of the entire ELF file */
Elf32_Ehdr ehdr; /* Buffered ELF file header */
FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */
@@ -127,12 +129,12 @@ struct elf_loadinfo_s
* addrenv - This is the handle created by up_addrenv_create() that can be
* used to manage the tasks address space.
* oldenv - This is a value returned by up_addrenv_select() that must be
- * used to restore the current hardware address environment.
+ * used to restore the current address environment.
*/
#ifdef CONFIG_ARCH_ADDRENV
group_addrenv_t addrenv; /* Task group address environment */
- save_addrenv_t oldenv; /* Saved hardware address environment */
+ save_addrenv_t oldenv; /* Saved address environment */
#endif
uint16_t symtabidx; /* Symbol table section index */
diff --git a/include/nuttx/binfmt/nxflat.h b/include/nuttx/binfmt/nxflat.h
index f44f4c77bd..69a7d8332a 100644
--- a/include/nuttx/binfmt/nxflat.h
+++ b/include/nuttx/binfmt/nxflat.h
@@ -99,12 +99,12 @@ struct nxflat_loadinfo_s
* addrenv - This is the handle created by up_addrenv_create() that can be
* used to manage the tasks address space.
* oldenv - This is a value returned by up_addrenv_select() that must be
- * used to restore the current hardware address environment.
+ * used to restore the current address environment.
*/
#ifdef CONFIG_ARCH_ADDRENV
group_addrenv_t addrenv; /* Task group address environment */
- save_addrenv_t oldenv; /* Saved hardware address environment */
+ save_addrenv_t oldenv; /* Saved address environment */
#endif
/* File descriptors */