summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-06-18 17:14:13 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-06-18 17:14:13 +0000
commit050865808bfb56aa3f3dee42157779cf47b16f0e (patch)
tree5d14751d56799e813097236560ee020447470007 /misc
parentd12b92e21445508bcb0b8acff9b03e2c71b9da71 (diff)
downloadnuttx-050865808bfb56aa3f3dee42157779cf47b16f0e.tar.gz
nuttx-050865808bfb56aa3f3dee42157779cf47b16f0e.tar.bz2
nuttx-050865808bfb56aa3f3dee42157779cf47b16f0e.zip
First rough port of XFLAT tools
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1903 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'misc')
-rw-r--r--misc/buildroot/ChangeLog2
-rw-r--r--misc/buildroot/Config.in2
-rw-r--r--misc/buildroot/Makefile2
-rw-r--r--misc/buildroot/configs/arm-defconfig6
-rw-r--r--misc/buildroot/configs/arm7tdmi-defconfig-4.2.46
-rw-r--r--misc/buildroot/configs/arm920t-defconfig-4.2.46
-rw-r--r--misc/buildroot/configs/arm920t-defconfig-4.3.36
-rw-r--r--misc/buildroot/configs/arm926t-defconfig-4.2.46
-rw-r--r--misc/buildroot/configs/avr-defconfig-4.3.35
-rw-r--r--misc/buildroot/configs/bfin-defconfig-4.2.45
-rw-r--r--misc/buildroot/configs/cortexm3-defconfig-4.3.36
-rw-r--r--misc/buildroot/configs/cortexm3-defconfig-nxflat106
-rw-r--r--misc/buildroot/configs/h8300_defconfig5
-rw-r--r--misc/buildroot/configs/m32c-defconfig-4.2.45
-rw-r--r--misc/buildroot/configs/m68hc11-config5
-rw-r--r--misc/buildroot/configs/m68k-defconfig5
-rw-r--r--misc/buildroot/configs/sh-defconfig5
-rw-r--r--misc/buildroot/package/Makefile.in1
-rw-r--r--misc/buildroot/toolchain/Config.in1
-rw-r--r--misc/buildroot/toolchain/binutils/binutils.mk2
-rw-r--r--misc/buildroot/toolchain/gcc/Config.in16
-rw-r--r--misc/buildroot/toolchain/gcc/gcc-nuttx-3.x.mk3
-rw-r--r--misc/buildroot/toolchain/gcc/gcc-nuttx-4.x.mk3
-rw-r--r--misc/buildroot/toolchain/nxflat/Config.in9
-rw-r--r--misc/buildroot/toolchain/nxflat/Makefile74
-rw-r--r--misc/buildroot/toolchain/nxflat/arm/Makefile50
-rw-r--r--misc/buildroot/toolchain/nxflat/arm/arm.h157
-rw-r--r--misc/buildroot/toolchain/nxflat/arm/disarm.c1004
-rw-r--r--misc/buildroot/toolchain/nxflat/arm/dyncall_skeleton.def728
-rw-r--r--misc/buildroot/toolchain/nxflat/ldnxflat.c2088
-rw-r--r--misc/buildroot/toolchain/nxflat/mknxflat.c956
-rw-r--r--misc/buildroot/toolchain/nxflat/nxflat.h164
-rw-r--r--misc/buildroot/toolchain/nxflat/nxflat.mk63
-rw-r--r--misc/buildroot/toolchain/nxflat/readxflat.c669
-rw-r--r--misc/buildroot/toolchain/nxflat/reloc-macros.h123
35 files changed, 6287 insertions, 7 deletions
diff --git a/misc/buildroot/ChangeLog b/misc/buildroot/ChangeLog
index 86b43b443..9589df83d 100644
--- a/misc/buildroot/ChangeLog
+++ b/misc/buildroot/ChangeLog
@@ -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
+
diff --git a/misc/buildroot/Config.in b/misc/buildroot/Config.in
index 68d1cbe3b..66fc2bb97 100644
--- a/misc/buildroot/Config.in
+++ b/misc/buildroot/Config.in
@@ -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.
diff --git a/misc/buildroot/Makefile b/misc/buildroot/Makefile
index 9546d8a4a..5000dec8f 100644
--- a/misc/buildroot/Makefile
+++ b/misc/buildroot/Makefile
@@ -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
diff --git a/misc/buildroot/configs/arm-defconfig b/misc/buildroot/configs/arm-defconfig
index d6116f849..5d5b7c24c 100644
--- a/misc/buildroot/configs/arm-defconfig
+++ b/misc/buildroot/configs/arm-defconfig
@@ -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
@@ -97,6 +98,11 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+# BR2_PACKAGE_NXFLAT is not set
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/arm7tdmi-defconfig-4.2.4 b/misc/buildroot/configs/arm7tdmi-defconfig-4.2.4
index 92b1e526c..4802a5cac 100644
--- a/misc/buildroot/configs/arm7tdmi-defconfig-4.2.4
+++ b/misc/buildroot/configs/arm7tdmi-defconfig-4.2.4
@@ -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
@@ -100,6 +101,11 @@ BR2_INSTALL_LIBSTDCPP=y
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+# BR2_PACKAGE_NXFLAT is not set
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/arm920t-defconfig-4.2.4 b/misc/buildroot/configs/arm920t-defconfig-4.2.4
index 5e084b4c0..3701c0309 100644
--- a/misc/buildroot/configs/arm920t-defconfig-4.2.4
+++ b/misc/buildroot/configs/arm920t-defconfig-4.2.4
@@ -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
@@ -100,6 +101,11 @@ BR2_INSTALL_LIBSTDCPP=y
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+# BR2_PACKAGE_NXFLAT is not set
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/arm920t-defconfig-4.3.3 b/misc/buildroot/configs/arm920t-defconfig-4.3.3
index 1864e2515..096277c2f 100644
--- a/misc/buildroot/configs/arm920t-defconfig-4.3.3
+++ b/misc/buildroot/configs/arm920t-defconfig-4.3.3
@@ -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
@@ -100,6 +101,11 @@ BR2_INSTALL_LIBSTDCPP=y
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+# BR2_PACKAGE_NXFLAT is not set
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/arm926t-defconfig-4.2.4 b/misc/buildroot/configs/arm926t-defconfig-4.2.4
index 46dfc5a55..0e16d434d 100644
--- a/misc/buildroot/configs/arm926t-defconfig-4.2.4
+++ b/misc/buildroot/configs/arm926t-defconfig-4.2.4
@@ -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
@@ -100,6 +101,11 @@ BR2_INSTALL_LIBSTDCPP=y
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+# BR2_PACKAGE_NXFLAT is not set
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/avr-defconfig-4.3.3 b/misc/buildroot/configs/avr-defconfig-4.3.3
index 9f8aabc30..97ed51b19 100644
--- a/misc/buildroot/configs/avr-defconfig-4.3.3
+++ b/misc/buildroot/configs/avr-defconfig-4.3.3
@@ -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
@@ -80,6 +81,10 @@ BR2_INSTALL_LIBSTDCPP=y
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/bfin-defconfig-4.2.4 b/misc/buildroot/configs/bfin-defconfig-4.2.4
index de400eafb..574d68268 100644
--- a/misc/buildroot/configs/bfin-defconfig-4.2.4
+++ b/misc/buildroot/configs/bfin-defconfig-4.2.4
@@ -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
@@ -79,6 +80,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/cortexm3-defconfig-4.3.3 b/misc/buildroot/configs/cortexm3-defconfig-4.3.3
index 5c0c7a783..6fb291871 100644
--- a/misc/buildroot/configs/cortexm3-defconfig-4.3.3
+++ b/misc/buildroot/configs/cortexm3-defconfig-4.3.3
@@ -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
@@ -100,6 +101,11 @@ BR2_INSTALL_LIBSTDCPP=y
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+# BR2_PACKAGE_NXFLAT is not set
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/cortexm3-defconfig-nxflat b/misc/buildroot/configs/cortexm3-defconfig-nxflat
new file mode 100644
index 000000000..2628fc201
--- /dev/null
+++ b/misc/buildroot/configs/cortexm3-defconfig-nxflat
@@ -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"
diff --git a/misc/buildroot/configs/h8300_defconfig b/misc/buildroot/configs/h8300_defconfig
index 481b46f22..92af3b4a0 100644
--- a/misc/buildroot/configs/h8300_defconfig
+++ b/misc/buildroot/configs/h8300_defconfig
@@ -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
@@ -79,6 +80,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/m32c-defconfig-4.2.4 b/misc/buildroot/configs/m32c-defconfig-4.2.4
index 44d409850..02ffd21d0 100644
--- a/misc/buildroot/configs/m32c-defconfig-4.2.4
+++ b/misc/buildroot/configs/m32c-defconfig-4.2.4
@@ -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
@@ -79,6 +80,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/m68hc11-config b/misc/buildroot/configs/m68hc11-config
index 76fd3b8fb..8bba821ca 100644
--- a/misc/buildroot/configs/m68hc11-config
+++ b/misc/buildroot/configs/m68hc11-config
@@ -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
@@ -79,6 +80,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/m68k-defconfig b/misc/buildroot/configs/m68k-defconfig
index afdc84175..e1e0eedb9 100644
--- a/misc/buildroot/configs/m68k-defconfig
+++ b/misc/buildroot/configs/m68k-defconfig
@@ -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
@@ -79,6 +80,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/configs/sh-defconfig b/misc/buildroot/configs/sh-defconfig
index 175899e1e..d057b5503 100644
--- a/misc/buildroot/configs/sh-defconfig
+++ b/misc/buildroot/configs/sh-defconfig
@@ -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
@@ -86,6 +87,10 @@ BR2_EXTRA_GCC_CONFIG_OPTIONS=""
# BR2_PACKAGE_GDB_HOST is not set
#
+# NuttX Binary Support
+#
+
+#
# Common Toolchain Options
#
# BR2_PACKAGE_SSTRIP_TARGET is not set
diff --git a/misc/buildroot/package/Makefile.in b/misc/buildroot/package/Makefile.in
index 1338356d4..d79783343 100644
--- a/misc/buildroot/package/Makefile.in
+++ b/misc/buildroot/package/Makefile.in
@@ -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++
diff --git a/misc/buildroot/toolchain/Config.in b/misc/buildroot/toolchain/Config.in
index 1675c32d4..9acc55783 100644
--- a/misc/buildroot/toolchain/Config.in
+++ b/misc/buildroot/toolchain/Config.in
@@ -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"
diff --git a/misc/buildroot/toolchain/binutils/binutils.mk b/misc/buildroot/toolchain/binutils/binutils.mk
index 49ae481ae..3e9d5aced 100644
--- a/misc/buildroot/toolchain/binutils/binutils.mk
+++ b/misc/buildroot/toolchain/binutils/binutils.mk
@@ -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)
diff --git a/misc/buildroot/toolchain/gcc/Config.in b/misc/buildroot/toolchain/gcc/Config.in
index b8a25e64f..dfc9b5648 100644
--- a/misc/buildroot/toolchain/gcc/Config.in
+++ b/misc/buildroot/toolchain/gcc/Config.in
@@ -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
diff --git a/misc/buildroot/toolchain/gcc/gcc-nuttx-3.x.mk b/misc/buildroot/toolchain/gcc/gcc-nuttx-3.x.mk
index ae3081d58..cc55e5b43 100644
--- a/misc/buildroot/toolchain/gcc/gcc-nuttx-3.x.mk
+++ b/misc/buildroot/toolchain/gcc/gcc-nuttx-3.x.mk
@@ -220,4 +220,7 @@ gcc-clean:
gcc-dirclean:
rm -rf $(GCC_BUILD_DIR)
+ifeq ($(strip $(BR2_PACKAGE_GCC)),y)
+TARGETS += gcc
+endif
endif
diff --git a/misc/buildroot/toolchain/gcc/gcc-nuttx-4.x.mk b/misc/buildroot/toolchain/gcc/gcc-nuttx-4.x.mk
index 1a2dbcb3f..68f852143 100644
--- a/misc/buildroot/toolchain/gcc/gcc-nuttx-4.x.mk
+++ b/misc/buildroot/toolchain/gcc/gcc-nuttx-4.x.mk
@@ -200,4 +200,7 @@ gcc-clean:
gcc-dirclean:
rm -rf $(GCC_BUILD_DIR)
+ifeq ($(strip $(BR2_PACKAGE_GCC)),y)
+TARGETS += gcc
+endif
endif
diff --git a/misc/buildroot/toolchain/nxflat/Config.in b/misc/buildroot/toolchain/nxflat/Config.in
new file mode 100644
index 000000000..a977bede1
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/Config.in
@@ -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
+
diff --git a/misc/buildroot/toolchain/nxflat/Makefile b/misc/buildroot/toolchain/nxflat/Makefile
new file mode 100644
index 000000000..287dda7d6
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/Makefile
@@ -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
+
diff --git a/misc/buildroot/toolchain/nxflat/arm/Makefile b/misc/buildroot/toolchain/nxflat/arm/Makefile
new file mode 100644
index 000000000..68abf2afd
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/arm/Makefile
@@ -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
+
diff --git a/misc/buildroot/toolchain/nxflat/arm/arm.h b/misc/buildroot/toolchain/nxflat/arm/arm.h
new file mode 100644
index 000000000..e761dfe68
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/arm/arm.h
@@ -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 */
diff --git a/misc/buildroot/toolchain/nxflat/arm/disarm.c b/misc/buildroot/toolchain/nxflat/arm/disarm.c
new file mode 100644
index 000000000..ad430472f
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/arm/disarm.c
@@ -0,0 +1,1004 @@
+/***********************************************************************
+ * toolchain/nxflat/disasm.c
+ * ARM Disassembler
+ *
+ * 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 derived from parts of of the binutils package
+ *
+ * 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
+ *
+ ***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#define BDISP(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000) /* 26 bit */
+
+struct arm_opcode
+{
+ u_int32_t value;
+ u_int32_t mask;
+ char *assembler;
+};
+
+static char * arm_conditional[] =
+{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
+
+typedef struct
+{
+ const char *name;
+ const char *description;
+ const char *reg_names[16];
+}
+arm_regname;
+
+static arm_regname regnames[] =
+{
+ { "raw" , "Select raw register names",
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
+ { "gcc", "Select register names used by GCC",
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
+ { "std", "Select register names used in ARM's ISA documentation",
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
+ { "apcs", "Select register names used in the APCS",
+ { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
+ { "atpcs", "Select register names used in the ATPCS",
+ { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
+ { "special-atpcs", "Select special register names used in the ATPCS",
+ { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}
+};
+
+static unsigned int regname_selected = 1;
+
+#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
+#define arm_regnames regnames[regname_selected].reg_names
+
+static char * arm_fp_const[] =
+{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
+
+static char * arm_shift[] =
+{"lsl", "lsr", "asr", "ror"};
+
+static struct arm_opcode arm_opcodes[] =
+ {
+ /* ARM instructions. */
+ {0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
+ {0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
+ {0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
+ {0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
+ {0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
+
+ /* V5J instruction. */
+ {0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
+
+ /* XScale instructions. */
+ {0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
+ {0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
+ {0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
+ {0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
+ {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
+ {0xf450f000, 0xfc70f000, "pld\t%a"},
+
+ /* V5 Instructions. */
+ {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
+ {0xfa000000, 0xfe000000, "blx\t%B"},
+ {0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
+ {0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
+ {0xfc100000, 0xfe100000, "ldc2%22'l\t%8-11d, cr%12-15d, %A"},
+ {0xfc000000, 0xfe100000, "stc2%22'l\t%8-11d, cr%12-15d, %A"},
+ {0xfe000000, 0xff000010, "cdp2\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+
+ /* V5E "El Segundo" Instructions. */
+ {0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
+ {0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
+ {0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+
+ {0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+
+ {0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+
+ {0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
+ {0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
+ {0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
+ {0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
+
+ {0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
+ {0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
+
+ {0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
+ {0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
+ {0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
+ {0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
+
+ {0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+ {0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+
+ /* ARM Instructions. */
+ {0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
+ {0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
+ {0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
+ {0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
+ {0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
+ {0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
+ {0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
+ {0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
+ {0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
+ {0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
+ {0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
+ {0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
+ {0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
+ {0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
+ {0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
+ {0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
+ {0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
+ {0x06000010, 0x0e000010, "undefined"},
+ {0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
+ {0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
+ {0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
+ {0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
+ {0x0f000000, 0x0f000000, "swi%c\t%0-23x"},
+
+ /* Floating point coprocessor (FPA) instructions */
+ {0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
+ {0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
+ {0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
+ {0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
+ {0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
+ {0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
+ {0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
+ {0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
+ {0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
+ {0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
+ {0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
+ {0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
+ {0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
+ {0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
+ {0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
+ {0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
+ {0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
+ {0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
+ {0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
+ {0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
+ {0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
+ {0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
+ {0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
+ {0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
+ {0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
+ {0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
+ {0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
+ {0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
+ {0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
+ {0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
+
+ /* Floating point coprocessor (VFP) instructions */
+ {0x0eb00bc0, 0x0fff0ff0, "fabsd%c\t%1z, %0z"},
+ {0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%1y, %0y"},
+ {0x0e300b00, 0x0ff00ff0, "faddd%c\t%1z, %2z, %0z"},
+ {0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %1y"},
+ {0x0eb40b40, 0x0fff0f70, "fcmp%7'ed%c\t%1z, %0z"},
+ {0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%1y, %0y"},
+ {0x0eb50b40, 0x0fff0f70, "fcmp%7'ezd%c\t%1z"},
+ {0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%1y"},
+ {0x0eb00b40, 0x0fff0ff0, "fcpyd%c\t%1z, %0z"},
+ {0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%1y, %0y"},
+ {0x0eb70ac0, 0x0fff0fd0, "fcvtds%c\t%1z, %0y"},
+ {0x0eb70bc0, 0x0fbf0ff0, "fcvtsd%c\t%1y, %0z"},
+ {0x0e800b00, 0x0ff00ff0, "fdivd%c\t%1z, %2z, %0z"},
+ {0x0e800a00, 0x0fb00f50, "fdivs%c\t%1y, %2y, %0y"},
+ {0x0d100b00, 0x0f700f00, "fldd%c\t%1z, %A"},
+ {0x0c900b00, 0x0fd00f00, "fldmia%0?xd%c\t%16-19r%21'!, %3z"},
+ {0x0d300b00, 0x0ff00f00, "fldmdb%0?xd%c\t%16-19r!, %3z"},
+ {0x0d100a00, 0x0f300f00, "flds%c\t%1y, %A"},
+ {0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %3y"},
+ {0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %3y"},
+ {0x0e000b00, 0x0ff00ff0, "fmacd%c\t%1z, %2z, %0z"},
+ {0x0e000a00, 0x0fb00f50, "fmacs%c\t%1y, %2y, %0y"},
+ {0x0e200b10, 0x0ff00fff, "fmdhr%c\t%2z, %12-15r"},
+ {0x0e000b10, 0x0ff00fff, "fmdlr%c\t%2z, %12-15r"},
+ {0x0c400b10, 0x0ff00ff0, "fmdrr%c\t%0z, %12-15r, %16-19r"},
+ {0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %2z"},
+ {0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %2z"},
+ {0x0c500b10, 0x0ff00ff0, "fmrrd%c\t%12-15r, %16-19r, %0z"},
+ {0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %4y"},
+ {0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %2y"},
+ {0x0ef1fa10, 0x0fffffff, "fmstat%c"},
+ {0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
+ {0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
+ {0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
+ {0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
+ {0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
+ {0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def 0x%16-19x>"},
+ {0x0e100b00, 0x0ff00ff0, "fmscd%c\t%1z, %2z, %0z"},
+ {0x0e100a00, 0x0fb00f50, "fmscs%c\t%1y, %2y, %0y"},
+ {0x0e000a10, 0x0ff00f7f, "fmsr%c\t%2y, %12-15r"},
+ {0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%12-15r, %16-19r, %4y"},
+ {0x0e200b00, 0x0ff00ff0, "fmuld%c\t%1z, %2z, %0z"},
+ {0x0e200a00, 0x0fb00f50, "fmuls%c\t%1y, %2y, %0y"},
+ {0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
+ {0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
+ {0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
+ {0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
+ {0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
+ {0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def 0x%16-19x>, %12-15r"},
+ {0x0eb10b40, 0x0fff0ff0, "fnegd%c\t%1z, %0z"},
+ {0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%1y, %0y"},
+ {0x0e000b40, 0x0ff00ff0, "fnmacd%c\t%1z, %2z, %0z"},
+ {0x0e000a40, 0x0fb00f50, "fnmacs%c\t%1y, %2y, %0y"},
+ {0x0e100b40, 0x0ff00ff0, "fnmscd%c\t%1z, %2z, %0z"},
+ {0x0e100a40, 0x0fb00f50, "fnmscs%c\t%1y, %2y, %0y"},
+ {0x0e200b40, 0x0ff00ff0, "fnmuld%c\t%1z, %2z, %0z"},
+ {0x0e200a40, 0x0fb00f50, "fnmuls%c\t%1y, %2y, %0y"},
+ {0x0eb80bc0, 0x0fff0fd0, "fsitod%c\t%1z, %0y"},
+ {0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%1y, %0y"},
+ {0x0eb10bc0, 0x0fff0ff0, "fsqrtd%c\t%1z, %0z"},
+ {0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%1y, %0y"},
+ {0x0d000b00, 0x0f700f00, "fstd%c\t%1z, %A"},
+ {0x0c800b00, 0x0fd00f00, "fstmia%0?xd%c\t%16-19r%21'!, %3z"},
+ {0x0d200b00, 0x0ff00f00, "fstmdb%0?xd%c\t%16-19r!, %3z"},
+ {0x0d000a00, 0x0f300f00, "fsts%c\t%1y, %A"},
+ {0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %3y"},
+ {0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %3y"},
+ {0x0e300b40, 0x0ff00ff0, "fsubd%c\t%1z, %2z, %0z"},
+ {0x0e300a40, 0x0fb00f50, "fsubs%c\t%1y, %2y, %0y"},
+ {0x0ebc0b40, 0x0fbe0f70, "fto%16?sui%7'zd%c\t%1y, %0z"},
+ {0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%1y, %0y"},
+ {0x0eb80b40, 0x0fff0fd0, "fuitod%c\t%1z, %0y"},
+ {0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%1y, %0y"},
+
+ /* Cirrus coprocessor instructions. */
+ {0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
+ {0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
+ {0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
+ {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
+ {0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
+ {0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
+ {0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
+ {0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
+ {0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
+ {0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
+ {0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
+ {0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
+ {0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
+ {0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
+ {0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
+ {0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
+ {0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
+ {0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
+ {0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
+ {0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
+ {0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
+ {0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
+ {0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
+ {0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
+ {0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
+ {0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
+ {0x0e100610, 0x0ff0fff0, "cfmval32%c\tmvax%0-3d, mvfx%16-19d"},
+ {0x0e000610, 0x0ff0fff0, "cfmv32al%c\tmvfx%0-3d, mvax%16-19d"},
+ {0x0e100630, 0x0ff0fff0, "cfmvam32%c\tmvax%0-3d, mvfx%16-19d"},
+ {0x0e000630, 0x0ff0fff0, "cfmv32am%c\tmvfx%0-3d, mvax%16-19d"},
+ {0x0e100650, 0x0ff0fff0, "cfmvah32%c\tmvax%0-3d, mvfx%16-19d"},
+ {0x0e000650, 0x0ff0fff0, "cfmv32ah%c\tmvfx%0-3d, mvax%16-19d"},
+ {0x0e000670, 0x0ff0fff0, "cfmv32a%c\tmvfx%0-3d, mvax%16-19d"},
+ {0x0e100670, 0x0ff0fff0, "cfmva32%c\tmvax%0-3d, mvfx%16-19d"},
+ {0x0e000690, 0x0ff0fff0, "cfmv64a%c\tmvdx%0-3d, mvax%16-19d"},
+ {0x0e100690, 0x0ff0fff0, "cfmva64%c\tmvax%0-3d, mvdx%16-19d"},
+ {0x0e1006b0, 0x0ff0fff0, "cfmvsc32%c\tdspsc, mvfx%16-19d"},
+ {0x0e0006b0, 0x0ff0fff0, "cfmv32sc%c\tmvfx%0-3d, dspsc"},
+ {0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
+ {0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
+ {0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
+ {0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
+ {0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
+ {0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
+ {0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
+ {0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
+ {0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
+ {0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
+ {0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
+ {0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
+ {0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
+ {0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
+ {0x0e000500, 0x0ff00f00, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
+ {0x0e200500, 0x0ff00f00, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
+ {0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
+ {0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
+ {0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
+ {0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
+ {0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
+ {0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
+ {0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
+ {0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+ {0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+ {0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+ {0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+ {0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+ {0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+ {0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
+ {0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
+ {0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
+ {0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
+ {0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+ {0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+ {0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+ {0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e000600, 0x0ff00f00, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e100600, 0x0ff00f00, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e200600, 0x0ff00f00, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {0x0e300600, 0x0ff00f00, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
+
+ /* Generic coprocessor instructions */
+ {0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
+ {0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
+
+ /* The rest. */
+ {0x00000000, 0x00000000, "undefined instruction %0-31x"},
+ {0x00000000, 0x00000000, 0}
+ };
+
+static inline void print_address(FILE *stream, u_int32_t offset)
+{
+ fprintf(stream, "0x%08x", offset);
+}
+
+static void arm_decode_shift(u_int32_t given, FILE *stream)
+{
+ fprintf(stream, "%s", arm_regnames[given & 0xf]);
+
+ if ((given & 0xff0) != 0)
+ {
+ if ((given & 0x10) == 0)
+ {
+ int amount = (given & 0xf80) >> 7;
+ int shift = (given & 0x60) >> 5;
+
+ if (amount == 0)
+ {
+ if (shift == 3)
+ {
+ fprintf(stream, ", rrx");
+ return;
+ }
+
+ amount = 32;
+ }
+
+ fprintf(stream, ", %s #%d", arm_shift[shift], amount);
+ }
+ else
+ fprintf(stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
+ arm_regnames[(given & 0xf00) >> 8]);
+ }
+}
+
+int print_insn_arm(u_int32_t pc, FILE *stream, u_int32_t given)
+{
+ struct arm_opcode *insn;
+
+ for (insn = arm_opcodes; insn->assembler; insn++)
+ {
+ if ((given & insn->mask) == insn->value)
+ {
+ char * c;
+
+ for (c = insn->assembler; *c; c++)
+ {
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case '%':
+ fprintf(stream, "%%");
+ break;
+
+ case 'a':
+ if (((given & 0x000f0000) == 0x000f0000)
+ && ((given & 0x02000000) == 0))
+ {
+ int offset = given & 0xfff;
+
+ fprintf(stream, "[pc");
+
+ if (given & 0x01000000)
+ {
+ if ((given & 0x00800000) == 0)
+ offset = - offset;
+
+ /* Pre-indexed. */
+ fprintf(stream, ", #%d]", offset);
+
+ offset += pc + 8;
+
+ /* Cope with the possibility of write-back
+ being used. Probably a very dangerous thing
+ for the programmer to do, but who are we to
+ argue ? */
+ if (given & 0x00200000)
+ fprintf(stream, "!");
+ }
+ else
+ {
+ /* Post indexed. */
+ fprintf(stream, "], #%d", offset);
+
+ /* ie ignore the offset. */
+ offset = pc + 8;
+ }
+
+ fprintf(stream, "\t; ");
+ print_address(stream, offset);
+ }
+ else
+ {
+ fprintf(stream, "[%s",
+ arm_regnames[(given >> 16) & 0xf]);
+ if ((given & 0x01000000) != 0)
+ {
+ if ((given & 0x02000000) == 0)
+ {
+ int offset = given & 0xfff;
+ if (offset)
+ fprintf(stream, ", %s#%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ }
+ else
+ {
+ fprintf(stream, ", %s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""));
+ arm_decode_shift (given, stream);
+ }
+
+ fprintf(stream, "]%s",
+ ((given & 0x00200000) != 0) ? "!" : "");
+ }
+ else
+ {
+ if ((given & 0x02000000) == 0)
+ {
+ int offset = given & 0xfff;
+ if (offset)
+ fprintf(stream, "], %s#%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ else
+ fprintf(stream, "]");
+ }
+ else
+ {
+ fprintf(stream, "], %s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""));
+ arm_decode_shift (given, stream);
+ }
+ }
+ }
+ break;
+
+ case 's':
+ if ((given & 0x004f0000) == 0x004f0000)
+ {
+ /* PC relative with immediate offset. */
+ int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+
+ if ((given & 0x00800000) == 0)
+ offset = -offset;
+
+ fprintf(stream, "[pc, #%d]\t; ", offset);
+
+ print_address(stream, offset + pc + 8);
+ }
+ else
+ {
+ fprintf(stream, "[%s",
+ arm_regnames[(given >> 16) & 0xf]);
+ if ((given & 0x01000000) != 0)
+ {
+ /* Pre-indexed. */
+ if ((given & 0x00400000) == 0x00400000)
+ {
+ /* Immediate. */
+ int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+ if (offset)
+ fprintf(stream, ", %s#%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ }
+ else
+ {
+ /* Register. */
+ fprintf(stream, ", %s%s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""),
+ arm_regnames[given & 0xf]);
+ }
+
+ fprintf(stream, "]%s",
+ ((given & 0x00200000) != 0) ? "!" : "");
+ }
+ else
+ {
+ /* Post-indexed. */
+ if ((given & 0x00400000) == 0x00400000)
+ {
+ /* Immediate. */
+ int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+ if (offset)
+ fprintf(stream, "], %s#%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ else
+ fprintf(stream, "]");
+ }
+ else
+ {
+ /* Register. */
+ fprintf(stream, "], %s%s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""),
+ arm_regnames[given & 0xf]);
+ }
+ }
+ }
+ break;
+
+ case 'b':
+ print_address(stream, BDISP (given) * 4 + pc + 8);
+ break;
+
+ case 'c':
+ fprintf(stream, "%s",
+ arm_conditional [(given >> 28) & 0xf]);
+ break;
+
+ case 'm':
+ {
+ int started = 0;
+ int reg;
+
+ fprintf(stream, "{");
+ for (reg = 0; reg < 16; reg++)
+ if ((given & (1 << reg)) != 0)
+ {
+ if (started)
+ fprintf(stream, ", ");
+ started = 1;
+ fprintf(stream, "%s", arm_regnames[reg]);
+ }
+ fprintf(stream, "}");
+ }
+ break;
+
+ case 'o':
+ if ((given & 0x02000000) != 0)
+ {
+ int rotate = (given & 0xf00) >> 7;
+ int immed = (given & 0xff);
+ immed = (((immed << (32 - rotate))
+ | (immed >> rotate)) & 0xffffffff);
+ fprintf(stream, "#%d\t; 0x%x", immed, immed);
+ }
+ else
+ arm_decode_shift (given, stream);
+ break;
+
+ case 'p':
+ if ((given & 0x0000f000) == 0x0000f000)
+ fprintf(stream, "p");
+ break;
+
+ case 't':
+ if ((given & 0x01200000) == 0x00200000)
+ fprintf(stream, "t");
+ break;
+
+ case 'A':
+ fprintf(stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+ if ((given & 0x01000000) != 0)
+ {
+ int offset = given & 0xff;
+ if (offset)
+ fprintf(stream, ", %s#%d]%s",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4,
+ ((given & 0x00200000) != 0 ? "!" : ""));
+ else
+ fprintf(stream, "]");
+ }
+ else
+ {
+ int offset = given & 0xff;
+ if (offset)
+ fprintf(stream, "], %s#%d",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4);
+ else
+ fprintf(stream, "]");
+ }
+ break;
+
+ case 'B':
+ /* Print ARM V5 BLX(1) address: pc+25 bits. */
+ {
+ u_int32_t address;
+ u_int32_t offset = 0;
+
+ if (given & 0x00800000)
+ /* Is signed, hi bits should be ones. */
+ offset = (-1) ^ 0x00ffffff;
+
+ /* Offset is (SignExtend(offset field)<<2). */
+ offset += given & 0x00ffffff;
+ offset <<= 2;
+ address = offset + pc + 8;
+
+ if (given & 0x01000000)
+ /* H bit allows addressing to 2-byte boundaries. */
+ address += 2;
+
+ print_address(stream, address);
+ }
+ break;
+
+ case 'I':
+ /* Print a Cirrus/DSP shift immediate. */
+ /* Immediates are 7bit signed ints with bits 0..3 in
+ bits 0..3 of opcode and bits 4..6 in bits 5..7
+ of opcode. */
+ {
+ int imm;
+
+ imm = (given & 0xf) | ((given & 0xe0) >> 1);
+
+ /* Is ``imm'' a negative number? */
+ if (imm & 0x40)
+ imm |= (-1 << 7);
+
+ fprintf(stream, "%d", imm);
+ }
+
+ break;
+
+ case 'C':
+ fprintf(stream, "_");
+ if (given & 0x80000)
+ fprintf(stream, "f");
+ if (given & 0x40000)
+ fprintf(stream, "s");
+ if (given & 0x20000)
+ fprintf(stream, "x");
+ if (given & 0x10000)
+ fprintf(stream, "c");
+ break;
+
+ case 'F':
+ switch (given & 0x00408000)
+ {
+ case 0:
+ fprintf(stream, "4");
+ break;
+ case 0x8000:
+ fprintf(stream, "1");
+ break;
+ case 0x00400000:
+ fprintf(stream, "2");
+ break;
+ default:
+ fprintf(stream, "3");
+ }
+ break;
+
+ case 'P':
+ switch (given & 0x00080080)
+ {
+ case 0:
+ fprintf(stream, "s");
+ break;
+ case 0x80:
+ fprintf(stream, "d");
+ break;
+ case 0x00080000:
+ fprintf(stream, "e");
+ break;
+ default:
+ fprintf(stream, "<illegal precision>");
+ break;
+ }
+ break;
+ case 'Q':
+ switch (given & 0x00408000)
+ {
+ case 0:
+ fprintf(stream, "s");
+ break;
+ case 0x8000:
+ fprintf(stream, "d");
+ break;
+ case 0x00400000:
+ fprintf(stream, "e");
+ break;
+ default:
+ fprintf(stream, "p");
+ break;
+ }
+ break;
+ case 'R':
+ switch (given & 0x60)
+ {
+ case 0:
+ break;
+ case 0x20:
+ fprintf(stream, "p");
+ break;
+ case 0x40:
+ fprintf(stream, "m");
+ break;
+ default:
+ fprintf(stream, "z");
+ break;
+ }
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int bitstart = *c++ - '0';
+ int bitend = 0;
+ while (*c >= '0' && *c <= '9')
+ bitstart = (bitstart * 10) + *c++ - '0';
+
+ switch (*c)
+ {
+ case '-':
+ c++;
+
+ while (*c >= '0' && *c <= '9')
+ bitend = (bitend * 10) + *c++ - '0';
+
+ if (!bitend)
+ return -1;
+
+ switch (*c)
+ {
+ case 'r':
+ {
+ int32_t reg;
+
+ reg = given >> bitstart;
+ reg &= (2 << (bitend - bitstart)) - 1;
+
+ fprintf(stream, "%s", arm_regnames[reg]);
+ }
+ break;
+ case 'd':
+ {
+ int32_t reg;
+
+ reg = given >> bitstart;
+ reg &= (2 << (bitend - bitstart)) - 1;
+
+ fprintf(stream, "%d", reg);
+ }
+ break;
+ case 'x':
+ {
+ int32_t reg;
+
+ reg = given >> bitstart;
+ reg &= (2 << (bitend - bitstart)) - 1;
+
+ fprintf(stream, "0x%08x", reg);
+
+ /* Some SWI instructions have special
+ meanings. */
+ if ((given & 0x0fffffff) == 0x0FF00000)
+ fprintf(stream, "\t; IMB");
+ else if ((given & 0x0fffffff) == 0x0FF00001)
+ fprintf(stream, "\t; IMBRange");
+ }
+ break;
+ case 'X':
+ {
+ int32_t reg;
+
+ reg = given >> bitstart;
+ reg &= (2 << (bitend - bitstart)) - 1;
+
+ fprintf(stream, "%01x", reg & 0xf);
+ }
+ break;
+ case 'f':
+ {
+ int32_t reg;
+
+ reg = given >> bitstart;
+ reg &= (2 << (bitend - bitstart)) - 1;
+
+ if (reg > 7)
+ fprintf(stream, "#%s",
+ arm_fp_const[reg & 7]);
+ else
+ fprintf(stream, "f%d", reg);
+ }
+ break;
+ default:
+ return -1;
+ }
+ break;
+
+ case 'y':
+ case 'z':
+ {
+ int single = *c == 'y';
+ int regno;
+
+ switch (bitstart)
+ {
+ case 4: /* Sm pair */
+ fprintf(stream, "{");
+ /* Fall through. */
+ case 0: /* Sm, Dm */
+ regno = given & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 5) & 1;
+ }
+ break;
+
+ case 1: /* Sd, Dd */
+ regno = (given >> 12) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 22) & 1;
+ }
+ break;
+
+ case 2: /* Sn, Dn */
+ regno = (given >> 16) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 7) & 1;
+ }
+ break;
+
+ case 3: /* List */
+ fprintf(stream, "{");
+ regno = (given >> 12) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 22) & 1;
+ }
+ break;
+
+
+ default:
+ return -1;
+ }
+
+ fprintf(stream, "%c%d", single ? 's' : 'd', regno);
+
+ if (bitstart == 3)
+ {
+ int count = given & 0xff;
+
+ if (single == 0)
+ count >>= 1;
+
+ if (--count)
+ {
+ fprintf(stream, "-%c%d",
+ single ? 's' : 'd',
+ regno + count);
+ }
+
+ fprintf(stream, "}");
+ }
+ else if (bitstart == 4)
+ fprintf(stream, ", %c%d}", single ? 's' : 'd',
+ regno + 1);
+
+ break;
+ }
+
+ case '`':
+ c++;
+ if ((given & (1 << bitstart)) == 0)
+ fprintf(stream, "%c", *c);
+ break;
+ case '\'':
+ c++;
+ if ((given & (1 << bitstart)) != 0)
+ fprintf(stream, "%c", *c);
+ break;
+ case '?':
+ ++c;
+ if ((given & (1 << bitstart)) != 0)
+ fprintf(stream, "%c", *c++);
+ else
+ fprintf(stream, "%c", *++c);
+ break;
+ default:
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+ }
+ }
+ else
+ fprintf(stream, "%c", *c);
+ }
+ return 0;
+ }
+ }
+ return -1;
+}
diff --git a/misc/buildroot/toolchain/nxflat/arm/dyncall_skeleton.def b/misc/buildroot/toolchain/nxflat/arm/dyncall_skeleton.def
new file mode 100644
index 000000000..29551163b
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/arm/dyncall_skeleton.def
@@ -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";
+
+
+
+
diff --git a/misc/buildroot/toolchain/nxflat/ldnxflat.c b/misc/buildroot/toolchain/nxflat/ldnxflat.c
new file mode 100644
index 000000000..c2026f97d
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/ldnxflat.c
@@ -0,0 +1,2088 @@
+/***********************************************************************
+ * toolchain/nxflat/ldnxflat.c
+ * Convert ELF (or any BFD format) to NXFLAT binary format
+ *
+ * ldnxflat takes a fully resolvable elf binary which was linked with -r
+ * and resolves all references, then generates relocation table entries for
+ * any relocation entries in data sections. This is designed to work with
+ * the options -fpic -msingle-pic-base -mno-got (or -membedded-pic)
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ *
+ * Modified from ldelf2xflat (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>
+ *
+ * Extended from the FLAT ldnxflat.c (original copyright below )
+ *
+ * Copyright (C) 2000 NETsilicon, Inc.
+ * Copyright (C) 2000 WireSpeed Communications Corp
+ *
+ * author : Joe deBlaquiere ( joe@wirespeed.com )
+ *
+ * converted from elf2flt.c ( original copyright below )
+ *
+ * elf2flt copyright :
+ *
+ * (c) 1999, Greg Ungerer <gerg@moreton.com.au>
+ * (c) 1999, Phil Blundell, Nexus Electronics Ltd <pb@nexus.co.uk>
+ *
+ * Hacked this about badly to fully support relocating binaries.
+ *
+ * Originally obj-res.c
+ *
+ * (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
+ * (c) 1998, D. Jeff Dionne
+ * (c) 1998, The Silver Hammer Group Ltd.
+ * (c) 1996, 1997 Dionne & Associates
+ * jeff@ryeham.ee.ryerson.ca
+ *
+ * Relocation added March 1997, Kresten Krab Thorup
+ * krab@california.daimi.aau.dk
+ *
+ * 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
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ * Included Files
+ ***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdarg.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include "bfd.h"
+#include "arch/arm.h"
+#include "nxflat.h"
+
+/***********************************************************************
+ * Compilation Switches
+ ***********************************************************************/
+
+/* #define RELOCS_IN_NETWORK_ORDER 1 */
+
+#define LIBS_CAN_INCLUDE_LIBS 1
+
+/***********************************************************************
+ * Definitions
+ ***********************************************************************/
+
+#ifndef PARAMS
+# define PARAMS(x) x
+#endif
+
+#ifdef __CYGWIN32__
+# define O_PLATFORM O_BINARY
+#else
+# define O_PLATFORM 0
+#endif
+
+#define MAX_SECTIONS 16
+#define DEFAULT_STACK_SIZE 4096
+
+#define IS_GLOBAL(x) ((((x)->flags)&(BSF_GLOBAL))!=0)
+
+#define NXFLAT_HDR_SIZE sizeof(struct nxflat_hdr_s)
+
+/* The names of these fields have changed in later versions of binutils
+ * (after 2.13 and before 2.15) and the meaning of _rawsize is has also
+ * changed somewhat. In the same timeframe, the name of the section
+ * structure changed.
+ */
+
+#if 0
+# define COOKED_SIZE _cooked_size
+# define RAW_SIZE _raw_size
+# define bfd_section sec
+#else
+# define COOKED_SIZE size
+# define RAW_SIZE rawsize
+#endif
+
+/***********************************************************************
+ * Private Types
+ ***********************************************************************/
+
+struct elf_internal_sym
+ {
+ bfd_vma st_value; /* Value of the symbol */
+ bfd_vma st_size; /* Associated symbol size */
+ u_int32_t st_name; /* Symbol name, index in string tbl */
+ u_int8_t st_info; /* Type and binding attributes */
+ u_int8_t st_other; /* No defined meaning, 0 */
+ u_int16_t st_shndx; /* Associated section index */
+ };
+
+typedef struct
+ {
+ /* The BFD symbol. */
+
+ asymbol symbol;
+
+ /* ELF symbol information. */
+
+ struct elf_internal_sym internal_elf_sym;
+
+ /* Backend specific information. */
+
+ union
+ {
+ unsigned int hppa_arg_reloc;
+ void *mips_extr;
+ void *any;
+ }
+ tc_data;
+
+ /* Version information. This is from an Elf_Internal_Versym structure in a
+ * SHT_GNU_versym section. It is zero if there is no version information. */
+
+ u_int16_t version;
+
+ } elf_symbol_type;
+
+typedef struct _segment_info
+ {
+ const char *name;
+ bfd_vma low_mark;
+ bfd_vma high_mark;
+ size_t size;
+ void *contents;
+ asection *subsect[MAX_SECTIONS];
+ int nsubsects;
+ } segment_info;
+
+typedef void (*func_type) (asymbol * sym, void *arg1, void *arg2, void *arg3);
+
+/***********************************************************************
+ * Private Variable Data
+ ***********************************************************************/
+
+static int verbose = 0;
+static int dsyms = 0;
+static int stack_size = 0;
+
+static int32_t counter = 0;
+
+static const char *program_name = NULL;
+static const char *bfd_filename = NULL;
+static const char *entry_name = NULL;
+static char *out_filename = NULL;
+
+static segment_info text_info;
+static segment_info data_info;
+static segment_info bss_info;
+
+static asymbol **symbol_table = NULL;
+static int32_t number_of_symbols = 0;
+
+static asymbol *entry_symbol = NULL;
+static asymbol *dynname_begin_symbol = NULL;
+static asymbol *dynname_end_symbol = NULL;
+static asymbol *dynimport_begin_symbol = NULL;
+static asymbol *dynimport_end_symbol = NULL;
+
+/***********************************************************************
+ * Private Constant Data
+ ***********************************************************************/
+
+static const char default_exe_entry_name[] = "_start";
+static const char dynpath_begin_name[] = "__dynpath_begin";
+static const char dynpath_end_name[] = "__dynpath_end";
+static const char dynname_begin_name[] = "__dynname_begin";
+static const char dynname_end_name[] = "__dynname_end";
+static const char dynexport_begin_name[] = "__dynexport_begin";
+static const char dynexport_end_name[] = "__dynexport_end";
+static const char dynimport_begin_name[] = "__dynimport_begin";
+static const char dynimport_end_name[] = "__dynimport_end";
+static const char dynloader_name[] = "__dynloader";
+
+/***********************************************************************
+ * Private Functions
+ ***********************************************************************/
+
+/***********************************************************************
+ * nxflat_swap32
+ ***********************************************************************/
+
+#ifdef ARCH_BIG_ENDIAN
+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;
+}
+#endif
+
+/***********************************************************************
+ * get_xflat32
+ ***********************************************************************/
+
+static inline u_int32_t get_xflat32(u_int32_t * addr32)
+{
+ return ntohl(*addr32);
+}
+
+/***********************************************************************
+ * put_xflat32
+ ***********************************************************************/
+
+static void inline put_xflat32(u_int32_t * addr32, u_int32_t val32)
+{
+ *addr32 = htonl(val32);
+}
+
+/***********************************************************************
+ * put_xflat16
+ ***********************************************************************/
+
+static void inline put_xflat16(u_int16_t * addr16, u_int16_t val16)
+{
+#if 1
+ *addr16 = htons(val16);
+#else
+ u_int32_t *addr32 = (u_int32_t *) (((u_int32_t) addr16) & ~3);
+ u_int32_t ndx = ((((u_int32_t) addr16) >> 1) & 1);
+
+ union
+ {
+ u_int16_t hw[2];
+ u_int32_t w;
+ } uword;
+
+ /* Fetch the 32 bit value */
+
+ uword.w = get_xflat32(addr32);
+
+ /* Add in the 16 bit value */
+
+ uword.hw[ndx] = val16;
+
+ /* Then save the 32-bit value */
+
+ put_xflat32(addr32, uword.w);
+#endif
+}
+
+/***********************************************************************
+ * get_symbols
+ ***********************************************************************/
+
+static asymbol **get_symbols(bfd * abfd, int32_t * num)
+{
+ int32_t storage_needed;
+
+ 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;
+
+ if (verbose)
+ {
+ printf("Read %d symbols\n", number_of_symbols);
+ }
+
+ return symbol_table;
+}
+
+/***********************************************************************
+ * traverse_global_symbols
+ ***********************************************************************/
+
+static void
+traverse_global_symbols(void *arg1, void *arg2, void *arg3, func_type fn)
+{
+ int i;
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ /* Check if it is a global function symbol defined in this */
+
+ if (IS_GLOBAL(symbol_table[i]))
+ {
+ /* Yes, process the symbol */
+
+ fn(symbol_table[i], arg1, arg2, arg3);
+ }
+ }
+}
+
+/***********************************************************************
+ * check_special_symbol
+ ***********************************************************************/
+
+static void check_special_symbol(asymbol * sym,
+ void *arg1, void *arg2, void *arg3)
+{
+ if ((entry_name) && (strcmp(entry_name, sym->name) == 0))
+ {
+ entry_symbol = sym;
+ }
+ else if (strcmp(dynname_begin_name, sym->name) == 0)
+ {
+ dynname_begin_symbol = sym;
+ }
+ else if (strcmp(dynname_end_name, sym->name) == 0)
+ {
+ dynname_end_symbol = sym;
+ }
+ else if (strcmp(dynimport_begin_name, sym->name) == 0)
+ {
+ dynimport_begin_symbol = sym;
+ }
+ else if (strcmp(dynimport_end_name, sym->name) == 0)
+ {
+ dynimport_end_symbol = sym;
+ }
+ counter++;
+}
+
+/***********************************************************************
+ * find_special_symbols
+ ***********************************************************************/
+
+static void inline find_special_symbols(void)
+{
+ counter = 0;
+ traverse_global_symbols(NULL, NULL, NULL, check_special_symbol);
+
+ if (entry_symbol == NULL)
+ {
+ fprintf(stderr, "ERROR: Executable entry point \"%s\" not found\n",
+ entry_name);
+ exit(1);
+ }
+
+ if (dynname_begin_symbol == NULL)
+ {
+ fprintf(stderr, "WARNING: Special symbol \"%s\" not found\n",
+ dynname_begin_name);
+ }
+ else
+ {
+ if (dynname_end_symbol == NULL)
+ {
+ fprintf(stderr, "ERROR: Symbol \"%s\" found, but missing \"%s\"\n",
+ dynname_begin_name, dynname_end_name);
+ exit(1);
+ }
+
+#ifndef LIBS_CAN_INCLUDE_LIBS
+ if (binary_type == NXFLAT_BINARY_TYPE_DYN)
+ {
+ fprintf(stderr,
+ "WARNING: Shared library binary contains "
+ "library names!\n");
+ fprintf(stderr,
+ " Library names cannot be used by a "
+ "shared library object\n");
+ fprintf(stderr,
+ " You may want to rebuild rebuild the "
+ "shared library intermediate file without\n");
+ fprintf(strderr,
+ " specifying Library names (-l option "
+ "in ldelflib)\n");
+
+ dynname_begin_symbol = NULL;
+ dynname_end_symbol = NULL;
+ }
+#endif /* LIBS_CAN_INCLUDE_LIBS */
+ }
+
+ if (dynimport_begin_symbol == NULL)
+ {
+ fprintf(stderr, "WARNING: Special symbol \"%s\" not found\n",
+ dynimport_begin_name);
+ dynimport_end_symbol = NULL;
+ }
+ else if (dynimport_end_symbol == NULL)
+ {
+ fprintf(stderr, "ERROR: Symbol \"%s\" found, but missing \"%s\"\n",
+ dynimport_begin_name, dynimport_end_name);
+ exit(1);
+ }
+}
+
+/***********************************************************************
+ * put_special_symbol
+ ***********************************************************************/
+
+static void
+put_special_symbol(asymbol * begin_sym, asymbol * end_sym,
+ u_int32_t * addr, u_int16_t * count,
+ u_int32_t elem_size, u_int32_t offset)
+{
+ u_int32_t file_offset = 0;
+ u_int32_t elems = 0;
+
+ u_int32_t begin_sym_value;
+ u_int32_t begin_sect_vma;
+
+ /* We'll assume its okay if this symbol was not found. */
+
+ if (begin_sym != NULL)
+ {
+ /* Get the value of the beginning symbol and the section that it is
+ * defined in. */
+
+ begin_sym_value = begin_sym->value;
+ if (begin_sym->section == NULL)
+ {
+ fprintf(stderr, "No section for symbol \"%s\"\n", begin_sym->name);
+ exit(1);
+ }
+ else
+ {
+ /* Get the file offset to the beginning symbol */
+
+ begin_sect_vma = begin_sym->section->vma;
+
+ file_offset = NXFLAT_HDR_SIZE + /* Size of the xFLT header */
+ begin_sect_vma + /* Virtual address of section */
+ begin_sym_value + /* Value of the symbol */
+ offset; /* Additional file offset */
+
+ /* If there is a begin symbol, then there MUST be a corresponding
+ * ending symbol. We must have this to get the size of the data
+ * structure. This size will be used to determined the number of
+ * elements in the array. */
+
+ if (end_sym == NULL)
+ {
+ /* No matching end symbol */
+
+ fprintf(stderr,
+ "ERROR: Begin sym \"%s\" found, no corresponding end\n",
+ begin_sym->name);
+ exit(1);
+ }
+ else if (end_sym->section == NULL)
+ {
+ /* No section associated with the end symbol */
+
+ fprintf(stderr, "No section for symbol \"%s\"\n", end_sym->name);
+ exit(1);
+ }
+ else if (end_sym->section != begin_sym->section)
+ {
+ /* Section associated with the end symbol is not the same as the
+ * section associated with the begin symbol. */
+
+ fprintf(stderr,
+ "ERROR: Begin sym \"%s\" is defined in section \"%s\"\n",
+ begin_sym->name, begin_sym->section->name);
+ fprintf(stderr,
+ " but sym \"%s\" is defined in section \"%s\"\n",
+ end_sym->name, end_sym->section->name);
+ exit(1);
+ }
+ else if (end_sym->value < begin_sym_value)
+ {
+ /* End symbol is before the begin symbol? */
+
+ fprintf(stderr,
+ "ERROR: Begin sym \"%s\" lies at offset %d "
+ "in section \"%s\"\n",
+ begin_sym->name, begin_sym_value,
+ begin_sym->section->name);
+ fprintf(stderr,
+ " but sym \"%s\" is before that at offset: %d\n",
+ end_sym->name, (u_int32_t) end_sym->value);
+ exit(1);
+ }
+ else
+ {
+ /* Get the size of the structure in bytes */
+
+ u_int32_t array_size = end_sym->value - begin_sym_value;
+
+ /* Get the number of elements in the structure. */
+
+ elems = array_size / elem_size;
+
+ /* Verify that there are an even number of elements in the array. */
+
+ if (elems * elem_size != array_size)
+ {
+ fprintf(stderr,
+ "ERROR: Array size (%d) is not a multiple "
+ "of the element size (%d)\n", array_size, elem_size);
+ exit(1);
+ }
+ }
+ }
+
+ if (verbose)
+ {
+ printf("Symbol %s: value: %08x section offset: %08x "
+ "file offset: %08x count: %d\n",
+ begin_sym->name, begin_sym_value, begin_sect_vma,
+ file_offset, elems);
+ }
+ }
+
+ put_xflat32(addr, file_offset);
+ put_xflat16(count, elems);
+}
+
+/***********************************************************************
+ * put_entry_point
+ ***********************************************************************/
+
+static void put_entry_point(struct nxflat_hdr_s *hdr)
+{
+ u_int32_t entry_point = 0;
+
+ if (entry_symbol)
+ {
+ struct bfd_section *sect;
+
+ /* Does this symbol lie in the text section? */
+
+ sect = entry_symbol->section;
+ if (sect == NULL)
+ {
+ fprintf(stderr, "No section for entry symbol \"%s\"\n",
+ entry_symbol->name);
+ exit(1);
+ }
+
+ /* Get the file offset to the entry point symbol */
+
+ entry_point = NXFLAT_HDR_SIZE + sect->vma + entry_symbol->value;
+
+ printf("Entry symbol \"%s\": %08x in section \"%s\"\n",
+ entry_symbol->name, entry_point, sect->name);
+
+ /* If verbose is selected, we'll show the details of the calculation. */
+
+ if (verbose)
+ {
+ printf("(HDR: %08lx + Section VMA: %08x + Symbol Value: %08x)\n",
+ NXFLAT_HDR_SIZE, (u_int32_t) sect->vma,
+ (u_int32_t) entry_symbol->value);
+ }
+ }
+
+ /* Does the entry point lie within the text region? */
+
+ if ((entry_point < NXFLAT_HDR_SIZE) ||
+ (entry_point >= NXFLAT_HDR_SIZE + text_info.size))
+ {
+
+ /* No... One special case: A shared library may not need an
+ * initialization entry point. */
+
+ if (entry_point == 0)
+ {
+ /* Complain a little in this case... The used might have intended to
+ * specify one. */
+
+ fprintf(stderr,
+ "WARNING: Library has no initialization entry point\n");
+ }
+ else
+ {
+ /* Otherwise, complain a lot. We either have a program with no
+ * entry_point or a bogus entry_point. */
+
+ fprintf(stderr, "ERROR: Invalid entry point: %08x\n", entry_point);
+ fprintf(stderr, " Valid TEXT range: %08lx - %08lx\n",
+ NXFLAT_HDR_SIZE, NXFLAT_HDR_SIZE + text_info.size);
+ exit(1);
+ }
+ }
+
+ /* Put the entry point into the xFLT header. */
+
+ put_xflat32(&hdr->h_entry, entry_point);
+}
+
+/***********************************************************************
+ * get_reloc_type
+ ***********************************************************************/
+
+static int get_reloc_type(asection * sym_section, segment_info ** sym_segment)
+{
+ int i;
+
+ /* Locate the address referred to by section type. In the context in which
+ * this runs, we can no longer use the flags field (it is zero for some
+ * reason). But we can search for matches with the buffered section
+ * pointers. */
+
+ /* Check if the symbol is defined in a BSS section */
+
+ for (i = 0; i < bss_info.nsubsects; i++)
+ {
+ if (bss_info.subsect[i] == sym_section)
+ {
+ /* Yes... */
+
+ if (verbose)
+ {
+ printf("Sym section %s is BSS\n", sym_section->name);
+ }
+
+ if (sym_segment)
+ *sym_segment = &bss_info;
+ return NXFLAT_RELOC_TYPE_BSS;
+ }
+ }
+
+ /* Check if the symbol is defined in a TEXT section */
+
+ for (i = 0; i < text_info.nsubsects; i++)
+ {
+ if (text_info.subsect[i] == sym_section)
+ {
+ /* Yes... */
+
+ if (verbose)
+ {
+ printf("Sym section %s is CODE\n", sym_section->name);
+ }
+
+ if (sym_segment)
+ *sym_segment = &text_info;
+ return NXFLAT_RELOC_TYPE_TEXT;
+ }
+ }
+
+ /* Check if the symbol is defined in a DATA section */
+
+ for (i = 0; i < data_info.nsubsects; i++)
+ {
+ if (data_info.subsect[i] == sym_section)
+ {
+ /* Yes... */
+
+ if (verbose)
+ {
+ printf("Sym section %s is DATA\n", sym_section->name);
+ }
+
+ if (sym_segment)
+ *sym_segment = &data_info;
+ return NXFLAT_RELOC_TYPE_DATA;
+ }
+ }
+
+ fprintf(stderr,
+ "ERROR: Could not find region for sym_section \"%s\" (%p)\n",
+ sym_section->name, sym_section);
+ return NXFLAT_RELOC_TYPE_NONE;
+}
+
+/***********************************************************************
+ * resolve_segment_relocs
+ ***********************************************************************/
+
+static void
+resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms,
+ u_int32_t * n_relocs, struct nxflat_reloc_s **relocs)
+{
+ int i;
+ int j;
+ int relsize, relcount;
+ arelent **relpp;
+ struct nxflat_reloc_s *nxflat_relocs;
+ u_int32_t nxflat_reloc_count;
+
+ nxflat_relocs = *relocs;
+ nxflat_reloc_count = *n_relocs;
+
+ for (i = 0; i < inf->nsubsects; i++)
+ {
+ relcount = inf->subsect[i]->reloc_count;
+ if (verbose)
+ {
+ printf("Section %s has %08x relocs\n",
+ inf->subsect[i]->name, relcount);
+ }
+ if (0 >= relcount)
+ continue;
+
+ relsize = bfd_get_reloc_upper_bound(input_bfd, inf->subsect[i]);
+ if (verbose)
+ {
+ printf("Section %s reloc size: %08x\n",
+ inf->subsect[i]->name, relsize);
+ }
+ if (0 >= relsize)
+ continue;
+
+ relpp = (arelent **) malloc((size_t) relsize);
+ relcount =
+ bfd_canonicalize_reloc(input_bfd, inf->subsect[i], relpp, syms);
+
+ if (relcount < 0)
+ {
+ fprintf(stderr, "ERROR: bfd_canonicalize_reloc failed!\n");
+ exit(1);
+ }
+ if (verbose)
+ {
+ printf("Section %s can'd %08x relocs\n",
+ inf->subsect[i]->name, relcount);
+ }
+
+ for (j = 0; j < relcount; j++)
+ {
+ reloc_howto_type *how_to = relpp[j]->howto;
+ asymbol *rel_sym = *relpp[j]->sym_ptr_ptr;
+ asection *rel_section = rel_sym->section;
+
+ if (verbose > 1)
+ {
+ printf("rel %d -> sym @ %p [%28s] s_addr @ %08x, "
+ "rel %08x how %s\n",
+ j, relpp[j]->sym_ptr_ptr, rel_sym->name,
+ (u_int32_t) relpp[j]->address,
+ (u_int32_t) relpp[j]->addend, how_to->name);
+ }
+
+ switch (how_to->type)
+ {
+ case R_ARM_PLT32:
+ case R_ARM_PC24:
+ {
+ int32_t *opcode;
+ int32_t temp;
+ int32_t saved;
+
+ if (verbose)
+ {
+ printf("performing PC24 link at addr %08x to "
+ "sym [%20s] @ %08x\n",
+ (u_int32_t) relpp[j]->address, rel_sym->name,
+ (u_int32_t) rel_sym->value);
+ }
+
+ /* Can't fix what we ain't got */
+
+ if (!(SEC_IN_MEMORY & rel_sym->section->flags))
+ {
+ fprintf(stderr, "ERROR: section %s not loaded into mem!\n",
+ rel_sym->section->name);
+ exit(1);
+ }
+
+ /* PC24 -> can only fix text to text refs */
+
+ if (!(SEC_CODE & rel_sym->section->flags))
+ {
+ fprintf(stderr, "ERROR: section %s not code!\n",
+ rel_sym->section->name);
+ exit(1);
+ }
+
+ if (!(SEC_CODE & inf->subsect[i]->flags))
+ {
+ fprintf(stderr, "ERROR: section %s not code!\n",
+ rel_sym->section->name);
+ exit(1);
+ }
+
+ opcode = (int32_t *) (inf->contents + relpp[j]->address);
+ if (verbose > 1)
+ {
+ printf("original opcode @ %p is %08x ",
+#ifdef ARCH_BIG_ENDIAN
+ opcode, (int32_t) nxflat_swap32(*opcode));
+#else
+ opcode, *opcode);
+#endif
+ printf("rsh %d ", how_to->rightshift);
+ printf(" sz %d ", how_to->size);
+ printf("bit %d ", how_to->bitsize);
+ printf("rel %d ", how_to->pc_relative);
+ printf("smask %08x ", (u_int32_t) how_to->src_mask);
+ printf("dmask %08x ", (u_int32_t) how_to->dst_mask);
+ printf("off %d ", how_to->pcrel_offset);
+ printf("\n");
+ }
+
+ if (how_to->pcrel_offset)
+ {
+#ifdef ARCH_BIG_ENDIAN
+ saved = temp = (int32_t) nxflat_swap32(*opcode);
+#else
+ saved = temp = *opcode;
+#endif
+ /* mask */
+ temp &= how_to->src_mask;
+
+ /* sign extend */
+ temp <<= (32 - how_to->bitsize);
+ temp >>= (32 - how_to->bitsize);
+
+ /* offset */
+ temp +=
+ ((rel_sym->value + rel_sym->section->vma)
+ - relpp[j]->address) >> how_to->rightshift;
+
+ /* demote */
+ /* temp >>= how_to->rightshift; */
+
+ /* mask upper bits from rollover */
+ temp &= how_to->dst_mask;
+
+ /* replace data that was masked */
+ temp |= saved & (~how_to->dst_mask);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Do not know how pcrel_offset\n");
+ exit(1);
+ }
+
+ if (verbose > 1)
+ {
+ printf("result opcode: %08x\n", temp);
+ }
+#ifdef ARCH_BIG_ENDIAN
+ *opcode = (int32_t) nxflat_swap32(temp);
+#else
+ *opcode = temp;
+#endif
+ }
+ break;
+
+ case R_ARM_ABS32:
+ {
+ int32_t *opcode;
+ int32_t temp;
+ int32_t saved;
+
+ if (verbose)
+ {
+ printf("performing ABS32 link at addr %08x to "
+ "sym [%20s] @ %08x\n",
+ (u_int32_t) relpp[j]->address, rel_sym->name,
+ (u_int32_t) rel_sym->value);
+ }
+
+ /* ABS32 links from .text are easy - since the fetches will */
+ /* always be base relative. the ABS32 refs from data will be */
+ /* handled the same, with an appropriate reloc record for */
+ /* the load_flat_binary() kernel routine to handle */
+
+ opcode = (int32_t *) (inf->contents + relpp[j]->address);
+ if (verbose)
+ {
+ printf("original opcode @ %p is %08x ",
+#ifdef ARCH_BIG_ENDIAN
+ opcode, (int32_t) nxflat_swap32(*opcode));
+#else
+ opcode, *opcode);
+#endif
+ printf("rsh %d ", how_to->rightshift);
+ printf(" sz %d ", how_to->size);
+ printf("bit %d ", how_to->bitsize);
+ printf("rel %d ", how_to->pc_relative);
+ printf("smask %08x ", (u_int32_t) how_to->src_mask);
+ printf("dmask %08x ", (u_int32_t) how_to->dst_mask);
+ printf("off %d ", how_to->pcrel_offset);
+ printf("\n");
+ }
+
+#ifdef ARCH_BIG_ENDIAN
+ saved = temp = (int32_t) nxflat_swap32(*opcode);
+#else
+ saved = temp = *opcode;
+#endif
+ /* mask */
+
+ temp &= how_to->src_mask;
+
+ /* sign extend */
+
+ temp <<= (32 - how_to->bitsize);
+ temp >>= (32 - how_to->bitsize);
+
+ /* offset */
+
+ temp += (rel_sym->value + rel_sym->section->vma) >>
+ how_to->rightshift;
+
+ /* demote */
+ /* temp >>= how_to->rightshift; */
+
+ /* mask upper bits from rollover */
+
+ temp &= how_to->dst_mask;
+
+ /* replace data that was masked */
+
+ temp |= saved & (~how_to->dst_mask);
+
+ if (verbose)
+ {
+ printf("result opcode: %08x\n", temp);
+ }
+#ifdef ARCH_BIG_ENDIAN
+ *opcode = (int32_t) nxflat_swap32(temp);
+#else
+ *opcode = temp;
+#endif
+ if ((inf->subsect[i]->flags & SEC_DATA) &&
+ (inf->subsect[i]->flags & SEC_ALLOC))
+ {
+ int reltype;
+
+ if (verbose)
+ printf("RELOCATION in DATA!\n");
+
+ /* Locate the address referred to by section type. */
+
+ reltype = get_reloc_type(rel_section, NULL);
+
+ /* Create space for one more relocation. */
+
+ nxflat_relocs = realloc(nxflat_relocs,
+ (nxflat_reloc_count + 1)
+ * sizeof(struct nxflat_reloc_s));
+
+ /* And tuck in the new relocation. */
+
+
+ nxflat_relocs[nxflat_reloc_count].r_info = NXFLAT_RELOC(reltype, relpp[j]->address);
+ nxflat_reloc_count++;
+ }
+ }
+ break;
+
+ case R_ARM_GOTOFF:
+ /* Relocation is relative to the start of the global offset
+ * table. */
+
+ fprintf(stderr,
+ "Attempted GOTOFF reloc at addr %08x to "
+ "sym [%20s] @ %08x\n",
+ (u_int32_t) relpp[j]->address, rel_sym->name,
+ (u_int32_t) rel_sym->value);
+ goto got_not_supported;
+
+ case R_ARM_GOT32:
+ /* Relocation is to the entry for this symbol in the global
+ * offset table. */
+ fprintf(stderr,
+ "Attempted GOT32 reloc at addr %08x to "
+ "sym [%20s] @ %08x\n",
+ (u_int32_t) relpp[j]->address, rel_sym->name,
+ (u_int32_t) rel_sym->value);
+ goto got_not_supported;
+
+ case R_ARM_GOTPC:
+ /* Use global offset table as symbol value. */
+ fprintf(stderr,
+ "Attempted GOTPC reloc at addr %08x to "
+ "sym [%20s] @ %08x\n",
+ (u_int32_t) relpp[j]->address, rel_sym->name,
+ (u_int32_t) rel_sym->value);
+
+ got_not_supported:
+ fprintf(stderr,
+ "You must compile using the -mno-got or -membedded-pic "
+ "compiler option\n");
+ break;
+
+ default:
+ fprintf(stderr,
+ "Do not know how to handle reloc %d type %s @ %p!\n",
+ how_to->type, how_to->name, how_to);
+ break;
+ }
+ }
+
+ /* Mark the section as having no relocs */
+
+ inf->subsect[i]->flags &= !(SEC_RELOC);
+ inf->subsect[i]->reloc_count = 0;
+ }
+
+ /* Write reloc record data back out */
+
+ *relocs = nxflat_relocs;
+ *n_relocs = nxflat_reloc_count;
+}
+
+/***********************************************************************
+ * dump_symbol
+ ***********************************************************************/
+
+static void dump_symbol(asymbol * psym)
+{
+ if (bfd_is_com_section(psym->section))
+ {
+ /* Common Global - unplaced */
+
+ printf("Sym[%24s] @ sz %04x ",
+ psym->name, (u_int32_t) psym->value);
+ printf("align %04x ",
+ (u_int32_t) ((elf_symbol_type *) psym)->internal_elf_sym.st_value);
+ }
+ else
+ {
+ printf("Sym[%24s] @ %04x align ",
+ psym->name, (u_int32_t) psym->value);
+ printf("sz %04x ",
+ (u_int32_t) ((elf_symbol_type *) psym)->internal_elf_sym.st_size);
+ }
+ printf("%c", psym->flags & BSF_OBJECT ? 'O' : ' ');
+ printf("%c", psym->flags & BSF_DYNAMIC ? 'D' : ' ');
+ printf("%c", psym->flags & BSF_FILE ? 'F' : ' ');
+ printf("%c", psym->flags & BSF_INDIRECT ? 'I' : ' ');
+ printf("%c", psym->flags & BSF_WARNING ? 'W' : ' ');
+ printf("%c", psym->flags & BSF_CONSTRUCTOR ? 'C' : ' ');
+ printf("%c", psym->flags & BSF_NOT_AT_END ? 'N' : ' ');
+ printf("%c", psym->flags & BSF_OLD_COMMON ? 'c' : ' ');
+ printf("%c", psym->flags & BSF_SECTION_SYM ? 'S' : ' ');
+ printf("%c", psym->flags & BSF_WEAK ? 'w' : ' ');
+ printf("%c", psym->flags & BSF_KEEP_G ? 'G' : ' ');
+ printf("%c", psym->flags & BSF_KEEP ? 'K' : ' ');
+ printf("%c", psym->flags & BSF_FUNCTION ? 'f' : ' ');
+ printf("%c", psym->flags & BSF_DEBUGGING ? 'd' : ' ');
+ printf("%c", psym->flags & BSF_GLOBAL ? 'g' : ' ');
+ printf("%c", psym->flags & BSF_LOCAL ? 'l' : ' ');
+ printf("\n");
+}
+
+/***********************************************************************
+ * check_symbol_overlap
+ ***********************************************************************/
+
+static void check_symbol_overlap(asymbol ** symbols, int number_of_symbols)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ elf_symbol_type *sym_i;
+ bfd_vma base_i;
+ bfd_vma top_i;
+ bfd_vma size_i;
+
+ sym_i = (elf_symbol_type *) symbols[i];
+ base_i = sym_i->symbol.section->vma + sym_i->internal_elf_sym.st_value;
+ size_i = sym_i->internal_elf_sym.st_size;
+
+ if (0 == size_i)
+ {
+ if (sym_i->symbol.section->flags & SEC_CODE)
+ {
+ /* must be an internal branch - ignore */
+ if (verbose)
+ printf("Sym [%20s] is zero len, skipping!\n",
+ sym_i->symbol.name);
+ continue;
+ }
+ else
+ {
+ /* pointer - fake size up */
+ size_i = 4;
+ }
+ }
+
+ top_i = base_i + size_i;
+
+ if (verbose)
+ {
+ printf("Sym->[%20s] base %08x, top %08x\n",
+ sym_i->symbol.name, (u_int32_t) base_i, (u_int32_t) top_i);
+ }
+
+ for (j = (i + 1); j < number_of_symbols; j++)
+ {
+ elf_symbol_type *sym_j;
+ bfd_vma base_j;
+ bfd_vma top_j;
+ bfd_vma size_j = 0;
+
+ sym_j = (elf_symbol_type *) symbols[j];
+ base_j =
+ sym_j->symbol.section->vma + sym_j->internal_elf_sym.st_value;
+
+ if (0 == size_j)
+ {
+ if (sym_j->symbol.section->flags & SEC_CODE)
+ {
+ /* must be an internal branch - ignore */
+ continue;
+ }
+ else
+ {
+ /* pointer - fake size up */
+ size_j = 4;
+ }
+ }
+
+ top_j = base_j + sym_j->internal_elf_sym.st_size;
+
+ if (0 == sym_j->internal_elf_sym.st_size)
+ {
+ continue;
+ }
+
+ if ((base_j < top_i) && (top_j > base_i))
+ {
+ /* symbols overlap - bad bad bad bad */
+
+ if (verbose)
+ {
+ fprintf(stdout,
+ "symbols [%20s][%6s] and [%20s][%6s] OVERLAP!\n",
+ sym_i->symbol.name, sym_i->symbol.section->name,
+ sym_j->symbol.name, sym_j->symbol.section->name);
+ fprintf(stdout, "Sym->[%20s] base %08x, top %08x\n",
+ sym_i->symbol.name, (u_int32_t) base_i,
+ (u_int32_t) top_i);
+ fprintf(stdout, "Sym->[%20s] base %08x, top %08x\n",
+ sym_j->symbol.name, (u_int32_t) base_j,
+ (u_int32_t) top_j);
+ }
+ }
+
+ }
+ }
+}
+
+/***********************************************************************
+ * map_common_symbols
+ ***********************************************************************/
+
+static void
+map_common_symbols(bfd * input_bfd, asymbol ** symbols, int number_of_symbols)
+{
+ asection *bss_s;
+ int i;
+ int j;
+
+ bfd_vma baseaddr;
+ bfd_vma align;
+ bfd_vma size;
+ bfd_vma symbase;
+ bfd_vma offset;
+
+ bss_s = bss_info.subsect[0];
+ baseaddr = 0;
+
+ printf("checking overlap before mapping\n");
+
+ check_symbol_overlap(symbols, number_of_symbols);
+
+ printf("mapping COMMONS\n");
+
+ if (NULL == bss_s)
+ {
+ fprintf(stderr, "WARNING: NULL section passed to map_common_symbols\n");
+ return;
+ }
+
+ if (verbose)
+ {
+ printf("Assigning COMMON symbols to section %s\n", bss_s->name);
+ }
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ if (bfd_is_com_section(symbols[i]->section))
+ {
+ if (verbose > 1)
+ {
+ printf("COMMON sym[%04d] -> ", i);
+ dump_symbol(symbols[i]);
+ }
+
+ /* get parameters of unmapped symbol */
+#if 0
+ align = ((elf_symbol_type *) symbols[i])->internal_elf_sym.st_value;
+#else
+ /* Ignore alignment - just make sure we're word aligned we're not
+ * worrying about page boundaries since we're flat mem and we're not
+ * really concerned with cache alignment - maybe someday */
+
+ align = 0x04;
+#endif
+ size = ((elf_symbol_type *) symbols[i])->internal_elf_sym.st_size;
+
+ if (0 == size)
+ {
+ if (verbose)
+ {
+ printf("zero size symbol assumed to be a ptr size = 4\n");
+ }
+ size = 0x04;
+ }
+
+ if (size % 0x04)
+ {
+ printf("non-mod4 symbol rounded up 4\n");
+ size = ((size >> 2) + 1) << 2;
+ }
+
+ /* INSERT SYMBOL AT END OF BSS - MUCH MO BETTA */
+
+ /* calulate transaction effects - insert blank b4 sym to get align */
+
+ baseaddr = bss_s->COOKED_SIZE;
+ symbase = ((baseaddr + align - 1) / align) * align;
+ offset = (symbase + size) - baseaddr;
+
+ if (verbose > 1)
+ {
+ printf(" ba: %08x sb: %08x al: %04x sz: %04x of: %04x\n",
+ (u_int32_t) baseaddr, (u_int32_t) symbase,
+ (u_int32_t) align, (u_int32_t) size, (u_int32_t) offset);
+ }
+
+ /* Add space to bss segment and section */
+
+ bss_info.high_mark += offset;
+ bss_info.size += offset;
+ bss_s->COOKED_SIZE += offset;
+ bss_s->RAW_SIZE += offset;
+
+ /* find all end markers and offset */
+
+ for (j = 0; j < number_of_symbols; j++)
+ {
+ if (bss_s == symbols[j]->section)
+ {
+ if (verbose > 1)
+ {
+ printf("checking endsym? %08x sym[%04d] -> ",
+ (u_int32_t) baseaddr, j);
+ dump_symbol(symbols[j]);
+ }
+
+ if (symbols[j]->value >= baseaddr)
+ {
+ symbols[j]->value += offset;
+ ((elf_symbol_type *) symbols[j])->internal_elf_sym.
+ st_value += offset;
+ if (verbose > 1)
+ {
+ printf("sym MOVED!!!\n");
+ printf("to sym[%04d] -> ", j);
+ dump_symbol(symbols[j]);
+ }
+ }
+ }
+ }
+
+ /* stuff sym at base */
+
+ symbols[i]->section = bss_s;
+ symbols[i]->value = symbase;
+ symbols[i]->flags = BSF_OBJECT | BSF_GLOBAL;
+ ((elf_symbol_type *) symbols[i])->internal_elf_sym.st_value = symbase;
+
+ if (verbose > 1)
+ {
+ printf("NEW sym[%04d] -> ", i);
+ dump_symbol(symbols[i]);
+ }
+ }
+ }
+
+ check_symbol_overlap(symbols, number_of_symbols);
+}
+
+/***********************************************************************
+ * output_relocs
+ ***********************************************************************/
+
+static struct nxflat_reloc_s *output_relocs(bfd * input_bfd, asymbol ** symbols,
+ int number_of_symbols,
+ u_int32_t * n_relocs)
+{
+ struct nxflat_reloc_s *nxflat_relocs;
+ asection *sym_section;
+ arelent **relpp, **p, *q;
+ const char *sym_name, *section_name;
+ u_int32_t nxflat_reloc_count;
+ int relsize, relcount;
+ int reltype;
+ int rc;
+ bfd_vma v, addend;
+ segment_info *relseg, *sym_segment;
+ u_int32_t seg_offset;
+
+ int i;
+
+ *n_relocs = 0;
+ nxflat_relocs = NULL;
+ nxflat_reloc_count = 0;
+ rc = 0;
+
+#if 1
+
+ /* new code */
+
+ if (verbose)
+ {
+ printf(" Before mapp high mark %08x cooked %08x raw %08x \n",
+ (u_int32_t) bss_info.high_mark,
+ (u_int32_t) bss_info.subsect[0]->COOKED_SIZE,
+ (u_int32_t) bss_info.subsect[0]->RAW_SIZE);
+ }
+
+ /* Unmapped 'common' symbols need to be stuffed into bss */
+
+ map_common_symbols(input_bfd, symbols, number_of_symbols);
+
+ if (verbose)
+ {
+ printf(" After map high mark %08x cooked %08x raw %08x \n",
+ (u_int32_t) bss_info.high_mark,
+ (u_int32_t) bss_info.subsect[0]->COOKED_SIZE,
+ (u_int32_t) bss_info.subsect[0]->RAW_SIZE);
+ }
+
+ if (verbose)
+ {
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ printf("sym[%04d] -> ", i);
+ dump_symbol(symbols[i]);
+ }
+ }
+
+ /* Stuff the addrs into the code (and data) */
+
+ resolve_segment_relocs(input_bfd, &text_info, symbols,
+ &nxflat_reloc_count, &nxflat_relocs);
+ resolve_segment_relocs(input_bfd, &data_info, symbols,
+ &nxflat_reloc_count, &nxflat_relocs);
+ resolve_segment_relocs(input_bfd, &bss_info, symbols,
+ &nxflat_reloc_count, &nxflat_relocs);
+
+ *n_relocs = nxflat_reloc_count;
+
+ printf(" returning %d relocs\n", nxflat_reloc_count);
+
+ /* need to emit relocs for data only */
+ return nxflat_relocs;
+
+#endif
+
+ relsize = bfd_get_dynamic_reloc_upper_bound(input_bfd);
+ if (relsize <= 0)
+ {
+ if (verbose)
+ printf("no relocation entries\n");
+ return 0;
+ }
+
+ relpp = (arelent **) malloc(relsize);
+ relcount = bfd_canonicalize_dynamic_reloc(input_bfd, relpp, symbols);
+ if (relcount <= 0)
+ {
+ if (verbose)
+ printf("no relocation entries\n");
+ *n_relocs = 0;
+ return NULL;
+ }
+
+ for (p = relpp; (relcount && (*p != NULL)); p++, relcount--)
+ {
+ q = *p;
+ if (q->sym_ptr_ptr && *q->sym_ptr_ptr)
+ {
+ sym_name = (*(q->sym_ptr_ptr))->name;
+ sym_section = (*(q->sym_ptr_ptr))->section;
+ section_name = (*(q->sym_ptr_ptr))->section->name;
+
+ if (verbose)
+ {
+ printf("Reloc address %08x type %s\n",
+ (u_int32_t) q->address, q->howto->name);
+ }
+
+ switch (q->howto->type)
+ {
+ case R_ARM_RELATIVE:
+ /* This reloc describes an offset from the "program base". We
+ * need to figure out which segment it actually refers to, fiddle
+ * the addend and output an appropriate FLAT reloc to be resolved
+ * at run time. */
+ /* XXX In an ideal world, the linker would output different
+ * relocs for the different sections, so we wouldn't need to grub
+ * around in the memory map quite so much. */
+
+ v = q->address;
+ reltype = -1;
+ relseg = sym_segment = NULL;
+ if (v >= text_info.low_mark && v <= text_info.high_mark)
+ {
+ /* The existing FLAT binary format only allows relocs to be
+ * in the .data segment. Relocating in .text would be bad
+ * practice anyway so this is no great loss. */
+
+ printf("WARNING: Illegal RELATIVE reloc in text "
+ "segment ignored.\n");
+ continue;
+ }
+ else if (v >= data_info.low_mark && v <= data_info.high_mark)
+ relseg = &data_info;
+
+ if (!relseg)
+ {
+ /* This reloc isn't in the text or data segment. Probably it
+ * refers to debug information and we can just ignore it. */
+
+ if (verbose)
+ {
+ fprintf(stderr,
+ "WARNING: ignoring reloc at %08x\n",
+ (u_int32_t) v);
+ }
+ continue;
+ }
+
+ /* Locate the reloc in the appropriate segment and extract the
+ * existing addend. */
+
+ seg_offset = v - relseg->low_mark;
+ addend = *((bfd_vma *) (relseg->contents + seg_offset));
+
+ if (verbose)
+ {
+ printf("RELATIVE reloc at (%s+%08x) addend %08x\n",
+ relseg->name, seg_offset, (u_int32_t) addend);
+ }
+
+ /* Locate the address referred to by section type. */
+
+ reltype = get_reloc_type(sym_section, &sym_segment);
+
+ if (!sym_segment)
+ {
+ /* The addend isn't within any of the segments we know about.
+ * This might mean it was in a section we threw away. In any
+ * case, there is nothing we can do about it now. */
+
+ printf("ERROR: reloc at (%s+%08x) has out of "
+ " range addend %08x or unrecognized "
+ " section \"%s\"\n",
+ relseg->name, seg_offset,
+ (u_int32_t) addend, sym_section->name);
+ rc = -1;
+ continue;
+ }
+
+ /* Verify that the addend offset lies within the address range we
+ * have identified for the segment. */
+
+ if (addend < sym_segment->low_mark ||
+ addend > sym_segment->high_mark)
+ {
+ fprintf(stderr,
+ "ERROR: Symbol addend %x does lie within "
+ "segment address range (%x-%x)\n",
+ (u_int32_t) addend, (u_int32_t) sym_segment->low_mark,
+ (u_int32_t) sym_segment->high_mark);
+ continue;
+ }
+
+ /* Factor out the starting VMA of the segment, adjust the addend
+ * in core and output a new reloc. */
+
+ addend -= sym_segment->low_mark;
+
+ if (verbose)
+ {
+ printf("(%s+%08x)\n",
+ sym_segment->name, (u_int32_t) addend);
+ }
+
+ *((bfd_vma *) (relseg->contents + seg_offset)) = addend;
+
+ nxflat_relocs = realloc(nxflat_relocs,
+ (nxflat_reloc_count + 1)
+ * sizeof(struct nxflat_reloc_s));
+
+ nxflat_relocs[nxflat_reloc_count].r_info = NXFLAT_RELOC(reltype, seg_offset);
+ nxflat_reloc_count++;
+ break;
+
+ case R_ARM_PC24:
+ case R_ARM_GLOB_DAT:
+ /* Because we linked with -Bsymbolic, the linker will already
+ * have resolved all function calls apart from those to undefined
+ * symbols. So long as this is a weak reference, we do nothing
+ * and the reloc will be incomplete - it is up to the application
+ * to avoid executing such branches. Global data relocs are also
+ * OK to leave unresolved since they will yield zero by default.
+ * If we encounter an unresolved strong reference we punt; the
+ * linker should have trapped this case already so this is a
+ * "can't happen" situation. */
+
+ if (!((*q->sym_ptr_ptr)->flags & BSF_WEAK))
+ {
+ printf("ERROR: undefined symbolic reference to %s\n",
+ (*q->sym_ptr_ptr)->name);
+ rc = -1;
+ }
+ break;
+
+ default:
+ printf("ERROR: unknown reloc type %s\n", q->howto->name);
+ rc = -1;
+ break;
+ }
+ }
+ else
+ {
+ printf("ERROR: undefined relocation entry\n");
+ rc = -1;
+ continue;
+ }
+ }
+
+ if (rc < 0)
+ return (NULL);
+
+ *n_relocs = nxflat_reloc_count;
+ return nxflat_relocs;
+}
+
+/***********************************************************************
+ * is_unwanted_section
+ ***********************************************************************/
+
+/* Return 1 if this is a section that we want to throw away but can only
+ * identify by name. Normally, any section with appropriate-looking flags
+ * will get copied into the output file.
+ */
+
+static int is_unwanted_section(asection * s)
+{
+ if (!strcmp(s->name, ".hash"))
+ return 1;
+ if (!strcmp(s->name, ".dynstr") || !strcmp(s->name, ".dynsym"))
+ return 1;
+ if (s->flags & SEC_DEBUGGING)
+ return 1;
+ return 0;
+}
+
+/***********************************************************************
+ * register_section
+ ***********************************************************************/
+
+/* Mark this section for inclusion in some segment. */
+static void register_section(asection * s, segment_info * inf)
+{
+ if (verbose)
+ printf("registering section %s to %s segment\n", s->name, inf->name);
+ inf->subsect[inf->nsubsects++] = s;
+}
+
+/***********************************************************************
+ * dump_sections
+ ***********************************************************************/
+
+/* Print out the sections that make up this segment for debugging. */
+static void dump_sections(segment_info * inf)
+{
+ int i;
+ printf(" [ ");
+ for (i = 0; i < inf->nsubsects; i++)
+ printf("%s ", inf->subsect[i]->name);
+ printf("]\n");
+}
+
+/***********************************************************************
+ * load_sections
+ ***********************************************************************/
+
+/* Pull the sections that make up this segment in off disk. */
+static void load_sections(bfd * bfd, segment_info * inf)
+{
+ int i;
+ void *ptr;
+ if (!inf->size)
+ return; /* Nothing to do */
+ inf->contents = malloc(inf->size);
+ if (!inf->contents)
+ {
+ fprintf(stderr, "ERROR: Out of memory.\n");
+ exit(1);
+ }
+ ptr = inf->contents;
+ for (i = 0; i < inf->nsubsects; i++)
+ {
+ if (!bfd_get_section_contents(bfd, inf->subsect[i], ptr,
+ 0, inf->subsect[i]->COOKED_SIZE))
+ {
+ fprintf(stderr, "ERROR: Failed to read section contents.\n");
+ exit(1);
+ }
+ ptr += inf->subsect[i]->COOKED_SIZE;
+ inf->subsect[i]->flags |= SEC_IN_MEMORY;
+ }
+}
+
+/***********************************************************************
+ * stack_nxflat_segment
+ ***********************************************************************/
+
+static void stack_nxflat_segment(segment_info * inf)
+{
+ bfd_vma min_addr = 0x7fffffff;
+ bfd_vma max_addr = 0x00000000;
+ int i;
+
+ for (i = 0; i < inf->nsubsects; i++)
+ {
+ bfd_vma vma = inf->subsect[i]->vma;
+ if (vma < min_addr)
+ min_addr = vma;
+
+ vma += inf->subsect[i]->COOKED_SIZE;
+ if (vma > max_addr)
+ max_addr = vma;
+ }
+
+ inf->low_mark = min_addr;
+ inf->high_mark = max_addr;
+ inf->size = max_addr - min_addr;
+}
+
+/***********************************************************************
+ * 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, " -e <entry-point>\n");
+ fprintf(stderr, " Entry point to module [%s for executable]\n",
+ default_exe_entry_name);
+ fprintf(stderr, " NULL for shared library\n");
+ fprintf(stderr, " -l Build a shared library binary [executable]\n");
+ fprintf(stderr, " -o <out-filename>\n");
+ fprintf(stderr, " Output to <out-filename> [<bfd-filename>.xflt]\n");
+ fprintf(stderr, " -s <stack-size>\n");
+ fprintf(stderr, " Set stack size to <stack-size>. Ignored if -l also\n");
+ fprintf(stderr, " selected. [%d]\n", DEFAULT_STACK_SIZE);
+ fprintf(stderr, " -v Verbose output [no verbose output]\n");
+ fprintf(stderr, " If -v is applied twice, additional debug output\n");
+ fprintf(stderr, " be enabled.\n");
+ fprintf(stderr, "\n");
+ exit(2);
+}
+
+/***********************************************************************
+ * parse_args
+ ***********************************************************************/
+
+static void parse_args(int argc, char **argv)
+{
+ int opt;
+
+ /* Save our name (for show_usage) */
+
+ program_name = argv[0];
+
+ /* Set some default values */
+
+ stack_size = 0;
+ entry_name = NULL;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "ERROR: Missing required arguments\n\n");
+ show_usage();
+ }
+
+ /* Get miscellaneous options from the command line. */
+
+ while ((opt = getopt(argc, argv, "de:lo:s:v")) != -1)
+ {
+ switch (opt)
+ {
+
+ case 'd':
+ dsyms++;
+ break;
+
+ case 'e':
+ entry_name = optarg;
+ break;
+
+ case 'o':
+ out_filename = optarg;
+ break;
+
+ case 's':
+ stack_size = atoi(optarg);
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'l':
+ default:
+ fprintf(stderr, "ERROR: %s Unknown option\n\n", argv[0]);
+ show_usage();
+ break;
+ }
+ }
+
+ /* The very last thing is also the name of the BFD input file */
+
+ bfd_filename = argv[argc - 1];
+
+ /* Verify that an appropriate stack size is selected. */
+
+ if (stack_size == 0)
+ {
+ /* Executables must have a stack_size selected. */
+
+ printf("Using default stack size: %d\n", DEFAULT_STACK_SIZE);
+ stack_size = DEFAULT_STACK_SIZE;
+ }
+
+ if (entry_name == NULL)
+ {
+ printf("Using entry_point: %s\n", default_exe_entry_name);
+ entry_name = default_exe_entry_name;
+ }
+}
+
+/***********************************************************************
+ * Public Functions
+ ***********************************************************************/
+
+/***********************************************************************
+ * main
+ ***********************************************************************/
+
+int main(int argc, char **argv, char **envp)
+{
+ int fd;
+ bfd *bf;
+ asection *s;
+
+ asymbol **symbol_table;
+ int32_t number_of_symbols;
+
+ u_int32_t reloc_len;
+ u_int32_t *reloc;
+
+ struct nxflat_hdr_s hdr;
+
+ /* Parse the incoming command line */
+
+ parse_args(argc, argv);
+
+ /* Open the BFD input file */
+
+ if (!(bf = bfd_openr(argv[argc - 1], 0)))
+ {
+ fprintf(stderr, "ERROR: Failed to open %s\n", argv[argc - 1]);
+ exit(1);
+ }
+
+ /* Verify the format of the BFD file */
+
+ if (bfd_check_format(bf, bfd_object) == 0)
+ {
+ printf("File is not an object file\n");
+ exit(2);
+ }
+
+ /* Read the symbol table from the file */
+
+ symbol_table = get_symbols(bf, &number_of_symbols);
+
+ /* Find all of the special symbols that we will need in the symbol table that
+ * we just read. */
+
+ find_special_symbols();
+
+ /* Walk the list of sections, figuring out where each one goes and how much
+ * storage it requires. */
+
+ text_info.low_mark = data_info.low_mark = bss_info.low_mark = -1;
+ text_info.high_mark = data_info.high_mark = bss_info.high_mark = 0;
+ text_info.contents = data_info.contents = bss_info.contents = NULL;
+ text_info.size = data_info.size = bss_info.size = 0;
+ text_info.nsubsects = data_info.nsubsects = bss_info.nsubsects = 0;
+ text_info.name = "text";
+ data_info.name = "data";
+ bss_info.name = "bss";
+
+ for (s = bf->sections; s != NULL; s = s->next)
+ {
+ if (verbose)
+ printf("reading section %s\n", s->name);
+
+ /* ignore blatantly useless sections */
+ if (is_unwanted_section(s))
+ continue;
+
+ if (s->flags == SEC_ALLOC)
+ {
+ if (verbose)
+ {
+ printf("Section %s is ALLOC only\n", s->name);
+ }
+ register_section(s, &bss_info);
+ continue;
+ }
+ if ((s->flags & SEC_CODE) && (s->flags & SEC_ALLOC))
+ {
+ if (verbose)
+ {
+ printf("Section %s is CODE\n", s->name);
+ }
+ register_section(s, &text_info);
+ continue;
+ }
+ if ((s->flags & SEC_DATA) && (s->flags & SEC_ALLOC))
+ {
+ if (verbose)
+ {
+ printf("section %s is DATA\n", s->name);
+ }
+ register_section(s, &data_info);
+ continue;
+ }
+ if (verbose)
+ printf("WARNING: ignoring section %s\n", s->name);
+ }
+
+ /* Fixup high and low water VMA address */
+
+ stack_nxflat_segment(&text_info);
+ stack_nxflat_segment(&data_info);
+ stack_nxflat_segment(&bss_info);
+
+ /* Check for a data offset due to the presence of a GOT */
+
+ printf("INPUT SECTIONS:\n");
+ printf("SECT LOW MARK HIGH MARK (SIZE BYTES)\n");
+ if (text_info.nsubsects == 0)
+ {
+ printf("TEXT Not found Not found ( Not found )\n");
+ }
+ else
+ {
+ printf("TEXT %08x %08x (%08lx)\n",
+ (u_int32_t) text_info.low_mark, (u_int32_t) text_info.high_mark,
+ text_info.size);
+
+ if (text_info.low_mark != 0)
+ {
+ fprintf(stderr, "ERROR: text section must be origined at zero");
+ exit(1);
+ }
+ }
+
+ if (data_info.nsubsects == 0)
+ {
+ printf("DATA Not found Not found ( Not found )\n");
+ }
+ else
+ {
+ printf("DATA %08x %08x (%08lx)\n",
+ (u_int32_t) data_info.low_mark, (u_int32_t) data_info.high_mark,
+ data_info.size);
+
+ if (data_info.low_mark != 0)
+ {
+ fprintf(stderr, "ERROR: data section must be origined at zero");
+ exit(1);
+ }
+ }
+
+ if (bss_info.nsubsects == 0)
+ {
+ printf("BSS Not found Not found ( Not found )\n");
+ }
+ else
+ {
+ printf("BSS %08x %08x (%08lx)\n",
+ (u_int32_t) bss_info.low_mark, (u_int32_t) bss_info.high_mark,
+ bss_info.size);
+
+ /* If data is present, then BSS was be origined immediately after the
+ * data. */
+
+ if (data_info.nsubsects > 0)
+ {
+ /* There is data... Account for possible ALIGN 0x10 at end of data */
+
+ u_int32_t bss_start1 = data_info.high_mark;
+ u_int32_t bss_start2 = ((bss_start1 + 0x0f) & ~0x0f);
+
+ if ((bss_info.low_mark < bss_start1) &&
+ (bss_info.low_mark > bss_start2))
+ {
+ fprintf(stderr,
+ "ERROR: bss must be origined immediately after "
+ "the data section\n");
+ exit(1);
+ }
+ }
+
+ /* If there is no data, then the BSS must be origined at zero */
+
+ else if (bss_info.low_mark != 0)
+ {
+ fprintf(stderr, "ERROR: bss section (with no data section) must be");
+ fprintf(stderr, " origined at zero\n");
+ exit(1);
+ }
+ }
+
+ if (verbose)
+ {
+ printf("TEXT:");
+ dump_sections(&text_info);
+ printf("DATA:");
+ dump_sections(&data_info);
+ printf("BSS: ");
+ dump_sections(&bss_info);
+ }
+
+ /* Slurp the section contents in. No need to load BSS since we know * it
+ * isn't initialised. */
+
+ load_sections(bf, &text_info);
+ load_sections(bf, &data_info);
+
+ reloc = (u_int32_t *)
+ output_relocs(bf, symbol_table, number_of_symbols, &reloc_len);
+
+ /* Fill in the xFLT file header */
+
+ memcpy(hdr.h_magic, "xFLT", 4);
+
+ put_xflat32(&hdr.h_datastart, NXFLAT_HDR_SIZE + text_info.size);
+ put_xflat32(&hdr.h_dataend, NXFLAT_HDR_SIZE + text_info.size + data_info.size);
+ put_xflat32(&hdr.h_bssend,
+ NXFLAT_HDR_SIZE + text_info.size + data_info.size +
+ bss_info.size);
+ put_xflat32(&hdr.h_stacksize, stack_size); /* FIXME */
+ put_xflat32(&hdr.h_relocstart,
+ NXFLAT_HDR_SIZE + text_info.size + data_info.size);
+ put_xflat32(&hdr.h_reloccount, reloc_len);
+
+ put_entry_point(&hdr);
+
+ put_special_symbol(dynimport_begin_symbol,
+ dynimport_end_symbol,
+ &hdr.h_importsymbols,
+ &hdr.h_importcount,
+ sizeof(struct nxflat_import_s), text_info.size);
+
+ #ifdef RELOCS_IN_NETWORK_ORDER
+ {
+ int i;
+ for (i = 0; i < reloc_len; i++)
+ {
+ reloc[i] = htonl(reloc[i]);
+ }
+ }
+#endif
+
+ if (verbose && reloc)
+ {
+ printf("reloc size: %04x\n", reloc_len);
+ }
+
+ if (!out_filename)
+ {
+ out_filename = malloc(strlen(bfd_filename) + 5); /* 5 to add suffix */
+ strcpy(out_filename, bfd_filename);
+ strcat(out_filename, ".xflt");
+ }
+
+ fd = open(out_filename, O_WRONLY | O_PLATFORM | O_CREAT | O_TRUNC, 0744);
+ if (fd < 0)
+ {
+ fprintf(stderr, "ERROR: Failed open output file %s\n", out_filename);
+ exit(4);
+ }
+
+ write(fd, &hdr, sizeof(hdr));
+ write(fd, text_info.contents, text_info.size);
+ write(fd, data_info.contents, data_info.size);
+
+ if (reloc)
+ {
+ write(fd, reloc, reloc_len * 4);
+ }
+
+ close(fd);
+
+ exit(0);
+}
diff --git a/misc/buildroot/toolchain/nxflat/mknxflat.c b/misc/buildroot/toolchain/nxflat/mknxflat.c
new file mode 100644
index 000000000..7f1987486
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/mknxflat.c
@@ -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);
+}
diff --git a/misc/buildroot/toolchain/nxflat/nxflat.h b/misc/buildroot/toolchain/nxflat/nxflat.h
new file mode 100644
index 000000000..e8419426a
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/nxflat.h
@@ -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 */
+
diff --git a/misc/buildroot/toolchain/nxflat/nxflat.mk b/misc/buildroot/toolchain/nxflat/nxflat.mk
new file mode 100644
index 000000000..2a0728e6c
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/nxflat.mk
@@ -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
+
diff --git a/misc/buildroot/toolchain/nxflat/readxflat.c b/misc/buildroot/toolchain/nxflat/readxflat.c
new file mode 100644
index 000000000..d4131bc75
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/readxflat.c
@@ -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;
+}
diff --git a/misc/buildroot/toolchain/nxflat/reloc-macros.h b/misc/buildroot/toolchain/nxflat/reloc-macros.h
new file mode 100644
index 000000000..5cef95154
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/reloc-macros.h
@@ -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 */