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