From f99eb7d89bba1dffba9efbe1450707ae0878e05e Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Sun, 21 Jun 2009 13:41:39 +0000
Subject: [PATCH] Add NXFLAT dynamic binding logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1919 42af7a65-404d-4744-a932-0658087f49c3
---
 TODO                              |   5 +
 binfmt/binfmt_loadmodule.c        |   8 +-
 binfmt/libnxflat/Make.defs        |   3 +-
 binfmt/libnxflat/libnxflat_bind.c | 172 ++++++++++++++++++++++++++++++
 binfmt/nxflat.c                   |  10 ++
 include/nuttx/binfmt.h            |  34 +++---
 include/nuttx/nxflat.h            |  17 +++
 7 files changed, 230 insertions(+), 19 deletions(-)
 create mode 100644 binfmt/libnxflat/libnxflat_bind.c

diff --git a/TODO b/TODO
index d8a61946fe..da9356e26a 100644
--- a/TODO
+++ b/TODO
@@ -320,6 +320,11 @@ o Pascal Add-On (pcode/)
 o Documentation (Documentation/)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+  Description: Need to document which APIs can be used in interrupt
+               handlers (like mq_send and sem_post) and which cannot.
+  Status:      Open
+  Priority:    Low
+
 o Build system
   ^^^^^^^^^^^^
 
diff --git a/binfmt/binfmt_loadmodule.c b/binfmt/binfmt_loadmodule.c
index 1034ad16ff..c251f0af77 100644
--- a/binfmt/binfmt_loadmodule.c
+++ b/binfmt/binfmt_loadmodule.c
@@ -74,7 +74,8 @@
  * Name: load_module
  *
  * Description:
- *   Load a module into memory and prep it for execution.
+ *   Load a module into memory, bind it to an exported symbol take, and
+ *   prep the module for execution.
  *
  * Returned Value:
  *   This is an end-user function, so it follows the normal convention:
@@ -83,7 +84,7 @@
  *
  ****************************************************************************/
 
-int load_module(const char *filename, FAR struct binary_s *bin)
+int load_module(FAR struct binary_s *bin)
 {
   FAR struct binfmt_s *binfmt;
   int ret;
@@ -96,7 +97,7 @@ int load_module(const char *filename, FAR struct binary_s *bin)
   else
 #endif
     {
-      bdbg("Loading %s\n", filename);
+      bdbg("Loading %s\n", bin->filename);
 
       /* Disabling pre-emption should be sufficient protection while
        * accessing the list of registered binary format handlers.
@@ -116,7 +117,6 @@ int load_module(const char *filename, FAR struct binary_s *bin)
           ret = binfmt->load(bin);
           if (ret == OK)
             {
-
               /* Successfully loaded -- break out with ret == 0 */
 
               dump_module(bin);
diff --git a/binfmt/libnxflat/Make.defs b/binfmt/libnxflat/Make.defs
index 21d00f7f17..9e95936519 100644
--- a/binfmt/libnxflat/Make.defs
+++ b/binfmt/libnxflat/Make.defs
@@ -35,4 +35,5 @@
 
 LIBNXFLAT_ASRCS =
 LIBNXFLAT_CSRCS = libnxflat_init.c libnxflat_uninit.c libnxflat_load.c \
-		  libnxflat_unload.c libnxflat_verify.c libnxflat_read.c
+		  libnxflat_unload.c libnxflat_verify.c libnxflat_read.c \
+		  libnxflat_bind.c
diff --git a/binfmt/libnxflat/libnxflat_bind.c b/binfmt/libnxflat/libnxflat_bind.c
new file mode 100644
index 0000000000..887fcfe587
--- /dev/null
+++ b/binfmt/libnxflat/libnxflat_bind.c
@@ -0,0 +1,172 @@
+/****************************************************************************
+ * binfmt/libnxflat/libnxflat_bind.c
+ *
+ *   Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+
+#include <nxflat.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arpa/inet.h>
+#include <nuttx/nxflat.h>
+#include <nuttx/symtab.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/***********************************************************************
+ * Name: nxflat_bind
+ *
+ * Description:
+ *   Bind the imported symbol names in the loaded module described by
+ *   'loadinfo' using the exported symbol values provided by 'symtab'
+ *
+ * Returned Value:
+ *   0 (OK) is returned on success and a negated errno is returned on
+ *   failure.
+ *
+ ***********************************************************************/
+
+int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo,
+                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;
+
+  char   *symname;
+  uint32  offset;
+  uint16  nimports;
+  int     i;
+
+  /* Get the ISpace load address of the module.  The NXFLAT header is the
+   * first thing at the beginning of the ISpace.
+   */
+
+  hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace;
+
+  /* From this, we can get the offset to the list of symbols imported by
+   * this module and the number of symbols imported by this module.
+   */
+
+  offset   = ntohl(hdr->h_importsymbols);
+  nimports = ntohs(hdr->h_importcount);
+
+  /* Verify that this module requires imported symbols */
+
+  if (offset != 0 && nimports > 0)
+    {
+      /* It does.. make sure that exported symbols are provided */
+
+      DEBUGASSERT(symtab && nexports > 0);
+
+      /* If non-zero, the value of the imported symbol list that we get
+       * from the header is a file offset.  We will have to convert this
+       * to an offset into the DSpace segment to get the pointer to the
+       * beginning of the imported symbol list.
+       */
+
+      DEBUGASSERT(offset >= loadinfo->isize &&
+                  offset < loadinfo->isize + loadinfo->dsize);
+
+      imports = (struct nxflat_import_s*)
+	(offset - loadinfo->isize + loadinfo->dspace);
+
+      /* Now, search the list of imported symbols and attempt to bind
+       * each symbol to the value exported by from the exported symbol
+       * table.
+       */
+
+      for (i = 0; i < nimports; i++)
+	{
+	  /* 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);
+
+	  /* 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);
+              return -ENOENT;
+	    }
+
+	  /* And put this into the module's import structure. */
+
+	  imports[i].i_funcaddress =  (uint32)symbol->sym_value;
+
+	  bvdbg("Bound imported function '%s' to address %08x\n",
+	        symname, imports[i].function_address);
+	}
+    }
+
+  return OK;
+}
+
diff --git a/binfmt/nxflat.c b/binfmt/nxflat.c
index e9c2b99618..53f689a9be 100644
--- a/binfmt/nxflat.c
+++ b/binfmt/nxflat.c
@@ -173,6 +173,16 @@ static int nxflat_loadbinary(struct binary_s *binp)
       return ret;
     }
 
+  /* Bind the program to the exported symbol table */
+
+  ret = nxflat_bind(&loadinfo, binp->exports, binp->nexports);
+  if (ret != 0)
+    {
+      bdbg("Failed to bind symbols program binary: %d\n", ret);
+      nxflat_uninit(&loadinfo);
+      return ret;
+    }
+
   /* Return the load information */
 
   binp->entrypt   = (main_t)(loadinfo.ispace + loadinfo.entryoffs);
diff --git a/include/nuttx/binfmt.h b/include/nuttx/binfmt.h
index 0c4238989d..3fe0b3a382 100644
--- a/include/nuttx/binfmt.h
+++ b/include/nuttx/binfmt.h
@@ -55,20 +55,25 @@
 
 /* This describes the file to be loaded */
 
+struct symtab_s;
 struct binary_s
 {
-  /* Provided to the loader */
-
-  FAR const char  *filename;         /* Full path to the binary */
-  FAR const char **argv;             /* Argument list */
-
-  /* Provided by the loader (if successful) */
-
-  main_t       entrypt;              /* Entry point into a program module */
-  FAR void    *ispace;               /* Memory-mapped, I-space (.text) address */
-  FAR struct dspace_s *dspace;       /* Address of the allocated .data/.bss space */
-  size_t       isize;                /* Size of the I-space region (needed for munmap) */
-  size_t       stacksize;            /* Size of the stack in bytes (unallocated) */
+  /* Information provided to the loader to load and bind a module */
+
+  FAR const char *filename;            /* Full path to the binary to be loaded */
+  FAR const char **argv;               /* Argument list */
+  FAR const struct symtab_s *exports;  /* Table of exported symbols */
+  int nexports;                        /* The number of symbols in exports[] */
+
+  /* Information provided from the loader (if successful) describing the
+   * resources used by the loaded module.
+   */
+
+  main_t entrypt;                      /* Entry point into a program module */
+  FAR void *ispace;                    /* Memory-mapped, I-space (.text) address */
+  FAR struct dspace_s *dspace;         /* Address of the allocated .data/.bss space */
+  size_t isize;                        /* Size of the I-space region (needed for munmap) */
+  size_t stacksize;                    /* Size of the stack in bytes (unallocated) */
 };
 
 /* This describes one binary format handler */
@@ -125,7 +130,8 @@ EXTERN int unregister_binfmt(FAR struct binfmt_s *binfmt);
  * Name: load_module
  *
  * Description:
- *   Load a module into memory and prep it for execution.
+ *   Load a module into memory, bind it to an exported symbol take, and
+ *   prep the module for execution.
  *
  * Returned Value:
  *   This is an end-user function, so it follows the normal convention:
@@ -134,7 +140,7 @@ EXTERN int unregister_binfmt(FAR struct binfmt_s *binfmt);
  *
  ****************************************************************************/
 
-EXTERN int load_module(const char *filename, FAR struct binary_s *bin);
+EXTERN int load_module(FAR struct binary_s *bin);
 
 /****************************************************************************
  * Name: unload_module
diff --git a/include/nuttx/nxflat.h b/include/nuttx/nxflat.h
index 543f00e6d3..eac9d0d3cb 100644
--- a/include/nuttx/nxflat.h
+++ b/include/nuttx/nxflat.h
@@ -182,6 +182,23 @@ EXTERN int nxflat_load(struct nxflat_loadinfo_s *loadinfo);
 EXTERN int nxflat_read(struct nxflat_loadinfo_s *loadinfo, char *buffer,
                        int readsize, int offset);
 
+/***********************************************************************
+ * Name: nxflat_bind
+ *
+ * Description:
+ *   Bind the imported symbol names in the loaded module described by
+ *   'loadinfo' using the exported symbol values provided by 'symtab'
+ *
+ * Returned Value:
+ *   0 (OK) is returned on success and a negated errno is returned on
+ *   failure.
+ *
+ ***********************************************************************/
+
+struct symtab_s;
+EXTERN int nxflat_bind(FAR struct nxflat_loadinfo_s *loadinfo,
+                       FAR const struct symtab_s *exports, int nexports);
+
 /***********************************************************************
  * Name: 
  *
-- 
GitLab