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:
parent
1fc2cd7816
commit
e5f9b42ea0
45 changed files with 96 additions and 4148 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
71
arch/x86/src/common/Toolchain.defs
Normal file
71
arch/x86/src/common/Toolchain.defs
Normal 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)
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
|
@ -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.
|
|
|
@ -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
|
|
|
@ -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) }
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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 */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue