First rough port of XFLAT tools
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1903 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
79fda86ba3
commit
b45b663f53
|
@ -49,3 +49,5 @@ buildroot-0.1.7 2009-xx-xx <spudmonkey@racsa.co.cr>
|
|||
|
||||
* configs/avr-defconfig-4.3.3: Added support for AVR to support a NuttX
|
||||
port of the ATmega128.
|
||||
* toolchain/nxflat: Added logic to build NuttX NXFLAT binding support tools
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ config BR2_STAGING_DIR
|
|||
|
||||
config BR2_NUTTX_DIR
|
||||
string "Path to the NuttX root directory"
|
||||
default "$(TOPDIR)/nuttx"
|
||||
default "../nuttx"
|
||||
help
|
||||
This is the location where the NuttX source tree is located.
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ cc-option = $(shell if $(TARGET_CC) $(TARGET_CFLAGS) $(1) -S -o /dev/null -xc /d
|
|||
# along with the packages to build for the target.
|
||||
#
|
||||
##############################################################
|
||||
TARGETS:=uclibc-configured binutils gcc uclibc-target-utils
|
||||
TARGETS:=binutils
|
||||
include toolchain/Makefile.in
|
||||
include package/Makefile.in
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
BR2_GCC_VERSION_3_4_6=y
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -96,6 +97,11 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
# BR2_PACKAGE_NXFLAT is not set
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -80,6 +80,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
BR2_GCC_VERSION_4_2_4=y
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -99,6 +100,11 @@ BR2_INSTALL_LIBSTDCPP=y
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
# BR2_PACKAGE_NXFLAT is not set
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -80,6 +80,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
BR2_GCC_VERSION_4_2_4=y
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -99,6 +100,11 @@ BR2_INSTALL_LIBSTDCPP=y
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
# BR2_PACKAGE_NXFLAT is not set
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -80,6 +80,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
BR2_GCC_VERSION_4_3_3=y
|
||||
|
@ -99,6 +100,11 @@ BR2_INSTALL_LIBSTDCPP=y
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
# BR2_PACKAGE_NXFLAT is not set
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -80,6 +80,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
BR2_GCC_VERSION_4_2_4=y
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -99,6 +100,11 @@ BR2_INSTALL_LIBSTDCPP=y
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
# BR2_PACKAGE_NXFLAT is not set
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -60,6 +60,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
BR2_GCC_VERSION_4_3_3=y
|
||||
|
@ -79,6 +80,10 @@ BR2_INSTALL_LIBSTDCPP=y
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -60,6 +60,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
BR2_GCC_VERSION_4_2_4=y
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -78,6 +79,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -80,6 +80,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
BR2_GCC_VERSION_4_3_3=y
|
||||
|
@ -99,6 +100,11 @@ BR2_INSTALL_LIBSTDCPP=y
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
# BR2_PACKAGE_NXFLAT is not set
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
#
|
||||
BR2_HAVE_DOT_CONFIG=y
|
||||
# BR2_alpha is not set
|
||||
BR2_arm=y
|
||||
# BR2_armeb is not set
|
||||
# BR2_avr is not set
|
||||
# BR2_avr32 is not set
|
||||
# BR2_bfin is not set
|
||||
# BR2_cris is not set
|
||||
# BR2_i386 is not set
|
||||
# BR2_m32c is not set
|
||||
# BR2_m68k is not set
|
||||
# BR2_m68hc11 is not set
|
||||
# BR2_m68hc12 is not set
|
||||
# BR2_mips is not set
|
||||
# BR2_mipsel is not set
|
||||
# BR2_nios2 is not set
|
||||
# BR2_powerpc is not set
|
||||
# BR2_sh is not set
|
||||
# BR2_sh64 is not set
|
||||
# BR2_h8300 is not set
|
||||
# BR2_sparc is not set
|
||||
# BR2_x86_64 is not set
|
||||
# BR2_generic_arm is not set
|
||||
# BR2_arm610 is not set
|
||||
# BR2_arm7tdmi is not set
|
||||
# BR2_arm710 is not set
|
||||
# BR2_arm720t is not set
|
||||
# BR2_arm740t is not set
|
||||
# BR2_arm920t is not set
|
||||
# BR2_arm922t is not set
|
||||
# BR2_arm926t is not set
|
||||
# BR2_arm1136jf_s is not set
|
||||
BR2_cortex_m3=y
|
||||
# BR2_sa110 is not set
|
||||
# BR2_sa1100 is not set
|
||||
# BR2_xscale is not set
|
||||
# BR2_iwmmxt is not set
|
||||
BR2_ARM_OABI=y
|
||||
# BR2_ARM_EABI is not set
|
||||
BR2_ARCH="arm"
|
||||
BR2_GCC_TARGET_TUNE="cortex-m3"
|
||||
BR2_GCC_TARGET_ARCH="armv7-m"
|
||||
BR2_GCC_TARGET_ABI="apcs-gnu"
|
||||
BR2_ENDIAN="LITTLE"
|
||||
|
||||
#
|
||||
# Build options
|
||||
#
|
||||
BR2_WGET="wget --passive-ftp"
|
||||
BR2_SVN="svn co"
|
||||
BR2_ZCAT="zcat"
|
||||
BR2_BZCAT="bzcat"
|
||||
BR2_TAR_OPTIONS=""
|
||||
BR2_DL_DIR="$(BASE_DIR)/../archives"
|
||||
BR2_STAGING_DIR="$(BUILD_DIR)/staging_dir"
|
||||
BR2_NUTTX_DIR="$(TOPDIR)/../nuttx"
|
||||
BR2_TOPDIR_PREFIX=""
|
||||
BR2_TOPDIR_SUFFIX=""
|
||||
BR2_GNU_BUILD_SUFFIX="arm-elf"
|
||||
BR2_GNU_TARGET_SUFFIX="elf"
|
||||
# BR2_PREFER_IMA is not set
|
||||
# BR2_DEPRECATED is not set
|
||||
|
||||
#
|
||||
# Toolchain Options
|
||||
#
|
||||
|
||||
#
|
||||
# Binutils Options
|
||||
#
|
||||
# BR2_BINUTILS_VERSION_2_17 is not set
|
||||
# BR2_BINUTILS_VERSION_2_19 is not set
|
||||
BR2_BINUTILS_VERSION_2_19_1=y
|
||||
BR2_BINUTILS_VERSION="2.19.1"
|
||||
BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
||||
|
||||
#
|
||||
# GCC Options
|
||||
#
|
||||
# BR2_PACKAGE_GCC is not set
|
||||
# BR2_GCC_SUPPORTS_SYSROOT is not set
|
||||
|
||||
#
|
||||
# Gdb Options
|
||||
#
|
||||
# BR2_PACKAGE_GDB is not set
|
||||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
BR2_PACKAGE_NXFLAT=y
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
# BR2_PACKAGE_SSTRIP_TARGET is not set
|
||||
# BR2_PACKAGE_SSTRIP_HOST is not set
|
||||
# BR2_ENABLE_MULTILIB is not set
|
||||
BR2_LARGEFILE=y
|
||||
BR2_SOFT_FLOAT=y
|
||||
BR2_TARGET_OPTIMIZATION="-Os -pipe"
|
|
@ -60,6 +60,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
BR2_GCC_VERSION_3_4_6=y
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -78,6 +79,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -60,6 +60,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
# BR2_GCC_VERSION_3_4_6 is not set
|
||||
BR2_GCC_VERSION_4_2_4=y
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -78,6 +79,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -60,6 +60,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
BR2_GCC_VERSION_3_4_6=y
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -78,6 +79,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -60,6 +60,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
BR2_GCC_VERSION_3_4_6=y
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -78,6 +79,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -67,6 +67,7 @@ BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
|
|||
#
|
||||
# GCC Options
|
||||
#
|
||||
BR2_PACKAGE_GCC=y
|
||||
BR2_GCC_VERSION_3_4_6=y
|
||||
# BR2_GCC_VERSION_4_2_4 is not set
|
||||
# BR2_GCC_VERSION_4_3_3 is not set
|
||||
|
@ -85,6 +86,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
|
|||
# BR2_PACKAGE_GDB_SERVER is not set
|
||||
# BR2_PACKAGE_GDB_HOST is not set
|
||||
|
||||
#
|
||||
# NuttX Binary Support
|
||||
#
|
||||
|
||||
#
|
||||
# Common Toolchain Options
|
||||
#
|
||||
|
|
|
@ -17,7 +17,6 @@ BZCAT:=$(strip $(subst ",, $(BR2_BZCAT)))
|
|||
TAR_OPTIONS=$(subst ",, $(BR2_TAR_OPTIONS)) -xf
|
||||
#")
|
||||
|
||||
|
||||
TARGET_CFLAGS=$(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING)
|
||||
HOSTCC:=gcc
|
||||
HOSTCXX:=g++
|
||||
|
|
|
@ -5,6 +5,7 @@ menu "Toolchain Options"
|
|||
source "toolchain/binutils/Config.in"
|
||||
source "toolchain/gcc/Config.in"
|
||||
source "toolchain/gdb/Config.in"
|
||||
source "toolchain/nxflat/Config.in"
|
||||
|
||||
comment "Common Toolchain Options"
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ $(BINUTILS_DIR1)/binutils/objdump: $(BINUTILS_DIR1)/.configured
|
|||
$(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/bin/ld: $(BINUTILS_DIR1)/binutils/objdump
|
||||
$(MAKE) -C $(BINUTILS_DIR1) install
|
||||
|
||||
binutils: dependencies uclibc-configured $(BINUTILS_HOST_PREREQ) $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/bin/ld
|
||||
binutils: dependencies $(BINUTILS_HOST_PREREQ) $(STAGING_DIR)/$(REAL_GNU_TARGET_NAME)/bin/ld
|
||||
|
||||
binutils-source: $(DL_DIR)/$(BINUTILS_SOURCE)
|
||||
|
||||
|
|
|
@ -2,11 +2,18 @@
|
|||
|
||||
comment "GCC Options"
|
||||
|
||||
config BR2_PACKAGE_GCC
|
||||
bool "Build GCC cross-compiler"
|
||||
default n
|
||||
help
|
||||
Build the GCC cross-compiler for the target architecture.
|
||||
|
||||
choice
|
||||
prompt "GCC compiler Version"
|
||||
default BR2_GCC_VERSION_4_3_3 if BR2_cortex_m3
|
||||
default BR2_GCC_VERSION_4_2_4 if !BR2_avr32 && !BR2_cortex_m3
|
||||
default BR2_GCC_VERSION_3_4_6 if BR2_avr32 && !BR2_cortex_m3
|
||||
depends on BR2_PACKAGE_GCC
|
||||
help
|
||||
Select the version of gcc you wish to use.
|
||||
|
||||
|
@ -39,6 +46,7 @@ config BR2_GCC_VERSION
|
|||
config BR2_GCC_USE_SJLJ_EXCEPTIONS
|
||||
bool "Enable setjmp/longjmp exceptions?"
|
||||
default n
|
||||
depends on BR2_PACKAGE_GCC
|
||||
help
|
||||
For some platforms, proper stack unwinding works perfectly,
|
||||
while other platforms must use setjmp/longjmp exceptions for
|
||||
|
@ -47,12 +55,14 @@ config BR2_GCC_USE_SJLJ_EXCEPTIONS
|
|||
|
||||
config BR2_EXTRA_GCC_CONFIG_OPTIONS
|
||||
string "Additional gcc options"
|
||||
depends on BR2_PACKAGE_GCC
|
||||
default ""
|
||||
help
|
||||
Any additional gcc configure options you may want to include....
|
||||
|
||||
config BR2_INSTALL_LIBSTDCPP
|
||||
bool "Build C++ compiler?"
|
||||
depends on BR2_PACKAGE_GCC
|
||||
default n
|
||||
# >= 4.2.0 work fine without LARGEFILE
|
||||
select BR2_LARGEFILE if !BR2_GCC_SUPPORTS_SYSROOT
|
||||
|
@ -62,21 +72,21 @@ config BR2_INSTALL_LIBSTDCPP
|
|||
config BR2_INSTALL_LIBGCJ
|
||||
bool "Build/install java compiler and libgcj?"
|
||||
default n
|
||||
depends on !BR2_avr32 && BR2_INSTALL_LIBSTDCPP
|
||||
depends on BR2_PACKAGE_GCC && !BR2_avr32 && BR2_INSTALL_LIBSTDCPP
|
||||
help
|
||||
Build/install java compiler and libgcj?
|
||||
|
||||
config BR2_INSTALL_OBJC
|
||||
bool "Build/install Objective-C compiler and runtime?"
|
||||
default n
|
||||
depends on !BR2_avr32
|
||||
depends on BR2_PACKAGE_GCC && !BR2_avr32
|
||||
help
|
||||
Build/install Objective-C compiler and runtime?
|
||||
|
||||
config BR2_INSTALL_FORTRAN
|
||||
bool "Build/install Fortran compiler and runtime?"
|
||||
default n
|
||||
depends on !BR2_avr32
|
||||
depends on BR2_PACKAGE_GCC && !BR2_avr32
|
||||
help
|
||||
Build/install Fortran compiler and runtime?
|
||||
Note that it is highly recommended NOT to use gfortran
|
||||
|
|
|
@ -220,4 +220,7 @@ gcc-clean:
|
|||
gcc-dirclean:
|
||||
rm -rf $(GCC_BUILD_DIR)
|
||||
|
||||
ifeq ($(strip $(BR2_PACKAGE_GCC)),y)
|
||||
TARGETS += gcc
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -200,4 +200,7 @@ gcc-clean:
|
|||
gcc-dirclean:
|
||||
rm -rf $(GCC_BUILD_DIR)
|
||||
|
||||
ifeq ($(strip $(BR2_PACKAGE_GCC)),y)
|
||||
TARGETS += gcc
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
comment "NuttX Binary Support"
|
||||
|
||||
config BR2_PACKAGE_NXFLAT
|
||||
bool "Build NXFLAT tools"
|
||||
default n
|
||||
depends on BR2_arm
|
||||
help
|
||||
Build tools need to build NuttX NXFLAT load-able binary
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
############################################################################
|
||||
# toolchain/nxflat/Makefile
|
||||
#
|
||||
# Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
CFLAGS += -Wall -I. -I$(BINUTILS_DIR)/bfd
|
||||
LDFLAGS += -L$(BINUTILS_DIR)/bfd -L$(BINUTILS_DIR)/libiberty
|
||||
LIBS = -lbfd -liberty -lz
|
||||
|
||||
LDNXFLAT_OBJS = ldnxflat.o
|
||||
MKNXFLAT_OBJS = mknxflat.o
|
||||
READNXFLAT_OBJS = readxflat.o
|
||||
OBJS = $(LDNXFLAT_OBJS) $(MKNXFLAT_OBJS) $(READNXFLAT_OBJS)
|
||||
|
||||
BIN = ldnxflat mknxflat readnxflat
|
||||
|
||||
GXX_VERSION = ${shell $(ARCHCXX) -dumpversion | cut -d. -f1}
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(OBJS): %.o: %.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
arch:
|
||||
@ln -sf $(ARCH) arch
|
||||
|
||||
ldnxflat: arch $(LDNXFLAT_OBJS)
|
||||
$(CC) $(LDFLAGS) $(LDNXFLAT_OBJS) -o $@ $(LIBS)
|
||||
|
||||
mknxflat: arch $(MKNXFLAT_OBJS)
|
||||
$(CC) $(LDFLAGS) $(MKNXFLAT_OBJS) -o $@ $(LIBS)
|
||||
|
||||
arch/libarch.a:
|
||||
$(MAKE) -C arch CC="$(CC)"
|
||||
|
||||
readnxflat: arch $(READNXFLAT_OBJS) arch/libarch.a
|
||||
$(CC) $(LDFLAGS) -L arch -o $@ $(READNXFLAT_OBJS) $(LIBS) -larch
|
||||
|
||||
# Housekeeping
|
||||
|
||||
clean:
|
||||
-$(MAKE) -C arch clean
|
||||
rm -f *.o $(BIN) arch *~ .*.swp
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
############################################################################
|
||||
# toolchain/nxflat/arm/Makefile
|
||||
#
|
||||
# Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
CFLAGS += -Wall
|
||||
BIN = libarch.a
|
||||
OBJS = disarm.o
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(OBJS): %.o: %.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(AR) rcs $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *~ .*.swp core
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/***********************************************************************
|
||||
* xflat/tools/arm/arm.h
|
||||
* ARM ELF support for BFD.
|
||||
*
|
||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Derived from XFLAT:
|
||||
*
|
||||
* Copyright (c) 2006, Cadenux, LLC. All rights reserved.
|
||||
* Copyright (c) 2006, Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Which simply lifted it from the BFD:
|
||||
*
|
||||
* Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* This file is part of BFD, the Binary File Descriptor library.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _ELF_ARM_H
|
||||
#define _ELF_ARM_H
|
||||
|
||||
#include "reloc-macros.h"
|
||||
|
||||
/* Processor specific flags for the ELF header e_flags field. */
|
||||
#define EF_ARM_RELEXEC 0x01
|
||||
#define EF_ARM_HASENTRY 0x02
|
||||
#define EF_INTERWORK 0x04
|
||||
#define EF_APCS_26 0x08
|
||||
#define EF_APCS_FLOAT 0x10
|
||||
#define EF_PIC 0x20
|
||||
#define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */
|
||||
#define EF_NEW_ABI 0x80
|
||||
#define EF_OLD_ABI 0x100
|
||||
#define EF_SOFT_FLOAT 0x200
|
||||
#define EF_VFP_FLOAT 0x400
|
||||
|
||||
/* Other constants defined in the ARM ELF spec. version B-01. */
|
||||
#define EF_SYMSARESORTED 0x04 /* NB conflicts with EF_INTERWORK */
|
||||
#define EF_DYNSYMSUSESEGIDX 0x08 /* NB conflicts with EF_APCS26 */
|
||||
#define EF_MAPSYMSFIRST 0x10 /* NB conflicts with EF_APCS_FLOAT */
|
||||
#define EF_EABIMASK 0xFF000000
|
||||
|
||||
#define EF_EABI_VERSION(flags) ((flags) & EF_EABIMASK)
|
||||
#define EF_EABI_UNKNOWN 0x00000000
|
||||
#define EF_EABI_VER1 0x01000000
|
||||
#define EF_EABI_VER2 0x02000000
|
||||
|
||||
/* Local aliases for some flags to match names used by COFF port. */
|
||||
#define F_INTERWORK EF_INTERWORK
|
||||
#define F_APCS26 EF_APCS_26
|
||||
#define F_APCS_FLOAT EF_APCS_FLOAT
|
||||
#define F_PIC EF_PIC
|
||||
#define F_SOFT_FLOAT EF_SOFT_FLOAT
|
||||
#define F_VFP_FLOAT EF_VFP_FLOAT
|
||||
|
||||
/* Additional symbol types for Thumb */
|
||||
#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */
|
||||
#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */
|
||||
|
||||
/* ARM-specific values for sh_flags */
|
||||
#define SHF_ENTRYSECT 0x10000000 /* Section contains an entry point. */
|
||||
#define SHF_COMDEF 0x80000000 /* Section may be multiply defined in the input to a link step. */
|
||||
|
||||
/* ARM-specific program header flags. */
|
||||
#define PF_ARM_SB 0x10000000 /* Segment contains the location addressed by the static base. */
|
||||
#define PF_ARM_PI 0x20000000 /* Segment is position-independent. */
|
||||
#define PF_ARM_ABS 0x40000000 /* Segment must be loaded at its base address. */
|
||||
|
||||
/* Relocation types. */
|
||||
|
||||
START_RELOC_NUMBERS (elf_arm_reloc_type)
|
||||
RELOC_NUMBER (R_ARM_NONE, 0)
|
||||
RELOC_NUMBER (R_ARM_PC24, 1)
|
||||
RELOC_NUMBER (R_ARM_ABS32, 2)
|
||||
RELOC_NUMBER (R_ARM_REL32, 3)
|
||||
#ifdef OLD_ARM_ABI
|
||||
RELOC_NUMBER (R_ARM_ABS8, 4)
|
||||
RELOC_NUMBER (R_ARM_ABS16, 5)
|
||||
RELOC_NUMBER (R_ARM_ABS12, 6)
|
||||
RELOC_NUMBER (R_ARM_THM_ABS5, 7)
|
||||
RELOC_NUMBER (R_ARM_THM_PC22, 8)
|
||||
RELOC_NUMBER (R_ARM_SBREL32, 9)
|
||||
RELOC_NUMBER (R_ARM_AMP_VCALL9, 10)
|
||||
RELOC_NUMBER (R_ARM_THM_PC11, 11) /* Cygnus extension to abi: Thumb unconditional branch. */
|
||||
RELOC_NUMBER (R_ARM_THM_PC9, 12) /* Cygnus extension to abi: Thumb conditional branch. */
|
||||
RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 13)
|
||||
RELOC_NUMBER (R_ARM_GNU_VTENTRY, 14)
|
||||
#else /* not OLD_ARM_ABI */
|
||||
RELOC_NUMBER (R_ARM_PC13, 4)
|
||||
RELOC_NUMBER (R_ARM_ABS16, 5)
|
||||
RELOC_NUMBER (R_ARM_ABS12, 6)
|
||||
RELOC_NUMBER (R_ARM_THM_ABS5, 7)
|
||||
RELOC_NUMBER (R_ARM_ABS8, 8)
|
||||
RELOC_NUMBER (R_ARM_SBREL32, 9)
|
||||
RELOC_NUMBER (R_ARM_THM_PC22, 10)
|
||||
RELOC_NUMBER (R_ARM_THM_PC8, 11)
|
||||
RELOC_NUMBER (R_ARM_AMP_VCALL9, 12)
|
||||
RELOC_NUMBER (R_ARM_SWI24, 13)
|
||||
RELOC_NUMBER (R_ARM_THM_SWI8, 14)
|
||||
RELOC_NUMBER (R_ARM_XPC25, 15)
|
||||
RELOC_NUMBER (R_ARM_THM_XPC22, 16)
|
||||
#endif /* not OLD_ARM_ABI */
|
||||
RELOC_NUMBER (R_ARM_COPY, 20) /* Copy symbol at runtime. */
|
||||
RELOC_NUMBER (R_ARM_GLOB_DAT, 21) /* Create GOT entry. */
|
||||
RELOC_NUMBER (R_ARM_JUMP_SLOT, 22) /* Create PLT entry. */
|
||||
RELOC_NUMBER (R_ARM_RELATIVE, 23) /* Adjust by program base. */
|
||||
RELOC_NUMBER (R_ARM_GOTOFF, 24) /* 32 bit offset to GOT. */
|
||||
RELOC_NUMBER (R_ARM_GOTPC, 25) /* 32 bit PC relative offset to GOT. */
|
||||
RELOC_NUMBER (R_ARM_GOT32, 26) /* 32 bit GOT entry. */
|
||||
RELOC_NUMBER (R_ARM_PLT32, 27) /* 32 bit PLT address. */
|
||||
#ifdef OLD_ARM_ABI
|
||||
FAKE_RELOC (FIRST_INVALID_RELOC, 28)
|
||||
FAKE_RELOC (LAST_INVALID_RELOC, 249)
|
||||
#else /* not OLD_ARM_ABI */
|
||||
FAKE_RELOC (FIRST_INVALID_RELOC1, 28)
|
||||
FAKE_RELOC (LAST_INVALID_RELOC1, 31)
|
||||
RELOC_NUMBER (R_ARM_ALU_PCREL7_0, 32)
|
||||
RELOC_NUMBER (R_ARM_ALU_PCREL15_8, 33)
|
||||
RELOC_NUMBER (R_ARM_ALU_PCREL23_15, 34)
|
||||
RELOC_NUMBER (R_ARM_LDR_SBREL11_0, 35)
|
||||
RELOC_NUMBER (R_ARM_ALU_SBREL19_12, 36)
|
||||
RELOC_NUMBER (R_ARM_ALU_SBREL27_20, 37)
|
||||
FAKE_RELOC (FIRST_INVALID_RELOC2, 38)
|
||||
FAKE_RELOC (LAST_INVALID_RELOC2, 99)
|
||||
RELOC_NUMBER (R_ARM_GNU_VTENTRY, 100)
|
||||
RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 101)
|
||||
RELOC_NUMBER (R_ARM_THM_PC11, 102) /* Cygnus extension to abi: Thumb unconditional branch. */
|
||||
RELOC_NUMBER (R_ARM_THM_PC9, 103) /* Cygnus extension to abi: Thumb conditional branch. */
|
||||
FAKE_RELOC (FIRST_INVALID_RELOC3, 104)
|
||||
FAKE_RELOC (LAST_INVALID_RELOC3, 248)
|
||||
RELOC_NUMBER (R_ARM_RXPC25, 249)
|
||||
#endif /* not OLD_ARM_ABI */
|
||||
RELOC_NUMBER (R_ARM_RSBREL32, 250)
|
||||
RELOC_NUMBER (R_ARM_THM_RPC22, 251)
|
||||
RELOC_NUMBER (R_ARM_RREL32, 252)
|
||||
RELOC_NUMBER (R_ARM_RABS32, 253)
|
||||
RELOC_NUMBER (R_ARM_RPC24, 254)
|
||||
RELOC_NUMBER (R_ARM_RBASE, 255)
|
||||
END_RELOC_NUMBERS
|
||||
|
||||
#endif /* _ELF_ARM_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,728 @@
|
|||
/***********************************************************************
|
||||
* toolchain/nxflat/arm/dyncall_skeleton.def
|
||||
*
|
||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
/*******************************************************************
|
||||
* File Prologue
|
||||
*******************************************************************/
|
||||
|
||||
static const char file_prologue[] =
|
||||
"/*******************************************************************\n"
|
||||
" *\n"
|
||||
" * This file contains the dynamic call logic that performs the thunk\n"
|
||||
" * for outound calls from one module to another.\n"
|
||||
" *\n"
|
||||
" * ARM register quick reference:\n"
|
||||
" *\n"
|
||||
" * Name Number ARM Procedure Calling Standard Role\n"
|
||||
" *\n"
|
||||
" * a1 r0 argument 1/integer result/scratch register/argc\n"
|
||||
" * a2 r1 argument 2/scratch register/argv\n"
|
||||
" * a3 r2 argument 3/scratch register/envp\n"
|
||||
" * a4 r3 argument 4/scratch register\n"
|
||||
" * v1 r4 register variable\n"
|
||||
" * v2 r5 register variable\n"
|
||||
" * v3 r6 register variable\n"
|
||||
" * v4 r7 register variable\n"
|
||||
" * v5 r8 register variable\n"
|
||||
" * sb/v6 r9 static base/register variable\n"
|
||||
" * sl/v7 r10 stack limit/stack chunk handle/reg. variable\n"
|
||||
" * fp r11 frame pointer\n"
|
||||
" * ip r12 scratch register/new-sb in inter-link-unit calls\n"
|
||||
" * sp r13 lower end of current stack frame\n"
|
||||
" * lr r14 link address/scratch register\n"
|
||||
" * pc r15 program counter\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"/*******************************************************************\n"
|
||||
" * Included Files\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"/*******************************************************************\n"
|
||||
" * Definitions\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"/* Register definitions */\n\n"
|
||||
"#define PIC_REG r10\t/* The PIC base register */\n"
|
||||
"#define RINFO r4\t/* Pointer to dyninfo structure */\n"
|
||||
"#define MYPIC r5\t/* Saved PIC base register value */\n"
|
||||
"#define FRAME r6\t/* Current state save frame */\n"
|
||||
"#define SAVEREG1 r4\t/* First pushed register */\n"
|
||||
"#define SAVEREG2 r7\t/* Last pushed register */\n"
|
||||
"#define TMP3 r5\t/* Careful, overlaps MYPIC */\n"
|
||||
"#define WORK r7\t/* Safe to used */\n"
|
||||
"#define TMP1 ip\n"
|
||||
"#define TMP2 lr\n\n"
|
||||
"/* This is the EXIT software interrupt code. */\n\n"
|
||||
"#define DFR_EXIT_SWINO 0x900001\n";
|
||||
|
||||
#ifdef CONFIG_ARCH_DSC25
|
||||
static const char dyntrace_enable[] =
|
||||
"\n/* Conditional Compilation */\n\n"
|
||||
"#define __DYNTRACE 1\n"
|
||||
"#define __DYNTRACE_USE_HARDWARE 1\n"
|
||||
"#define __DYNTRACE_CONFIG_DSC25 1\n";
|
||||
#else
|
||||
static const char dyntrace_enable[] =
|
||||
"\n/* Conditional Compilation */\n\n"
|
||||
"#define __DYNTRACE 1\n";
|
||||
#endif
|
||||
|
||||
static const char import_prologue[] =
|
||||
"\n/* This is an assembly language representation of the\n"
|
||||
" * struct nxflat_import_s structure:\n"
|
||||
" */\n\n"
|
||||
"#define RINFO_FCNNAME 0\t/* Offset to the function name */\n"
|
||||
"#define RINFO_FCNADDR 4\t/* Offset to the function address */\n"
|
||||
"#define RINFO_PICBASE 8\t/* Offset to the PIC base value */\n\n"
|
||||
"/* The common dynamic call logic receives the following C stack frame.\n"
|
||||
" * NOTE: The number of registers should be SAVEREG2-SAVEREG1+2.\n"
|
||||
" */\n\n"
|
||||
"#define SP_OFFSET_CREG1 0\n"
|
||||
"#define SP_OFFSET_CREG2 4\n"
|
||||
"#define SP_OFFSET_CREG3 8\n"
|
||||
"#define SP_OFFSET_CREG4 12\n"
|
||||
"#define SP_OFFSET_CREG5 16\n"
|
||||
"#define SP_FRAME_SIZE 20\n\n"
|
||||
"/* The common dynamic call logic will create the following dynamic\n"
|
||||
" * frame:\n"
|
||||
" */\n\n"
|
||||
"#define DFR_OFFSET_ALLOCATED 0\n"
|
||||
"#define DFR_OFFSET_REFCOUNT 1\n"
|
||||
"#define DFR_OFFSET_UNUSED1 2\n"
|
||||
"#define DFR_OFFSET_UNUSED2 3\n"
|
||||
"#define DFR_OFFSET_CREG1 4\n"
|
||||
"#define DFR_OFFSET_CREG2 8\n"
|
||||
"#define DFR_OFFSET_CREG3 12\n"
|
||||
"#define DFR_OFFSET_CREG4 16\n"
|
||||
"#define DFR_OFFSET_CREG5 20\n\n"
|
||||
"#define DFR_FRAME_SIZE_BYTES 24\n"
|
||||
"#define DFR_FRAME_SIZE_WORDS (DFR_FRAME_SIZE_BYTES >> 2)\n\n"
|
||||
"/* These definitions determine that memory that will be set aside\n"
|
||||
" * for frame storage:\n"
|
||||
" */\n";
|
||||
|
||||
static const char import_frame_size[] =
|
||||
"\n#define DFR_NUM_FRAMES %d\n"
|
||||
"#define DFR_FRAME_ALLOC_BYTES (DFR_FRAME_SIZE_BYTES*DFR_NUM_FRAMES)\n"
|
||||
"#define DFR_FRAME_ALLOC_WORDS (DFR_FRAME_ALLOC_BYTES >> 2)\n";
|
||||
|
||||
static const char dynamic_frames[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" * The Dynamic Frame Storage\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"/* This defines an array of state save frames the will used by the\n"
|
||||
" * dynamic call logic to hold information needed to manage a \"thunk.\"\n"
|
||||
" */\n\n"
|
||||
"\t.bss\n"
|
||||
"\t.align\t2\n"
|
||||
"\t.local\t__dynframes\n"
|
||||
"\t.type\t__dynframes, object\n"
|
||||
"__dynframes:\n"
|
||||
"\t.fill\tDFR_FRAME_ALLOC_WORDS, 4, 0\n"
|
||||
"\t.size\t__dynframes, .-__dynframes\n";
|
||||
|
||||
static const char nonreturning_dynamic_frame[] =
|
||||
"\n/* This defines a special storage location for functions that don't\n"
|
||||
" * (normally) return. It is kept separate from other frames to prevent\n"
|
||||
" * overwriting; this storage only exists in case the function does\n"
|
||||
" * return (which can happen on an error condition).\n"
|
||||
" */\n\n"
|
||||
"\t.bss\n"
|
||||
"\t.align\t2\n"
|
||||
"\t.local\t__dynnrframe\n"
|
||||
"\t.type\t__dynnrframe, object\n"
|
||||
"__dynnrframe:\n"
|
||||
"\t.fill\tDFR_FRAME_SIZE_WORDS, 4, 0\n"
|
||||
"\t.size\t__dynnrframe, .-__dynnrframe\n";
|
||||
|
||||
/*******************************************************************
|
||||
* Import Function Name String Table
|
||||
*******************************************************************/
|
||||
|
||||
static const char import_name_strtab_prologue[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" * Import Function Names\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"/* These are the names of all of the functions that are imported.\n"
|
||||
" * Notice that all data associated with the library names is retained\n"
|
||||
" * in the .text section."
|
||||
" */\n\n"
|
||||
"\t.text\n"
|
||||
"\t.align\t0\n";
|
||||
|
||||
#define MKIMPSTRTABARG(fn,i) (i), (i), (i), (fn), (i), (i)
|
||||
|
||||
static const char import_name_strtab_format[] =
|
||||
"\n\t.local\t__dynimport%04d\n"
|
||||
"\t.type\t__dynimport%04d, object\n\n"
|
||||
"__dynimport%04d:\n"
|
||||
"\t.asciz\t\"%s\"\n"
|
||||
"\t.size\t__dynimport%04d, .-__dynimport%04d\n";
|
||||
|
||||
/*******************************************************************
|
||||
* Per Import Dyanamic Call Information
|
||||
*******************************************************************/
|
||||
|
||||
static const char dynimport_decl_prologue[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" * Imported Symbol Table (an array of type struct flat_import)\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"/* Notice that, unlike most other arrays in this file, this array\n"
|
||||
" * is declared to reside in .data. Because of this, there will be\n"
|
||||
" * per-process instances of this table.\n"
|
||||
" */\n\n"
|
||||
"\t.data\n"
|
||||
"\t.align\t2\n\n"
|
||||
"\t.global\t__dynimport_begin\n"
|
||||
"\t.type\t__dynimport_begin, object\n"
|
||||
"\t.global\t__dynimport_end\n"
|
||||
"\t.type\t__dynimport_end, object\n\n";
|
||||
|
||||
#define MKINFODECLARGS(fn, i) (i), (fn), (i)
|
||||
|
||||
static const char dynimport_decl_format[] =
|
||||
"\t.local\t__dyninfo%04d\t/* Dynamic info for imported symbol %s */\n"
|
||||
"\t.type\t__dyninfo%04d, object\n";
|
||||
|
||||
static const char dynimport_array_prologue[] =
|
||||
"\n__dynimport_begin:\n";
|
||||
|
||||
#define MKINFOARGS(fn, i) (i), (fn), (i), (i), (i)
|
||||
|
||||
static const char dynimport_array_format[] =
|
||||
"__dyninfo%04d:\t\t\t/* Dynamic info for imported symbol %s */\n"
|
||||
"\t.word\t__dynimport%04d\t/* Offset to name of imported function */\n"
|
||||
"\t.word\t0\t\t/* Resolved address of imported function */\n"
|
||||
"\t.word\t0\t\t/* Data segment address for imported func */\n"
|
||||
"\t.size\t__dyninfo%04d, .-__dyninfo%04d\n";
|
||||
|
||||
static const char dynimport_array_epilogue[] =
|
||||
"__dynimport_end:\n"
|
||||
"\t.size\t__dynimport_begin, __dynimport_end-__dynimport_begin\n";
|
||||
|
||||
static const char dyncall_decl_prologue[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" * Per Import Dynamic Call Logic\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"\t.text\n"
|
||||
"\t.align\t2\n";
|
||||
|
||||
#define MKCALLARGS(fn, i) (fn), (fn), (fn), (fn), (i), (fn), (fn)
|
||||
|
||||
static const char dyncall_format[] =
|
||||
"\n/* Dynamic call logic for imported symbol %s */\n\n"
|
||||
"\t.global\t%s\n"
|
||||
"\t.type\t%s, function\n\n"
|
||||
"%s:\n"
|
||||
"\tldr\tTMP1, =__dyninfo%04d\n"
|
||||
"\tb\t__dyncall1\n"
|
||||
"\t.size\t%s, .-%s\n";
|
||||
|
||||
static const char dyncall_format2[] =
|
||||
"\n/* Dynamic call logic for special imported symbol %s */\n\n"
|
||||
"\t.global\t%s\n"
|
||||
"\t.type\t%s, function\n\n"
|
||||
"%s:\n"
|
||||
"\tldr\tTMP1, =__dyninfo%04d\n"
|
||||
"\tb\t__dyncall2\n"
|
||||
"\t.size\t%s, .-%s\n";
|
||||
|
||||
static const char nonreturning_dyncall_format[] =
|
||||
"\n/* Dynamic call logic for imported, non-returning symbol %s */\n\n"
|
||||
"\t.global\t%s\n"
|
||||
"\t.type\t%s, function\n\n"
|
||||
"%s:\n"
|
||||
"\tldr\tTMP1, =__dyninfo%04d\n"
|
||||
"\tb\t__dynnoreturn\n"
|
||||
"\t.size\t%s, .-%s\n";
|
||||
|
||||
/*******************************************************************
|
||||
* Dynamic Call Trace Logic
|
||||
*******************************************************************/
|
||||
|
||||
static const char dyntrace_function[] =
|
||||
"\n/* This is constant data used to by the __dyntrace function */\n\n"
|
||||
"#ifdef __DYNTRACE\n\n"
|
||||
"\t.section\t.rodata\n\n"
|
||||
"# ifdef __DYNTRACE_USE_HARDWARE\n"
|
||||
"# define __DYNTRACE_LBRACE_SIZE 3\n"
|
||||
"# define __DYNTRACE_RBRACE_SIZE 3\n\n"
|
||||
"\t.local\t.LC_lbrace\n"
|
||||
"\t.type\t.LC_lbrace, object\n"
|
||||
"\t.size\t.LC_lbrace, __DYNTRACE_LBRACE_SIZE\n"
|
||||
".LC_lbrace:\n"
|
||||
"\t.ascii\t\"\\r\\n[\"\n\n"
|
||||
"\t.local\t.LC_rbrace\n"
|
||||
"\t.type\t.LC_rbrace, object\n"
|
||||
"\t.size\t.LC_rbrace, __DYNTRACE_RBRACE_SIZE\n"
|
||||
".LC_rbrace:\n"
|
||||
"\t.ascii\t\"]\\r\\n\"\n\n"
|
||||
"# else\n\n"
|
||||
"# define __DYNTRACE_LBRACE_SIZE 2\n"
|
||||
"# define __DYNTRACE_RBRACE_SIZE 2\n\n"
|
||||
"\t.local\t.LC_lbrace\n"
|
||||
"\t.type\t.LC_lbrace, object\n"
|
||||
"\t.size\t.LC_lbrace, __DYNTRACE_LBRACE_SIZE\n"
|
||||
".LC_lbrace:\n"
|
||||
"\t.ascii\t\"\\n[\"\n\n"
|
||||
"\t.local\t.LC_rbrace\n"
|
||||
"\t.type\t.LC_rbrace, object\n"
|
||||
"\t.size\t.LC_rbrace, __DYNTRACE_RBRACE_SIZE\n"
|
||||
".LC_rbrace:\n"
|
||||
"\t.ascii\t\"]\\n\"\n\n"
|
||||
"#endif /* __DYNTRACE_USE_HARDWARE */\n\n"
|
||||
"#define __DYNTRACE_EXITTING_SIZE 8\n"
|
||||
"\t.local\t.LC_exitting\n"
|
||||
"\t.type\t.LC_exitting, object\n"
|
||||
"\t.size\t.LC_exitting, __DYNTRACE_EXITTING_SIZE\n"
|
||||
".LC_exitting:\n"
|
||||
"\t.ascii\t\"ABORTING\"\n\n"
|
||||
"/* Macros to write trace information to the console/stderr\n"
|
||||
" *\n"
|
||||
" * r1 = write buffer address\n"
|
||||
" * r2 = write buffer size\n"
|
||||
" *\n"
|
||||
" * Will use all registers normally altered on a C subroutine call:\n"
|
||||
" * r0-r3, ip (r12), and lr (r14).\n"
|
||||
" */\n\n"
|
||||
"#ifdef __DYNTRACE_USE_HARDWARE\n"
|
||||
"\t/* These are the same macros that can be found in\n"
|
||||
"\t * linux/arch/armnommu/kernel/debug-armv.S for the 2.4 kernel\n"
|
||||
"\t */\n\n"
|
||||
"#ifdef __DYNTRACE_CONFIG_DSC25\n"
|
||||
"\t.macro\taddruart,rx\n"
|
||||
"\tldr\t\\rx, =0x00030300\t@ UART0 base\n"
|
||||
"\t.endm\n\n"
|
||||
"\t.macro\tsenduart,rd,rx\n"
|
||||
"\tstrh\t\\rd, [\\rx, #0x00]\t@ UARTx_DTRR Offset\n"
|
||||
"\t.endm\n\n"
|
||||
"\t.macro\twaituart,rd,rx\n"
|
||||
"1001:\tldrh\t\\rd, [\\rx, #0x0c]\t@ UARTx_SR Offset\n"
|
||||
"\ttst\t\\rd, #0x0400\t\t@ Check TX fifo ind.\n"
|
||||
"\tbeq\t1001b\t\t\t@ loop til 1=room in TX fifo\n"
|
||||
"\t.endm\n\n"
|
||||
"\t.macro\tbusyuart,rd,rx\n"
|
||||
"1002:\tldrh\t\\rd, [\\rx, #0x0c]\t@ UARTx_SR Offset\n"
|
||||
"\ttst\t\\rd, #0x0001\t\t@ Check TX empty bit\n"
|
||||
"\tbne\t1002b\t\t\t@ loop til 0=TX fifo empty\n"
|
||||
"\t.endm\n"
|
||||
"#else\n"
|
||||
"# error Unsupported architecture\n"
|
||||
"#endif\n"
|
||||
"\t.macro __dyntrace_write\n"
|
||||
"\tbl\t__dynwrite\n"
|
||||
"\t.endm\n\n"
|
||||
"/* Write directly to the uart hardware:\n"
|
||||
" * r1 = addr, r2 = number of bytes.\n"
|
||||
" */\n\n"
|
||||
"\t.text\n"
|
||||
"\t.align\t2\n"
|
||||
"\t.local\t__dynwrite\n"
|
||||
"\t.type\t__dynwrite, function\n"
|
||||
"__dynwrite:\n\n"
|
||||
"\taddruart r3\t\t\t@ Get the UART address\n"
|
||||
"1:\twaituart r0, r3\t\t\t@ Wait for UART available\n"
|
||||
"\tldrb\tr0, [r1], #1\t\t@ Fetch the next byte\n"
|
||||
"\tsenduart r0, r3\t\t\t@ Send the byte\n"
|
||||
"\tbusyuart r0, r3\t\t\t@ Wait for the byte to go\n"
|
||||
"\tsubs\tr2, r2, #1\t\t@ Decr # bytes sent\n"
|
||||
"\tbne\t1b\t\t\t@ Done?\n"
|
||||
"\tmov\tpc, lr\t\t\t@ Yes, Return\n"
|
||||
"#else\n"
|
||||
"/* This macro uses the write syscall to output trace information: */\n\n"
|
||||
"\t.macro __dyntrace_write\n"
|
||||
"\tmov\tr0, #1\n"
|
||||
"\tswi\t0x900004\n"
|
||||
"\t.endm\n"
|
||||
"#endif\n\n"
|
||||
"/* If enabled, the __dyntrace function will be called just before\n"
|
||||
" * each call into a shared library is performed. The __dyntrace\n"
|
||||
" * function will print the name of the called function on stderr\n"
|
||||
" * in the follow format: \\n[name]\\n. WARNING: This function uses\n"
|
||||
" * the write syscall directly!\n"
|
||||
" *\n"
|
||||
" * The following register state is assume on entry:\n"
|
||||
" * o WORK is available for use\n"
|
||||
" * o [PIC_REG] points to our data segment\n"
|
||||
" * o [RINFO] holds the offset to the info structure\n"
|
||||
" * [RINFO]+RINFO_FCNAME points to the symbol name.\n"
|
||||
" */\n\n"
|
||||
"\t.text\n"
|
||||
"\t.align\t2\n"
|
||||
"\t.local\t__dyntrace\n"
|
||||
"\t.type\t__dyntrace, function\n"
|
||||
"__dyntrace:\n\n"
|
||||
"\t/* Save all registers normally altered on a C subroutine call:\n"
|
||||
"\t * r0-r3, ip (r12), and lr (r14).\n"
|
||||
"\t */\n\n"
|
||||
"\tstmfd\tsp!, {r0-r3, ip, lr}\n\n"
|
||||
"\t/* Write the leading \"\\n[\" */\n\n"
|
||||
"\tldr\tr1, .Llbrace_addr\n"
|
||||
"\tadd\tr1, PIC_REG, r1\n"
|
||||
"\tmov\tr2, #__DYNTRACE_LBRACE_SIZE\n"
|
||||
"\t__dyntrace_write\n\n"
|
||||
"\t/* Determine the length of the name string */\n\n"
|
||||
"\tadd\tr3, PIC_REG, RINFO\n"
|
||||
"\tldr\tr1, [r3, #RINFO_FCNNAME]\n"
|
||||
"\tmov\tr2, #0\n"
|
||||
".Lstrlen_loop:\n"
|
||||
"\tldrb\tr0, [r1], #1\n"
|
||||
"\tcmp\tr0, #0\n"
|
||||
"\taddne\tr2, r2, #1\n"
|
||||
"\tbne\t.Lstrlen_loop\n\n"
|
||||
"\t/* Then write the name string */\n\n"
|
||||
"\tldr\tr1, [r3, #RINFO_FCNNAME]\n"
|
||||
"\t__dyntrace_write\n\n"
|
||||
"\t/* Write the trailing \"\\n[\" */\n\n"
|
||||
"\tldr\tr1, .Lrbrace_addr\n"
|
||||
"\tadd\tr1, PIC_REG, r1\n"
|
||||
"\tmov\tr2, #__DYNTRACE_LBRACE_SIZE\n"
|
||||
"\t__dyntrace_write\n\n"
|
||||
"\tldmfd\tsp!, {r0-r3, ip, pc}\n\n"
|
||||
"\t.align\t2\n"
|
||||
".Llbrace_addr:\n"
|
||||
"\t.word\t.LC_lbrace\n"
|
||||
".Lrbrace_addr:\n"
|
||||
"\t.word\t.LC_rbrace\n"
|
||||
"\t.size\t __dyntrace, .-__dyntrace\n"
|
||||
"#endif /* __DYNTRACE */\n";
|
||||
|
||||
/*******************************************************************
|
||||
* Common Dyanamic Call Information
|
||||
*******************************************************************/
|
||||
|
||||
static const char frame_macros[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" * Frame Management Macros\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"\t.macro\tget_frame, frame, refcount, tmp1, tmp2\n\n"
|
||||
"\t/* Get frame = first frame in the __dynframes list, and\n"
|
||||
"\t * tmp2 = the first address past the __dynframe list.\n"
|
||||
"\t */\n\n"
|
||||
"\tldr\t\\tmp2, =DFR_FRAME_ALLOC_BYTES\n"
|
||||
"\tldr\t\\tmp1, =__dynframes\n"
|
||||
"\tadd\t\\frame, PIC_REG, \\tmp1\n"
|
||||
"\tadd\t\\tmp2, \\tmp2, \\frame\n\n"
|
||||
"\t/* Loop until an unsused frame is found our until the\n"
|
||||
"\t * end of the __dynframes list is encountered. Normally,\n"
|
||||
"\t * this will be very fast -- because the first frame should\n"
|
||||
"\t * be available.\n"
|
||||
"\t */\n\n"
|
||||
"1:\n"
|
||||
"\tmov\t\\tmp1, #1\n"
|
||||
"\tswpb\t\\tmp1, \\tmp1, [\\frame]\n"
|
||||
"\tcmp\t\\tmp1, #0\n"
|
||||
"\tbeq\t2f\n\n"
|
||||
"\t/* Increment to the next frame in the list and check if this\n"
|
||||
"\t * next frame lies beyond the __dynframes list.\n"
|
||||
"\t */\n\n"
|
||||
"\tadd\t\\frame, \\frame, #DFR_FRAME_SIZE_BYTES\n"
|
||||
"\tcmp\t\\frame, \\tmp2\n"
|
||||
"\tbcc\t1b\n\n"
|
||||
"\t/* Failure! The list is full! We don't have many options\n"
|
||||
"\t * here so we will just exit with error number = 1.\n"
|
||||
"\t */\n\n"
|
||||
"#ifdef __DYNTRACE\n"
|
||||
"\tldr\tr1, =.LC_exitting\n"
|
||||
"\tmov\tr2, #__DYNTRACE_EXITTING_SIZE\n"
|
||||
"\t__dyntrace_write\n"
|
||||
"#endif\n\n"
|
||||
"\tmov\tr0, #1\n"
|
||||
"\tswi\tDFR_EXIT_SWINO\n\n"
|
||||
"\t/* Set the reference count on the frame and continue with\n"
|
||||
"\t * frame = the available frame */\n"
|
||||
"2:\n"
|
||||
"\tstrb\t\\refcount, [\\frame, #DFR_OFFSET_REFCOUNT]\n"
|
||||
"\t.endm\n\n"
|
||||
"\t.macro release_frame, frame, tmp1\n"
|
||||
"\tldrb\t\\tmp1, [\\frame, #DFR_OFFSET_REFCOUNT]\n"
|
||||
"\tcmp\t\\tmp1, #0\n"
|
||||
"\tsub\t\\tmp1, \\tmp1, #1\n"
|
||||
"\tble\t3f\n"
|
||||
"\tcmp\t\\tmp1, #0\n"
|
||||
"\tstrb\t\\tmp1, [\\frame, #DFR_OFFSET_REFCOUNT]\n"
|
||||
"\tstreqb\t\\tmp1, [\\frame, #DFR_OFFSET_ALLOCATED]\n"
|
||||
"3:\n"
|
||||
"\t.endm\n";
|
||||
|
||||
static const char nonreturning_frame_macros[] =
|
||||
"\t.macro\tget_nrframe, frame, refcount, tmp1, tmp2\n\n"
|
||||
"\tldr\t\\frame, =__dynnrframe\n"
|
||||
"\tadd\t\\frame, PIC_REG, \\frame\n"
|
||||
"\t.endm\n\n"
|
||||
"\t.macro release_nrframe, frame, tmp1\n"
|
||||
"\t.endm\n";
|
||||
|
||||
static const char dyncall_prologue[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" *\n"
|
||||
" * This the dynamic call logic.\n"
|
||||
" *\n"
|
||||
" *\t1. SAVEREG1-SAVEREG2, and lr stored on the C stack\n"
|
||||
" *\t2. [PIC_REG] = Points to our data segment\n"
|
||||
" *\t3. [RINFO] = Offset to info structure in data segment\n"
|
||||
" *\t4. [WORK] = Reference count to be applied to the frame\n"
|
||||
" *\t5. TMP1, TMP2 and TMP3 are available for use.\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"\t.text\n"
|
||||
"\t.align\t2\n"
|
||||
"\t.local\t__dyncall\n"
|
||||
"\t.type\t__dyncall, function\n"
|
||||
"\t.local\t__dyncall1\n"
|
||||
"\t.type\t__dyncall1, function\n"
|
||||
"\t.local\t__dyncall2\n"
|
||||
"\t.type\t__dyncall2, function\n\n"
|
||||
"__dyncall1:\n"
|
||||
"\tstmdb\tsp!, {SAVEREG1-SAVEREG2, lr}\n"
|
||||
"\tmov\tRINFO, TMP1\n"
|
||||
"\tmov\tWORK, #1\n"
|
||||
"\tb\t__dyncall\n"
|
||||
"\t.size\t__dyncall1, .-__dyncall1\n\n"
|
||||
"__dyncall2:\n"
|
||||
"\tstmdb\tsp!, {SAVEREG1-SAVEREG2, lr}\n"
|
||||
"\tmov\tRINFO, TMP1\n"
|
||||
"\tmov\tWORK, #2\n"
|
||||
"\t.size\t__dyncall2, .-__dyncall2\n\n"
|
||||
"__dyncall:\n";
|
||||
|
||||
static const char dyntrace_call[] =
|
||||
"\n#ifdef __DYNTRACE\n"
|
||||
"\tbl\t__dyntrace\n"
|
||||
"#endif /* __DYNTRACE */\n";
|
||||
|
||||
static const char dyncall_epilogue[] =
|
||||
"\n\t/***********************************************************\n"
|
||||
"\t * Transfer all of the information saved on the C stack to\n"
|
||||
"\t * a dynamic frame.\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\t/* Get FRAME = the dynamic frame. */\n\n"
|
||||
"\tget_frame\tFRAME, WORK, TMP1, TMP2\n\n"
|
||||
"\t/* Copy the current C stack frame in the dynamic frame */\n\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG1]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG1]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG2]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG2]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG3]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG3]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG4]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG4]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG5]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG5]\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * And release the C stack frame.\n"
|
||||
"\t * At this point, the entire call stack should be pristine.\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tadd\tsp, sp, #SP_FRAME_SIZE\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Get the dyncall information.\n"
|
||||
"\t * Before the following section:\n"
|
||||
"\t *\t[PIC_REG] = Points to our PIC base\n"
|
||||
"\t *\t[FRAME] = Reference to dynamic frame\n"
|
||||
"\t *\t[RINFO] = Offset to info structure in data segment\n"
|
||||
"\t *\tRWORK, TMP1-3 are available\n"
|
||||
"\t *\n"
|
||||
"\t * After the following:\n"
|
||||
"\t *\t[RINFO] = Dyncall info pointer\n"
|
||||
"\t *\t[MYPIC] = Points to our PIC base\n"
|
||||
"\t *\t[FRAME] = Reference to dynamic frame\n"
|
||||
"\t *\t[PIC_REG] = Holds the new PIC base for the target\n"
|
||||
"\t *\t[WORK] = Target function entry point\n"
|
||||
"\t *\tTMP1-3 are still available\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tadd\tRINFO, PIC_REG, RINFO\n"
|
||||
"\tmov\tMYPIC, PIC_REG\n"
|
||||
"\tldr\tPIC_REG, [RINFO, #RINFO_PICBASE]\n"
|
||||
"\tldr\tWORK, [RINFO, #RINFO_FCNADDR]\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Call the function entry point.\n"
|
||||
"\t *\n"
|
||||
"\t * This logic performs a 32-bit, register version of the\n"
|
||||
"\t * the bl instruction. \n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tmov\tlr, pc\n"
|
||||
"\tmov\tpc, WORK\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Return from the thunked function\n"
|
||||
"\t *\n"
|
||||
"\t * At this point:\n"
|
||||
"\t *\t1. We should have our PIC base in MYPIC.\n"
|
||||
"\t *\t2. We should have the reference to the dynamic frame in FRAME\n"
|
||||
"\t *\t3. We are free to use: r0-r3, RINFO, PIC_REG, FRAME-2, TMP1-2\n"
|
||||
"\t *\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\t/* First, recover our PIC base into from a register that will\n"
|
||||
"\t * have been restored.\n"
|
||||
"\t */\n\n"
|
||||
"\tmov\tPIC_REG, MYPIC\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Restore the C stack frame and release the dynamic frame\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\t/* Re-allocate the stack frame */\n\n"
|
||||
"\tsub\tsp, sp, #SP_FRAME_SIZE\n\n"
|
||||
"\t/* Then transfer the information into the C stack frame\n"
|
||||
"\t * that was saved in the dynamic frame\n"
|
||||
"\t */\n\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG1]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG1]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG2]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG2]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG3]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG3]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG4]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG4]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG5]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG5]\n\n"
|
||||
"\t/* Release the dynamic frame */\n\n"
|
||||
"\trelease_frame\tFRAME, TMP1\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * And return to the caller\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tldmia\tsp!, {SAVEREG1-SAVEREG2, pc}\n"
|
||||
"\t.size\t__dyncall, .-__dyncall\n";
|
||||
|
||||
static const char nonreturning_dyncall_prologue[] =
|
||||
"\n/*******************************************************************\n"
|
||||
" *\n"
|
||||
" * This is special dynamic call logic for functions that do not\n"
|
||||
" * (normally) return.\n"
|
||||
" *\n"
|
||||
" *\t1. SAVEREG1-SAVEREG2, and lr stored on the C stack\n"
|
||||
" *\t2. [PIC_REG] = Points to our data segment\n"
|
||||
" *\t3. [RINFO] = Offset to info structure in data segment\n"
|
||||
" *\t3. [WORK] = Reference count to be applied to the frame\n"
|
||||
" *\t4. TMP1 and TMP2 are available for use.\n"
|
||||
" *******************************************************************/\n\n"
|
||||
"\t.text\n"
|
||||
"\t.align\t2\n"
|
||||
"\t.local\t__dynnoreturn\n"
|
||||
"\t.type\t__dynnoreturn, function\n\n"
|
||||
"__dynnoreturn:\n"
|
||||
"\tstmdb\tsp!, {SAVEREG1-SAVEREG2, lr}\n"
|
||||
"\tmov\tRINFO, TMP1\n"
|
||||
"\tmov\tWORK, #0\n";
|
||||
|
||||
static const char nonreturning_dyncall_epilogue[] =
|
||||
"\n\t/***********************************************************\n"
|
||||
"\t * Transfer all of the information saved on the C stack to\n"
|
||||
"\t * a dynamic frame.\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\t/* Get FRAME = the dynamic frame. */\n\n"
|
||||
"\tget_nrframe\tFRAME, WORK, TMP1, TMP2\n\n"
|
||||
"\t/* Copy the current C stack frame in the dynamic frame */\n\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG1]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG1]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG2]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG2]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG3]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG3]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG4]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG4]\n"
|
||||
"\tldr\tTMP2, [sp, #SP_OFFSET_CREG5]\n"
|
||||
"\tstr\tTMP2, [FRAME, #DFR_OFFSET_CREG5]\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * And release the C stack frame.\n"
|
||||
"\t * At this point, the entire call stack should be pristine.\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tadd\tsp, sp, #SP_FRAME_SIZE\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Get the dyncall information.\n"
|
||||
"\t * Before the following section:\n"
|
||||
"\t *\t[PIC_REG] = Points to our PIC base\n"
|
||||
"\t *\t[FRAME] = Reference to dynamic frame\n"
|
||||
"\t *\t[RINFO] = Offset to info structure in data segment\n"
|
||||
"\t *\tRWORK, TMP1-3 are available\n"
|
||||
"\t *\n"
|
||||
"\t * After the following:\n"
|
||||
"\t *\t[RINFO] = Dyncall info pointer\n"
|
||||
"\t *\t[MYPIC] = Points to our PIC base\n"
|
||||
"\t *\t[FRAME] = Reference to dynamic frame\n"
|
||||
"\t *\t[PIC_REG] = Holds the new PIC base for the target\n"
|
||||
"\t *\t[WORK] = Target function entry point\n"
|
||||
"\t *\tTMP1-3 are still available\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tadd\tRINFO, PIC_REG, RINFO\n"
|
||||
"\tmov\tMYPIC, PIC_REG\n"
|
||||
"\tldr\tPIC_REG, [RINFO, #RINFO_PICBASE]\n"
|
||||
"\tldr\tWORK, [RINFO, #RINFO_FCNADDR]\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Call the function entry point.\n"
|
||||
"\t *\n"
|
||||
"\t * This logic performs a 32-bit, register version of the\n"
|
||||
"\t * the bl instruction. \n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tmov\tlr, pc\n"
|
||||
"\tmov\tpc, WORK\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Return from the thunked function\n"
|
||||
"\t *\n"
|
||||
"\t * At this point:\n"
|
||||
"\t *\t1. We should have our PIC base in MYPIC.\n"
|
||||
"\t *\t2. We should have a reference to the dynamic frame in FRAME\n"
|
||||
"\t *\t3. We are free to use: r0-r3, RINFO, PIC_REG, FRAME-2, TMP1-2\n"
|
||||
"\t *\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\t/* First, recover our PIC base from a register the will have\n"
|
||||
"\t * been restored.\n"
|
||||
"\t */\n\n"
|
||||
"\tmov\tPIC_REG, MYPIC\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * Restore the C stack frame\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\t/* Re-allocate the stack frame */\n\n"
|
||||
"\tsub\tsp, sp, #SP_FRAME_SIZE\n\n"
|
||||
"\t/* Then transfer the information into the C stack frame\n"
|
||||
"\t * that was saved in the dynamic frame.\n"
|
||||
"\t */\n\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG1]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG1]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG2]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG2]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG3]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG3]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG4]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG4]\n"
|
||||
"\tldr\tTMP2, [FRAME, #DFR_OFFSET_CREG5]\n"
|
||||
"\tstr\tTMP2, [sp, #SP_OFFSET_CREG5]\n\n"
|
||||
"\t/* Release the dynamic frame */\n\n"
|
||||
"\trelease_nrframe\tFRAME, TMP1\n\n"
|
||||
"\t/***********************************************************\n"
|
||||
"\t * And return to the caller\n"
|
||||
"\t ***********************************************************/\n\n"
|
||||
"\tldmia\tsp!, {SAVEREG1-SAVEREG2, pc}\n"
|
||||
"\t.size\t__dynnoreturn, .-__dynnoreturn\n";
|
||||
|
||||
static const char file_epilogue[] =
|
||||
"\t.end\n";
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,956 @@
|
|||
/***********************************************************************
|
||||
* xflat/tools/mknxflat.c
|
||||
*
|
||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Modified from ldelflib (see http://xflat.org):
|
||||
*
|
||||
* Copyright (c) 2002, 2006, Cadenux, LLC. All rights reserved.
|
||||
* Copyright (c) 2002, 2006, Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Included Files
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <bfd.h>
|
||||
|
||||
#include "nxflat.h"
|
||||
#include "arch/arm.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Definitions
|
||||
***********************************************************************/
|
||||
|
||||
#define dbg(format, arg...) \
|
||||
if (verbose) printf(format, ## arg)
|
||||
|
||||
#define BSF_GLOBL_FUNC (BSF_GLOBAL|BSF_FUNCTION)
|
||||
#define BSF_WEAK_FUNC (BSF_WEAK|BSF_FUNCTION)
|
||||
#define BSF_DEFINED (BSF_LOCAL|BSF_GLOBAL)
|
||||
|
||||
#define IS_GLOBL_FUNC(x) ((((x)->flags)&(BSF_GLOBL_FUNC))==(BSF_GLOBL_FUNC))
|
||||
#define IS_WEAK_FUNC(x) ((((x)->flags)&(BSF_WEAK_FUNC))==(BSF_WEAK_FUNC))
|
||||
#define IS_DEFINED(x) ((((x)->flags)&(BSF_DEFINED))!=0)
|
||||
#define IS_OBJECT(x) ((((x)->flags)&(BSF_OBJECT))!=0)
|
||||
#define IS_WEAK(x) ((((x)->flags)&(BSF_WEAK))!=0)
|
||||
|
||||
#define MAX_EXPORT_NAMES 1024
|
||||
#define DEFAULT_MAX_THREADS 6
|
||||
#define MIN_THREADS 3
|
||||
|
||||
/***********************************************************************
|
||||
* Private Types
|
||||
***********************************************************************/
|
||||
|
||||
typedef int (*symfunc_type) (asymbol * sym, void *arg);
|
||||
typedef int (*namefunc_type) (const char *name, void *arg);
|
||||
|
||||
/***********************************************************************
|
||||
* Private Variables
|
||||
***********************************************************************/
|
||||
|
||||
/* Command line settings (counters but treated like booleans) */
|
||||
|
||||
static int verbose = 0;
|
||||
static int weak_imports = 0;
|
||||
static int dsyms = 0;
|
||||
static int enable_trace = 0;
|
||||
static int max_threads = DEFAULT_MAX_THREADS;
|
||||
|
||||
/* Characteristics of things */
|
||||
static int calls_nonreturning_functions = 0;
|
||||
static int calls_forkers = 0;
|
||||
|
||||
/* Sizes of things */
|
||||
|
||||
static long number_of_symbols = 0;
|
||||
static long number_undefined = 0;
|
||||
|
||||
/* Names of things */
|
||||
|
||||
static const char *program_name = NULL;
|
||||
static const char *bfd_filename = NULL;
|
||||
static const char *out_filename = NULL;
|
||||
|
||||
/* The symbol table. */
|
||||
|
||||
static asymbol **symbol_table = NULL;
|
||||
|
||||
/* handle to included file */
|
||||
|
||||
static FILE *include_stream = NULL;
|
||||
static char token[1024];
|
||||
|
||||
static int counter;
|
||||
|
||||
/***********************************************************************
|
||||
* Private constant data
|
||||
***********************************************************************/
|
||||
|
||||
/* All of the strings defining the generated file are here: */
|
||||
|
||||
#include "arch/dyncall_skeleton.def"
|
||||
|
||||
static const char dyn_symbol_prefix[] = "__dyn";
|
||||
#define DYN_SYMBOL_PREFIX_LEN 5
|
||||
|
||||
/* This is the list of names of libc and libpthread functions that
|
||||
* do not return. These may require some special handling -- at a
|
||||
* minimum, they must tie up resources that can only be released
|
||||
* when the function returns.
|
||||
*/
|
||||
|
||||
static const char *const nonreturners[] = {
|
||||
"abort", /* Never returns */
|
||||
"err", /* Never returns */
|
||||
"errx", /* Never returns */
|
||||
"execl", /* Usually doesn't return */
|
||||
"execle", /* Usually doesn't return */
|
||||
"execlp", /* Usually doesn't return */
|
||||
"execv", /* Usually doesn't return */
|
||||
"execv", /* Usually doesn't return */
|
||||
"execve", /* Usually doesn't return */
|
||||
"execvp", /* Usually doesn't return */
|
||||
"execvp", /* Usually doesn't return */
|
||||
"exit", /* Never returns */
|
||||
"_exit", /* Never returns */
|
||||
"_Exit", /* Never returns */
|
||||
"longjmp", /* Never returns */
|
||||
"_longjmp", /* Never returns */
|
||||
"pthread_exit", /* Never returns */
|
||||
"siglongjmp", /* Never returns */
|
||||
"__uClibc_main", /* Never returns */
|
||||
"__uClibc_start_main", /* Never returns */
|
||||
"verr", /* Never returns */
|
||||
"verrx", /* Never returns */
|
||||
NULL /* End of list */
|
||||
};
|
||||
|
||||
/* This is the list of names of libc functions that behave very
|
||||
* strangely: They return twice.
|
||||
*/
|
||||
|
||||
static const char *const forkers[] = {
|
||||
"clone",
|
||||
"fork",
|
||||
"setjmp",
|
||||
"_setjmp",
|
||||
"__sigsetjmp",
|
||||
"vfork",
|
||||
NULL /* End of list */
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* Private Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* show_usage
|
||||
***********************************************************************/
|
||||
|
||||
static void show_usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options] <bfd-filename>\n\n", program_name);
|
||||
fprintf(stderr, "Where options are one or more of the following. Note\n");
|
||||
fprintf(stderr, "that a space is always required between the option and\n");
|
||||
fprintf(stderr, "any following arguments.\n\n");
|
||||
fprintf(stderr, " -d Use dynamic symbol table. [symtab]\n");
|
||||
fprintf(stderr, " -f <cmd-filename>\n");
|
||||
fprintf(stderr, " Take next commands from <cmd-filename> [cmd-line]\n");
|
||||
fprintf(stderr, " -o <out-filename>\n");
|
||||
fprintf(stderr, " Output to <out-filename> [stdout]\n");
|
||||
fprintf(stderr, " -p <max_threads>\n");
|
||||
fprintf(stderr,
|
||||
" The maximum number of threads that can make simultaneous\n");
|
||||
fprintf(stderr, " make calls into a shared library [6]\n");
|
||||
fprintf(stderr, " -t Enable tracing of outbound shared library function\n");
|
||||
fprintf(stderr, " calls. [no tracing]\n");
|
||||
fprintf(stderr, " -v Verbose output [no output]\n");
|
||||
fprintf(stderr, " -w Import weakly declared functions, i.e., weakly\n");
|
||||
fprintf(stderr, " declared functions are expected to be provided at\n");
|
||||
fprintf(stderr, " load-time [not imported]\n");
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_symbols
|
||||
***********************************************************************/
|
||||
|
||||
static asymbol **get_symbols(bfd * abfd, long *num)
|
||||
{
|
||||
long storage_needed;
|
||||
asymbol **symbol_table;
|
||||
long number_of_symbols;
|
||||
|
||||
if (dsyms)
|
||||
storage_needed = bfd_get_dynamic_symtab_upper_bound(abfd);
|
||||
else
|
||||
storage_needed = bfd_get_symtab_upper_bound(abfd);
|
||||
|
||||
if (storage_needed < 0)
|
||||
abort();
|
||||
|
||||
if (storage_needed == 0)
|
||||
return NULL;
|
||||
|
||||
symbol_table = (asymbol **) malloc(storage_needed);
|
||||
|
||||
if (dsyms)
|
||||
number_of_symbols = bfd_canonicalize_dynamic_symtab(abfd, symbol_table);
|
||||
else
|
||||
number_of_symbols = bfd_canonicalize_symtab(abfd, symbol_table);
|
||||
if (number_of_symbols < 0)
|
||||
abort();
|
||||
|
||||
*num = number_of_symbols;
|
||||
return symbol_table;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* traverse_undefined_functions
|
||||
***********************************************************************/
|
||||
|
||||
static int traverse_undefined_functions(void *arg, symfunc_type fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < number_of_symbols; i++)
|
||||
{
|
||||
/* Check if it is undefined and not an object. I have found that symbol
|
||||
* typing can be misleading: Imported functions are not marked as
|
||||
* BSF_FUNCTION; weakly defined objects are listed as undefined objects.
|
||||
* Conclusion: We will error if a object is truly undefined! */
|
||||
|
||||
if ((symbol_table[i]->value == 0) &&
|
||||
(!IS_DEFINED(symbol_table[i])) && (!IS_OBJECT(symbol_table[i])))
|
||||
{
|
||||
/* Is is imported as a "weak" symbol? If so, we will process the
|
||||
* symbol only if we were requested to do so from the command line. */
|
||||
|
||||
if ((!IS_WEAK(symbol_table[i])) || (weak_imports > 0))
|
||||
{
|
||||
/* Yes, process the symbol */
|
||||
|
||||
if (fn(symbol_table[i], arg) != 0)
|
||||
{
|
||||
/* If the function returns a non-zero value, then we
|
||||
* terminate the traversal and return a non-zero value also. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 0 meaning that all undefined symbols were examined successfully. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_string
|
||||
***********************************************************************/
|
||||
|
||||
static void put_string(int fd, const char *string)
|
||||
{
|
||||
ssize_t bytes_available = strlen(string);
|
||||
ssize_t bytes_written = write(fd, string, bytes_available);
|
||||
if (bytes_written < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Failed to write %ld bytes of string to output, errno=%d\n",
|
||||
(long)bytes_available, errno);
|
||||
exit(5);
|
||||
}
|
||||
else if (bytes_written != bytes_available)
|
||||
{
|
||||
fprintf(stderr, "Only wrote %ld of %ld bytes of string to output\n",
|
||||
(long)bytes_written, (long)bytes_available);
|
||||
exit(6);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* does_not_return_name/sym
|
||||
***********************************************************************/
|
||||
|
||||
static int does_not_return_name(const char *func_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check every name in the list of (usually) non-returning function */
|
||||
|
||||
for (i = 0; nonreturners[i] != NULL; i++)
|
||||
{
|
||||
/* Is this function name in the list */
|
||||
|
||||
if (strcmp(func_name, nonreturners[i]) == 0)
|
||||
{
|
||||
/* Yes, return true now. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Its not in the list, return false */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int does_not_return_sym(asymbol * sym, void *arg)
|
||||
{
|
||||
const char *func_name = sym->name;
|
||||
if (func_name)
|
||||
return does_not_return_name(func_name);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* check_for_nonreturning_functions
|
||||
***********************************************************************/
|
||||
|
||||
static void check_for_nonreturning_functions(void)
|
||||
{
|
||||
calls_nonreturning_functions =
|
||||
traverse_undefined_functions(NULL, does_not_return_sym);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* is_forker_name/sym
|
||||
***********************************************************************/
|
||||
|
||||
static int is_forker_name(const char *func_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check every name in the list of forkers */
|
||||
|
||||
for (i = 0; forkers[i] != NULL; i++)
|
||||
{
|
||||
/* Is this function name in the list */
|
||||
|
||||
if (strcmp(func_name, forkers[i]) == 0)
|
||||
{
|
||||
/* Yes, return true now. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Its not in the list, return false */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_forker_sym(asymbol * sym, void *arg)
|
||||
{
|
||||
const char *func_name = sym->name;
|
||||
if (func_name)
|
||||
return does_not_return_name(func_name);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* check_for_forkers
|
||||
***********************************************************************/
|
||||
|
||||
static void check_for_forkers(void)
|
||||
{
|
||||
calls_forkers = traverse_undefined_functions(NULL, is_forker_sym);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* count_undefined
|
||||
***********************************************************************/
|
||||
|
||||
static int count_undefined(asymbol * sym, void *arg)
|
||||
{
|
||||
number_undefined++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_dynimport_decl
|
||||
***********************************************************************/
|
||||
|
||||
static int put_dynimport_decl(asymbol * sym, void *arg)
|
||||
{
|
||||
char dynimport_decl[1024];
|
||||
const char *func_name = sym->name;
|
||||
int fd = (int)arg;
|
||||
|
||||
/* Put the declaration for the dynamic info structure */
|
||||
if (func_name)
|
||||
{
|
||||
sprintf(dynimport_decl, dynimport_decl_format,
|
||||
MKINFODECLARGS(func_name, counter));
|
||||
put_string(fd, dynimport_decl);
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_dynimport_array
|
||||
***********************************************************************/
|
||||
|
||||
static int put_dynimport_array(asymbol * sym, void *arg)
|
||||
{
|
||||
char dynimport_array[1024];
|
||||
const char *func_name = sym->name;
|
||||
int fd = (int)arg;
|
||||
|
||||
/* Create the dynimport_array */
|
||||
|
||||
if (func_name)
|
||||
{
|
||||
sprintf(dynimport_array, dynimport_array_format,
|
||||
MKINFOARGS(func_name, counter));
|
||||
put_string(fd, dynimport_array);
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_nxflat_import
|
||||
***********************************************************************/
|
||||
|
||||
static int put_nxflat_import(asymbol * sym, void *arg)
|
||||
{
|
||||
char thunk[4096];
|
||||
const char *func_name = sym->name;
|
||||
int fd = (int)arg;
|
||||
|
||||
if (func_name)
|
||||
{
|
||||
/* Create the thunk */
|
||||
|
||||
if (does_not_return_name(func_name) != 0)
|
||||
{
|
||||
/* The special case for functions that may not return */
|
||||
|
||||
sprintf(thunk, nonreturning_dyncall_format,
|
||||
MKCALLARGS(func_name, counter));
|
||||
}
|
||||
else if (is_forker_name(func_name) != 0)
|
||||
{
|
||||
/* The special case for functions that fork */
|
||||
|
||||
sprintf(thunk, dyncall_format2, MKCALLARGS(func_name, counter));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The normal case */
|
||||
|
||||
sprintf(thunk, dyncall_format, MKCALLARGS(func_name, counter));
|
||||
}
|
||||
|
||||
put_string(fd, thunk);
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_all_nxflat_import
|
||||
***********************************************************************/
|
||||
|
||||
static void put_all_nxflat_import(int fd)
|
||||
{
|
||||
if (number_undefined > 0)
|
||||
{
|
||||
/* Put all of the declarations for the dynimport structures together. */
|
||||
|
||||
put_string(fd, dynimport_decl_prologue);
|
||||
counter = 0;
|
||||
(void)traverse_undefined_functions((void *)fd, put_dynimport_decl);
|
||||
|
||||
/* Put all of the dynimport structures together as an array */
|
||||
|
||||
put_string(fd, dynimport_array_prologue);
|
||||
counter = 0;
|
||||
(void)traverse_undefined_functions((void *)fd, put_dynimport_array);
|
||||
put_string(fd, dynimport_array_epilogue);
|
||||
|
||||
/* Put all of the dyncall logic together */
|
||||
|
||||
put_string(fd, dyncall_decl_prologue);
|
||||
counter = 0;
|
||||
(void)traverse_undefined_functions((void *)fd, put_nxflat_import);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_import_name
|
||||
***********************************************************************/
|
||||
|
||||
static int put_import_name(asymbol * sym, void *arg)
|
||||
{
|
||||
char import_name[512];
|
||||
const char *func_name = sym->name;
|
||||
int fd = (int)arg;
|
||||
|
||||
/* Create the import_name */
|
||||
|
||||
if (func_name)
|
||||
{
|
||||
sprintf(import_name, import_name_strtab_format,
|
||||
MKIMPSTRTABARG(func_name, counter));
|
||||
put_string(fd, import_name);
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_import_name_strtab
|
||||
***********************************************************************/
|
||||
|
||||
static void inline put_import_name_strtab(int fd)
|
||||
{
|
||||
if (number_undefined > 0)
|
||||
{
|
||||
counter = 0;
|
||||
put_string(fd, import_name_strtab_prologue);
|
||||
(void)traverse_undefined_functions((void *)fd, put_import_name);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_file_epilogue
|
||||
***********************************************************************/
|
||||
|
||||
static void inline put_file_epilogue(int fd)
|
||||
{
|
||||
/* Is it necessary to generate any thunk logic? */
|
||||
|
||||
if (number_undefined > 0)
|
||||
{
|
||||
/* Yes, was tracing enabled? */
|
||||
|
||||
if (enable_trace > 0)
|
||||
{
|
||||
/* Yes, generate the function to output the trace */
|
||||
|
||||
put_string(fd, dyntrace_function);
|
||||
}
|
||||
|
||||
/* Output macros for managing the frame storage */
|
||||
|
||||
put_string(fd, frame_macros);
|
||||
|
||||
if (calls_nonreturning_functions)
|
||||
{
|
||||
/* Output special macros for managing frames for noreturning
|
||||
* functions */
|
||||
|
||||
put_string(fd, nonreturning_frame_macros);
|
||||
}
|
||||
|
||||
/* Output the beginning of the dynamic call function. */
|
||||
|
||||
put_string(fd, dyncall_prologue);
|
||||
|
||||
/* If tracing is enabled, then insert a call to the the trace generation
|
||||
* function. */
|
||||
|
||||
if (enable_trace > 0)
|
||||
{
|
||||
put_string(fd, dyntrace_call);
|
||||
}
|
||||
|
||||
/* Output the rest of the dynamic call function. */
|
||||
|
||||
put_string(fd, dyncall_epilogue);
|
||||
|
||||
/* Does the module call any non-returning functions? */
|
||||
|
||||
if (calls_nonreturning_functions)
|
||||
{
|
||||
/* Yes, output the beginning of a special dynamic call function. */
|
||||
|
||||
put_string(fd, nonreturning_dyncall_prologue);
|
||||
|
||||
/* If tracing is enabled, then insert a call to the the trace
|
||||
* generation function. */
|
||||
|
||||
if (enable_trace > 0)
|
||||
{
|
||||
put_string(fd, dyntrace_call);
|
||||
}
|
||||
|
||||
/* Output the rest of the special dynamic call function. */
|
||||
|
||||
put_string(fd, nonreturning_dyncall_epilogue);
|
||||
}
|
||||
}
|
||||
put_string(fd, file_epilogue);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* put_file_prologue
|
||||
***********************************************************************/
|
||||
|
||||
static void inline put_file_prologue(int fd)
|
||||
{
|
||||
put_string(fd, file_prologue);
|
||||
if (enable_trace > 0)
|
||||
{
|
||||
put_string(fd, dyntrace_enable);
|
||||
}
|
||||
if (number_undefined > 0)
|
||||
{
|
||||
char frame_size[1024];
|
||||
|
||||
put_string(fd, import_prologue);
|
||||
sprintf(frame_size, import_frame_size, max_threads);
|
||||
put_string(fd, frame_size);
|
||||
put_string(fd, dynamic_frames);
|
||||
|
||||
if (calls_nonreturning_functions)
|
||||
{
|
||||
put_string(fd, nonreturning_dynamic_frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_file_token
|
||||
***********************************************************************/
|
||||
|
||||
#define ISSPACE(c) \
|
||||
((c==' ')||(c=='\f')||(c=='\n')||(c=='\r')||(c=='\t')||(c=='\v'))
|
||||
|
||||
#define ISTERMINATOR(c) (ISSPACE(c)||(c==EOF))
|
||||
|
||||
static int get_file_token(FILE * in_stream)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
/* Skip over leading whitespace */
|
||||
|
||||
do
|
||||
c = getc(in_stream);
|
||||
while ISSPACE
|
||||
(c);
|
||||
|
||||
if (c == EOF)
|
||||
return EOF;
|
||||
|
||||
/* Add the token to the buffer. Copy characters until the buffer is full, or
|
||||
* a terminator is encountered. */
|
||||
|
||||
for (i = 0; ((i < 1023) && !ISTERMINATOR(c)); i++, c = getc(in_stream))
|
||||
{
|
||||
token[i] = (char)c;
|
||||
}
|
||||
|
||||
/* Handle the string truncation case. */
|
||||
|
||||
token[i] = '\0';
|
||||
while (!ISTERMINATOR(c))
|
||||
c = getc(in_stream);
|
||||
|
||||
/* Return success. On next entry, we will get the next character after the
|
||||
* terminator. If the terminator was EOF, we should get EOF again. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_token
|
||||
***********************************************************************/
|
||||
|
||||
static char *get_token(int *argno, int argc, char **argv)
|
||||
{
|
||||
char *retval = NULL;
|
||||
|
||||
if (include_stream)
|
||||
{
|
||||
if (get_file_token(include_stream) == EOF)
|
||||
{
|
||||
fclose(include_stream);
|
||||
include_stream = NULL;
|
||||
retval = get_token(argno, argc, argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = strdup(token);
|
||||
}
|
||||
}
|
||||
else if (*argno >= argc)
|
||||
{
|
||||
retval = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = argv[*argno];
|
||||
(*argno)++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_arg
|
||||
***********************************************************************/
|
||||
|
||||
static char *get_arg(int *argno, int argc, char **argv)
|
||||
{
|
||||
char *retval;
|
||||
|
||||
/* Get the next argument */
|
||||
|
||||
retval = get_token(argno, argc, argv);
|
||||
if ((retval == NULL) || (retval[0] == '-'))
|
||||
{
|
||||
fprintf(stderr, "Option requires an argument\n\n");
|
||||
show_usage();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_opt
|
||||
***********************************************************************/
|
||||
|
||||
static int get_opt(int *argno, int argc, char **argv)
|
||||
{
|
||||
char *opt;
|
||||
int len;
|
||||
int retval = -1;
|
||||
|
||||
/* Get the next argument */
|
||||
|
||||
opt = get_token(argno, argc, argv);
|
||||
if (opt != NULL)
|
||||
{
|
||||
/* It must be of length 2 and start with a '-' */
|
||||
|
||||
len = strlen(opt);
|
||||
if ((len == 2) && (opt[0] == '-'))
|
||||
{
|
||||
retval = (int)opt[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s Unrecognized option\n\n", opt);
|
||||
show_usage();
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* parse_args
|
||||
***********************************************************************/
|
||||
|
||||
static void parse_args(int argc, char **argv)
|
||||
{
|
||||
int argno = 1;
|
||||
int opt;
|
||||
|
||||
/* Save our name (for show_usage) */
|
||||
|
||||
program_name = argv[0];
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing required arguments\n\n");
|
||||
show_usage();
|
||||
}
|
||||
|
||||
/* Get the name of the input BFD file. This is always the last thing in the
|
||||
* argument list. We decrement argc so that the parsing logic will not look
|
||||
* at it. */
|
||||
|
||||
bfd_filename = argv[argc - 1];
|
||||
argc--;
|
||||
|
||||
/* Get miscellaneous options from the command line. */
|
||||
|
||||
while ((opt = get_opt(&argno, argc, argv)) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'd':
|
||||
dsyms++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
char *filename = get_arg(&argno, argc, argv);
|
||||
if (include_stream)
|
||||
{
|
||||
fprintf(stderr, "Cannot use -f from within a cmd-file\n\n");
|
||||
show_usage();
|
||||
}
|
||||
else
|
||||
{
|
||||
include_stream = fopen(filename, "r");
|
||||
if (!include_stream)
|
||||
{
|
||||
fprintf(stderr, "Could not open cmd-file %s\n\n", filename);
|
||||
show_usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
out_filename = get_arg(&argno, argc, argv);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
{
|
||||
int nthreads = atoi(get_arg(&argno, argc, argv));
|
||||
if (nthreads < MIN_THREADS)
|
||||
{
|
||||
fprintf(stderr, "Invalid number of threads (%d) using %d\n",
|
||||
nthreads, max_threads);
|
||||
}
|
||||
else
|
||||
{
|
||||
max_threads = nthreads;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
enable_trace++;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
weak_imports++;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s Unknown option\n\n", argv[0]);
|
||||
show_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* main
|
||||
***********************************************************************/
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
bfd *bf;
|
||||
int out_fd = 0;
|
||||
|
||||
/* Get the input arguments */
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
/* Make sure that we can option the BFD file */
|
||||
|
||||
dbg("Opening BFD file: %s\n", bfd_filename);
|
||||
if (!(bf = bfd_openr(bfd_filename, 0)))
|
||||
{
|
||||
fprintf(stderr, "Failed to open BFD file: %s, errno=%d\n",
|
||||
bfd_filename, errno);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
dbg("Checking format\n");
|
||||
if (bfd_check_format(bf, bfd_object) == 0)
|
||||
{
|
||||
fprintf(stderr, "BFD file %s is not an object file\n", bfd_filename);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
dbg("Loading symbol table from BFD file %s\n", bfd_filename);
|
||||
symbol_table = get_symbols(bf, &number_of_symbols);
|
||||
|
||||
/* Count the number of undefined function symbols */
|
||||
|
||||
(void)traverse_undefined_functions(NULL, count_undefined);
|
||||
|
||||
/* Check if the module calls any non-returning functions (like exit). These
|
||||
* will require some additional setup. */
|
||||
|
||||
check_for_nonreturning_functions();
|
||||
check_for_forkers();
|
||||
|
||||
/* Make sure that we can open the output file if one is specified. If no
|
||||
* out_filename is specified, we'll use stdout. */
|
||||
|
||||
if (out_filename)
|
||||
{
|
||||
out_fd = open(out_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (out_fd < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to open output file: %s, errno=%d\n",
|
||||
out_filename, errno);
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the thunk file in three pieces: 1. The constant file prologue 2.
|
||||
* Library path information (if any) 3. Library file name information (if
|
||||
* any) 4. Exported symbole information (if any) 5. Imported symbole
|
||||
* information (if any) 6. The constant file epilogue. */
|
||||
|
||||
put_file_prologue(out_fd);
|
||||
put_import_name_strtab(out_fd);
|
||||
put_all_nxflat_import(out_fd);
|
||||
put_file_epilogue(out_fd);
|
||||
|
||||
if (out_fd > 0)
|
||||
close(out_fd);
|
||||
exit(0);
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/****************************************************************************
|
||||
* toolchain/nxflat/nxflat.h
|
||||
*
|
||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __TOOLCHAIN_NXFLAT_NXFLAT_H
|
||||
#define __TOOLCHAIN_NXFLAT_NXFLAT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define NXFLAT_MAX_STRING_SIZE 64 /* Largest size of string (w/zterminator) */
|
||||
#define NXFLAT_MAGIC "NxFT" /* NXFLAT magic number */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* The NXFLAT file header
|
||||
*
|
||||
* The elements within this structure are stored in network order (i.e.,
|
||||
* ntohs() and ntohl() should be used to access fields within the
|
||||
* header.
|
||||
****************************************************************************/
|
||||
|
||||
struct nxflat_hdr_s
|
||||
{
|
||||
/* The "magic number" identifying the file type. This field should contain
|
||||
* "NxFT". NOTE that there is no other versioning information other than
|
||||
* this magic number. */
|
||||
|
||||
char h_magic[4];
|
||||
|
||||
/* The following fields provide the memory map for the nxflat binary.
|
||||
* h_entry - Offset to the the first executable insruction from the
|
||||
* beginning of the file. h_datastart - Offset to the beginning of the data
|
||||
* segment from the beginning of the file. This field can also interpreted
|
||||
* as the size of the ISpace segment. h_dataend - Offset to the end of the
|
||||
* data segment from the beginning of the file. h_bssend - Offset to the
|
||||
* end of bss segment from the beginning of the file. The text segment can
|
||||
* be considered to be the contiguous (unrelocated) address space range
|
||||
* from address zero through (but not including) h_datastart. The size of
|
||||
* the data/bss segment includes (as a minimum) the data and bss regions
|
||||
* (bss_end - data_start) as well as the size of the stack. At run time,
|
||||
* this region will also include program arguments and environement
|
||||
* variables. The bss segment is data_end through bss_end. */
|
||||
|
||||
u_int32_t h_entry;
|
||||
u_int32_t h_datastart;
|
||||
u_int32_t h_dataend;
|
||||
u_int32_t h_bssend;
|
||||
|
||||
/* Size of stack, in bytes */
|
||||
|
||||
u_int32_t h_stacksize;
|
||||
|
||||
/* Relocation entries h_relocstart - Offset to the beginning of an array of
|
||||
* relocation records (struct nxflat_reloc). The offset is relative to the
|
||||
* start of the file h_reloccount - The number of relocation records in the
|
||||
* arry */
|
||||
|
||||
u_int32_t h_relocstart; /* Offset of relocation records */
|
||||
u_int32_t h_reloccount; /* Number of relocation records */
|
||||
|
||||
/* Imported symbol table (NOTE no symbols are exported) h_importsymbols -
|
||||
* Offset to the beginning of an array of imported symbol structures
|
||||
* (struct nxflat_import). The h_importsymbols offset is relative to the
|
||||
* beginning of the file. Each entry of the array contains an u_int32_t
|
||||
* offset (again from the beginning of the file) to the name of a symbol
|
||||
* string. This string is null-terminated. h_importcount - The number of
|
||||
* records in the h_exportsymbols array. */
|
||||
|
||||
u_int32_t h_importsymbols; /* Offset to list of imported symbols */
|
||||
u_int16_t h_importcount; /* Number of imported symbols */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* NXFLAT Relocation types.
|
||||
*
|
||||
* The relocation records are an array of the following type.
|
||||
****************************************************************************/
|
||||
|
||||
struct nxflat_reloc_s
|
||||
{
|
||||
u_int32_t r_info; /* Bit-encoded relocation info */
|
||||
};
|
||||
|
||||
/* Pack the type and the offset into one 32-bit value */
|
||||
|
||||
#define NXFLAT_RELOC(t,o) (((u_int32_t)((t) & 3) << 28) | ((o) & 0x1fffffff))
|
||||
|
||||
/* The top three bits of the relocation info is the relocation type (see the
|
||||
* NXFLAT_RELOC_TYPE_* definitions below. This is an unsigned value.
|
||||
*/
|
||||
|
||||
#define NXFLAT_RELOC_TYPE(r) ((u_int32_t)(r) >> 28)
|
||||
|
||||
/* The bottom 28 bits of the relocation info is the (non-negative) offset into
|
||||
* the D-Space that needs the fixup.
|
||||
*/
|
||||
|
||||
#define NXFLAT_RELOC_OFFSET(r) ((u_int32_t)(r) & 0x1fffffff)
|
||||
|
||||
/* These are possible values for the relocation type */
|
||||
|
||||
#define NXFLAT_RELOC_TYPE_NONE 0 /* Invalid relocation type */
|
||||
#define NXFLAT_RELOC_TYPE_TEXT 1 /* Symbol lies in .text region */
|
||||
#define NXFLAT_RELOC_TYPE_DATA 2 /* Symbol lies in .data region */
|
||||
#define NXFLAT_RELOC_TYPE_BSS 3 /* Symbol lies in .bss region */
|
||||
#define NXFLAT_RELOC_TYPE_NUM 4
|
||||
|
||||
/****************************************************************************
|
||||
* NXFLAT Imported symbol type
|
||||
*
|
||||
* The imported symbols are an array of the following type. The fields
|
||||
* in each element are stored in native machine order.
|
||||
****************************************************************************/
|
||||
|
||||
struct nxflat_import_s
|
||||
{
|
||||
u_int32_t i_funcname; /* Offset to name of imported function */
|
||||
u_int32_t i_funcaddress; /* Resolved address of imported function */
|
||||
};
|
||||
|
||||
#endif /* __TOOLCHAIN_NXFLAT_NXFLAT_H */
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
############################################################################
|
||||
# toolchain/nxflat/nxflat.mk
|
||||
#
|
||||
# Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
NXFLAT_DIR = $(TOPDIR)/toolchain/nxflat
|
||||
|
||||
$(NXFLAT_DIR)/.compiled:
|
||||
echo "NUTTX_DIR: $(NUTTX_DIR)"
|
||||
$(MAKE) -C $(NXFLAT_DIR) BINUTILS_DIR="$(BINUTILS_DIR1)" \
|
||||
ARCH=$(BR2_ARCH) CC="$(HOSTCC)"
|
||||
touch $@
|
||||
|
||||
$(NXFLAT_DIR)/.installed: $(NXFLAT_DIR)/.compiled
|
||||
install -m 755 $(NXFLAT_DIR)/mknxflat $(STAGING_DIR)/bin/mknxflat
|
||||
install -m 755 $(NXFLAT_DIR)/ldnxflat $(STAGING_DIR)/bin/ldnxflat
|
||||
install -m 755 $(NXFLAT_DIR)/readnxflat $(STAGING_DIR)/bin/readnxflat
|
||||
touch $@
|
||||
|
||||
nxflat: binutils $(NXFLAT_DIR)/.installed
|
||||
|
||||
nxflat-clean:
|
||||
$(MAKE) -C $(NXFLAT_DIR) clean
|
||||
rm -f $(STAGING_DIR)/bin/mknxflat $(STAGING_DIR)/bin/ldnxflat $(STAGING_DIR)/bin/readnxflat
|
||||
rm -f $(NXFLAT_DIR)/.compiled $(NXFLAT_DIR)/.installed
|
||||
|
||||
nxflat-dirclean: nxflat-clean
|
||||
true
|
||||
|
||||
ifeq ($(strip $(BR2_PACKAGE_NXFLAT)),y)
|
||||
TARGETS += nxflat
|
||||
endif
|
||||
|
|
@ -0,0 +1,669 @@
|
|||
/***********************************************************************
|
||||
* toolchain/nxflat/readnxflat.c
|
||||
*
|
||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Modified from readxflat (see http://xflat.org):
|
||||
*
|
||||
* Copyright (c) 2002, 2006, Cadenux, LLC. All rights reserved.
|
||||
* Copyright (c) 2002, 2006, Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Compilation Flags
|
||||
***********************************************************************/
|
||||
|
||||
#define SWAP_BYTES 1
|
||||
|
||||
/***********************************************************************
|
||||
* Included Files
|
||||
***********************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h> /* ntohl and friends */
|
||||
#include "nxflat.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Compilation Switches
|
||||
***********************************************************************/
|
||||
|
||||
/* #define RELOCS_IN_NETWORK_ORDER */
|
||||
|
||||
/***********************************************************************
|
||||
* Definitions
|
||||
***********************************************************************/
|
||||
#define NXFLAT_HDR_SIZE sizeof(struct nxflat_hdr_s)
|
||||
|
||||
/***********************************************************************
|
||||
* Private Data
|
||||
***********************************************************************/
|
||||
static const char *program_name;
|
||||
static const char *nxflat_filename;
|
||||
|
||||
static int dump_header = 0;
|
||||
static int dump_relocs = 0;
|
||||
static int dump_imports = 0;
|
||||
static int dump_text = 0;
|
||||
static int dump_data = 0;
|
||||
static int verbose = 0;
|
||||
|
||||
static int num_errors = 0;
|
||||
|
||||
#ifdef ARCH_BIG_ENDIAN
|
||||
static int big_endian = 1; /* Assume big-endian */
|
||||
#else
|
||||
static int big_endian = 0; /* Assume little-endian */
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
* Private Constant Data
|
||||
***********************************************************************/
|
||||
|
||||
static const char unknown[] = "UNKNOWN";
|
||||
|
||||
static const char header_reloc_none[] = "RELOC_NONE";
|
||||
static const char header_reloc_text[] = "RELOC_TEXT";
|
||||
static const char header_reloc_data[] = "RELOC_DATA";
|
||||
static const char header_reloc_bss[] = "RELOC_BSS";
|
||||
|
||||
static const char *reloc_type_string[] = {
|
||||
header_reloc_none,
|
||||
header_reloc_text,
|
||||
header_reloc_data,
|
||||
header_reloc_bss,
|
||||
unknown
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* Public Function Prototypes
|
||||
***********************************************************************/
|
||||
|
||||
extern void __attribute__ ((weak)) print_insn_arm(u_int32_t pc,
|
||||
FILE * stream,
|
||||
u_int32_t given);
|
||||
|
||||
/***********************************************************************
|
||||
* Private Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* swap32
|
||||
***********************************************************************/
|
||||
|
||||
static inline u_int32_t nxflat_swap32(u_int32_t little)
|
||||
{
|
||||
u_int32_t big =
|
||||
((little >> 24) & 0xff) |
|
||||
(((little >> 16) & 0xff) << 8) |
|
||||
(((little >> 8) & 0xff) << 16) | ((little & 0xff) << 24);
|
||||
return big;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_nxflat32
|
||||
***********************************************************************/
|
||||
|
||||
static inline u_int32_t get_nxflat32(u_int32_t * addr32)
|
||||
{
|
||||
return ntohl(*addr32);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_nxflat16
|
||||
***********************************************************************/
|
||||
|
||||
static inline u_int16_t get_nxflat16(u_int16_t * addr16)
|
||||
{
|
||||
return ntohs(*addr16);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dump_hex_data
|
||||
***********************************************************************/
|
||||
|
||||
static void dump_hex_data(FILE * in_stream, struct nxflat_hdr_s *header)
|
||||
{
|
||||
u_int32_t data_start = get_nxflat32(&header->h_datastart);
|
||||
u_int32_t data_end = get_nxflat32(&header->h_dataend);
|
||||
int32_t words_left = (data_end - data_start) / sizeof(u_int32_t);
|
||||
u_int32_t addr;
|
||||
u_int32_t buffer[64];
|
||||
|
||||
printf("\nXFLAT DATA SEGMENT:\n\n");
|
||||
|
||||
/* Seek to the beginning of data in the file */
|
||||
|
||||
if (fseek(in_stream, data_start, SEEK_SET) != 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Failed to seek to data in file: offset: %08x\n",
|
||||
data_start);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now dump all of the data reading 64 words at a time */
|
||||
|
||||
addr = 0;
|
||||
while (words_left > 0)
|
||||
{
|
||||
size_t nread = fread(buffer, sizeof(u_int32_t), 64, in_stream);
|
||||
if (nread >= 0)
|
||||
{
|
||||
union
|
||||
{
|
||||
u_int32_t l[4];
|
||||
unsigned char b[16];
|
||||
} row;
|
||||
int32_t i, j, k;
|
||||
|
||||
for (i = 0; i < nread; i += 4)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
row.l[j] = buffer[i + j];
|
||||
}
|
||||
|
||||
printf("%08x: ", addr);
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
printf("%08x ", row.l[j]);
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
|
||||
for (j = 0; j < 4 * sizeof(u_int32_t); j += sizeof(u_int32_t))
|
||||
{
|
||||
for (k = 0; k < sizeof(u_int32_t); k++)
|
||||
{
|
||||
if (isprint(row.b[j + k]))
|
||||
putchar(row.b[j + k]);
|
||||
else
|
||||
putchar('.');
|
||||
}
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
addr += 4 * sizeof(u_int32_t);
|
||||
}
|
||||
words_left -= nread;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* disassemble_text
|
||||
***********************************************************************/
|
||||
|
||||
static void disassemble_text(FILE * in_stream, struct nxflat_hdr_s *header)
|
||||
{
|
||||
if (print_insn_arm)
|
||||
{
|
||||
u_int32_t text_start = NXFLAT_HDR_SIZE;
|
||||
u_int32_t text_end = get_nxflat32(&header->h_datastart);
|
||||
int32_t insns_left = (text_end - text_start) / sizeof(u_int32_t);
|
||||
u_int32_t addr;
|
||||
u_int32_t buffer[64];
|
||||
|
||||
printf("\nXFLAT TEXT:\n\n");
|
||||
|
||||
/* Seek to the beginning of text in the file */
|
||||
if (fseek(in_stream, text_start, SEEK_SET) != 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Failed to seek to text in file: offset: %08x\n",
|
||||
text_start);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now dump all of the data reading 64 insns at a time */
|
||||
|
||||
addr = text_start;
|
||||
while (insns_left > 0)
|
||||
{
|
||||
size_t nread = fread(buffer, sizeof(u_int32_t), 64, in_stream);
|
||||
if (nread > 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nread; i++)
|
||||
{
|
||||
u_int32_t insn = buffer[i];
|
||||
if (big_endian)
|
||||
{
|
||||
insn = nxflat_swap32(insn);
|
||||
}
|
||||
|
||||
printf("%08x %08x\t", addr, insn);
|
||||
print_insn_arm(addr, stdout, insn);
|
||||
putchar('\n');
|
||||
addr += sizeof(u_int32_t);
|
||||
}
|
||||
insns_left -= nread;
|
||||
}
|
||||
else
|
||||
break;
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dump_imported_symbols
|
||||
***********************************************************************/
|
||||
|
||||
static void dump_imported_symbols(FILE * in_stream, struct nxflat_hdr_s *header)
|
||||
{
|
||||
struct nxflat_import_s import;
|
||||
u_int32_t import_offset;
|
||||
u_int32_t file_offset;
|
||||
char imported_symbol_name[NXFLAT_MAX_STRING_SIZE];
|
||||
int status;
|
||||
int i;
|
||||
|
||||
printf("\nIMPORTED SYMBOLS:\n");
|
||||
printf(" ADDRESS DATA SEGM SYMBOL NAME\n\n");
|
||||
|
||||
import_offset = get_nxflat32(&header->h_importsymbols);
|
||||
|
||||
for (i = 0; i < get_nxflat16(&header->h_importcount); i++)
|
||||
{
|
||||
/* Seek to the next imported symbol */
|
||||
|
||||
file_offset = i * sizeof(struct nxflat_import_s) + import_offset;
|
||||
|
||||
if (fseek(in_stream, file_offset, SEEK_SET) != 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: fseek to imported symbol %d struct failed\n",
|
||||
i);
|
||||
fprintf(stderr, " file_offset: %d, errno: %d\n", file_offset,
|
||||
errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Read the next import entry. */
|
||||
|
||||
status = fread((void *)&import,
|
||||
sizeof(struct nxflat_import_s), 1, in_stream);
|
||||
|
||||
if (status != 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Read imported symbol %d struct failed, "
|
||||
"errno: %d\n", i + 1, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (big_endian)
|
||||
{
|
||||
import.i_funcname = nxflat_swap32(import.i_funcname);
|
||||
import.i_funcaddress = nxflat_swap32(import.i_funcaddress);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
/* Print the raw info */
|
||||
|
||||
printf("[%4d %08x %08x]\n",
|
||||
i + 1, import.i_funcaddress, import.i_funcname);
|
||||
}
|
||||
|
||||
/* Seek to the function name in the file */
|
||||
|
||||
file_offset = import.i_funcname + NXFLAT_HDR_SIZE;
|
||||
if (0 != fseek(in_stream, file_offset, SEEK_SET))
|
||||
{
|
||||
fprintf(stderr, "ERROR: fseek to imported symbol %d name failed\n",
|
||||
i);
|
||||
fprintf(stderr, " file_offset: %d, errno: %d\n",
|
||||
file_offset, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Then, read the imported symbol name (assuming it is less than
|
||||
* NXFLAT_MAX_STRING_SIZE in length). */
|
||||
|
||||
status = fread((void *)imported_symbol_name, NXFLAT_MAX_STRING_SIZE,
|
||||
1, in_stream);
|
||||
if (status != 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Read imported symbol %d name failed, "
|
||||
"errno: %d\n", i + 1, errno);
|
||||
exit(1);
|
||||
}
|
||||
imported_symbol_name[NXFLAT_MAX_STRING_SIZE - 1] = '\0';
|
||||
|
||||
/* And print it */
|
||||
|
||||
printf("%5d ", i + 1);
|
||||
|
||||
if (import.i_funcaddress)
|
||||
{
|
||||
printf("%08x ", import.i_funcaddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("UNKNOWN ");
|
||||
}
|
||||
|
||||
printf("%s\n", imported_symbol_name);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dump_relocation_entries
|
||||
***********************************************************************/
|
||||
|
||||
static void dump_relocation_entries(FILE * in_stream, struct nxflat_hdr_s *header)
|
||||
{
|
||||
struct nxflat_reloc_s reloc;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
/* Seek to the beginning of the relocation records. */
|
||||
|
||||
if (0 != fseek(in_stream, get_nxflat32(&header->h_relocstart), SEEK_SET))
|
||||
{
|
||||
fprintf(stderr, "ERROR: fseek to reloc records failed, errno: %d\n",
|
||||
errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("\nRELOCATION ENTRIES:\n");
|
||||
printf(" DATA OFFS RELOC TYPE\n\n");
|
||||
|
||||
for (i = 0; i < get_nxflat32(&header->h_reloccount); i++)
|
||||
{
|
||||
/* Read the next reloction entry. */
|
||||
|
||||
status = fread((void *)&reloc, sizeof(struct nxflat_reloc_s), 1, in_stream);
|
||||
if (status != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading reloc record %d, errno: %d\n",
|
||||
i + 1, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef RELOCS_IN_NETWORK_ORDER
|
||||
{
|
||||
u_int32_t *ptmp;
|
||||
ptmp = (u_int32_t *) & reloc;
|
||||
*ptmp = get_nxflat32(ptmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NXFLAT_RELOC_TYPE(reloc.r_info) >= NXFLAT_RELOC_TYPE_NUM)
|
||||
{
|
||||
printf("%5d %08x UNKNOWN(%d)\n", i + 1,
|
||||
NXFLAT_RELOC_OFFSET(reloc.r_info), NXFLAT_RELOC_TYPE(reloc.r_info));
|
||||
fprintf(stderr, "Error eloc type out of range(%d)\n",
|
||||
NXFLAT_RELOC_TYPE(reloc.r_info));
|
||||
num_errors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%5d %08x %s\n",
|
||||
i + 1, NXFLAT_RELOC_OFFSET(reloc.r_info),
|
||||
reloc_type_string[NXFLAT_RELOC_TYPE(reloc.r_info)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dump_hdr
|
||||
***********************************************************************/
|
||||
|
||||
static void dump_hdr(struct nxflat_hdr_s *header)
|
||||
{
|
||||
/* Print the contents of the FLT header */
|
||||
|
||||
printf("\nXFLAT HEADER:\n");
|
||||
printf("\nMagic %c%c%c%c\n",
|
||||
header->h_magic[0], header->h_magic[1],
|
||||
header->h_magic[2], header->h_magic[3]);
|
||||
|
||||
printf("\nMEMORY MAP:\n");
|
||||
printf(" Text start %08lx\n", NXFLAT_HDR_SIZE);
|
||||
printf(" Entry point %08x\n", get_nxflat32(&header->h_entry));
|
||||
printf(" Data start %08x\n", get_nxflat32(&header->h_datastart));
|
||||
printf(" Data end %08x\n", get_nxflat32(&header->h_dataend) - 1);
|
||||
printf(" Bss start %08x\n", get_nxflat32(&header->h_dataend));
|
||||
printf(" Bss end %08x\n", get_nxflat32(&header->h_bssend) - 1);
|
||||
printf("TOTAL SIZE %08x\n\n", get_nxflat32(&header->h_bssend));
|
||||
printf("Stack size %08x\n", get_nxflat32(&header->h_stacksize));
|
||||
printf("\nRELOCATIONS:\n");
|
||||
printf(" Reloc start %08x\n", get_nxflat32(&header->h_relocstart));
|
||||
printf(" reloc count %d\n", get_nxflat32(&header->h_reloccount));
|
||||
printf("\nIMPORTED SYMBOLS:\n");
|
||||
printf(" Import start %08x\n", get_nxflat32(&header->h_importsymbols));
|
||||
printf(" Import count %d\n\n", get_nxflat16(&header->h_importcount));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* show_usage
|
||||
***********************************************************************/
|
||||
|
||||
static void show_usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options] <flat-filename>\n\n", program_name);
|
||||
#if 1
|
||||
fprintf(stderr, "Where options are one or more of the following:\n\n");
|
||||
#else
|
||||
fprintf(stderr, "Where options are one or more of the following. Note\n");
|
||||
fprintf(stderr, "that a space is always required between the option and\n");
|
||||
fprintf(stderr, "any following arguments\n\n");
|
||||
#endif
|
||||
fprintf(stderr, " -h Dump the XFLAT file header [not dumped]\n");
|
||||
fprintf(stderr, " -r Dump relocation entries [not dumped]\n");
|
||||
fprintf(stderr, " -i Dump the imported symbol table [not dumped]\n");
|
||||
fprintf(stderr, " -x Dump xFLT loader pathname [not dumped]\n");
|
||||
fprintf(stderr, " -c Disassemble the text section [not dumped]\n");
|
||||
fprintf(stderr, " -d Dump data section (hex) [not dumped]\n");
|
||||
fprintf(stderr, " -a Dump all of the above [not dumped]\n");
|
||||
#ifdef ARCH_BIG_ENDIAN
|
||||
fprintf(stderr, " -b Assume little-endian byteorder [big endian]\n");
|
||||
#else
|
||||
fprintf(stderr, " -b Assume big-endian byteorder [little endian]\n");
|
||||
#endif
|
||||
fprintf(stderr, " -v Output verbose debug info [no output]\n");
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* parse_args
|
||||
***********************************************************************/
|
||||
|
||||
static void parse_args(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
/* Save our name (for show_usage) */
|
||||
|
||||
program_name = argv[0];
|
||||
|
||||
/* At least three things must appear on the program line: the program name,
|
||||
* the BFD filname, and at least one option. */
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing required arguments\n\n");
|
||||
show_usage();
|
||||
}
|
||||
|
||||
/* Get miscellaneous options from the command line. */
|
||||
|
||||
while ((opt = getopt(argc, argv, "hrieLlxcbdav")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
||||
case 'h': /* Dump the flat file header */
|
||||
dump_header++;
|
||||
break;
|
||||
|
||||
case 'r': /* Dump the flat file header */
|
||||
dump_relocs++;
|
||||
break;
|
||||
|
||||
case 'i': /* Dump the imported symbol table */
|
||||
dump_imports++;
|
||||
break;
|
||||
|
||||
case 'c': /* Disassembly text */
|
||||
if (print_insn_arm)
|
||||
{
|
||||
dump_text++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("-c ignored: No disassembler available\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b': /* other-endian */
|
||||
#ifdef ARCH_BIG_ENDIAN
|
||||
big_endian = 0;
|
||||
#else
|
||||
big_endian++;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'd': /* Dump data */
|
||||
dump_data++;
|
||||
break;
|
||||
|
||||
case 'a': /* Dump everying */
|
||||
dump_header++;
|
||||
dump_relocs++;
|
||||
dump_imports++;
|
||||
dump_text++;
|
||||
dump_data++;
|
||||
break;
|
||||
|
||||
case 'v': /* Output verbose debug information */
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s Unknown option\n\n", argv[0]);
|
||||
show_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the name of the input BFD file. */
|
||||
|
||||
nxflat_filename = argv[argc - 1];
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* main
|
||||
***********************************************************************/
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
FILE *in_stream;
|
||||
struct nxflat_hdr_s header;
|
||||
|
||||
/* Get the input parameters */
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
/* Open the FLT file */
|
||||
|
||||
in_stream = fopen(nxflat_filename, "rb");
|
||||
if (NULL == in_stream)
|
||||
{
|
||||
fprintf(stderr, "Cannot open file %s for reading\n", nxflat_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Read the FLT header */
|
||||
|
||||
if (1 != fread((void *)&header, sizeof(struct nxflat_hdr_s), 1, in_stream))
|
||||
{
|
||||
fprintf(stderr, "Error reading flat header\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Dumping Flat Binary File: %s\n", nxflat_filename);
|
||||
|
||||
/* Dump the contents of the FLT header */
|
||||
|
||||
if (dump_header)
|
||||
{
|
||||
dump_hdr(&header);
|
||||
}
|
||||
|
||||
/* Dump the relocation entries */
|
||||
|
||||
if (dump_relocs)
|
||||
{
|
||||
dump_relocation_entries(in_stream, &header);
|
||||
}
|
||||
|
||||
/* Dump all imported symbols */
|
||||
|
||||
if (dump_imports)
|
||||
{
|
||||
dump_imported_symbols(in_stream, &header);
|
||||
}
|
||||
|
||||
if (dump_text)
|
||||
{
|
||||
disassemble_text(in_stream, &header);
|
||||
}
|
||||
|
||||
if (dump_data)
|
||||
{
|
||||
dump_hex_data(in_stream, &header);
|
||||
}
|
||||
|
||||
fclose(in_stream);
|
||||
|
||||
if (num_errors > 0)
|
||||
{
|
||||
fprintf(stderr, "Finished with %d errors\n", num_errors);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/***********************************************************************
|
||||
* toolchain/nxflat/reloc-macros.h
|
||||
*
|
||||
* Generic relocation support for BFD.
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of BFD, the Binary File Descriptor library.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************
|
||||
*
|
||||
* These macros are used by the various *.h target specific header
|
||||
* files to either generate an enum containing all the known relocations
|
||||
* for that target, or if RELOC_MACROS_GEN_FUNC is defined, a recognition
|
||||
* function is generated instead. (This is used by binutils/readelf.c)
|
||||
*
|
||||
* Given a header file like this:
|
||||
*
|
||||
* START_RELOC_NUMBERS (foo)
|
||||
* RELOC_NUMBER (R_foo_NONE, 0)
|
||||
* RELOC_NUMBER (R_foo_32, 1)
|
||||
* FAKE_RELOC (R_foo_illegal, 2)
|
||||
* EMPTY_RELOC (R_foo_max)
|
||||
* END_RELOC_NUMBERS
|
||||
*
|
||||
* Then the following will be produced by default (ie if
|
||||
* RELOC_MACROS_GEN_FUNC is *not* defined).
|
||||
*
|
||||
* enum foo
|
||||
* {
|
||||
* foo = -1,
|
||||
* R_foo_NONE = 0,
|
||||
* R_foo_32 = 1,
|
||||
* R_foo_illegal = 2,
|
||||
* R_foo_max
|
||||
* };
|
||||
*
|
||||
* If RELOC_MACROS_GEN_FUNC *is* defined, then instead the
|
||||
* following function will be generated:
|
||||
*
|
||||
* static const char * foo PARAMS ((unsigned long rtype));
|
||||
* static const char *
|
||||
* foo (rtype)
|
||||
* unsigned long rtype;
|
||||
* {
|
||||
* switch (rtype)
|
||||
* {
|
||||
* case 0: return "R_foo_NONE";
|
||||
* case 1: return "R_foo_32";
|
||||
* default: return NULL;
|
||||
* }
|
||||
* }
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _RELOC_MACROS_H
|
||||
# define _RELOC_MACROS_H
|
||||
|
||||
# ifdef RELOC_MACROS_GEN_FUNC
|
||||
|
||||
/* This function takes the relocation number and returns the
|
||||
* string version name of the name of that relocation. If
|
||||
* the relocation is not recognised, NULL is returned.
|
||||
*/
|
||||
|
||||
# define START_RELOC_NUMBERS(name) \
|
||||
static const char * name PARAMS ((unsigned long rtype)); \
|
||||
static const char * \
|
||||
name (rtype) \
|
||||
unsigned long rtype; \
|
||||
{ \
|
||||
switch (rtype) \
|
||||
{
|
||||
|
||||
# ifdef __STDC__
|
||||
# define RELOC_NUMBER(name, number) case number : return #name ;
|
||||
# else
|
||||
# define RELOC_NUMBER(name, number) case number : return "name" ;
|
||||
# endif
|
||||
|
||||
# define FAKE_RELOC(name, number)
|
||||
# define EMPTY_RELOC(name)
|
||||
|
||||
# define END_RELOC_NUMBERS \
|
||||
default: return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
# else /* Default to generating enum. */
|
||||
|
||||
/* Some compilers cannot cope with an enum that ends with a trailing
|
||||
* comma, so START_RELOC_NUMBERS creates a fake reloc entry, (initialised
|
||||
* to -1 so that the first real entry will still default to 0). Further
|
||||
* entries then prepend a comma to their definitions, creating a list
|
||||
* of enumerator entries that will satisfy these compilers.
|
||||
*/
|
||||
|
||||
# ifdef __STDC__
|
||||
# define START_RELOC_NUMBERS(name) enum name { _##name = -1
|
||||
# else
|
||||
# define START_RELOC_NUMBERS(name) enum name { name = -1
|
||||
# endif
|
||||
|
||||
# define RELOC_NUMBER(name, number) , name = number
|
||||
# define FAKE_RELOC(name, number) , name = number
|
||||
# define EMPTY_RELOC(name) , name
|
||||
# define END_RELOC_NUMBERS };
|
||||
|
||||
# endif
|
||||
|
||||
#endif /* RELOC_MACROS_H */
|
Loading…
Reference in New Issue