1
0
Fork 0
forked from nuttx/nuttx-update

binfmt/libelf:Remove libelf implementation [2/2]

this commit is part two, all logic move to modlib, so we can remove it.
and change all use defconfig

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2024-07-10 12:08:27 +08:00 committed by Xiang Xiao
parent 1fc2cd7816
commit e5f9b42ea0
45 changed files with 96 additions and 4148 deletions

View file

@ -510,7 +510,7 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)
# Zig toolchain # Zig toolchain

View file

@ -211,4 +211,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -179,4 +179,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -109,4 +109,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -98,4 +98,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -103,4 +103,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -324,4 +324,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -140,4 +140,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -88,4 +88,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -126,4 +126,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -417,7 +417,7 @@ else
LDELFFLAGS += --oformat elf64-littleriscv LDELFFLAGS += --oformat elf64-littleriscv
endif endif
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)
# Zig toolchain # Zig toolchain

View file

@ -135,4 +135,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -0,0 +1,71 @@
############################################################################
# arch/x86/src/common/Toolchain.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
ARCHOPTIMIZATION = -g3
endif
ifneq ($(CONFIG_DEBUG_NOOPT),y)
ARCHOPTIMIZATION += -O2
endif
ARCHCPUFLAGS = -march=i486 -mtune=i486 -fno-stack-protector
ARCHPICFLAGS = -fpic
ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
# Check if building a 32-bit target with a 64-bit toolchain
ifeq ($(CONFIG_ARCH_X86_M32),y)
ARCHCPUFLAGS += -m32
LDFLAGS += -m elf_i386
endif
# We have to use a cross-development toolchain under Cygwin because the native
# Cygwin toolchains don't generate ELF binaries.
ifeq ($(CONFIG_WINDOWS_CYGWIN),y)
CROSSDEV = i486-nuttx-elf-
endif
CC = $(CROSSDEV)gcc
CPP = $(CROSSDEV)gcc -E -x c
LD = $(CROSSDEV)ld
STRIP = $(CROSSDEV)strip --strip-unneeded
AR = $(CROSSDEV)ar rcs
NM = $(CROSSDEV)nm
OBJCOPY = $(CROSSDEV)objcopy
OBJDUMP = $(CROSSDEV)objdump
CFLAGS := $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS)
AFLAGS := $(CFLAGS) -D__ASSEMBLY__
# Loadable module definitions
CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden
LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)
# ELF module definitions
CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -195,7 +195,7 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main --gc-sections LDELFFLAGS = -r -e main --gc-sections
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)
# -fno-pic to avoid GOT relocations # -fno-pic to avoid GOT relocations
# -mcmodel=large to avoid out-of-range 32-bit relocations # -mcmodel=large to avoid out-of-range 32-bit relocations

View file

@ -206,4 +206,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden -mtext-section-literals
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden -mtext-section-literals CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden -mtext-section-literals
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -210,4 +210,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden -mtext-section-literals
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden -mtext-section-literals CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden -mtext-section-literals
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -117,4 +117,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -221,4 +221,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -119,4 +119,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -144,4 +144,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -119,4 +119,4 @@ CELFFLAGS = $(CFLAGS) -fvisibility=hidden
CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)binfmt$(DELIM)libelf$(DELIM)gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)modlib$(DELIM)gnu-elf.ld)

View file

@ -33,9 +33,6 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/binfmt/binfmt.h> #include <nuttx/binfmt/binfmt.h>
#include <nuttx/binfmt/elf.h>
#include "libelf/libelf.h"
#ifdef CONFIG_ELF #ifdef CONFIG_ELF

View file

@ -1,48 +0,0 @@
# ##############################################################################
# binfmt/libelf/CMakeLists.txt
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
# license agreements. See the NOTICE file distributed with this work for
# additional information regarding copyright ownership. The ASF licenses this
# file to you under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
#
# ##############################################################################
if(CONFIG_ELF)
set(SRCS)
# ELF library
list(
APPEND
SRCS
libelf_bind.c
libelf_init.c
libelf_addrenv.c
libelf_iobuffer.c
libelf_load.c
libelf_read.c
libelf_sections.c
libelf_symbols.c
libelf_uninit.c
libelf_unload.c
libelf_verify.c)
if(CONFIG_BINFMT_CONSTRUCTORS)
list(APPEND SRCS libelf_ctors.c libelf_dtors.c)
endif()
target_sources(binfmt PRIVATE ${SRCS})
endif()

View file

@ -1,72 +0,0 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config ELF_ALIGN_LOG2
int "Log2 Section Alignment"
default 2
---help---
Align all sections to this Log2 value: 0->1, 1->2, 2->4, etc.
config ELF_STACKSIZE
int "ELF Stack Size"
default DEFAULT_TASK_STACKSIZE
---help---
This is the default stack size that will be used when starting ELF binaries.
config ELF_BUFFERSIZE
int "ELF I/O Buffer Size"
default 32
---help---
This is an I/O buffer that is used to access the ELF 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: 32
config ELF_BUFFERINCR
int "ELF I/O Buffer Realloc Increment"
default 32
---help---
This is an I/O buffer that is used to access the ELF 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 ELF_DUMPBUFFER
bool "Dump ELF buffers"
default n
depends on DEBUG_INFO
---help---
Dump various ELF buffers for debug purposes
config ELF_EXIDX_SECTNAME
string "ELF Section Name for Exception Index"
default ".ARM.exidx"
depends on CXX_EXCEPTION && ARCH_ARM
---help---
Set the name string for the exception index section on the ELF modules to
be loaded by the ELF binary loader.
This is needed to support exception handling on loadable ELF modules.
config ELF_RELOCATION_BUFFERCOUNT
int "ELF Relocation Table Buffer Count"
default 256
---help---
This is a relocation buffer that is used to store elf relocation table to
reduce access fs. Default: 256
config ELF_SYMBOL_CACHECOUNT
int "ELF SYMBOL Table Cache Count"
default 256
---help---
This is a cache that is used to store elf symbol table to
reduce access fs. Default: 256
config ELF_LOADTO_LMA
bool "ELF load sections to LMA"
default n
---help---
Load all section to LMA not VMA, so the startup code(e.g. start.S) need
relocate .data section to the final address(VMA) and zero .bss section
by self.

View file

@ -1,41 +0,0 @@
############################################################################
# binfmt/libelf/Make.defs
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifeq ($(CONFIG_ELF),y)
# ELF library
CSRCS += libelf_bind.c libelf_init.c libelf_addrenv.c libelf_iobuffer.c
CSRCS += libelf_load.c libelf_read.c libelf_sections.c libelf_symbols.c
CSRCS += libelf_uninit.c libelf_unload.c libelf_verify.c
ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
CSRCS += libelf_ctors.c libelf_dtors.c
endif
# Hook the libelf subdirectory into the build
VPATH += libelf
SUBDIRS += libelf
DEPPATH += --dep-path libelf
endif

View file

@ -1,118 +0,0 @@
/****************************************************************************
* binfmt/libelf/gnu-elf.ld
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
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*)
. = ALIGN(4);
_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 = . ;
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors))
_ectors = . ;
}
.dtors :
{
_sdtors = . ;
*(.dtors) /* Old ABI: Unallocated */
*(.fini_array) /* New ABI: Allocated */
*(SORT(.fini_array.*))
_edtors = . ;
}
.bss :
{
_sbss = . ;
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.b*)
*(COMMON)
_ebss = . ;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}

View file

@ -1,345 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __BINFMT_LIBELF_LIBELF_H
#define __BINFMT_LIBELF_LIBELF_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/binfmt/elf.h>
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_verifyheader(FAR const Elf_Ehdr *header);
/****************************************************************************
* Name: elf_read
*
* Description:
* Read 'readsize' bytes from the object file at 'offset'. The data is
* read into 'buffer.' If 'buffer' is part of the ELF address environment,
* then the caller is responsible for assuring that that address
* environment is in place before calling this function (i.e., that
* elf_addrenv_select() has been called if CONFIG_ARCH_ADDRENV=y).
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset);
/****************************************************************************
* Name: elf_loadphdrs
*
* Description:
* Loads program headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_loadphdrs(FAR struct elf_loadinfo_s *loadinfo);
/****************************************************************************
* Name: elf_loadshdrs
*
* Description:
* Loads section headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo);
/****************************************************************************
* Name: elf_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 elf_findsection(FAR struct elf_loadinfo_s *loadinfo,
FAR const char *sectname);
/****************************************************************************
* Name: elf_findsymtab
*
* Description:
* Find the symbol table section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_findsymtab(FAR struct elf_loadinfo_s *loadinfo);
/****************************************************************************
* Name: elf_readsym
*
* Description:
* Read the ELF symbol structure at the specified 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 elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
FAR Elf_Sym *sym);
/****************************************************************************
* Name: elf_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 elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_Sym *sym,
FAR const struct symtab_s *exports, int nexports);
/****************************************************************************
* Name: elf_freebuffers
*
* Description:
* Release all working buffers.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_freebuffers(FAR struct elf_loadinfo_s *loadinfo);
/****************************************************************************
* Name: elf_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 elf_allocbuffer(FAR struct elf_loadinfo_s *loadinfo);
/****************************************************************************
* Name: elf_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 elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment);
/****************************************************************************
* Name: elf_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 elf_loadctors(FAR struct elf_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Name: elf_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 elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Name: elf_addrenv_alloc
*
* Description:
* Allocate memory for the ELF image (textalloc and dataalloc).
* If CONFIG_ARCH_ADDRENV=n, textalloc will be allocated using kmm_zalloc()
* and dataalloc will be a offset from textalloc.
* If CONFIG_ARCH_ADDRENV=y, then textalloc and dataalloc will be allocated
* using up_addrenv_create().
* In either case, there will be a unique instance of textalloc and
* dataalloc (and stack) for each instance of a process.
*
* Input Parameters:
* loadinfo - Load state information
* textsize - The size (in bytes) of the .text address environment needed
* for the ELF image (read/execute).
* datasize - The size (in bytes) of the .bss/.data address environment
* needed for the ELF image (read/write).
* heapsize - The initial size (in bytes) of the heap address environment
* needed by the task. This region may be read/write only.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
size_t datasize, size_t heapsize);
/****************************************************************************
* Name: elf_addrenv_select
*
* Description:
* Temporarily select the task's address environment.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Name: elf_addrenv_restore
*
* Description:
* Restore the address environment before elf_addrenv_select() was called..
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo);
#endif
/****************************************************************************
* Name: elf_addrenv_free
*
* Description:
* Release the address environment previously created by
* elf_addrenv_alloc(). This function is called only under certain error
* conditions after the module has been loaded but not yet started.
* After the module has been started, the address environment will
* automatically be freed when the module exits.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* None.
*
****************************************************************************/
void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo);
#endif /* __BINFMT_LIBELF_LIBELF_H */

View file

@ -1,354 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_addrenv.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/addrenv.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <sys/mman.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ELF_TEXT_WRE (PROT_READ | PROT_WRITE | PROT_EXEC)
#define ELF_TEXT_RE (PROT_READ | PROT_EXEC)
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_addrenv_alloc
*
* Description:
* Allocate memory for the ELF image (textalloc and dataalloc). If
* CONFIG_ARCH_ADDRENV=n, textalloc will be allocated using kmm_zalloc()
* and dataalloc will be a offset from textalloc. If
* CONFIG_ARCH_ADDRENV=y, then textalloc and dataalloc will be allocated
* using up_addrenv_create(). In either case, there will be a unique
* instance of textalloc and dataalloc (and stack) for each instance of a
* process.
*
* Input Parameters:
* loadinfo - Load state information
* textsize - The size (in bytes) of the .text address environment needed
* for the ELF image (read/execute).
* datasize - The size (in bytes) of the .bss/.data address environment
* needed for the ELF image (read/write).
* heapsize - The initial size (in bytes) of the heap address environment
* needed by the task. This region may be read/write only.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
size_t datasize, size_t heapsize)
{
#ifdef CONFIG_ARCH_ADDRENV
FAR struct arch_addrenv_s *addrenv;
FAR void *vtext;
FAR void *vdata;
int ret;
/* Create an address environment for the new ELF task */
loadinfo->addrenv = addrenv_allocate();
if (!loadinfo->addrenv)
{
return -ENOMEM;
}
/* Start creating the address environment sections */
addrenv = &loadinfo->addrenv->addrenv;
ret = up_addrenv_create(textsize, datasize, heapsize, addrenv);
if (ret < 0)
{
berr("ERROR: up_addrenv_create failed: %d\n", ret);
goto errout_with_addrenv;
}
/* Get the virtual address associated with the start of the address
* environment. This is the base address that we will need to use to
* access the ELF image (but only if the address environment has been
* selected.
*/
ret = up_addrenv_vtext(addrenv, &vtext);
if (ret < 0)
{
berr("ERROR: up_addrenv_vtext failed: %d\n", ret);
goto errout_with_addrenv;
}
ret = up_addrenv_vdata(addrenv, textsize, &vdata);
if (ret < 0)
{
berr("ERROR: up_addrenv_vdata failed: %d\n", ret);
goto errout_with_addrenv;
}
loadinfo->textalloc = (uintptr_t)vtext;
loadinfo->dataalloc = (uintptr_t)vdata;
return OK;
errout_with_addrenv:
addrenv_drop(loadinfo->addrenv, false);
return ret;
#else
if (loadinfo->ehdr.e_type == ET_EXEC)
{
return OK;
}
/* Allocate memory to hold the ELF image */
# ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign,
textsize);
# else
loadinfo->textalloc = (uintptr_t)
kumm_memalign(loadinfo->textalign, textsize);
# endif
if (!loadinfo->textalloc)
{
return -ENOMEM;
}
if (loadinfo->datasize > 0)
{
# ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->dataalloc = (uintptr_t)
up_dataheap_memalign(loadinfo->dataalign,
datasize);
# else
loadinfo->dataalloc = (uintptr_t)
kumm_memalign(loadinfo->dataalign, datasize);
# endif
if (!loadinfo->dataalloc)
{
return -ENOMEM;
}
}
# endif
return OK;
#endif
}
/****************************************************************************
* Name: elf_addrenv_select
*
* Description:
* Temporarily select the task's address environment.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo)
{
int ret;
/* Instantiate the new address environment */
ret = addrenv_select(loadinfo->addrenv, &loadinfo->oldenv);
if (ret < 0)
{
berr("ERROR: addrenv_select failed: %d\n", ret);
return ret;
}
/* Allow write access to .text */
ret = up_addrenv_mprot(&loadinfo->addrenv->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRE);
if (ret < 0)
{
berr("ERROR: up_addrenv_text_enable_write failed: %d\n", ret);
return ret;
}
return OK;
}
#endif
/****************************************************************************
* Name: elf_addrenv_restore
*
* Description:
* Restore the address environment before elf_addrenv_select() was called..
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo)
{
int ret;
/* Remove write access to .text */
ret = up_addrenv_mprot(&loadinfo->addrenv->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_RE);
if (ret < 0)
{
berr("ERROR: up_addrenv_text_disable_write failed: %d\n", ret);
return ret;
}
/* Restore the old address environment */
ret = addrenv_restore(loadinfo->oldenv);
if (ret < 0)
{
berr("ERROR: addrenv_restore failed: %d\n", ret);
return ret;
}
return OK;
}
#endif
/****************************************************************************
* Name: elf_addrenv_free
*
* Description:
* Release the address environment previously created by
* elf_addrenv_alloc(). This function is called only under certain error
* conditions after the module has been loaded but not yet started.
* After the module has been started, the address environment will
* automatically be freed when the module exits.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* None.
*
****************************************************************************/
void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo)
{
#ifdef CONFIG_ARCH_ADDRENV
/* Free the address environment */
addrenv_drop(loadinfo->addrenv, false);
#else
# ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->textalloc != 0)
{
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)loadinfo->textalloc);
# else
kumm_free((FAR void *)loadinfo->textalloc);
# endif
}
if (loadinfo->dataalloc != 0)
{
# if defined(CONFIG_ARCH_USE_DATA_HEAP)
up_dataheap_free((FAR void *)loadinfo->dataalloc);
# else
kumm_free((FAR void *)loadinfo->dataalloc);
# endif
}
# else
int i;
for (i = 0; loadinfo->ehdr.e_type == ET_REL && i < loadinfo->ehdr.e_shnum;
i++)
{
if (loadinfo->sectalloc[i] == 0)
{
continue;
}
if ((loadinfo->shdr[i].sh_flags & SHF_WRITE) != 0)
{
# if defined(CONFIG_ARCH_USE_DATA_HEAP)
up_dataheap_free((FAR void *)loadinfo->sectalloc[i]);
# else
kumm_free((FAR void *)loadinfo->sectalloc[i]);
# endif
}
else
{
# if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)loadinfo->sectalloc[i]);
# else
kumm_free((FAR void *)loadinfo->sectalloc[i]);
# endif
}
}
kmm_free(loadinfo->sectalloc);
loadinfo->sectalloc = 0;
# endif
#endif
/* Clear out all indications of the allocated address environment */
loadinfo->textalloc = 0;
loadinfo->dataalloc = 0;
loadinfo->textsize = 0;
loadinfo->datasize = 0;
}

View file

@ -1,703 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_bind.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/elf.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CONFIG_DEBUG_FEATURES, CONFIG_DEBUG_INFO, and CONFIG_DEBUG_BINFMT have to
* be defined or CONFIG_ELF_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_INFO) || !defined (CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
# define elf_dumpbuffer(m,b,n) binfodumpbuffer(m,b,n)
#else
# define elf_dumpbuffer(m,b,n)
#endif
#ifdef ARCH_ELFDATA
# define ARCH_ELFDATA_DEF arch_elfdata_t arch_data; \
memset(&arch_data, 0, sizeof(arch_elfdata_t))
# define ARCH_ELFDATA_PARM &arch_data
#else
# define ARCH_ELFDATA_DEF
# define ARCH_ELFDATA_PARM NULL
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct elf_symcache_s
{
dq_entry_t entry;
Elf_Sym sym;
int idx;
};
typedef struct elf_symcache_s elf_symcache_t;
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: elf_readrels
*
* Description:
* Read the (ELF_Rel structure * buffer count) into memory.
*
****************************************************************************/
static inline int elf_readrels(FAR struct elf_loadinfo_s *loadinfo,
FAR const Elf_Shdr *relsec,
int index, FAR Elf_Rel *rels,
int count)
{
off_t offset;
int size;
/* Verify that the symbol table index lies within symbol table */
if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rel)))
{
berr("Bad relocation symbol index: %d\n", index);
return -EINVAL;
}
/* Get the file offset to the symbol table entry */
offset = sizeof(Elf_Rel) * index;
size = sizeof(Elf_Rel) * count;
if (offset + size > relsec->sh_size)
{
size = relsec->sh_size - offset;
}
/* And, finally, read the symbol table entry into memory */
return elf_read(loadinfo, (FAR uint8_t *)rels, size,
relsec->sh_offset + offset);
}
/****************************************************************************
* Name: elf_readrelas
*
* Description:
* Read the (ELF_Rela structure * buffer count) into memory.
*
****************************************************************************/
static inline int elf_readrelas(FAR struct elf_loadinfo_s *loadinfo,
FAR const Elf_Shdr *relsec,
int index, FAR Elf_Rela *relas,
int count)
{
off_t offset;
int size;
/* Verify that the symbol table index lies within symbol table */
if (index < 0 || index > (relsec->sh_size / sizeof(Elf_Rela)))
{
berr("Bad relocation symbol index: %d\n", index);
return -EINVAL;
}
/* Get the file offset to the symbol table entry */
offset = sizeof(Elf_Rela) * index;
size = sizeof(Elf_Rela) * count;
if (offset + size > relsec->sh_size)
{
size = relsec->sh_size - offset;
}
/* And, finally, read the symbol table entry into memory */
return elf_read(loadinfo, (FAR uint8_t *)relas, size,
relsec->sh_offset + offset);
}
/****************************************************************************
* Name: elf_relocate and elf_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 elf_relocate(FAR struct elf_loadinfo_s *loadinfo, int relidx,
FAR const struct symtab_s *exports, int nexports)
{
FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx];
FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info];
FAR Elf_Rel *rels;
FAR Elf_Rel *rel;
FAR elf_symcache_t *cache;
FAR Elf_Sym *sym;
FAR dq_entry_t *e;
dq_queue_t q;
uintptr_t addr;
int symidx;
int ret;
int i;
int j;
/* Define potential architecture specific elf data container */
ARCH_ELFDATA_DEF;
rels = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rel));
if (rels == NULL)
{
berr("Failed to allocate memory for elf relocation\n");
return -ENOMEM;
}
dq_init(&q);
/* Examine each relocation in the section. 'relsec' is the section
* containing the relations. 'dstsec' is the section containing the data
* to be relocated.
*/
ret = OK;
for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rel); i++)
{
/* Read the relocation entry into memory */
rel = &rels[i % CONFIG_ELF_RELOCATION_BUFFERCOUNT];
if (!(i % CONFIG_ELF_RELOCATION_BUFFERCOUNT))
{
ret = elf_readrels(loadinfo, relsec, i, rels,
CONFIG_ELF_RELOCATION_BUFFERCOUNT);
if (ret < 0)
{
berr("Section %d reloc %d: "
"Failed to read relocation entry: %d\n",
relidx, i, ret);
break;
}
}
/* Get the symbol table index for the relocation. This is contained
* in a bit-field within the r_info element.
*/
symidx = ELF_R_SYM(rel->r_info);
/* First try the cache */
sym = NULL;
for (e = dq_peek(&q); e; e = dq_next(e))
{
cache = (FAR elf_symcache_t *)e;
if (cache->idx == symidx)
{
dq_rem(&cache->entry, &q);
dq_addfirst(&cache->entry, &q);
sym = &cache->sym;
break;
}
}
/* If the symbol was not found in the cache, we will need to read the
* symbol from the file.
*/
if (sym == NULL)
{
if (j < CONFIG_ELF_SYMBOL_CACHECOUNT)
{
cache = kmm_malloc(sizeof(elf_symcache_t));
if (!cache)
{
berr("Failed to allocate memory for elf symbols\n");
ret = -ENOMEM;
break;
}
j++;
}
else
{
cache = (FAR elf_symcache_t *)dq_remlast(&q);
}
sym = &cache->sym;
/* Read the symbol table entry into memory */
ret = elf_readsym(loadinfo, symidx, sym);
if (ret < 0)
{
berr("Section %d reloc %d: Failed to read symbol[%d]: %d\n",
relidx, i, symidx, ret);
kmm_free(cache);
break;
}
/* Get the value of the symbol (in sym.st_value) */
ret = elf_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)
{
berr("Section %d reloc %d: "
"Undefined symbol[%d] has no name: %d\n",
relidx, i, symidx, ret);
}
else
{
berr("Section %d reloc %d: "
"Failed to get value of symbol[%d]: %d\n",
relidx, i, symidx, ret);
kmm_free(cache);
break;
}
}
cache->idx = symidx;
dq_addfirst(&cache->entry, &q);
}
if (sym->st_shndx == SHN_UNDEF && sym->st_name == 0)
{
sym = NULL;
}
/* Calculate the relocation address. */
if (rel->r_offset < 0 ||
rel->r_offset > dstsec->sh_size - sizeof(uint32_t))
{
berr("Section %d reloc %d: Relocation address out of range, "
"offset %" PRIdPTR " size %jd\n",
relidx, i, (uintptr_t)rel->r_offset,
(uintmax_t)dstsec->sh_size);
ret = -EINVAL;
break;
}
addr = dstsec->sh_addr + rel->r_offset;
/* Now perform the architecture-specific relocation */
ret = up_relocate(rel, sym, addr, ARCH_ELFDATA_PARM);
if (ret < 0)
{
berr("ERROR: Section %d reloc %d: Relocation failed: %d\n",
relidx, i, ret);
break;
}
}
kmm_free(rels);
while ((e = dq_peek(&q)))
{
dq_rem(e, &q);
kmm_free(e);
}
return ret;
}
static int elf_relocateadd(FAR struct elf_loadinfo_s *loadinfo, int relidx,
FAR const struct symtab_s *exports, int nexports)
{
FAR Elf_Shdr *relsec = &loadinfo->shdr[relidx];
FAR Elf_Shdr *dstsec = &loadinfo->shdr[relsec->sh_info];
FAR Elf_Rela *relas;
FAR Elf_Rela *rela;
FAR elf_symcache_t *cache;
FAR Elf_Sym *sym;
FAR dq_entry_t *e;
dq_queue_t q;
uintptr_t addr;
int symidx;
int ret;
int i;
int j;
/* Define potential architecture specific elf data container */
ARCH_ELFDATA_DEF;
relas = kmm_malloc(CONFIG_ELF_RELOCATION_BUFFERCOUNT * sizeof(Elf_Rela));
if (relas == NULL)
{
berr("Failed to allocate memory for elf relocation\n");
return -ENOMEM;
}
dq_init(&q);
/* Examine each relocation in the section. 'relsec' is the section
* containing the relations. 'dstsec' is the section containing the data
* to be relocated.
*/
ret = OK;
for (i = j = 0; i < relsec->sh_size / sizeof(Elf_Rela); i++)
{
/* Read the relocation entry into memory */
rela = &relas[i % CONFIG_ELF_RELOCATION_BUFFERCOUNT];
if (!(i % CONFIG_ELF_RELOCATION_BUFFERCOUNT))
{
ret = elf_readrelas(loadinfo, relsec, i, relas,
CONFIG_ELF_RELOCATION_BUFFERCOUNT);
if (ret < 0)
{
berr("Section %d reloc %d: "
"Failed to read relocation entry: %d\n",
relidx, i, ret);
break;
}
}
/* Get the symbol table index for the relocation. This is contained
* in a bit-field within the r_info element.
*/
symidx = ELF_R_SYM(rela->r_info);
/* First try the cache */
sym = NULL;
for (e = dq_peek(&q); e; e = dq_next(e))
{
cache = (FAR elf_symcache_t *)e;
if (cache->idx == symidx)
{
dq_rem(&cache->entry, &q);
dq_addfirst(&cache->entry, &q);
sym = &cache->sym;
break;
}
}
/* If the symbol was not found in the cache, we will need to read the
* symbol from the file.
*/
if (sym == NULL)
{
if (j < CONFIG_ELF_SYMBOL_CACHECOUNT)
{
cache = kmm_malloc(sizeof(elf_symcache_t));
if (!cache)
{
berr("Failed to allocate memory for elf symbols\n");
ret = -ENOMEM;
break;
}
j++;
}
else
{
cache = (FAR elf_symcache_t *)dq_remlast(&q);
}
sym = &cache->sym;
/* Read the symbol table entry into memory */
ret = elf_readsym(loadinfo, symidx, sym);
if (ret < 0)
{
berr("Section %d reloc %d: Failed to read symbol[%d]: %d\n",
relidx, i, symidx, ret);
kmm_free(cache);
break;
}
/* Get the value of the symbol (in sym.st_value) */
ret = elf_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)
{
bwarn("Section %d reloc %d: "
"Undefined symbol[%d] has no name: %d\n",
relidx, i, symidx, ret);
}
else
{
berr("Section %d reloc %d: "
"Failed to get value of symbol[%d]: %d\n",
relidx, i, symidx, ret);
kmm_free(cache);
break;
}
}
cache->idx = symidx;
dq_addfirst(&cache->entry, &q);
}
if (sym->st_shndx == SHN_UNDEF && sym->st_name == 0)
{
sym = NULL;
}
/* Calculate the relocation address. */
if (rela->r_offset < 0 ||
rela->r_offset > dstsec->sh_size)
{
berr("Section %d reloc %d: Relocation address out of range, "
"offset %" PRIdPTR " size %jd\n",
relidx, i, (uintptr_t)rela->r_offset,
(uintmax_t)dstsec->sh_size);
ret = -EINVAL;
break;
}
addr = dstsec->sh_addr + rela->r_offset;
/* Now perform the architecture-specific relocation */
ret = up_relocateadd(rela, sym, addr, ARCH_ELFDATA_PARM);
if (ret < 0)
{
berr("ERROR: Section %d reloc %d: Relocation failed: %d\n",
relidx, i, ret);
break;
}
}
kmm_free(relas);
while ((e = dq_peek(&q)))
{
dq_rem(e, &q);
kmm_free(e);
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_bind(FAR struct elf_loadinfo_s *loadinfo,
FAR const struct symtab_s *exports, int nexports)
{
#ifdef CONFIG_ARCH_ADDRENV
int status;
#endif
int ret;
int i;
/* Find the symbol and string tables */
ret = elf_findsymtab(loadinfo);
if (ret < 0)
{
return ret;
}
#ifdef CONFIG_ARCH_ADDRENV
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_addrenv_select() failed: %d\n", ret);
return ret;
}
#endif
/* 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 = elf_relocate(loadinfo, i, exports, nexports);
}
else if (loadinfo->shdr[i].sh_type == SHT_RELA)
{
ret = elf_relocateadd(loadinfo, i, exports, nexports);
}
if (ret < 0)
{
break;
}
}
#if defined(CONFIG_ARCH_ADDRENV)
/* 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).
*/
#if 0 /* REVISIT... has some problems */
up_addrenv_coherent(&loadinfo->addrenv.addrenv);
#else
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
up_coherent_dcache(loadinfo->dataalloc, loadinfo->datasize);
#endif
/* Restore the original address environment */
status = elf_addrenv_restore(loadinfo);
if (status < 0)
{
berr("ERROR: elf_addrenv_restore() failed: %d\n", status);
if (ret == OK)
{
ret = status;
}
}
#else
/* 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).
*/
if (loadinfo->textsize > 0)
{
up_coherent_dcache(loadinfo->textalloc, loadinfo->textsize);
}
if (loadinfo->datasize > 0)
{
up_coherent_dcache(loadinfo->dataalloc, loadinfo->datasize);
}
# ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
for (i = 0; loadinfo->ehdr.e_type == ET_REL && i < loadinfo->ehdr.e_shnum;
i++)
{
if (loadinfo->sectalloc[i] == 0)
{
continue;
}
up_coherent_dcache(loadinfo->sectalloc[i], loadinfo->shdr[i].sh_size);
}
# endif
#endif
return ret;
}

View file

@ -1,193 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_ctors.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
{
FAR Elf_Shdr *shdr;
size_t ctorsize;
int ctoridx;
int ret;
int i;
DEBUGASSERT(loadinfo->ctors == NULL);
/* 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 = elf_findsection(loadinfo, ".ctors");
if (ctoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static constructor section.
*/
binfo("elf_findsection .ctors section failed: %d\n", ctoridx);
return ctoridx == -ENOENT ? OK : ctoridx;
}
/* 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);
binfo("ctoridx=%d ctorsize=%zd sizeof(binfmt_ctor_t)=%zd 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 = kumm_malloc(ctorsize);
if (!loadinfo->ctoralloc)
{
berr("Failed to allocate memory for .ctors\n");
return -ENOMEM;
}
loadinfo->ctors = (binfmt_ctor_t *)loadinfo->ctoralloc;
/* Read the section header table into memory */
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->ctors, ctorsize,
shdr->sh_offset);
if (ret < 0)
{
berr("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 = (FAR uintptr_t *)
((FAR void *)(&loadinfo->ctors)[i]);
binfo("ctor %d: "
"%08" PRIxPTR " + %08" PRIxPTR " = %08" PRIxPTR "\n", i,
*ptr, loadinfo->textalloc, (*ptr + loadinfo->textalloc));
*ptr += loadinfo->textalloc;
}
}
else
{
/* Save the address of the .ctors (actually, .init_array) where
* it was loaded into memory. Since the .ctors lie in allocated
* memory, they will be relocated via the normal mechanism.
*/
loadinfo->ctors = (binfmt_ctor_t *)shdr->sh_addr;
}
}
return OK;
}
#endif /* CONFIG_BINFMT_CONSTRUCTORS */

View file

@ -1,194 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_dtors.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
#ifdef CONFIG_BINFMT_CONSTRUCTORS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
{
FAR Elf_Shdr *shdr;
size_t dtorsize;
int dtoridx;
int ret;
int i;
DEBUGASSERT(loadinfo->dtors == NULL);
/* 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 = elf_findsection(loadinfo, ".dtors");
if (dtoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static destructor section.
*/
binfo("elf_findsection .dtors section failed: %d\n", dtoridx);
return dtoridx == -ENOENT ? OK : dtoridx;
}
/* 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);
binfo("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->dtoralloc = kumm_malloc(dtorsize);
if (!loadinfo->dtoralloc)
{
berr("Failed to allocate memory for .dtors\n");
return -ENOMEM;
}
loadinfo->dtors = (binfmt_dtor_t *)loadinfo->dtoralloc;
/* Read the section header table into memory */
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->dtors, dtorsize,
shdr->sh_offset);
if (ret < 0)
{
berr("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 = (FAR uintptr_t *)
((FAR void *)(&loadinfo->dtors)[i]);
binfo("dtor %d: "
"%08" PRIxPTR " + %08" PRIxPTR " = %08" PRIxPTR "\n", i,
*ptr, loadinfo->textalloc, (*ptr + loadinfo->textalloc));
*ptr += loadinfo->textalloc;
}
}
else
{
/* Save the address of the .dtors (actually, .init_array) where
* it was loaded into memory. Since the .dtors lie in allocated
* memory, they will be relocated via the normal mechanism.
*/
loadinfo->dtors = (binfmt_dtor_t *)shdr->sh_addr;
}
}
return OK;
}
#endif /* CONFIG_BINFMT_CONSTRUCTORS */

View file

@ -1,178 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_init.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/stat.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CONFIG_DEBUG_FEATURES, CONFIG_DEBUG_INFO, and CONFIG_DEBUG_BINFMT have to
* be defined or CONFIG_ELF_DUMPBUFFER does nothing.
*/
#if !defined(CONFIG_DEBUG_INFO) || !defined(CONFIG_DEBUG_BINFMT)
# undef CONFIG_ELF_DUMPBUFFER
#endif
#ifdef CONFIG_ELF_DUMPBUFFER
# define elf_dumpbuffer(m,b,n) binfodumpbuffer(m,b,n)
#else
# define elf_dumpbuffer(m,b,n)
#endif
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: elf_fileinfo
*
* Description:
* Get some stats info of the ELF file
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static inline int elf_fileinfo(FAR struct elf_loadinfo_s *loadinfo)
{
struct stat buf;
int ret;
/* Get the file stats */
ret = file_fstat(&loadinfo->file, &buf);
if (ret < 0)
{
berr("Failed to stat file: %d\n", ret);
return ret;
}
/* Return some stats info of the file in the loadinfo structure */
loadinfo->filelen = buf.st_size;
loadinfo->fileuid = buf.st_uid;
loadinfo->filegid = buf.st_gid;
loadinfo->filemode = buf.st_mode;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_init
*
* 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 elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
{
int ret;
binfo("filename: %s loadinfo: %p\n", filename, loadinfo);
/* Clear the load info structure */
memset(loadinfo, 0, sizeof(struct elf_loadinfo_s));
/* Open the binary file for reading (only) */
ret = file_open(&loadinfo->file, filename, O_RDONLY | O_CLOEXEC);
if (ret < 0)
{
berr("Failed to open ELF binary %s: %d\n", filename, ret);
return ret;
}
/* Get some stats info of the file. */
ret = elf_fileinfo(loadinfo);
if (ret < 0)
{
berr("elf_fileinfo failed: %d\n", ret);
return ret;
}
/* Read the ELF ehdr from offset 0 */
ret = elf_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr,
sizeof(Elf_Ehdr), 0);
if (ret < 0)
{
berr("Failed to read ELF header: %d\n", ret);
return ret;
}
elf_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr,
sizeof(Elf_Ehdr));
/* Verify the ELF header */
ret = elf_verifyheader(&loadinfo->ehdr);
if (ret < 0)
{
/* This may not be an error because we will be called to attempt
* loading EVERY binary. If elf_verifyheader() does not recognize
* the ELF header, it will -ENOEXEC which simply informs the system
* that the file is not an ELF file. elf_verifyheader() will return
* other errors if the ELF header is not correctly formed.
*/
berr("Bad ELF header: %d\n", ret);
return ret;
}
return OK;
}

View file

@ -1,122 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_iobuffer.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_allocbuffer(FAR struct elf_loadinfo_s *loadinfo)
{
/* Has a buffer been allocated? */
if (!loadinfo->iobuffer)
{
/* No.. allocate one now */
loadinfo->iobuffer = kmm_malloc(CONFIG_ELF_BUFFERSIZE);
if (!loadinfo->iobuffer)
{
berr("Failed to allocate an I/O buffer\n");
return -ENOMEM;
}
loadinfo->buflen = CONFIG_ELF_BUFFERSIZE;
}
return OK;
}
/****************************************************************************
* Name: elf_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 elf_reallocbuffer(FAR struct elf_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(loadinfo->iobuffer, newsize);
if (!buffer)
{
berr("Failed to reallocate the I/O buffer\n");
return -ENOMEM;
}
/* Save the new buffer info */
loadinfo->iobuffer = buffer;
loadinfo->buflen = newsize;
return OK;
}

View file

@ -1,552 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_load.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/param.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/addrenv.h>
#include <nuttx/elf.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.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)
/* _ALIGN_UP: 'a' is assumed to be a power of two */
#define _ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1))
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
#if defined(CONFIG_ARCH_USE_SEPARATED_SECTION) && !defined(CONFIG_ARCH_ADDRENV)
static int elf_section_alloc(FAR struct elf_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, uint8_t idx)
{
if (loadinfo->ehdr.e_type != ET_REL)
{
return -EINVAL;
}
if (loadinfo->sectalloc == NULL)
{
/* Allocate memory info for all sections */
loadinfo->sectalloc = kmm_zalloc(sizeof(uintptr_t) *
loadinfo->ehdr.e_shnum);
if (loadinfo->sectalloc == NULL)
{
return -ENOMEM;
}
}
elf_sectname(loadinfo, shdr);
if ((shdr->sh_flags & SHF_WRITE) != 0)
{
# ifdef CONFIG_ARCH_USE_DATA_HEAP
loadinfo->sectalloc[idx] = (uintptr_t)
up_dataheap_memalign(
(FAR const char *)loadinfo->iobuffer,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)kumm_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->dataalloc == 0)
{
loadinfo->dataalloc = loadinfo->sectalloc[idx];
}
}
else
{
# ifdef CONFIG_ARCH_USE_TEXT_HEAP
loadinfo->sectalloc[idx] = (uintptr_t)
up_textheap_memalign(
(FAR const char *)loadinfo->iobuffer,
shdr->sh_addralign,
shdr->sh_size);
# else
loadinfo->sectalloc[idx] = (uintptr_t)kumm_memalign(shdr->sh_addralign,
shdr->sh_size);
# endif
if (loadinfo->textalloc == 0)
{
loadinfo->textalloc = loadinfo->sectalloc[idx];
}
}
return OK;
}
#endif
/****************************************************************************
* Name: elf_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 elf_elfsize(FAR struct elf_loadinfo_s *loadinfo)
{
size_t textsize = 0;
size_t datasize = 0;
int i;
/* Accumulate the size each section into memory that is marked SHF_ALLOC */
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_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
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
{
#if defined(CONFIG_ARCH_USE_SEPARATED_SECTION) && !defined(CONFIG_ARCH_ADDRENV)
if (elf_section_alloc(loadinfo, shdr, i) >= 0)
{
continue;
}
#endif
datasize = _ALIGN_UP(datasize, shdr->sh_addralign);
datasize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->dataalign < shdr->sh_addralign)
{
loadinfo->dataalign = shdr->sh_addralign;
}
}
else
{
#if defined(CONFIG_ARCH_USE_SEPARATED_SECTION) && !defined(CONFIG_ARCH_ADDRENV)
if (elf_section_alloc(loadinfo, shdr, i) >= 0)
{
continue;
}
#endif
textsize = _ALIGN_UP(textsize, shdr->sh_addralign);
textsize += ELF_ALIGNUP(shdr->sh_size);
if (loadinfo->textalign < shdr->sh_addralign)
{
loadinfo->textalign = shdr->sh_addralign;
}
}
}
}
/* Save the allocation size */
loadinfo->textsize = textsize;
loadinfo->datasize = datasize;
}
#ifdef CONFIG_ELF_LOADTO_LMA
/****************************************************************************
* Name: elf_vma2lma
*
* Description:
* Convert section`s VMA to LMA according to PhysAddr(p_paddr) of
* Program Header.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
static int elf_vma2lma(FAR struct elf_loadinfo_s *loadinfo,
FAR Elf_Shdr *shdr, FAR Elf_Addr *lma)
{
int i;
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
{
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
if (shdr->sh_addr >= phdr->p_vaddr &&
shdr->sh_addr < phdr->p_vaddr + phdr->p_memsz)
{
*lma = phdr->p_paddr + shdr->sh_addr - phdr->p_vaddr;
return 0;
}
}
return -ENOENT;
}
#endif
/****************************************************************************
* Name: elf_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 elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
{
FAR uint8_t *text = (FAR uint8_t *)loadinfo->textalloc;
FAR uint8_t *data = (FAR uint8_t *)loadinfo->dataalloc;
FAR uint8_t **pptr = NULL;
int ret;
int i;
/* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
binfo("Loaded sections:\n");
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type == ET_REL)
{
pptr = (FAR uint8_t **)&loadinfo->sectalloc[i];
}
else
#endif
/* SHF_WRITE indicates that the section address space is write-
* able
*/
if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
{
pptr = &data;
}
else
{
pptr = &text;
}
/* SHF_ALLOC indicates that the section requires memory during
* execution.
*/
if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
/* Set the VMA regardless, some relocations might depend on this */
shdr->sh_addr = (uintptr_t)*pptr;
continue;
}
if (*pptr == NULL)
{
if (shdr->sh_type != SHT_NOBITS)
{
Elf_Addr addr = shdr->sh_addr;
#ifdef CONFIG_ELF_LOADTO_LMA
ret = elf_vma2lma(loadinfo, shdr, &addr);
if (ret < 0)
{
berr("ERROR: Failed to convert addr %d: %d\n", i, ret);
return ret;
}
#endif
/* Read the section data from sh_offset to specified region */
ret = elf_read(loadinfo, (FAR uint8_t *)addr,
shdr->sh_size, shdr->sh_offset);
if (ret < 0)
{
berr("ERROR: Failed to read section %d: %d\n", i, ret);
return ret;
}
}
#ifndef CONFIG_ELF_LOADTO_LMA
/* If there is no data in an allocated section, then the
* allocated section must be cleared.
*/
else
{
memset((FAR uint8_t *)shdr->sh_addr, 0, shdr->sh_size);
}
#endif
continue;
}
#ifndef CONFIG_ARCH_USE_SEPARATED_SECTION
*pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr, shdr->sh_addralign);
#endif
/* 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 = elf_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset);
if (ret < 0)
{
berr("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 */
binfo("%d. %08lx->%08lx\n", i,
(unsigned long)shdr->sh_addr, (unsigned long)*pptr);
shdr->sh_addr = (uintptr_t)*pptr;
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
if (loadinfo->ehdr.e_type != ET_REL)
{
*pptr += ELF_ALIGNUP(shdr->sh_size);
}
#else
/* Setup the memory pointer for the next time through the loop */
*pptr += ELF_ALIGNUP(shdr->sh_size);
#endif
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_load(FAR struct elf_loadinfo_s *loadinfo)
{
/* Determine the heapsize to allocate. heapsize is ignored if there is
* no address environment because the heap is a shared resource in that
* case. If there is no dynamic stack then heapsize must at least as big
* as the fixed stack size since the stack will be allocated from the heap
* in that case.
*/
#if !defined(CONFIG_ARCH_ADDRENV)
size_t heapsize = 0;
#elif defined(CONFIG_ARCH_STACK_DYNAMIC)
size_t heapsize = ARCH_HEAP_SIZE;
#else
size_t heapsize = MAX(ARCH_HEAP_SIZE, CONFIG_ELF_STACKSIZE);
#endif
#ifdef CONFIG_ELF_EXIDX_SECTNAME
int exidx;
#endif
int ret;
binfo("loadinfo: %p\n", loadinfo);
DEBUGASSERT(loadinfo && loadinfo->file.f_inode);
/* Load program headers into memory */
ret = elf_loadphdrs(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_loadphdrs failed: %d\n", ret);
goto errout_with_buffers;
}
/* Load section headers into memory */
ret = elf_loadshdrs(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_loadshdrs failed: %d\n", ret);
goto errout_with_buffers;
}
/* Determine total size to allocate */
elf_elfsize(loadinfo);
/* Allocate (and zero) memory for the ELF file. */
ret = elf_addrenv_alloc(loadinfo, loadinfo->textsize, loadinfo->datasize,
heapsize);
if (ret < 0)
{
berr("ERROR: elf_addrenv_alloc() failed: %d\n", ret);
goto errout_with_buffers;
}
#ifdef CONFIG_ARCH_ADDRENV
/* If CONFIG_ARCH_ADDRENV=y, then the loaded ELF lies in a virtual address
* space that may not be in place now. elf_addrenv_select() will
* temporarily instantiate that address space.
*/
ret = elf_addrenv_select(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_addrenv_select() failed: %d\n", ret);
goto errout_with_buffers;
}
#endif
/* Load ELF section data into memory */
ret = elf_loadfile(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_loadfile failed: %d\n", ret);
goto errout_with_addrenv;
}
/* Load static constructors and destructors. */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
ret = elf_loadctors(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_loadctors failed: %d\n", ret);
goto errout_with_addrenv;
}
ret = elf_loaddtors(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_loaddtors failed: %d\n", ret);
goto errout_with_addrenv;
}
#endif
#ifdef CONFIG_ELF_EXIDX_SECTNAME
exidx = elf_findsection(loadinfo, CONFIG_ELF_EXIDX_SECTNAME);
if (exidx < 0)
{
binfo("elf_findsection: Exception Index section not found: %d\n",
exidx);
}
else
{
up_init_exidx(loadinfo->shdr[exidx].sh_addr,
loadinfo->shdr[exidx].sh_size);
}
#endif
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the original address environment */
ret = elf_addrenv_restore(loadinfo);
if (ret < 0)
{
berr("ERROR: elf_addrenv_restore() failed: %d\n", ret);
goto errout_with_buffers;
}
#endif
return OK;
/* Error exits */
errout_with_addrenv:
#ifdef CONFIG_ARCH_ADDRENV
elf_addrenv_restore(loadinfo);
#endif
errout_with_buffers:
elf_unload(loadinfo);
return ret;
}

View file

@ -1,188 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_read.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <inttypes.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include <nuttx/binfmt/elf.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef ELF_DUMP_READDATA /* Define to dump all file data read */
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: elf_dumpreaddata
****************************************************************************/
#ifdef ELF_DUMP_READDATA
static inline void elf_dumpreaddata(FAR char *buffer, size_t buflen)
{
FAR uint32_t *buf32 = (FAR uint32_t *)buffer;
size_t i;
size_t j;
for (i = 0; i < buflen; i += 32)
{
syslog(LOG_DEBUG, "%04zx:", i);
for (j = 0; j < 32; j += sizeof(uint32_t))
{
syslog(LOG_DEBUG, " %08" PRIx32, *buf32++);
}
syslog(LOG_DEBUG, "\n");
}
}
#else
# define elf_dumpreaddata(b,n)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_read
*
* Description:
* Read 'readsize' bytes from the object file at 'offset'. The data is
* read into 'buffer.' If 'buffer' is part of the ELF address environment,
* then the caller is responsible for assuring that that address
* environment is in place before calling this function (i.e., that
* elf_addrenv_select() has been called if CONFIG_ARCH_ADDRENV=y).
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset)
{
size_t nsize = readsize; /* Bytes to read from the object file */
ssize_t nbytes; /* Number of bytes read */
off_t rpos; /* Position returned by lseek */
int ret = OK; /* Return value */
#ifdef CONFIG_ARCH_USE_COPY_SECTION
FAR uint8_t *dest = buffer; /* Destination address - `buffer` */
/* Redirect `buffer` to temporary allocated memory */
buffer = kmm_malloc(readsize);
if (buffer == NULL)
{
berr("ERROR: Failed to allocate memory\n");
return -ENOMEM;
}
#endif
binfo("Read %zu bytes from offset %" PRIdOFF "\n", readsize, offset);
/* Loop until all of the requested data has been read. */
while (readsize > 0)
{
/* Seek to the next read position */
rpos = file_seek(&loadinfo->file, offset, SEEK_SET);
if (rpos != offset)
{
berr("Failed to seek to position %" PRIdOFF ": %" PRIdOFF "\n",
offset, rpos);
ret = rpos;
goto errout;
}
/* Read the file data at offset into the user buffer */
nbytes = file_read(&loadinfo->file,
buffer + nsize - readsize, readsize);
if (nbytes < 0)
{
/* EINTR just means that we received a signal */
if (nbytes != -EINTR)
{
berr("Read from offset %" PRIdOFF " failed: %zd\n",
offset, nbytes);
ret = nbytes;
goto errout;
}
}
else if (nbytes == 0)
{
berr("Unexpected end of file\n");
ret = -ENODATA;
goto errout;
}
else
{
readsize -= nbytes;
offset += nbytes;
}
}
#ifdef CONFIG_ARCH_USE_COPY_SECTION
/* Copy the requested data from temporary memory to destination */
ret = up_copy_section(dest, buffer, nsize);
if (ret < 0)
{
berr("ERROR: Failed to copy section at offset %"PRIdOFF"\n", offset);
goto errout;
}
#endif
elf_dumpreaddata(buffer, nsize);
errout:
#ifdef CONFIG_ARCH_USE_COPY_SECTION
/* Free the temporary memory */
kmm_free(buffer);
#endif
return ret;
}

View file

@ -1,342 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_sections.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* 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/elf.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
FAR const Elf_Shdr *shdr)
{
FAR Elf_Shdr *shstr;
off_t offset;
size_t bytesread = 0;
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)
{
berr("No section header string table\n");
return -EINVAL;
}
/* Allocate an I/O buffer if necessary. This buffer is used by
* elf_sectname() to accumulate the variable length symbol name.
*/
ret = elf_allocbuffer(loadinfo);
if (ret < 0)
{
berr("elf_allocbuffer failed: %d\n", ret);
return ret;
}
/* 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 */
for (; ; )
{
FAR uint8_t *buffer = &loadinfo->iobuffer[bytesread];
size_t readlen = loadinfo->buflen - bytesread;
/* Get the number of bytes to read */
if (offset + readlen > loadinfo->filelen)
{
if (loadinfo->filelen <= offset)
{
berr("At end of file\n");
return -EINVAL;
}
readlen = loadinfo->filelen - offset;
}
/* Read that number of bytes into the array */
ret = elf_read(loadinfo, buffer, readlen, offset + bytesread);
if (ret < 0)
{
berr("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 = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
if (ret < 0)
{
berr("elf_reallocbuffer failed: %d\n", ret);
return ret;
}
}
/* We will not get here */
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_loadphdrs
*
* Description:
* Loads program headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_loadphdrs(FAR struct elf_loadinfo_s *loadinfo)
{
size_t phdrsize;
int ret;
DEBUGASSERT(loadinfo->phdr == NULL);
/* Verify that there are programs */
if (loadinfo->ehdr.e_phnum < 1)
{
binfo("No programs(?)\n");
return 0;
}
/* Get the total size of the program header table */
phdrsize = (size_t)loadinfo->ehdr.e_phentsize *
(size_t)loadinfo->ehdr.e_phnum;
if (loadinfo->ehdr.e_phoff + phdrsize > loadinfo->filelen)
{
berr("Insufficient space in file for program header table\n");
return -ESPIPE;
}
/* Allocate memory to hold a working copy of the program header table */
loadinfo->phdr = (FAR Elf_Phdr *)kmm_malloc(phdrsize);
if (!loadinfo->phdr)
{
berr("Failed to allocate the program header table. Size: %ld\n",
(long)phdrsize);
return -ENOMEM;
}
/* Read the program header table into memory */
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->phdr, phdrsize,
loadinfo->ehdr.e_phoff);
if (ret < 0)
{
berr("Failed to read program header table: %d\n", ret);
}
return ret;
}
/****************************************************************************
* Name: elf_loadshdrs
*
* Description:
* Loads section headers into memory.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
{
size_t shdrsize;
int ret;
DEBUGASSERT(loadinfo->shdr == NULL);
/* Verify that there are sections */
if (loadinfo->ehdr.e_shnum < 1)
{
berr("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)
{
berr("Insufficient space in file for section header table\n");
return -ESPIPE;
}
/* Allocate memory to hold a working copy of the sector header table */
loadinfo->shdr = kmm_malloc(shdrsize);
if (!loadinfo->shdr)
{
berr("Failed to allocate the section header table. Size: %zu\n",
shdrsize);
return -ENOMEM;
}
/* Read the section header table into memory */
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->shdr, shdrsize,
loadinfo->ehdr.e_shoff);
if (ret < 0)
{
berr("Failed to read section header table: %d\n", ret);
}
return ret;
}
/****************************************************************************
* Name: elf_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 elf_findsection(FAR struct elf_loadinfo_s *loadinfo,
FAR const char *sectname)
{
int i;
/* Search through the shdr[] array in loadinfo for a section named
* 'sectname'
*/
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR const Elf_Shdr *shdr = &loadinfo->shdr[i];
/* Get the name of this section */
int ret = elf_sectname(loadinfo, shdr);
if (ret < 0)
{
berr("elf_sectname failed: %d\n", ret);
return ret;
}
/* Check if the name of this section is 'sectname' */
binfo("%d. Comparing \"%s\" and .\"%s\"\n",
i, loadinfo->iobuffer, sectname);
if (strcmp((FAR const char *)loadinfo->iobuffer, sectname) == 0)
{
/* We found it... return the index */
return i;
}
}
/* We failed to find a section with this name. */
return -ENOENT;
}

View file

@ -1,340 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_symbols.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/binfmt/elf.h>
#include <nuttx/symtab.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_symname(FAR struct elf_loadinfo_s *loadinfo,
FAR const Elf_Sym *sym)
{
off_t offset;
size_t bytesread = 0;
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)
{
bwarn("Symbol has no name\n");
return -ESRCH;
}
/* Allocate an I/O buffer. This buffer is used by elf_symname() to
* accumulate the variable length symbol name.
*/
ret = elf_allocbuffer(loadinfo);
if (ret < 0)
{
berr("elf_allocbuffer failed: %d\n", ret);
return ret;
}
offset = loadinfo->shdr[loadinfo->strtabidx].sh_offset + sym->st_name;
/* Loop until we get the entire symbol name into memory */
for (; ; )
{
FAR uint8_t *buffer = &loadinfo->iobuffer[bytesread];
size_t readlen = loadinfo->buflen - bytesread;
/* Get the number of bytes to read */
if (offset + readlen > loadinfo->filelen)
{
if (loadinfo->filelen <= offset)
{
berr("At end of file\n");
return -EINVAL;
}
readlen = loadinfo->filelen - offset;
}
/* Read that number of bytes into the array */
ret = elf_read(loadinfo, buffer, readlen, offset + bytesread);
if (ret < 0)
{
berr("elf_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 = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
if (ret < 0)
{
berr("elf_reallocbuffer failed: %d\n", ret);
return ret;
}
}
/* We will not get here */
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_findsymtab
*
* Description:
* Find the symbol table section.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_findsymtab(FAR struct elf_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)
{
berr("No symbols in ELF file\n");
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Name: elf_readsym
*
* Description:
* Read the ELF symbol structure at the specified 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 elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
FAR Elf_Sym *sym)
{
FAR Elf_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(Elf_Sym)))
{
berr("Bad relocation symbol index: %d\n", index);
return -EINVAL;
}
/* Get the file offset to the symbol table entry */
offset = symtab->sh_offset + sizeof(Elf_Sym) * index;
/* And, finally, read the symbol table entry into memory */
return elf_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf_Sym), offset);
}
/****************************************************************************
* Name: elf_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 elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf_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. */
berr("SHN_COMMON: Re-compile with -fno-common\n");
return -ENOSYS;
}
case SHN_ABS:
{
/* st_value already holds the correct value */
binfo("SHN_ABS: st_value=%08lx\n", (long)sym->st_value);
return OK;
}
case SHN_UNDEF:
{
/* Get the name of the undefined symbol */
ret = elf_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.
*/
bwarn("SHN_UNDEF: Failed to get symbol name: %d\n", ret);
return ret;
}
/* Check if the base code exports a symbol of this name */
symbol = symtab_findbyname(exports, (FAR char *)loadinfo->iobuffer,
nexports);
if (!symbol)
{
berr("SHN_UNDEF: Exported symbol \"%s\" not found\n",
loadinfo->iobuffer);
return -ENOENT;
}
/* Yes... add the exported symbol value to the ELF symbol table
* entry
*/
binfo("SHN_UNDEF: name=%s "
"%08" PRIxPTR "+%08" PRIxPTR "=%08" PRIxPTR "\n",
loadinfo->iobuffer, (uintptr_t)sym->st_value,
(uintptr_t)symbol->sym_value,
(uintptr_t)(sym->st_value + (uintptr_t)symbol->sym_value));
sym->st_value += (uintptr_t)symbol->sym_value;
}
break;
default:
{
secbase = loadinfo->shdr[sym->st_shndx].sh_addr;
binfo("Other: %08" PRIxPTR "+%08" PRIxPTR "=%08" PRIxPTR "\n",
(uintptr_t)sym->st_value, secbase,
(uintptr_t)(sym->st_value + secbase));
sym->st_value += secbase;
}
break;
}
return OK;
}

View file

@ -1,119 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_uninit.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <unistd.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_uninit
*
* Description:
* Releases any resources committed by elf_init(). This essentially
* undoes the actions of elf_init.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_uninit(struct elf_loadinfo_s *loadinfo)
{
/* Free all working buffers */
elf_freebuffers(loadinfo);
/* Close the ELF file */
if (loadinfo->file.f_inode)
{
file_close(&loadinfo->file);
}
return OK;
}
/****************************************************************************
* Name: elf_freebuffers
*
* Description:
* Release all working buffers.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
****************************************************************************/
int elf_freebuffers(FAR struct elf_loadinfo_s *loadinfo)
{
/* Release all working allocations */
if (loadinfo->phdr)
{
kmm_free((FAR void *)loadinfo->phdr);
loadinfo->phdr = NULL;
}
if (loadinfo->shdr)
{
kmm_free(loadinfo->shdr);
loadinfo->shdr = NULL;
}
if (loadinfo->iobuffer)
{
kmm_free(loadinfo->iobuffer);
loadinfo->iobuffer = NULL;
loadinfo->buflen = 0;
}
return OK;
}

View file

@ -1,102 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_unload.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/elf.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_unload
*
* Description:
* This function unloads the object from memory. This essentially undoes
* the actions of elf_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 elf_unload(FAR struct elf_loadinfo_s *loadinfo)
{
/* Free all working buffers */
elf_freebuffers(loadinfo);
/* Release memory holding the relocated ELF image */
elf_addrenv_free(loadinfo);
/* Release memory used to hold static constructors and destructors */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
# ifndef CONFIG_ARCH_ADDRENV
if (loadinfo->ctoralloc != 0)
{
kumm_free(loadinfo->ctoralloc);
}
if (loadinfo->dtoralloc != 0)
{
kumm_free(loadinfo->dtoralloc);
}
# endif
loadinfo->ctoralloc = NULL;
loadinfo->ctors = NULL;
loadinfo->nctors = 0;
loadinfo->dtoralloc = NULL;
loadinfo->dtors = NULL;
loadinfo->ndtors = 0;
#endif
return OK;
}

View file

@ -1,109 +0,0 @@
/****************************************************************************
* binfmt/libelf/libelf_verify.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <string.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/elf.h>
#include <nuttx/binfmt/elf.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
static const char g_elfmagic[EI_MAGIC_SIZE] = EI_MAGIC;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_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 elf_verifyheader(FAR const Elf_Ehdr *ehdr)
{
if (!ehdr)
{
berr("NULL ELF header!");
return -ENOEXEC;
}
/* Verify that the magic number indicates an ELF file */
if (memcmp(ehdr->e_ident, g_elfmagic, EI_MAGIC_SIZE) != 0)
{
binfo("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 && ehdr->e_type != ET_EXEC)
{
berr("Not a relocatable or executable file: e_type=%d\n",
ehdr->e_type);
return -EINVAL;
}
/* Verify that this file works with the currently configured architecture */
if (!up_checkarch(ehdr))
{
berr("Not a supported architecture\n");
return -ENOEXEC;
}
/* Looks good so far... we still might find some problems later. */
return OK;
}

View file

@ -54,4 +54,4 @@ LDNXFLATFLAGS = -e main -s 2048
# ELF module definitions # ELF module definitions
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)

View file

@ -42,4 +42,4 @@ LDNXFLATFLAGS = -e main -s 2048
# ELF module definitions # ELF module definitions
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)

View file

@ -53,4 +53,4 @@ CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs
CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)

View file

@ -280,7 +280,7 @@ ifeq ($(CONFIG_LIBC_ARCH_ELF_64BIT),y)
endif endif
LDELFFLAGS = -r -e main --gc-sections LDELFFLAGS = -r -e main --gc-sections
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld)
ifeq ($(CONFIG_HOST_MACOS),y) ifeq ($(CONFIG_HOST_MACOS),y)
LDFLAGS += -Wl,-dead_strip LDFLAGS += -Wl,-dead_strip

View file

@ -188,7 +188,7 @@ APPLD=gnu-elf.ld
if [ -f "${BOARDDIR}/scripts/${APPLD}" ]; then if [ -f "${BOARDDIR}/scripts/${APPLD}" ]; then
cp -f "${BOARDDIR}/scripts/${APPLD}" "${EXPORTDIR}/scripts/." cp -f "${BOARDDIR}/scripts/${APPLD}" "${EXPORTDIR}/scripts/."
else else
cp -f "${TOPDIR}/binfmt/libelf/${APPLD}" "${EXPORTDIR}/scripts/." cp -f "${TOPDIR}/libs/libc/modlib/${APPLD}" "${EXPORTDIR}/scripts/."
fi fi
if [ "${NUTTX_BUILD}" = "kernel" ]; then if [ "${NUTTX_BUILD}" = "kernel" ]; then