insmod is code complete and ready for test

This commit is contained in:
Gregory Nutt 2015-12-11 10:55:21 -06:00
parent 05cb7a9043
commit 44e45f0f91
19 changed files with 201 additions and 897 deletions

2
arch

@ -1 +1 @@
Subproject commit c8448d662d63fecbbd8c603ab54cfbe2de200fe1
Subproject commit ca979759a701c3c5e7acb8fc8c604ee112c45601

View file

@ -12,6 +12,16 @@ config BINFMT_DISABLE
if !BINFMT_DISABLE
config MODULE
bool "Enable loadable OS modules"
default n
---help---
Enable support for loadable OS modules. Default: n
if MODULE
source binfmt/libmodule/Kconfig
endif
config BINFMT_EXEPATH
bool "Support PATH variable"
default n

View file

@ -71,6 +71,7 @@ VPATH =
SUBDIRS =
DEPPATH = --dep-path .
include libmodule$(DELIM)Make.defs
include libnxflat$(DELIM)Make.defs
include libelf$(DELIM)Make.defs
include libbuiltin$(DELIM)Make.defs

View file

@ -49,7 +49,6 @@
#include <arpa/inet.h>
#include <nuttx/arch.h>
#include <nuttx/binfmt/binfmt.h>
#include <nuttx/binfmt/module.h>
#include "libmodule/libmodule.h"
@ -78,26 +77,6 @@
# define MIN(a,b) (a < b ? a : b)
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int mod_loadbinary(FAR struct binary_s *binp);
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT)
static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static struct binfmt_s g_modbinfmt =
{
NULL, /* next */
mod_loadbinary, /* load */
NULL, /* unload */
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -107,24 +86,16 @@ static struct binfmt_s g_modbinfmt =
****************************************************************************/
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT)
static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
static void mod_dumploadinfo(FAR struct libmod_loadinfo_s *loadinfo)
{
int i;
bdbg("LOAD_INFO:\n");
bdbg(" textalloc: %08lx\n", (long)loadinfo->textalloc);
bdbg(" dataalloc: %08lx\n", (long)loadinfo->dataalloc);
bdbg(" datastart: %08lx\n", (long)loadinfo->datastart);
bdbg(" textsize: %ld\n", (long)loadinfo->textsize);
bdbg(" datasize: %ld\n", (long)loadinfo->datasize);
bdbg(" filelen: %ld\n", (long)loadinfo->filelen);
#ifdef CONFIG_BINFMT_CONSTRUCTORS
bdbg(" ctoralloc: %08lx\n", (long)loadinfo->ctoralloc);
bdbg(" ctors: %08lx\n", (long)loadinfo->ctors);
bdbg(" nctors: %d\n", loadinfo->nctors);
bdbg(" dtoralloc: %08lx\n", (long)loadinfo->dtoralloc);
bdbg(" dtors: %08lx\n", (long)loadinfo->dtors);
bdbg(" ndtors: %d\n", loadinfo->ndtors);
#endif
bdbg(" filfd: %d\n", loadinfo->filfd);
bdbg(" symtabidx: %d\n", loadinfo->symtabidx);
bdbg(" strtabidx: %d\n", loadinfo->strtabidx);
@ -186,25 +157,28 @@ static void mod_dumpinitializer(mod_initializer_t initializer,
#endif
/****************************************************************************
* Name: mod_loadbinary
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: insmod
*
* Description:
* Verify that the file is an ELF binary and, if so, load the ELF
* binary into memory
* Verify that the file is an ELF module binary and, if so, load the
* module into kernel memory and initialize it for use.
*
****************************************************************************/
static int mod_loadbinary(FAR struct binary_s *binp)
int insmod(FAR struct module_s *modp)
{
struct mod_loadinfo_s loadinfo; /* Contains globals for libmodule */
mod_initializer_t initializer;
int ret;
struct libmod_loadinfo_s loadinfo; /* Contains globals for libmodule */
int ret;
bvdbg("Loading file: %s\n", binp->filename);
bvdbg("Loading file: %s\n", modp->filename);
/* Initialize the ELF library to load the program binary. */
ret = libmod_initialize(binp->filename, &loadinfo);
ret = libmod_initialize(modp->filename, &loadinfo);
mod_dumploadinfo(&loadinfo);
if (ret != 0)
{
@ -224,7 +198,7 @@ static int mod_loadbinary(FAR struct binary_s *binp)
/* Bind the program to the exported symbol table */
ret = libmod_bind(&loadinfo, binp->exports, binp->nexports);
ret = libmod_bind(&loadinfo, modp->exports, modp->nexports);
if (ret != 0)
{
bdbg("Failed to bind symbols program binary: %d\n", ret);
@ -233,43 +207,18 @@ static int mod_loadbinary(FAR struct binary_s *binp)
/* Return the load information */
binp->entrypt = NULL;
binp->stacksize = 0;
/* Add the ELF allocation to the alloc[] only if there is no address
* environment. If there is an address environment, it will automatically
* be freed when the function exits
*
* REVISIT: If the module is loaded then unloaded, wouldn't this cause
* a memory leak?
*/
binp->alloc[0] = (FAR void *)loadinfo.textalloc;
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/* Save information about constructors. NOTE: destructors are not
* yet supported.
*/
binp->alloc[1] = loadinfo.ctoralloc;
binp->ctors = loadinfo.ctors;
binp->nctors = loadinfo.nctors;
binp->alloc[2] = loadinfo.dtoralloc;
binp->dtors = loadinfo.dtors;
binp->ndtors = loadinfo.ndtors;
#endif
modp->initializer = (mod_initializer_t)(loadinfo.textalloc + loadinfo.ehdr.e_entry);
modp->alloc = (FAR void *)loadinfo.textalloc;
/* Get the module initializer entry point */
initializer = (mod_initializer_t)(loadinfo.textalloc + loadinfo.ehdr.e_entry);
if (initialize)
if (modp->initializer)
{
mod_dumpinitializer(initializer, &loadinfo);
mod_dumpinitializer(modp->initializer, &loadinfo);
/* Call the module initializer */
ret = initializer();
ret = modp->initializer();
if (ret < 0)
{
bdbg("Failed to initialize the module: %d\n", ret);
@ -288,56 +237,4 @@ errout:
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mod_initialize
*
* Description:
* ELF support is built unconditionally. However, in order to
* use this binary format, this function must be called during system
* initialization in order to register the ELF binary format.
*
* Returned Value:
* This is a NuttX internal function so it follows the convention that
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_initialize(void)
{
int ret;
/* Register ourselves as a binfmt loader */
bvdbg("Registering ELF\n");
ret = register_binfmt(&g_modbinfmt);
if (ret != 0)
{
bdbg("Failed to register binfmt: %d\n", ret);
}
return ret;
}
/****************************************************************************
* Name: mod_uninitialize
*
* Description:
* Unregister the ELF binary loader
*
* Returned Value:
* None
*
****************************************************************************/
void mod_uninitialize(void)
{
unregister_binfmt(&g_modbinfmt);
}
#endif /* CONFIG_MODULE */

View file

@ -33,13 +33,3 @@ config MODULE_DUMPBUFFER
depends on DEBUG && DEBUG_VERBOSE
---help---
Dump various module buffers for debug purposes
config MODULE_EXIDX_SECTNAME
string "Module Section Name for Exception Index"
default ".ARM.exidx"
depends on UCLIBCXX_EXCEPTION
---help---
Set the name string for the exception index section on the modules to
be loaded by the module binary loader.
This is needed to support exception handling on loadable modules.

View file

@ -33,23 +33,19 @@
#
############################################################################
ifeq ($(CONFIG_ELF),y)
ifeq ($(CONFIG_MODULE),y)
# ELF application interfaces
# OS module interfaces
BINFMT_CSRCS += module.c
BINFMT_CSRCS += insmod.c
# ELF library
# loadable module library
BINFMT_CSRCS += libmodule_bind.c libmodule_init.c libmodule_iobuffer.c
BINFMT_CSRCS += libmodule_load.c libmodule_read.c libmodule_sections.c
BINFMT_CSRCS += libmodule_symbols.c libmodule_uninit.c libmodule_unload.c
BINFMT_CSRCS += libmodule_verify.c
ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
BINFMT_CSRCS += libmodule_ctors.c libmodule_dtors.c
endif
# Hook the libmodule subdirectory into the build
VPATH += libmodule

View file

@ -45,14 +45,6 @@ SECTIONS
*(.glue_7)
*(.glue_7t)
*(.jcr)
/* C++ support: The .init and .fini sections contain specific logic
* to manage static constructors and destructors.
*/
*(.gnu.linkonce.t.*)
*(.init) /* Old ABI */
*(.fini) /* Old ABI */
_etext = . ;
}
@ -76,30 +68,6 @@ SECTIONS
_edata = . ;
}
/* C++ support. For each global and static local C++ object,
* GCC creates a small subroutine to construct the object. Pointers
* to these routines (not the routines themselves) are stored as
* simple, linear arrays in the .ctors section of the object file.
* Similarly, pointers to global/static destructor routines are
* stored in .dtors.
*/
.ctors :
{
_sctors = . ;
*(.ctors) /* Old ABI: Unallocated */
*(.init_array) /* New ABI: Allocated */
_ectors = . ;
}
.dtors :
{
_sdtors = . ;
*(.dtors) /* Old ABI: Unallocated */
*(.fini_array) /* New ABI: Allocated */
_edtors = . ;
}
.bss :
{
_sbss = . ;

View file

@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/libmodule/libmodule.h
*
* Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -48,18 +48,125 @@
#include <nuttx/arch.h>
#include <nuttx/binfmt/module.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/* This struct provides a description of the currently loaded instantiation
* of the kernel module.
*/
struct libmod_loadinfo_s
{
/* elfalloc is the base address of the memory that is allocated to hold the
* module image.
*
* The alloc[] array in struct module_s will hold memory that persists after
* the module has been loaded.
*/
uintptr_t textalloc; /* .text memory allocated when module was loaded */
uintptr_t datastart; /* Start of.bss/.data memory in .text allocation */
size_t textsize; /* Size of the module .text memory allocation */
size_t datasize; /* Size of the module .bss/.data memory allocation */
off_t filelen; /* Length of the entire module file */
Elf32_Ehdr ehdr; /* Buffered module file header */
FAR Elf32_Shdr *shdr; /* Buffered module section headers */
uint8_t *iobuffer; /* File I/O buffer */
uint16_t symtabidx; /* Symbol table section index */
uint16_t strtabidx; /* String table section index */
uint16_t buflen; /* size of iobuffer[] */
int filfd; /* Descriptor for the file being loaded */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* These are APIs exported by libmodule and used by insmod
****************************************************************************/
/****************************************************************************
* Name: libmod_initialize
*
* Description:
* This function is called to configure the library to process an kernel
* module.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_initialize(FAR const char *filename,
FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_uninitialize
*
* Description:
* Releases any resources committed by mod_init(). This essentially
* undoes the actions of libmod_initialize.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_uninitialize(FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_load
*
* Description:
* Loads the binary into memory, allocating memory, performing relocations
* and initializing the data and bss segments.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_load(FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_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;
int libmod_bind(FAR struct libmod_loadinfo_s *loadinfo,
FAR const struct symtab_s *exports, int nexports);
/****************************************************************************
* Name: libmod_unload
*
* Description:
* This function unloads the object from memory. This essentially undoes
* the actions of mod_load. It is called only under certain error
* conditions after the module has been loaded but not yet started.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_unload(struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_verifyheader
*
@ -229,42 +336,4 @@ int libmod_allocbuffer(FAR struct libmod_loadinfo_s *loadinfo);
int libmod_reallocbuffer(FAR struct libmod_loadinfo_s *loadinfo, size_t increment);
/****************************************************************************
* Name: libmod_findctors
*
* Description:
* Find C++ static constructors.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
#ifdef CONFIG_BINFMT_CONSTRUCTORS
int libmod_loadctors(FAR struct libmod_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Name: libmod_loaddtors
*
* Description:
* Load pointers to static destructors into an in-memory array.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
#ifdef CONFIG_BINFMT_CONSTRUCTORS
int libmod_loaddtors(FAR struct libmod_loadinfo_s *loadinfo);
#endif
#endif /* __BINFMT_LIBELF_LIBELF_H */

View file

@ -56,18 +56,18 @@
****************************************************************************/
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be
* defined or CONFIG_ELF_DUMPBUFFER does nothing.
* defined or CONFIG_MODULE_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
# undef CONFIG_MODULE_DUMPBUFFER
#endif
#ifndef CONFIG_ELF_BUFFERSIZE
# define CONFIG_ELF_BUFFERSIZE 128
#ifndef CONFIG_MODULE_BUFFERSIZE
# define CONFIG_MODULE_BUFFERSIZE 128
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
#ifdef CONFIG_MODULE_DUMPBUFFER
# define libmod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define libmod_dumpbuffer(m,b,n)

View file

@ -1,216 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_ctors.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_loadctors
*
* Description:
* Load pointers to static constructors into an in-memory array.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_loadctors(FAR struct libmod_loadinfo_s *loadinfo)
{
FAR Elf32_Shdr *shdr;
size_t ctorsize;
int ctoridx;
int ret;
int i;
DEBUGASSERT(loadinfo->ctors == NULL);
/* Allocate an I/O buffer if necessary. This buffer is used by
* libmod_sectname() to accumulate the variable length symbol name.
*/
ret = libmod_allocbuffer(loadinfo);
if (ret < 0)
{
bdbg("libmod_allocbuffer failed: %d\n", ret);
return -ENOMEM;
}
/* Find the index to the section named ".ctors." NOTE: On old ABI system,
* .ctors is the name of the section containing the list of constructors;
* On newer systems, the similar section is called .init_array. It is
* expected that the linker script will force the section name to be ".ctors"
* in either case.
*/
ctoridx = libmod_findsection(loadinfo, ".ctors");
if (ctoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static constructor section.
*/
bvdbg("libmod_findsection .ctors section failed: %d\n", ctoridx);
return ret == -ENOENT ? OK : ret;
}
/* Now we can get a pointer to the .ctor section in the section header
* table.
*/
shdr = &loadinfo->shdr[ctoridx];
/* Get the size of the .ctor section and the number of constructors that
* will need to be called.
*/
ctorsize = shdr->sh_size;
loadinfo->nctors = ctorsize / sizeof(binfmt_ctor_t);
bvdbg("ctoridx=%d ctorsize=%d sizeof(binfmt_ctor_t)=%d nctors=%d\n",
ctoridx, ctorsize, sizeof(binfmt_ctor_t), loadinfo->nctors);
/* Check if there are any constructors. It is not an error if there
* are none.
*/
if (loadinfo->nctors > 0)
{
/* Check an assumption that we made above */
DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(binfmt_ctor_t));
/* In the old ABI, the .ctors section is not allocated. In that case,
* we need to allocate memory to hold the .ctors and then copy the
* from the file into the allocated memory.
*
* SHF_ALLOC indicates that the section requires memory during
* execution.
*/
if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
/* Allocate memory to hold a copy of the .ctor section */
loadinfo->ctoralloc = (binfmt_ctor_t *)kmm_malloc(ctorsize);
if (!loadinfo->ctoralloc)
{
bdbg("Failed to allocate memory for .ctors\n");
return -ENOMEM;
}
loadinfo->ctors = (binfmt_ctor_t *)loadinfo->ctoralloc;
/* Read the section header table into memory */
ret = libmod_read(loadinfo, (FAR uint8_t *)loadinfo->ctors, ctorsize,
shdr->sh_offset);
if (ret < 0)
{
bdbg("Failed to allocate .ctors: %d\n", ret);
return ret;
}
/* Fix up all of the .ctor addresses. Since the addresses
* do not lie in allocated memory, there will be no relocation
* section for them.
*/
for (i = 0; i < loadinfo->nctors; i++)
{
FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]);
bvdbg("ctor %d: %08lx + %08lx = %08lx\n",
i, *ptr, (unsigned long)loadinfo->textalloc,
(unsigned long)(*ptr + loadinfo->textalloc));
*ptr += loadinfo->textalloc;
}
}
else
{
/* Save the address of the .ctors (actually, .init_array) where it was
* loaded into memory. Since the .ctors lie in allocated memory, they
* will be relocated via the normal mechanism.
*/
loadinfo->ctors = (binfmt_ctor_t *)shdr->sh_addr;
}
}
return OK;
}
#endif /* CONFIG_BINFMT_CONSTRUCTORS */

View file

@ -1,216 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_dtors.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_loaddtors
*
* Description:
* Load pointers to static destructors into an in-memory array.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_loaddtors(FAR struct libmod_loadinfo_s *loadinfo)
{
FAR Elf32_Shdr *shdr;
size_t dtorsize;
int dtoridx;
int ret;
int i;
DEBUGASSERT(loadinfo->dtors == NULL);
/* Allocate an I/O buffer if necessary. This buffer is used by
* libmod_sectname() to accumulate the variable length symbol name.
*/
ret = libmod_allocbuffer(loadinfo);
if (ret < 0)
{
bdbg("libmod_allocbuffer failed: %d\n", ret);
return -ENOMEM;
}
/* Find the index to the section named ".dtors." NOTE: On old ABI system,
* .dtors is the name of the section containing the list of destructors;
* On newer systems, the similar section is called .fini_array. It is
* expected that the linker script will force the section name to be ".dtors"
* in either case.
*/
dtoridx = libmod_findsection(loadinfo, ".dtors");
if (dtoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static destructor section.
*/
bvdbg("libmod_findsection .dtors section failed: %d\n", dtoridx);
return ret == -ENOENT ? OK : ret;
}
/* Now we can get a pointer to the .dtor section in the section header
* table.
*/
shdr = &loadinfo->shdr[dtoridx];
/* Get the size of the .dtor section and the number of destructors that
* will need to be called.
*/
dtorsize = shdr->sh_size;
loadinfo->ndtors = dtorsize / sizeof(binfmt_dtor_t);
bvdbg("dtoridx=%d dtorsize=%d sizeof(binfmt_dtor_t)=%d ndtors=%d\n",
dtoridx, dtorsize, sizeof(binfmt_dtor_t), loadinfo->ndtors);
/* Check if there are any destructors. It is not an error if there
* are none.
*/
if (loadinfo->ndtors > 0)
{
/* Check an assumption that we made above */
DEBUGASSERT(shdr->sh_size == loadinfo->ndtors * sizeof(binfmt_dtor_t));
/* In the old ABI, the .dtors section is not allocated. In that case,
* we need to allocate memory to hold the .dtors and then copy the
* from the file into the allocated memory.
*
* SHF_ALLOC indicates that the section requires memory during
* execution.
*/
if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
/* Allocate memory to hold a copy of the .dtor section */
loadinfo->ctoralloc = (binfmt_dtor_t *)kmm_malloc(dtorsize);
if (!loadinfo->ctoralloc)
{
bdbg("Failed to allocate memory for .dtors\n");
return -ENOMEM;
}
loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc;
/* Read the section header table into memory */
ret = libmod_read(loadinfo, (FAR uint8_t *)loadinfo->dtors, dtorsize,
shdr->sh_offset);
if (ret < 0)
{
bdbg("Failed to allocate .dtors: %d\n", ret);
return ret;
}
/* Fix up all of the .dtor addresses. Since the addresses
* do not lie in allocated memory, there will be no relocation
* section for them.
*/
for (i = 0; i < loadinfo->ndtors; i++)
{
FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->dtors)[i]);
bvdbg("dtor %d: %08lx + %08lx = %08lx\n",
i, *ptr, (unsigned long)loadinfo->textalloc,
(unsigned long)(*ptr + loadinfo->textalloc));
*ptr += loadinfo->textalloc;
}
}
else
{
/* Save the address of the .dtors (actually, .init_array) where it was
* loaded into memory. Since the .dtors lie in allocated memory, they
* will be relocated via the normal mechanism.
*/
loadinfo->dtors = (binfmt_dtor_t *)shdr->sh_addr;
}
}
return OK;
}
#endif /* CONFIG_BINFMT_CONSTRUCTORS */

View file

@ -57,14 +57,14 @@
****************************************************************************/
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be
* defined or CONFIG_ELF_DUMPBUFFER does nothing.
* defined or CONFIG_MODULE_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
# undef CONFIG_MODULE_DUMPBUFFER
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
#ifdef CONFIG_MODULE_DUMPBUFFER
# define libmod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define libmod_dumpbuffer(m,b,n)

View file

@ -84,14 +84,14 @@ int libmod_allocbuffer(FAR struct libmod_loadinfo_s *loadinfo)
{
/* No.. allocate one now */
loadinfo->iobuffer = (FAR uint8_t *)kmm_malloc(CONFIG_ELF_BUFFERSIZE);
loadinfo->iobuffer = (FAR uint8_t *)kmm_malloc(CONFIG_MODULE_BUFFERSIZE);
if (!loadinfo->iobuffer)
{
bdbg("Failed to allocate an I/O buffer\n");
return -ENOMEM;
}
loadinfo->buflen = CONFIG_ELF_BUFFERSIZE;
loadinfo->buflen = CONFIG_MODULE_BUFFERSIZE;
}
return OK;

View file

@ -50,6 +50,7 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
@ -58,7 +59,7 @@
* Pre-processor Definitions
****************************************************************************/
#define ELF_ALIGN_MASK ((1 << CONFIG_ELF_ALIGN_LOG2) - 1)
#define ELF_ALIGN_MASK ((1 << CONFIG_MODULE_ALIGN_LOG2) - 1)
#define ELF_ALIGNUP(a) (((unsigned long)(a) + ELF_ALIGN_MASK) & ~ELF_ALIGN_MASK)
#define ELF_ALIGNDOWN(a) ((unsigned long)(a) & ~ELF_ALIGN_MASK)
@ -157,7 +158,7 @@ static inline int libmod_loadfile(FAR struct libmod_loadinfo_s *loadinfo)
bvdbg("Loaded sections:\n");
text = (FAR uint8_t *)loadinfo->textalloc;
data = (FAR uint8_t *)loadinfo->dataalloc;
data = (FAR uint8_t *)loadinfo->datastart;
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
@ -243,10 +244,6 @@ static inline int libmod_loadfile(FAR struct libmod_loadinfo_s *loadinfo)
int libmod_load(FAR struct libmod_loadinfo_s *loadinfo)
{
size_t heapsize;
#ifdef CONFIG_UCLIBCXX_EXCEPTION
int exidx;
#endif
int ret;
bvdbg("loadinfo: %p\n", loadinfo);
@ -265,15 +262,11 @@ int libmod_load(FAR struct libmod_loadinfo_s *loadinfo)
libmod_elfsize(loadinfo);
/* Determine the heapsize to allocate. */
heapsize = 0;
/* Allocate (and zero) memory for the ELF file. */
/* Allocate memory to hold the ELF image */
loadinfo->textalloc = (uintptr_t)kmm_zalloc(textsize + datasize);
loadinfo->textalloc = (uintptr_t)kmm_zalloc(loadinfo->textsize + loadinfo->datasize);
if (!loadinfo->textalloc)
{
bdbg("ERROR: Failed to allocate memory for the module\n");
@ -281,7 +274,7 @@ int libmod_load(FAR struct libmod_loadinfo_s *loadinfo)
goto errout_with_buffers;
}
loadinfo->dataalloc = loadinfo->textalloc + textsize;
loadinfo->datastart = loadinfo->textalloc + loadinfo->textsize;
/* Load ELF section data into memory */
@ -292,36 +285,6 @@ int libmod_load(FAR struct libmod_loadinfo_s *loadinfo)
goto errout_with_buffers;
}
/* Load static constructors and destructors. */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
ret = libmod_loadctors(loadinfo);
if (ret < 0)
{
bdbg("ERROR: libmod_loadctors failed: %d\n", ret);
goto errout_with_buffers;
}
ret = libmod_loaddtors(loadinfo);
if (ret < 0)
{
bdbg("ERROR: libmod_loaddtors failed: %d\n", ret);
goto errout_with_buffers;
}
#endif
#ifdef CONFIG_UCLIBCXX_EXCEPTION
exidx = libmod_findsection(loadinfo, CONFIG_ELF_EXIDX_SECTNAME);
if (exidx < 0)
{
bvdbg("libmod_findsection: Exception Index section not found: %d\n", exidx);
}
else
{
up_init_exidx(loadinfo->shdr[exidx].sh_addr, loadinfo->shdr[exidx].sh_size);
}
#endif
return OK;
/* Error exits */

View file

@ -49,6 +49,8 @@
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

View file

@ -156,7 +156,7 @@ static inline int libmod_sectname(FAR struct libmod_loadinfo_s *loadinfo,
/* No.. then we have to read more */
ret = libmod_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
ret = libmod_reallocbuffer(loadinfo, CONFIG_MODULE_BUFFERINCR);
if (ret < 0)
{
bdbg("libmod_reallocbuffer failed: %d\n", ret);

View file

@ -54,8 +54,8 @@
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_ELF_BUFFERINCR
# define CONFIG_ELF_BUFFERINCR 32
#ifndef CONFIG_MODULE_BUFFERINCR
# define CONFIG_MODULE_BUFFERINCR 32
#endif
/****************************************************************************
@ -146,7 +146,7 @@ static int libmod_symname(FAR struct libmod_loadinfo_s *loadinfo,
/* No.. then we have to read more */
ret = libmod_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
ret = libmod_reallocbuffer(loadinfo, CONFIG_MODULE_BUFFERINCR);
if (ret < 0)
{
bdbg("libmod_reallocbuffer failed: %d\n", ret);

View file

@ -93,32 +93,10 @@ int libmod_unload(struct libmod_loadinfo_s *loadinfo)
/* Clear out all indications of the allocated address environment */
loadinfo->textalloc = 0;
loadinfo->dataalloc = 0;
loadinfo->datastart = 0;
loadinfo->textsize = 0;
loadinfo->datasize = 0;
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/* Release memory used to hold static constructors and destructors */
if (loadinfo->ctoralloc != 0)
{
kmm_free(loadinfo->ctoralloc);
loadinfo->ctoralloc = NULL;
}
loadinfo->ctors = NULL;
loadinfo->nctors = 0;
if (loadinfo->dtoralloc != 0)
{
kmm_free(loadinfo->dtoralloc);
loadinfo->dtoralloc = NULL;
}
loadinfo->dtors = NULL;
loadinfo->ndtors = 0;
#endif
return OK;
}

View file

@ -86,45 +86,6 @@
* Public Types
****************************************************************************/
/* This struct provides a description of the currently loaded instantiation
* of the kernel module.
*/
struct mod_loadinfo_s
{
/* elfalloc is the base address of the memory that is allocated to hold the
* module image.
*
* The alloc[] array in struct binary_s will hold memory that persists after
* the module has been loaded.
*/
uintptr_t textalloc; /* .text memory allocated when module was loaded */
uintptr_t dataalloc; /* .bss/.data memory allocated when module was loaded */
size_t textsize; /* Size of the module .text memory allocation */
size_t datasize; /* Size of the module .bss/.data memory allocation */
off_t filelen; /* Length of the entire module file */
Elf32_Ehdr ehdr; /* Buffered module file header */
FAR Elf32_Shdr *shdr; /* Buffered module section headers */
uint8_t *iobuffer; /* File I/O buffer */
/* Constructors and destructors */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
FAR void *ctoralloc; /* Memory allocated for ctors */
FAR void *dtoralloc; /* Memory allocated dtors */
FAR binfmt_ctor_t *ctors; /* Pointer to a list of constructors */
FAR binfmt_dtor_t *dtors; /* Pointer to a list of destructors */
uint16_t nctors; /* Number of constructors */
uint16_t ndtors; /* Number of destructors */
#endif
uint16_t symtabidx; /* Symbol table section index */
uint16_t strtabidx; /* String table section index */
uint16_t buflen; /* size of iobuffer[] */
int filfd; /* Descriptor for the file being loaded */
};
/* A NuttX module is expected to export a function called module_initialize()
* that has the following function prototype. This function should appear as
* the entry point in the ELF module file and will be called bythe binfmt
@ -145,8 +106,34 @@ struct mod_loadinfo_s
typedef CODE int (*mod_initializer_t)(void);
/* This describes the file to be loaded.
*
* NOTE 1: The 'filename' must be the full, absolute path to the file to be
* executed unless CONFIG_BINFMT_EXEPATH is defined. In that case,
* 'filename' may be a relative path; a set of candidate absolute paths
* will be generated using the PATH environment variable and load_module()
* will attempt to load each file that is found at those absolute paths.
*/
struct symtab_s;
struct module_s
{
/* Information provided to insmod by the caller */
FAR const char *filename; /* Full path to the binary to be loaded (See NOTE 1 above) */
FAR const struct symtab_s *exports; /* Table of exported symbols */
int nexports; /* The number of symbols in exports[] */
/* Information provided from insmod (if successful) describing the
* resources used by the loaded module.
*/
mod_initializer_t initializer; /* Module initializer function */
FAR void *alloc; /* Allocated kernel memory */
};
/****************************************************************************
* Public Functions
* Public Function Prototypes
****************************************************************************/
#undef EXTERN
@ -159,120 +146,15 @@ extern "C"
#endif
/****************************************************************************
* These are APIs exported by libelf (but are used only by the binfmt logic):
****************************************************************************/
/****************************************************************************
* Name: libmod_initialize
* Name: insmod
*
* Description:
* This function is called to configure the library to process an kernel
* module.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
* Verify that the file is an ELF module binary and, if so, load the
* module into kernel memory and initialize it for use.
*
****************************************************************************/
int libmod_initalize(FAR const char *filename,
FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_uninitialize
*
* Description:
* Releases any resources committed by mod_init(). This essentially
* undoes the actions of mod_init.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_uninitialize(FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_load
*
* Description:
* Loads the binary into memory, allocating memory, performing relocations
* and initializing the data and bss segments.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_load(FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_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;
int mod_bind(FAR struct mod_loadinfo_s *loadinfo,
FAR const struct symtab_s *exports, int nexports);
/****************************************************************************
* Name: mod_unload
*
* Description:
* This function unloads the object from memory. This essentially undoes
* the actions of mod_load. It is called only under certain error
* conditions after the module has been loaded but not yet started.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_unload(struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* These are APIs used outside of binfmt by NuttX:
****************************************************************************/
/****************************************************************************
* Name: mod_initialize
*
* Description:
* Module support is built unconditionally. However, in order to
* use this binary format, this function must be called during system
* initialization in order to register the module binary format.
*
* Returned Value:
* This is a NuttX internal function so it follows the convention that
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_initialize(void);
/****************************************************************************
* Name: mod_uninitialize
*
* Description:
* Unregister the module loader
*
* Returned Value:
* None
*
****************************************************************************/
void mod_uninitialize(void);
int insmod(FAR struct module_s *modp);
/****************************************************************************
* These are APIs must be provided by architecture-specific logic.
@ -323,26 +205,6 @@ int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
int up_relocateadd(FAR const Elf32_Rela *rel,
FAR const Elf32_Sym *sym, uintptr_t addr);
#ifdef CONFIG_UCLIBCXX_EXCEPTION
/****************************************************************************
* Name: up_init_exidx
*
* Description:
* Load the boundaries of the Exception Index ELF section in order to
* support exception handling for loaded modules.
*
* Input Parameters:
* address - The ELF section address for the Exception Index
* size - The size of the ELF section.
*
* Returned Value:
* Always returns Zero (OK).
*
****************************************************************************/
int up_init_exidx(Elf32_Addr address, Elf32_Word size);
#endif
/****************************************************************************
* Name: up_coherent_dcache
*