mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
binfmt/libmodule: Add support for kernel modules. Initial commit is just the ELF module support with name changes
This commit is contained in:
parent
f9f19d867b
commit
8bcf35ff39
19 changed files with 3849 additions and 0 deletions
|
@ -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
52
binfmt/libmodule/Kconfig
Normal 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.
|
59
binfmt/libmodule/Make.defs
Normal file
59
binfmt/libmodule/Make.defs
Normal 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
129
binfmt/libmodule/gnu-elf.ld
Normal 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) }
|
||||
}
|
266
binfmt/libmodule/libmodule.h
Normal file
266
binfmt/libmodule/libmodule.h
Normal 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 */
|
332
binfmt/libmodule/libmodule_bind.c
Normal file
332
binfmt/libmodule/libmodule_bind.c
Normal 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;
|
||||
}
|
216
binfmt/libmodule/libmodule_ctors.c
Normal file
216
binfmt/libmodule/libmodule_ctors.c
Normal 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 */
|
216
binfmt/libmodule/libmodule_dtors.c
Normal file
216
binfmt/libmodule/libmodule_dtors.c
Normal 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 */
|
202
binfmt/libmodule/libmodule_init.c
Normal file
202
binfmt/libmodule/libmodule_init.c
Normal 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;
|
||||
}
|
||||
|
136
binfmt/libmodule/libmodule_iobuffer.c
Normal file
136
binfmt/libmodule/libmodule_iobuffer.c
Normal 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;
|
||||
}
|
||||
|
333
binfmt/libmodule/libmodule_load.c
Normal file
333
binfmt/libmodule/libmodule_load.c
Normal 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;
|
||||
}
|
||||
|
163
binfmt/libmodule/libmodule_read.c
Normal file
163
binfmt/libmodule/libmodule_read.c
Normal 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;
|
||||
}
|
287
binfmt/libmodule/libmodule_sections.c
Normal file
287
binfmt/libmodule/libmodule_sections.c
Normal 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;
|
||||
}
|
346
binfmt/libmodule/libmodule_symbols.c
Normal file
346
binfmt/libmodule/libmodule_symbols.c
Normal 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;
|
||||
}
|
126
binfmt/libmodule/libmodule_uninit.c
Normal file
126
binfmt/libmodule/libmodule_uninit.c
Normal 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;
|
||||
}
|
124
binfmt/libmodule/libmodule_unload.c
Normal file
124
binfmt/libmodule/libmodule_unload.c
Normal 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;
|
||||
}
|
||||
|
123
binfmt/libmodule/libmodule_verify.c
Normal file
123
binfmt/libmodule/libmodule_verify.c
Normal 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
368
binfmt/module.c
Normal 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 */
|
369
include/nuttx/binfmt/module.h
Normal file
369
include/nuttx/binfmt/module.h
Normal 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 */
|
Loading…
Reference in a new issue