Move module support from binfmt/ to sched/ so that it can be configured and built independently from binfmt features

This commit is contained in:
Gregory Nutt
2015-12-12 07:09:17 -06:00
parent 44e45f0f91
commit 49554fe4fc
22 changed files with 393 additions and 574 deletions

View File

@@ -12,16 +12,6 @@ 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,7 +71,6 @@ 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

@@ -1,240 +0,0 @@
/****************************************************************************
* binfmt/module.c
*
* 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
* 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 <stdint.h>
#include <string.h>
#include <elf32.h>
#include <debug.h>
#include <errno.h>
#include <arpa/inet.h>
#include <nuttx/arch.h>
#include <nuttx/binfmt/module.h>
#include "libmodule/libmodule.h"
#ifdef CONFIG_MODULE
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be
* defined or CONFIG_MODULE_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_MODULE_DUMPBUFFER
#endif
#ifdef CONFIG_MODULE_DUMPBUFFER
# define mod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define mod_dumpbuffer(m,b,n)
#endif
#ifndef MIN
# define MIN(a,b) (a < b ? a : b)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mod_dumploadinfo
****************************************************************************/
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT)
static void mod_dumploadinfo(FAR struct libmod_loadinfo_s *loadinfo)
{
int i;
bdbg("LOAD_INFO:\n");
bdbg(" textalloc: %08lx\n", (long)loadinfo->textalloc);
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);
bdbg(" filfd: %d\n", loadinfo->filfd);
bdbg(" symtabidx: %d\n", loadinfo->symtabidx);
bdbg(" strtabidx: %d\n", loadinfo->strtabidx);
bdbg("ELF Header:\n");
bdbg(" e_ident: %02x %02x %02x %02x\n",
loadinfo->ehdr.e_ident[0], loadinfo->ehdr.e_ident[1],
loadinfo->ehdr.e_ident[2], loadinfo->ehdr.e_ident[3]);
bdbg(" e_type: %04x\n", loadinfo->ehdr.e_type);
bdbg(" e_machine: %04x\n", loadinfo->ehdr.e_machine);
bdbg(" e_version: %08x\n", loadinfo->ehdr.e_version);
bdbg(" e_entry: %08lx\n", (long)loadinfo->ehdr.e_entry);
bdbg(" e_phoff: %d\n", loadinfo->ehdr.e_phoff);
bdbg(" e_shoff: %d\n", loadinfo->ehdr.e_shoff);
bdbg(" e_flags: %08x\n" , loadinfo->ehdr.e_flags);
bdbg(" e_ehsize: %d\n", loadinfo->ehdr.e_ehsize);
bdbg(" e_phentsize: %d\n", loadinfo->ehdr.e_phentsize);
bdbg(" e_phnum: %d\n", loadinfo->ehdr.e_phnum);
bdbg(" e_shentsize: %d\n", loadinfo->ehdr.e_shentsize);
bdbg(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
bdbg(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
{
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
bdbg("Sections %d:\n", i);
bdbg(" sh_name: %08x\n", shdr->sh_name);
bdbg(" sh_type: %08x\n", shdr->sh_type);
bdbg(" sh_flags: %08x\n", shdr->sh_flags);
bdbg(" sh_addr: %08x\n", shdr->sh_addr);
bdbg(" sh_offset: %d\n", shdr->sh_offset);
bdbg(" sh_size: %d\n", shdr->sh_size);
bdbg(" sh_link: %d\n", shdr->sh_link);
bdbg(" sh_info: %d\n", shdr->sh_info);
bdbg(" sh_addralign: %d\n", shdr->sh_addralign);
bdbg(" sh_entsize: %d\n", shdr->sh_entsize);
}
}
}
#else
# define mod_dumploadinfo(i)
#endif
/****************************************************************************
* Name: mod_dumpinitializer
****************************************************************************/
#ifdef CONFIG_MODULE_DUMPBUFFER
static void mod_dumpinitializer(mod_initializer_t initializer,
FAR struct mod_loadinfo_s *loadinfo)
{
mod_dumpbuffer("Initializer code", (FAR const uint8_t *)initializer,
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
}
#else
# define mod_dumpinitializer(b,l)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: insmod
*
* Description:
* Verify that the file is an ELF module binary and, if so, load the
* module into kernel memory and initialize it for use.
*
****************************************************************************/
int insmod(FAR struct module_s *modp)
{
struct libmod_loadinfo_s loadinfo; /* Contains globals for libmodule */
int ret;
bvdbg("Loading file: %s\n", modp->filename);
/* Initialize the ELF library to load the program binary. */
ret = libmod_initialize(modp->filename, &loadinfo);
mod_dumploadinfo(&loadinfo);
if (ret != 0)
{
bdbg("Failed to initialize for load of ELF program: %d\n", ret);
goto errout;
}
/* Load the program binary */
ret = libmod_load(&loadinfo);
mod_dumploadinfo(&loadinfo);
if (ret != 0)
{
bdbg("Failed to load ELF program binary: %d\n", ret);
goto errout_with_init;
}
/* Bind the program to the exported symbol table */
ret = libmod_bind(&loadinfo, modp->exports, modp->nexports);
if (ret != 0)
{
bdbg("Failed to bind symbols program binary: %d\n", ret);
goto errout_with_load;
}
/* Return the load information */
modp->initializer = (mod_initializer_t)(loadinfo.textalloc + loadinfo.ehdr.e_entry);
modp->alloc = (FAR void *)loadinfo.textalloc;
/* Get the module initializer entry point */
if (modp->initializer)
{
mod_dumpinitializer(modp->initializer, &loadinfo);
/* Call the module initializer */
ret = modp->initializer();
if (ret < 0)
{
bdbg("Failed to initialize the module: %d\n", ret);
goto errout_with_load;
}
}
libmod_uninitialize(&loadinfo);
return OK;
errout_with_load:
libmod_unload(&loadinfo);
errout_with_init:
libmod_uninitialize(&loadinfo);
errout:
return ret;
}
#endif /* CONFIG_MODULE */

View File

@@ -1,35 +0,0 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config MODULE_ALIGN_LOG2
int "Log2 Section Alignment"
default 2
---help---
Align all sections to this Log2 value: 0->1, 1->2, 2->4, etc.
config MODULE_BUFFERSIZE
int "Module I/O Buffer Size"
default 128
---help---
This is an I/O buffer that is used to access the module file.
Variable length items will need to be read (such as symbol names).
This is really just this initial size of the buffer; it will be
reallocated as necessary to hold large symbol names). Default: 128
config MODULE_BUFFERINCR
int "Module I/O Buffer Realloc Increment"
default 32
---help---
This is an I/O buffer that is used to access the module file.
Variable length items will need to be read (such as symbol names).
This value specifies the size increment to use each time the
buffer is reallocated. Default: 32
config MODULE_DUMPBUFFER
bool "Dump module buffers"
default n
depends on DEBUG && DEBUG_VERBOSE
---help---
Dump various module buffers for debug purposes

View File

@@ -1,55 +0,0 @@
############################################################################
# binfmt/libmodule/Make.defs
#
# 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.
#
############################################################################
ifeq ($(CONFIG_MODULE),y)
# OS module interfaces
BINFMT_CSRCS += insmod.c
# 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
# Hook the libmodule subdirectory into the build
VPATH += libmodule
SUBDIRS += libmodule
DEPPATH += --dep-path libmodule
endif

View File

@@ -1,97 +0,0 @@
/****************************************************************************
* binfmt/libmodule/gnu-elf.ld
*
* 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
* 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.
*
****************************************************************************/
SECTIONS
{
.text 0x00000000 :
{
_stext = . ;
*(.text)
*(.text.*)
*(.gnu.warning)
*(.stub)
*(.glue_7)
*(.glue_7t)
*(.jcr)
_etext = . ;
}
.rodata :
{
_srodata = . ;
*(.rodata)
*(.rodata1)
*(.rodata.*)
*(.gnu.linkonce.r*)
_erodata = . ;
}
.data :
{
_sdata = . ;
*(.data)
*(.data1)
*(.data.*)
*(.gnu.linkonce.d*)
_edata = . ;
}
.bss :
{
_sbss = . ;
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.b*)
*(COMMON)
_ebss = . ;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}

View File

@@ -1,339 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule.h
*
* 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
* 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.
*
****************************************************************************/
#ifndef __BINFMT_LIBELF_LIBELF_H
#define __BINFMT_LIBELF_LIBELF_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <elf32.h>
#include <nuttx/arch.h>
#include <nuttx/binfmt/module.h>
/****************************************************************************
* 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
*
* Description:
* Given the header from a possible ELF executable, verify that it is
* an ELF executable.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_verifyheader(FAR const Elf32_Ehdr *header);
/****************************************************************************
* Name: libmod_read
*
* Description:
* Read 'readsize' bytes from the object file at 'offset'. The data is
* read into 'buffer.'
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_read(FAR struct libmod_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset);
/****************************************************************************
* Name: libmod_loadshdrs
*
* Description:
* Loads section headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_loadshdrs(FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_findsection
*
* Description:
* A section by its name.
*
* Input Parameters:
* loadinfo - Load state information
* sectname - Name of the section to find
*
* Returned Value:
* On success, the index to the section is returned; A negated errno value
* is returned on failure.
*
****************************************************************************/
int libmod_findsection(FAR struct libmod_loadinfo_s *loadinfo,
FAR const char *sectname);
/****************************************************************************
* Name: libmod_findsymtab
*
* Description:
* Find the symbol table section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_findsymtab(FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_readsym
*
* Description:
* Read the ELFT symbol structure at the specfied index into memory.
*
* Input Parameters:
* loadinfo - Load state information
* index - Symbol table index
* sym - Location to return the table entry
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_readsym(FAR struct libmod_loadinfo_s *loadinfo, int index,
FAR Elf32_Sym *sym);
/****************************************************************************
* Name: libmod_symvalue
*
* Description:
* Get the value of a symbol. The updated value of the symbol is returned
* in the st_value field of the symbol table entry.
*
* Input Parameters:
* loadinfo - Load state information
* sym - Symbol table entry (value might be undefined)
* exports - The symbol table to use for resolving undefined symbols.
* nexports - Number of symbols in the symbol table.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
* EINVAL - There is something inconsistent in the symbol table (should only
* happen if the file is corrupted)
* ENOSYS - Symbol lies in common
* ESRCH - Symbol has no name
* ENOENT - Symbol undefined and not provided via a symbol table
*
****************************************************************************/
int libmod_symvalue(FAR struct libmod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
FAR const struct symtab_s *exports, int nexports);
/****************************************************************************
* Name: libmod_freebuffers
*
* Description:
* Release all working buffers.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_freebuffers(FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_allocbuffer
*
* Description:
* Perform the initial allocation of the I/O buffer, if it has not already
* been allocated.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_allocbuffer(FAR struct libmod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: libmod_reallocbuffer
*
* Description:
* Increase the size of I/O buffer by the specified buffer increment.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_reallocbuffer(FAR struct libmod_loadinfo_s *loadinfo, size_t increment);
#endif /* __BINFMT_LIBELF_LIBELF_H */

View File

@@ -1,332 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_bind.c
*
* 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
* 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 <stdint.h>
#include <string.h>
#include <elf32.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/binfmt/module.h>
#include <nuttx/binfmt/symtab.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be
* defined or CONFIG_MODULE_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_MODULE_DUMPBUFFER
#endif
#ifndef CONFIG_MODULE_BUFFERSIZE
# define CONFIG_MODULE_BUFFERSIZE 128
#endif
#ifdef CONFIG_MODULE_DUMPBUFFER
# define libmod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define libmod_dumpbuffer(m,b,n)
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_readrel
*
* Description:
* Read the ELF32_Rel structure into memory.
*
****************************************************************************/
static inline int libmod_readrel(FAR struct libmod_loadinfo_s *loadinfo,
FAR const Elf32_Shdr *relsec,
int index, FAR Elf32_Rel *rel)
{
off_t offset;
/* Verify that the symbol table index lies within symbol table */
if (index < 0 || index > (relsec->sh_size / sizeof(Elf32_Rel)))
{
bdbg("Bad relocation symbol index: %d\n", index);
return -EINVAL;
}
/* Get the file offset to the symbol table entry */
offset = relsec->sh_offset + sizeof(Elf32_Rel) * index;
/* And, finally, read the symbol table entry into memory */
return libmod_read(loadinfo, (FAR uint8_t *)rel, sizeof(Elf32_Rel), offset);
}
/****************************************************************************
* Name: libmod_relocate and libmod_relocateadd
*
* Description:
* Perform all relocations associated with a section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static int libmod_relocate(FAR struct libmod_loadinfo_s *loadinfo, int relidx,
FAR const struct symtab_s *exports, int nexports)
{
FAR Elf32_Shdr *relsec = &loadinfo->shdr[relidx];
FAR Elf32_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info];
Elf32_Rel rel;
Elf32_Sym sym;
FAR Elf32_Sym *psym;
uintptr_t addr;
int symidx;
int ret;
int i;
/* Examine each relocation in the section. 'relsec' is the section
* containing the relations. 'dstsec' is the section containing the data
* to be relocated.
*/
for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++)
{
psym = &sym;
/* Read the relocation entry into memory */
ret = libmod_readrel(loadinfo, relsec, i, &rel);
if (ret < 0)
{
bdbg("Section %d reloc %d: Failed to read relocation entry: %d\n",
relidx, i, ret);
return ret;
}
/* Get the symbol table index for the relocation. This is contained
* in a bit-field within the r_info element.
*/
symidx = ELF32_R_SYM(rel.r_info);
/* Read the symbol table entry into memory */
ret = libmod_readsym(loadinfo, symidx, &sym);
if (ret < 0)
{
bdbg("Section %d reloc %d: Failed to read symbol[%d]: %d\n",
relidx, i, symidx, ret);
return ret;
}
/* Get the value of the symbol (in sym.st_value) */
ret = libmod_symvalue(loadinfo, &sym, exports, nexports);
if (ret < 0)
{
/* The special error -ESRCH is returned only in one condition: The
* symbol has no name.
*
* There are a few relocations for a few architectures that do
* no depend upon a named symbol. We don't know if that is the
* case here, but we will use a NULL symbol pointer to indicate
* that case to up_relocate(). That function can then do what
* is best.
*/
if (ret == -ESRCH)
{
bdbg("Section %d reloc %d: Undefined symbol[%d] has no name: %d\n",
relidx, i, symidx, ret);
psym = NULL;
}
else
{
bdbg("Section %d reloc %d: Failed to get value of symbol[%d]: %d\n",
relidx, i, symidx, ret);
return ret;
}
}
/* Calculate the relocation address. */
if (rel.r_offset < 0 || rel.r_offset > dstsec->sh_size - sizeof(uint32_t))
{
bdbg("Section %d reloc %d: Relocation address out of range, offset %d size %d\n",
relidx, i, rel.r_offset, dstsec->sh_size);
return -EINVAL;
}
addr = dstsec->sh_addr + rel.r_offset;
/* Now perform the architecture-specific relocation */
ret = up_relocate(&rel, psym, addr);
if (ret < 0)
{
bdbg("ERROR: Section %d reloc %d: Relocation failed: %d\n", relidx, i, ret);
return ret;
}
}
return OK;
}
static int libmod_relocateadd(FAR struct libmod_loadinfo_s *loadinfo, int relidx,
FAR const struct symtab_s *exports, int nexports)
{
bdbg("Not implemented\n");
return -ENOSYS;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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.
*
****************************************************************************/
int libmod_bind(FAR struct libmod_loadinfo_s *loadinfo,
FAR const struct symtab_s *exports, int nexports)
{
int ret;
int i;
/* Find the symbol and string tables */
ret = libmod_findsymtab(loadinfo);
if (ret < 0)
{
return ret;
}
/* Allocate an I/O buffer. This buffer is used by libmod_symname() to
* accumulate the variable length symbol name.
*/
ret = libmod_allocbuffer(loadinfo);
if (ret < 0)
{
bdbg("libmod_allocbuffer failed: %d\n", ret);
return -ENOMEM;
}
/* Process relocations in every allocated section */
for (i = 1; i < loadinfo->ehdr.e_shnum; i++)
{
/* Get the index to the relocation section */
int infosec = loadinfo->shdr[i].sh_info;
if (infosec >= loadinfo->ehdr.e_shnum)
{
continue;
}
/* Make sure that the section is allocated. We can't relocated
* sections that were not loaded into memory.
*/
if ((loadinfo->shdr[infosec].sh_flags & SHF_ALLOC) == 0)
{
continue;
}
/* Process the relocations by type */
if (loadinfo->shdr[i].sh_type == SHT_REL)
{
ret = libmod_relocate(loadinfo, i, exports, nexports);
}
else if (loadinfo->shdr[i].sh_type == SHT_RELA)
{
ret = libmod_relocateadd(loadinfo, i, exports, nexports);
}
if (ret < 0)
{
break;
}
}
#if defined(CONFIG_ARCH_HAVE_COHERENT_DCACHE)
/* Ensure that the I and D caches are coherent before starting the newly
* loaded module by cleaning the D cache (i.e., flushing the D cache
* contents to memory and invalidating the I cache).
*/
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
up_coherent_dcache(loadinfo->dataalloc, loadinfo->datasize);
#endif
return ret;
}

View File

@@ -1,205 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_init.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 <sys/stat.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <elf32.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_BINFMT have to be
* defined or CONFIG_MODULE_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_MODULE_DUMPBUFFER
#endif
#ifdef CONFIG_MODULE_DUMPBUFFER
# define libmod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define libmod_dumpbuffer(m,b,n)
#endif
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_filelen
*
* Description:
* Get the size of the ELF file
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static inline int libmod_filelen(FAR struct libmod_loadinfo_s *loadinfo,
FAR const char *filename)
{
struct stat buf;
int ret;
/* Get the file stats */
ret = stat(filename, &buf);
if (ret < 0)
{
int errval = errno;
bdbg("Failed to stat file: %d\n", errval);
return -errval;
}
/* Verify that it is a regular file */
if (!S_ISREG(buf.st_mode))
{
bdbg("Not a regular file. mode: %d\n", buf.st_mode);
return -ENOENT;
}
/* TODO: Verify that the file is readable. Not really important because
* we will detect this when we try to open the file read-only.
*/
/* Return the size of the file in the loadinfo structure */
loadinfo->filelen = buf.st_size;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_initialize
*
* Description:
* This function is called to configure the library to process an ELF
* program binary.
*
* 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)
{
int ret;
bvdbg("filename: %s loadinfo: %p\n", filename, loadinfo);
/* Clear the load info structure */
memset(loadinfo, 0, sizeof(struct libmod_loadinfo_s));
/* Get the length of the file. */
ret = libmod_filelen(loadinfo, filename);
if (ret < 0)
{
bdbg("libmod_filelen failed: %d\n", ret);
return ret;
}
/* Open the binary file for reading (only) */
loadinfo->filfd = open(filename, O_RDONLY);
if (loadinfo->filfd < 0)
{
int errval = errno;
bdbg("Failed to open ELF binary %s: %d\n", filename, errval);
return -errval;
}
/* Read the ELF ehdr from offset 0 */
ret = libmod_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr,
sizeof(Elf32_Ehdr), 0);
if (ret < 0)
{
bdbg("Failed to read ELF header: %d\n", ret);
return ret;
}
libmod_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr,
sizeof(Elf32_Ehdr));
/* Verify the ELF header */
ret = libmod_verifyheader(&loadinfo->ehdr);
if (ret < 0)
{
/* This may not be an error because we will be called to attempt loading
* EVERY binary. If libmod_verifyheader() does not recognize the ELF header,
* it will -ENOEXEC whcih simply informs the system that the file is not an
* ELF file. libmod_verifyheader() will return other errors if the ELF header
* is not correctly formed.
*/
bdbg("Bad ELF header: %d\n", ret);
return ret;
}
return OK;
}

View File

@@ -1,136 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_iobuffer.c
*
* Copyright (C) 2012-2013 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 <debug.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_allocbuffer
*
* Description:
* Perform the initial allocation of the I/O buffer, if it has not already
* been allocated.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_allocbuffer(FAR struct libmod_loadinfo_s *loadinfo)
{
/* Has a buffer been allocated> */
if (!loadinfo->iobuffer)
{
/* No.. allocate one now */
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_MODULE_BUFFERSIZE;
}
return OK;
}
/****************************************************************************
* Name: libmod_reallocbuffer
*
* Description:
* Increase the size of I/O buffer by the specified buffer increment.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_reallocbuffer(FAR struct libmod_loadinfo_s *loadinfo, size_t increment)
{
FAR void *buffer;
size_t newsize;
/* Get the new size of the allocation */
newsize = loadinfo->buflen + increment;
/* And perform the reallocation */
buffer = kmm_realloc((FAR void *)loadinfo->iobuffer, newsize);
if (!buffer)
{
bdbg("Failed to reallocate the I/O buffer\n");
return -ENOMEM;
}
/* Save the new buffer info */
loadinfo->iobuffer = buffer;
loadinfo->buflen = newsize;
return OK;
}

View File

@@ -1,296 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_load.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 <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <elf32.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#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)
#ifndef MAX
# define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
# define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_elfsize
*
* Description:
* Calculate total memory allocation for the ELF file.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static void libmod_elfsize(struct libmod_loadinfo_s *loadinfo)
{
size_t textsize;
size_t datasize;
int i;
/* Accumulate the size each section into memory that is marked SHF_ALLOC */
textsize = 0;
datasize = 0;
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
/* SHF_ALLOC indicates that the section requires memory during
* execution.
*/
if ((shdr->sh_flags & SHF_ALLOC) != 0)
{
/* 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->textsize = textsize;
loadinfo->datasize = datasize;
}
/****************************************************************************
* Name: libmod_loadfile
*
* Description:
* Read the section data into memory. Section addresses in the shdr[] are
* updated to point to the corresponding position in the memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static inline int libmod_loadfile(FAR struct libmod_loadinfo_s *loadinfo)
{
FAR uint8_t *text;
FAR uint8_t *data;
FAR uint8_t **pptr;
int ret;
int i;
/* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
bvdbg("Loaded sections:\n");
text = (FAR uint8_t *)loadinfo->textalloc;
data = (FAR uint8_t *)loadinfo->datastart;
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf32_Shdr *shdr = &loadinfo->shdr[i];
/* SHF_ALLOC indicates that the section requires memory during
* execution */
if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
continue;
}
/* SHF_WRITE indicates that the section address space is write-
* able
*/
if ((shdr->sh_flags & SHF_WRITE) != 0)
{
pptr = &data;
}
else
{
pptr = &text;
}
/* SHT_NOBITS indicates that there is no data in the file for the
* section.
*/
if (shdr->sh_type != SHT_NOBITS)
{
/* Read the section data from sh_offset to the memory region */
ret = libmod_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset);
if (ret < 0)
{
bdbg("ERROR: Failed to read section %d: %d\n", i, ret);
return ret;
}
}
/* If there is no data in an allocated section, then the allocated
* section must be cleared.
*/
else
{
memset(*pptr, 0, shdr->sh_size);
}
/* Update sh_addr to point to copy in memory */
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 */
*pptr += ELF_ALIGNUP(shdr->sh_size);
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
int ret;
bvdbg("loadinfo: %p\n", loadinfo);
DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);
/* Load section headers into memory */
ret = libmod_loadshdrs(loadinfo);
if (ret < 0)
{
bdbg("ERROR: libmod_loadshdrs failed: %d\n", ret);
goto errout_with_buffers;
}
/* Determine total size to allocate */
libmod_elfsize(loadinfo);
/* Allocate (and zero) memory for the ELF file. */
/* Allocate memory to hold the ELF image */
loadinfo->textalloc = (uintptr_t)kmm_zalloc(loadinfo->textsize + loadinfo->datasize);
if (!loadinfo->textalloc)
{
bdbg("ERROR: Failed to allocate memory for the module\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
loadinfo->datastart = loadinfo->textalloc + loadinfo->textsize;
/* Load ELF section data into memory */
ret = libmod_loadfile(loadinfo);
if (ret < 0)
{
bdbg("ERROR: libmod_loadfile failed: %d\n", ret);
goto errout_with_buffers;
}
return OK;
/* Error exits */
errout_with_buffers:
libmod_unload(loadinfo);
return ret;
}

View File

@@ -1,165 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_read.c
*
* Copyright (C) 2014 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 <sys/types.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <elf32.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef ELF_DUMP_READDATA /* Define to dump all file data read */
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_dumpreaddata
****************************************************************************/
#if defined(ELF_DUMP_READDATA)
static inline void libmod_dumpreaddata(FAR char *buffer, int buflen)
{
FAR uint32_t *buf32 = (FAR uint32_t *)buffer;
int i;
int j;
for (i = 0; i < buflen; i += 32)
{
syslog(LOG_DEBUG, "%04x:", i);
for (j = 0; j < 32; j += sizeof(uint32_t))
{
syslog(LOG_DEBUG, " %08x", *buf32++);
}
syslog(LOG_DEBUG, "\n");
}
}
#else
# define libmod_dumpreaddata(b,n)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_read
*
* Description:
* Read 'readsize' bytes from the object file at 'offset'. The data is
* read into 'buffer.'
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_read(FAR struct libmod_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset)
{
ssize_t nbytes; /* Number of bytes read */
off_t rpos; /* Position returned by lseek */
bvdbg("Read %ld bytes from offset %ld\n", (long)readsize, (long)offset);
/* Loop until all of the requested data has been read. */
while (readsize > 0)
{
/* Seek to the next read position */
rpos = lseek(loadinfo->filfd, offset, SEEK_SET);
if (rpos != offset)
{
int errval = errno;
bdbg("Failed to seek to position %lu: %d\n",
(unsigned long)offset, errval);
return -errval;
}
/* Read the file data at offset into the user buffer */
nbytes = read(loadinfo->filfd, buffer, readsize);
if (nbytes < 0)
{
int errval = errno;
/* EINTR just means that we received a signal */
if (errval != EINTR)
{
bdbg("Read from offset %lu failed: %d\n",
(unsigned long)offset, errval);
return -errval;
}
}
else if (nbytes == 0)
{
bdbg("Unexpected end of file\n");
return -ENODATA;
}
else
{
readsize -= nbytes;
buffer += nbytes;
offset += nbytes;
}
}
libmod_dumpreaddata(buffer, readsize);
return OK;
}

View File

@@ -1,287 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_sections.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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_sectname
*
* Description:
* Get the symbol name in loadinfo->iobuffer[].
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static inline int libmod_sectname(FAR struct libmod_loadinfo_s *loadinfo,
FAR const Elf32_Shdr *shdr)
{
FAR Elf32_Shdr *shstr;
FAR uint8_t *buffer;
off_t offset;
size_t readlen;
size_t bytesread;
int shstrndx;
int ret;
/* Get the section header table index of the entry associated with the
* section name string table. If the file has no section name string table,
* this member holds the value SH_UNDEF.
*/
shstrndx = loadinfo->ehdr.e_shstrndx;
if (shstrndx == SHN_UNDEF)
{
bdbg("No section header string table\n");
return -EINVAL;
}
/* Get the section name string table section header */
shstr = &loadinfo->shdr[shstrndx];
/* Get the file offset to the string that is the name of the section. This
* is the sum of:
*
* shstr->sh_offset: The file offset to the first byte of the section
* header string table data.
* shdr->sh_name: The offset to the name of the section in the section
* name table
*/
offset = shstr->sh_offset + shdr->sh_name;
/* Loop until we get the entire section name into memory */
buffer = loadinfo->iobuffer;
bytesread = 0;
for (; ; )
{
/* Get the number of bytes to read */
readlen = loadinfo->buflen - bytesread;
if (offset + readlen > loadinfo->filelen)
{
if (loadinfo->filelen <= offset)
{
bdbg("At end of file\n");
return -EINVAL;
}
readlen = loadinfo->filelen - offset;
}
/* Read that number of bytes into the array */
buffer = &loadinfo->iobuffer[bytesread];
ret = libmod_read(loadinfo, buffer, readlen, offset);
if (ret < 0)
{
bdbg("Failed to read section name\n");
return ret;
}
bytesread += readlen;
/* Did we read the NUL terminator? */
if (memchr(buffer, '\0', readlen) != NULL)
{
/* Yes, the buffer contains a NUL terminator. */
return OK;
}
/* No.. then we have to read more */
ret = libmod_reallocbuffer(loadinfo, CONFIG_MODULE_BUFFERINCR);
if (ret < 0)
{
bdbg("libmod_reallocbuffer failed: %d\n", ret);
return ret;
}
}
/* We will not get here */
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_loadshdrs
*
* Description:
* Loads section headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_loadshdrs(FAR struct libmod_loadinfo_s *loadinfo)
{
size_t shdrsize;
int ret;
DEBUGASSERT(loadinfo->shdr == NULL);
/* Verify that there are sections */
if (loadinfo->ehdr.e_shnum < 1)
{
bdbg("No sections(?)\n");
return -EINVAL;
}
/* Get the total size of the section header table */
shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->ehdr.e_shnum;
if (loadinfo->ehdr.e_shoff + shdrsize > loadinfo->filelen)
{
bdbg("Insufficent space in file for section header table\n");
return -ESPIPE;
}
/* Allocate memory to hold a working copy of the sector header table */
loadinfo->shdr = (FAR FAR Elf32_Shdr *)kmm_malloc(shdrsize);
if (!loadinfo->shdr)
{
bdbg("Failed to allocate the section header table. Size: %ld\n",
(long)shdrsize);
return -ENOMEM;
}
/* Read the section header table into memory */
ret = libmod_read(loadinfo, (FAR uint8_t *)loadinfo->shdr, shdrsize,
loadinfo->ehdr.e_shoff);
if (ret < 0)
{
bdbg("Failed to read section header table: %d\n", ret);
}
return ret;
}
/****************************************************************************
* Name: libmod_findsection
*
* Description:
* A section by its name.
*
* Input Parameters:
* loadinfo - Load state information
* sectname - Name of the section to find
*
* Returned Value:
* On success, the index to the section is returned; A negated errno value
* is returned on failure.
*
****************************************************************************/
int libmod_findsection(FAR struct libmod_loadinfo_s *loadinfo,
FAR const char *sectname)
{
FAR const Elf32_Shdr *shdr;
int ret;
int i;
/* Search through the shdr[] array in loadinfo for a section named 'sectname' */
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
/* Get the name of this section */
shdr = &loadinfo->shdr[i];
ret = libmod_sectname(loadinfo, shdr);
if (ret < 0)
{
bdbg("libmod_sectname failed: %d\n", ret);
return ret;
}
/* Check if the name of this section is 'sectname' */
bvdbg("%d. Comparing \"%s\" and .\"%s\"\n",
i, loadinfo->iobuffer, sectname);
if (strcmp((FAR const char *)loadinfo->iobuffer, sectname) == 0)
{
/* We found it... return the index */
return i;
}
}
/* We failed to find a section with this name. */
return -ENOENT;
}

View File

@@ -1,346 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_symbols.c
*
* 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
* 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 <stdlib.h>
#include <string.h>
#include <elf32.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/binfmt/module.h>
#include <nuttx/binfmt/symtab.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_MODULE_BUFFERINCR
# define CONFIG_MODULE_BUFFERINCR 32
#endif
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_symname
*
* Description:
* Get the symbol name in loadinfo->iobuffer[].
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
* EINVAL - There is something inconsistent in the symbol table (should only
* happen if the file is corrupted).
* ESRCH - Symbol has no name
*
****************************************************************************/
static int libmod_symname(FAR struct libmod_loadinfo_s *loadinfo,
FAR const Elf32_Sym *sym)
{
FAR uint8_t *buffer;
off_t offset;
size_t readlen;
size_t bytesread;
int ret;
/* Get the file offset to the string that is the name of the symbol. The
* st_name member holds an offset into the file's symbol string table.
*/
if (sym->st_name == 0)
{
bdbg("Symbol has no name\n");
return -ESRCH;
}
offset = loadinfo->shdr[loadinfo->strtabidx].sh_offset + sym->st_name;
/* Loop until we get the entire symbol name into memory */
bytesread = 0;
for (; ; )
{
/* Get the number of bytes to read */
readlen = loadinfo->buflen - bytesread;
if (offset + readlen > loadinfo->filelen)
{
if (loadinfo->filelen <= offset)
{
bdbg("At end of file\n");
return -EINVAL;
}
readlen = loadinfo->filelen - offset;
}
/* Read that number of bytes into the array */
buffer = &loadinfo->iobuffer[bytesread];
ret = libmod_read(loadinfo, buffer, readlen, offset);
if (ret < 0)
{
bdbg("libmod_read failed: %d\n", ret);
return ret;
}
bytesread += readlen;
/* Did we read the NUL terminator? */
if (memchr(buffer, '\0', readlen) != NULL)
{
/* Yes, the buffer contains a NUL terminator. */
return OK;
}
/* No.. then we have to read more */
ret = libmod_reallocbuffer(loadinfo, CONFIG_MODULE_BUFFERINCR);
if (ret < 0)
{
bdbg("libmod_reallocbuffer failed: %d\n", ret);
return ret;
}
}
/* We will not get here */
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_findsymtab
*
* Description:
* Find the symbol table section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_findsymtab(FAR struct libmod_loadinfo_s *loadinfo)
{
int i;
/* Find the symbol table section header and its associated string table */
for (i = 1; i < loadinfo->ehdr.e_shnum; i++)
{
if (loadinfo->shdr[i].sh_type == SHT_SYMTAB)
{
loadinfo->symtabidx = i;
loadinfo->strtabidx = loadinfo->shdr[i].sh_link;
break;
}
}
/* Verify that there is a symbol and string table */
if (loadinfo->symtabidx == 0)
{
bdbg("No symbols in ELF file\n");
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Name: libmod_readsym
*
* Description:
* Read the ELFT symbol structure at the specfied index into memory.
*
* Input Parameters:
* loadinfo - Load state information
* index - Symbol table index
* sym - Location to return the table entry
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_readsym(FAR struct libmod_loadinfo_s *loadinfo, int index,
FAR Elf32_Sym *sym)
{
FAR Elf32_Shdr *symtab = &loadinfo->shdr[loadinfo->symtabidx];
off_t offset;
/* Verify that the symbol table index lies within symbol table */
if (index < 0 || index > (symtab->sh_size / sizeof(Elf32_Sym)))
{
bdbg("Bad relocation symbol index: %d\n", index);
return -EINVAL;
}
/* Get the file offset to the symbol table entry */
offset = symtab->sh_offset + sizeof(Elf32_Sym) * index;
/* And, finally, read the symbol table entry into memory */
return libmod_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset);
}
/****************************************************************************
* Name: libmod_symvalue
*
* Description:
* Get the value of a symbol. The updated value of the symbol is returned
* in the st_value field of the symbol table entry.
*
* Input Parameters:
* loadinfo - Load state information
* sym - Symbol table entry (value might be undefined)
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
* EINVAL - There is something inconsistent in the symbol table (should only
* happen if the file is corrupted).
* ENOSYS - Symbol lies in common
* ESRCH - Symbol has no name
* ENOENT - Symbol undefined and not provided via a symbol table
*
****************************************************************************/
int libmod_symvalue(FAR struct libmod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
FAR const struct symtab_s *exports, int nexports)
{
FAR const struct symtab_s *symbol;
uintptr_t secbase;
int ret;
switch (sym->st_shndx)
{
case SHN_COMMON:
{
/* NuttX ELF modules should be compiled with -fno-common. */
bdbg("SHN_COMMON: Re-compile with -fno-common\n");
return -ENOSYS;
}
case SHN_ABS:
{
/* st_value already holds the correct value */
bvdbg("SHN_ABS: st_value=%08lx\n", (long)sym->st_value);
return OK;
}
case SHN_UNDEF:
{
/* Get the name of the undefined symbol */
ret = libmod_symname(loadinfo, sym);
if (ret < 0)
{
/* There are a few relocations for a few architectures that do
* no depend upon a named symbol. We don't know if that is the
* case here, but return and special error to the caller to
* indicate the nameless symbol.
*/
bdbg("SHN_UNDEF: Failed to get symbol name: %d\n", ret);
return ret;
}
/* Check if the base code exports a symbol of this name */
#ifdef CONFIG_SYMTAB_ORDEREDBYNAME
symbol = symtab_findorderedbyname(exports, (FAR char *)loadinfo->iobuffer, nexports);
#else
symbol = symtab_findbyname(exports, (FAR char *)loadinfo->iobuffer, nexports);
#endif
if (!symbol)
{
bdbg("SHN_UNDEF: Exported symbol \"%s\" not found\n", loadinfo->iobuffer);
return -ENOENT;
}
/* Yes... add the exported symbol value to the ELF symbol table entry */
bvdbg("SHN_ABS: name=%s %08x+%08x=%08x\n",
loadinfo->iobuffer, sym->st_value, symbol->sym_value,
sym->st_value + symbol->sym_value);
sym->st_value += (Elf32_Word)((uintptr_t)symbol->sym_value);
}
break;
default:
{
secbase = loadinfo->shdr[sym->st_shndx].sh_addr;
bvdbg("Other: %08x+%08x=%08x\n",
sym->st_value, secbase, sym->st_value + secbase);
sym->st_value += secbase;
}
break;
}
return OK;
}

View File

@@ -1,126 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_uninit.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 <unistd.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_uninitialize
*
* Description:
* Releases any resources committed by libmod_initialize(). 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(struct libmod_loadinfo_s *loadinfo)
{
/* Free all working buffers */
libmod_freebuffers(loadinfo);
/* Close the ELF file */
if (loadinfo->filfd >= 0)
{
close(loadinfo->filfd);
}
return OK;
}
/****************************************************************************
* Name: libmod_freebuffers
*
* Description:
* Release all working buffers.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int libmod_freebuffers(struct libmod_loadinfo_s *loadinfo)
{
/* Release all working allocations */
if (loadinfo->shdr)
{
kmm_free((FAR void *)loadinfo->shdr);
loadinfo->shdr = NULL;
}
if (loadinfo->iobuffer)
{
kmm_free((FAR void *)loadinfo->iobuffer);
loadinfo->iobuffer = NULL;
loadinfo->buflen = 0;
}
return OK;
}

View File

@@ -1,102 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_unload.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 <stdlib.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_unload
*
* Description:
* This function unloads the object from memory. This essentially undoes
* the actions of libmod_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)
{
/* Free all working buffers */
libmod_freebuffers(loadinfo);
/* Release memory holding the relocated ELF image */
if (loadinfo->textalloc != 0)
{
kmm_free((FAR void *)loadinfo->textalloc);
}
/* Clear out all indications of the allocated address environment */
loadinfo->textalloc = 0;
loadinfo->datastart = 0;
loadinfo->textsize = 0;
loadinfo->datasize = 0;
return OK;
}

View File

@@ -1,123 +0,0 @@
/****************************************************************************
* binfmt/libmodule/libmodule_verify.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 <debug.h>
#include <errno.h>
#include <nuttx/binfmt/module.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
static const char g_modmagic[EI_MAGIC_SIZE] =
{
0x7f, 'E', 'L', 'F'
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libmod_verifyheader
*
* Description:
* Given the header from a possible ELF executable, verify that it
* is an ELF executable.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
* -ENOEXEC : Not an ELF file
* -EINVAL : Not a relocatable ELF file or not supported by the current,
* configured architecture.
*
****************************************************************************/
int libmod_verifyheader(FAR const Elf32_Ehdr *ehdr)
{
if (!ehdr)
{
bdbg("NULL ELF header!");
return -ENOEXEC;
}
/* Verify that the magic number indicates an ELF file */
if (memcmp(ehdr->e_ident, g_modmagic, EI_MAGIC_SIZE) != 0)
{
bvdbg("Not ELF magic {%02x, %02x, %02x, %02x}\n",
ehdr->e_ident[0], ehdr->e_ident[1], ehdr->e_ident[2], ehdr->e_ident[3]);
return -ENOEXEC;
}
/* Verify that this is a relocatable file */
if (ehdr->e_type != ET_REL)
{
bdbg("Not a relocatable file: e_type=%d\n", ehdr->e_type);
return -EINVAL;
}
/* Verify that this file works with the currently configured architecture */
if (up_checkarch(ehdr))
{
bdbg("Not a supported architecture\n");
return -ENOEXEC;
}
/* Looks good so far... we still might find some problems later. */
return OK;
}