aboutsummaryrefslogtreecommitdiff
path: root/nuttx/binfmt/libnxflat/libnxflat_bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/binfmt/libnxflat/libnxflat_bind.c')
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_bind.c185
1 files changed, 154 insertions, 31 deletions
diff --git a/nuttx/binfmt/libnxflat/libnxflat_bind.c b/nuttx/binfmt/libnxflat/libnxflat_bind.c
index ca348178d..816810a46 100644
--- a/nuttx/binfmt/libnxflat/libnxflat_bind.c
+++ b/nuttx/binfmt/libnxflat/libnxflat_bind.c
@@ -38,6 +38,7 @@
****************************************************************************/
#include <nuttx/config.h>
+#include <nuttx/compiler.h>
#include <stdint.h>
#include <string.h>
@@ -47,8 +48,11 @@
#include <debug.h>
#include <arpa/inet.h>
-#include <nuttx/nxflat.h>
-#include <nuttx/symtab.h>
+
+#include <nuttx/binfmt/nxflat.h>
+#include <nuttx/binfmt/symtab.h>
+
+#include "libnxflat.h"
/****************************************************************************
* Pre-processor Definitions
@@ -229,8 +233,6 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace;
- /* From this, we can get the list of relocation entries. */
-
/* From this, we can get the offset to the list of relocation entries */
offset = ntohl(hdr->h_relocstart);
@@ -247,11 +249,27 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
DEBUGASSERT(offset + nrelocs * sizeof(struct nxflat_reloc_s)
<= (loadinfo->isize + loadinfo->dsize));
- relocs = (FAR struct nxflat_reloc_s*)
+ relocs = (FAR struct nxflat_reloc_s *)
(offset - loadinfo->isize + loadinfo->dspace->region);
bvdbg("isize: %08lx dpsace: %p relocs: %p\n",
(long)loadinfo->isize, loadinfo->dspace->region, relocs);
+ /* All relocations are performed within the D-Space allocation. If
+ * CONFIG_ADDRENV=y, then that D-Space allocation lies in an address
+ * environment that may not be in place. So, in that case, we must call
+ * nxflat_addrenv_select to temporarily instantiate that address space
+ * before the relocations can be performed.
+ */
+
+#ifdef CONFIG_ADDRENV
+ ret = nxflat_addrenv_select(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("ERROR: nxflat_addrenv_select() failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
/* Now, traverse the relocation list of and bind each GOT relocation. */
ret = OK; /* Assume success */
@@ -259,11 +277,16 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
{
/* Handle the relocation by the relocation type */
+#ifdef CONFIG_CAN_PASS_STRUCTS
reloc = *relocs++;
+#else
+ memcpy(&reloc, relocs, sizeof(struct nxflat_reloc_s));
+ relocs++;
+#endif
+
result = OK;
switch (NXFLAT_RELOC_TYPE(reloc.r_info))
{
-
/* NXFLAT_RELOC_TYPE_REL32I Meaning: Object file contains a 32-bit offset
* into I-Space at the offset.
* Fixup: Add mapped I-Space address to the offset.
@@ -329,6 +352,17 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
nxflat_dumpbuffer("GOT", (FAR const uint8_t*)relocs, nrelocs * sizeof(struct nxflat_reloc_s));
}
#endif
+
+ /* Restore the original address environment */
+
+#ifdef CONFIG_ADDRENV
+ ret = nxflat_addrenv_restore(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("ERROR: nxflat_addrenv_restore() failed: %d\n", ret);
+ }
+#endif
+
return ret;
}
@@ -346,16 +380,19 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
****************************************************************************/
static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
- FAR const struct symtab_s *exports,
- int nexports)
+ FAR const struct symtab_s *exports,
+ int nexports)
{
FAR struct nxflat_import_s *imports;
FAR struct nxflat_hdr_s *hdr;
- FAR const struct symtab_s *symbol;
+ FAR const struct symtab_s *symbol;
char *symname;
uint32_t offset;
uint16_t nimports;
+#ifdef CONFIG_ADDRENV
+ int ret;
+#endif
int i;
/* The NXFLAT header is the first thing at the beginning of the ISpace. */
@@ -370,6 +407,22 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
nimports = ntohs(hdr->h_importcount);
bvdbg("Imports offset: %08x nimports: %d\n", offset, nimports);
+ /* The import[] table resides within the D-Space allocation. If
+ * CONFIG_ADDRENV=y, then that D-Space allocation lies in an address
+ * environment that may not be in place. So, in that case, we must call
+ * nxflat_addrenv_select to temporarily instantiate that address space
+ * before the import[] table can be modified.
+ */
+
+#ifdef CONFIG_ADDRENV
+ ret = nxflat_addrenv_select(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("ERROR: nxflat_addrenv_select() failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
/* Verify that this module requires imported symbols */
if (offset != 0 && nimports > 0)
@@ -388,7 +441,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
offset < loadinfo->isize + loadinfo->dsize);
imports = (struct nxflat_import_s*)
- (offset - loadinfo->isize + loadinfo->dspace->region);
+ (offset - loadinfo->isize + loadinfo->dspace->region);
/* Now, traverse the list of imported symbols and attempt to bind
* each symbol to the value exported by from the exported symbol
@@ -396,41 +449,44 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
*/
for (i = 0; i < nimports; i++)
- {
- bvdbg("Import[%d] (%08p) offset: %08x func: %08x\n",
- i, &imports[i], imports[i].i_funcname, imports[i].i_funcaddress);
+ {
+ bvdbg("Import[%d] (%08p) offset: %08x func: %08x\n",
+ i, &imports[i], imports[i].i_funcname, imports[i].i_funcaddress);
- /* Get a pointer to the imported symbol name. The name itself
- * lies in the TEXT segment. But the reference to the name
- * lies in DATA segment. Therefore, the name reference should
- * have been relocated when the module was loaded.
- */
+ /* Get a pointer to the imported symbol name. The name itself
+ * lies in the TEXT segment. But the reference to the name
+ * lies in DATA segment. Therefore, the name reference should
+ * have been relocated when the module was loaded.
+ */
offset = imports[i].i_funcname;
DEBUGASSERT(offset < loadinfo->isize);
- symname = (char*)(offset + loadinfo->ispace + sizeof(struct nxflat_hdr_s));
+ symname = (char*)(offset + loadinfo->ispace + sizeof(struct nxflat_hdr_s));
- /* Find the exported symbol value for this this symbol name. */
+ /* Find the exported symbol value for this this symbol name. */
#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
symbol = symtab_findorderedbyname(exports, symname, nexports);
#else
symbol = symtab_findbyname(exports, symname, nexports);
#endif
- if (!symbol)
- {
- bdbg("Exported symbol \"%s\" not found\n", symname);
+ if (!symbol)
+ {
+ bdbg("Exported symbol \"%s\" not found\n", symname);
+#ifdef CONFIG_ADDRENV
+ (void)nxflat_addrenv_restore(loadinfo);
+#endif
return -ENOENT;
- }
+ }
- /* And put this into the module's import structure. */
+ /* And put this into the module's import structure. */
- imports[i].i_funcaddress = (uint32_t)symbol->sym_value;
+ imports[i].i_funcaddress = (uint32_t)symbol->sym_value;
- bvdbg("Bound import[%d] (%08p) to export '%s' (%08x)\n",
- i, &imports[i], symname, imports[i].i_funcaddress);
- }
+ bvdbg("Bound import[%d] (%08p) to export '%s' (%08x)\n",
+ i, &imports[i], symname, imports[i].i_funcaddress);
+ }
}
/* Dump the relocation import table */
@@ -441,7 +497,74 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
nxflat_dumpbuffer("Imports", (FAR const uint8_t*)imports, nimports * sizeof(struct nxflat_import_s));
}
#endif
+
+ /* Restore the original address environment */
+
+#ifdef CONFIG_ADDRENV
+ ret = nxflat_addrenv_restore(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("ERROR: nxflat_addrenv_restore() failed: %d\n", ret);
+ }
+
+ return ret;
+#else
+ return OK;
+#endif
+}
+
+/****************************************************************************
+ * Name: nxflat_clearbss
+ *
+ * Description:
+ * Clear uninitialized .bss memory
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static inline int nxflat_clearbss(FAR struct nxflat_loadinfo_s *loadinfo)
+{
+#ifdef CONFIG_ADDRENV
+ int ret;
+#endif
+
+ /* .bss resides within the D-Space allocation. If CONFIG_ADDRENV=y, then
+ * that D-Space allocation lies in an address environment that may not be
+ * in place. So, in that case, we must call nxflat_addrenv_select to
+ * temporarily instantiate that address space before the .bss can be
+ * accessed.
+ */
+
+#ifdef CONFIG_ADDRENV
+ ret = nxflat_addrenv_select(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("ERROR: nxflat_addrenv_select() failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
+ /* Zero the BSS area */
+
+ memset((void*)(loadinfo->dspace->region + loadinfo->datasize), 0,
+ loadinfo->bsssize);
+
+ /* Restore the original address environment */
+
+#ifdef CONFIG_ADDRENV
+ ret = nxflat_addrenv_restore(loadinfo);
+ if (ret < 0)
+ {
+ bdbg("ERROR: nxflat_addrenv_restore() failed: %d\n", ret);
+ }
+
+ return ret;
+#else
return OK;
+#endif
}
/****************************************************************************
@@ -483,10 +606,10 @@ int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo,
* space in the loaded file.
*/
- memset((void*)(loadinfo->dspace->region + loadinfo->datasize),
- 0, loadinfo->bsssize);
+ ret = nxflat_clearbss(loadinfo);
}
}
+
return ret;
}