diff options
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 79 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-a/arm_addrenv.c | 94 | ||||
-rw-r--r-- | nuttx/arch/z80/src/z180/z180_mmu.c | 64 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_execmodule.c | 4 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf.h | 22 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_addrenv.c | 62 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_bind.c | 2 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_ctors.c | 5 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_dtors.c | 5 | ||||
-rw-r--r-- | nuttx/binfmt/libelf/libelf_load.c | 61 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat.h | 8 | ||||
-rw-r--r-- | nuttx/binfmt/libnxflat/libnxflat_addrenv.c | 18 | ||||
-rw-r--r-- | nuttx/include/nuttx/addrenv.h | 6 | ||||
-rw-r--r-- | nuttx/include/nuttx/arch.h | 57 | ||||
-rw-r--r-- | nuttx/include/nuttx/binfmt/elf.h | 10 | ||||
-rw-r--r-- | nuttx/include/nuttx/binfmt/nxflat.h | 4 |
16 files changed, 351 insertions, 150 deletions
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index e76b2ce0a..f67ccdc0d 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@ <h1><big><font color="#3c34ec"> <i>NuttX RTOS Porting Guide</i> </font></big></h1> - <p>Last Updated: August 22, 2014</p> + <p>Last Updated: August 24, 2014</p> </td> </tr> </table> @@ -108,12 +108,13 @@ <ul> <a href="#up_addrenv_create">4.4.1 <code>up_addrenv_create()</code></a></br> <a href="#up_addrenv_destroy">4.4.2 <code>up_addrenv_destroy()</code></a></br> - <a href="#up_addrenv_vaddr">4.4.3 <code>up_addrenv_vaddr()</code></a></br> - <a href="#up_addrenv_select">4.4.4 <code>up_addrenv_select()</code></a></br> - <a href="#up_addrenv_restore">4.4.5 <code>up_addrenv_restore()</code></a></br> - <a href="#up_addrenv_assign">4.4.6 <code>up_addrenv_assign()</code></a></br> - <a href="#up_addrenv_attach">4.4.7 <code>up_addrenv_attach()</code></a></br> - <a href="#up_addrenv_detach">4.4.8 <code>up_addrenv_detach()</code></a> + <a href="#up_addrenv_vtext">4.4.3 <code>up_addrenv_vtext()</code></a></br> + <a href="#up_addrenv_vdata">4.4.4 <code>up_addrenv_vdata()</code></a></br> + <a href="#up_addrenv_select">4.4.5 <code>up_addrenv_select()</code></a></br> + <a href="#up_addrenv_restore">4.4.6 <code>up_addrenv_restore()</code></a></br> + <a href="#up_addrenv_assign">4.4.7 <code>up_addrenv_assign()</code></a></br> + <a href="#up_addrenv_attach">4.4.8 <code>up_addrenv_attach()</code></a></br> + <a href="#up_addrenv_detach">4.4.9 <code>up_addrenv_detach()</code></a> </ul> <a href="#exports">4.5 APIs Exported by NuttX to Architecture-Specific Logic</a> <ul> @@ -2943,19 +2944,23 @@ VxWorks provides the following comparable interface: Destroy an address environment. </li> <li> - <a href="#up_addrenv_vaddr">4.4.3 <code>up_addrenv_vaddr()</code></a>: - Returns the virtual base address of the address environment. + <a href="#up_addrenv_vtext">4.4.3 <code>up_addrenv_vtext()</code></a>: + Returns the virtual base address of the <code>.text</code> address environment. </li> <li> - <a href="#up_addrenv_select">4.4.4 <code>up_addrenv_select()</code></a>: + <a href="#up_addrenv_vdata">4.4.4 <code>up_addrenv_vdata()</code></a>: + Returns the virtual base address of the <code>.bss</code>/<code>.data</code> address environment. + </li> + <li> + <a href="#up_addrenv_select">4.4.5 <code>up_addrenv_select()</code></a>: Instantiate an address environment. </li> <li> - <a href="#up_addrenv_restore">4.4.5 <code>up_addrenv_restore()</code></a>: + <a href="#up_addrenv_restore">4.4.6 <code>up_addrenv_restore()</code></a>: Restore an address environment. </li> <li> - <a href="#up_addrenv_assign">4.4.6 <code>up_addrenv_assign()</code></a>: + <a href="#up_addrenv_assign">4.4.7 <code>up_addrenv_assign()</code></a>: Assign an address environment to a thread. </li> </ul> @@ -2968,12 +2973,12 @@ VxWorks provides the following comparable interface: </p> <ul> <li> - <a href="#up_addrenv_attach">4.4.7 <code>up_addrenv_attach()</code></a>: + <a href="#up_addrenv_attach">4.4.8 <code>up_addrenv_attach()</code></a>: Clone the group address environment assigned to a new thread. This operation is done when a pthread is created that share's the same address environment. </li> <li> - <a href="#up_addrenv_detach">4.4.8 <code>up_addrenv_detach()</code></a>: + <a href="#up_addrenv_detach">4.4.9 <code>up_addrenv_detach()</code></a>: Release the thread's reference to a group address environment when a task/thread exits. </li> </ul> @@ -2983,7 +2988,7 @@ VxWorks provides the following comparable interface: <h3><a name="up_addrenv_create">4.4.1 <code>up_addrenv_create()</code></a></h3> <p><b>Function Prototype</b>:</p> <ul> - <code>int up_addrenv_create(size_t envsize, FAR group_addrenv_t *addrenv);</code> + <code>int up_addrenv_create(size_t textsize, size_t datasize, FAR group_addrenv_t *addrenv);</code> </ul> <p><b>Description</b>:</p> <ul> @@ -2992,7 +2997,8 @@ VxWorks provides the following comparable interface: </ul> <p><b>Input Parameters</b>:</p> <ul> - <li><code>envsize</code>: The size (in bytes) of the address environment needed by the task.</li> + <li><code>textsize</code>: The size (in bytes) of the <code>.text</code> address environment needed by the task. This region may be read/execute only.</li> + <li><code>datasize</code>: The size (in bytes) of the <code>.bss/.data</code> address environment needed by the task. This region may be read/write only.</li> <li><code>addrenv</code>: The location to return the representation of the task address environment.</li> </ul> <p><b>Returned Value</b>:</p> @@ -3018,27 +3024,48 @@ VxWorks provides the following comparable interface: Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h3><a name="up_addrenv_vaddr">4.4.3 <code>up_addrenv_vaddr()</code></a></h3> +<h3><a name="up_addrenv_vtext">4.4.3 <code>up_addrenv_vtext()</code></a></h3> +<p><b>Function Prototype</b>:<p> +<ul> + <code>int up_addrenv_vtext(FAR group_addrenv_t addrenv, FAR void **vtext);</code> +</ul> +<p><b>Description</b>:</p> +<ul> + Return the virtual <code>.text</code> 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. +</ul> +<p><b>Input Parameters</b>:</p> +<ul> + <li><code>addrenv</code>: The representation of the task address environment previously returned by up_addrenv_create.</li> + <li><code>vtext</code>: The location to return the virtual address.</li> +</ul> +<p><b>Returned Value</b>:</p> +<ul> + Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. +</ul> + +<h3><a name="up_addrenv_vdata">4.4.4 <code>up_addrenv_vdata()</code></a></h3> <p><b>Function Prototype</b>:<p> <ul> - <code>int up_addrenv_vaddr(FAR group_addrenv_t addrenv, FAR void **vaddr);</code> + <code>int up_addrenv_vdata(FAR group_addrenv_t addrenv, size_t textsize, FAR void **vdata);</code> </ul> <p><b>Description</b>:</p> <ul> - Return the virtual address associated with the newly create address environment. + Return the virtual <code>.text</code> 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. </ul> <p><b>Input Parameters</b>:</p> <ul> <li><code>addrenv</code>: The representation of the task address environment previously returned by up_addrenv_create.</li> - <li><code>vaddr</code>: The location to return the virtual address.</li> + <li><code>textsize</code>: 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.</li> + <li><code>vdata</code>: The location to return the virtual address.</li> </ul> <p><b>Returned Value</b>:</p> <ul> Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h3><a name="up_addrenv_select">4.4.4 <code>up_addrenv_select()</code></a></h3> +<h3><a name="up_addrenv_select">4.4.5 <code>up_addrenv_select()</code></a></h3> <p><b>Function Prototype</b>:<p> <ul> <code>int up_addrenv_select(group_addrenv_t addrenv, save_addrenv_t *oldenv);</code> @@ -3062,7 +3089,7 @@ VxWorks provides the following comparable interface: Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h3><a name="up_addrenv_restore">4.4.5 <code>up_addrenv_restore()</code></a></h3> +<h3><a name="up_addrenv_restore">4.4.6 <code>up_addrenv_restore()</code></a></h3> <p><b>Function Prototype</b>:<p> <ul> <code>int up_addrenv_restore(save_addrenv_t oldenv);</code> @@ -3081,10 +3108,10 @@ VxWorks provides the following comparable interface: Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h3><a name="up_addrenv_assign">4.4.6 <code>up_addrenv_assign()</code></a></h3> +<h3><a name="up_addrenv_assign">4.4.7 <code>up_addrenv_assign()</code></a></h3> <p><b>Function Prototype</b>:<p> <ul> - <code>int up_addrenv_assign(group_addrenv_t addrenv, FAR struct task_group_s *group);</code> + <code>int up_addrenv_assign(FAR const group_addrenv_t *addrenv, FAR struct task_group_s *group);</code> </ul> <p><b>Description</b>:</p> <ul> @@ -3100,7 +3127,7 @@ VxWorks provides the following comparable interface: Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h3><a name="up_addrenv_attach">4.4.7 <code>up_addrenv_attach()</code></a></h3> +<h3><a name="up_addrenv_attach">4.4.8 <code>up_addrenv_attach()</code></a></h3> <p><b>Function Prototype</b>:<p> <ul> <code>int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);</code> @@ -3126,7 +3153,7 @@ VxWorks provides the following comparable interface: Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> -<h3><a name="up_addrenv_detach">4.4.8 <code>up_addrenv_detach()</code></a></h3> +<h3><a name="up_addrenv_detach">4.4.9 <code>up_addrenv_detach()</code></a></h3> <p><b>Function Prototype</b>:<p> <ul> <code>int up_addrenv_detach(FAR struct task_group_s *group, FAR struct task_group_s *tcb);</code> diff --git a/nuttx/arch/arm/src/armv7-a/arm_addrenv.c b/nuttx/arch/arm/src/armv7-a/arm_addrenv.c index 5aa21aa6c..d575a68c8 100644 --- a/nuttx/arch/arm/src/armv7-a/arm_addrenv.c +++ b/nuttx/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 <nuttx/config.h> +#include <string.h> #include <errno.h> #include <nuttx/arch.h> @@ -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/nuttx/arch/z80/src/z180/z180_mmu.c b/nuttx/arch/z80/src/z180/z180_mmu.c index 5f788859f..cdf5c8405 100644 --- a/nuttx/arch/z80/src/z180/z180_mmu.c +++ b/nuttx/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,29 +338,57 @@ 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 * * Description: @@ -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/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: diff --git a/nuttx/include/nuttx/addrenv.h b/nuttx/include/nuttx/addrenv.h index 6460e2213..b5373880d 100644 --- a/nuttx/include/nuttx/addrenv.h +++ b/nuttx/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/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h index 951d959fe..81847acd2 100644 --- a/nuttx/include/nuttx/arch.h +++ b/nuttx/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/nuttx/include/nuttx/binfmt/elf.h b/nuttx/include/nuttx/binfmt/elf.h index ec79ffb48..71c7aa282 100644 --- a/nuttx/include/nuttx/binfmt/elf.h +++ b/nuttx/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/nuttx/include/nuttx/binfmt/nxflat.h b/nuttx/include/nuttx/binfmt/nxflat.h index f44f4c77b..69a7d8332 100644 --- a/nuttx/include/nuttx/binfmt/nxflat.h +++ b/nuttx/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 */ |