binfmt/libmodule: Add support for kernel modules. Initial commit is just the ELF module support with name changes

This commit is contained in:
Gregory Nutt 2015-12-10 09:53:31 -06:00
parent f9f19d867b
commit 8bcf35ff39
19 changed files with 3849 additions and 0 deletions

View file

@ -11233,4 +11233,6 @@
that of the type of a pthread. Hence, it could be confused as a
task. Same problem as fixed on 2015-11-29, but in different location
(2015-12-09).
* binfmt/libmodule: Add support for kernel modules. Initial commit is
just the ELF module support with name changes (2015-12-10).

52
binfmt/libmodule/Kconfig Normal file
View file

@ -0,0 +1,52 @@
#
# 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_STACKSIZE
int "Module Stack Size"
default 2048
---help---
This is the default stack size that will be used when starting
module initialization tasks.
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
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

@ -0,0 +1,59 @@
############################################################################
# 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_ELF),y)
# ELF application interfaces
BINFMT_CSRCS += module.c
# ELF 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
SUBDIRS += libmodule
DEPPATH += --dep-path libmodule
endif

129
binfmt/libmodule/gnu-elf.ld Normal file
View file

@ -0,0 +1,129 @@
/****************************************************************************
* binfmt/libmodule/gnu-elf.ld
*
* 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.
*
****************************************************************************/
SECTIONS
{
.text 0x00000000 :
{
_stext = . ;
*(.text)
*(.text.*)
*(.gnu.warning)
*(.stub)
*(.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 = . ;
}
.rodata :
{
_srodata = . ;
*(.rodata)
*(.rodata1)
*(.rodata.*)
*(.gnu.linkonce.r*)
_erodata = . ;
}
.data :
{
_sdata = . ;
*(.data)
*(.data1)
*(.data.*)
*(.gnu.linkonce.d*)
_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 = . ;
*(.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

@ -0,0 +1,266 @@
/****************************************************************************
* binfmt/libmodule/libmodule.h
*
* 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.
*
****************************************************************************/
#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>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Name: mod_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 mod_verifyheader(FAR const Elf32_Ehdr *header);
/****************************************************************************
* Name: mod_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 mod_read(FAR struct mod_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset);
/****************************************************************************
* Name: mod_loadshdrs
*
* Description:
* Loads section headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_loadshdrs(FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_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 mod_findsection(FAR struct mod_loadinfo_s *loadinfo,
FAR const char *sectname);
/****************************************************************************
* Name: mod_findsymtab
*
* Description:
* Find the symbol table section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_findsymtab(FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_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 mod_readsym(FAR struct mod_loadinfo_s *loadinfo, int index,
FAR Elf32_Sym *sym);
/****************************************************************************
* Name: mod_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 mod_symvalue(FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym,
FAR const struct symtab_s *exports, int nexports);
/****************************************************************************
* Name: mod_freebuffers
*
* Description:
* Release all working buffers.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_freebuffers(FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_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 mod_allocbuffer(FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_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 mod_reallocbuffer(FAR struct mod_loadinfo_s *loadinfo, size_t increment);
/****************************************************************************
* Name: mod_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 mod_loadctors(FAR struct mod_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Name: mod_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 mod_loaddtors(FAR struct mod_loadinfo_s *loadinfo);
#endif
#endif /* __BINFMT_LIBELF_LIBELF_H */

View file

@ -0,0 +1,332 @@
/****************************************************************************
* 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_ELF_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
#endif
#ifndef CONFIG_ELF_BUFFERSIZE
# define CONFIG_ELF_BUFFERSIZE 128
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
# define mod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define mod_dumpbuffer(m,b,n)
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mod_readrel
*
* Description:
* Read the ELF32_Rel structure into memory.
*
****************************************************************************/
static inline int mod_readrel(FAR struct mod_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 mod_read(loadinfo, (FAR uint8_t *)rel, sizeof(Elf32_Rel), offset);
}
/****************************************************************************
* Name: mod_relocate and mod_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 mod_relocate(FAR struct mod_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 = mod_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 = mod_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 = mod_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 mod_relocateadd(FAR struct mod_loadinfo_s *loadinfo, int relidx,
FAR const struct symtab_s *exports, int nexports)
{
bdbg("Not implemented\n");
return -ENOSYS;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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.
*
****************************************************************************/
int mod_bind(FAR struct mod_loadinfo_s *loadinfo,
FAR const struct symtab_s *exports, int nexports)
{
int ret;
int i;
/* Find the symbol and string tables */
ret = mod_findsymtab(loadinfo);
if (ret < 0)
{
return ret;
}
/* Allocate an I/O buffer. This buffer is used by mod_symname() to
* accumulate the variable length symbol name.
*/
ret = mod_allocbuffer(loadinfo);
if (ret < 0)
{
bdbg("mod_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 = mod_relocate(loadinfo, i, exports, nexports);
}
else if (loadinfo->shdr[i].sh_type == SHT_RELA)
{
ret = mod_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

@ -0,0 +1,216 @@
/****************************************************************************
* 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: mod_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 mod_loadctors(FAR struct mod_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
* mod_sectname() to accumulate the variable length symbol name.
*/
ret = mod_allocbuffer(loadinfo);
if (ret < 0)
{
bdbg("mod_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 = mod_findsection(loadinfo, ".ctors");
if (ctoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static constructor section.
*/
bvdbg("mod_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 = mod_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

@ -0,0 +1,216 @@
/****************************************************************************
* 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: mod_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 mod_loaddtors(FAR struct mod_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
* mod_sectname() to accumulate the variable length symbol name.
*/
ret = mod_allocbuffer(loadinfo);
if (ret < 0)
{
bdbg("mod_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 = mod_findsection(loadinfo, ".dtors");
if (dtoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static destructor section.
*/
bvdbg("mod_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 = mod_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

@ -0,0 +1,202 @@
/****************************************************************************
* 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_ELF_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_VERBOSE) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
# define mod_dumpbuffer(m,b,n) bvdbgdumpbuffer(m,b,n)
#else
# define mod_dumpbuffer(m,b,n)
#endif
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mod_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 mod_filelen(FAR struct mod_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: mod_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 mod_initialize(FAR const char *filename, FAR struct mod_loadinfo_s *loadinfo)
{
int ret;
bvdbg("filename: %s loadinfo: %p\n", filename, loadinfo);
/* Clear the load info structure */
memset(loadinfo, 0, sizeof(struct mod_loadinfo_s));
/* Get the length of the file. */
ret = mod_filelen(loadinfo, filename);
if (ret < 0)
{
bdbg("mod_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 = mod_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;
}
mod_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr, sizeof(Elf32_Ehdr));
/* Verify the ELF header */
ret = mod_verifyheader(&loadinfo->ehdr);
if (ret < 0)
{
/* This may not be an error because we will be called to attempt loading
* EVERY binary. If mod_verifyheader() does not recognize the ELF header,
* it will -ENOEXEC whcih simply informs the system that the file is not an
* ELF file. mod_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

@ -0,0 +1,136 @@
/****************************************************************************
* binfmt/libmodule/mod_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: mod_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 mod_allocbuffer(FAR struct mod_loadinfo_s *loadinfo)
{
/* Has a buffer been allocated> */
if (!loadinfo->iobuffer)
{
/* No.. allocate one now */
loadinfo->iobuffer = (FAR uint8_t *)kmm_malloc(CONFIG_ELF_BUFFERSIZE);
if (!loadinfo->iobuffer)
{
bdbg("Failed to allocate an I/O buffer\n");
return -ENOMEM;
}
loadinfo->buflen = CONFIG_ELF_BUFFERSIZE;
}
return OK;
}
/****************************************************************************
* Name: mod_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 mod_reallocbuffer(FAR struct mod_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

@ -0,0 +1,333 @@
/****************************************************************************
* 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/binfmt/module.h>
#include "libmodule.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ELF_ALIGN_MASK ((1 << CONFIG_ELF_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: mod_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 mod_elfsize(struct mod_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: mod_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 mod_loadfile(FAR struct mod_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->dataalloc;
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 = mod_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: 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)
{
size_t heapsize;
#ifdef CONFIG_UCLIBCXX_EXCEPTION
int exidx;
#endif
int ret;
bvdbg("loadinfo: %p\n", loadinfo);
DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);
/* Load section headers into memory */
ret = mod_loadshdrs(loadinfo);
if (ret < 0)
{
bdbg("ERROR: mod_loadshdrs failed: %d\n", ret);
goto errout_with_buffers;
}
/* Determine total size to allocate */
mod_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);
if (!loadinfo->textalloc)
{
bdbg("ERROR: Failed to allocate memory for the module\n");
ret = -ENOMEM;
goto errout_with_buffers;
}
loadinfo->dataalloc = loadinfo->textalloc + textsize;
/* Load ELF section data into memory */
ret = mod_loadfile(loadinfo);
if (ret < 0)
{
bdbg("ERROR: mod_loadfile failed: %d\n", ret);
goto errout_with_buffers;
}
/* Load static constructors and destructors. */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
ret = mod_loadctors(loadinfo);
if (ret < 0)
{
bdbg("ERROR: mod_loadctors failed: %d\n", ret);
goto errout_with_buffers;
}
ret = mod_loaddtors(loadinfo);
if (ret < 0)
{
bdbg("ERROR: mod_loaddtors failed: %d\n", ret);
goto errout_with_buffers;
}
#endif
#ifdef CONFIG_UCLIBCXX_EXCEPTION
exidx = mod_findsection(loadinfo, CONFIG_ELF_EXIDX_SECTNAME);
if (exidx < 0)
{
bvdbg("mod_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 */
errout_with_buffers:
mod_unload(loadinfo);
return ret;
}

View file

@ -0,0 +1,163 @@
/****************************************************************************
* 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>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef ELF_DUMP_READDATA /* Define to dump all file data read */
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mod_dumpreaddata
****************************************************************************/
#if defined(ELF_DUMP_READDATA)
static inline void mod_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 mod_dumpreaddata(b,n)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mod_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 mod_read(FAR struct mod_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;
}
}
mod_dumpreaddata(buffer, readsize);
return OK;
}

View file

@ -0,0 +1,287 @@
/****************************************************************************
* 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: mod_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 mod_sectname(FAR struct mod_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 = mod_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 = mod_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
if (ret < 0)
{
bdbg("mod_reallocbuffer failed: %d\n", ret);
return ret;
}
}
/* We will not get here */
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mod_loadshdrs
*
* Description:
* Loads section headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_loadshdrs(FAR struct mod_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 = mod_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: mod_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 mod_findsection(FAR struct mod_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 = mod_sectname(loadinfo, shdr);
if (ret < 0)
{
bdbg("mod_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

@ -0,0 +1,346 @@
/****************************************************************************
* 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_ELF_BUFFERINCR
# define CONFIG_ELF_BUFFERINCR 32
#endif
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mod_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 mod_symname(FAR struct mod_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 = mod_read(loadinfo, buffer, readlen, offset);
if (ret < 0)
{
bdbg("mod_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 = mod_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
if (ret < 0)
{
bdbg("mod_reallocbuffer failed: %d\n", ret);
return ret;
}
}
/* We will not get here */
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mod_findsymtab
*
* Description:
* Find the symbol table section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_findsymtab(FAR struct mod_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: mod_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 mod_readsym(FAR struct mod_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 mod_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset);
}
/****************************************************************************
* Name: mod_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 mod_symvalue(FAR struct mod_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 = mod_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

@ -0,0 +1,126 @@
/****************************************************************************
* 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: mod_uninit
*
* Description:
* Releases any resources committed by mod_initialize(). This essentially
* undoes the actions of mod_initialize.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_uninit(struct mod_loadinfo_s *loadinfo)
{
/* Free all working buffers */
mod_freebuffers(loadinfo);
/* Close the ELF file */
if (loadinfo->filfd >= 0)
{
close(loadinfo->filfd);
}
return OK;
}
/****************************************************************************
* Name: mod_freebuffers
*
* Description:
* Release all working buffers.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int mod_freebuffers(struct mod_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

@ -0,0 +1,124 @@
/****************************************************************************
* 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: 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)
{
/* Free all working buffers */
mod_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->dataalloc = 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

@ -0,0 +1,123 @@
/****************************************************************************
* binfmt/libmodule/mod_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: mod_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 mod_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;
}

368
binfmt/module.c Normal file
View file

@ -0,0 +1,368 @@
/****************************************************************************
* 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/binfmt.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
#ifndef CONFIG_MODULE_STACKSIZE
# define CONFIG_MODULE_STACKSIZE 2048
#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 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
****************************************************************************/
/****************************************************************************
* Name: mod_dumploadinfo
****************************************************************************/
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT)
static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
{
int i;
bdbg("LOAD_INFO:\n");
bdbg(" textalloc: %08lx\n", (long)loadinfo->textalloc);
bdbg(" dataalloc: %08lx\n", (long)loadinfo->dataalloc);
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);
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_dumpentrypt
****************************************************************************/
#ifdef CONFIG_MODULE_DUMPBUFFER
static void mod_dumpentrypt(FAR struct binary_s *binp,
FAR struct mod_loadinfo_s *loadinfo)
{
#ifdef CONFIG_ARCH_ADDRENV
int ret;
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. mod_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = mod_addrenv_select(loadinfo);
if (ret < 0)
{
bdbg("ERROR: mod_addrenv_select() failed: %d\n", ret);
return;
}
#endif
mod_dumpbuffer("Entry code", (FAR const uint8_t *)binp->entrypt,
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the original address environment */
ret = mod_addrenv_restore(loadinfo);
if (ret < 0)
{
bdbg("ERROR: mod_addrenv_restore() failed: %d\n", ret);
}
#endif
}
#else
# define mod_dumpentrypt(b,l)
#endif
/****************************************************************************
* Name: mod_loadbinary
*
* Description:
* Verify that the file is an ELF binary and, if so, load the ELF
* binary into memory
*
****************************************************************************/
static int mod_loadbinary(FAR struct binary_s *binp)
{
struct mod_loadinfo_s loadinfo; /* Contains globals for libmodule */
int ret;
bvdbg("Loading file: %s\n", binp->filename);
/* Initialize the ELF library to load the program binary. */
ret = mod_init(binp->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 = mod_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 = mod_bind(&loadinfo, binp->exports, binp->nexports);
if (ret != 0)
{
bdbg("Failed to bind symbols program binary: %d\n", ret);
goto errout_with_load;
}
/* Return the load information */
binp->entrypt = (main_t)(loadinfo.textalloc + loadinfo.ehdr.e_entry);
binp->stacksize = CONFIG_MODULE_STACKSIZE;
/* 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?
*/
#ifdef CONFIG_ARCH_ADDRENV
# warning "REVISIT"
#else
binp->alloc[0] = (FAR void *)loadinfo.textalloc;
#endif
#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
#ifdef CONFIG_ARCH_ADDRENV
/* Save the address environment in the binfmt structure. This will be
* needed when the module is executed.
*/
up_addrenv_clone(&loadinfo.addrenv, &binp->addrenv);
#endif
mod_dumpentrypt(binp, &loadinfo);
mod_uninit(&loadinfo);
return OK;
errout_with_load:
mod_unload(&loadinfo);
errout_with_init:
mod_uninit(&loadinfo);
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

@ -0,0 +1,369 @@
/****************************************************************************
* include/nuttx/binfmt/module.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 __INCLUDE_NUTTX_BINFMT_MODULE_H
#define __INCLUDE_NUTTX_BINFMT_MODULE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <elf32.h>
#include <nuttx/binfmt/binfmt.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
#ifndef CONFIG_MODULE_ALIGN_LOG2
# define CONFIG_MODULE_ALIGN_LOG2 2
#endif
#ifndef CONFIG_MODULE_STACKSIZE
# define CONFIG_MODULE_STACKSIZE 2048
#endif
#ifndef CONFIG_MODULE_BUFFERSIZE
# define CONFIG_MODULE_BUFFERSIZE 128
#endif
#ifndef CONFIG_MODULE_BUFFERINCR
# define CONFIG_MODULE_BUFFERINCR 32
#endif
/* Allocation array size and indices */
#define LIBMODULE_MODULE_ALLOC 0
#ifdef CONFIG_BINFMT_CONSTRUCTORS
# define LIBMODULE_CTORS_ALLOC 1
# define LIBMODULE_CTPRS_ALLOC 2
# define LIBMODULE_NALLOC 3
#else
# define LIBMODULE_NALLOC 1
#endif
/****************************************************************************
* 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.
*
* If CONFIG_ARCH_ADDRENV=n, elfalloc will be allocated using kmm_malloc() (or
* kmm_zalloc()). If CONFIG_ARCH_ADDRENV-y, then elfalloc will be allocated using
* up_addrenv_create(). In either case, there will be a unique instance
* of elfalloc (and stack) for each instance of a process.
*
* 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
/* Address environment.
*
* addrenv - This is the handle created by up_addrenv_create() that can be
* used to manage the tasks address space.
* oldenv - This is a value returned by up_addrenv_select() that must be
* used to restore the current address environment.
*/
#ifdef CONFIG_ARCH_ADDRENV
group_addrenv_t addrenv; /* Task group address environment */
save_addrenv_t oldenv; /* Saved address environment */
#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 */
};
/****************************************************************************
* Public Functions
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* These are APIs exported by libelf (but are used only by the binfmt logic):
****************************************************************************/
/****************************************************************************
* Name: mod_init
*
* 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 mod_init(FAR const char *filename, FAR struct mod_loadinfo_s *loadinfo);
/****************************************************************************
* Name: mod_uninit
*
* 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 mod_uninit(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);
/****************************************************************************
* These are APIs must be provided by architecture-specific logic.
* (These really belong in include/nuttx/arch.h):
****************************************************************************/
/****************************************************************************
* Name: up_checkarch
*
* Description:
* Given the ELF header in 'hdr', verify that the module is appropriate
* for the current, configured architecture. Every architecture that uses
* the module loader must provide this function.
*
* Input Parameters:
* hdr - The ELF header read from the module file.
*
* Returned Value:
* True if the architecture supports this module file.
*
****************************************************************************/
bool up_checkarch(FAR const Elf32_Ehdr *hdr);
/****************************************************************************
* Name: up_relocate and up_relocateadd
*
* Description:
* Perform on architecture-specific ELF relocation. Every architecture
* that uses the module loader must provide this function.
*
* Input Parameters:
* rel - The relocation type
* sym - The ELF symbol structure containing the fully resolved value.
* There are a few relocation types for a few architectures that do
* not require symbol information. For those, this value will be
* NULL. Implementations of these functions must be able to handle
* that case.
* addr - The address that requires the relocation.
*
* Returned Value:
* Zero (OK) if the relocation was successful. Otherwise, a negated errno
* value indicating the cause of the relocation failure.
*
****************************************************************************/
int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
uintptr_t addr);
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
*
* Description:
* Ensure that the I and D caches are coherent within specified region
* by cleaning the D cache (i.e., flushing the D cache contents to memory
* and invalidating the I cache. This is typically used when code has been
* written to a memory region, and will be executed.
*
* Input Parameters:
* addr - virtual start address of region
* len - Size of the address region in bytes
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_ARCH_HAVE_COHERENT_DCACHE
void up_coherent_dcache(uintptr_t addr, size_t len);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_NUTTX_BINFMT_MODULE_H */