[PATCH v2] cpukit: Add libdl with the Runtime Loader (RTL) code.
Chris Johns
chrisj at rtems.org
Thu Oct 30 10:00:05 UTC 2014
This is a merge of the RTL project.
---
cpukit/Makefile.am | 20 +-
cpukit/configure.ac | 18 +-
cpukit/libdl/Makefile.am | 36 +
cpukit/libdl/dlfcn-shell.c | 117 +++
cpukit/libdl/dlfcn-shell.h | 17 +
cpukit/libdl/dlfcn.c | 153 +++
cpukit/libdl/dlfcn.h | 112 ++
cpukit/libdl/fastlz.c | 551 ++++++++++
cpukit/libdl/fastlz.h | 100 ++
.../libdl/include/arch/arm/machine/elf_machdep.h | 131 +++
.../libdl/include/arch/bfin/machine/elf_machdep.h | 28 +
.../libdl/include/arch/h8300/machine/elf_machdep.h | 59 ++
.../libdl/include/arch/i386/machine/elf_machdep.h | 63 ++
.../libdl/include/arch/lm32/machine/elf_machdep.h | 34 +
.../libdl/include/arch/m32r/machine/elf_machdep.h | 39 +
.../libdl/include/arch/m68k/machine/elf_machdep.h | 47 +
.../libdl/include/arch/mips/machine/elf_machdep.h | 196 ++++
.../libdl/include/arch/moxie/machine/elf_machdep.h | 15 +
.../libdl/include/arch/nios2/machine/elf_machdep.h | 46 +
.../include/arch/powerpc/machine/elf_machdep.h | 105 ++
.../libdl/include/arch/sparc/machine/elf_machdep.h | 92 ++
.../libdl/include/arch/v850/machine/elf_machdep.h | 74 ++
cpukit/libdl/include/link.h | 45 +
cpukit/libdl/include/link_elf.h | 79 ++
cpukit/libdl/include/sys/cdefs_elf.h | 152 +++
cpukit/libdl/include/sys/exec_elf.h | 1097 ++++++++++++++++++++
cpukit/libdl/preinstall.am | 7 +
cpukit/libdl/rap-shell.c | 106 ++
cpukit/libdl/rap-shell.h | 14 +
cpukit/libdl/rap.c | 484 +++++++++
cpukit/libdl/rap.h | 115 ++
cpukit/libdl/rtl-alloc-heap.c | 33 +
cpukit/libdl/rtl-alloc-heap.h | 47 +
cpukit/libdl/rtl-allocator.c | 210 ++++
cpukit/libdl/rtl-allocator.h | 176 ++++
cpukit/libdl/rtl-chain-iterator.c | 57 +
cpukit/libdl/rtl-chain-iterator.h | 59 ++
cpukit/libdl/rtl-debugger.c | 96 ++
cpukit/libdl/rtl-elf.c | 882 ++++++++++++++++
cpukit/libdl/rtl-elf.h | 165 +++
cpukit/libdl/rtl-error.c | 47 +
cpukit/libdl/rtl-error.h | 44 +
cpukit/libdl/rtl-find-file.c | 110 ++
cpukit/libdl/rtl-find-file.h | 45 +
cpukit/libdl/rtl-fwd.h | 33 +
cpukit/libdl/rtl-indirect-ptr.h | 235 +++++
cpukit/libdl/rtl-mdreloc-arm.c | 323 ++++++
cpukit/libdl/rtl-mdreloc-bfin.c | 115 ++
cpukit/libdl/rtl-mdreloc-h8300.c | 101 ++
cpukit/libdl/rtl-mdreloc-i386.c | 103 ++
cpukit/libdl/rtl-mdreloc-lm32.c | 120 +++
cpukit/libdl/rtl-mdreloc-m32r.c | 156 +++
cpukit/libdl/rtl-mdreloc-m68k.c | 148 +++
cpukit/libdl/rtl-mdreloc-mips.c | 190 ++++
cpukit/libdl/rtl-mdreloc-moxie.c | 88 ++
cpukit/libdl/rtl-mdreloc-nios2.c | 44 +
cpukit/libdl/rtl-mdreloc-powerpc.c | 186 ++++
cpukit/libdl/rtl-mdreloc-sparc.c | 261 +++++
cpukit/libdl/rtl-mdreloc-v850.c | 97 ++
cpukit/libdl/rtl-obj-cache.c | 197 ++++
cpukit/libdl/rtl-obj-cache.h | 132 +++
cpukit/libdl/rtl-obj-comp.c | 179 ++++
cpukit/libdl/rtl-obj-comp.h | 122 +++
cpukit/libdl/rtl-obj-fwd.h | 39 +
cpukit/libdl/rtl-obj.c | 1031 ++++++++++++++++++
cpukit/libdl/rtl-obj.h | 580 +++++++++++
cpukit/libdl/rtl-rap.c | 980 +++++++++++++++++
cpukit/libdl/rtl-rap.h | 54 +
cpukit/libdl/rtl-shell.c | 389 +++++++
cpukit/libdl/rtl-shell.h | 39 +
cpukit/libdl/rtl-string.c | 32 +
cpukit/libdl/rtl-string.h | 37 +
cpukit/libdl/rtl-sym.c | 245 +++++
cpukit/libdl/rtl-sym.h | 128 +++
cpukit/libdl/rtl-trace.c | 134 +++
cpukit/libdl/rtl-trace.h | 100 ++
cpukit/libdl/rtl-unresolved.c | 471 +++++++++
cpukit/libdl/rtl-unresolved.h | 212 ++++
cpukit/libdl/rtl.c | 637 ++++++++++++
cpukit/libdl/rtl.h | 320 ++++++
cpukit/preinstall.am | 87 +-
cpukit/wrapup/Makefile.am | 4 +
testsuites/libtests/Makefile.am | 6 +-
testsuites/libtests/configure.ac | 13 +
testsuites/libtests/dl01/Makefile.am | 43 +
testsuites/libtests/dl01/dl-load.c | 46 +
testsuites/libtests/dl01/dl-load.h | 14 +
testsuites/libtests/dl01/dl-o1.c | 28 +
testsuites/libtests/dl01/dl01.doc | 0
testsuites/libtests/dl01/dl01.scn | 0
testsuites/libtests/dl01/init.c | 84 ++
91 files changed, 14701 insertions(+), 5 deletions(-)
create mode 100644 cpukit/libdl/Makefile.am
create mode 100644 cpukit/libdl/dlfcn-shell.c
create mode 100644 cpukit/libdl/dlfcn-shell.h
create mode 100644 cpukit/libdl/dlfcn.c
create mode 100644 cpukit/libdl/dlfcn.h
create mode 100644 cpukit/libdl/fastlz.c
create mode 100644 cpukit/libdl/fastlz.h
create mode 100644 cpukit/libdl/include/arch/arm/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/bfin/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/h8300/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/i386/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/lm32/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/m32r/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/m68k/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/mips/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/moxie/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/nios2/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/powerpc/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/sparc/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/arch/v850/machine/elf_machdep.h
create mode 100644 cpukit/libdl/include/link.h
create mode 100644 cpukit/libdl/include/link_elf.h
create mode 100644 cpukit/libdl/include/sys/cdefs_elf.h
create mode 100644 cpukit/libdl/include/sys/exec_elf.h
create mode 100644 cpukit/libdl/preinstall.am
create mode 100644 cpukit/libdl/rap-shell.c
create mode 100644 cpukit/libdl/rap-shell.h
create mode 100644 cpukit/libdl/rap.c
create mode 100644 cpukit/libdl/rap.h
create mode 100644 cpukit/libdl/rtl-alloc-heap.c
create mode 100644 cpukit/libdl/rtl-alloc-heap.h
create mode 100644 cpukit/libdl/rtl-allocator.c
create mode 100644 cpukit/libdl/rtl-allocator.h
create mode 100644 cpukit/libdl/rtl-chain-iterator.c
create mode 100644 cpukit/libdl/rtl-chain-iterator.h
create mode 100644 cpukit/libdl/rtl-debugger.c
create mode 100644 cpukit/libdl/rtl-elf.c
create mode 100644 cpukit/libdl/rtl-elf.h
create mode 100644 cpukit/libdl/rtl-error.c
create mode 100644 cpukit/libdl/rtl-error.h
create mode 100644 cpukit/libdl/rtl-find-file.c
create mode 100644 cpukit/libdl/rtl-find-file.h
create mode 100644 cpukit/libdl/rtl-fwd.h
create mode 100644 cpukit/libdl/rtl-indirect-ptr.h
create mode 100644 cpukit/libdl/rtl-mdreloc-arm.c
create mode 100644 cpukit/libdl/rtl-mdreloc-bfin.c
create mode 100644 cpukit/libdl/rtl-mdreloc-h8300.c
create mode 100644 cpukit/libdl/rtl-mdreloc-i386.c
create mode 100644 cpukit/libdl/rtl-mdreloc-lm32.c
create mode 100644 cpukit/libdl/rtl-mdreloc-m32r.c
create mode 100644 cpukit/libdl/rtl-mdreloc-m68k.c
create mode 100644 cpukit/libdl/rtl-mdreloc-mips.c
create mode 100644 cpukit/libdl/rtl-mdreloc-moxie.c
create mode 100644 cpukit/libdl/rtl-mdreloc-nios2.c
create mode 100644 cpukit/libdl/rtl-mdreloc-powerpc.c
create mode 100644 cpukit/libdl/rtl-mdreloc-sparc.c
create mode 100644 cpukit/libdl/rtl-mdreloc-v850.c
create mode 100644 cpukit/libdl/rtl-obj-cache.c
create mode 100644 cpukit/libdl/rtl-obj-cache.h
create mode 100644 cpukit/libdl/rtl-obj-comp.c
create mode 100644 cpukit/libdl/rtl-obj-comp.h
create mode 100644 cpukit/libdl/rtl-obj-fwd.h
create mode 100644 cpukit/libdl/rtl-obj.c
create mode 100644 cpukit/libdl/rtl-obj.h
create mode 100644 cpukit/libdl/rtl-rap.c
create mode 100644 cpukit/libdl/rtl-rap.h
create mode 100644 cpukit/libdl/rtl-shell.c
create mode 100644 cpukit/libdl/rtl-shell.h
create mode 100644 cpukit/libdl/rtl-string.c
create mode 100644 cpukit/libdl/rtl-string.h
create mode 100644 cpukit/libdl/rtl-sym.c
create mode 100644 cpukit/libdl/rtl-sym.h
create mode 100644 cpukit/libdl/rtl-trace.c
create mode 100644 cpukit/libdl/rtl-trace.h
create mode 100644 cpukit/libdl/rtl-unresolved.c
create mode 100644 cpukit/libdl/rtl-unresolved.h
create mode 100644 cpukit/libdl/rtl.c
create mode 100644 cpukit/libdl/rtl.h
create mode 100644 testsuites/libtests/dl01/Makefile.am
create mode 100644 testsuites/libtests/dl01/dl-load.c
create mode 100644 testsuites/libtests/dl01/dl-load.h
create mode 100644 testsuites/libtests/dl01/dl-o1.c
create mode 100644 testsuites/libtests/dl01/dl01.doc
create mode 100644 testsuites/libtests/dl01/dl01.scn
create mode 100644 testsuites/libtests/dl01/init.c
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 93b07c8..5e0ae72 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS += libi2c
SUBDIRS += libmisc
SUBDIRS += libmd
SUBDIRS += libgnat
+SUBDIRS += libdl
SUBDIRS += wrapup
SUBDIRS += zlib
@@ -41,7 +42,6 @@ include_uuid_HEADERS = libmisc/uuid/uuid.h
include_utf8procdir = $(includedir)/utf8proc
include_utf8proc_HEADERS = libmisc/utf8proc/utf8proc.h
-if NEWLIB
include_sysdir = $(includedir)/sys
include_sys_HEADERS =
@@ -69,6 +69,24 @@ include_rtems_bsdnetdir = $(includedir)/rtems/bsdnet
include_rtems_bsdnet_HEADERS = libnetworking/rtems/bsdnet/servers.h
include_rtems_bsdnet_HEADERS += libnetworking/rtems/bsdnet/_types.h
endif
+
+if LIBDL
+include_HEADERS += libdl/dlfcn.h
+include_HEADERS += libdl/include/link.h
+include_HEADERS += libdl/include/link_elf.h
+include_sys_HEADERS += libdl/include/sys/cdefs_elf.h
+include_sys_HEADERS += libdl/include/sys/exec_elf.h
+include_arch_machinedir = $(includedir)/machine
+include_arch_machine_HEADERS =
+include_arch_machine_HEADERS += libdl/include/arch/@RTEMS_CPU@/machine/elf_machdep.h
+include_rtems_rtldir = $(includedir)/rtems/rtl
+include_rtems_rtl_HEADERS =
+include_rtems_rtl_HEADERS += libdl/dlfcn-shell.h
+include_rtems_rtl_HEADERS += libdl/rtl.h libdl/rtl-allocator.h libdl/rtl-obj-fwd.h
+include_rtems_rtl_HEADERS += libdl/rtl-fwd.h libdl/rtl-obj.h libdl/rtl-obj-cache.h
+include_rtems_rtl_HEADERS += libdl/rtl-obj-comp.h libdl/rtl-unresolved.h
+include_rtems_rtl_HEADERS += libdl/rtl-indirect-ptr.h libdl/rtl-sym.h
+include_rtems_rtl_HEADERS += libdl/rap.h libdl/rap-shell.h
endif
include_rtems_HEADERS += include/rtems/bspIo.h
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index fcf3437..b3c818c 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -298,7 +298,7 @@ AC_ENABLE_MULTILIB([Makefile],[..])
AC_MSG_CHECKING([for assignable stdio])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
- [#include <stdio.h>],
+ [#include <stdio.h>],
[stdin = fopen("/tmp", "r")])],
[HAVE_ASSIGNABLE_STDIO=yes],
[HAVE_ASSIGNABLE_STDIO=no])
@@ -322,7 +322,7 @@ AC_CHECK_SIZEOF([time_t])
AC_CHECK_SIZEOF([size_t])
-# FIXME: Mandatory in SUSv4, optional in SUSv3.
+# FIXME: Mandatory in SUSv4, optional in SUSv3.
# Not implemented in GCC/newlib, so far.
AC_CHECK_DECLS([WORD_BIT],,,[#include <limits.h>])
AC_CHECK_DECLS([LONG_BIT],,,[#include <limits.h>])
@@ -372,6 +372,19 @@ AM_CONDITIONAL([RPCTOOLS],[test "$RPCGEN" = rpcgen \
&& test -n "$AWK" \
&& test "$enable_rpcgen" = yes])
+# Filter dynamic loading to only build for architectures that have
+# reloc backends
+AC_MSG_CHECKING([whether CPU supports libdl])
+case $RTEMS_CPU in
+ arm | bfin | h8300 | i386 | lm32 | m32r | m68k | mips | \
+ moxie | nios2 | powerpc | sparc | v850)
+ HAVE_LIBDL=yes ;;
+ *)
+ HAVE_LIBDL=no ;;
+esac
+AM_CONDITIONAL(LIBDL,[test x"$HAVE_LIBDL" = x"yes"])
+AC_MSG_RESULT([$HAVE_LIBDL])
+
RTEMS_AMPOLISH3
# Explicitly list all Makefiles here
@@ -412,6 +425,7 @@ librpc/Makefile
libmisc/Makefile
libi2c/Makefile
libmd/Makefile
+libdl/Makefile
zlib/Makefile
ftpd/Makefile
telnetd/Makefile
diff --git a/cpukit/libdl/Makefile.am b/cpukit/libdl/Makefile.am
new file mode 100644
index 0000000..11f1478
--- /dev/null
+++ b/cpukit/libdl/Makefile.am
@@ -0,0 +1,36 @@
+if LIBDL
+
+include $(top_srcdir)/automake/compile.am
+
+noinst_LIBRARIES = libdl.a
+libdl_a_SOURCES = \
+ dlfcn-shell.c \
+ dlfcn.c \
+ fastlz.c \
+ rap-shell.c \
+ rap.c \
+ rtl.c \
+ rtl-alloc-heap.c \
+ rtl-allocator.c \
+ rtl-chain-iterator.c \
+ rtl-debugger.c \
+ rtl-elf.c \
+ rtl-error.c \
+ rtl-find-file.c \
+ rtl-obj-cache.c \
+ rtl-obj-comp.c \
+ rtl-obj.c \
+ rtl-rap.c \
+ rtl-shell.c \
+ rtl-string.c \
+ rtl-sym.c \
+ rtl-trace.c \
+ rtl-unresolved.c
+
+libdl_a_SOURCES += rtl-mdreloc- at RTEMS_CPU@.c
+libdl_a_CPPFLAGS = $(AM_CPPFLAGS) -DRTEMS_RTL_RAP_LOADER=1 -DRTEMS_RTL_ELF_LOADER=1
+
+include $(srcdir)/preinstall.am
+include $(top_srcdir)/automake/local.am
+
+endif
diff --git a/cpukit/libdl/dlfcn-shell.c b/cpukit/libdl/dlfcn-shell.c
new file mode 100644
index 0000000..5655ab1
--- /dev/null
+++ b/cpukit/libdl/dlfcn-shell.c
@@ -0,0 +1,117 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor Dynamic Loading API Shell Support.
+ *
+ * Shell command wrappers for the Dynamic Loading API.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dlfcn.h>
+#include <rtems/rtl/dlfcn-shell.h>
+
+static void*
+convert_ascii_to_voidp (const char* arg)
+{
+ if (strcmp (arg, "base") == 0)
+ return RTLD_DEFAULT;
+ return (void*) strtoul (arg, NULL, 16);
+}
+
+int
+shell_dlopen (int argc, char* argv[])
+{
+ int arg;
+ for (arg = 1; arg < argc; arg++)
+ {
+ void* handle = dlopen (argv[arg], RTLD_NOW | RTLD_GLOBAL);
+ if (handle)
+ {
+ int unresolved;
+ char* message = "loaded";
+ if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0)
+ message = "dlinfo error checking unresolved status";
+ else if (unresolved)
+ message = "has unresolved externals";
+ printf ("handle: %p %s\n", handle, message);
+ }
+ else
+ printf ("error: %s\n", dlerror ());
+ }
+ return 0;
+}
+
+int
+shell_dlclose (int argc, char* argv[])
+{
+ return 0;
+}
+
+static bool
+lookup_dlsym (void** value, int argc, char* argv[])
+{
+ if (argc >= 3)
+ {
+ void* handle = convert_ascii_to_voidp (argv[1]);
+ if (handle)
+ {
+ *value = dlsym (handle, argv[2]);
+ if (*value)
+ return true;
+ else
+ printf ("error: invalid handle or symbol\n");
+ }
+ else
+ printf ("error: invalid handle");
+ }
+ else
+ printf ("error: requires handle and symbol name\n");
+ return false;
+}
+
+int
+shell_dlsym (int argc, char* argv[])
+{
+ void* value;
+ if (lookup_dlsym (&value, argc, argv))
+ {
+ printf ("%s = %p\n", argv[2], value);
+ return 0;
+ }
+ return -1;
+}
+
+typedef int (*call_t)(int argc, char* argv[]);
+
+int
+shell_dlcall (int argc, char* argv[])
+{
+ void* value;
+ if (lookup_dlsym (&value, argc, argv))
+ {
+ call_t call = value;
+ int r;
+ printf ("(*%p)(%d, ....)\n", value, argc - 3);
+ r = call (argc - 3, argv + 3);
+ printf ("return %d\n", r);
+ return 0;
+ }
+ return -1;
+}
diff --git a/cpukit/libdl/dlfcn-shell.h b/cpukit/libdl/dlfcn-shell.h
new file mode 100644
index 0000000..0406b6c
--- /dev/null
+++ b/cpukit/libdl/dlfcn-shell.h
@@ -0,0 +1,17 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if !defined(_DLFCN_SHELL_H_)
+#define _DLFCN_SHELL_H_
+
+int shell_dlopen (int argc, char* argv[]);
+int shell_dlclose (int argc, char* argv[]);
+int shell_dlsym (int argc, char* argv[]);
+int shell_dlcall (int argc, char* argv[]);
+
+#endif
diff --git a/cpukit/libdl/dlfcn.c b/cpukit/libdl/dlfcn.c
new file mode 100644
index 0000000..7c10202
--- /dev/null
+++ b/cpukit/libdl/dlfcn.c
@@ -0,0 +1,153 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtl
+ *
+ * @brief RTEMS POSIX Dynamic Module Loading Interface.
+ *
+ * This is the POSIX interface to run-time loading of code into RTEMS.
+ */
+
+#include <stdint.h>
+#include <dlfcn.h>
+#include <rtems/rtl/rtl.h>
+
+static rtems_rtl_obj_t*
+dl_get_obj_from_handle (void* handle)
+{
+ rtems_rtl_obj_t* obj;
+
+ /*
+ * Handle the special cases provided in NetBSD and Sun documentation.
+ * http://download.oracle.com/docs/cd/E19253-01/816-5168/dlsym-3c/index.html
+ * We currently do not manage the loading dependences in the module mappings
+ * so we cannot handle the searching based on loading order where overriding
+ * can occur.
+ */
+
+ if ((handle == RTLD_DEFAULT) || (handle == RTLD_SELF))
+ obj = rtems_rtl_baseimage ();
+ else
+ obj = rtems_rtl_check_handle (handle);
+
+ return obj;
+}
+
+void*
+dlopen (const char* name, int mode)
+{
+ rtems_rtl_obj_t* obj = NULL;
+
+ if (!rtems_rtl_lock ())
+ return NULL;
+
+ _rtld_debug.r_state = RT_ADD;
+ _rtld_debug_state ();
+
+ if (name)
+ obj = rtems_rtl_load_object (name, mode);
+ else
+ obj = rtems_rtl_baseimage ();
+
+ _rtld_debug.r_state = RT_CONSISTENT;
+ _rtld_debug_state();
+
+ rtems_rtl_unlock ();
+
+ return obj;
+}
+
+int
+dlclose (void* handle)
+{
+ rtems_rtl_obj_t* obj;
+ int r;
+
+ if (!rtems_rtl_lock ())
+ return -1;
+
+ obj = rtems_rtl_check_handle (handle);
+ if (!obj)
+ {
+ rtems_rtl_unlock ();
+ return -1;
+ }
+
+ _rtld_debug.r_state = RT_DELETE;
+ _rtld_debug_state ();
+
+ r = rtems_rtl_unload_object (obj) ? 0 : -1;
+
+ _rtld_debug.r_state = RT_CONSISTENT;
+ _rtld_debug_state ();
+
+ rtems_rtl_unlock ();
+
+ return r;
+}
+
+void*
+dlsym (void* handle, const char *symbol)
+{
+ rtems_rtl_obj_t* obj;
+ rtems_rtl_obj_sym_t* sym;
+ void* symval = NULL;
+
+ if (!rtems_rtl_lock ())
+ return NULL;
+
+ obj = dl_get_obj_from_handle (handle);
+ if (obj)
+ {
+ sym = rtems_rtl_symbol_obj_find (obj, symbol);
+ if (sym)
+ symval = sym->value;
+ }
+
+ rtems_rtl_unlock ();
+
+ return symval;
+}
+
+const char*
+dlerror (void)
+{
+ static char msg[64];
+ rtems_rtl_get_error (msg, sizeof (msg));
+ return msg;
+}
+
+int
+dlinfo (void* handle, int request, void* p)
+{
+ rtems_rtl_obj_t* obj;
+ int rc = -1;
+
+ if (!rtems_rtl_lock () || !p)
+ return -1;
+
+ obj = dl_get_obj_from_handle (handle);
+ if (obj)
+ {
+ switch (request)
+ {
+ case RTLD_DI_UNRESOLVED:
+ *((int*) p) = rtems_rtl_obj_unresolved (obj) ? 1 : 0;
+ rc = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ rtems_rtl_unlock ();
+
+ return rc;
+}
diff --git a/cpukit/libdl/dlfcn.h b/cpukit/libdl/dlfcn.h
new file mode 100644
index 0000000..1ac3ba1
--- /dev/null
+++ b/cpukit/libdl/dlfcn.h
@@ -0,0 +1,112 @@
+/* $NetBSD: dlfcn.h,v 1.21 2010/01/07 07:35:35 skrll Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _DLFCN_H_
+#define _DLFCN_H_
+
+//#include <sys/featuretest.h>
+#include <sys/cdefs.h>
+
+#if defined(_NETBSD_SOURCE)
+typedef struct _dl_info {
+ const char *dli_fname; /* File defining the symbol */
+ void *dli_fbase; /* Base address */
+ const char *dli_sname; /* Symbol name */
+ const void *dli_saddr; /* Symbol address */
+} Dl_info;
+#endif /* defined(_NETBSD_SOURCE) */
+
+/*
+ * User interface to the run-time linker.
+ */
+__BEGIN_DECLS
+void *dlopen(const char *, int);
+int dlclose(void *);
+void *dlsym(void * __restrict, const char * __restrict);
+#if defined(_NETBSD_SOURCE)
+int dladdr(void * __restrict, Dl_info * __restrict);
+int dlctl(void *, int, void *);
+#endif
+int dlinfo(void *, int, void *);
+const char *dlerror(void);
+__END_DECLS
+
+/* Values for dlopen `mode'. */
+#define RTLD_LAZY 1
+#define RTLD_NOW 2
+#define RTLD_GLOBAL 0x100 /* Allow global searches in object */
+#define RTLD_LOCAL 0x200
+#if defined(_NETBSD_SOURCE)
+#define DL_LAZY RTLD_LAZY /* Compat */
+#endif
+
+/*
+ * Special handle arguments for dlsym().
+ */
+#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
+#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
+#define RTLD_SELF ((void *) -3) /* Search the caller itself. */
+
+/*
+ * dlctl() commands
+ */
+#if defined(_NETBSD_SOURCE)
+#define DL_GETERRNO 1
+#define DL_GETSYMBOL 2
+#if 0
+#define DL_SETSRCHPATH x
+#define DL_GETLIST x
+#define DL_GETREFCNT x
+#define DL_GETLOADADDR x
+#endif /* 0 */
+#endif /* defined(_NETBSD_SOURCE) */
+
+/*
+ * dlinfo() commands
+ *
+ * From Solaris: http://docs.sun.com/app/docs/doc/816-5168/dlinfo-3c?a=view
+ */
+#define RTLD_DI_UNRESOLVED 10
+#if defined(_NETBSD_SOURCE)
+#define RTLD_DI_LINKMAP 3
+#if 0
+#define RTLD_DI_ARGSINFO 1
+#define RTLD_DI_CONFIGADDR 2
+#define RTLD_DI_LMID 4
+#define RTLD_DI_SERINFO 5
+#define RTLD_DI_SERINFOSIZE 6
+#define RTLD_DI_ORIGIN 7
+#define RTLD_DI_GETSIGNAL 8
+#define RTLD_DI_SETSIGNAL 9
+#endif
+#endif /* _NETBSD_SOURCE */
+
+#endif /* !defined(_DLFCN_H_) */
diff --git a/cpukit/libdl/fastlz.c b/cpukit/libdl/fastlz.c
new file mode 100644
index 0000000..3c9d6f6
--- /dev/null
+++ b/cpukit/libdl/fastlz.c
@@ -0,0 +1,551 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya at kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+
+/*
+ * Always check for bound when decompressing.
+ * Generally it is best to leave it defined.
+ */
+#define FASTLZ_SAFE
+
+/*
+ * Give hints to the compiler for branch prediction optimization.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#else
+#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#endif
+
+/*
+ * Use inlined functions for supported systems.
+ */
+#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
+#define FASTLZ_INLINE inline
+#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
+#define FASTLZ_INLINE __inline
+#else
+#define FASTLZ_INLINE
+#endif
+
+/*
+ * Prevent accessing more than 8-bit at once, except on x86 architectures.
+ */
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_STRICT_ALIGN
+#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_M_IX86) /* Intel, MSVC */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__386)
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_X86_) /* MinGW */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__I86__) /* Digital Mars */
+#undef FASTLZ_STRICT_ALIGN
+#endif
+#endif
+
+/*
+ * FIXME: use preprocessor magic to set this on different platforms!
+ */
+typedef unsigned char flzuint8;
+typedef unsigned short flzuint16;
+typedef unsigned int flzuint32;
+
+/* prototypes */
+int fastlz_compress(const void* input, int length, void* output);
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_DISTANCE 8192
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_READU16(p) *((const flzuint16*)(p))
+#else
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
+#endif
+
+#define HASH_LOG 13
+#define HASH_SIZE (1<< HASH_LOG)
+#define HASH_MASK (HASH_SIZE-1)
+#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 1
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz1_compress
+#define FASTLZ_DECOMPRESSOR fastlz1_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
+#include "fastlz.c"
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 2
+
+#undef MAX_DISTANCE
+#define MAX_DISTANCE 8191
+#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz2_compress
+#define FASTLZ_DECOMPRESSOR fastlz2_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
+#include "fastlz.c"
+
+int fastlz_compress(const void* input, int length, void* output)
+{
+ /* for short block, choose fastlz1 */
+ if(length < 65536)
+ return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout)
+{
+ /* magic identifier for compression level */
+ int level = ((*(const flzuint8*)input) >> 5) + 1;
+
+ if(level == 1)
+ return fastlz1_decompress(input, length, output, maxout);
+ if(level == 2)
+ return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void* input, int length, void* output)
+{
+ if(level == 1)
+ return fastlz1_compress(input, length, output);
+ if(level == 2)
+ return fastlz2_compress(input, length, output);
+
+ return 0;
+}
+
+#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
+{
+ const flzuint8* ip = (const flzuint8*) input;
+ const flzuint8* ip_bound = ip + length - 2;
+ const flzuint8* ip_limit = ip + length - 12;
+ flzuint8* op = (flzuint8*) output;
+
+ const flzuint8* htab[HASH_SIZE];
+ const flzuint8** hslot;
+ flzuint32 hval;
+
+ flzuint32 copy;
+
+ /* sanity check */
+ if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
+ {
+ if(length)
+ {
+ /* create literal copy only */
+ *op++ = length-1;
+ ip_bound++;
+ while(ip <= ip_bound)
+ *op++ = *ip++;
+ return length+1;
+ }
+ else
+ return 0;
+ }
+
+ /* initializes hash table */
+ for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
+ *hslot = ip;
+
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY-1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ {
+ const flzuint8* ref;
+ flzuint32 distance;
+
+ /* minimum match length */
+ flzuint32 len = 3;
+
+ /* comparison starting-point */
+ const flzuint8* anchor = ip;
+
+ /* check for a run */
+#if FASTLZ_LEVEL==2
+ if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
+ {
+ distance = 1;
+ ip += 3;
+ ref = anchor - 1 + 3;
+ goto match;
+ }
+#endif
+
+ /* find potential match */
+ HASH_FUNCTION(hval,ip);
+ hslot = htab + hval;
+ ref = htab[hval];
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* update hash table */
+ *hslot = anchor;
+
+ /* is this a match? check the first 3 bytes */
+ if(distance==0 ||
+#if FASTLZ_LEVEL==1
+ (distance >= MAX_DISTANCE) ||
+#else
+ (distance >= MAX_FARDISTANCE) ||
+#endif
+ *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
+ goto literal;
+
+#if FASTLZ_LEVEL==2
+ /* far, needs at least 5-byte match */
+ if(distance >= MAX_DISTANCE)
+ {
+ if(*ip++ != *ref++ || *ip++!= *ref++)
+ goto literal;
+ len += 2;
+ }
+
+ match:
+#endif
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if(!distance)
+ {
+ /* zero distance means a run */
+ flzuint8 x = ip[-1];
+ while(ip < ip_bound)
+ if(*ref++ != x) break; else ip++;
+ }
+ else
+ for(;;)
+ {
+ /* safe because the outer check against ip limit */
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ if(*ref++ != *ip++) break;
+ while(ip < ip_bound)
+ if(*ref++ != *ip++) break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if(copy)
+ /* copy is biased, '0' means 1 byte copy */
+ *(op-copy-1) = copy-1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+#if FASTLZ_LEVEL==2
+ if(distance < MAX_DISTANCE)
+ {
+ if(len < 7)
+ {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ }
+ else
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ for(len-=7; len >= 255; len-= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = (distance & 255);
+ }
+ }
+ else
+ {
+ /* far away, but not yet in the another galaxy... */
+ if(len < 7)
+ {
+ distance -= MAX_DISTANCE;
+ *op++ = (len << 5) + 31;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ else
+ {
+ distance -= MAX_DISTANCE;
+ *op++ = (7 << 5) + 31;
+ for(len-=7; len >= 255; len-= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ }
+#else
+
+ if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
+ while(len > MAX_LEN-2)
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 -2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN-2;
+ }
+
+ if(len < 7)
+ {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ }
+ else
+ {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+#endif
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval,ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval,ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY-1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
+ {
+ copy = 0;
+ *op++ = MAX_COPY-1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while(ip <= ip_bound)
+ {
+ *op++ = *ip++;
+ copy++;
+ if(copy == MAX_COPY)
+ {
+ copy = 0;
+ *op++ = MAX_COPY-1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if(copy)
+ *(op-copy-1) = copy-1;
+ else
+ op--;
+
+#if FASTLZ_LEVEL==2
+ /* marker for fastlz2 */
+ *(flzuint8*)output |= (1 << 5);
+#endif
+
+ return op - (flzuint8*)output;
+}
+
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
+{
+ const flzuint8* ip = (const flzuint8*) input;
+ const flzuint8* ip_limit = ip + length;
+ flzuint8* op = (flzuint8*) output;
+ flzuint8* op_limit = op + maxout;
+ flzuint32 ctrl = (*ip++) & 31;
+ int loop = 1;
+
+ do
+ {
+ const flzuint8* ref = op;
+ flzuint32 len = ctrl >> 5;
+ flzuint32 ofs = (ctrl & 31) << 8;
+
+ if(ctrl >= 32)
+ {
+#if FASTLZ_LEVEL==2
+ flzuint8 code;
+#endif
+ len--;
+ ref -= ofs;
+ if (len == 7-1)
+#if FASTLZ_LEVEL==1
+ len += *ip++;
+ ref -= *ip++;
+#else
+ do
+ {
+ code = *ip++;
+ len += code;
+ } while (code==255);
+ code = *ip++;
+ ref -= code;
+
+ /* match from 16-bit distance */
+ if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
+ if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
+ {
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_DISTANCE;
+ }
+#endif
+
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
+ return 0;
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
+ return 0;
+#endif
+
+ if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ ctrl = *ip++;
+ else
+ loop = 0;
+
+ if(ref == op)
+ {
+ /* optimize copy for a run */
+ flzuint8 b = ref[-1];
+ *op++ = b;
+ *op++ = b;
+ *op++ = b;
+ for(; len; --len)
+ *op++ = b;
+ }
+ else
+ {
+#if !defined(FASTLZ_STRICT_ALIGN)
+ const flzuint16* p;
+ flzuint16* q;
+#endif
+ /* copy from reference */
+ ref--;
+ *op++ = *ref++;
+ *op++ = *ref++;
+ *op++ = *ref++;
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+ /* copy a byte, so that now it's word aligned */
+ if(len & 1)
+ {
+ *op++ = *ref++;
+ len--;
+ }
+
+ /* copy 16-bit at once */
+ q = (flzuint16*) op;
+ op += len;
+ p = (const flzuint16*) ref;
+ for(len>>=1; len > 4; len-=4)
+ {
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ }
+ for(; len; --len)
+ *q++ = *p++;
+#else
+ for(; len; --len)
+ *op++ = *ref++;
+#endif
+ }
+ }
+ else
+ {
+ ctrl++;
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
+ return 0;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
+ return 0;
+#endif
+
+ *op++ = *ip++;
+ for(--ctrl; ctrl; ctrl--)
+ *op++ = *ip++;
+
+ loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
+ if(loop)
+ ctrl = *ip++;
+ }
+ }
+ while(FASTLZ_EXPECT_CONDITIONAL(loop));
+
+ return op - (flzuint8*)output;
+}
+
+#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
diff --git a/cpukit/libdl/fastlz.h b/cpukit/libdl/fastlz.h
new file mode 100644
index 0000000..f87bc7b
--- /dev/null
+++ b/cpukit/libdl/fastlz.h
@@ -0,0 +1,100 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya at kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef FASTLZ_H
+#define FASTLZ_H
+
+#define FASTLZ_VERSION 0x000100
+
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 0
+#define FASTLZ_VERSION_REVISION 0
+
+#define FASTLZ_VERSION_STRING "0.1.0"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+*/
+
+int fastlz_compress(const void* input, int length, void* output);
+
+/**
+ Decompress a block of compressed data and returns the size of the
+ decompressed block. If error occurs, e.g. the compressed data is
+ corrupted or the output buffer is not large enough, then 0 (zero)
+ will be returned instead.
+
+ The input buffer and the output buffer can not overlap.
+
+ Decompression is memory safe and guaranteed not to write the output buffer
+ more than what is specified in maxout.
+ */
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress above.
+*/
+
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* FASTLZ_H */
diff --git a/cpukit/libdl/include/arch/arm/machine/elf_machdep.h b/cpukit/libdl/include/arch/arm/machine/elf_machdep.h
new file mode 100644
index 0000000..78c88b5
--- /dev/null
+++ b/cpukit/libdl/include/arch/arm/machine/elf_machdep.h
@@ -0,0 +1,131 @@
+/* $NetBSD: elf_machdep.h,v 1.8 2009/05/30 05:56:52 skrll Exp $ */
+
+#if defined(__ARMEB__)
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#else
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+#endif
+
+#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */
+#define ELF64_MACHDEP_ID_CASES \
+ /* no 64-bit ELF machine types supported */
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_ARM_RELEXEC 0x00000001
+#define EF_ARM_HASENTRY 0x00000002
+#define EF_ARM_INTERWORK 0x00000004 /* GNU binutils 000413 */
+#define EF_ARM_SYMSARESORTED 0x00000004 /* ARM ELF A08 */
+#define EF_ARM_APCS_26 0x00000008 /* GNU binutils 000413 */
+#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 /* ARM ELF B01 */
+#define EF_ARM_APCS_FLOAT 0x00000010 /* GNU binutils 000413 */
+#define EF_ARM_MAPSYMSFIRST 0x00000010 /* ARM ELF B01 */
+#define EF_ARM_PIC 0x00000020
+#define EF_ARM_ALIGN8 0x00000040 /* 8-bit structure alignment. */
+#define EF_ARM_NEW_ABI 0x00000080
+#define EF_ARM_OLD_ABI 0x00000100
+#define EF_ARM_SOFT_FLOAT 0x00000200
+#define EF_ARM_EABIMASK 0xff000000
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_ARM: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_ARM
+
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+
+/* Processor specific relocation types */
+
+#define R_ARM_NONE 0
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5
+#define R_ARM_ABS12 6
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_CALL 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+
+/* TLS relocations */
+#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
+
+/* 20-31 are reserved for ARM Linux. */
+#define R_ARM_COPY 20
+#define R_ARM_GLOB_DAT 21
+#define R_ARM_JUMP_SLOT 22
+#define R_ARM_RELATIVE 23
+#define R_ARM_GOTOFF 24
+#define R_ARM_GOTPC 25
+#define R_ARM_GOT32 26
+#define R_ARM_PLT32 27
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_THM_JUMP24 30
+#define R_ARM_BASE_ABS 31
+
+#define R_ARM_ALU_PCREL_7_0 32
+#define R_ARM_ALU_PCREL_15_8 33
+#define R_ARM_ALU_PCREL_23_15 34
+#define R_ARM_ALU_SBREL_11_0 35
+#define R_ARM_ALU_SBREL_19_12 36
+#define R_ARM_ALU_SBREL_27_20 37
+#define R_ARM_V4BX 40
+#define R_ARM_PREL31 41
+
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
+
+#define R_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+
+#define R_ARM_THM_JUMP19 51
+
+/* 96-111 are reserved to G++. */
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_THM_JUMP11 102
+#define R_ARM_THM_JUMP8 103
+
+/* More TLS relocations */
+#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic */
+#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic */
+#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS */
+#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of */
+#define R_ARM_TLS_LE32 108
+#define R_ARM_TLS_LDO12 109
+#define R_ARM_TLS_LE12 110
+#define R_ARM_TLS_IE12GP 111
+
+/* 112-127 are reserved for private experiments. */
+
+#define R_ARM_RXPC25 249
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS32 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+
+#define R_TYPE(name) __CONCAT(R_ARM_,name)
+
+/* Processor specific program header flags */
+#define PF_ARM_SB 0x10000000
+#define PF_ARM_PI 0x20000000
+#define PF_ARM_ENTRY 0x80000000
+
+/* Processor specific section header flags */
+#define SHF_ENTRYSECT 0x10000000
+#define SHF_COMDEF 0x80000000
+
+/* Processor specific symbol types */
+#define STT_ARM_TFUNC STT_LOPROC
diff --git a/cpukit/libdl/include/arch/bfin/machine/elf_machdep.h b/cpukit/libdl/include/arch/bfin/machine/elf_machdep.h
new file mode 100644
index 0000000..cf0dc19
--- /dev/null
+++ b/cpukit/libdl/include/arch/bfin/machine/elf_machdep.h
@@ -0,0 +1,28 @@
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_BLACKFIN: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_BLACKFIN
+
+#define ARCH_ELFSIZE 32
+
+#define R_BFIN_UNUSED0 0
+
+#define R_BFIN_RIMM16 5
+#define R_BFIN_LUIMM16 6
+#define R_BFIN_HUIMM16 7
+#define R_BFIN_PCREL12_JUMP_S 8
+#define R_BFIN_PCREL24_JUMP_X 9
+#define R_BFIN_PCREL24 10
+#define R_BFIN_PCREL24_JU 13
+#define R_BFIN_PCREL24_CALL_X 14
+
+#define R_BFIN_BYTE_DATA 16
+#define R_BFIN_BYTE2_DATA 17
+#define R_BFIN_BYTE4_DATA 18
+
+
+
+#define R_TYPE(name) __CONCAT(R_BFIN_,name)
diff --git a/cpukit/libdl/include/arch/h8300/machine/elf_machdep.h b/cpukit/libdl/include/arch/h8300/machine/elf_machdep.h
new file mode 100644
index 0000000..3d04915
--- /dev/null
+++ b/cpukit/libdl/include/arch/h8300/machine/elf_machdep.h
@@ -0,0 +1,59 @@
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_H8_300: \
+ case EM_H8_300H: \
+ case EM_H8S: \
+ case EM_H8_500: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_H8_300
+#define ARCH_ELFSIZE 32
+
+#define R_H8_NONE 0
+#define R_H8_DIR32 1
+#define R_H8_DIR32_28 2
+#define R_H8_DIR32_24 3
+#define R_H8_DIR32_16 4
+#define R_H8_DIR32U 6
+#define R_H8_DIR32U_28 7
+#define R_H8_DIR32U_24 8
+#define R_H8_DIR32U_20 9
+#define R_H8_DIR32U_16 10
+#define R_H8_DIR24 11
+#define R_H8_DIR24_20 12
+#define R_H8_DIR24_16 13
+#define R_H8_DIR24U 14
+#define R_H8_DIR24U_20 15
+#define R_H8_DIR24U_16 16
+#define R_H8_DIR16 17
+#define R_H8_DIR16U 18
+#define R_H8_DIR16S_32 19
+#define R_H8_DIR16S_28 20
+#define R_H8_DIR16S_24 21
+#define R_H8_DIR16S_20 22
+#define R_H8_DIR16S 23
+#define R_H8_DIR8 24
+#define R_H8_DIR8U 25
+#define R_H8_DIR8Z_32 26
+#define R_H8_DIR8Z_28 27
+#define R_H8_DIR8Z_24 28
+#define R_H8_DIR8Z_20 29
+#define R_H8_DIR8Z_16 30
+#define R_H8_PCREL16 31
+#define R_H8_PCREL8 32
+#define R_H8_BPOS 33
+#define R_H8_PCREL32 34
+#define R_H8_GOT32O 35
+#define R_H8_GOT16O 36
+#define R_H8_DIR16A8 59
+#define R_H8_DIR16R8 60
+#define R_H8_DIR24A8 61
+#define R_H8_DIR24R8 62
+#define R_H8_DIR32A16 63
+#define R_H8_ABS32 65
+#define R_H8_ABS32A16 127
+
+
+#define R_TYPE(name) __CONCAT(R_H8_,name)
diff --git a/cpukit/libdl/include/arch/i386/machine/elf_machdep.h b/cpukit/libdl/include/arch/i386/machine/elf_machdep.h
new file mode 100644
index 0000000..442c561
--- /dev/null
+++ b/cpukit/libdl/include/arch/i386/machine/elf_machdep.h
@@ -0,0 +1,63 @@
+/* $NetBSD: elf_machdep.h,v 1.10 2009/05/30 05:56:52 skrll Exp $ */
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_386: \
+ case EM_486: \
+ break;
+
+#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */
+#define ELF64_MACHDEP_ID_CASES \
+ /* no 64-bit ELF machine types supported */
+
+#define ELF32_MACHDEP_ID EM_386
+
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+
+/* i386 relocations */
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+
+/* TLS relocations */
+#define R_386_TLS_TPOFF 14
+#define R_386_TLS_IE 15
+#define R_386_TLS_GOTIE 16
+#define R_386_TLS_LE 17
+#define R_386_TLS_GD 18
+#define R_386_TLS_LDM 19
+
+/* The following relocations are GNU extensions. */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+
+/* More TLS relocations */
+#define R_386_TLS_GD_32 24
+#define R_386_TLS_GD_PUSH 25
+#define R_386_TLS_GD_CALL 26
+#define R_386_TLS_GD_POP 27
+#define R_386_TLS_LDM_32 28
+#define R_386_TLS_LDM_PUSH 29
+#define R_386_TLS_LDM_CALL 30
+#define R_386_TLS_LDM_POP 31
+#define R_386_TLS_LDO_32 32
+#define R_386_TLS_IE_32 33
+#define R_386_TLS_LE_32 34
+#define R_386_TLS_DTPMOD32 35
+#define R_386_TLS_DTPOFF32 36
+#define R_386_TLS_TPOFF32 37
+#define R_386_TLS_GOTDESC 39
+#define R_386_TLS_DESC_CALL 40
+#define R_386_TLS_DESC 41
+
+#define R_TYPE(name) __CONCAT(R_386_,name)
diff --git a/cpukit/libdl/include/arch/lm32/machine/elf_machdep.h b/cpukit/libdl/include/arch/lm32/machine/elf_machdep.h
new file mode 100644
index 0000000..29c75b8
--- /dev/null
+++ b/cpukit/libdl/include/arch/lm32/machine/elf_machdep.h
@@ -0,0 +1,34 @@
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_LATTICEMICO32: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_LATTICEMICO32
+
+#define EF_MACH32_MACH 0x00000001
+
+//#define EF_BLACKFIN
+
+#define ARCH_ELFSIZE 32
+
+#define R_LM32_NONE 0
+#define R_LM32_8 1
+#define R_LM32_16 2
+#define R_LM32_32 3
+#define R_LM32_HI16 4
+#define R_LM32_LO16 5
+#define R_LM32_GPREL16 6
+#define R_LM32_CALL 7
+#define R_LM32_BRANCH 8
+#define R_LM32_GNU_VTINHERIT 9
+#define R_LM32_GNU_VTENTRY 10
+#define R_LM32_16_GOT 11
+#define R_LM32_GOTOFF_HI16 12
+#define R_LM32_GOTOFF_LO16 13
+#define R_LM32_COPY 14
+#define R_LM32_GLOT_DAT 15
+#define R_LM32_JMP_SLOT 16
+#define R_LM32_RELATIVE 17
+
+#define R_TYPE(name) __CONCAT(R_LM32_,name)
diff --git a/cpukit/libdl/include/arch/m32r/machine/elf_machdep.h b/cpukit/libdl/include/arch/m32r/machine/elf_machdep.h
new file mode 100644
index 0000000..3f531cf
--- /dev/null
+++ b/cpukit/libdl/include/arch/m32r/machine/elf_machdep.h
@@ -0,0 +1,39 @@
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_M32R: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_M32R
+
+#define ARCH_ELFSIZE 32
+
+#define R_M32R_NONE 0
+/*-----------OLD TYPE-------------*/
+#define R_M32R_16 1
+#define R_M32R_32 2
+#define R_M32R_24 3
+#define R_M32R_10_PCREL 4
+#define R_M32R_18_PCREL 5
+#define R_M32R_26_PCREL 6
+#define R_M32R_HI16_ULO 7
+#define R_M32R_HI16_SLO 8
+#define R_M32R_LO16 9
+#define R_M32R_SDA16 10
+#define R_M32R_GNU_VTINHERIT 11
+#define R_M32R_GNU_VTENTRY 12
+/*--------------------------------*/
+
+#define R_M32R_16_RELA 33
+#define R_M32R_32_RELA 34
+#define R_M32R_24_RELA 35
+#define R_M32R_18_PCREL_RELA 37
+#define R_M32R_26_PCREL_RELA 38
+#define R_M32R_HI16_ULO_RELA 39
+#define R_M32R_HI16_SLO_RELA 40
+#define R_M32R_LO16_RELA 41
+#define R_M32R_SDA16_RELA 42
+#define R_M32R_RELA_GNU_VTINHERIT 43
+#define R_M32R_RELA_GNU_VTENTRY 44
+
+#define R_TYPE(name) __CONCAT(R_M32R_,name)
diff --git a/cpukit/libdl/include/arch/m68k/machine/elf_machdep.h b/cpukit/libdl/include/arch/m68k/machine/elf_machdep.h
new file mode 100644
index 0000000..9a987c6
--- /dev/null
+++ b/cpukit/libdl/include/arch/m68k/machine/elf_machdep.h
@@ -0,0 +1,47 @@
+/* $NetBSD: elf_machdep.h,v 1.7 2002/01/28 21:34:48 thorpej Exp $ */
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_68K: \
+ break;
+
+#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */
+#define ELF64_MACHDEP_ID_CASES \
+ /* no 64-bit ELF machine types supported */
+
+#define ELF32_MACHDEP_ID EM_68K
+
+/*
+ * Machine-dependent ELF flags. These are defined by the GNU tools.
+ */
+#define EF_CPU32 0x00810000
+#define EF_M68000 0x01000000
+
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+
+/* m68k relocation types */
+#define R_68K_NONE 0
+#define R_68K_32 1
+#define R_68K_16 2
+#define R_68K_8 3
+#define R_68K_PC32 4
+#define R_68K_PC16 5
+#define R_68K_PC8 6
+#define R_68K_GOT32 7
+#define R_68K_GOT16 8
+#define R_68K_GOT8 9
+#define R_68K_GOT32O 10
+#define R_68K_GOT16O 11
+#define R_68K_GOT8O 12
+#define R_68K_PLT32 13
+#define R_68K_PLT16 14
+#define R_68K_PLT8 15
+#define R_68K_PLT32O 16
+#define R_68K_PLT16O 17
+#define R_68K_PLT8O 18
+#define R_68K_COPY 19
+#define R_68K_GLOB_DAT 20
+#define R_68K_JMP_SLOT 21
+#define R_68K_RELATIVE 22
+
+#define R_TYPE(name) __CONCAT(R_68K_,name)
diff --git a/cpukit/libdl/include/arch/mips/machine/elf_machdep.h b/cpukit/libdl/include/arch/mips/machine/elf_machdep.h
new file mode 100644
index 0000000..d27d431
--- /dev/null
+++ b/cpukit/libdl/include/arch/mips/machine/elf_machdep.h
@@ -0,0 +1,196 @@
+/* $NetBSD: elf_machdep.h,v 1.15 2011/03/15 07:39:22 matt Exp $ */
+
+#ifndef _MIPS_ELF_MACHDEP_H_
+#define _MIPS_ELF_MACHDEP_H_
+
+#ifdef _LP64
+#define ARCH_ELFSIZE 64 /* MD native binary size */
+#else
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+#endif
+
+#if ELFSIZE == 32
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_MIPS: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_MIPS
+#elif ELFSIZE == 64
+#define ELF64_MACHDEP_ID_CASES \
+ case EM_MIPS: \
+ break;
+
+#define ELF64_MACHDEP_ID EM_MIPS
+#endif
+
+/* mips relocs. */
+
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_REL32 3
+#define R_MIPS_REL R_MIPS_REL32
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5 /* high 16 bits of symbol value */
+#define R_MIPS_LO16 6 /* low 16 bits of symbol value */
+#define R_MIPS_GPREL16 7 /* GP-relative reference */
+#define R_MIPS_LITERAL 8 /* Reference to literal section */
+#define R_MIPS_GOT16 9 /* Reference to global offset table */
+#define R_MIPS_GOT R_MIPS_GOT16
+#define R_MIPS_PC16 10 /* 16 bit PC relative reference */
+#define R_MIPS_CALL16 11 /* 16 bit call thru glbl offset tbl */
+#define R_MIPS_CALL R_MIPS_CALL16
+#define R_MIPS_GPREL32 12
+
+/* 13, 14, 15 are not defined at this point. */
+#define R_MIPS_UNUSED1 13
+#define R_MIPS_UNUSED2 14
+#define R_MIPS_UNUSED3 15
+
+/*
+ * The remaining relocs are apparently part of the 64-bit Irix ELF ABI.
+ */
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_RELGOT 36
+#define R_MIPS_JALR 37
+/* TLS relocations */
+
+#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */
+#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */
+#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */
+#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */
+#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */
+#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */
+#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */
+#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */
+#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */
+#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */
+#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
+#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
+#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
+
+#define R_MIPS_max 51
+
+#define R_TYPE(name) __CONCAT(R_MIPS_,name)
+
+#define R_MIPS16_min 100
+#define R_MIPS16_26 100
+#define R_MIPS16_GPREL 101
+#define R_MIPS16_GOT16 102
+#define R_MIPS16_CALL16 103
+#define R_MIPS16_HI16 104
+#define R_MIPS16_LO16 105
+#define R_MIPS16_max 106
+
+
+/* mips dynamic tags */
+
+#define DT_MIPS_RLD_VERSION 0x70000001
+#define DT_MIPS_TIME_STAMP 0x70000002
+#define DT_MIPS_ICHECKSUM 0x70000003
+#define DT_MIPS_IVERSION 0x70000004
+#define DT_MIPS_FLAGS 0x70000005
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_CONFLICT 0x70000008
+#define DT_MIPS_LIBLIST 0x70000009
+#define DT_MIPS_CONFLICTNO 0x7000000b
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* number of local got ents */
+#define DT_MIPS_LIBLISTNO 0x70000010
+#define DT_MIPS_SYMTABNO 0x70000011 /* number of .dynsym entries */
+#define DT_MIPS_UNREFEXTNO 0x70000012
+#define DT_MIPS_GOTSYM 0x70000013 /* first dynamic sym in got */
+#define DT_MIPS_HIPAGENO 0x70000014
+#define DT_MIPS_RLD_MAP 0x70000016 /* address of loader map */
+
+/*
+ * ELF Flags
+ */
+#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */
+#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */
+#define EF_MIPS_ABI2 0x00000020 /* N32 */
+
+#define EF_MIPS_ARCH_ASE 0x0f000000 /* Architectural extensions */
+#define EF_MIPS_ARCH_MDMX 0x08000000 /* MDMX multimedia extension */
+#define EF_MIPS_ARCH_M16 0x04000000 /* MIPS-16 ISA extensions */
+
+#define EF_MIPS_ARCH 0xf0000000 /* Architecture field */
+#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */
+#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */
+#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */
+#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code */
+#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code */
+#define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code */
+#define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code */
+#define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code */
+#define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code */
+
+#define EF_MIPS_ABI 0x0000f000
+#define EF_MIPS_ABI_O32 0x00001000
+#define EF_MIPS_ABI_O64 0x00002000
+#define EF_MIPS_ABI_EABI32 0x00003000
+#define EF_MIPS_ABI_EABI64 0x00004000
+
+#if defined(__MIPSEB__)
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF64_MACHDEP_ENDIANNESS ELFDATA2MSB
+#elif defined(__MIPSEL__)
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+#define ELF64_MACHDEP_ENDIANNESS ELFDATA2LSB
+#elif !defined(HAVE_NBTOOL_CONFIG_H)
+#error neither __MIPSEL__ nor __MIPSEB__ are defined.
+#endif
+
+#ifdef _KERNEL
+#ifdef _KERNEL_OPT
+#include "opt_compat_netbsd.h"
+#endif
+#ifdef COMPAT_16
+/*
+ * Up to 1.6, the ELF dynamic loader (ld.elf_so) was not relocatable.
+ * Tell the kernel ELF exec code not to try relocating the interpreter
+ * for dynamically-linked ELF binaries.
+ */
+#define ELF_INTERP_NON_RELOCATABLE
+#endif /* COMPAT_16 */
+
+/*
+ * We need to be able to include the ELF header so we can pick out the
+ * ABI being used.
+ */
+#ifdef ELFSIZE
+#define ELF_MD_PROBE_FUNC ELFNAME2(mips_netbsd,probe)
+#define ELF_MD_COREDUMP_SETUP ELFNAME2(coredump,setup)
+#endif
+
+struct exec_package;
+
+int mips_netbsd_elf32_probe(struct lwp *, struct exec_package *, void *, char *,
+ vaddr_t *);
+void coredump_elf32_setup(struct lwp *, void *);
+
+int mips_netbsd_elf64_probe(struct lwp *, struct exec_package *, void *, char *,
+ vaddr_t *);
+void coredump_elf64_setup(struct lwp *, void *);
+#endif /* _KERNEL */
+
+#endif /* _MIPS_ELF_MACHDEP_H_ */
diff --git a/cpukit/libdl/include/arch/moxie/machine/elf_machdep.h b/cpukit/libdl/include/arch/moxie/machine/elf_machdep.h
new file mode 100644
index 0000000..3f0df23
--- /dev/null
+++ b/cpukit/libdl/include/arch/moxie/machine/elf_machdep.h
@@ -0,0 +1,15 @@
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_MOXIE: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_MOXIE
+
+#define ARCH_ELFSIZE 32
+
+#define R_MOXIE_NONE 0
+#define R_MOXIE_32 1
+#define R_MOXIE_PCREL10 2
+
+#define R_TYPE(name) __CONCAT(R_MOXIE_,name)
diff --git a/cpukit/libdl/include/arch/nios2/machine/elf_machdep.h b/cpukit/libdl/include/arch/nios2/machine/elf_machdep.h
new file mode 100644
index 0000000..3f3c108
--- /dev/null
+++ b/cpukit/libdl/include/arch/nios2/machine/elf_machdep.h
@@ -0,0 +1,46 @@
+/* $NetBSD: elf_machdep.h,v 1.7 2002/01/28 21:34:48 thorpej Exp $ */
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_ALTERA_NIOS2: \
+ break;
+
+#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */
+#define ELF64_MACHDEP_ID_CASES \
+ /* no 64-bit ELF machine types supported */
+
+#define ELF32_MACHDEP_ID EM_ALTERA_NIOS2
+
+/*
+ * Machine-dependent ELF flags. These are defined by the GNU tools.
+ */
+#define EF_NIOS2 0x00810000
+
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+
+/* NIOS2 relocation types */
+#define R_NIOS2_NONE 0
+#define R_NIOS2_32 1
+#define R_NIOS2_16 2
+#define R_NIOS2_8 3
+#define R_NIOS2_PC32 4
+#define R_NIOS2_PC16 5
+#define R_NIOS2_PC8 6
+#define R_NIOS2_GOT32 7
+#define R_NIOS2_GOT16 8
+#define R_NIOS2_GOT8 9
+#define R_NIOS2_GOT32O 10
+#define R_NIOS2_GOT16O 11
+#define R_NIOS2_GOT8O 12
+#define R_NIOS2_PLT32 13
+#define R_NIOS2_PLT16 14
+#define R_NIOS2_PLT8 15
+#define R_NIOS2_PLT32O 16
+#define R_NIOS2_PLT16O 17
+#define R_NIOS2_PLT8O 18
+#define R_NIOS2_COPY 19
+#define R_NIOS2_GLOB_DAT 20
+#define R_NIOS2_JMP_SLOT 21
+#define R_NIOS2_RELATIVE 22
+
+#define R_TYPE(name) __CONCAT(R_NIOS2_,name)
diff --git a/cpukit/libdl/include/arch/powerpc/machine/elf_machdep.h b/cpukit/libdl/include/arch/powerpc/machine/elf_machdep.h
new file mode 100644
index 0000000..f0fdb3f
--- /dev/null
+++ b/cpukit/libdl/include/arch/powerpc/machine/elf_machdep.h
@@ -0,0 +1,105 @@
+/* $NetBSD: elf_machdep.h,v 1.9 2011/01/15 10:00:07 matt Exp $ */
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_PPC: \
+ break;
+
+#define ELF64_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF64_MACHDEP_ID_CASES \
+ case EM_PPC64: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_PPC
+#define ELF64_MACHDEP_ID EM_PPC64
+
+#ifdef _LP64
+#define ARCH_ELFSIZE 64 /* MD native binary size */
+#else
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+#endif
+
+/* Specify the value of _GLOBAL_OFFSET_TABLE_ */
+#define DT_PPC_GOT DT_LOPROC
+
+#define R_PPC_NONE 0
+#define R_PPC_32 1
+#define R_PPC_24 2
+#define R_PPC_16 3
+#define R_PPC_16_LO 4
+#define R_PPC_16_HI 5 /* R_PPC_ADDIS */
+#define R_PPC_16_HA 6
+#define R_PPC_14 7
+#define R_PPC_14_TAKEN 8
+#define R_PPC_14_NTAKEN 9
+#define R_PPC_REL24 10 /* R_PPC_BRANCH */
+#define R_PPC_REL14 11
+#define R_PPC_REL14_TAKEN 12
+#define R_PPC_REL14_NTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLT24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_U32 24
+#define R_PPC_U16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+#define R_PPC_ADDR30 37
+
+/* TLS relocations */
+#define R_PPC_TLS 67
+
+#define R_PPC_DTPMOD32 68
+#define R_PPC_TPREL16 69
+#define R_PPC_TPREL16_LO 70
+#define R_PPC_TPREL16_HI 71
+#define R_PPC_TPREL16_HA 72
+#define R_PPC_TPREL32 73
+#define R_PPC_DTPREL16 74
+#define R_PPC_DTPREL16_LO 75
+#define R_PPC_DTPREL16_HI 76
+#define R_PPC_DTPREL16_HA 77
+#define R_PPC_DTPREL32 78
+
+#define R_PPC_GOT_TLSGD16 79
+#define R_PPC_GOT_TLSGD16_LO 80
+#define R_PPC_GOT_TLSGD16_HI 81
+#define R_PPC_GOT_TLSGD16_HA 82
+#define R_PPC_GOT_TLSLD16 83
+#define R_PPC_GOT_TLSLD16_LO 84
+#define R_PPC_GOT_TLSLD16_HI 85
+#define R_PPC_GOT_TLSLD16_HA 86
+
+#define R_PPC_GOT_TPREL16 87
+#define R_PPC_GOT_TPREL16_LO 88
+#define R_PPC_GOT_TPREL16_HI 89
+#define R_PPC_GOT_TPREL16_HA 90
+#define R_PPC_GOT_DTPREL16 91
+#define R_PPC_GOT_DTPREL16_LO 92
+#define R_PPC_GOT_DTPREL16_HI 93
+#define R_PPC_GOT_DTPREL16_HA 94
+#define R_PPC_TLSGD 95
+#define R_PPC_TLSLD 96
+
+/* Used for the secure-plt PIC code sequences */
+#define R_PPC_REL16 249
+#define R_PPC_REL16_LO 250
+#define R_PPC_REL16_HI 251
+#define R_PPC_REL16_HA 252
+
+#define R_TYPE(name) __CONCAT(R_PPC_,name)
diff --git a/cpukit/libdl/include/arch/sparc/machine/elf_machdep.h b/cpukit/libdl/include/arch/sparc/machine/elf_machdep.h
new file mode 100644
index 0000000..e8f2b63
--- /dev/null
+++ b/cpukit/libdl/include/arch/sparc/machine/elf_machdep.h
@@ -0,0 +1,92 @@
+/* $NetBSD: elf_machdep.h,v 1.7 2009/05/30 05:56:53 skrll Exp $ */
+
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_SPARC: \
+ case EM_SPARC32PLUS: \
+ break;
+
+#define ELF64_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF64_MACHDEP_ID_CASES \
+ case EM_SPARC32PLUS: \
+ case EM_SPARCV9: \
+ /* no 64-bit ELF machine types supported */
+
+#define ELF32_MACHDEP_ID EM_SPARC /* XXX right? */
+
+#define ARCH_ELFSIZE 32 /* MD native binary size */
+
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_HH22 34
+#define R_SPARC_HM10 35
+#define R_SPARC_LM22 36
+#define R_SPARC_PC_HH22 37
+#define R_SPARC_PC_HM10 38
+#define R_SPARC_PC_LM22 39
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_GLOB_JMP 42
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+
+/* TLS relocations */
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+
+#define R_TYPE(name) __CONCAT(R_SPARC_,name)
diff --git a/cpukit/libdl/include/arch/v850/machine/elf_machdep.h b/cpukit/libdl/include/arch/v850/machine/elf_machdep.h
new file mode 100644
index 0000000..b76d149
--- /dev/null
+++ b/cpukit/libdl/include/arch/v850/machine/elf_machdep.h
@@ -0,0 +1,74 @@
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_V850: \
+ break;
+
+#define ELF32_MACHDEP_ID EM_V850
+
+
+
+#define EF_V850_ARCH 0xf0000000
+#define E_V850_ARCH 0x00000000
+#define E_V850E_ARCH 0x10000000
+#define E_V850E1_ARCH 0x20000000
+#define E_V850E2_ARCH 0x30000000
+#define E_V850E2V3_ARCH 0x40000000
+
+#define ARCH_ELFSIZE 32
+
+
+#define R_V850_NONE 0
+#define R_V850_9_PCREL 1
+#define R_V850_22_PCREL 2
+#define R_V850_HI16_S 3
+#define R_V850_HI16 4
+#define R_V850_LO16 5
+#define R_V850_ABS32 6
+#define R_V850_16 7
+#define R_V850_8 8
+#define R_V850_SDA_16_16_OFFSET 9
+#define R_V850_SDA_15_16_OFFSET 10
+#define R_V850_ZDA_16_16_OFFSET 11
+#define R_V850_ZDA_15_16_OFFSET 12
+#define R_V850_TDA_6_8_OFFSET 13
+#define R_V850_TDA_7_8_OFFSET 14
+#define R_V850_TDA_7_7_OFFSET 15
+#define R_V850_TDA_16_16_OFFSET 16
+#define R_V850_TDA_4_5_OFFSET 17
+#define R_V850_TDA_4_4_OFFSET 18
+#define R_V850_SDA_16_16_SPLIT_OFFSET 19
+#define R_V850_ZDA_16_16_SPLIT_OFFSET 20
+#define R_V850_CALLT_6_7_OFFSET 21
+#define R_V850_CALLT_16_16_OFFSET 22
+#define R_V850_GNU_VTINHERIT 23
+#define R_V850_GNU_VTENTRY 24
+#define R_V850_LONGCALL 25
+#define R_V850_LONGJUMP 26
+#define R_V850_ALIGN 27
+#define R_V850_REL32 28
+#define R_V850_LO16_SPLIT_OFFSET 29
+#define R_V850_16_PCREL 30
+#define R_V850_17_PCREL 31
+#define R_V850_23 32
+#define R_V850_32_PCREL 33
+#define R_V850_32_ABS 34
+#define R_V850_16_SPLIT_OFFSET 35
+#define R_V850_16_S1 36
+#define R_V850_LO16_S1 37
+#define R_V850_CALLT_15_16_OFFSET 38
+#define R_V850_32_GOTPCREL 39
+#define R_V850_16_GOT 40
+#define R_V850_32_GOT 41
+#define R_V850_22_PLT 42
+#define R_V850_32_PLT 43
+#define R_V850_COPY 44
+#define R_V850_GLOB_DAT 45
+#define R_V850_JMP_SLOT 46
+#define R_V850_RELATIVE 47
+#define R_V850_16_GOTOFF 48
+#define R_V850_32_GOTOFF 49
+#define R_V850_CODE 50
+#define R_V850_DATA 51
+
+#define R_TYPE(name) __CONCAT(R_V850_,name)
diff --git a/cpukit/libdl/include/link.h b/cpukit/libdl/include/link.h
new file mode 100644
index 0000000..c93efd9
--- /dev/null
+++ b/cpukit/libdl/include/link.h
@@ -0,0 +1,45 @@
+/* $NetBSD: link.h,v 1.13 2008/04/28 20:22:54 martin Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _LINK_H_
+#define _LINK_H_
+
+/*
+ * Pull in the correct definitions for our toolchain target.
+ */
+#ifdef __ELF__
+#include <link_elf.h>
+#else
+#include <link_aout.h>
+#endif
+
+#endif /* _LINK_H_ */
diff --git a/cpukit/libdl/include/link_elf.h b/cpukit/libdl/include/link_elf.h
new file mode 100644
index 0000000..d2691b6
--- /dev/null
+++ b/cpukit/libdl/include/link_elf.h
@@ -0,0 +1,79 @@
+/* $NetBSD: link_elf.h,v 1.8 2009/11/04 19:28:03 pooka Exp $ */
+
+/*
+ * This only exists for GDB.
+ */
+
+#ifndef _LINK_ELF_H_
+#define _LINK_ELF_H_
+
+#include <sys/types.h>
+
+#include <machine/elf_machdep.h>
+#include <stdint.h>
+#include <rtems/rtl/rtl-obj-fwd.h>
+
+enum sections
+{
+ rap_text = 0,
+ rap_const = 1,
+ rap_ctor = 2,
+ rap_dtor = 3,
+ rap_data = 4,
+ rap_bss = 5,
+ rap_secs = 6
+};
+
+/**
+ * Object details.
+ */
+typedef struct
+{
+ const char* name; /**< Section name. */
+ uint32_t offset; /**< The offset in the elf file. */
+ uint32_t size; /**< The size of the section. */
+ uint32_t rap_id; /**< Which obj does this section belongs to. */
+}section_detail;
+
+/**
+ * link map structure will be used for GDB support.
+ */
+struct link_map {
+ const char* name; /**< Name of the obj. */
+ uint32_t sec_num; /**< The count of section. */
+ section_detail* sec_detail; /**< The section details. */
+ uint32_t* sec_addr[rap_secs]; /**< The RAP section addr. */
+ uint32_t rpathlen; /**< The length of the path. */
+ char* rpath; /**< The path of object files. */
+ struct link_map* l_next; /**< Linked list of mapped libs. */
+ struct link_map* l_prev;
+};
+
+/**
+ * r_debug is used to manage the debug related structures.
+ */
+struct r_debug {
+ int r_version; /* not used */
+ struct link_map *r_map; /* list of loaded images */
+ enum {
+ RT_CONSISTENT, /* things are stable */
+ RT_ADD, /* adding a shared library */
+ RT_DELETE /* removing a shared library */
+ } r_state;
+};
+
+/*
+ * stub function. It is empty.
+ */
+void _rtld_debug_state (void);
+
+/*
+ * add link map to the list.
+ */
+int _rtld_linkmap_add (rtems_rtl_obj_t* obj);
+
+/*
+ * Remove link map from the list.
+ */
+void _rtld_linkmap_delete (rtems_rtl_obj_t* obj);
+#endif /* _LINK_ELF_H_ */
diff --git a/cpukit/libdl/include/sys/cdefs_elf.h b/cpukit/libdl/include/sys/cdefs_elf.h
new file mode 100644
index 0000000..91903d6
--- /dev/null
+++ b/cpukit/libdl/include/sys/cdefs_elf.h
@@ -0,0 +1,152 @@
+/* $NetBSD: cdefs_elf.h,v 1.24 2005/07/16 17:53:36 christos Exp $ */
+
+/*
+ * Copyright (c) 1995, 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _SYS_CDEFS_ELF_H_
+#define _SYS_CDEFS_ELF_H_
+
+#ifdef __LEADING_UNDERSCORE
+#define _C_LABEL(x) __CONCAT(_,x)
+#define _C_LABEL_STRING(x) "_"x
+#else
+#define _C_LABEL(x) x
+#define _C_LABEL_STRING(x) x
+#endif
+
+#if __STDC__
+#define ___RENAME(x) __asm__(___STRING(_C_LABEL(x)))
+#else
+#ifdef __LEADING_UNDERSCORE
+#define ___RENAME(x) ____RENAME(_/**/x)
+#define ____RENAME(x) __asm__(___STRING(x))
+#else
+#define ___RENAME(x) __asm__(___STRING(x))
+#endif
+#endif
+
+#define __indr_reference(sym,alias) /* nada, since we do weak refs */
+
+#if __STDC__
+#define __strong_alias(alias,sym) \
+ __asm__(".global " _C_LABEL_STRING(#alias) "\n" \
+ _C_LABEL_STRING(#alias) " = " _C_LABEL_STRING(#sym));
+
+#define __weak_alias(alias,sym) \
+ __asm__(".weak " _C_LABEL_STRING(#alias) "\n" \
+ _C_LABEL_STRING(#alias) " = " _C_LABEL_STRING(#sym));
+#define __weak_extern(sym) \
+ __asm__(".weak " _C_LABEL_STRING(#sym));
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu.warning." #sym "\n\t.ascii \"" msg "\"\n\t.text");
+
+#else /* !__STDC__ */
+
+#ifdef __LEADING_UNDERSCORE
+#define __weak_alias(alias,sym) ___weak_alias(_/**/alias,_/**/sym)
+#define ___weak_alias(alias,sym) \
+ __asm__(".weak alias\nalias = sym");
+#else
+#define __weak_alias(alias,sym) \
+ __asm__(".weak alias\nalias = sym");
+#endif
+#ifdef __LEADING_UNDERSCORE
+#define __weak_extern(sym) ___weak_extern(_/**/sym)
+#define ___weak_extern(sym) \
+ __asm__(".weak sym");
+#else
+#define __weak_extern(sym) \
+ __asm__(".weak sym");
+#endif
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu.warning.sym\n\t.ascii msg ; .text");
+
+#endif /* !__STDC__ */
+
+#if __STDC__
+#define __SECTIONSTRING(_sec, _str) \
+ __asm__(".section " #_sec "\n\t.asciz \"" _str "\"\n\t.previous")
+#else
+#define __SECTIONSTRING(_sec, _str) \
+ __asm__(".section _sec\n\t.asciz _str\n\t.previous")
+#endif
+
+#define __IDSTRING(_n,_s) __SECTIONSTRING(.ident,_s)
+
+#define __RCSID(_s) __IDSTRING(rcsid,_s)
+#define __SCCSID(_s)
+#define __SCCSID2(_s)
+#if 0 /* XXX userland __COPYRIGHTs have \ns in them */
+#define __COPYRIGHT(_s) __SECTIONSTRING(.copyright,_s)
+#else
+#define __COPYRIGHT(_s) \
+ static const char copyright[] \
+ __attribute__((__unused__,__section__(".copyright"))) = _s
+#endif
+
+#define __KERNEL_RCSID(_n, _s) __RCSID(_s)
+#define __KERNEL_SCCSID(_n, _s)
+#if 0 /* XXX see above */
+#define __KERNEL_COPYRIGHT(_n, _s) __COPYRIGHT(_s)
+#else
+#define __KERNEL_COPYRIGHT(_n, _s) __SECTIONSTRING(.copyright, _s)
+#endif
+
+#ifndef __lint__
+#define __link_set_make_entry(set, sym) \
+ static void const * const __link_set_##set##_sym_##sym \
+ __section("link_set_" #set) __used = &sym
+#define __link_set_make_entry2(set, sym, n) \
+ static void const * const __link_set_##set##_sym_##sym##_##n \
+ __section("link_set_" #set) __used = &sym[n]
+#else
+#define __link_set_make_entry(set, sym) \
+ extern void const * const __link_set_##set##_sym_##sym
+#define __link_set_make_entry2(set, sym, n) \
+ extern void const * const __link_set_##set##_sym_##sym##_##n
+#endif /* __lint__ */
+
+#define __link_set_add_text(set, sym) __link_set_make_entry(set, sym)
+#define __link_set_add_rodata(set, sym) __link_set_make_entry(set, sym)
+#define __link_set_add_data(set, sym) __link_set_make_entry(set, sym)
+#define __link_set_add_bss(set, sym) __link_set_make_entry(set, sym)
+#define __link_set_add_text2(set, sym, n) __link_set_make_entry2(set, sym, n)
+#define __link_set_add_rodata2(set, sym, n) __link_set_make_entry2(set, sym, n)
+#define __link_set_add_data2(set, sym, n) __link_set_make_entry2(set, sym, n)
+#define __link_set_add_bss2(set, sym, n) __link_set_make_entry2(set, sym, n)
+
+#define __link_set_decl(set, ptype) \
+ extern ptype * const __start_link_set_##set[]; \
+ extern ptype * const __stop_link_set_##set[] \
+
+#define __link_set_start(set) (__start_link_set_##set)
+#define __link_set_end(set) (__stop_link_set_##set)
+
+#define __link_set_count(set) \
+ (__link_set_end(set) - __link_set_start(set))
+
+#endif /* !_SYS_CDEFS_ELF_H_ */
diff --git a/cpukit/libdl/include/sys/exec_elf.h b/cpukit/libdl/include/sys/exec_elf.h
new file mode 100644
index 0000000..08da7e8
--- /dev/null
+++ b/cpukit/libdl/include/sys/exec_elf.h
@@ -0,0 +1,1097 @@
+/* $NetBSD: exec_elf.h,v 1.102 2010/03/01 11:27:29 skrll Exp $ */
+
+/*-
+ * Copyright (c) 1994 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _SYS_EXEC_ELF_H_
+#define _SYS_EXEC_ELF_H_
+
+/*
+ * The current ELF ABI specification is available at:
+ * http://www.sco.com/developers/gabi/
+ *
+ * Current header definitions are in:
+ * http://www.sco.com/developers/gabi/latest/ch4.eheader.html
+ */
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/types.h>
+#else
+#include <inttypes.h>
+#endif /* _KERNEL || _STANDALONE */
+
+#if defined(ELFSIZE)
+#define CONCAT(x,y) __CONCAT(x,y)
+#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
+#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
+#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
+#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
+#endif
+
+#if HAVE_NBTOOL_CONFIG_H
+#include <nbinclude/machine/elf_machdep.h>
+#else
+#include <machine/elf_machdep.h>
+#endif
+
+typedef uint8_t Elf_Byte;
+
+typedef uint32_t Elf32_Addr;
+#define ELF32_FSZ_ADDR 4
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_SOff;
+#define ELF32_FSZ_OFF 4
+typedef int32_t Elf32_Sword;
+#define ELF32_FSZ_SWORD 4
+typedef uint32_t Elf32_Word;
+#define ELF32_FSZ_WORD 4
+typedef uint16_t Elf32_Half;
+#define ELF32_FSZ_HALF 2
+typedef uint64_t Elf32_Lword;
+#define ELF32_FSZ_LWORD 8
+
+typedef uint64_t Elf64_Addr;
+#define ELF64_FSZ_ADDR 8
+typedef uint64_t Elf64_Off;
+typedef int64_t Elf64_SOff;
+#define ELF64_FSZ_OFF 8
+typedef int32_t Elf64_Shalf;
+#define ELF64_FSZ_SHALF 4
+
+#ifndef ELF64_FSZ_SWORD
+typedef int32_t Elf64_Sword;
+#define ELF64_FSZ_SWORD 4
+#endif /* ELF64_FSZ_SWORD */
+#ifndef ELF64_FSZ_WORD
+typedef uint32_t Elf64_Word;
+#define ELF64_FSZ_WORD 4
+#endif /* ELF64_FSZ_WORD */
+
+typedef int64_t Elf64_Sxword;
+#define ELF64_FSZ_SXWORD 8
+typedef uint64_t Elf64_Xword;
+#define ELF64_FSZ_XWORD 8
+typedef uint64_t Elf64_Lword;
+#define ELF64_FSZ_LWORD 8
+typedef uint32_t Elf64_Half;
+#define ELF64_FSZ_HALF 4
+typedef uint16_t Elf64_Quarter;
+#define ELF64_FSZ_QUARTER 2
+
+/*
+ * ELF Header
+ */
+#define ELF_NIDENT 16
+
+typedef struct {
+ unsigned char e_ident[ELF_NIDENT]; /* Id bytes */
+ Elf32_Half e_type; /* file type */
+ Elf32_Half e_machine; /* machine type */
+ Elf32_Word e_version; /* version number */
+ Elf32_Addr e_entry; /* entry point */
+ Elf32_Off e_phoff; /* Program hdr offset */
+ Elf32_Off e_shoff; /* Section hdr offset */
+ Elf32_Word e_flags; /* Processor flags */
+ Elf32_Half e_ehsize; /* sizeof ehdr */
+ Elf32_Half e_phentsize; /* Program header entry size */
+ Elf32_Half e_phnum; /* Number of program headers */
+ Elf32_Half e_shentsize; /* Section header entry size */
+ Elf32_Half e_shnum; /* Number of section headers */
+ Elf32_Half e_shstrndx; /* String table index */
+} Elf32_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[ELF_NIDENT]; /* Id bytes */
+ Elf64_Quarter e_type; /* file type */
+ Elf64_Quarter e_machine; /* machine type */
+ Elf64_Half e_version; /* version number */
+ Elf64_Addr e_entry; /* entry point */
+ Elf64_Off e_phoff; /* Program hdr offset */
+ Elf64_Off e_shoff; /* Section hdr offset */
+ Elf64_Half e_flags; /* Processor flags */
+ Elf64_Quarter e_ehsize; /* sizeof ehdr */
+ Elf64_Quarter e_phentsize; /* Program header entry size */
+ Elf64_Quarter e_phnum; /* Number of program headers */
+ Elf64_Quarter e_shentsize; /* Section header entry size */
+ Elf64_Quarter e_shnum; /* Number of section headers */
+ Elf64_Quarter e_shstrndx; /* String table index */
+} Elf64_Ehdr;
+
+/* e_ident offsets */
+#define EI_MAG0 0 /* '\177' */
+#define EI_MAG1 1 /* 'E' */
+#define EI_MAG2 2 /* 'L' */
+#define EI_MAG3 3 /* 'F' */
+#define EI_CLASS 4 /* File class */
+#define EI_DATA 5 /* Data encoding */
+#define EI_VERSION 6 /* File version */
+#define EI_OSABI 7 /* Operating system/ABI identification */
+#define EI_ABIVERSION 8 /* ABI version */
+#define EI_PAD 9 /* Start of padding bytes up to EI_NIDENT*/
+#define EI_NIDENT 16 /* First non-ident header byte */
+
+/* e_ident[EI_MAG0,EI_MAG3] */
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+/* e_ident[EI_CLASS] */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+#define ELFCLASSNUM 3
+
+/* e_ident[EI_DATA] */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement values, LSB first */
+#define ELFDATA2MSB 2 /* 2's complement values, MSB first */
+
+/* e_ident[EI_VERSION] */
+#define EV_NONE 0 /* Invalid version */
+#define EV_CURRENT 1 /* Current version */
+#define EV_NUM 2
+
+/* e_ident[EI_OSABI] */
+#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
+#define ELFOSABI_HPUX 1 /* HP-UX operating system */
+#define ELFOSABI_NETBSD 2 /* NetBSD */
+#define ELFOSABI_LINUX 3 /* GNU/Linux */
+#define ELFOSABI_HURD 4 /* GNU/Hurd */
+#define ELFOSABI_86OPEN 5 /* 86Open */
+#define ELFOSABI_SOLARIS 6 /* Solaris */
+#define ELFOSABI_MONTEREY 7 /* Monterey */
+#define ELFOSABI_IRIX 8 /* IRIX */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD */
+#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD */
+#define ELFOSABI_OPENVMS 13 /* OpenVMS */
+#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
+#define ELFOSABI_AROS 15 /* Amiga Research OS */
+/* Unofficial OSABIs follow */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define ELFOSABI_NONE ELFOSABI_SYSV
+#define ELFOSABI_AIX ELFOSABI_MONTEREY
+
+/* e_type */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_NUM 5
+
+#define ET_LOOS 0xfe00 /* Operating system specific range */
+#define ET_HIOS 0xfeff
+#define ET_LOPROC 0xff00 /* Processor-specific range */
+#define ET_HIPROC 0xffff
+
+/* e_machine */
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola 68000 */
+#define EM_88K 5 /* Motorola 88000 */
+#define EM_486 6 /* Intel 80486 */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS I Architecture */
+#define EM_S370 9 /* Amdahl UTS on System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */
+ /* 11-14 - Reserved */
+#define EM_RS6000 11 /* IBM RS/6000 XXX reserved */
+#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */
+#define EM_NCUBE 16 /* NCube XXX reserved */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* 64-bit PowerPC */
+ /* 22-35 - Reserved */
+#define EM_S390 22 /* System/390 XXX reserved */
+#define EM_V800 36 /* NEC V800 */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* Advanced RISC Machines ARM */
+#define EM_ALPHA 41 /* DIGITAL Alpha */
+#define EM_SH 42 /* Hitachi Super-H */
+#define EM_SPARCV9 43 /* SPARC Version 9 */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced Processor */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola MC68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Star*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronics ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded family processor */
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */
+#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */
+#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */
+#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_ST19 74 /* STMicroelectronics ST19 8-bit CPU */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded CPU */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP processor */
+#define EM_ZSP 79 /* LSI Logic's 16-bit DSP processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard's machine-independent format */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */
+#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */
+#define EM_NS32K 97 /* National Semiconductor 32000 series */
+#define EM_TPC 98 /* Tenor Network TPC processor */
+#define EM_SNP1K 99 /* Trebia SNP 1000 processor */
+#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller */
+#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */
+#define EM_MAX 102 /* MAX processor */
+#define EM_CR 103 /* National Semiconductor CompactRISC micorprocessor */
+#define EM_F2MC16 104 /* Fujitsu F2MC16 */
+#define EM_MSP430 105 /* Texas Instruments MSP430 */
+#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */
+#define EM_SE_C33 107 /* Seiko Epson S1C33 family */
+#define EM_SEP 108 /* Sharp embedded microprocessor */
+#define EM_ARCA 109 /* Arca RISC microprocessor */
+#define EM_UNICORE 110 /* UNICORE from PKU-Unity Ltd. and MPRC Peking University */
+#define EM_EXCESS 111 /* eXcess: 16/32/64-bit configurable embedded CPU */
+#define EM_DXP 112 /* Icera Semiconductor Inc. Deep Execution Processor */
+#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
+#define EM_CRX 114 /* National Semiconductor CRX */
+#define EM_XGATE 115 /* Motorola XGATE embedded processor */
+#define EM_C166 116 /* Infineon C16x/XC16x processor */
+#define EM_M16C 117 /* Renesas M16C series microprocessors */
+#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F Digital Signal Controller */
+#define EM_CE 119 /* Freescale Communication Engine RISC core */
+#define EM_M32C 120 /* Renesas M32C series microprocessors */
+
+#define EM_LATTICEMICO32 138 /* RICS processor for Lattice FPGA architecture */
+
+#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze 32-bit RISC soft processor core */
+
+#define EM_MOXIE 0xFEED
+
+/* Unofficial machine types follow */
+#define EM_AVR32 6317 /* used by NetBSD/avr32 */
+#define EM_ALPHA_EXP 36902 /* used by NetBSD/alpha; obsolete */
+#define EM_NUM 36903
+
+/*
+ * Program Header
+ */
+typedef struct {
+ Elf32_Word p_type; /* entry type */
+ Elf32_Off p_offset; /* offset */
+ Elf32_Addr p_vaddr; /* virtual address */
+ Elf32_Addr p_paddr; /* physical address */
+ Elf32_Word p_filesz; /* file size */
+ Elf32_Word p_memsz; /* memory size */
+ Elf32_Word p_flags; /* flags */
+ Elf32_Word p_align; /* memory & file alignment */
+} Elf32_Phdr;
+
+typedef struct {
+ Elf64_Half p_type; /* entry type */
+ Elf64_Half p_flags; /* flags */
+ Elf64_Off p_offset; /* offset */
+ Elf64_Addr p_vaddr; /* virtual address */
+ Elf64_Addr p_paddr; /* physical address */
+ Elf64_Xword p_filesz; /* file size */
+ Elf64_Xword p_memsz; /* memory size */
+ Elf64_Xword p_align; /* memory & file alignment */
+} Elf64_Phdr;
+
+/* p_type */
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved, unspecified semantics */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_NUM 7
+
+#define PT_LOOS 0x60000000 /* OS-specific range */
+#define PT_HIOS 0x6fffffff
+#define PT_LOPROC 0x70000000 /* Processor-specific range */
+#define PT_HIPROC 0x7fffffff
+
+#define PT_MIPS_REGINFO 0x70000000
+
+/* p_flags */
+#define PF_R 0x4 /* Segment is readable */
+#define PF_W 0x2 /* Segment is writable */
+#define PF_X 0x1 /* Segment is executable */
+
+#define PF_MASKOS 0x0ff00000 /* Operating system specific values */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific values */
+
+/* Extended program header index. */
+#define PN_XNUM 0xffff
+
+/*
+ * Section Headers
+ */
+typedef struct {
+ Elf32_Word sh_name; /* section name (.shstrtab index) */
+ Elf32_Word sh_type; /* section type */
+ Elf32_Word sh_flags; /* section flags */
+ Elf32_Addr sh_addr; /* virtual address */
+ Elf32_Off sh_offset; /* file offset */
+ Elf32_Word sh_size; /* section size */
+ Elf32_Word sh_link; /* link to another */
+ Elf32_Word sh_info; /* misc info */
+ Elf32_Word sh_addralign; /* memory alignment */
+ Elf32_Word sh_entsize; /* table entry size */
+} Elf32_Shdr;
+
+typedef struct {
+ Elf64_Half sh_name; /* section name (.shstrtab index) */
+ Elf64_Half sh_type; /* section type */
+ Elf64_Xword sh_flags; /* section flags */
+ Elf64_Addr sh_addr; /* virtual address */
+ Elf64_Off sh_offset; /* file offset */
+ Elf64_Xword sh_size; /* section size */
+ Elf64_Half sh_link; /* link to another */
+ Elf64_Half sh_info; /* misc info */
+ Elf64_Xword sh_addralign; /* memory alignment */
+ Elf64_Xword sh_entsize; /* table entry size */
+} Elf64_Shdr;
+
+/* sh_type */
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program information */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation information w/ addend */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Auxiliary information */
+#define SHT_NOBITS 8 /* No space allocated in file image */
+#define SHT_REL 9 /* Relocation information w/o addend */
+#define SHT_SHLIB 10 /* Reserved, unspecified semantics */
+#define SHT_DYNSYM 11 /* Symbol table for dynamic linker */
+#define SHT_INIT_ARRAY 14 /* Initialization function pointers */
+#define SHT_FINI_ARRAY 15 /* Termination function pointers */
+#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs */
+#define SHT_GROUP 17 /* Section group */
+#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX) */
+#define SHT_NUM 19
+
+#define SHT_LOOS 0x60000000 /* Operating system specific range */
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_SUNW_verdef 0x6ffffffd /* Versions defined by file */
+#define SHT_GNU_verdef SHT_SUNW_verdef
+#define SHT_SUNW_verneed 0x6ffffffe /* Versions needed by file */
+#define SHT_GNU_verneed SHT_SUNW_verneed
+#define SHT_SUNW_versym 0x6fffffff /* Symbol versions */
+#define SHT_GNU_versym SHT_SUNW_versym
+#define SHT_HIOS 0x6fffffff
+#define SHT_LOPROC 0x70000000 /* Processor-specific range */
+#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000 /* Application-specific range */
+#define SHT_HIUSER 0xffffffff
+
+/* sh_flags */
+#define SHF_WRITE 0x1 /* Section contains writable data */
+#define SHF_ALLOC 0x2 /* Section occupies memory */
+#define SHF_EXECINSTR 0x4 /* Section contains executable insns */
+
+#define SHF_MASKOS 0x0f000000 /* Operating system specific values */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific values */
+
+/*
+ * Symbol Table
+ */
+typedef struct {
+ Elf32_Word st_name; /* Symbol name (.strtab index) */
+ Elf32_Word st_value; /* value of symbol */
+ Elf32_Word st_size; /* size of symbol */
+ Elf_Byte st_info; /* type / binding attrs */
+ Elf_Byte st_other; /* unused */
+ Elf32_Half st_shndx; /* section index of symbol */
+} Elf32_Sym;
+
+typedef struct {
+ Elf64_Half st_name; /* Symbol name (.strtab index) */
+ Elf_Byte st_info; /* type / binding attrs */
+ Elf_Byte st_other; /* unused */
+ Elf64_Quarter st_shndx; /* section index of symbol */
+ Elf64_Addr st_value; /* value of symbol */
+ Elf64_Xword st_size; /* size of symbol */
+} Elf64_Sym;
+
+/* Symbol Table index of the undefined symbol */
+#define ELF_SYM_UNDEFINED 0
+
+#define STN_UNDEF 0 /* undefined index */
+
+/* st_info: Symbol Bindings */
+#define STB_LOCAL 0 /* local symbol */
+#define STB_GLOBAL 1 /* global symbol */
+#define STB_WEAK 2 /* weakly defined global symbol */
+#define STB_NUM 3
+
+#define STB_LOOS 10 /* Operating system specific range */
+#define STB_HIOS 12
+#define STB_LOPROC 13 /* Processor-specific range */
+#define STB_HIPROC 15
+
+/* st_info: Symbol Types */
+#define STT_NOTYPE 0 /* Type not specified */
+#define STT_OBJECT 1 /* Associated with a data object */
+#define STT_FUNC 2 /* Associated with a function */
+#define STT_SECTION 3 /* Associated with a section */
+#define STT_FILE 4 /* Associated with a file name */
+#define STT_COMMON 5 /* Uninitialised common block */
+#define STT_TLS 6 /* Thread local data object */
+#define STT_NUM 7
+
+#define STT_LOOS 10 /* Operating system specific range */
+#define STT_HIOS 12
+#define STT_LOPROC 13 /* Processor-specific range */
+#define STT_HIPROC 15
+
+/* st_other: Visibility Types */
+#define STV_DEFAULT 0 /* use binding type */
+#define STV_INTERNAL 1 /* not referenced from outside */
+#define STV_HIDDEN 2 /* not visible, may be used via ptr */
+#define STV_PROTECTED 3 /* visible, not preemptible */
+#define STV_EXPORTED 4
+#define STV_SINGLETON 5
+#define STV_ELIMINATE 6
+
+/* st_info/st_other utility macros */
+#define ELF_ST_BIND(info) ((uint32_t)(info) >> 4)
+#define ELF_ST_TYPE(info) ((uint32_t)(info) & 0xf)
+#define ELF_ST_INFO(bind,type) ((Elf_Byte)(((bind) << 4) | \
+ ((type) & 0xf)))
+#define ELF_ST_VISIBILITY(other) ((uint32_t)(other) & 3)
+
+/*
+ * Special section indexes
+ */
+#define SHN_UNDEF 0 /* Undefined section */
+
+#define SHN_LORESERVE 0xff00 /* Reserved range */
+#define SHN_ABS 0xfff1 /* Absolute symbols */
+#define SHN_COMMON 0xfff2 /* Common symbols */
+#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere */
+#define SHN_HIRESERVE 0xffff
+
+#define SHN_LOPROC 0xff00 /* Processor-specific range */
+#define SHN_HIPROC 0xff1f
+#define SHN_LOOS 0xff20 /* Operating system specific range */
+#define SHN_HIOS 0xff3f
+
+#define SHN_MIPS_ACOMMON 0xff00
+#define SHN_MIPS_TEXT 0xff01
+#define SHN_MIPS_DATA 0xff02
+#define SHN_MIPS_SCOMMON 0xff03
+
+/*
+ * Relocation Entries
+ */
+typedef struct {
+ Elf32_Word r_offset; /* where to do it */
+ Elf32_Word r_info; /* index & type of relocation */
+} Elf32_Rel;
+
+typedef struct {
+ Elf32_Word r_offset; /* where to do it */
+ Elf32_Word r_info; /* index & type of relocation */
+ Elf32_Sword r_addend; /* adjustment value */
+} Elf32_Rela;
+
+/* r_info utility macros */
+#define ELF32_R_SYM(info) ((info) >> 8)
+#define ELF32_R_TYPE(info) ((info) & 0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
+
+typedef struct {
+ Elf64_Addr r_offset; /* where to do it */
+ Elf64_Xword r_info; /* index & type of relocation */
+} Elf64_Rel;
+
+typedef struct {
+ Elf64_Addr r_offset; /* where to do it */
+ Elf64_Xword r_info; /* index & type of relocation */
+ Elf64_Sxword r_addend; /* adjustment value */
+} Elf64_Rela;
+
+/* r_info utility macros */
+#define ELF64_R_SYM(info) ((info) >> 32)
+#define ELF64_R_TYPE(info) ((info) & 0xffffffff)
+#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type))
+
+/*
+ * Move entries
+ */
+typedef struct {
+ Elf32_Lword m_value; /* symbol value */
+ Elf32_Word m_info; /* size + index */
+ Elf32_Word m_poffset; /* symbol offset */
+ Elf32_Half m_repeat; /* repeat count */
+ Elf32_Half m_stride; /* stride info */
+} Elf32_Move;
+
+#define ELF32_M_SYM(info) ((info) >> 8)
+#define ELF32_M_SIZE(info) (info) & 0xff)
+#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size))
+
+typedef struct {
+ Elf64_Lword m_value; /* symbol value */
+ Elf64_Xword m_info; /* size + index */
+ Elf64_Xword m_poffset; /* symbol offset */
+ Elf64_Half m_repeat; /* repeat count */
+ Elf64_Half m_stride; /* stride info */
+} Elf64_Move;
+
+#define ELF64_M_SYM(info) ((info) >> 8)
+#define ELF64_M_SIZE(info) (info) & 0xff)
+#define ELF64_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size))
+
+/*
+ * Hardware/software capabilities entry
+ */
+typedef struct {
+ Elf32_Word c_tag; /* entry tag value */
+ union {
+ Elf32_Addr c_ptr;
+ Elf32_Word c_val;
+ } c_un;
+} Elf32_Cap;
+
+typedef struct {
+ Elf64_Xword c_tag; /* entry tag value */
+ union {
+ Elf64_Addr c_ptr;
+ Elf64_Xword c_val;
+ } c_un;
+} Elf64_Cap;
+
+/*
+ * Dynamic Section structure array
+ */
+typedef struct {
+ Elf32_Word d_tag; /* entry tag value */
+ union {
+ Elf32_Addr d_ptr;
+ Elf32_Word d_val;
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct {
+ Elf64_Xword d_tag; /* entry tag value */
+ union {
+ Elf64_Addr d_ptr;
+ Elf64_Xword d_val;
+ } d_un;
+} Elf64_Dyn;
+
+/* d_tag */
+#define DT_NULL 0 /* Marks end of dynamic array */
+#define DT_NEEDED 1 /* Name of needed library (DT_STRTAB offset) */
+#define DT_PLTRELSZ 2 /* Size, in bytes, of relocations in PLT */
+#define DT_PLTGOT 3 /* Address of PLT and/or GOT */
+#define DT_HASH 4 /* Address of symbol hash table */
+#define DT_STRTAB 5 /* Address of string table */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_RELA 7 /* Address of Rela relocation table */
+#define DT_RELASZ 8 /* Size, in bytes, of DT_RELA table */
+#define DT_RELAENT 9 /* Size, in bytes, of one DT_RELA entry */
+#define DT_STRSZ 10 /* Size, in bytes, of DT_STRTAB table */
+#define DT_SYMENT 11 /* Size, in bytes, of one DT_SYMTAB entry */
+#define DT_INIT 12 /* Address of initialization function */
+#define DT_FINI 13 /* Address of termination function */
+#define DT_SONAME 14 /* Shared object name (DT_STRTAB offset) */
+#define DT_RPATH 15 /* Library search path (DT_STRTAB offset) */
+#define DT_SYMBOLIC 16 /* Start symbol search within local object */
+#define DT_REL 17 /* Address of Rel relocation table */
+#define DT_RELSZ 18 /* Size, in bytes, of DT_REL table */
+#define DT_RELENT 19 /* Size, in bytes, of one DT_REL entry */
+#define DT_PLTREL 20 /* Type of PLT relocation entries */
+#define DT_DEBUG 21 /* Used for debugging; unspecified */
+#define DT_TEXTREL 22 /* Relocations might modify non-writable seg */
+#define DT_JMPREL 23 /* Address of relocations associated with PLT */
+#define DT_BIND_NOW 24 /* Process all relocations at load-time */
+#define DT_INIT_ARRAY 25 /* Address of initialization function array */
+#define DT_FINI_ARRAY 26 /* Size, in bytes, of DT_INIT_ARRAY array */
+#define DT_INIT_ARRAYSZ 27 /* Address of termination function array */
+#define DT_FINI_ARRAYSZ 28 /* Size, in bytes, of DT_FINI_ARRAY array*/
+#define DT_NUM 29
+
+#define DT_LOOS 0x60000000 /* Operating system specific range */
+#define DT_VERSYM 0x6ffffff0 /* Symbol versions */
+#define DT_FLAGS_1 0x6ffffffb /* ELF dynamic flags */
+#define DT_VERDEF 0x6ffffffc /* Versions defined by file */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of versions defined by file */
+#define DT_VERNEED 0x6ffffffe /* Versions needed by file */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of versions needed by file */
+#define DT_HIOS 0x6fffffff
+#define DT_LOPROC 0x70000000 /* Processor-specific range */
+#define DT_HIPROC 0x7fffffff
+
+/* Flag values for DT_FLAGS_1 (incomplete) */
+#define DF_1_INITFIRST 0x00000020 /* Object's init/fini take priority */
+
+/*
+ * Auxiliary Vectors
+ */
+typedef struct {
+ Elf32_Word a_type; /* 32-bit id */
+ Elf32_Word a_v; /* 32-bit id */
+} Aux32Info;
+
+typedef struct {
+ Elf64_Half a_type; /* 32-bit id */
+ Elf64_Xword a_v; /* 64-bit id */
+} Aux64Info;
+
+/* a_type */
+#define AT_NULL 0 /* Marks end of array */
+#define AT_IGNORE 1 /* No meaning, a_un is undefined */
+#define AT_EXECFD 2 /* Open file descriptor of object file */
+#define AT_PHDR 3 /* &phdr[0] */
+#define AT_PHENT 4 /* sizeof(phdr[0]) */
+#define AT_PHNUM 5 /* # phdr entries */
+#define AT_PAGESZ 6 /* PAGESIZE */
+#define AT_BASE 7 /* Interpreter base addr */
+#define AT_FLAGS 8 /* Processor flags */
+#define AT_ENTRY 9 /* Entry address of executable */
+#define AT_DCACHEBSIZE 10 /* Data cache block size */
+#define AT_ICACHEBSIZE 11 /* Instruction cache block size */
+#define AT_UCACHEBSIZE 12 /* Unified cache block size */
+
+ /* Vendor specific */
+#define AT_MIPS_NOTELF 10 /* XXX a_val != 0 -> MIPS XCOFF executable */
+
+#define AT_EUID 2000 /* euid (solaris compatible numbers) */
+#define AT_RUID 2001 /* ruid (solaris compatible numbers) */
+#define AT_EGID 2002 /* egid (solaris compatible numbers) */
+#define AT_RGID 2003 /* rgid (solaris compatible numbers) */
+
+ /* Solaris kernel specific */
+#define AT_SUN_LDELF 2004 /* dynamic linker's ELF header */
+#define AT_SUN_LDSHDR 2005 /* dynamic linker's section header */
+#define AT_SUN_LDNAME 2006 /* dynamic linker's name */
+#define AT_SUN_LPGSIZE 2007 /* large pagesize */
+
+ /* Other information */
+#define AT_SUN_PLATFORM 2008 /* sysinfo(SI_PLATFORM) */
+#define AT_SUN_HWCAP 2009 /* process hardware capabilities */
+#define AT_SUN_IFLUSH 2010 /* do we need to flush the instruction cache? */
+#define AT_SUN_CPU 2011 /* CPU name */
+ /* ibcs2 emulation band aid */
+#define AT_SUN_EMUL_ENTRY 2012 /* coff entry point */
+#define AT_SUN_EMUL_EXECFD 2013 /* coff file descriptor */
+ /* Executable's fully resolved name */
+#define AT_SUN_EXECNAME 2014
+
+/*
+ * Note Headers
+ */
+typedef struct {
+ Elf32_Word n_namesz;
+ Elf32_Word n_descsz;
+ Elf32_Word n_type;
+} Elf32_Nhdr;
+
+typedef struct {
+ Elf64_Half n_namesz;
+ Elf64_Half n_descsz;
+ Elf64_Half n_type;
+} Elf64_Nhdr;
+
+#define ELF_NOTE_TYPE_ABI_TAG 1
+
+/* GNU-specific note name and description sizes */
+#define ELF_NOTE_ABI_NAMESZ 4
+#define ELF_NOTE_ABI_DESCSZ 16
+/* GNU-specific note name */
+#define ELF_NOTE_ABI_NAME "GNU\0"
+
+/* GNU-specific OS/version value stuff */
+#define ELF_NOTE_ABI_OS_LINUX 0
+#define ELF_NOTE_ABI_OS_HURD 1
+#define ELF_NOTE_ABI_OS_SOLARIS 2
+
+/* NetBSD-specific note type: Emulation name. desc is emul name string. */
+#define ELF_NOTE_TYPE_NETBSD_TAG 1
+/* NetBSD-specific note name and description sizes */
+#define ELF_NOTE_NETBSD_NAMESZ 7
+#define ELF_NOTE_NETBSD_DESCSZ 4
+/* NetBSD-specific note name */
+#define ELF_NOTE_NETBSD_NAME "NetBSD\0\0"
+
+/* NetBSD-specific note type: Checksum. There should be 1 NOTE per PT_LOAD
+ section. desc is a tuple of <phnum>(16),<chk-type>(16),<chk-value>. */
+#define ELF_NOTE_TYPE_CHECKSUM_TAG 2
+#define ELF_NOTE_CHECKSUM_CRC32 1
+#define ELF_NOTE_CHECKSUM_MD5 2
+#define ELF_NOTE_CHECKSUM_SHA1 3
+#define ELF_NOTE_CHECKSUM_SHA256 4
+
+/* NetBSD-specific note type: PaX. There should be 1 NOTE per executable.
+ section. desc is a 32 bit bitmask */
+#define ELF_NOTE_TYPE_PAX_TAG 3
+#define ELF_NOTE_PAX_MPROTECT 0x01 /* Force enable Mprotect */
+#define ELF_NOTE_PAX_NOMPROTECT 0x02 /* Force disable Mprotect */
+#define ELF_NOTE_PAX_GUARD 0x04 /* Force enable Segvguard */
+#define ELF_NOTE_PAX_NOGUARD 0x08 /* Force disable Servguard */
+#define ELF_NOTE_PAX_ASLR 0x10 /* Force enable ASLR */
+#define ELF_NOTE_PAX_NOASLR 0x20 /* Force disable ASLR */
+#define ELF_NOTE_PAX_NAMESZ 4
+#define ELF_NOTE_PAX_NAME "PaX\0"
+#define ELF_NOTE_PAX_DESCSZ 4
+
+/*
+ * NetBSD-specific core file information.
+ *
+ * NetBSD ELF core files use notes to provide information about
+ * the process's state. The note name is "NetBSD-CORE" for
+ * information that is global to the process, and "NetBSD-CORE at nn",
+ * where "nn" is the lwpid of the LWP that the information belongs
+ * to (such as register state).
+ *
+ * We use the following note identifiers:
+ *
+ * ELF_NOTE_NETBSD_CORE_PROCINFO
+ * Note is a "netbsd_elfcore_procinfo" structure.
+ *
+ * We also use ptrace(2) request numbers (the ones that exist in
+ * machine-dependent space) to identify register info notes. The
+ * info in such notes is in the same format that ptrace(2) would
+ * export that information.
+ *
+ * Please try to keep the members of this structure nicely aligned,
+ * and if you add elements, add them to the end and bump the version.
+ */
+
+#define ELF_NOTE_NETBSD_CORE_NAME "NetBSD-CORE"
+
+#define ELF_NOTE_NETBSD_CORE_PROCINFO 1
+
+#define NETBSD_ELFCORE_PROCINFO_VERSION 1
+
+struct netbsd_elfcore_procinfo {
+ /* Version 1 fields start here. */
+ uint32_t cpi_version; /* netbsd_elfcore_procinfo version */
+ uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */
+ uint32_t cpi_signo; /* killing signal */
+ uint32_t cpi_sigcode; /* signal code */
+ uint32_t cpi_sigpend[4]; /* pending signals */
+ uint32_t cpi_sigmask[4]; /* blocked signals */
+ uint32_t cpi_sigignore[4];/* blocked signals */
+ uint32_t cpi_sigcatch[4];/* blocked signals */
+ int32_t cpi_pid; /* process ID */
+ int32_t cpi_ppid; /* parent process ID */
+ int32_t cpi_pgrp; /* process group ID */
+ int32_t cpi_sid; /* session ID */
+ uint32_t cpi_ruid; /* real user ID */
+ uint32_t cpi_euid; /* effective user ID */
+ uint32_t cpi_svuid; /* saved user ID */
+ uint32_t cpi_rgid; /* real group ID */
+ uint32_t cpi_egid; /* effective group ID */
+ uint32_t cpi_svgid; /* saved group ID */
+ uint32_t cpi_nlwps; /* number of LWPs */
+ int8_t cpi_name[32]; /* copy of p->p_comm */
+ /* Add version 2 fields below here. */
+ int32_t cpi_siglwp; /* LWP target of killing signal */
+};
+
+#if defined(ELFSIZE) && (ELFSIZE == 32)
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Rel Elf32_Rel
+#define Elf_Rela Elf32_Rela
+#define Elf_Dyn Elf32_Dyn
+#define Elf_Word Elf32_Word
+#define Elf_Sword Elf32_Sword
+#define Elf_Addr Elf32_Addr
+#define Elf_Off Elf32_Off
+#define Elf_SOff Elf32_SOff
+#define Elf_Nhdr Elf32_Nhdr
+
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
+#define ELFCLASS ELFCLASS32
+
+#define AuxInfo Aux32Info
+#elif defined(ELFSIZE) && (ELFSIZE == 64)
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Rel Elf64_Rel
+#define Elf_Rela Elf64_Rela
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Word Elf64_Word
+#define Elf_Sword Elf64_Sword
+#define Elf_Addr Elf64_Addr
+#define Elf_Off Elf64_Off
+#define Elf_SOff Elf64_SOff
+#define Elf_Nhdr Elf64_Nhdr
+
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
+#define ELFCLASS ELFCLASS64
+
+#define AuxInfo Aux64Info
+#endif
+
+#define ELF32_ST_BIND(info) ELF_ST_BIND(info)
+#define ELF32_ST_TYPE(info) ELF_ST_TYPE(info)
+#define ELF32_ST_INFO(bind,type) ELF_ST_INFO(bind,type)
+#define ELF32_ST_VISIBILITY(other) ELF_ST_VISIBILITY(other)
+
+#define ELF64_ST_BIND(info) ELF_ST_BIND(info)
+#define ELF64_ST_TYPE(info) ELF_ST_TYPE(info)
+#define ELF64_ST_INFO(bind,type) ELF_ST_INFO(bind,type)
+#define ELF64_ST_VISIBILITY(other) ELF_ST_VISIBILITY(other)
+
+typedef struct {
+ Elf32_Half si_boundto; /* direct bindings - symbol bound to */
+ Elf32_Half si_flags; /* per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct {
+ Elf64_Half si_boundto; /* direct bindings - symbol bound to */
+ Elf64_Half si_flags; /* per symbol flags */
+} Elf64_Syminfo;
+
+#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association
+ to object containing definition */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */
+#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be
+ lazily-loaded */
+#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to
+ object containing definition */
+#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference
+ directly bind to this symbol */
+#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */
+#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */
+
+#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */
+#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */
+#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */
+
+#define SYMINFO_NONE 0 /* Syminfo version */
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+/*
+ * These constants are used for Elf32_Verdef struct's version number.
+ */
+#define VER_DEF_NONE 0
+#define VER_DEF_CURRENT 1
+
+/*
+ * These constants are used for Elf32_Verdef struct's vd_flags.
+ */
+#define VER_FLG_BASE 0x1
+#define VER_FLG_WEAK 0x2
+
+/*
+ * These are used in an Elf32_Versym field.
+ */
+#define VER_NDX_LOCAL 0
+#define VER_NDX_GLOBAL 1
+
+/*
+ * These constants are used for Elf32_Verneed struct's version number.
+ */
+#define VER_NEED_NONE 0
+#define VER_NEED_CURRENT 1
+
+/*
+ * GNU Extension hidding symb
+ */
+#define VERSYM_HIDDEN 0x8000
+#define VERSYM_VERSION 0x7fff
+
+#define ELF_VER_CHR '@'
+
+/*
+ * These are current size independent.
+ */
+
+typedef struct {
+ Elf32_Half vd_version; /* version number of structure */
+ Elf32_Half vd_flags; /* flags (VER_FLG_*) */
+ Elf32_Half vd_ndx; /* version index */
+ Elf32_Half vd_cnt; /* number of verdaux entries */
+ Elf32_Word vd_hash; /* hash of name */
+ Elf32_Word vd_aux; /* offset to verdaux entries */
+ Elf32_Word vd_next; /* offset to next verdef */
+} Elf32_Verdef;
+typedef Elf32_Verdef Elf64_Verdef;
+
+typedef struct {
+ Elf32_Word vda_name; /* string table offset of name */
+ Elf32_Word vda_next; /* offset to verdaux */
+} Elf32_Verdaux;
+typedef Elf32_Verdaux Elf64_Verdaux;
+
+typedef struct {
+ Elf32_Half vn_version; /* version number of structure */
+ Elf32_Half vn_cnt; /* number of vernaux entries */
+ Elf32_Word vn_file; /* string table offset of library name*/
+ Elf32_Word vn_aux; /* offset to vernaux entries */
+ Elf32_Word vn_next; /* offset to next verneed */
+} Elf32_Verneed;
+typedef Elf32_Verneed Elf64_Verneed;
+
+typedef struct {
+ Elf32_Word vna_hash; /* Hash of dependency name */
+ Elf32_Half vna_flags; /* flags (VER_FLG_*) */
+ Elf32_Half vna_other; /* unused */
+ Elf32_Word vna_name; /* string table offset to version name*/
+ Elf32_Word vna_next; /* offset to next vernaux */
+} Elf32_Vernaux;
+typedef Elf32_Vernaux Elf64_Vernaux;
+
+typedef struct {
+ Elf32_Half vs_vers;
+} Elf32_Versym;
+typedef Elf32_Versym Elf64_Versym;
+
+#ifdef _KERNEL
+
+#define ELF_AUX_ENTRIES 14 /* Max size of aux array passed to loader */
+#define ELF32_NO_ADDR (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */
+#define ELF32_LINK_ADDR ((Elf32_Addr)-2) /* advises to use link address */
+#define ELF64_NO_ADDR (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */
+#define ELF64_LINK_ADDR ((Elf64_Addr)-2) /* advises to use link address */
+
+#if defined(ELFSIZE) && (ELFSIZE == 64)
+#define ELF_NO_ADDR ELF64_NO_ADDR
+#define ELF_LINK_ADDR ELF64_LINK_ADDR
+#elif defined(ELFSIZE) && (ELFSIZE == 32)
+#define ELF_NO_ADDR ELF32_NO_ADDR
+#define ELF_LINK_ADDR ELF32_LINK_ADDR
+#endif
+
+#ifndef ELF32_EHDR_FLAGS_OK
+#define ELF32_EHDR_FLAGS_OK(eh) 1
+#endif
+
+#ifndef ELF64_EHDR_FLAGS_OK
+#define ELF64_EHDR_FLAGS_OK(eh) 1
+#endif
+
+#if defined(ELFSIZE) && (ELFSIZE == 64)
+#define ELF_EHDR_FLAGS_OK(eh) ELF64_EHDR_FLAGS_OK(eh)
+#else
+#define ELF_EHDR_FLAGS_OK(eh) ELF32_EHDR_FLAGS_OK(eh)
+#endif
+
+#if defined(ELFSIZE)
+struct elf_args {
+ Elf_Addr arg_entry; /* program entry point */
+ Elf_Addr arg_interp; /* Interpreter load address */
+ Elf_Addr arg_phaddr; /* program header address */
+ Elf_Addr arg_phentsize; /* Size of program header */
+ Elf_Addr arg_phnum; /* Number of program headers */
+};
+#endif
+
+#ifdef _KERNEL_OPT
+#include "opt_execfmt.h"
+#endif
+
+#ifdef EXEC_ELF32
+int exec_elf32_makecmds(struct lwp *, struct exec_package *);
+int elf32_copyargs(struct lwp *, struct exec_package *,
+ struct ps_strings *, char **, void *);
+
+int coredump_elf32(struct lwp *, void *);
+int coredump_writenote_elf32(struct proc *, void *, Elf32_Nhdr *,
+ const char *, void *);
+
+int elf32_check_header(Elf32_Ehdr *, int);
+#endif
+
+#ifdef EXEC_ELF64
+int exec_elf64_makecmds(struct lwp *, struct exec_package *);
+int elf64_copyargs(struct lwp *, struct exec_package *,
+ struct ps_strings *, char **, void *);
+
+int coredump_elf64(struct lwp *, void *);
+int coredump_writenote_elf64(struct proc *, void *, Elf64_Nhdr *,
+ const char *, void *);
+
+int elf64_check_header(Elf64_Ehdr *, int);
+#endif
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_EXEC_ELF_H_ */
diff --git a/cpukit/libdl/preinstall.am b/cpukit/libdl/preinstall.am
new file mode 100644
index 0000000..dba6cc4
--- /dev/null
+++ b/cpukit/libdl/preinstall.am
@@ -0,0 +1,7 @@
+## Automatically generated by ampolish3 - Do not edit
+
+if AMPOLISH3
+$(srcdir)/preinstall.am: Makefile.am
+ $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
+endif
+
diff --git a/cpukit/libdl/rap-shell.c b/cpukit/libdl/rap-shell.c
new file mode 100644
index 0000000..664f3a3
--- /dev/null
+++ b/cpukit/libdl/rap-shell.c
@@ -0,0 +1,106 @@
+/*
+ * COPYRIGHT (c) 2013 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Application Loader.
+ *
+ * Shell command wrappers for the RTEMS Application loader.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems/rtl/rap.h>
+#include <rtems/rtl/rap-shell.h>
+
+static void
+shell_rap_command_help (void)
+{
+ printf ("usage: rap [cmd] [arg]\n" \
+ "Commands and options:\n" \
+ "ls: List the loaded applications (also list)\n" \
+ "ld: Load an application (also load)\n" \
+ "un: Unload an application (also unload)\n");
+}
+
+static void
+shell_rap_get_error (const char* what)
+{
+ char message[64];
+ int error;
+ error = rtems_rap_get_error (message, sizeof (message));
+ printf ("error: %s: (%d) %s\n", what, error, message);
+}
+
+static bool
+shell_rap_list_handler (void* handle)
+{
+ printf (" %-10p %-10p %-s\n",
+ handle, rtems_rap_dl_handle (handle), rtems_rap_name (handle));
+ return true;
+}
+
+static int
+shell_rap_list (int argc, char* argv[])
+{
+ printf (" App DL Handle Name\n");
+ return rtems_rap_iterate (shell_rap_list_handler) ? 0 : 1;
+}
+
+static int
+shell_rap_load (int argc, char* argv[])
+{
+ int r = 0;
+ if (argc == 0)
+ {
+ printf ("error: no application name\n");
+ return 0;
+ }
+ if (rtems_rap_load (argv[0], 0, argc - 1, (const char**) (argv + 1)))
+ printf ("%s loaded\n", argv[0]);
+ else
+ {
+ r = 1;
+ shell_rap_get_error ("loading");
+ }
+ return r;
+}
+
+int
+shell_rap (int argc, char* argv[])
+{
+ if (argc == 1)
+ {
+ shell_rap_command_help ();
+ return 0;
+ }
+
+ if ((strcmp (argv[1], "ls") == 0) ||
+ (strcmp (argv[1], "list") == 0))
+ {
+ return shell_rap_list (argc - 2, argv + 2);
+ }
+ else if ((strcmp (argv[1], "ld") == 0) ||
+ (strcmp (argv[1], "load") == 0))
+ {
+ return shell_rap_load (argc - 2, argv + 2);
+ }
+
+ printf ("error: invalid command: %s\n", argv[1]);
+ return 0;
+}
+
diff --git a/cpukit/libdl/rap-shell.h b/cpukit/libdl/rap-shell.h
new file mode 100644
index 0000000..c32529d
--- /dev/null
+++ b/cpukit/libdl/rap-shell.h
@@ -0,0 +1,14 @@
+/*
+ * COPYRIGHT (c) 2013 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if !defined(_RAP_SHELL_H_)
+#define _RAP_SHELL_H_
+
+int shell_rap (int argc, char* argv[]);
+
+#endif
diff --git a/cpukit/libdl/rap.c b/cpukit/libdl/rap.c
new file mode 100644
index 0000000..8dec41e
--- /dev/null
+++ b/cpukit/libdl/rap.c
@@ -0,0 +1,484 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rap
+ *
+ * @brief RTEMS Application Loader
+ *
+ * This is the RAP implementation.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+
+#include <dlfcn.h>
+#include <rtems/rtl/rap.h>
+#include <rtems/rtl/rtl.h>
+
+#include "rtl-find-file.h"
+
+/**
+ * The global RAP data. This structure is allocated on the heap when the first
+ * call to location an application and is never released.
+ */
+typedef struct rtems_rap_data_s
+{
+ rtems_id lock; /**< The RAP lock id */
+ rtems_chain_control apps; /**< List if loaded application. */
+ int last_errno; /**< Last error number. */
+ char last_error[64]; /**< Last error string. */
+} rtems_rap_data_t;
+
+/**
+ * The RAP file data. This structure is allocated on the heap when a file is
+ * loaded.
+ */
+typedef struct rtems_rap_app_s
+{
+ rtems_chain_node node; /**< The node's link in the chain. */
+ const char* name; /**< The file name */
+ void* handle; /**< The dlopen handle. */
+} rtems_rap_app_t;
+
+/**
+ * Semaphore configuration to create a mutex.
+ */
+#define RTEMS_MUTEX_ATTRIBS \
+ (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
+ RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
+
+/**
+ * RTL entry.
+ */
+#if (RTL_GLUE(__USER_LABEL_PREFIX__, 1) == RTL_GLUE(_, 1))
+ #define RTL_ENTRY_POINT "_rtems"
+#else
+ #define RTL_ENTRY_POINT "rtems"
+#endif
+
+/**
+ * Static RAP data is returned to the user when the loader is locked.
+ */
+static rtems_rap_data_t rap_;
+
+/**
+ * Verbose level for the RAP loader.
+ */
+static bool rap_verbose;
+
+/**
+ * RAP entry call signature.
+ */
+typedef int (*rtems_rap_entry_t)(int argc, const char* argv[]);
+
+/**
+ * Forward decl.
+ */
+static bool rtems_rap_unlock (void);
+
+static bool
+rtems_rap_data_init (void)
+{
+ /*
+ * Lock the RAP. We only create a lock if a call is made. First we test if a
+ * lock is present. If one is present we lock it. If not the libio lock is
+ * locked and we then test the lock again. If not present we create the lock
+ * then release libio lock.
+ */
+ if (!rap_.lock)
+ {
+ rtems_libio_lock ();
+
+ if (!rap_.lock)
+ {
+ rtems_status_code sc;
+ rtems_id lock;
+
+ /*
+ * Create the RAP lock.
+ */
+ sc = rtems_semaphore_create (rtems_build_name ('R', 'A', 'P', '_'),
+ 1, RTEMS_MUTEX_ATTRIBS,
+ RTEMS_NO_PRIORITY, &lock);
+ if (sc != RTEMS_SUCCESSFUL)
+ return false;
+
+ sc = rtems_semaphore_obtain (lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete (lock);
+ return false;
+ }
+
+ rap_.lock = lock;
+
+ /*
+ * Initialise the objects list and create any required services.
+ */
+ rtems_chain_initialize_empty (&rap_.apps);
+ }
+
+ rtems_libio_unlock ();
+
+ rtems_rap_unlock ();
+ }
+ return true;
+}
+
+static rtems_rap_data_t*
+rtems_rap_lock (void)
+{
+ rtems_status_code sc;
+
+ if (!rtems_rap_data_init ())
+ return NULL;
+
+ sc = rtems_semaphore_obtain (rap_.lock,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return &rap_;
+}
+
+static bool
+rtems_rap_unlock (void)
+{
+ /*
+ * Not sure any error should be returned or an assert.
+ */
+ rtems_status_code sc;
+ sc = rtems_semaphore_release (rap_.lock);
+ if ((sc != RTEMS_SUCCESSFUL) && (errno == 0))
+ {
+ errno = EINVAL;
+ return false;
+ }
+ return true;
+}
+
+static rtems_rap_app_t*
+rtems_rap_check_handle (void* handle)
+{
+ rtems_rap_app_t* app;
+ rtems_chain_node* node;
+
+ app = handle;
+ node = rtems_chain_first (&rap_.apps);
+
+ while (!rtems_chain_is_tail (&rap_.apps, node))
+ {
+ rtems_rap_app_t* check = (rtems_rap_app_t*) node;
+ if (check == app)
+ return app;
+ node = rtems_chain_next (node);
+ }
+
+ return NULL;
+}
+
+static rtems_rap_app_t*
+rtems_rap_app_alloc (void)
+{
+ rtems_rap_app_t* app = malloc (sizeof (rtems_rap_app_t));
+ memset (app, 0, sizeof (rtems_rap_app_t));
+ rtems_chain_append (&rap_.apps, &app->node);
+ return app;
+}
+
+static void
+rtems_rap_app_free (rtems_rap_app_t* app)
+{
+ if (app->handle)
+ {
+ dlclose (app->handle);
+ app->handle = NULL;
+ }
+
+ if (!rtems_chain_is_node_off_chain (&app->node))
+ rtems_chain_extract (&app->node);
+}
+
+static bool
+rtems_rap_match_name (rtems_rap_app_t* app, const char* name)
+{
+ const char* a;
+
+ /*
+ * Assume the app name is absolute, ie points to the file on disk. This means
+ * there is at least one delimiter in the name.
+ */
+
+ if (strncmp (app->name, name, strlen (name)) == 0)
+ return true;
+
+ a = app->name + strlen (app->name) - 1;
+
+ while (a >= app->name)
+ {
+ if (rtems_filesystem_is_delimiter (*a))
+ {
+ const char* n = name;
+
+ ++a;
+
+ while (*a && *n)
+ {
+ if (*a == '.')
+ {
+ if (*n == '\0')
+ return true;
+ }
+
+ ++a;
+ ++n;
+ }
+
+ return false;
+ }
+
+ --a;
+ }
+
+ return false;
+}
+
+static void
+rtems_rap_get_rtl_error (void)
+{
+ rap_.last_errno =
+ rtems_rtl_get_error (rap_.last_error, sizeof (rap_.last_error));
+}
+
+static void
+rtems_rap_set_error (int error, const char* format, ...)
+{
+ rtems_rap_data_t* rap = rtems_rap_lock ();
+ va_list ap;
+ va_start (ap, format);
+ rap->last_errno = error;
+ vsnprintf (rap->last_error, sizeof (rap->last_error), format, ap);
+ rtems_rap_unlock ();
+ va_end (ap);
+}
+
+bool
+rtems_rap_load (const char* name, int mode, int argc, const char* argv[])
+{
+ rtems_rap_data_t* rap = rtems_rap_lock ();
+
+ if (!rap)
+ return false;
+
+ if (rap_verbose)
+ printf ("rap: loading '%s'\n", name);
+
+ /*
+ * See if the app has already been loaded.
+ */
+ if (!rtems_rap_find (name))
+ {
+ rtems_rap_app_t* app;
+ rtems_rap_entry_t init;
+ rtems_rap_entry_t fini;
+ size_t size = 0;
+ int r;
+
+ /*
+ * Allocate a new application descriptor and attempt to load it.
+ */
+ app = rtems_rap_app_alloc ();
+ if (app == NULL)
+ {
+ rtems_rap_set_error (ENOMEM, "no memory for application");
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ /*
+ * Find the file in the file system using the search path.
+ */
+ if (!rtems_rtl_find_file (name, getenv ("PATH"), &app->name, &size))
+ {
+ rtems_rap_set_error (ENOENT, "file not found");
+ rtems_rap_app_free (app);
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ app->handle = dlopen (app->name, RTLD_NOW | mode);
+ if (!app->handle)
+ {
+ rtems_rap_get_rtl_error ();
+ rtems_rap_app_free (app);
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ init = dlsym (app->handle, RTL_ENTRY_POINT);
+ if (!init)
+ {
+ rtems_rap_get_rtl_error ();
+ rtems_rap_app_free (app);
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ fini = dlsym (app->handle, RTL_ENTRY_POINT);
+ if (!fini)
+ {
+ rtems_rap_get_rtl_error ();
+ rtems_rap_app_free (app);
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ r = init (argc, argv);
+ if (r != 0)
+ {
+ rtems_rap_set_error (r, "init call failure");
+ rtems_rap_app_free (app);
+ rtems_rap_unlock ();
+ return false;
+ }
+ }
+
+ rtems_rap_unlock ();
+
+ return true;
+}
+
+bool
+rtems_rap_unload (const char* name)
+{
+ rtems_rap_app_t* app;
+ rtems_rap_entry_t fini;
+ int r;
+
+ rtems_rap_lock ();
+
+ app = rtems_rap_find (name);
+
+ if (rap_verbose)
+ printf ("rap: unloading '%s'\n", name);
+
+ if (!app)
+ {
+ rtems_rap_set_error (ENOENT, "invalid handle");
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ fini = dlsym (app->handle, RTL_ENTRY_POINT);
+ if (!fini)
+ {
+ rtems_rap_get_rtl_error ();
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ r = fini (0, NULL);
+ if (r != 0)
+ {
+ rtems_rap_set_error (r, "fini failure");
+ rtems_rap_unlock ();
+ return false;
+ }
+
+ rtems_rap_app_free (app);
+ rtems_rap_unlock ();
+
+ return true;
+}
+
+void*
+rtems_rap_find (const char* name)
+{
+ rtems_rap_data_t* rap = rtems_rap_lock ();
+ rtems_chain_node* node;
+
+ node = rtems_chain_first (&rap->apps);
+
+ while (!rtems_chain_is_tail (&rap->apps, node))
+ {
+ rtems_rap_app_t* app = (rtems_rap_app_t*) node;
+ if (rtems_rap_match_name (app, name))
+ {
+ rtems_rap_unlock ();
+ return app;
+ }
+ node = rtems_chain_next (node);
+ }
+
+ rtems_rap_unlock ();
+
+ return NULL;
+}
+
+bool
+rtems_rap_iterate (rtems_rap_iterator_t iterator)
+{
+ rtems_rap_data_t* rap = rtems_rap_lock ();
+ rtems_chain_node* node;
+ bool result = true;
+
+ node = rtems_chain_first (&rap->apps);
+
+ while (!rtems_chain_is_tail (&rap->apps, node))
+ {
+ rtems_rap_app_t* app = (rtems_rap_app_t*) node;
+ result = iterator (app);
+ if (!result)
+ break;
+ node = rtems_chain_next (node);
+ }
+
+ rtems_rap_unlock ();
+
+ return result;
+}
+
+const char*
+rtems_rap_name (void* handle)
+{
+ rtems_rap_app_t* app = rtems_rap_check_handle (handle);
+ if (app)
+ return app->name;
+ return NULL;
+}
+
+void*
+rtems_rap_dl_handle (void* handle)
+{
+ rtems_rap_app_t* app = rtems_rap_check_handle (handle);
+ if (app)
+ return app->handle;
+ return NULL;
+}
+
+int
+rtems_rap_get_error (char* message, size_t max_message)
+{
+ rtems_rap_data_t* rap = rtems_rap_lock ();
+ int last_errno = rap->last_errno;
+ strncpy (message, rap->last_error, sizeof (rap->last_error));
+ rtems_rap_unlock ();
+ return last_errno;
+}
diff --git a/cpukit/libdl/rap.h b/cpukit/libdl/rap.h
new file mode 100644
index 0000000..e53699f
--- /dev/null
+++ b/cpukit/libdl/rap.h
@@ -0,0 +1,115 @@
+/*
+ * COPYRIGHT (c) 2013 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rap
+ *
+ * @brief RTEMS Application Loader
+ *
+ * This is the RTEMS Application loader for files in the RAP format.
+ */
+
+#if !defined (_RAP_H_)
+#define _RAP_H_
+
+#include <rtems.h>
+#include <rtems/chain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup rtems_rap RTEMS Application Loader
+ *
+ * The module implements an application loader for files in the RAP format. The
+ * RAP format is:
+ *
+ * <header>
+ * <compressed container>
+ *
+ * The compressed container is a stream of ELF relocatable object files.
+ *
+ * TBD.
+ */
+
+/**
+ * The module iterator handle.
+ */
+typedef bool (*rtems_rap_iterator_t) (void* handle);
+
+/**
+ * Load an application.
+ *
+ * @param name The name of the application file.
+ * @return bool True if the module loads else an error.
+ */
+bool rtems_rap_load (const char* name, int mode, int argc, const char* argv[]);
+
+/**
+ * Unload an application.
+ *
+ * @param obj The application descriptor.
+ * @retval true The application file has been unloaded.
+ * @retval false The application could not be unloaded.
+ */
+bool rtems_rap_unload (const char* name);
+
+/**
+ * Find the application handle given a file name.
+ *
+ * @param name The name of the application file. It can be absolute or
+ * relative. Relative names can the basename with an extension.
+ * @retval NULL No application file with that name found.
+ * @return void* The application descriptor.
+ */
+void* rtems_rap_find (const char* name);
+
+/**
+ * Run an iterator over the modules calling the iterator function.
+ *
+ * @param iterator The iterator function.
+ * @retval true The iterator function returned did not return false.
+ * @retval false The iterator function returned false..
+ */
+bool rtems_rap_iterate (rtems_rap_iterator_t iterator);
+
+/**
+ * Return the name of the module given a handle.
+ *
+ * @param handle The module handle.
+ * @return const char* The name of the module if the handle is valid else it
+ * is NULL.
+ */
+const char* rtems_rap_name (void* handle);
+
+/**
+ * Return the DL handle used to load the module given the RAP handle.
+ *
+ * @param handle The module handle.
+ * @return void* The DL handle returned by the dlopen call.
+ */
+void* rtems_rap_dl_handle (void* handle);
+
+/**
+ * Get the last error message clearing it. This call is not thread safe is
+ * multiple threads are loading object files at the same time. This call
+ * follows the model provided by the dlopen family of calls.
+ *
+ * @param message Pointer to a buffer to copy the message into.
+ * @param max_message The maximum message that can be copied.
+ * @return int The last error number.
+ */
+int rtems_rap_get_error (char* message, size_t max_message);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-alloc-heap.c b/cpukit/libdl/rtl-alloc-heap.c
new file mode 100644
index 0000000..44a4816
--- /dev/null
+++ b/cpukit/libdl/rtl-alloc-heap.c
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Allocator for the standard heap.
+ */
+
+#include <stdlib.h>
+
+#include "rtl-alloc-heap.h"
+
+void
+rtems_rtl_alloc_heap (bool allocate,
+ rtems_rtl_alloc_tag_t tag,
+ void** address,
+ size_t size)
+{
+ if (allocate)
+ *address = malloc (size);
+ else
+ {
+ free (*address);
+ *address = NULL;
+ }
+}
diff --git a/cpukit/libdl/rtl-alloc-heap.h b/cpukit/libdl/rtl-alloc-heap.h
new file mode 100644
index 0000000..d927655
--- /dev/null
+++ b/cpukit/libdl/rtl-alloc-heap.h
@@ -0,0 +1,47 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Allocator for the standard heap.
+ */
+
+#if !defined (_RTEMS_RTL_ALLOC_HEAP_H_)
+#define _RTEMS_RTL_ALLOC_HEAP_H_
+
+#include <rtems/rtl/rtl-allocator.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Allocator handler for the standard libc heap.
+ *
+ * @param allocation If true the request is to allocate memory else free.
+ * @param tag The type of allocation request.
+ * @param address Pointer to the memory address. If an allocation the value is
+ * unspecific on entry and the allocated address or NULL on
+ * exit. The NULL value means the allocation failed. If a delete
+ * or free request the memory address is the block to free. A
+ * free request of NULL is silently ignored.
+ * @param size The size of the allocation if an allocation request and
+ * not used if deleting or freeing a previous allocation.
+ */
+void rtems_rtl_alloc_heap(bool allocate,
+ rtems_rtl_alloc_tag_t tag,
+ void** address,
+ size_t size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c
new file mode 100644
index 0000000..b845013
--- /dev/null
+++ b/cpukit/libdl/rtl-allocator.c
@@ -0,0 +1,210 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Allocator
+ */
+
+#include <stdio.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-alloc-heap.h"
+#include "rtl-trace.h"
+
+/**
+ * Tags as symbols for tracing.
+ */
+#if RTEMS_RTL_TRACE
+static const char* tag_labels[6] =
+{
+ "OBJECT",
+ "SYMBOL",
+ "EXTERNAL",
+ "READ",
+ "READ_WRITE",
+ "READ_EXEC",
+};
+#define rtems_rtl_trace_tag_label(_l) tag_labels[_l]
+#else
+#define rtems_rtl_trace_tag_label(_l) ""
+#endif
+
+void
+rtems_rtl_alloc_initialise (rtems_rtl_alloc_data_t* data)
+{
+ int c;
+ data->allocator = rtems_rtl_alloc_heap;
+ for (c = 0; c < RTEMS_RTL_ALLOC_TAGS; ++c)
+ rtems_chain_initialize_empty (&data->indirects[c]);
+}
+
+void*
+rtems_rtl_alloc_new (rtems_rtl_alloc_tag_t tag, size_t size, bool zero)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+ void* address = NULL;
+
+ if (rtl)
+ rtl->allocator.allocator (true, tag, &address, size);
+
+ rtems_rtl_unlock ();
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
+ printf ("rtl: alloc: new: %s addr=%p size=%zu\n",
+ rtems_rtl_trace_tag_label (tag), address, size);
+
+ if (zero)
+ memset (address, 0, size);
+
+ return address;
+}
+
+void
+rtems_rtl_alloc_del (rtems_rtl_alloc_tag_t tag, void* address)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
+ printf ("rtl: alloc: del: %s addr=%p\n",
+ rtems_rtl_trace_tag_label (tag), address);
+
+ if (rtl && address)
+ rtl->allocator.allocator (false, tag, &address, 0);
+
+ rtems_rtl_unlock ();
+}
+
+rtems_rtl_allocator_t
+rtems_rtl_alloc_hook (rtems_rtl_allocator_t handler)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+ rtems_rtl_allocator_t previous = rtl->allocator.allocator;
+ rtl->allocator.allocator = handler;
+ rtems_rtl_unlock ();
+ return previous;
+}
+
+void
+rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag,
+ rtems_rtl_ptr_t* handle,
+ size_t size)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
+ {
+ if (!rtems_rtl_ptr_null (handle))
+ printf ("rtl: alloc: inew: %s handle=%p: not null\n",
+ rtems_rtl_trace_tag_label (tag), handle);
+ printf ("rtl: alloc: inew: %s handle=%p size=%zd\n",
+ rtems_rtl_trace_tag_label (tag), handle, size);
+ }
+
+ if (rtl)
+ {
+ rtems_rtl_alloc_data_t* allocator = &rtl->allocator;
+ handle->pointer = rtems_rtl_alloc_new (tag, size, false);
+ if (!rtems_rtl_ptr_null (handle))
+ rtems_chain_append_unprotected (&allocator->indirects[tag],
+ &handle->node);
+ }
+
+ rtems_rtl_unlock ();
+}
+
+void
+rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag,
+ rtems_rtl_ptr_t* handle)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
+ {
+ if (rtems_rtl_ptr_null (handle))
+ printf ("rtl: alloc: idel: %s handle=%p: is null\n",
+ rtems_rtl_trace_tag_label (tag), handle);
+ printf ("rtl: alloc: idel: %s handle=%p\n",
+ rtems_rtl_trace_tag_label (tag), handle);
+ }
+
+ if (rtl && !rtems_rtl_ptr_null (handle))
+ {
+ rtems_chain_extract_unprotected (&handle->node);
+ rtems_rtl_alloc_del (tag, &handle->pointer);
+ }
+}
+
+bool
+rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
+ void** const_base, size_t const_size,
+ void** data_base, size_t data_size,
+ void** bss_base, size_t bss_size)
+{
+ *text_base = *const_base = *data_base = *bss_base = NULL;
+
+ if (text_size)
+ {
+ *text_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_EXEC,
+ text_size, false);
+ if (!*text_base)
+ {
+ return false;
+ }
+ }
+
+ if (const_size)
+ {
+ *const_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ,
+ const_size, false);
+ if (!*const_base)
+ {
+ rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base);
+ return false;
+ }
+ }
+
+ if (data_size)
+ {
+ *data_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE,
+ data_size, false);
+ if (!*data_base)
+ {
+ rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base);
+ return false;
+ }
+ }
+
+ if (bss_size)
+ {
+ *bss_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE,
+ bss_size, false);
+ if (!*bss_base)
+ {
+ rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+rtems_rtl_alloc_module_del (void** text_base,
+ void** const_base,
+ void** data_base,
+ void** bss_base)
+{
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *bss_base);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *data_base);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *const_base);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_EXEC, *text_base);
+ *text_base = *const_base = *data_base = *bss_base = NULL;
+}
diff --git a/cpukit/libdl/rtl-allocator.h b/cpukit/libdl/rtl-allocator.h
new file mode 100644
index 0000000..8e90b7b
--- /dev/null
+++ b/cpukit/libdl/rtl-allocator.h
@@ -0,0 +1,176 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Allocator
+ */
+
+#if !defined (_RTEMS_RTL_ALLOCATOR_H_)
+#define _RTEMS_RTL_ALLOCATOR_H_
+
+#include <stdbool.h>
+
+#include "rtl-indirect-ptr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Define the types of allocation the loader requires.
+ *
+ * @note It is best to use the object tag for general memory allocation and to
+ * leave the tags with specific access properties to the module data
+ */
+enum rtems_rtl_alloc_tags_e {
+ RTEMS_RTL_ALLOC_OBJECT, /**< A generic memory object. */
+ RTEMS_RTL_ALLOC_SYMBOL, /**< Memory used for symbols. */
+ RTEMS_RTL_ALLOC_EXTERNAL, /**< Memory used for external symbols. */
+ RTEMS_RTL_ALLOC_READ, /**< The memory is read only. */
+ RTEMS_RTL_ALLOC_READ_WRITE, /**< The memory is read and write. */
+ RTEMS_RTL_ALLOC_READ_EXEC /**< The memory is read and executable. */
+};
+
+/**
+ * The allocator tag type.
+ */
+typedef enum rtems_rtl_alloc_tags_e rtems_rtl_alloc_tag_t;
+
+/**
+ * The number of tags.
+ */
+#define RTEMS_RTL_ALLOC_TAGS ((size_t) (RTEMS_RTL_ALLOC_READ_EXEC + 1))
+
+/**
+ * Allocator handler handles all RTL allocations. It can be hooked and
+ * overridded for customised allocation schemes or memory maps.
+ *
+ * @param allocation If true the request is to allocate memory else free.
+ * @param tag The type of allocation request.
+ * @param address Pointer to the memory address. If an allocation the value is
+ * unspecific on entry and the allocated address or NULL on
+ * exit. The NULL value means the allocation failed. If a delete
+ * or free request the memory address is the block to free. A
+ * free request of NULL is silently ignored.
+ * @param size The size of the allocation if an allocation request and
+ * not used if deleting or freeing a previous allocation.
+ */
+typedef void (*rtems_rtl_allocator_t)(bool allocate,
+ rtems_rtl_alloc_tag_t tag,
+ void** address,
+ size_t size);
+
+/**
+ * The allocator data.
+ */
+struct rtems_rtl_alloc_data_s {
+ /**< The memory allocator handler. */
+ rtems_rtl_allocator_t allocator;
+ /**< The indirect pointer chains. */
+ rtems_chain_control indirects[RTEMS_RTL_ALLOC_TAGS];
+};
+
+typedef struct rtems_rtl_alloc_data_s rtems_rtl_alloc_data_t;
+
+/**
+ * Initialise the allocate data.
+ *
+ * @param data The data to initialise.
+ */
+void rtems_rtl_alloc_initialise (rtems_rtl_alloc_data_t* data);
+
+/**
+ * The Runtime Loader allocator new allocates new memory and optionally clear
+ * the memory if requested.
+ *
+ * @param tag The type of allocation request.
+ * @param size The size of the allocation.
+ * @param zero If true the memory is cleared.
+ * @return void* The memory address or NULL is not memory available.
+ */
+void* rtems_rtl_alloc_new (rtems_rtl_alloc_tag_t tag, size_t size, bool zero);
+
+/**
+ * The Runtime Loader allocator delete deletes allocated memory.
+ *
+ * @param tag The type of allocation request.
+ * @param address The memory address to delete. A NULL is ignored.
+ */
+void rtems_rtl_alloc_del (rtems_rtl_alloc_tag_t tag, void* address);
+
+/**
+ * Hook the Runtime Loader allocatior. A handler can call the previous handler
+ * in the chain to use it for specific tags. The default handler uses the
+ * system heap. Do not unhook your handler if memory it allocates has not been
+ * returned.
+ *
+ * @param handler The handler to use as the allocator.
+ * @return rtems_rtl_alloc_handler_t The previous handler.
+ */
+rtems_rtl_allocator_t rtems_rtl_alloc_hook (rtems_rtl_allocator_t handler);
+
+/**
+ * Allocate memory to an indirect handle.
+ *
+ * @param tag The type of allocation request.
+ * @param handle The handle to allocate the memory to.
+ * @param size The size of the allocation.
+ */
+void rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag,
+ rtems_rtl_ptr_t* handle,
+ size_t size);
+
+/**
+ * Free memory from an indirect handle.
+ *
+ * @param tag The type of allocation request.
+ * @param handle The handle to free the memory from.
+ */
+void rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag,
+ rtems_rtl_ptr_t* handle);
+
+/**
+ * Allocate the memory for a module given the size of the text, const, data and
+ * bss sections. If any part of the allocation fails the no memory is
+ * allocated.
+ *
+ * @param text_base Pointer to the text base pointer.
+ * @param text_size The size of the read/exec section.
+ * @param const_base Pointer to the const base pointer.
+ * @param const_size The size of the read only section.
+ * @param data_base Pointer to the data base pointer.
+ * @prarm data_size The size of the read/write secton.
+ * @param bss_base Pointer to the bss base pointer.
+ * @param bss_size The size of the read/write.
+ * @retval true The memory has been allocated.
+ * @retval false The allocation of memory has failed.
+ */
+bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
+ void** const_base, size_t const_size,
+ void** data_base, size_t data_size,
+ void** bss_base, size_t bss_size);
+
+/**
+ * Free the memory allocated to a module.
+ *
+ * @param text_base Pointer to the text base pointer.
+ * @param const_base Pointer to the const base pointer.
+ * @param data_base Pointer to the data base pointer.
+ * @param bss_base Pointer to the bss base pointer.
+ */
+void rtems_rtl_alloc_module_del (void** text_base, void** const_base,
+ void** data_base, void** bss_base);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-chain-iterator.c b/cpukit/libdl/rtl-chain-iterator.c
new file mode 100644
index 0000000..39184ee
--- /dev/null
+++ b/cpukit/libdl/rtl-chain-iterator.c
@@ -0,0 +1,57 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor Chain Iterator
+ *
+ * A means of executing an iterator on a chain.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rtl-chain-iterator.h"
+
+bool
+rtems_rtl_chain_iterate (rtems_chain_control* chain,
+ rtems_chain_iterator iterator,
+ void* data)
+{
+ rtems_chain_node* node = rtems_chain_first (chain);
+ while (!rtems_chain_is_tail (chain, node))
+ {
+ rtems_chain_node* next_node = rtems_chain_next (node);
+ if (!iterator (node, data))
+ return false;
+ node = next_node;
+ }
+ return true;
+}
+
+/**
+ * Count iterator.
+ */
+static bool
+rtems_rtl_count_iterator (rtems_chain_node* node, void* data)
+{
+ int* count = data;
+ ++(*count);
+ return true;
+}
+
+int
+rtems_rtl_chain_count (rtems_chain_control* chain)
+{
+ int count = 0;
+ rtems_rtl_chain_iterate (chain, rtems_rtl_count_iterator, &count);
+ return count;
+}
diff --git a/cpukit/libdl/rtl-chain-iterator.h b/cpukit/libdl/rtl-chain-iterator.h
new file mode 100644
index 0000000..b3781e0
--- /dev/null
+++ b/cpukit/libdl/rtl-chain-iterator.h
@@ -0,0 +1,59 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Chain Iterator.
+ */
+
+#if !defined (_RTEMS_RTL_CHAIN_ITERATOR_H_)
+#define _RTEMS_RTL_CHAIN_ITERATOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <rtems/chain.h>
+
+/**
+ * Chain iterator handler.
+ */
+typedef bool (*rtems_chain_iterator) (rtems_chain_node* node, void* data);
+
+/**
+ * Iterate a chain of nodes invoking the iterator handler. Supply a data
+ * pointer the iterator moves data between the invoker and the iterator.
+ *
+ * The iterator allows removal of the node from the chain.
+ *
+ * @param chain The chain of nodes to iterator over.
+ * @param iterator The iterator handler called once for each node.
+ * @param data Pointer to the data used by the iterator.
+ * @retval true The whole chain was iterated over.
+ * @retval false The iterator returned false.
+ */
+bool
+rtems_rtl_chain_iterate (rtems_chain_control* chain,
+ rtems_chain_iterator iterator,
+ void* data);
+
+/**
+ * Count the number of nodes on the chain.
+ *
+ * @param chain The chain to count the nodes of.
+ * @return int The number of nodes.
+ */
+int rtems_rtl_chain_count (rtems_chain_control* chain);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-debugger.c b/cpukit/libdl/rtl-debugger.c
new file mode 100644
index 0000000..2eff2bd
--- /dev/null
+++ b/cpukit/libdl/rtl-debugger.c
@@ -0,0 +1,96 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtl
+ *
+ * @brief RTEMS Module Loading Debugger Interface.
+ *
+ * Inspection of run-time linkers in NetBSD and Android show a common type of
+ * structure that is used to interface to GDB. The NetBSD definition of this
+ * interface is being used and is defined in <link.h>. It defines a protocol
+ * that is used by GDB to inspect the state of dynamic libraries. I have not
+ * checked GDB code at when writing this comment but I suspect GDB sets a break
+ * point on the r_brk field of _rtld_debug and it has code that detects this
+ * break point being hit. When this happens it reads the state and performs the
+ * operation based on the r_state field.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <link.h>
+#include <rtems/rtl/rtl.h>
+#include "rtl-trace.h"
+#include "rtl-obj-fwd.h"
+
+struct r_debug _rtld_debug;
+
+void
+_rtld_debug_state (void)
+{
+ /*
+ * Empty. GDB only needs to hit this location.
+ */
+}
+
+int
+_rtld_linkmap_add (rtems_rtl_obj_t* obj)
+{
+ struct link_map* l = (struct link_map*)obj->detail;
+ struct link_map* prev;
+ uint32_t obj_num = obj->obj_num;
+ int i;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ printf ("rtl: linkmap_add\n");
+
+ for (i = 0; i < obj_num; ++i)
+ {
+ l[i].sec_addr[rap_text] = obj->text_base;
+ l[i].sec_addr[rap_const] = obj->const_base;
+ l[i].sec_addr[rap_data] = obj->data_base;
+ l[i].sec_addr[rap_bss] = obj->bss_base;
+ }
+
+ if (_rtld_debug.r_map == NULL)
+ {
+ _rtld_debug.r_map = l;
+ return true;
+ }
+
+ for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next);
+
+ l->l_prev = prev;
+ prev->l_next = l;
+
+ return true;
+}
+
+void
+_rtld_linkmap_delete (rtems_rtl_obj_t* obj)
+{
+ struct link_map* l = (struct link_map*)obj->detail;
+ /* link_maps are allocated together if not 1 */
+ struct link_map* e = l + obj->obj_num - 1;
+
+ while (e && e->l_next) e = e->l_next;
+
+ if (l->l_prev == NULL)
+ {
+ if ((_rtld_debug.r_map = e->l_next) != NULL)
+ e->l_next->l_prev = NULL;
+ return;
+ }
+ if ((l->l_prev->l_next = e->l_next) != NULL)
+ e->l_next->l_prev = l->l_prev;
+ return;
+}
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
new file mode 100644
index 0000000..e4f1ffc
--- /dev/null
+++ b/cpukit/libdl/rtl-elf.c
@@ -0,0 +1,882 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor
+ *
+ * This is the RTL implementation.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+#include "rtl-unresolved.h"
+
+/**
+ * The offsets in the unresolved array.
+ */
+#define REL_R_OFFSET (0)
+#define REL_R_INFO (1)
+#define REL_R_ADDEND (2)
+
+/**
+ * The ELF format signature.
+ */
+static rtems_rtl_loader_format_t elf_sig =
+{
+ .label = "ELF",
+ .flags = RTEMS_RTL_FMT_ELF
+};
+
+static bool
+rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
+{
+ /*
+ * This code is determined by the NetBSD machine headers.
+ */
+ switch (ehdr->e_machine)
+ {
+ ELFDEFNNAME (MACHDEP_ID_CASES)
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool
+rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj,
+ const Elf_Sym* sym,
+ const char* symname,
+ Elf_Word* value)
+{
+ rtems_rtl_obj_sect_t* sect;
+
+ if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE)
+ {
+ rtems_rtl_obj_sym_t* symbol = rtems_rtl_symbol_global_find (symname);
+ if (!symbol)
+ {
+ rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
+ return false;
+ }
+
+ *value = (Elf_Word) symbol->value;
+ return true;
+ }
+
+ sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
+ if (!sect)
+ {
+ rtems_rtl_set_error (EINVAL, "reloc symbol's section not found");
+ return false;
+ }
+
+ *value = sym->st_value + (Elf_Word) sect->base;
+ return true;
+}
+
+static bool
+rtems_rtl_elf_relocator (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ rtems_rtl_obj_cache_t* symbols;
+ rtems_rtl_obj_cache_t* strings;
+ rtems_rtl_obj_cache_t* relocs;
+ rtems_rtl_obj_sect_t* targetsect;
+ rtems_rtl_obj_sect_t* symsect;
+ rtems_rtl_obj_sect_t* strtab;
+ bool is_rela;
+ size_t reloc_size;
+ int reloc;
+
+ /*
+ * First check if the section the relocations are for exists. If it does not
+ * exist ignore these relocations. They are most probably debug sections.
+ */
+ targetsect = rtems_rtl_obj_find_section_by_index (obj, sect->info);
+ if (!targetsect)
+ return true;
+
+ rtems_rtl_obj_caches (&symbols, &strings, &relocs);
+
+ if (!symbols || !strings || !relocs)
+ return false;
+
+ symsect = rtems_rtl_obj_find_section (obj, ".symtab");
+ if (!symsect)
+ {
+ rtems_rtl_set_error (EINVAL, "no .symtab section");
+ return false;
+ }
+
+ strtab = rtems_rtl_obj_find_section (obj, ".strtab");
+ if (!strtab)
+ {
+ rtems_rtl_set_error (EINVAL, "no .strtab section");
+ return false;
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: relocation: %s, syms:%s\n", sect->name, symsect->name);
+
+ /*
+ * Handle the different relocation record types.
+ */
+ is_rela = ((sect->flags & RTEMS_RTL_OBJ_SECT_RELA) ==
+ RTEMS_RTL_OBJ_SECT_RELA) ? true : false;
+ reloc_size = is_rela ? sizeof (Elf_Rela) : sizeof (Elf_Rel);
+
+ for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
+ {
+ uint8_t relbuf[reloc_size];
+ const Elf_Rela* rela = (const Elf_Rela*) relbuf;
+ const Elf_Rel* rel = (const Elf_Rel*) relbuf;
+ Elf_Sym sym;
+ const char* symname = NULL;
+ off_t off;
+ Elf_Word type;
+ Elf_Word symvalue = 0;
+ bool relocate;
+
+ off = obj->ooffset + sect->offset + (reloc * reloc_size);
+
+ if (!rtems_rtl_obj_cache_read_byval (relocs, fd, off,
+ &relbuf[0], reloc_size))
+ return false;
+
+ if (is_rela)
+ off = (obj->ooffset + symsect->offset +
+ (ELF_R_SYM (rela->r_info) * sizeof (sym)));
+ else
+ off = (obj->ooffset + symsect->offset +
+ (ELF_R_SYM (rel->r_info) * sizeof (sym)));
+
+ if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
+ &sym, sizeof (sym)))
+ return false;
+
+ /*
+ * Only need the name of the symbol if global.
+ */
+ if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE)
+ {
+ size_t len;
+ off = obj->ooffset + strtab->offset + sym.st_name;
+ len = RTEMS_RTL_ELF_STRING_MAX;
+
+ if (!rtems_rtl_obj_cache_read (strings, fd, off,
+ (void**) &symname, &len))
+ return false;
+ }
+
+ /*
+ * See if the record references an external symbol. If it does find the
+ * symbol value. If the symbol cannot be found flag the object file as
+ * having unresolved externals and store the externals. The load of an
+ * object after this one may provide the unresolved externals.
+ */
+ if (is_rela)
+ type = ELF_R_TYPE(rela->r_info);
+ else
+ type = ELF_R_TYPE(rel->r_info);
+
+ relocate = true;
+
+ if (rtems_rtl_elf_rel_resolve_sym (type))
+ {
+ if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue))
+ {
+ uint16_t flags = 0;
+ rtems_rtl_word_t rel_words[3];
+
+ relocate = false;
+
+ if (is_rela)
+ {
+ flags = 1;
+ rel_words[REL_R_OFFSET] = rela->r_offset;
+ rel_words[REL_R_INFO] = rela->r_info;
+ rel_words[REL_R_ADDEND] = rela->r_addend;
+ }
+ else
+ {
+ rel_words[REL_R_OFFSET] = rel->r_offset;
+ rel_words[REL_R_INFO] = rel->r_info;
+ rel_words[REL_R_ADDEND] = 0;
+ }
+
+ if (!rtems_rtl_unresolved_add (obj,
+ flags,
+ symname,
+ targetsect->section,
+ rel_words))
+ return false;
+
+ ++obj->unresolved;
+ }
+ }
+
+ if (relocate)
+ {
+ if (is_rela)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rela: sym:%s(%-2d)=%08lx type:%-2d off:%08lx addend:%d\n",
+ symname, (int) ELF_R_SYM (rela->r_info), symvalue,
+ (int) ELF_R_TYPE (rela->r_info), rela->r_offset, (int) rela->r_addend);
+ if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
+ symname, sym.st_info, symvalue))
+ return false;
+ }
+ else
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rel: sym:%s(%-2d)=%08lx type:%-2d off:%08lx\n",
+ symname, (int) ELF_R_SYM (rel->r_info), symvalue,
+ (int) ELF_R_TYPE (rel->r_info), rel->r_offset);
+ if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
+ symname, sym.st_info, symvalue))
+ return false;
+ }
+ }
+ }
+
+ /*
+ * Set the unresolved externals status if there are unresolved externals.
+ */
+ if (obj->unresolved)
+ obj->flags |= RTEMS_RTL_OBJ_UNRESOLVED;
+
+ return true;
+}
+
+bool
+rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc_t* reloc,
+ rtems_rtl_obj_sym_t* sym)
+{
+ rtems_rtl_obj_sect_t* sect;
+ bool is_rela;
+ Elf_Word symvalue;
+
+ is_rela =reloc->flags & 1;
+
+ sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
+ if (!sect)
+ {
+ rtems_rtl_set_error (ENOEXEC, "unresolved sect not found");
+ return false;
+ }
+
+ symvalue = (Elf_Word) (intptr_t) sym->value;
+ if (is_rela)
+ {
+ Elf_Rela rela;
+ rela.r_offset = reloc->rel[REL_R_OFFSET];
+ rela.r_info = reloc->rel[REL_R_INFO];
+ rela.r_addend = reloc->rel[REL_R_ADDEND];
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rela: sym:%-2d type:%-2d off:%08lx addend:%d\n",
+ (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
+ rela.r_offset, (int) rela.r_addend);
+ if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
+ sym->name, sym->data, symvalue))
+ return false;
+ }
+ else
+ {
+ Elf_Rel rel;
+ rel.r_offset = reloc->rel[REL_R_OFFSET];
+ rel.r_info = reloc->rel[REL_R_INFO];
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rel: sym:%-2d type:%-2d off:%08lx\n",
+ (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
+ rel.r_offset);
+ if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
+ sym->name, sym->data, symvalue))
+ return false;
+ }
+
+ if (reloc->obj->unresolved)
+ {
+ --reloc->obj->unresolved;
+ if (!reloc->obj->unresolved)
+ reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
+ }
+
+ return true;
+}
+
+static bool
+rtems_rtl_elf_symbols (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ rtems_rtl_obj_cache_t* symbols;
+ rtems_rtl_obj_cache_t* strings;
+ rtems_rtl_obj_sect_t* strtab;
+ int globals;
+ int string_space;
+ char* string;
+ int sym;
+
+ strtab = rtems_rtl_obj_find_section (obj, ".strtab");
+ if (!strtab)
+ {
+ rtems_rtl_set_error (EINVAL, "no .strtab section");
+ return false;
+ }
+
+ rtems_rtl_obj_caches (&symbols, &strings, NULL);
+
+ if (!symbols || !strings)
+ return false;
+
+ /*
+ * Find the number of globals and the amount of string space
+ * needed. Also check for duplicate symbols.
+ */
+
+ globals = 0;
+ string_space = 0;
+
+ for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
+ {
+ Elf_Sym symbol;
+ off_t off;
+ const char* name;
+ size_t len;
+
+ off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
+
+ if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
+ &symbol, sizeof (symbol)))
+ return false;
+
+ off = obj->ooffset + strtab->offset + symbol.st_name;
+ len = RTEMS_RTL_ELF_STRING_MAX;
+
+ if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
+ return false;
+
+ /*
+ * Only keep the functions and global or weak symbols.
+ */
+ if ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
+ (ELF_ST_TYPE (symbol.st_info) == STT_FUNC))
+ {
+ if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
+ (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
+ {
+ /*
+ * If there is a globally exported symbol already present and this
+ * symbol is not weak raise an error. If the symbol is weak and present
+ * globally ignore this symbol and use the global one and if it is not
+ * present take this symbol global or weak. We accept the first weak
+ * symbol we find and make it globally exported.
+ */
+ if (rtems_rtl_symbol_global_find (name) &&
+ (ELF_ST_BIND (symbol.st_info) != STB_WEAK))
+ {
+ rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
+ return false;
+ }
+ else
+ {
+ ++globals;
+ string_space += strlen (name) + 1;
+ }
+ }
+ }
+ }
+
+ if (globals)
+ {
+ rtems_rtl_obj_sym_t* gsym;
+
+ obj->global_size = globals * sizeof (rtems_rtl_obj_sym_t) + string_space;
+ obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
+ obj->global_size, true);
+ if (!obj->global_table)
+ {
+ obj->global_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
+ return false;
+ }
+
+ obj->global_syms = globals;
+
+ for (sym = 0,
+ gsym = obj->global_table,
+ string = (((char*) obj->global_table) +
+ (globals * sizeof (rtems_rtl_obj_sym_t)));
+ sym < (sect->size / sizeof (Elf_Sym));
+ ++sym)
+ {
+ Elf_Sym symbol;
+ off_t off;
+ const char* name;
+ size_t len;
+
+ off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
+
+ if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
+ &symbol, sizeof (symbol)))
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ return false;
+ }
+
+ off = obj->ooffset + strtab->offset + symbol.st_name;
+ len = RTEMS_RTL_ELF_STRING_MAX;
+
+ if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
+ return false;
+
+ if (((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
+ (ELF_ST_TYPE (symbol.st_info) == STT_FUNC)) &&
+ ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
+ (ELF_ST_BIND (symbol.st_info) == STB_WEAK)))
+ {
+ rtems_rtl_obj_sect_t* symsect;
+ symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
+ if (!symsect)
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ rtems_rtl_set_error (EINVAL, "sym section not found");
+ return false;
+ }
+
+ rtems_chain_set_off_chain (&gsym->node);
+
+ memcpy (string, name, strlen (name) + 1);
+ gsym->name = string;
+ string += strlen (name) + 1;
+ gsym->value = symbol.st_value + (uint8_t*) symsect->base;
+ gsym->data = symbol.st_info;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+ printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d type:%-2d val:%8p sect:%d size:%d\n",
+ sym, (int) symbol.st_name, gsym->name,
+ (int) ELF_ST_BIND (symbol.st_info),
+ (int) ELF_ST_TYPE (symbol.st_info),
+ gsym->value, symbol.st_shndx,
+ (int) symbol.st_size);
+
+ ++gsym;
+ }
+ }
+
+ rtems_rtl_symbol_obj_add (obj);
+ }
+
+ return true;
+}
+
+static bool
+rtems_rtl_elf_loader (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ uint8_t* base_offset;
+ size_t len;
+
+ if (lseek (fd, obj->ooffset + sect->offset, SEEK_SET) < 0)
+ {
+ rtems_rtl_set_error (errno, "section load seek failed");
+ return false;
+ }
+
+ base_offset = sect->base;
+ len = sect->size;
+
+ while (len)
+ {
+ ssize_t r = read (fd, base_offset, len);
+ if (r <= 0)
+ {
+ rtems_rtl_set_error (errno, "section load read failed");
+ return false;
+ }
+ base_offset += r;
+ len -= r;
+ }
+
+ return true;
+}
+
+static bool
+rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr)
+{
+ rtems_rtl_obj_cache_t* sects;
+ rtems_rtl_obj_cache_t* strings;
+ int section;
+ off_t sectstroff;
+ off_t off;
+ Elf_Shdr shdr;
+
+ rtems_rtl_obj_caches (§s, &strings, NULL);
+
+ if (!sects || !strings)
+ return false;
+
+ /*
+ * Get the offset to the section string table.
+ */
+ off = obj->ooffset + ehdr->e_shoff + (ehdr->e_shstrndx * ehdr->e_shentsize);
+
+ if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
+ return false;
+
+ if (shdr.sh_type != SHT_STRTAB)
+ {
+ rtems_rtl_set_error (EINVAL, "bad .sectstr section type");
+ return false;
+ }
+
+ sectstroff = obj->ooffset + shdr.sh_offset;
+
+ for (section = 0; section < ehdr->e_shnum; ++section)
+ {
+ uint32_t flags;
+
+ off = obj->ooffset + ehdr->e_shoff + (section * ehdr->e_shentsize);
+
+ if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
+ return false;
+
+ flags = 0;
+
+ switch (shdr.sh_type)
+ {
+ case SHT_NULL:
+ /*
+ * Ignore.
+ */
+ break;
+
+ case SHT_PROGBITS:
+ /*
+ * There are 2 program bits sections. One is the program text and the
+ * other is the program data. The program text is flagged
+ * alloc/executable and the program data is flagged alloc/writable.
+ */
+ if ((shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC)
+ {
+ if ((shdr.sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR)
+ flags = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD;
+ else if ((shdr.sh_flags & SHF_WRITE) == SHF_WRITE)
+ flags = RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD;
+ else
+ flags = RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD;
+ }
+ break;
+
+ case SHT_NOBITS:
+ /*
+ * There is 1 NOBIT section which is the .bss section. There is nothing
+ * but a definition as the .bss is just a clear region of memory.
+ */
+ if ((shdr.sh_flags & (SHF_ALLOC | SHF_WRITE)) == (SHF_ALLOC | SHF_WRITE))
+ flags = RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO;
+ break;
+
+ case SHT_RELA:
+ flags = RTEMS_RTL_OBJ_SECT_RELA;
+ break;
+
+ case SHT_REL:
+ /*
+ * The sh_link holds the section index for the symbol table. The sh_info
+ * holds the section index the relocations apply to.
+ */
+ flags = RTEMS_RTL_OBJ_SECT_REL;
+ break;
+
+ case SHT_SYMTAB:
+ flags = RTEMS_RTL_OBJ_SECT_SYM;
+ break;
+
+ case SHT_STRTAB:
+ flags = RTEMS_RTL_OBJ_SECT_STR;
+ break;
+
+ default:
+ printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
+ section, (int) shdr.sh_type, (int) shdr.sh_flags);
+ break;
+ }
+
+ if (flags != 0)
+ {
+ char* name;
+ size_t len;
+
+ len = RTEMS_RTL_ELF_STRING_MAX;
+ if (!rtems_rtl_obj_cache_read (strings, fd,
+ sectstroff + shdr.sh_name,
+ (void**) &name, &len))
+ return false;
+
+ if (strcmp (".ctors", name) == 0)
+ flags |= RTEMS_RTL_OBJ_SECT_CTOR;
+ if (strcmp (".dtors", name) == 0)
+ flags |= RTEMS_RTL_OBJ_SECT_DTOR;
+
+ if (!rtems_rtl_obj_add_section (obj, section, name,
+ shdr.sh_size, shdr.sh_offset,
+ shdr.sh_addralign, shdr.sh_link,
+ shdr.sh_info, flags))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_obj_cache_t* header;
+ Elf_Ehdr ehdr;
+
+ rtems_rtl_obj_caches (&header, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
+ &ehdr, sizeof (ehdr)))
+ return false;
+
+ /*
+ * Check we have a valid ELF file.
+ */
+ if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
+ || ehdr.e_ident[EI_CLASS] != ELFCLASS)
+ {
+ return false;
+ }
+
+ if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+ || (ehdr.e_version != EV_CURRENT)
+ || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj)
+{
+ rtems_chain_control* sections = NULL;
+ rtems_chain_node* node = NULL;
+ size_t mask = 0;
+ struct link_map* l = NULL;
+ int sec_num = 0;
+ int i = 0;
+
+ /* caculate the size of sections' name. */
+
+ for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
+ mask <= RTEMS_RTL_OBJ_SECT_BSS;
+ mask <<= 1)
+ {
+ sections = &obj->sections;
+ node = rtems_chain_first (sections);
+ while (!rtems_chain_is_tail (sections, node))
+ {
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+
+ if ((sect->size != 0) && ((sect->flags & mask) != 0))
+ {
+ ++sec_num;
+ }
+ node = rtems_chain_next (node);
+ }
+ }
+
+ obj->obj_num = 1;
+ obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ sizeof(struct link_map) +
+ sec_num * sizeof (section_detail), true);
+ if (!obj->detail)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
+ return false;
+ }
+
+ l = (struct link_map*) obj->detail;
+ l->name = obj->oname;
+ l->sec_num = sec_num;
+ l->sec_detail = (section_detail*) (l + 1);
+ l->rpathlen = 0;
+ l->rpath = NULL;
+ l->l_next = NULL;
+ l->l_prev = NULL;
+ l->sec_addr[rap_text] = obj->text_base;
+ l->sec_addr[rap_const] = obj->const_base;
+ l->sec_addr[rap_data] = obj->data_base;
+ l->sec_addr[rap_bss] = obj->bss_base;
+
+
+ section_detail* sd = l->sec_detail;
+ sections = &obj->sections;
+ node = rtems_chain_first (sections);
+ for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
+ mask <= RTEMS_RTL_OBJ_SECT_BSS;
+ mask <<= 1)
+ {
+ sections = &obj->sections;
+ node = rtems_chain_first (sections);
+ while (!rtems_chain_is_tail (sections, node))
+ {
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+
+ if ((sect->size != 0) && ((sect->flags & mask) != 0))
+ {
+ sd[i].name = sect->name;
+ sd[i].size = sect->size;
+ if (mask == RTEMS_RTL_OBJ_SECT_TEXT)
+ {
+ sd[i].rap_id = rap_text;
+ sd[i].offset = sect->base - obj->text_base;
+ }
+ if (mask == RTEMS_RTL_OBJ_SECT_CONST)
+ {
+ sd[i].rap_id = rap_const;
+ sd[i].offset = sect->base - obj->const_base;
+ }
+ if (mask == RTEMS_RTL_OBJ_SECT_DATA)
+ {
+ sd[i].rap_id = rap_data;
+ sd[i].offset = sect->base - obj->data_base;
+ }
+ if (mask == RTEMS_RTL_OBJ_SECT_BSS)
+ {
+ sd[i].rap_id = rap_bss;
+ sd[i].offset = sect->base - obj->bss_base;
+ }
+
+ ++i;
+ }
+ node = rtems_chain_next (node);
+ }
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_obj_cache_t* header;
+ Elf_Ehdr ehdr;
+
+ rtems_rtl_obj_caches (&header, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
+ &ehdr, sizeof (ehdr)))
+ return false;
+
+ /*
+ * Check we have a valid ELF file.
+ */
+ if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
+ || ehdr.e_ident[EI_CLASS] != ELFCLASS)
+ {
+ rtems_rtl_set_error (EINVAL, "invalid ELF file format");
+ return false;
+ }
+
+ if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+ || (ehdr.e_version != EV_CURRENT)
+ || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
+ {
+ rtems_rtl_set_error (EINVAL, "unsupported ELF file version");
+ return false;
+ }
+
+ if (!rtems_rtl_elf_machine_check (&ehdr))
+ {
+ rtems_rtl_set_error (EINVAL, "unsupported machine type");
+ return false;
+ }
+
+ if (ehdr.e_type == ET_DYN)
+ {
+ rtems_rtl_set_error (EINVAL, "unsupported ELF file type");
+ return false;
+ }
+
+ if (ehdr.e_phentsize != 0)
+ {
+ rtems_rtl_set_error (EINVAL, "ELF file contains program headers");
+ return false;
+ }
+
+ if (ehdr.e_shentsize != sizeof (Elf_Shdr))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid ELF section header size");
+ return false;
+ }
+
+ /*
+ * Parse the section information first so we have the memory map of the object
+ * file and the memory allocated. Any further allocations we make to complete
+ * the load will not fragment the memory.
+ */
+ if (!rtems_rtl_elf_parse_sections (obj, fd, &ehdr))
+ return false;
+
+ obj->entry = (void*)(uintptr_t) ehdr.e_entry;
+
+ if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
+ return false;
+
+ if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
+ return false;
+
+ if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
+ return false;
+
+ if (!rtems_rtl_elf_load_details (obj))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+rtems_rtl_loader_format_t*
+rtems_rtl_elf_file_sig (void)
+{
+ return &elf_sig;
+}
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
new file mode 100644
index 0000000..115c05a
--- /dev/null
+++ b/cpukit/libdl/rtl-elf.h
@@ -0,0 +1,165 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Headers
+ */
+
+#if !defined (_RTEMS_RTL_ELF_H_)
+#define _RTEMS_RTL_ELF_H_
+
+#include "rtl-fwd.h"
+#include "rtl-obj-fwd.h"
+#include "rtl-sym.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ ** Imported NetBSD ELF Specifics Start.
+ **/
+
+/*
+ * Always 32bit for RTEMS at the moment. Do not add '()'. Leave plain.
+ */
+#define ELFSIZE 32
+
+/*
+ * Define _STANDALONE then remove after.
+ */
+#define _STANDALONE 1
+
+#include <sys/cdefs.h>
+#include <sys/exec_elf.h>
+
+#undef _STANDALONE
+
+/**
+ ** Imported NetBSD ELF Specifics End.
+ **/
+
+/**
+ * Maximum string length. This a read buffering limit rather than a
+ * specific ELF length. I hope this is ok as I am concerned about
+ * some C++ symbol lengths.
+ */
+#define RTEMS_RTL_ELF_STRING_MAX (256)
+
+/**
+ * Architecture specific handler to check is a relocation record's type is
+ * required to resolve a symbol.
+ *
+ * @param type The type field in the relocation record.
+ * @retval true The relocation record require symbol resolution.
+ * @retval false The relocation record does not require symbol resolution.
+ */
+bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type);
+
+/**
+ * Architecture specific relocation handler compiled in for a specific
+ * architecture by the build system. The handler applies the relocation
+ * to the target.
+ *
+ * @param obj The object file being relocated.
+ * @param rel The ELF relocation record.
+ * @param sect The section of the object file the relocation is for.
+ * @param symname The symbol's name.
+ * @param syminfo The ELF symbol info field.
+ * @param symvalue If a symbol is referenced, this is the symbols value.
+ * @retval bool The relocation has been applied.
+ * @retval bool The relocation could not be applied.
+ */
+bool rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue);
+
+/**
+ * Architecture specific relocation handler compiled in for a specific
+ * architecture by the build system. The handler applies the relocation
+ * to the target.
+ *
+ * @param obj The object file being relocated.
+ * @param rela The ELF addend relocation record.
+ * @param sect The section of the object file the relocation is for.
+ * @param symname The symbol's name.
+ * @param syminfo The ELF symbol info field.
+ * @param symvalue If a symbol is referenced, this is the symbols value.
+ * @retval bool The relocation has been applied.
+ * @retval bool The relocation could not be applied.
+ */
+bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue);
+
+/**
+ * Find the symbol. The symbol is passed as an ELF type symbol with the name
+ * and the value returned is the absolute address of the symbol.
+ *
+ * If the symbol type is STT_NOTYPE the symbol references a global symbol. The
+ * gobal symbol table is searched to find it and that value returned. If the
+ * symbol is local to the object module the section for the symbol is located
+ * and it's base added to the symbol's value giving an absolute location.
+ *
+ * @param obj The object the symbol is being resolved for.
+ * @param sym The ELF type symbol.
+ * @param symname The sym's name read from the symbol string table.
+ * @param value Return the value of the symbol. Only valid if the return value
+ * is true.
+ * @retval true The symbol resolved.
+ * @retval false The symbol could not be result. The RTL error is set.
+ */
+bool rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj,
+ const Elf_Sym* sym,
+ const char* symname,
+ Elf_Word* value);
+
+/**
+ * The ELF format check handler.
+ *
+ * @param obj The object being checked.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The ELF file details handler.
+ *
+ * @param obj Load the details of the obj.
+ */
+bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj);
+
+/**
+ * The ELF format load handler.
+ *
+ * @param obj The object to load.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The ELF format signature handler.
+ *
+ * @return rtems_rtl_loader_format_t* The format's signature.
+ */
+rtems_rtl_loader_format_t* rtems_rtl_elf_file_sig (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-error.c b/cpukit/libdl/rtl-error.c
new file mode 100644
index 0000000..bc2e3e4
--- /dev/null
+++ b/cpukit/libdl/rtl-error.c
@@ -0,0 +1,47 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtl
+ *
+ * @brief RTEMS Run-Time Linker Error
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-error.h"
+
+void
+rtems_rtl_set_error (int error, const char* format, ...)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+ va_list ap;
+ va_start (ap, format);
+ rtl->last_errno = error;
+ vsnprintf (rtl->last_error, sizeof (rtl->last_error), format, ap);
+ rtems_rtl_unlock ();
+ va_end (ap);
+}
+
+int
+rtems_rtl_get_error (char* message, size_t max_message)
+{
+ rtems_rtl_data_t* rtl = rtems_rtl_lock ();
+ int last_errno = rtl->last_errno;
+ strncpy (message, rtl->last_error, sizeof (rtl->last_error));
+ rtems_rtl_unlock ();
+ return last_errno;
+}
+
diff --git a/cpukit/libdl/rtl-error.h b/cpukit/libdl/rtl-error.h
new file mode 100644
index 0000000..a17db59
--- /dev/null
+++ b/cpukit/libdl/rtl-error.h
@@ -0,0 +1,44 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Error
+ */
+
+#if !defined (_RTEMS_RTL_ERROR_H_)
+#define _RTEMS_RTL_ERROR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if __GNUC__
+#define RTEMS_RTL_PRINTF_ATTR __attribute__((__format__(__printf__,2,3)))
+#else
+#define RTEMS_RTL_PRINTF_ATTR
+#endif
+
+/**
+ * Sets the error.
+ *
+ * Assumes the RTL has been locked.
+ *
+ * @param error The errno error number.
+ * @param format The error format string.
+ * @param ... The variable arguments that depend on the format string.
+ */
+void rtems_rtl_set_error (int error, const char* format, ...) RTEMS_RTL_PRINTF_ATTR;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-find-file.c b/cpukit/libdl/rtl-find-file.c
new file mode 100644
index 0000000..589be40
--- /dev/null
+++ b/cpukit/libdl/rtl-find-file.c
@@ -0,0 +1,110 @@
+/*
+ * COPYRIGHT (c) 2012-2013 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtl
+ *
+ * @brief RTEMS Run-Time Linker Error
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-find-file.h"
+#include "rtl-error.h"
+#include "rtl-string.h"
+#include "rtl-trace.h"
+
+#if WAF_BUILD
+#define rtems_filesystem_is_delimiter rtems_filesystem_is_separator
+#endif
+
+bool
+rtems_rtl_find_file (const char* name,
+ const char* paths,
+ const char** file_name,
+ size_t* size)
+{
+ struct stat sb;
+
+ *file_name = NULL;
+ *size = 0;
+
+ if (rtems_filesystem_is_delimiter (name[0]) || (name[0] == '.'))
+ {
+ if (stat (name, &sb) == 0)
+ *file_name = rtems_rtl_strdup (name);
+ }
+ else if (paths)
+ {
+ const char* start;
+ const char* end;
+ int len;
+ char* fname;
+
+ start = paths;
+ end = start + strlen (paths);
+ len = strlen (name);
+
+ while (!*file_name && (start != end))
+ {
+ const char* delimiter = strchr (start, ':');
+
+ if (delimiter == NULL)
+ delimiter = end;
+
+ /*
+ * Allocate the path fragment, separator, name, terminating nul. Form the
+ * path then see if the stat call works.
+ */
+
+ fname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ (delimiter - start) + 1 + len + 1, true);
+ if (!fname)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory searching for file");
+ return false;
+ }
+
+ memcpy (fname, start, delimiter - start);
+ fname[delimiter - start] = '/';
+ memcpy (fname + (delimiter - start) + 1, name, len);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: find-file: path: %s\n", fname);
+
+ if (stat (fname, &sb) < 0)
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, fname);
+ else
+ *file_name = fname;
+
+ start = delimiter;
+ if (start != end)
+ ++start;
+ }
+ }
+
+ if (!*file_name)
+ return false;
+
+ *size = sb.st_size;
+
+ return true;
+}
diff --git a/cpukit/libdl/rtl-find-file.h b/cpukit/libdl/rtl-find-file.h
new file mode 100644
index 0000000..fc8a9dc
--- /dev/null
+++ b/cpukit/libdl/rtl-find-file.h
@@ -0,0 +1,45 @@
+/*
+ * COPYRIGHT (c) 2012-2013 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object Support.
+ */
+
+#if !defined (_RTEMS_RTL_FIND_FILE_H_)
+#define _RTEMS_RTL_FIND_FILE_H_
+
+#include <rtems.h>
+#include <rtems/chain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Find a file on disk given a name and a path.
+ *
+ * @param name The file name to find. Can be relative or absolute.
+ * @param paths The paths to search.
+ * @param file_name Place the full path in this location if found.
+ * @param size The size of the file if found as returned by the 'stat' call.
+ * @retval true The file was found.
+ * @retval false The file was not found.
+ */
+bool rtems_rtl_find_file (const char* name,
+ const char* paths,
+ const char** file_name,
+ size_t* size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-fwd.h b/cpukit/libdl/rtl-fwd.h
new file mode 100644
index 0000000..115ba8c
--- /dev/null
+++ b/cpukit/libdl/rtl-fwd.h
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Headers
+ */
+
+#if !defined (_RTEMS_RTL_FWD_H_)
+#define _RTEMS_RTL_FWD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The forward declaration of the obj structure.
+ */
+struct rtems_rtl_data_s;
+typedef struct rtems_rtl_data_s rtems_rtl_data_t;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-indirect-ptr.h b/cpukit/libdl/rtl-indirect-ptr.h
new file mode 100644
index 0000000..5a5b43b
--- /dev/null
+++ b/cpukit/libdl/rtl-indirect-ptr.h
@@ -0,0 +1,235 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Indirect Pointer Management allows memory
+ * compaction in the allocator.
+ */
+
+#if !defined (_RTEMS_RTL_INDIRECT_PTR_H_)
+#define _RTEMS_RTL_INDIRECT_PTR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <rtems/chain.h>
+
+/**
+ * The RTL Indirect pointer.
+ */
+struct rtems_rtl_ptr_s {
+ rtems_chain_node node; /**< Indirect pointers are held on lists. */
+ void* pointer; /**< The actual pointer. */
+};
+
+typedef struct rtems_rtl_ptr_s rtems_rtl_ptr_t;
+
+/**
+ * The RTL Indirect size and pointer.
+ */
+struct rtems_rtl_sptr_s {
+ rtems_rtl_ptr_t ptr; /**< The indirect pointer. */
+ size_t size; /**< The size of the memory block. */
+};
+
+typedef struct rtems_rtl_sptr_s rtems_rtl_sptr_t;
+
+/**
+ * A chain of indirect pointers for users to chain in applications.
+ *
+ * @note The chain the pointer is on is internal to the allocator and cannot be
+ * used by applications.
+ */
+struct rtems_rtl_ptr_chain_s {
+ rtems_chain_node node; /**< Chain of indirect pointers. */
+ rtems_rtl_ptr_t ptr; /**< The indirect pointer. */
+};
+
+typedef struct rtems_rtl_ptr_chain_s rtems_rtl_ptr_chain_t;
+
+/**
+ * A chain of indirect sized pointers for users to chain in applications.
+ *
+ * @note The chain the pointer is on is internal to the allocator and cannot be
+ * used by applications.
+ */
+struct rtems_rtl_sptr_chain_s {
+ rtems_chain_node node; /**< Chain of indirect pointers. */
+ rtems_rtl_sptr_t ptr; /**< The indirect pointer. */
+};
+
+typedef struct rtems_rtl_sptr_chain_s rtems_rtl_sptr_chain_t;
+
+/**
+ * Get the pointer given an indirect handle.
+ *
+ * @param handle The handle the pointer is returned from.
+ * @return void* The pointer held in the handle.
+ */
+static inline void* rtems_rtl_ptr_get (rtems_rtl_ptr_t* handle)
+{
+ return handle->pointer;
+}
+
+/**
+ * Set the pointer given an indirect handle and the pointer.
+ *
+ * @param handle The handle the pointer is returned from.
+ * @param pointer The pointer to set in the handle.
+ */
+static inline void rtems_rtl_ptr_set (rtems_rtl_ptr_t* handle, void* pointer)
+{
+ handle->pointer = pointer;
+}
+
+/**
+ * Initialise the indirect handle.
+ *
+ * @param handle The handle to initialise.
+ */
+static inline void rtems_rtl_ptr_init (rtems_rtl_ptr_t* handle)
+{
+ rtems_chain_set_off_chain (&handle->node);
+ handle->pointer = NULL;
+}
+
+/**
+ * Is the indirect handle NULL ?
+ *
+ * @param handle The handle to test.
+ * @return bool True if the pointer is NULL.
+ */
+static inline bool rtems_rtl_ptr_null (rtems_rtl_ptr_t* handle)
+{
+ return handle->pointer == NULL;
+}
+
+/**
+ * Move the allocated pointer from one handle to another. The source handle is
+ * cleared and removed from the list of handles.
+ *
+ * @param src The source handle to move the pointer from.
+ * @param dst The destination handle to receive the pointer.
+ */
+static inline void rtems_rtl_ptr_move (rtems_rtl_ptr_t* dst, rtems_rtl_ptr_t* src)
+{
+ /*
+ * We do not know which chain the src handle resides on so insert the dst
+ * handle after the src handle then extract the src handle.
+ */
+ rtems_chain_insert_unprotected (&src->node, &dst->node);
+ rtems_chain_extract_unprotected (&src->node);
+ dst->pointer = src->pointer;
+ rtems_rtl_ptr_init (src);
+}
+
+/**
+ * Return the pointer as the type provided.
+ *
+ * @param _h The handle.
+ * @param _t The type.
+ */
+#define rtems_rtl_ptr_type_get(_h, _t) ((_t*) rtems_rtl_ptr_get (_h))
+
+/**
+ * Get the pointer given an indirect handle.
+ *
+ * @param handle The handle the pointer is returned from.
+ * @return void* The pointer held in the handle.
+ */
+static inline void* rtems_rtl_sptr_get (rtems_rtl_sptr_t* handle)
+{
+ return rtems_rtl_ptr_get (&handle->ptr);
+}
+
+/**
+ * Set the pointer given an indirect handle and the pointer.
+ *
+ * @param handle The handle the pointer is returned from.
+ * @param pointer The pointer to set in the handle.
+ */
+static inline void rtems_rtl_sptr_set (rtems_rtl_sptr_t* handle, void* pointer)
+{
+ rtems_rtl_ptr_set (&handle->ptr, pointer);
+}
+
+/**
+ * Initialise the indirect handle.
+ *
+ * @param handle The handle to initialise.
+ */
+static inline void rtems_rtl_sptr_init (rtems_rtl_sptr_t* handle)
+{
+ rtems_rtl_ptr_init (&handle->ptr);
+ handle->size = 0;
+}
+
+/**
+ * Is the indirect handle NULL ?
+ *
+ * @param handle The handle to test.
+ * @return bool True if the pointer is NULL.
+ */
+static inline bool rtems_rtl_sptr_null (rtems_rtl_sptr_t* handle)
+{
+ return rtems_rtl_ptr_null (&handle->ptr);
+}
+
+/**
+ * Move the allocated pointer from one handle to another. The source handle is
+ * cleared and removed from the list of handles.
+ *
+ * @param src The source handle to move the pointer from.
+ * @param dst The destination handle to receive the pointer.
+ */
+static inline void rtems_rtl_sptr_move (rtems_rtl_sptr_t* dst, rtems_rtl_sptr_t* src)
+{
+ rtems_rtl_ptr_move (&dst->ptr, &src->ptr);
+ dst->size = src->size;
+ src->size = 0;
+}
+
+/**
+ * Get the size.
+ *
+ * @param handle The handle to get the size from.
+ * @return size_t The size_t.
+ */
+static inline size_t rtems_rtl_sptr_get_size (rtems_rtl_sptr_t* handle)
+{
+ return handle->size;
+}
+
+/**
+ * Set the size.
+ *
+ * @param handle The handle to set the size.
+ * @param size The size to set..
+ */
+static inline void rtems_rtl_sptr_set_size (rtems_rtl_sptr_t* handle, size_t size)
+{
+ handle->size = size;
+}
+
+/**
+ * Return the pointer as the type provided.
+ *
+ * @param _h The handle.
+ * @param _t The type.
+ */
+#define rtems_rtl_sptr_type_get(_h, _t) ((_t*) rtems_rtl_sptr_get (_h))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
new file mode 100644
index 0000000..692c829
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -0,0 +1,323 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: mdreloc.c,v 1.33 2010/01/14 12:12:07 skrll Exp $ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+/*
+ * It is possible for the compiler to emit relocations for unaligned data.
+ * We handle this situation with these inlines.
+ */
+#define RELOC_ALIGNED_P(x) \
+ (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+
+static inline Elf_Addr
+load_ptr(void *where)
+{
+ Elf_Addr res;
+
+ memcpy(&res, where, sizeof(res));
+
+ return (res);
+}
+
+static inline void
+store_ptr(void *where, Elf_Addr val)
+{
+
+ memcpy(where, &val, sizeof(val));
+}
+
+/*
+ * The address of Thumb function symbols is it's real address plus one.
+ * This is done by compiler, thus do not consider symtype here.
+ */
+static inline int
+isThumb(Elf_Word symvalue)
+{
+ if ((symvalue & 0x1) == 0x1)
+ return true;
+ else return false;
+}
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf_Addr tmp;
+ Elf_Word insn, addend;
+ Elf_Word sign, i1, i2;
+ uint16_t lower_insn, upper_insn;
+
+ where = (Elf_Addr *)(sect->base + rel->r_offset);
+
+ switch (ELF_R_TYPE(rel->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(CALL): /* BL/BLX */
+ case R_TYPE(JUMP24): /* B/BL<cond> */
+ insn = *where;
+
+ if (insn & 0x00800000)
+ addend = insn | 0xff000000;
+ else addend = insn & 0x00ffffff;
+
+ if (isThumb(symvalue)) {
+ if ((insn & 0xfe000000) == 0xfa000000); /* Already blx */
+ else {
+ if ((insn & 0xff000000) == 0xeb000000) { /* BL <label> */
+ *where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
+ } else {
+ printf("JUMP24 is not suppored from arm to thumb\n");
+ return false;
+ }
+ }
+ }
+
+ tmp = symvalue + (addend << 2) - (Elf_Addr)where;
+ tmp = (Elf_Sword)tmp >> 2;
+
+ if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
+ printf("CALL/JUMP24 Overflow\n");
+ return false;
+ }
+
+ *where = (*where & 0xff000000) | (tmp & 0xffffff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+
+ break;
+
+ case R_TYPE(V4BX):
+ /* Miscellaneous, ignore */
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf ("rtl: V4BX %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
+ break;
+
+ case R_TYPE(MOVT_ABS):
+ case R_TYPE(MOVW_ABS_NC):
+ insn = *where;
+
+ addend = ((insn >> 4) & 0xf000) | (insn & 0x0fff);
+ if (addend & 0x8000)
+ addend |= 0xffff0000;
+
+ tmp = symvalue + addend;
+
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(MOVW_ABS_NC))
+ tmp &= 0xffff;
+ else {
+ tmp = (Elf_Sword)tmp >> 16;
+ if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
+ printf("MOVT_ABS Overflow\n");
+ return false;
+ }
+ }
+
+ *where = (insn & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+
+ case R_TYPE(REL32): /* word32 (S + A) | T - P */
+ case R_TYPE(ABS32): /* word32 (S + A) | T */
+ case R_TYPE(GLOB_DAT): /* word32 (S + A) | T */
+ if (__predict_true(RELOC_ALIGNED_P(where))) {
+ tmp = *where + symvalue;
+ if (isThumb(symvalue))
+ tmp |= 1;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32))
+ tmp -= (Elf_Addr)where;
+ *where = tmp;
+ } else {
+ tmp = load_ptr(where) + symvalue;
+ if (isThumb(symvalue))
+ tmp |= 1;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32))
+ tmp -= (Elf_Addr)where;
+ store_ptr(where, tmp);
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL32/ABS32/GLOB_DAT %p @ %p in %s",
+ (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(THM_MOVT_ABS):
+ case R_TYPE(THM_MOVW_ABS_NC):
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+
+ addend = ((upper_insn & 0x000f) << 12) | ((upper_insn & 0x0400) << 1) |
+ ((lower_insn & 0x7000) >> 4) | (lower_insn & 0x00ff);
+ addend = (addend ^ 0x8000) - 0x8000;
+
+ tmp = addend + symvalue;
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
+ tmp >>= 16;
+
+ *(uint16_t *)where = (uint16_t)((upper_insn & 0xfbf0) |
+ ((tmp & 0xf000) >> 12) |
+ ((tmp & 0x0800) >> 1));
+ *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0x8f00) |
+ ((tmp & 0x0700) << 4) |
+ (tmp & 0x00ff));
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
+
+ break;
+
+ case R_TYPE(THM_JUMP24):
+ /* same to THM_CALL; insn b.w */
+ case R_TYPE(THM_CALL):
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+ sign = (upper_insn & (1 << 10)) >> 10;
+ i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
+ i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
+ tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
+ addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
+
+ if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */
+ else {
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(THM_JUMP24)) {
+ tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */
+ printf("THM_JUMP24 to arm not supported\n");
+ return false;
+ }
+ else {
+ /* THM_CALL bl-->blx */
+ lower_insn &=~(1<<12);
+ }
+ }
+
+ tmp = symvalue + addend;
+ tmp = tmp - (Elf_Addr)where;
+
+ if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
+ printf("THM_CALL/JUMP24 overflow\n");
+ return false;
+ }
+
+ sign = (tmp >> 24) & 1;
+ *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
+ ((tmp >> 12) & 0x3ff));
+
+ *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)|
+ ((sign ^ (~(tmp >> 23) & 1)) << 13) |
+ ((sign ^ (~(tmp >> 22) & 1)) << 11) |
+ ((tmp >> 1) & 0x7ff));
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){
+ printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
+
+ break;
+
+ case R_TYPE(THM_JUMP19):
+
+ if (!isThumb(symvalue)) {
+ printf("THM_JUMP19 to arm not supported\n");
+ return false;
+ }
+
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+ sign = (upper_insn >> 10) & 0x1;
+
+ if ((((upper_insn & 0x3f) >> 7) & 0x7) == 0x7) {
+ printf("THM_JUMP19 failed\n");
+ return false; /*if cond <3:1> == '111', see Related codings in armv7a manual */
+ }
+
+ i1 = (lower_insn >> 13) & 0x1;
+ i2 = (lower_insn >> 11) & 0x1;
+
+ tmp = ((i2 << 19) | (i1 << 18) | ((upper_insn & 0x3f) << 12) | ((lower_insn & 0x7ff) << 1));
+ addend = (tmp | ((sign ? 0 : 1) << 20)) - (1 << 20);
+ tmp = symvalue + addend;
+
+ tmp = tmp - (Elf_Addr)where;
+
+ if (((Elf_Sword)tmp > 0x7ffffe) || ((Elf_Sword)tmp < -0x800000)) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "THM_JUMP19 relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ sign = (tmp >> 20) & 0x1;
+ i2 = (tmp >> 19) & 0x1;
+ i1 = (tmp >> 18) & 0x1;
+
+ *(uint16_t*)where = (upper_insn & 0xfbc0) | (sign << 10) | ((tmp >> 12) & 0x3f);
+ *((uint16_t*)where + 1) = (lower_insn & 0xd000) | (i1 << 13) |
+ (i2 << 11) | ((tmp >> 1) & 0x7ff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: THM_JUMP19 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ default:
+ printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ "contents = %p\n",
+ ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
+ (void *)rel->r_offset, (void *)*where);
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %ld "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c
new file mode 100644
index 0000000..1c9fd5b
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-bfin.c
@@ -0,0 +1,115 @@
+#include <sys/cdefs.h>
+
+#include <stdio.h>
+#include <rtl.h>
+#include <errno.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+static inline Elf_Addr
+load_ptr(void *where)
+{
+ Elf_Addr res;
+
+ memcpy(&res, where, sizeof(res));
+
+ return (res);
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr target = 0;
+ Elf_Addr *where;
+ Elf_Word tmp;
+ Elf_Word size; //byte
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("rela relocation type is %d relocated address 0x%08x",
+ ELF_R_TYPE(rela->r_info), where);
+ }
+
+ tmp = symvalue;
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(UNUSED0):
+ break;
+
+ case R_TYPE(HUIMM16):
+ tmp = symvalue >> 16;
+ case R_TYPE(LUIMM16):
+ case R_TYPE(RIMM16):
+ size = 2;
+ break;
+
+ case R_TYPE(BYTE4_DATA):
+ size = 4;
+ break;
+
+ case R_TYPE(PCREL24):
+ case R_TYPE(PCREL24_JU):
+ where = (Elf_Addr*)((Elf_Addr)where - 2); /* Back 2 bytes */
+ tmp = symvalue - (Elf_Addr)where;
+ tmp >>= 1;
+ if ((tmp & 0x20000000) == 0x20000000)
+ tmp |= 0xc0000000;
+
+ if ((tmp & 0xff000000) && (~tmp & 0xff800000)) {
+ printf("PCREL24/PCREL24_JU Overflow\n");
+ return false;
+ }
+
+ tmp = (load_ptr(where) & 0x0000ff00) | ((tmp & 0x0000ffff) << 16) |
+ ((tmp & 0x00ff0000) >> 16);
+ size = 4;
+ break;
+
+ case R_TYPE(PCREL12_JUMP_S):
+ tmp = symvalue - (Elf_Addr)where;
+ tmp >>= 1;
+ if ((tmp & 0x20000000) == 0x20000000)
+ tmp |= 0xc0000000;
+
+ if ((tmp & 0xfffff000) && (~tmp & 0xfffff800)) {
+ printf("PCREL12_JUMP_S Overflow\n");
+ return false;
+ }
+
+ tmp = ((*(uint16_t *)where) & 0xf000) | (tmp & 0xfff);
+ size = 2;
+ break;
+
+ default:
+ printf("Unspported rela type\n");
+ return false;
+ }
+
+ memcpy((void*)where, &tmp, size);
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c
new file mode 100644
index 0000000..925601b
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-h8300.c
@@ -0,0 +1,101 @@
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf_Word tmp;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
+ printf("relocated address 0x%08lx\n", (Elf_Addr)where);
+ }
+
+ tmp = symvalue;
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(DIR16):
+ *(uint16_t *)where += symvalue + rela->r_addend;
+ break;
+
+ case R_TYPE(DIR32):
+ case R_TYPE(DIR32A16):
+ *where += symvalue + rela->r_addend;
+ break;
+
+ case R_TYPE(DIR24A8):
+ if (ELF32_R_SYM(rela->r_info))
+ *where += symvalue + rela->r_addend;
+ break;
+
+ case R_TYPE(DIR24R8):
+ where = (uint32_t *)((uint32_t)where - 1);
+ *where = (*where & 0xff000000) | ((*where & 0xffffff) + symvalue + rela->r_addend);
+ break;
+
+ case R_TYPE(PCREL8):
+ /* bcc instruction */
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where - 1;
+ if (((Elf32_Sword)tmp > 0x7f) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x80)){
+ printf("PCREL8 overflow\n");
+ return false;
+ } else {
+ *(uint8_t *)where = tmp;
+ }
+ break;
+
+ case R_TYPE(PCREL16):
+ /* bcc instruction */
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where - 2;
+ if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x8000)){
+ printf("PCREL16 overflow\n");
+ return false;
+ } else {
+ *(uint16_t *)where = tmp;
+ }
+ break;
+
+ default:
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ printf("Unsupported reloc types\n");
+ return false;
+ }
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c
new file mode 100644
index 0000000..b6dd9b7
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-i386.c
@@ -0,0 +1,103 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: mdreloc.c,v 1.31 2010/01/14 11:58:32 skrll Exp $ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr target = 0;
+ Elf_Addr* where;
+ Elf_Addr tmp;
+
+ where = (Elf_Addr *)(sect->base + rel->r_offset);
+
+ switch (ELF_R_TYPE(rel->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(PC32):
+ target = (Elf_Addr) symvalue;
+ *where += target - (Elf_Addr)where;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc PC32 in %s --> %p (%p @ %p) in %s\n",
+ sect->name, (void*) symvalue,
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(GOT32):
+ case R_TYPE(32):
+ case R_TYPE(GLOB_DAT):
+ target = (Elf_Addr) symvalue;
+
+ tmp = target + *where;
+ if (*where != tmp)
+ *where = tmp;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc 32/GLOB_DAT in %s --> %p @ %p in %s\n",
+ sect->name, (void *)*where, where,
+ rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(RELATIVE):
+ *where += (Elf_Addr)sect->base;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc RELATIVE in %s --> %p @ %p\n",
+ rtems_rtl_obj_oname (obj), (void *)*where, where);
+ break;
+
+ case R_TYPE(COPY):
+ printf ("rtl: reloc COPY (please report)\n");
+ break;
+
+ default:
+ printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ "contents = %p\n",
+ ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
+ (void *)rel->r_offset, (void *)*where);
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %ld "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ return true;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c
new file mode 100644
index 0000000..057d6ce
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-lm32.c
@@ -0,0 +1,120 @@
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf32_Word tmp;
+ Elf32_Word insn;
+
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(HI16):
+ insn = *where;
+ /* orhi/mvhi instruction
+ * 31--------26|25-21|20-16|15----0|
+ * |0 1 1 1 1 0 |rY |rX |imm16 |
+ */
+ if (0x1e == (insn >> 26)) {
+ insn &= 0xffff0000;
+ insn |= ((symvalue + rela->r_addend) >> 16);
+ *where = insn;
+ }
+ break;
+
+ case R_TYPE(LO16):
+ insn = *where;
+ /* ori instruction
+ * 31--------26|25-21|20-16|15----0|
+ * |0 0 1 1 1 0 |rY |rX |imm16 |
+ */
+ if (0xe == (insn >> 26)) {
+ insn &= 0xffff0000;
+ insn |= ((symvalue + rela->r_addend) & 0xffff);
+ *where = insn;
+ }
+ break;
+
+ case R_TYPE(CALL):
+ insn = *where;
+ /*
+ * calli instruction
+ * 31-------26|25---0|
+ * |1 1 1 1 1 0|imm26 |
+ * Syntax: call imm26
+ * Operation: ra = pc + 4; pc = pc + sign_extend(imm26<<2)
+ */
+ if (0x3e == (insn >> 26)) {
+ Elf_Sword imm26 = symvalue +rela->r_addend - (Elf_Addr)where;
+ imm26 = (imm26 >> 2) & 0x3ffffff;
+ insn = 0xf8000000 + imm26;
+ *where = insn;
+ }
+ break;
+
+ case R_TYPE(BRANCH):
+ insn = *where;
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ tmp = (Elf32_Sword)tmp >> 2;
+ if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -0x8000)){
+ printf("BRANCH Overflow\n");
+ return false;
+ }
+
+ *where = (*where & 0xffff0000) | (tmp & 0xffff);
+ break;
+
+ case R_TYPE(32):
+ *where = symvalue + rela->r_addend;
+ break;
+
+ default:
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ printf("Unsupported reloc types\n");
+ return false;
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
+ printf("relocated address 0x%08lx\n", (Elf_Addr)where);
+ }
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-m32r.c b/cpukit/libdl/rtl-mdreloc-m32r.c
new file mode 100644
index 0000000..de32f06
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-m32r.c
@@ -0,0 +1,156 @@
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+static inline Elf_Addr
+load_ptr(void *where)
+{
+ Elf_Addr res;
+
+ memcpy(&res, where, sizeof(res));
+
+ return (res);
+}
+
+static inline void
+store_ptr(void *where, Elf_Addr val)
+{
+ memcpy(where, &val, sizeof(val));
+}
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+
+ Elf_Addr *where;
+ Elf_Word tmp;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("relocated address 0x%08lx\n", (Elf_Addr)where);
+ }
+
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(16_RELA):
+ /*
+ * half16: S + A
+ */
+ *(uint16_t *)where = (symvalue + rela->r_addend) & 0xffff;
+ break;
+
+ case R_TYPE(24_RELA):
+ /*
+ * imm24: (S + A) & 0xFFFFFF
+ */
+ tmp = symvalue + rela->r_addend;
+ if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
+ printf("24_RELA Overflow\n");
+ return false;
+ }
+ *where = (*where & 0xff000000) | tmp & 0xffffff;
+ break;
+
+ case R_TYPE(32_RELA):
+ /*
+ * word32: S + A
+ */
+ *where += symvalue + rela->r_addend;
+ break;
+
+ case R_TYPE(26_PCREL_RELA):
+ /*
+ * disp24: ((S + A - P) >> 2) & 0xFFFFFF
+ */
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ tmp = (Elf_Sword)tmp >> 2;
+ if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
+ printf("26_PCREL_RELA Overflow\n");
+ return false;
+ }
+
+ *where = (*where & 0xff000000) | (tmp & 0xffffff);
+ break;
+
+ case R_TYPE(18_PCREL_RELA):
+ /*
+ * disp16: ((S + A - P) >> 2) & 0xFFFFFF
+ */
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ tmp = (Elf_Sword)tmp >> 2;
+ if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
+ printf("18_PCREL_RELA Overflow\n");
+ return false;
+ }
+
+ *where = (*where & 0xffff0000) | (tmp & 0xffff);
+ break;
+
+ case R_TYPE(HI16_ULO_RELA):
+ /*
+ * imm16: ((S + A) >> 16)
+ */
+ tmp = *where;
+ tmp += ((symvalue + rela->r_addend) >> 16) & 0xffff;
+ *where = tmp;
+ break;
+
+ case R_TYPE(HI16_SLO_RELA):
+ /*
+ * imm16: ((S + A) >> 16) or ((S + A + 0x10000) >> 16)
+ */
+ tmp = symvalue + rela->r_addend;
+ if (tmp & 0x8000) tmp += 0x10000;
+ tmp = (tmp >> 16) & 0xffff;
+ *where += tmp;
+ break;
+
+ case R_TYPE(LO16_RELA):
+ /*
+ * imm16: (S + A) & 0xFFFF
+ */
+ tmp = symvalue + rela->r_addend;
+ *where = (*where & 0xffff0000) | (tmp & 0xffff);
+ break;
+
+ default:
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ printf("Unsupported rela reloc types\n");
+ return false;
+ }
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return true;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c
new file mode 100644
index 0000000..36692eb
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-m68k.c
@@ -0,0 +1,148 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: mdreloc.c,v 1.26 2010/01/14 11:58:32 skrll Exp $ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+static inline int overflow_8_check(int value)
+{
+ if ((value & 0xffffff00) && (~value & 0xffffff80))
+ return true;
+ return false;
+}
+
+static inline int overflow_16_check(int value)
+{
+ if ((value & 0xffff0000) && (~value & 0xffff8000))
+ return true;
+ return false;
+}
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symnane,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr target = 0;
+ Elf_Addr* where;
+ Elf_Word tmp;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(PC8):
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (overflow_8_check(tmp))
+ return false;
+
+ *(uint8_t *)where = tmp;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
+ sect->name, (void*) (symvalue + rela->r_addend),
+ (void *)*where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(PC16):
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (overflow_16_check(tmp))
+ return false;
+
+ *(uint16_t*)where = tmp;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
+ sect->name, (void*) (symvalue + rela->r_addend),
+ (void *)*where, rtems_rtl_obj_oname (obj));
+ break;
+ case R_TYPE(PC32):
+ target = (Elf_Addr) symvalue + rela->r_addend;
+ *where += target - (Elf_Addr)where;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
+ sect->name, (void*) (symvalue + rela->r_addend),
+ (void *)*where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(GOT32):
+ case R_TYPE(32):
+ case R_TYPE(GLOB_DAT):
+ target = (Elf_Addr) symvalue + rela->r_addend;
+
+ if (*where != target)
+ *where = target;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(RELATIVE):
+ *where += (Elf_Addr) sect->base + rela->r_addend;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc RELATIVE in %s --> %p\n",
+ rtems_rtl_obj_oname (obj), (void *)*where);
+ break;
+
+ case R_TYPE(COPY):
+ /*
+ * These are deferred until all other relocations have
+ * been done. All we do here is make sure that the
+ * COPY relocation is not in a shared library. They
+ * are allowed only in executable files.
+ */
+ printf ("rtl: reloc COPY (please report)\n");
+ break;
+
+ default:
+ printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ "contents = %p\n",
+ ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
+ (void *)rela->r_offset, (void *)*where);
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %ld "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
+ return false;
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c
new file mode 100644
index 0000000..ea9989a
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-mips.c
@@ -0,0 +1,190 @@
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
+
+/*
+ * 1. _gp_disp symbol are not considered in this file.
+ * 2. There is a local/external column;
+ * local corresponds to (STB_LOCAL & STT_SECTION) and
+ * all others are external. Because if the type of a
+ * symbol is STT_SECTION, it must be STB_LOCAL. Thus
+ * just consider symtype here.
+ */
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf_Word tmp;
+ Elf_Word addend = (Elf_Word)0;
+ Elf_Word local = 0;
+ uint32_t t;
+
+
+ static Elf_Addr *where_hi16;
+ static Elf_Addr ahl;
+
+ where = (Elf_Addr *)(sect->base + rel->r_offset);
+ addend = *where;
+
+ if (syminfo == STT_SECTION)
+ local = 1;
+
+ switch (ELF_R_TYPE(rel->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(16):
+ tmp = addend & 0xffff;
+ if ((tmp & 0x8000) == 0x8000)
+ tmp |= 0xffff0000; /* Sign extend */
+ tmp = symvalue + (int)tmp;
+ if ((tmp & 0xffff0000) != 0) {
+ printf("R_MIPS_16 Overflow\n");
+ return false;
+ }
+
+ *where = (tmp & 0xffff) | (*where & 0xffff0000);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: R_MIPS_16 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(32):
+ tmp = symvalue + addend;
+ if (addend != tmp)
+ *where = tmp;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: R_MIPS_32 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(26):
+
+ addend &= 0x03ffffff;
+ addend <<= 2;
+
+ if (local == 1) { /* STB_LOCAL and STT_SECTION */
+ tmp = symvalue + (((Elf_Addr)where & 0xf0000000) | addend);
+ tmp >>= 2;
+
+ } else { /* external */
+
+ tmp = addend;
+
+ if ((tmp & 0x08000000) == 0x08000000)
+ tmp |= 0xf0000000; /* Sign extened */
+ tmp = ((int)tmp + symvalue) >> 2;
+
+ }
+
+ *where &= ~0x03ffffff;
+ *where |= tmp & 0x03ffffff;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: R_MIPS_26 local=%d %p @ %p in %s\n",
+ local, (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(HI16):
+ ahl = addend << 16;
+ where_hi16 = where;
+
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: R_MIPS_HI16 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(LO16):
+ //ahl += (int16_t)addend;
+ t = ahl + (int16_t)addend;
+ tmp = symvalue;
+ if (tmp == 0)
+ return false;
+
+ addend &= 0xffff0000;
+ addend |= (uint16_t)(t + tmp);
+ *where = addend;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf("*where %x where %x\n", *where, where);
+
+ addend = *where_hi16;
+ addend &= 0xffff0000;
+ addend |= ((t + tmp) - (int16_t)(t + tmp)) >> 16;
+ *where_hi16 = addend;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf("*where_hi %x where_hi %x\n", *where_hi16, where_hi16);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: R_MIPS_LO16 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(PC16):
+ tmp = addend & 0xffff;
+ if ((tmp & 0x8000) == 0x8000)
+ tmp |= 0xffff0000; /* Sign extend */
+ tmp = symvalue + ((int)tmp*4) - (Elf_Addr)where;
+ tmp = (Elf_Sword)tmp >> 2;
+ if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
+ printf("R_MIPS_PC16 Overflow\n");
+ return false;
+ }
+
+ *where = (tmp & 0xffff) | (*where & 0xffff0000);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: R_MIPS_PC16 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+
+ break;
+
+ default:
+ printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ "contents = %p\n",
+ ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
+ (void *)rel->r_offset, (void *)*where);
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %ld "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ return true;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c
new file mode 100644
index 0000000..284f68e
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-moxie.c
@@ -0,0 +1,88 @@
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf_Sword tmp;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+
+ /* Handle the not 4byte aligned address carefully */
+
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(32):
+ *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
+ *((uint16_t *)where + 1) = (symvalue + rela->r_addend) & 0xffff;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("*where 0x%04x%04x\n", *((uint16_t *)where + 1), *(uint16_t *)where);
+ }
+ break;
+
+ case R_TYPE(PCREL10):
+ /* beq, bge, bgeu, bgt, bgtu, ble, bleu, blt, bltu, bne */
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("*where %x\n", *(uint16_t *)where);
+ printf("symvalue - where %x\n", (int)(symvalue - (Elf_Word)where));
+ }
+ tmp = (symvalue + rela->r_addend - ((Elf_Word)where + 2)); /* pc is the next instruction */
+ tmp = (Elf_Sword)tmp >> 1;
+ if (((Elf32_Sword)tmp > 0x1ff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x200)){
+ printf("Overflow for PCREL10: %d exceed -0x200:0x1ff\n", tmp);
+ return false;
+ }
+
+ *(uint16_t *)where = (*(uint16_t *)where & 0xfc00) | (tmp & 0x3ff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("*where 0x%04x\n", *(uint16_t *)where);
+ }
+
+ break;
+
+ default:
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ printf("Unsupported reloc types\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-nios2.c b/cpukit/libdl/rtl-mdreloc-nios2.c
new file mode 100644
index 0000000..4f63f07
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-nios2.c
@@ -0,0 +1,44 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: mdreloc.c,v 1.26 2010/01/14 11:58:32 skrll Exp $ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ rtems_rtl_obj_sect_t* sect,
+ Elf_Word symvalue)
+{
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ rtems_rtl_obj_sect_t* sect,
+ Elf_Word symvalue)
+{
+ printf ("rtl: rel type record not supported; please report\n");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c
new file mode 100644
index 0000000..d1c0a4f
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-powerpc.c
@@ -0,0 +1,186 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: ppc_reloc.c,v 1.44 2010/01/13 20:17:22 christos Exp $ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
+ ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
+#define l(x) ((u_int32_t)(x) & 0xffff)
+
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr target = 0;
+ Elf_Addr* where;
+ Elf_Word tmp;
+ uint32_t mask = 0;
+ uint32_t bits = 0;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(32):
+ /*
+ * value:1; Field: word32; Expression: S + A
+ */
+ *where = symvalue + rela->r_addend;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR32 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(14):
+ /*
+ * value:7; Field: low14*; Expression: (S + A) >> 2
+ */
+ case R_TYPE(24):
+ /*
+ * value:2; Field: low24*; Expression: (S + A) >> 2
+ */
+ if (ELF_R_TYPE(rela->r_info) == R_TYPE(14)) {
+ bits = 14;
+ mask = 0xfffc;
+ } else {
+ bits = 24;
+ mask = 0x3fffffc;
+ }
+ tmp = (symvalue + rela->r_addend) >> 2;
+ if (tmp > (1<<bits -1 )) {
+ printf("Overflow ADDR14/ADDR24\n");
+ return false;
+ }
+ tmp = *where;
+ tmp &= ~mask;
+ tmp |= (symvalue + rela->r_addend) & mask;
+ *where = tmp;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(16_HA):
+ /*
+ * value:6; Field:half16; Expression: #ha(S+A)
+ */
+
+ tmp = symvalue + rela->r_addend;
+ *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: 16_HA %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(16_HI):
+ /*
+ * value:5; Field:half16; Expression: #hi(S+A)
+ */
+ *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: 16_HI %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ case R_TYPE(16_LO):
+ /*
+ * value:4; Field:half16; Expression: #lo(S+A)
+ */
+ *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: 16_LO %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(REL14):
+ /*
+ * value:11; Field:low14*; Expression:(S+A-P)>>2
+ */
+ case R_TYPE(REL24):
+ /*
+ * value:10; Field:low24*; Expression:(S+A-P)>>2
+ */
+ if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL24)) {
+ mask = 0x3fffffc;
+ bits = 24;
+ }
+ else if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL14)) {
+ mask = 0xfffc;
+ bits = 14;
+ }
+
+ tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
+ if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
+ ((Elf_Sword)tmp < -(1<<(bits-1)))) {
+ printf("Overflow REL14/REL24\n");
+ return false;
+ }
+
+ tmp = *where;
+ tmp &= ~mask;
+ tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
+ *where = tmp;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL24/REL14 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(REL32):
+ /*
+ * value:26; Field:word32*; Expression:S+A-P
+ */
+ *where = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL32 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ default:
+ printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ "contents = %p\n",
+ ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
+ (void *)rela->r_offset, (void *)*where);
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %ld "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
+ return false;
+ }
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ printf ("rtl: rel type record not supported; please report\n");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c
new file mode 100644
index 0000000..a8bf5e1
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-sparc.c
@@ -0,0 +1,261 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: mdreloc.c,v 1.43 2010/01/13 20:17:22 christos Exp $ */
+
+/*-
+ * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg and by Charles M. Hannum.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+
+#include <stdio.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+/*
+ * The following table holds for each relocation type:
+ * - the width in bits of the memory location the relocation
+ * applies to (not currently used)
+ * - the number of bits the relocation value must be shifted to the
+ * right (i.e. discard least significant bits) to fit into
+ * the appropriate field in the instruction word.
+ * - flags indicating whether
+ * * the relocation involves a symbol
+ * * the relocation is relative to the current position
+ * * the relocation is for a GOT entry
+ * * the relocation is relative to the load address
+ *
+ */
+#define _RF_S 0x80000000 /* Resolve symbol */
+#define _RF_A 0x40000000 /* Use addend */
+#define _RF_P 0x20000000 /* Location relative */
+#define _RF_G 0x10000000 /* GOT offset */
+#define _RF_B 0x08000000 /* Load address relative */
+#define _RF_U 0x04000000 /* Unaligned */
+#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */
+#define _RF_RS(s) ( (s) & 0xff) /* right shift */
+
+static const uint32_t reloc_target_flags[] = {
+ 0, /* NONE */
+ _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */
+ _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */
+ _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */
+ _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */
+ _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */
+ _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */
+ _RF_SZ(32) | _RF_RS(0), /* COPY */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */
+ _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */
+ _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* RELATIVE */
+ _RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */
+};
+
+#define NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
+#ifdef NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
+static const char *reloc_names[] = {
+ "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
+ "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
+ "22", "13", "LO10", "GOT10", "GOT13",
+ "GOT22", "PC10", "PC22", "WPLT30", "COPY",
+ "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32"
+};
+#endif
+
+#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0)
+#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0)
+#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0)
+#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0)
+#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0)
+#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff)
+#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff)
+
+static const int reloc_target_bitmask[] = {
+#define _BM(x) (~(-(1ULL << (x))))
+ 0, /* NONE */
+ _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */
+ _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */
+ _BM(30), _BM(22), /* WDISP30, WDISP22 */
+ _BM(22), _BM(22), /* HI22, _22 */
+ _BM(13), _BM(10), /* RELOC_13, _LO10 */
+ _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */
+ _BM(10), _BM(22), /* _PC10, _PC22 */
+ _BM(30), 0, /* _WPLT30, _COPY */
+ -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
+ _BM(32) /* _UA32 */
+#undef _BM
+};
+#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return RELOC_RESOLVE_SYMBOL (type) ? true : false;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf_Word type, value, mask;
+
+ where = (Elf_Addr *) (sect->base + rela->r_offset);
+
+ type = ELF_R_TYPE(rela->r_info);
+ if (type == R_TYPE(NONE))
+ return true;
+
+ /* We do JMP_SLOTs in _rtld_bind() below */
+ if (type == R_TYPE(JMP_SLOT))
+ return true;
+
+ /* COPY relocs are also handled elsewhere */
+ if (type == R_TYPE(COPY))
+ return true;
+
+ /*
+ * We use the fact that relocation types are an `enum'
+ * Note: R_SPARC_6 is currently numerically largest.
+ */
+ if (type > R_TYPE(6))
+ return false;
+
+ value = rela->r_addend;
+
+ /*
+ * Handle relative relocs here, as an optimization.
+ */
+ if (type == R_TYPE (RELATIVE)) {
+ *where += (Elf_Addr)(sect->base + value);
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc relative in %s --> %p",
+ rtems_rtl_obj_oname (obj), (void *)*where);
+ return true;
+ }
+
+ if (RELOC_RESOLVE_SYMBOL (type)) {
+ /* Add in the symbol's absolute address */
+ value += symvalue;
+ }
+
+ if (RELOC_PC_RELATIVE (type)) {
+ value -= (Elf_Word)where;
+ }
+
+ if (RELOC_BASE_RELATIVE (type)) {
+ /*
+ * Note that even though sparcs use `Elf_rela'
+ * exclusively we still need the implicit memory addend
+ * in relocations referring to GOT entries.
+ * Undoubtedly, someone f*cked this up in the distant
+ * past, and now we're stuck with it in the name of
+ * compatibility for all eternity..
+ *
+ * In any case, the implicit and explicit should be
+ * mutually exclusive. We provide a check for that
+ * here.
+ */
+#define DIAGNOSTIC
+#ifdef DIAGNOSTIC
+ if (value != 0 && *where != 0) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf("rtl: reloc base_rel(%s): where=%p, *where 0x%lx, "
+ "addend=0x%lx, base %p\n",
+ rtems_rtl_obj_oname (obj),
+ where, *where, rela->r_addend, sect->base);
+ }
+#endif
+ value += (Elf_Word)(sect->base + *where);
+ }
+
+ mask = RELOC_VALUE_BITMASK (type);
+ value >>= RELOC_VALUE_RIGHTSHIFT (type);
+ value &= mask;
+
+ if (RELOC_UNALIGNED(type)) {
+ /* Handle unaligned relocations. */
+ Elf_Addr tmp = 0;
+ char *ptr = (char *)where;
+ int i, size = RELOC_TARGET_SIZE (type) / 8;
+
+ /* Read it in one byte at a time. */
+ for (i=0; i<size; i++)
+ tmp = (tmp << 8) | ptr[i];
+
+ tmp &= ~mask;
+ tmp |= value;
+
+ /* Write it back out. */
+ for (i=0; i<size; i++)
+ ptr[i] = ((tmp >> (8*i)) & 0xff);
+
+ } else {
+ *where &= ~mask;
+ *where |= value;
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: %s %p @ %p in %s\n",
+ reloc_names[type], (void *)*where, where, rtems_rtl_obj_oname (obj));
+
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ printf ("rtl: rel type record not supported; please report\n");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c
new file mode 100644
index 0000000..5372e81
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-v850.c
@@ -0,0 +1,97 @@
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-trace.h"
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ Elf_Addr *where;
+ Elf_Word tmp;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
+ printf("relocated address 0x%08lx\n", (Elf_Addr)where);
+ }
+
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(HI16_S):
+ tmp = (Elf_Sword)(symvalue + rela->r_addend) >> 16;
+ ((uint16_t *)where)[0] = tmp & 0xffff;
+ break;
+
+ case R_TYPE(LO16):
+ tmp = symvalue + rela->r_addend;
+ ((uint16_t *)where)[0] = tmp & 0xffff;
+ break;
+
+ case R_TYPE(LO16_S1):
+ tmp = symvalue + rela->r_addend;
+ ((uint16_t *)where)[0] = tmp & 0xfffe | 0x1;
+ break;
+
+ case R_TYPE(22_PCREL):
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (((Elf_Sword)tmp > 0x1fffff) || ((Elf_Sword)tmp < -0x200000)) {
+ printf("Overflow\n");
+ return false;
+ }
+
+ ((uint16_t *)where)[0] = (*(uint16_t *)where & 0xffc0) |
+ ((tmp >> 16) & 0x3f);
+ ((uint16_t *)where)[1] = (tmp & 0xfffe);
+
+ break;
+
+ case R_TYPE(ABS32):
+ tmp = symvalue + rela->r_addend;
+ tmp += ((uint16_t *)where)[0];
+ tmp += ((uint16_t *)where)[1] << 16;
+ ((uint16_t *)where)[0] = tmp & 0xffff;
+ ((uint16_t *)where)[1] = (tmp >> 16) & 0xffff;
+ break;
+
+ default:
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ printf("error reloc type\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect_t* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
diff --git a/cpukit/libdl/rtl-obj-cache.c b/cpukit/libdl/rtl-obj-cache.c
new file mode 100644
index 0000000..23d7d07
--- /dev/null
+++ b/cpukit/libdl/rtl-obj-cache.c
@@ -0,0 +1,197 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File cache buffers a section of the
+ * object file in a buffer to localise read performance.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl-allocator.h>
+#include "rtl-obj-cache.h"
+#include "rtl-error.h"
+
+bool
+rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size)
+{
+ cache->fd = -1;
+ cache->file_size = 0;
+ cache->offset = 0;
+ cache->size = size;
+ cache->level = 0;
+ cache->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
+ if (!cache->buffer)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for cache buffer");
+ return false;
+ }
+ return true;
+}
+
+void
+rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache)
+{
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer);
+ cache->fd = -1;
+ cache->file_size = 0;
+ cache->level = 0;
+}
+
+void
+rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache)
+{
+ cache->fd = -1;
+ cache->file_size = 0;
+ cache->level = 0;
+}
+
+bool
+rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
+ int fd,
+ off_t offset,
+ void** buffer,
+ size_t* length)
+{
+ struct stat sb;
+
+ if (*length > cache->size)
+ {
+ rtems_rtl_set_error (EINVAL, "read size larger than cache size");
+ return false;
+ }
+
+ if (cache->fd == fd)
+ {
+ if (offset > cache->file_size)
+ {
+ rtems_rtl_set_error (EINVAL, "offset past end of file: offset=%i size=%i",
+ (int) offset, (int) cache->file_size);
+ return false;
+ }
+
+ if ((offset + *length) > cache->file_size)
+ *length = cache->file_size - offset;
+ }
+
+ while (true)
+ {
+ size_t buffer_offset = 0;
+ size_t buffer_read = cache->size;
+
+ /*
+ * Is the data in the cache for this file ?
+ */
+ if (fd == cache->fd)
+ {
+ /*
+ * Is any part of the data in the cache ?
+ */
+ if ((offset >= cache->offset) &&
+ (offset < (cache->offset + cache->level)))
+ {
+ buffer_offset = offset - cache->offset;
+
+ /*
+ * Return the location of the data in the cache.
+ */
+ *buffer = cache->buffer + buffer_offset;
+
+ /*
+ * Is all the data in the cache or just a part ?
+ */
+ if (*length <= (cache->level - buffer_offset))
+ {
+ return true;
+ }
+
+ /*
+ * Copy down the data in the buffer and then fill the remaining
+ * space with as much data we are able to read.
+ */
+ memmove (cache->buffer,
+ cache->buffer + buffer_offset,
+ cache->size - buffer_offset);
+
+ buffer_read = buffer_offset;
+ buffer_offset = cache->size - buffer_offset;
+ }
+ }
+
+ if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0)
+ {
+ rtems_rtl_set_error (errno, "file seek failed");
+ return false;
+ }
+
+ /*
+ * Loop reading the data from the file until either an error or 0 is
+ * returned and if data has been read check if the amount is what we
+ * want. If not it is an error. A POSIX read can read data in fragments.
+ */
+ cache->level = buffer_read;
+ while (buffer_read)
+ {
+ int r = read (fd, cache->buffer + buffer_offset, buffer_read);
+ if (r < 0)
+ {
+ rtems_rtl_set_error (errno, "file read failed");
+ return false;
+ }
+ if ((r == 0) && buffer_read)
+ {
+ cache->level = cache->level - buffer_read;
+ buffer_read = 0;
+ }
+ else
+ {
+ buffer_read -= r;
+ buffer_offset += r;
+ }
+ }
+
+ cache->fd = fd;
+ cache->offset = offset;
+
+ if (fstat (cache->fd, &sb) < 0)
+ {
+ rtems_rtl_set_error (errno, "file stat failed");
+ return false;
+ }
+
+ cache->file_size = sb.st_size;
+ }
+
+ return false;
+}
+
+bool
+rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache_t* cache,
+ int fd,
+ off_t offset,
+ void* buffer,
+ size_t length)
+{
+ void* cbuffer = 0;
+ size_t len = length;
+ bool ok = rtems_rtl_obj_cache_read (cache, fd, offset, &cbuffer, &len);
+ if (ok && (len != length))
+ ok = false;
+ if (ok)
+ memcpy (buffer, cbuffer, length);
+ return ok;
+}
diff --git a/cpukit/libdl/rtl-obj-cache.h b/cpukit/libdl/rtl-obj-cache.h
new file mode 100644
index 0000000..8abb7f3
--- /dev/null
+++ b/cpukit/libdl/rtl-obj-cache.h
@@ -0,0 +1,132 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File cache buffers a section of the
+ * object file in a buffer to localise read performance.
+ *
+ * This is a simple object file cache that holds a buffer of data from the
+ * offset in the file the read is requested from. Writes are not supported.
+ *
+ * The cache holds the file descriptor, the offset into the file and the amount
+ * of valid data in the cache. If the file is ever modified the user of the
+ * cache to responsible for flushing the cache. For example the cache should be
+ * flused if the file is closed.
+ *
+ * The cache can return by reference or by value. By reference allow access to
+ * the cache buffer. Do not modify the cache's data. By value will copy the
+ * requested data into the user supplied buffer.
+ *
+ * The read by reference call allows you to probe the file's data. For example
+ * a string in an object file can be an unknown length. You can request a read
+ * up to the cache's size by reference. The code will attempt to have this data
+ * in the buffer. If there is not enough data in the file the length will be
+ * modifed to reflect this.
+ *
+ * You can have more than one cache for a single file all looking at different
+ * parts of the file.
+ */
+
+#if !defined (_RTEMS_RTL_OBJ_CACHE_H_)
+#define _RTEMS_RTL_OBJ_CACHE_H_
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The buffer cache.
+ */
+typedef struct rtems_rtl_obj_cache_s
+{
+ int fd; /**< The file descriptor of the data in the cache. */
+ size_t file_size; /**< The size of the file. */
+ off_t offset; /**< The base offset of the buffer. */
+ size_t size; /**< The size of the cache. */
+ size_t level; /**< The amount of data in the cache. A file can be
+ * smaller than the cache file. */
+ uint8_t* buffer; /**< The buffer */
+} rtems_rtl_obj_cache_t;
+
+/**
+ * Open a cache allocating a single buffer of the size passed. The default
+ * state of the cache is flushed. No already open checks are made.
+ *
+ * @param cache The cache to initialise.
+ * @param size The size of the cache.
+ * @retval true The cache is open.
+ * @retval false The cache is not open. The RTL error is set.
+ */
+bool rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size);
+
+/**
+ * Close a cache.
+ *
+ * @param cache The cache to close.
+ */
+void rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache);
+
+/**
+ * Flush the cache. Any further read will read the data from the file.
+ *
+ * @param cache The cache to flush.
+ */
+void rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache);
+
+/**
+ * Read data by reference. The length contains the amount of data that should
+ * be available in the cache and referenced by the buffer handle. It must be
+ * less than or equal to the size of the cache. This call will return the
+ * amount of data that is available. It can be less than you ask if the offset
+ * and size is past the end of the file.
+ *
+ * @param cache The cache to reference data from.
+ * @param fd The file descriptor. Must be an open file.
+ * @param offset The offset in the file to reference the data to.
+ * @param buffer The location to reference the data from.
+ * @param length The length of data to reference. Can be modified to a
+ * lesser value and true is still returned so check it.
+ * @retval true The data referenced is in the cache.
+ * @retval false The read failed and the RTL error has been set.
+ */
+bool rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
+ int fd,
+ off_t offset,
+ void** buffer,
+ size_t* length);
+
+/**
+ * Read data by value. The data is copied to the user supplied buffer.
+ *
+ * @param cache The cache to read the data from.
+ * @param fd The file descriptor. Must be an open file.
+ * @param offset The offset in the file to read the data from.
+ * @param buffer The location the data is written into.
+ * @param length The length of data to read.
+ * @retval true The data has been read from the cache.
+ * @retval false The read failed and the RTL error has been set.
+ */
+bool rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache_t* cache,
+ int fd,
+ off_t offset,
+ void* buffer,
+ size_t length);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-obj-comp.c b/cpukit/libdl/rtl-obj-comp.c
new file mode 100644
index 0000000..d9c5462
--- /dev/null
+++ b/cpukit/libdl/rtl-obj-comp.c
@@ -0,0 +1,179 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object Compression manages a compress
+ * stream of data.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl-allocator.h>
+#include "rtl-obj-comp.h"
+#include "rtl-error.h"
+
+#include "fastlz.h"
+
+#include <stdio.h>
+
+bool
+rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp,
+ size_t size)
+{
+ comp->cache = NULL;
+ comp->fd = -1;
+ comp->compression = RTEMS_RTL_COMP_LZ77;
+ comp->offset = 0;
+ comp->size = size;
+ comp->level = 0;
+ comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
+ if (!comp->buffer)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
+ return false;
+ }
+ comp->read = 0;
+ return true;
+}
+
+void
+rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp)
+{
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
+ comp->cache = NULL;
+ comp->fd = -1;
+ comp->compression = RTEMS_RTL_COMP_LZ77;
+ comp->level = 0;
+ comp->size = 0;
+ comp->offset = 0;
+ comp->read = 0;
+}
+
+void
+rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t* comp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset)
+{
+ comp->cache = cache;
+ comp->fd = fd;
+ comp->compression = compression;
+ comp->offset = offset;
+ comp->level = 0;
+ comp->read = 0;
+}
+
+bool
+rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
+ void* buffer,
+ size_t length)
+{
+ uint8_t* bin = buffer;
+
+ if (!comp->cache)
+ {
+ rtems_rtl_set_error (EINVAL, "not open");
+ return false;
+ }
+
+ if (comp->fd != comp->cache->fd)
+ {
+ comp->level = 0;
+ }
+
+ while (length)
+ {
+ size_t buffer_level;
+
+ buffer_level = length > comp->level ? comp->level : length;
+
+ if (buffer_level)
+ {
+ memcpy (bin, comp->buffer, buffer_level);
+
+ if ((comp->level - buffer_level) != 0)
+ {
+ memmove (comp->buffer,
+ comp->buffer + buffer_level,
+ comp->level - buffer_level);
+ }
+
+ bin += buffer_level;
+ length -= buffer_level;
+ comp->level -= buffer_level;
+ comp->read += buffer_level;
+ }
+
+ if (length)
+ {
+ uint8_t* input = NULL;
+ uint16_t block_size;
+ size_t in_length = sizeof (block_size);
+ int decompressed;
+
+ if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
+ (void**) &input, &in_length))
+ return false;
+
+ block_size = (input[0] << 8) | input[1];
+
+ comp->offset += sizeof (block_size);
+
+ in_length = block_size;
+
+ if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
+ (void**) &input, &in_length))
+ return false;
+
+ if (in_length != block_size)
+ {
+ rtems_rtl_set_error (EIO, "compressed read failed: bs=%u in=%u",
+ block_size, in_length);
+ return false;
+ }
+
+ switch (comp->compression)
+ {
+ case RTEMS_RTL_COMP_NONE:
+ memcpy (comp->buffer, input, in_length);
+ decompressed = in_length;
+ break;
+
+ case RTEMS_RTL_COMP_LZ77:
+ decompressed = fastlz_decompress (input, in_length,
+ comp->buffer, comp->size);
+ if (decompressed == 0)
+ {
+ rtems_rtl_set_error (EBADF, "decompression failed");
+ return false;
+ }
+ break;
+
+ default:
+ rtems_rtl_set_error (EINVAL, "bad compression type");
+ return false;
+ }
+
+ comp->offset += block_size;
+
+ comp->level = decompressed;
+ }
+ }
+
+ return true;
+}
diff --git a/cpukit/libdl/rtl-obj-comp.h b/cpukit/libdl/rtl-obj-comp.h
new file mode 100644
index 0000000..df7a429
--- /dev/null
+++ b/cpukit/libdl/rtl-obj-comp.h
@@ -0,0 +1,122 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Compression manages a
+ * compressed stream of data.
+ *
+ * This is a simple interface to the object file cache to stream data from
+ * from a compressed object file. There is no ability to seek with the
+ * data from a compressed file. The module exists to allocate the output
+ * buffer when the loader starts and use the cache buffers will have been
+ * allocated.
+ */
+
+#if !defined (_RTEMS_RTL_OBJ_COMP_H_)
+#define _RTEMS_RTL_OBJ_COMP_H_
+
+#include <rtems/rtl/rtl-obj-cache.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The amount of input data read at a time from the file.
+ */
+#define RTEMS_RTL_DECOMP_INPUT_SIZE (256)
+
+/**
+ * The types of supported compression.
+ */
+#define RTEMS_RTL_COMP_NONE (0)
+#define RTEMS_RTL_COMP_LZ77 (1)
+
+/**
+ * The compressed file.
+ */
+typedef struct rtems_rtl_obj_cpmp_s
+{
+ rtems_rtl_obj_cache_t* cache; /**< The cache provides the input
+ * buffer. */
+ int fd; /**< The file descriptor. */
+ int compression; /**< The type of compression. */
+ off_t offset; /**< The base offset of the buffer. */
+ size_t size; /**< The size of the output buffer. */
+ size_t level; /**< The amount of data in the buffer. */
+ uint8_t* buffer; /**< The buffer */
+ uint32_t read; /**< The amount of data read. */
+} rtems_rtl_obj_comp_t;
+
+/**
+ * Return the input level.
+ */
+static inline uint32_t rtems_rtl_obj_comp_input (rtems_rtl_obj_comp_t* comp)
+{
+ return comp->read;
+}
+
+/**
+ * Open a compressor allocating the output buffer.
+ *
+ * @param comp The compressor to initialise.
+ * @param size The size of the compressor's output buffer.
+ * @retval true The compressor is open.
+ * @retval false The compressor is not open. The RTL error is set.
+ */
+bool rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp,
+ size_t size);
+
+/**
+ * Close a compressor.
+ *
+ * @param comp The compressor to close.
+ */
+void rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp);
+
+/**
+ * Set the cache and offset in the file the compressed stream starts.
+ *
+ * @param comp The compressor to set the offset in.
+ * @param cache The cache to read the file in by.
+ * @param fd The file descriptor. Must be an open file.
+ * @param compression The type of compression being streamed.
+ * @param offset The offset in the file the compressed stream starts.
+ */
+void rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t* comp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset);
+
+/**
+ * Read decompressed data. The length contains the amount of data that should
+ * be available in the cache and referenced by the buffer handle. It must be
+ * less than or equal to the size of the cache. This call will return the
+ * amount of data that is available. It can be less than you ask if the offset
+ * and size is past the end of the file.
+ *
+ * @param comp The compressor to read data from.
+ * @param buffer The buffer the output is written too.
+ * @param length The length of data to read. Can be modified to a
+ * lesser value and true is still returned so check it.
+ * @retval true The data referenced is in the cache.
+ * @retval false The read failed and the RTL error has been set.
+ */
+bool rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
+ void* buffer,
+ size_t length);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-obj-fwd.h b/cpukit/libdl/rtl-obj-fwd.h
new file mode 100644
index 0000000..c4186d9
--- /dev/null
+++ b/cpukit/libdl/rtl-obj-fwd.h
@@ -0,0 +1,39 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Headers
+ */
+
+#if !defined (_RTEMS_RTL_OBJ_FWD_H_)
+#define _RTEMS_RTL_OBJ_FWD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The forward declaration of the obj section structure.
+ */
+struct rtems_rtl_obj_sect_s;
+typedef struct rtems_rtl_obj_sect_s rtems_rtl_obj_sect_t;
+
+/**
+ * The forward declaration of the obj structure.
+ */
+struct rtems_rtl_obj_s;
+typedef struct rtems_rtl_obj_s rtems_rtl_obj_t;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
new file mode 100644
index 0000000..d4ee63c
--- /dev/null
+++ b/cpukit/libdl/rtl-obj.c
@@ -0,0 +1,1031 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtl
+ *
+ * @brief RTEMS Run-Time Linker Error
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rtems/libio_.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-chain-iterator.h"
+#include "rtl-obj.h"
+#include "rtl-error.h"
+#include "rtl-find-file.h"
+#include "rtl-string.h"
+#include "rtl-trace.h"
+
+#if RTEMS_RTL_RAP_LOADER
+#include "rtl-rap.h"
+#define RTEMS_RTL_RAP_LOADER_COUNT 1
+#else
+#define RTEMS_RTL_RAP_LOADER_COUNT 0
+#endif
+
+#if RTEMS_RTL_ELF_LOADER
+#include "rtl-elf.h"
+#define RTEMS_RTL_ELF_LOADER_COUNT 1
+#else
+#define RTEMS_RTL_ELF_LOADER_COUNT 0
+#endif
+
+/**
+ * The table of supported loader formats.
+ */
+static rtems_rtl_loader_table_t loaders[RTEMS_RTL_ELF_LOADER_COUNT +
+ RTEMS_RTL_RAP_LOADER_COUNT] =
+{
+#if RTEMS_RTL_RAP_LOADER
+ { rtems_rtl_rap_file_check, rtems_rtl_rap_file_load, rtems_rtl_rap_file_sig },
+#endif
+#if RTEMS_RTL_ELF_LOADER
+ { rtems_rtl_elf_file_check, rtems_rtl_elf_file_load, rtems_rtl_elf_file_sig },
+#endif
+};
+
+rtems_rtl_obj_t*
+rtems_rtl_obj_alloc (void)
+{
+ rtems_rtl_obj_t* obj = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ sizeof (rtems_rtl_obj_t),
+ true);
+ if (obj)
+ {
+ /*
+ * Initialise the chains.
+ */
+ rtems_chain_initialize_empty (&obj->sections);
+ }
+ return obj;
+}
+
+static void
+rtems_rtl_obj_free_names (rtems_rtl_obj_t* obj)
+{
+ if (rtems_rtl_obj_oname_valid (obj))
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->oname);
+ if (rtems_rtl_obj_aname_valid (obj))
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->aname);
+ if (rtems_rtl_obj_fname_valid (obj))
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->fname);
+}
+
+bool
+rtems_rtl_obj_free (rtems_rtl_obj_t* obj)
+{
+ if (obj->users || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0))
+ {
+ rtems_rtl_set_error (EINVAL, "cannot free obj still in use");
+ return false;
+ }
+ if (!rtems_chain_is_node_off_chain (&obj->link))
+ rtems_chain_extract (&obj->link);
+ rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base,
+ &obj->data_base, &obj->bss_base);
+ rtems_rtl_symbol_obj_erase (obj);
+ rtems_rtl_obj_free_names (obj);
+ if (obj->sec_num)
+ free (obj->sec_num);
+ if (obj->detail)
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*)obj->detail);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
+ return true;
+}
+
+bool
+rtems_rtl_obj_unresolved (rtems_rtl_obj_t* obj)
+{
+ return (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0 ? true : false;
+}
+
+bool
+rtems_rtl_parse_name (const char* name,
+ const char** aname,
+ const char** oname,
+ off_t* ooffset)
+{
+ const char* laname = NULL;
+ const char* loname = NULL;
+ const char* colon;
+ const char* end;
+
+ /*
+ * Parse the name to determine if the object file is part of an archive or it
+ * is an object file. If an archive check the name for a '@' to see if the
+ * archive contains an offset.
+ */
+ end = name + strlen (name);
+ colon = strrchr (name, ':');
+ if (colon == NULL || colon < strrchr(name, '/'))
+ colon = end;
+
+ loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, colon - name + 1, true);
+ if (!oname)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for object file name");
+ return false;
+ }
+
+ memcpy ((void*) loname, name, colon - name);
+
+ /*
+ * If the pointers match there is no ':' delimiter.
+ */
+ if (colon != end)
+ {
+ const char* at;
+
+ /*
+ * The file name is an archive and the object file name is next after the
+ * delimiter. Move the pointer to the archive name.
+ */
+ laname = loname;
+ ++colon;
+
+ /*
+ * See if there is a '@' to delimit an archive offset for the object in the
+ * archive.
+ */
+ at = strchr (colon, '@');
+
+ if (at == NULL)
+ at = end;
+
+
+ loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, at - colon + 1, true);
+ if (!loname)
+ {
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) laname);
+ rtems_rtl_set_error (ENOMEM, "no memory for object file name");
+ return false;
+ }
+
+ memcpy ((void*) loname, colon, at - colon);
+
+ if (at != end)
+ {
+ /*
+ * The object name has an archive offset. If the number
+ * does not parse 0 will be returned and the archive will be
+ * searched.
+ */
+ *ooffset = strtoul (at + 1, 0, 0);
+ }
+ }
+
+ *oname = loname;
+ *aname = laname;
+ return true;
+}
+
+static bool
+rtems_rtl_obj_parse_name (rtems_rtl_obj_t* obj, const char* name)
+{
+ return rtems_rtl_parse_name (name, &(obj->aname), &(obj->oname), &(obj->ooffset));
+}
+
+static bool
+rtems_rtl_seek_read (int fd, off_t off, size_t len, uint8_t* buffer)
+{
+ if (lseek (fd, off, SEEK_SET) < 0)
+ return false;
+ if (read (fd, buffer, len) != len)
+ return false;
+ return true;
+}
+
+/**
+ * Scan the decimal number returning the value found.
+ */
+static uint64_t
+rtems_rtl_scan_decimal (const uint8_t* string, size_t len)
+{
+ uint64_t value = 0;
+
+ while (len && (*string != ' '))
+ {
+ value *= 10;
+ value += *string - '0';
+ ++string;
+ --len;
+ }
+
+ return value;
+}
+
+/**
+ * Align the size to the next alignment point. Assume the alignment is a
+ * positive integral power of 2 if not 0 or 1. If 0 or 1 then there is no
+ * alignment.
+ */
+static size_t
+rtems_rtl_sect_align (size_t offset, uint32_t alignment)
+{
+ if ((alignment > 1) && ((offset & ~alignment) != 0))
+ offset = (offset + alignment) & ~(alignment - 1);
+ return offset;
+}
+
+/**
+ * Section size summer iterator data.
+ */
+typedef struct
+{
+ uint32_t mask; /**< The selection mask to sum. */
+ size_t size; /**< The size of all section fragments. */
+} rtems_rtl_obj_sect_summer_t;
+
+static bool
+rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data)
+{
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ rtems_rtl_obj_sect_summer_t* summer = data;
+ if ((sect->flags & summer->mask) == summer->mask)
+ summer->size =
+ rtems_rtl_sect_align (summer->size, sect->alignment) + sect->size;
+ return true;
+}
+
+static size_t
+rtems_rtl_obj_section_size (rtems_rtl_obj_t* obj, uint32_t mask)
+{
+ rtems_rtl_obj_sect_summer_t summer;
+ summer.mask = mask;
+ summer.size = 0;
+ rtems_rtl_chain_iterate (&obj->sections,
+ rtems_rtl_obj_sect_summer,
+ &summer);
+ return summer.size;
+}
+
+/**
+ * Section alignment iterator data. The first section's alignment sets the
+ * alignment for that type of section.
+ */
+typedef struct
+{
+ uint32_t mask; /**< The selection mask to look for alignment. */
+ uint32_t alignment; /**< The alignment of the section type. */
+} rtems_rtl_obj_sect_aligner_t;
+
+/**
+ * The section aligner iterator.
+ */
+static bool
+rtems_rtl_obj_sect_aligner (rtems_chain_node* node, void* data)
+{
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ rtems_rtl_obj_sect_aligner_t* aligner = data;
+ if ((sect->flags & aligner->mask) == aligner->mask)
+ {
+ aligner->alignment = sect->alignment;
+ return false;
+ }
+ return true;
+}
+
+static size_t
+rtems_rtl_obj_section_alignment (rtems_rtl_obj_t* obj, uint32_t mask)
+{
+ rtems_rtl_obj_sect_aligner_t aligner;
+ aligner.mask = mask;
+ aligner.alignment = 0;
+ rtems_rtl_chain_iterate (&obj->sections,
+ rtems_rtl_obj_sect_aligner,
+ &aligner);
+ return aligner.alignment;
+}
+
+static bool
+rtems_rtl_obj_section_handler (uint32_t mask,
+ rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
+{
+ rtems_chain_node* node = rtems_chain_first (&obj->sections);
+ while (!rtems_chain_is_tail (&obj->sections, node))
+ {
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ if ((sect->flags & mask) != 0)
+ {
+ if (!handler (obj, fd, sect, data))
+ return false;
+ }
+ node = rtems_chain_next (node);
+ }
+ return true;
+}
+
+bool
+rtems_rtl_match_name (rtems_rtl_obj_t* obj, const char* name)
+{
+ const char* n1 = obj->oname;
+ while ((*n1 != '\0') && (*n1 != '\n') && (*n1 != '/') &&
+ (*name != '\0') && (*name != '/') && (*n1 == *name))
+ {
+ ++n1;
+ ++name;
+ }
+ if (((*n1 == '\0') || (*n1 == '\n') || (*n1 == '/')) &&
+ ((*name == '\0') || (*name == '/')))
+ return true;
+ return false;
+}
+
+bool
+rtems_rtl_obj_find_file (rtems_rtl_obj_t* obj, const char* name)
+{
+ const char* pname;
+ rtems_rtl_data_t* rtl;
+
+ /*
+ * Parse the name. The object descriptor will have the archive name and/or
+ * object name fields filled in. A find of the file will result in the file
+ * name (fname) field pointing to the actual file if present on the file
+ * system.
+ */
+ if (!rtems_rtl_obj_parse_name (obj, name))
+ return false;
+
+ /*
+ * If the archive field (aname) is set we use that name else we use the
+ * object field (oname). If selected name is absolute we just point the aname
+ * field to the fname field to that name. If the field is relative we search
+ * the paths set in the RTL for the file.
+ */
+ if (rtems_rtl_obj_aname_valid (obj))
+ pname = rtems_rtl_obj_aname (obj);
+ else
+ pname = rtems_rtl_obj_oname (obj);
+
+ rtl = rtems_rtl_lock ();
+
+ if (!rtems_rtl_find_file (pname, rtl->paths, &obj->fname, &obj->fsize))
+ {
+ rtems_rtl_set_error (ENOENT, "file not found");
+ rtems_rtl_unlock ();
+ return false;
+ }
+
+ rtems_rtl_unlock ();
+
+ return true;
+}
+
+bool
+rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj,
+ int section,
+ const char* name,
+ size_t size,
+ off_t offset,
+ uint32_t alignment,
+ int link,
+ int info,
+ uint32_t flags)
+{
+ rtems_rtl_obj_sect_t* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ sizeof (rtems_rtl_obj_sect_t), true);
+ if (!sect)
+ {
+ rtems_rtl_set_error (ENOMEM, "adding allocated section");
+ return false;
+ }
+ sect->section = section;
+ sect->name = rtems_rtl_strdup (name);
+ sect->size = size;
+ sect->offset = offset;
+ sect->alignment = alignment;
+ sect->link = link;
+ sect->info = info;
+ sect->flags = flags;
+ sect->base = NULL;
+ rtems_chain_append (&obj->sections, §->node);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION))
+ printf ("rtl: sect: %-2d: %s\n", section, name);
+
+ return true;
+}
+
+void
+rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj)
+{
+ rtems_chain_node* node = rtems_chain_first (&obj->sections);
+ while (!rtems_chain_is_tail (&obj->sections, node))
+ {
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ rtems_chain_node* next_node = rtems_chain_next (node);
+ rtems_chain_extract (node);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) sect->name);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, sect);
+ node = next_node;
+ }
+}
+
+/**
+ * Section finder iterator data.
+ */
+typedef struct
+{
+ rtems_rtl_obj_sect_t* sect; /**< The matching section. */
+ const char* name; /**< The name to match. */
+ int index; /**< The index to match. */
+} rtems_rtl_obj_sect_finder_t;
+
+static bool
+rtems_rtl_obj_sect_match_name (rtems_chain_node* node, void* data)
+{
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ rtems_rtl_obj_sect_finder_t* match = data;
+ if (strcmp (sect->name, match->name) == 0)
+ {
+ match->sect = sect;
+ return false;
+ }
+ return true;
+}
+
+rtems_rtl_obj_sect_t*
+rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, const char* name)
+{
+ rtems_rtl_obj_sect_finder_t match;
+ match.sect = NULL;
+ match.name = name;
+ rtems_rtl_chain_iterate (&obj->sections,
+ rtems_rtl_obj_sect_match_name,
+ &match);
+ return match.sect;
+}
+
+static bool
+rtems_rtl_obj_sect_match_index (rtems_chain_node* node, void* data)
+{
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ rtems_rtl_obj_sect_finder_t* match = data;
+ if (sect->section == match->index)
+ {
+ match->sect = sect;
+ return false;
+ }
+ return true;
+}
+
+rtems_rtl_obj_sect_t*
+rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj, int index)
+{
+ rtems_rtl_obj_sect_finder_t match;
+ match.sect = NULL;
+ match.index = index;
+ rtems_rtl_chain_iterate (&obj->sections,
+ rtems_rtl_obj_sect_match_index,
+ &match);
+ return match.sect;
+}
+
+size_t
+rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_TEXT);
+}
+
+uint32_t
+rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_TEXT);
+}
+
+size_t
+rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_CONST);
+}
+
+uint32_t
+rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_CONST);
+}
+
+size_t
+rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_DATA);
+}
+
+uint32_t
+rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_DATA);
+}
+
+size_t
+rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS);
+}
+
+uint32_t
+rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_BSS);
+}
+
+bool
+rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
+{
+ uint32_t mask = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_RELA;
+ return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
+}
+
+bool
+rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
+{
+ uint32_t mask = RTEMS_RTL_OBJ_SECT_SYM;
+ return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
+}
+
+static size_t
+rtems_rtl_obj_sections_loader (uint32_t mask,
+ rtems_rtl_obj_t* obj,
+ int fd,
+ uint8_t* base,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
+{
+ rtems_chain_control* sections = &obj->sections;
+ rtems_chain_node* node = rtems_chain_first (sections);
+ size_t base_offset = 0;
+ bool first = true;
+ while (!rtems_chain_is_tail (sections, node))
+ {
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+
+ if ((sect->size != 0) && ((sect->flags & mask) != 0))
+ {
+ if (!first)
+ base_offset = rtems_rtl_sect_align (base_offset, sect->alignment);
+
+ sect->base = base + base_offset;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+ printf ("rtl: loading: %s -> %8p (%zi)\n",
+ sect->name, sect->base, sect->size);
+
+ if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
+ {
+ if (!handler (obj, fd, sect, data))
+ {
+ sect->base = 0;
+ return false;
+ }
+ }
+ else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
+ {
+ memset (base + base_offset, 0, sect->size);
+ }
+ else
+ {
+ sect->base = 0;
+ rtems_rtl_set_error (errno, "section has no load op");
+ return false;
+ }
+
+ base_offset += sect->size;
+ first = false;
+ }
+
+ node = rtems_chain_next (node);
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data)
+{
+ size_t text_size;
+ size_t const_size;
+ size_t data_size;
+ size_t bss_size;
+
+ text_size = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj);
+ const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_data_alignment (obj);
+ data_size = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj);
+ bss_size = rtems_rtl_obj_bss_size (obj);
+
+ /*
+ * Let the allocator manage the actual allocation. The user can use the
+ * standard heap or provide a specific allocator with memory protection.
+ */
+ if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size,
+ &obj->const_base, const_size,
+ &obj->data_base, data_size,
+ &obj->bss_base, bss_size))
+ {
+ obj->exec_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory to load obj");
+ return false;
+ }
+
+ obj->exec_size = text_size + const_size + data_size + bss_size;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+ {
+ printf ("rtl: load sect: text - b:%p s:%zi a:%" PRIu32 "\n",
+ obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj));
+ printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n",
+ obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj));
+ printf ("rtl: load sect: data - b:%p s:%zi a:%" PRIu32 "\n",
+ obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj));
+ printf ("rtl: load sect: bss - b:%p s:%zi a:%" PRIu32 "\n",
+ obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj));
+ }
+
+ /*
+ * Load all text then data then bss sections in seperate operations so each
+ * type of section is grouped together.
+ */
+ if (!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_TEXT,
+ obj, fd, obj->text_base, handler, data) ||
+ !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_CONST,
+ obj, fd, obj->const_base, handler, data) ||
+ !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_DATA,
+ obj, fd, obj->data_base, handler, data) ||
+ !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_BSS,
+ obj, fd, obj->bss_base, handler, data))
+ {
+ rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base,
+ &obj->data_base, &obj->bss_base);
+ obj->exec_size = 0;
+ return false;
+ }
+
+ return true;
+}
+
+static void
+rtems_rtl_obj_run_cdtors (rtems_rtl_obj_t* obj, uint32_t mask)
+{
+ rtems_chain_node* node = rtems_chain_first (&obj->sections);
+ while (!rtems_chain_is_tail (&obj->sections, node))
+ {
+ rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
+ if ((sect->flags & mask) == mask)
+ {
+ rtems_rtl_cdtor_t* handler;
+ size_t handlers = sect->size / sizeof (rtems_rtl_cdtor_t);
+ int c;
+ for (c = 0, handler = sect->base; c < handlers; ++c)
+ if (*handler)
+ (*handler) ();
+ }
+ node = rtems_chain_next (node);
+ }
+}
+
+void
+rtems_rtl_obj_run_ctors (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_CTOR);
+}
+
+void
+rtems_rtl_obj_run_dtors (rtems_rtl_obj_t* obj)
+{
+ return rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_DTOR);
+}
+
+/**
+ * Find a module in an archive returning the offset in the archive in the
+ * object descriptor.
+ */
+static bool
+rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd)
+{
+#define RTEMS_RTL_AR_IDENT "!<arch>\n"
+#define RTEMS_RTL_AR_IDENT_SIZE (sizeof (RTEMS_RTL_AR_IDENT) - 1)
+#define RTEMS_RTL_AR_FHDR_BASE RTEMS_RTL_AR_IDENT_SIZE
+#define RTEMS_RTL_AR_FNAME (0)
+#define RTEMS_RTL_AR_FNAME_SIZE (16)
+#define RTEMS_RTL_AR_SIZE (48)
+#define RTEMS_RTL_AR_SIZE_SIZE (10)
+#define RTEMS_RTL_AR_MAGIC (58)
+#define RTEMS_RTL_AR_MAGIC_SIZE (2)
+#define RTEMS_RTL_AR_FHDR_SIZE (60)
+
+ size_t fsize = obj->fsize;
+ off_t extended_file_names;
+ uint8_t header[RTEMS_RTL_AR_FHDR_SIZE];
+ bool scanning;
+
+ if (read (fd, &header[0], RTEMS_RTL_AR_IDENT_SIZE) != RTEMS_RTL_AR_IDENT_SIZE)
+ {
+ rtems_rtl_set_error (errno, "reading archive identifer");
+ return false;
+ }
+
+ if (memcmp (header, RTEMS_RTL_AR_IDENT, RTEMS_RTL_AR_IDENT_SIZE) != 0)
+ {
+ rtems_rtl_set_error (EINVAL, "invalid archive identifer");
+ return false;
+ }
+
+ /*
+ * Seek to the current offset in the archive and if we have a valid archive
+ * file header present check the file name for a match with the oname field
+ * of the object descriptor. If the archive header is not valid and it is the
+ * first pass reset the offset and start the search again in case the offset
+ * provided is not valid any more.
+ *
+ * The archive can have a symbol table at the start. Ignore it. A symbol
+ * table has the file name '/'.
+ *
+ * The archive can also have the GNU extended file name table. This
+ * complicates the processing. If the object's file name starts with '/' the
+ * remainder of the file name is an offset into the extended file name
+ * table. To find the extended file name table we need to scan from start of
+ * the archive for a file name of '//'. Once found we remeber the table's
+ * start and can direct seek to file name location. In other words the scan
+ * only happens once.
+ *
+ * If the name had the offset encoded we go straight to that location.
+ */
+
+ if (obj->ooffset != 0)
+ scanning = false;
+ else
+ {
+ scanning = true;
+ obj->ooffset = RTEMS_RTL_AR_FHDR_BASE;
+ }
+
+ extended_file_names = 0;
+
+ while (obj->ooffset < fsize)
+ {
+ /*
+ * Clean up any existing data.
+ */
+ memset (header, 0, sizeof (header));
+
+ if (!rtems_rtl_seek_read (fd, obj->ooffset, RTEMS_RTL_AR_FHDR_SIZE, &header[0]))
+ {
+ rtems_rtl_set_error (errno, "seek/read archive file header");
+ obj->ooffset = 0;
+ obj->fsize = 0;
+ return false;
+ }
+
+ if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) ||
+ (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a))
+ {
+ if (scanning)
+ {
+ rtems_rtl_set_error (EINVAL, "invalid archive file header");
+ obj->ooffset = 0;
+ obj->fsize = 0;
+ return false;
+ }
+
+ scanning = true;
+ obj->ooffset = RTEMS_RTL_AR_FHDR_BASE;
+ continue;
+ }
+
+ /*
+ * The archive header is always aligned to an even address.
+ */
+ obj->fsize = (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE],
+ RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1;
+
+ /*
+ * Check for the GNU extensions.
+ */
+ if (header[0] == '/')
+ {
+ off_t extended_off;
+
+ switch (header[1])
+ {
+ case ' ':
+ /*
+ * Symbols table. Ignore the table.
+ */
+ break;
+ case '/':
+ /*
+ * Extended file names table. Remember.
+ */
+ extended_file_names = obj->ooffset + RTEMS_RTL_AR_FHDR_SIZE;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /*
+ * Offset into the extended file name table. If we do not have the
+ * offset to the extended file name table find it.
+ */
+ extended_off =
+ rtems_rtl_scan_decimal (&header[1], RTEMS_RTL_AR_FNAME_SIZE);
+
+ if (extended_file_names == 0)
+ {
+ off_t off = obj->ooffset;
+ while (extended_file_names == 0)
+ {
+ off_t esize =
+ (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE],
+ RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1;
+ off += esize + RTEMS_RTL_AR_FHDR_SIZE;
+
+ if (!rtems_rtl_seek_read (fd, off,
+ RTEMS_RTL_AR_FHDR_SIZE, &header[0]))
+ {
+ rtems_rtl_set_error (errno,
+ "seeking/reading archive ext file name header");
+ obj->ooffset = 0;
+ obj->fsize = 0;
+ return false;
+ }
+
+ if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) ||
+ (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a))
+ {
+ rtems_rtl_set_error (errno, "invalid archive file header");
+ obj->ooffset = 0;
+ obj->fsize = 0;
+ return false;
+ }
+
+ if ((header[0] == '/') && (header[1] == '/'))
+ {
+ extended_file_names = off + RTEMS_RTL_AR_FHDR_SIZE;
+ break;
+ }
+ }
+ }
+
+ if (extended_file_names)
+ {
+ /*
+ * We know the offset in the archive to the extended file. Read the
+ * name from the table and compare with the name we are after.
+ */
+#define RTEMS_RTL_MAX_FILE_SIZE (256)
+ char name[RTEMS_RTL_MAX_FILE_SIZE];
+
+ if (!rtems_rtl_seek_read (fd, extended_file_names + extended_off,
+ RTEMS_RTL_MAX_FILE_SIZE, (uint8_t*) &name[0]))
+ {
+ rtems_rtl_set_error (errno,
+ "invalid archive ext file seek/read");
+ obj->ooffset = 0;
+ obj->fsize = 0;
+ return false;
+ }
+
+ if (rtems_rtl_match_name (obj, name))
+ {
+ obj->ooffset += RTEMS_RTL_AR_FHDR_SIZE;
+ return true;
+ }
+ }
+ break;
+ default:
+ /*
+ * Ignore the file because we do not know what it it.
+ */
+ break;
+ }
+ }
+ else
+ {
+ if (rtems_rtl_match_name (obj, (const char*) &header[RTEMS_RTL_AR_FNAME]))
+ {
+ obj->ooffset += RTEMS_RTL_AR_FHDR_SIZE;
+ return true;
+ }
+ }
+
+ obj->ooffset += obj->fsize + RTEMS_RTL_AR_FHDR_SIZE;
+ }
+
+ rtems_rtl_set_error (ENOENT, "object file not found");
+ obj->ooffset = 0;
+ obj->fsize = 0;
+ return false;
+}
+
+bool
+rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd)
+{
+ int l;
+
+ for (l = 0; l < (sizeof (loaders) / sizeof (rtems_rtl_loader_table_t)); ++l)
+ {
+ if (loaders[l].check (obj, fd))
+ return loaders[l].load (obj, fd);
+ }
+
+ rtems_rtl_set_error (ENOENT, "no format loader found");
+ return false;
+}
+
+bool
+rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
+{
+ int fd;
+
+ if (!rtems_rtl_obj_fname_valid (obj))
+ {
+ rtems_rtl_set_error (ENOMEM, "invalid object file name path");
+ return false;
+ }
+
+ fd = open (rtems_rtl_obj_fname (obj), O_RDONLY);
+ if (fd < 0)
+ {
+ rtems_rtl_set_error (ENOMEM, "opening for object file");
+ return false;
+ }
+
+ /*
+ * Find the object file in the archive if it is an archive that
+ * has been opened.
+ */
+ if (rtems_rtl_obj_aname_valid (obj))
+ {
+ if (!rtems_rtl_obj_archive_find (obj, fd))
+ {
+ rtems_rtl_obj_caches_flush ();
+ close (fd);
+ return false;
+ }
+ }
+
+ /*
+ * Call the format specific loader. Currently this is a call to the ELF
+ * loader. This call could be changed to allow probes then calls if more than
+ * one format is supported.
+ */
+ if (!rtems_rtl_obj_file_load (obj, fd))
+ {
+ rtems_rtl_obj_caches_flush ();
+ close (fd);
+ return false;
+ }
+
+ if (!_rtld_linkmap_add (obj)) /* For GDB */
+ {
+ close (fd);
+ return false;
+ }
+
+ rtems_rtl_obj_caches_flush ();
+
+ close (fd);
+
+ return true;
+}
+
+bool
+rtems_rtl_obj_unload (rtems_rtl_obj_t* obj)
+{
+ _rtld_linkmap_delete(obj);
+ rtems_rtl_symbol_obj_erase (obj);
+ return rtems_rtl_obj_free (obj);
+}
diff --git a/cpukit/libdl/rtl-obj.h b/cpukit/libdl/rtl-obj.h
new file mode 100644
index 0000000..0550723
--- /dev/null
+++ b/cpukit/libdl/rtl-obj.h
@@ -0,0 +1,580 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object Support.
+ */
+
+#if !defined (_RTEMS_RTL_OBJ_H_)
+#define _RTEMS_RTL_OBJ_H_
+
+#include <rtems.h>
+#include <rtems/chain.h>
+#include <rtems/rtl/rtl-sym.h>
+#include <rtems/rtl/rtl-unresolved.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Loader format flags.
+ */
+#define RTEMS_RTL_FMT_ELF (1 << 0)
+#define RTEMS_RTL_FMT_COMP (1 << 1)
+#define RTEMS_RTL_FMT_PRIVATE (1 << 16)
+
+/**
+ * Loader format definition.
+ */
+typedef struct rtems_rtl_loader_format_s
+{
+ /**
+ * The format label. This can be used to determine and manage
+ * specific formats.
+ */
+ const char* label;
+
+ /**
+ * The format flags.
+ */
+ uint32_t flags;
+} rtems_rtl_loader_format_t;
+
+/**
+ * The type of the format loader check handler. This handler checks the format
+ * and if it is detected as suitable it returns true.
+ */
+typedef bool (*rtems_rtl_loader_check) (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The type of the format loader handler. This handler loads the specific
+ * format.
+ */
+typedef bool (*rtems_rtl_loader_load) (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The type of the format loader handler. This handler loads the specific
+ * format.
+ */
+typedef rtems_rtl_loader_format_t* (*rtems_rtl_loader_sig) (void);
+
+/**
+ * Table for supported loadable formats.
+ */
+typedef struct rtems_rtl_loader_table_s
+{
+ rtems_rtl_loader_check check; /**< The check handler. */
+ rtems_rtl_loader_load load; /**< The loader. */
+ rtems_rtl_loader_sig signature; /**< The loader's signature. */
+} rtems_rtl_loader_table_t;
+
+/**
+ * Flags for the various section types.
+ */
+#define RTEMS_RTL_OBJ_SECT_TEXT (1 << 0) /**< Section holds program text. */
+#define RTEMS_RTL_OBJ_SECT_CONST (1 << 1) /**< Section holds program text. */
+#define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */
+#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */
+#define RTEMS_RTL_OBJ_SECT_REL (1 << 4) /**< Section holds relocation records. */
+#define RTEMS_RTL_OBJ_SECT_RELA (1 << 5) /**< Section holds relocation addend
+ * records. */
+#define RTEMS_RTL_OBJ_SECT_SYM (1 << 6) /**< Section holds symbols. */
+#define RTEMS_RTL_OBJ_SECT_STR (1 << 7) /**< Section holds strings. */
+#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 8) /**< Section allocates runtime memory. */
+#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 9) /**< Section is loaded from object file. */
+#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 10) /**< Section is writable, ie data. */
+#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 11) /**< Section is executable. */
+#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 12) /**< Section is preset to zero. */
+#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 13) /**< Section contains constructors. */
+#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 14) /**< Section contains destructors. */
+
+/**
+ * An object file is made up of sections and the can be more than
+ * one of a specific type of sections. All sections and grouped
+ * together in memory.
+ */
+struct rtems_rtl_obj_sect_s
+{
+ rtems_chain_node node; /**< The node's link in the chain. */
+ int section; /**< The section number. */
+ const char* name; /**< The section's name. */
+ size_t size; /**< The size of the section in memory. */
+ off_t offset; /**< Offset into the object file. Relative to
+ * the start of the object file. */
+ uint32_t alignment; /**< Alignment of this section. */
+ int link; /**< Section link field. */
+ int info; /**< Secfion info field. */
+ uint32_t flags; /**< The section's flags. */
+ void* base; /**< The base address of the section in
+ * memory. */
+};
+
+/**
+ * Object file descriptor flags.
+ */
+#define RTEMS_RTL_OBJ_LOCKED (1 << 0) /**< Lock the object file so it cannot
+ * be unloaded. */
+#define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved
+ * external symbols. */
+
+/**
+ * RTL Object. There is one for each object module loaded plus one for the base
+ * kernel image.
+ */
+struct rtems_rtl_obj_s
+{
+ rtems_chain_node link; /**< The node's link in the chain. */
+ uint32_t flags; /**< The status of the object file. */
+ uint32_t users; /**< References to the object file. */
+ const char* fname; /**< The file name for the object. */
+ const char* oname; /**< The object file name. Can be
+ * relative. */
+ const char* aname; /**< The archive name containing the
+ * object. NULL means the object is not
+ * in a lib */
+ off_t ooffset; /**< The object offset in the archive. */
+ size_t fsize; /**< Size of the object file. */
+ rtems_chain_control sections; /**< The sections of interest in the
+ * object file. */
+ rtems_rtl_obj_sym_t* global_table; /**< Global symbol table. */
+ size_t global_syms; /**< Global symbol count. */
+ size_t global_size; /**< Global symbol memory usage. */
+ uint32_t unresolved; /**< The number of unresolved relocations. */
+ void* text_base; /**< The base address of the text section
+ * in memory. */
+ void* const_base; /**< The base address of the const section
+ * in memory. */
+ void* data_base; /**< The base address of the data section
+ * in memory. */
+ void* bss_base; /**< The base address of the bss section
+ * in memory. */
+ size_t bss_size; /**< The size of the bss section. */
+ size_t exec_size; /**< The amount of executable memory
+ * allocated */
+ void* entry; /**< The entry point of the module. */
+ uint32_t checksum; /**< The checksum of the text sections. A
+ * zero means do not checksum. */
+ void* detail; /**< The file details. It contains the elf file
+ * detail, mainly including elf file name,
+ * section offset, section size, which
+ * elf this section belongs to.*/
+ uint32_t* sec_num; /**< The sec nums of each obj. */
+ uint32_t obj_num; /**< The count of elf files in an rtl obj. */
+ struct link_map* linkmap; /**< For GDB. */
+};
+
+/**
+ * A section handler is called once for each section that needs to be
+ * processed by this handler.
+ *
+ * @param obj The object file's descriptor the section belongs too.
+ * @param fd The file descriptor of the object file beling loaded.
+ * @param sect The section the handler is being invoked to handle.
+ * @param data A user supplied data variable.
+ * @retval true The operation was successful.
+ * @retval false The operation failed and the RTL has been set.
+ */
+typedef bool (*rtems_rtl_obj_sect_handler_t)(rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data);
+
+/**
+ * Get the file name.
+ *
+ * @param obj The object file.
+ * @return const char* The string.
+ */
+static inline const char* rtems_rtl_obj_fname (const rtems_rtl_obj_t* obj)
+{
+ return obj->fname;
+}
+
+/**
+ * Is the file name valid ?
+ *
+ * @param obj The object file.
+ * @return bool There is a file name
+ */
+static inline bool rtems_rtl_obj_fname_valid (const rtems_rtl_obj_t* obj)
+{
+ return obj->fname;
+}
+
+/**
+ * Get the object name.
+ *
+ * @param obj The object file.
+ * @return const char* The string.
+ */
+static inline const char* rtems_rtl_obj_oname (const rtems_rtl_obj_t* obj)
+{
+ return obj->oname;
+}
+
+/**
+ * Is the object name valid ?
+ *
+ * @param obj The object file.
+ * @return bool There is an object name
+ */
+static inline bool rtems_rtl_obj_oname_valid (const rtems_rtl_obj_t* obj)
+{
+ return obj->oname;
+}
+
+/**
+ * Get the archive name.
+ *
+ * @param obj The object file.
+ * @return const char* The string.
+ */
+static inline const char* rtems_rtl_obj_aname (const rtems_rtl_obj_t* obj)
+{
+ return obj->aname;
+}
+
+/**
+ * Is the archive name valid ?
+ *
+ * @param obj The object file.
+ * @return bool There is an archive name
+ */
+static inline bool rtems_rtl_obj_aname_valid (const rtems_rtl_obj_t* obj)
+{
+ return obj->aname;
+}
+
+/**
+ * Allocate an object structure on the heap.
+ *
+ * @retval NULL No memory for the object.
+ */
+rtems_rtl_obj_t* rtems_rtl_obj_alloc (void);
+
+/**
+ * Free the object structure and related resources.
+ *
+ * @param obj The object file's descriptor to free.
+ * @retval false The object has dependences.
+ * @retval true The object has been freed.
+ */
+bool rtems_rtl_obj_free (rtems_rtl_obj_t* obj);
+
+/**
+ * Does the object file have unresolved external references ? If it does the
+ * results of executing code is unpredictable.
+ *
+ * @param obj The object file's descriptor.
+ * @retval true The object file has unresolved externals.
+ * @retval false The object file has all external references resolved.
+ */
+bool rtems_rtl_obj_unresolved (rtems_rtl_obj_t* obj);
+
+/**
+ * Parses a filename and returns newly allocated strings with the archive name,
+ * object name, and the object's offset
+ *
+ * @param name The filename of the object
+ * @param aname Address of a string pointer that holds the archive name
+ * @param oname Address of a string pointer that holds the object name
+ * @param ooffset Address of an int that holds the object offset
+ * @retval true The parsing was successful
+ * @retval false The parsing was unsuccessful
+ */
+bool rtems_rtl_parse_name (const char* name,
+ const char** aname,
+ const char** oname,
+ off_t* ooffset);
+
+/**
+ * Load the object file.
+ *
+ * @param obj The object file's descriptor.
+ * @param fd The file descriptor.
+ * @param load_syms Load symbols.
+ * @param load_dep Load dependent object files.
+ * @retval true The load was successful.
+ * @retval false The load failed. The RTL error has been set.
+ */
+bool rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * Check of the name matches the object file's object name.
+ *
+ * @param obj The object file's descriptor.
+ * @param name The name to match.
+ */
+bool rtems_rtl_match_name (rtems_rtl_obj_t* obj, const char* name);
+
+/**
+ * Find an object file on disk that matches the name. The object descriptor is
+ * fill in with the various parts of a name. A name can have archive, object
+ * file and offset components. The search path in the RTL is searched.
+ *
+ * @param obj The object file's descriptor.
+ * @param name The name to locate on disk.
+ * @retval true The file has been found.
+ * @retval false The file could not be located. The RTL error has been set.
+ */
+bool rtems_rtl_obj_find_file (rtems_rtl_obj_t* obj, const char* name);
+
+/**
+ * Add a section to the object descriptor.
+ *
+ * @param obj The object file's descriptor.
+ * @param section The section's index number.
+ * @param name The name of the section.
+ * @param size The size of the section in memory.
+ * @param offset The offset of the section in the object file.
+ * @param alignment The alignment of the section in memory.
+ * @param link The section's link field (from the ELF format).
+ * @param info The section's info field (from the ELF format).
+ * @param flags The section's flags.
+ * @retval true The section has been added.
+ * @retval false The section has not been added. See the RTL error.
+ */
+bool rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj,
+ int section,
+ const char* name,
+ size_t size,
+ off_t offset,
+ uint32_t alignment,
+ int link,
+ int info,
+ uint32_t flags);
+
+/**
+ * Erase the object file descriptor's sections.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj);
+
+/**
+ * Find the section given a name.
+ *
+ * @param obj The object file's descriptor.
+ * @param name The name of the section to find.
+ * @retval NULL The section was not found.
+ * @return rtems_rtl_obj_sect_t* The named section.
+ */
+rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj,
+ const char* name);
+
+/**
+ * Find a section given a section's index number.
+ *
+ * @param obj The object file's descriptor.
+ * @param index The section's index to find.
+ * @retval NULL The section was not found.
+ * @return rtems_rtl_obj_sect_t* The found section.
+ */
+rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj,
+ int index);
+
+/**
+ * The text size of the object file. Only use once all the sections has been
+ * added. It includes alignments between sections that are part of the object's
+ * text area. The consts sections are included in this section.
+ *
+ * @param obj The object file's descriptor.
+ * @return size_t The size of the text area of the object file.
+ */
+size_t rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj);
+
+/**
+ * The text section alignment of the object file. Only use once all the
+ * sections has been added. The section alignment is the alignment of the first
+ * text type section loaded the text section.
+ *
+ * You can assume the alignment is a positive integral power of 2 if not 0 or
+ * 1. If 0 or 1 then there is no alignment.
+ *
+ * @param obj The object file's descriptor.
+ * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
+ */
+uint32_t rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj);
+
+/**
+ * The const size of the object file. Only use once all the sections has been
+ * added. It includes alignments between sections that are part of the object's
+ * const area. The consts sections are included in this section.
+ *
+ * @param obj The object file's descriptor.
+ * @return size_t The size of the const area of the object file.
+ */
+size_t rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj);
+
+/**
+ * The const section alignment of the object file. Only use once all the
+ * sections has been added. The section alignment is the alignment of the first
+ * const type section loaded the const section.
+ *
+ * You can assume the alignment is a positive integral power of 2 if not 0 or
+ * 1. If 0 or 1 then there is no alignment.
+ *
+ * @param obj The object file's descriptor.
+ * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
+ */
+uint32_t rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj);
+
+/**
+ * The data size of the object file. Only use once all the sections has been
+ * added. It includes alignments between sections that are part of the object's
+ * data area.
+ *
+ * @param obj The object file's descriptor.
+ * @return size_t The size of the data area of the object file.
+ */
+size_t rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj);
+
+/**
+ * The data section alignment of the object file. Only use once all the
+ * sections has been added. The section alignment is the alignment of the first
+ * data type section loaded the data section.
+ *
+ * You can assume the alignment is a positive integral power of 2 if not 0 or
+ * 1. If 0 or 1 then there is no alignment.
+ *
+ * @param obj The object file's descriptor.
+ * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
+ */
+uint32_t rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj);
+
+/**
+ * The bss size of the object file. Only use once all the sections has been
+ * added. It includes alignments between sections that are part of the object's
+ * bss area.
+ *
+ * @param obj The object file's descriptor.
+ * @return size_t The size of the bss area of the object file.
+ */
+size_t rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj);
+
+/**
+ * The bss section alignment of the object file. Only use once all the
+ * sections has been added. The section alignment is the alignment of the first
+ * bss type section loaded the bss section.
+ *
+ * You can assume the alignment is a positive integral power of 2 if not 0 or
+ * 1. If 0 or 1 then there is no alignment.
+ *
+ * @param obj The object file's descriptor.
+ * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
+ */
+uint32_t rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj);
+
+/**
+ * Relocate the object file. The object file's section are parsed for any
+ * relocation type sections.
+ *
+ * @param obj The object file's descriptor.
+ * @param fd The object file's file descriptor.
+ * @param handler The object file's format specific relocation handler.
+ * @param data User specific data handle.
+ * @retval true The object file was relocated.
+ * @retval false The relocation failed. The RTL error is set.
+ */
+bool rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data);
+
+/**
+ * Relocate an object file's unresolved reference.
+ *
+ * @param rec The unresolved relocation record.
+ * @param sym The unresolved relocation's referenced symbol.
+ * @retval true The object file record was relocated.
+ * @retval false The relocation failed. The RTL error is set.
+ */
+bool rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc_t* reloc,
+ rtems_rtl_obj_sym_t* sym);
+
+/**
+ * Load the symbols from the object file. Only the exported or public symbols
+ * are read into memory and held in the global symbol table.
+ *
+ * @param obj The object file's descriptor.
+ * @param fd The object file's file descriptor.
+ * @param handler The object file's format specific symbol handler.
+ * @param data User specific data handle.
+ * @retval true The object file's symbol where loaded.
+ * @retval false The symbol loading failed. The RTL error is set.
+ */
+bool rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data);
+
+/**
+ * Load the sections that have been allocated memory in the target. The bss
+ * type section does not load any data, it is set to 0. The text and data
+ * sections read the detault data from the object file into the target memory.
+ *
+ * @param obj The object file's descriptor.
+ * @param fd The object file's file descriptor.
+ * @param handler The object file's format specific load handler.
+ * @param data User specific data handle.
+ * @retval true The object has been sucessfully loaded.
+ * @retval false The load failed. The RTL error has been set.
+ */
+bool rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler_t handler,
+ void* data);
+
+/**
+ * Invoke the constructors the object has. Constructors are a table of pointers
+ * to "void (*)(void);" where NULL pointers are skipped. The table's size is
+ * taken from the section's size. The objet ELF specific code is responisble
+ * for flagging which sections contain constructors.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_run_ctors (rtems_rtl_obj_t* obj);
+
+/**
+ * Invoke the destructors the object has. Destructors are a table of pointers
+ * to "void (*)(void);" where NULL pointers are skipped. The table's size is
+ * taken from the section's size. The objet ELF specific code is responisble
+ * for flagging which sections contain destructors.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_run_dtors (rtems_rtl_obj_t* obj);
+
+/**
+ * Load the object file, reading all sections into memory, symbols and
+ * performing any relocation fixups.
+ *
+ * @param obj The object file's descriptor.
+ * @retval true The object file has been loaded.
+ * @retval false The load failed. The RTL error has been set.
+ */
+bool rtems_rtl_obj_load (rtems_rtl_obj_t* obj);
+
+/**
+ * Unload the object file, erasing all symbols and releasing all memory.
+ *
+ * @param obj The object file's descriptor.
+ * @retval true The object file has been unloaded.
+ * @retval false The unload failed. The RTL error has been set.
+ */
+bool rtems_rtl_obj_unload (rtems_rtl_obj_t* obj);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-rap.c b/cpukit/libdl/rtl-rap.c
new file mode 100644
index 0000000..ad05b24
--- /dev/null
+++ b/cpukit/libdl/rtl-rap.c
@@ -0,0 +1,980 @@
+/*
+ * COPYRIGHT (c) 2012-2013 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor
+ *
+ * This is the RAP format loader support..
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-obj-comp.h"
+#include "rtl-rap.h"
+#include "rtl-trace.h"
+#include "rtl-unresolved.h"
+
+/**
+ * The offsets in the unresolved array.
+ */
+#define REL_R_OFFSET (0)
+#define REL_R_INFO (1)
+#define REL_R_ADDEND (2)
+
+/**
+ * The ELF format signature.
+ */
+static rtems_rtl_loader_format_t rap_sig =
+{
+ .label = "RAP",
+ .flags = RTEMS_RTL_FMT_COMP
+};
+
+/**
+ * The section definitions found in a RAP file.
+ */
+typedef struct rtems_rtl_rap_sectdef_s
+{
+ const char* name; /**< Name of the section. */
+ const uint32_t flags; /**< Section flags. */
+} rtems_rtl_rap_sectdef_t;
+
+/**
+ * The section indexes. These are fixed.
+ */
+#define RTEMS_RTL_RAP_TEXT_SEC (0)
+#define RTEMS_RTL_RAP_CONST_SEC (1)
+#define RTEMS_RTL_RAP_CTOR_SEC (2)
+#define RTEMS_RTL_RAP_DTOR_SEC (3)
+#define RTEMS_RTL_RAP_DATA_SEC (4)
+#define RTEMS_RTL_RAP_BSS_SEC (5)
+#define RTEMS_RTL_RAP_SECS (6)
+
+/**
+ * The sections as loaded from a RAP file.
+ */
+static const rtems_rtl_rap_sectdef_t rap_sections[RTEMS_RTL_RAP_SECS] =
+{
+ { ".text", RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD },
+ { ".const", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD },
+ { ".ctor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CTOR },
+ { ".dtor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DTOR },
+ { ".data", RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD },
+ { ".bss", RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO }
+};
+
+/**
+ * The section definitions found in a RAP file.
+ */
+typedef struct rtems_rtl_rap_section_s
+{
+ uint32_t size; /**< The size of the section. */
+ uint32_t alignment; /**< The alignment of the section. */
+} rtems_rtl_rap_section_t;
+
+/**
+ * The RAP loader.
+ */
+typedef struct rtems_rtl_rap_s
+{
+ rtems_rtl_obj_cache_t* file; /**< The file cache for the RAP file. */
+ rtems_rtl_obj_comp_t* decomp; /**< The decompression streamer. */
+ uint32_t length; /**< The file length. */
+ uint32_t version; /**< The RAP file version. */
+ uint32_t compression; /**< The type of compression. */
+ uint32_t checksum; /**< The checksum. */
+ uint32_t machinetype; /**< The ELF machine type. */
+ uint32_t datatype; /**< The ELF data type. */
+ uint32_t class; /**< The ELF class. */
+ uint32_t init; /**< The initialisation strtab offset. */
+ uint32_t fini; /**< The finish strtab offset. */
+ rtems_rtl_rap_section_t secs[RTEMS_RTL_RAP_SECS]; /**< The sections. */
+ uint32_t symtab_size; /**< The symbol table size. */
+ char* strtab; /**< The string table. */
+ uint32_t strtab_size; /**< The string table size. */
+ uint32_t relocs_size; /**< The relocation table size. */
+ uint32_t symbols; /**< The number of symbols. */
+ uint32_t strtable_size;/**< The size of section names and obj names. */
+ uint32_t rpathlen; /**< The length of rpath. */
+ char* strtable; /**< The detail string which resides in obj detail. */
+} rtems_rtl_rap_t;
+
+/**
+ * Check the machine type.
+ */
+static bool
+rtems_rtl_rap_machine_check (uint32_t machinetype)
+{
+ /*
+ * This code is determined by the machine headers.
+ */
+ switch (machinetype)
+ {
+ ELFDEFNNAME (MACHDEP_ID_CASES)
+ default:
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Check the data type.
+ */
+static bool
+rtems_rtl_rap_datatype_check (uint32_t datatype)
+{
+ /*
+ * This code is determined by the machine headers.
+ */
+ if (datatype != ELFDEFNNAME (MACHDEP_ENDIANNESS))
+ return false;
+ return true;
+}
+
+/**
+ * Check the class of executable.
+ */
+static bool
+rtems_rtl_rap_class_check (uint32_t class)
+{
+ /*
+ * This code is determined by the machine headers.
+ */
+ switch (class)
+ {
+ case ELFCLASS32:
+ if (ARCH_ELFSIZE == 32)
+ return true;
+ break;
+ case ELFCLASS64:
+ if (ARCH_ELFSIZE == 64)
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+static uint32_t
+rtems_rtl_rap_get_uint32 (const uint8_t* buffer)
+{
+ uint32_t value = 0;
+ int b;
+ for (b = 0; b < sizeof (uint32_t); ++b)
+ {
+ value <<= 8;
+ value |= buffer[b];
+ }
+ return value;
+}
+
+static bool
+rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp_t* comp, uint32_t* value)
+{
+ uint8_t buffer[sizeof (uint32_t)];
+
+ if (!rtems_rtl_obj_comp_read (comp, buffer, sizeof (uint32_t)))
+ return false;
+
+ *value = rtems_rtl_rap_get_uint32 (buffer);
+
+ return true;
+}
+
+static bool
+rtems_rtl_rap_loader (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ rtems_rtl_rap_t* rap = (rtems_rtl_rap_t*) data;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: input %s=%lu\n",
+ sect->name, rtems_rtl_obj_comp_input (rap->decomp));
+
+ return rtems_rtl_obj_comp_read (rap->decomp, sect->base, sect->size);
+}
+
+static bool
+rtems_rtl_rap_relocate (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
+{
+ #define SYMNAME_BUFFER_SIZE (1024)
+ char* symname_buffer = NULL;
+ int section;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: relocation\n");
+
+ symname_buffer = malloc (SYMNAME_BUFFER_SIZE);
+ if (!symname_buffer)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for local symbol name buffer");
+ return false;
+ }
+
+ for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
+ {
+ rtems_rtl_obj_sect_t* targetsect;
+ uint32_t header = 0;
+ int relocs;
+ bool is_rela;
+ int r;
+
+ targetsect = rtems_rtl_obj_find_section (obj, rap_sections[section].name);
+
+ if (!targetsect)
+ {
+ rtems_rtl_set_error (EINVAL, "no target section found");
+ free (symname_buffer);
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &header))
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ /*
+ * Bit 31 of the header indicates if the relocations for this section
+ * have a valid addend field.
+ */
+
+ is_rela = (header & (1 << 31)) != 0 ? true : false;
+ relocs = header & ~(1 << 31);
+
+ if (relocs && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: relocation: %s: header: %08lx relocs: %d %s\n",
+ rap_sections[section].name,
+ header, relocs, is_rela ? "rela" : "rel");
+
+ for (r = 0; r < relocs; ++r)
+ {
+ uint32_t info = 0;
+ uint32_t offset = 0;
+ uint32_t addend = 0;
+ Elf_Word type;
+ const char* symname = NULL;
+ uint32_t symname_size;
+ Elf_Word symtype = 0;
+ Elf_Word symvalue = 0;
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &info))
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &offset))
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ /*
+ * The types are:
+ *
+ * 0 Section symbol offset in addend.
+ * 1 Symbol appended to the relocation record.
+ * 2 Symbol is in the strtabl.
+ *
+ * If type 2 bits 30:8 is the offset in the strtab. If type 1 the bits
+ * are the size of the string. The lower 8 bits of the info field if the
+ * ELF relocation type field.
+ */
+
+ if (((info & (1 << 31)) == 0) || is_rela)
+ {
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &addend))
+ {
+ free (symname_buffer);
+ return false;
+ }
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf (" %2d: info=%08lx offset=%lu addend=%lu\n",
+ r, info, offset, addend);
+
+ type = info & 0xff;
+
+ if ((info & (1 << 31)) == 0)
+ {
+ rtems_rtl_obj_sect_t* symsect;
+
+ symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8);
+ if (!symsect)
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ symvalue = (Elf_Word) symsect->base + addend;
+ }
+ else if (rtems_rtl_elf_rel_resolve_sym (type))
+ {
+ rtems_rtl_obj_sym_t* symbol;
+
+ symname_size = (info & ~(3 << 30)) >> 8;
+
+ if ((info & (1 << 30)) != 0)
+ {
+ symname = rap->strtab + symname_size;
+ }
+ else
+ {
+ if (symname_size > (SYMNAME_BUFFER_SIZE - 1))
+ {
+ free (symname_buffer);
+ rtems_rtl_set_error (EINVAL, "reloc symbol too big");
+ return false;
+ }
+
+ if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size))
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ symname_buffer[symname_size] = '\0';
+ symname = symname_buffer;
+ }
+
+ symbol = rtems_rtl_symbol_obj_find (obj, symname);
+
+ if (!symbol)
+ {
+ rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
+ free (symname_buffer);
+ return false;
+ }
+
+ symvalue = (Elf_Word) symbol->value;
+ }
+
+ if (is_rela)
+ {
+ Elf_Rela rela;
+
+ rela.r_offset = offset;
+ rela.r_info = type;
+
+ if ((info & (1 << 31)) == 0)
+ rela.r_addend = 0;
+ else rela.r_addend = addend;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf (" %2d: rela: type:%-2d off:%lu addend:%d" \
+ " symname=%s symtype=%lu symvalue=0x%08lx\n",
+ r, (int) type, offset, (int) addend,
+ symname, symtype, symvalue);
+
+ if (!rtems_rtl_elf_relocate_rela (obj, &rela, targetsect,
+ symname, symtype, symvalue))
+ {
+ free (symname_buffer);
+ return false;
+ }
+ }
+ else
+ {
+ Elf_Rel rel;
+
+ rel.r_offset = offset;
+ rel.r_info = type;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf (" %2d: rel: type:%-2d off:%lu" \
+ " symname=%s symtype=%lu symvalue=0x%08lx\n",
+ r, (int) type, offset,
+ symname, symtype, symvalue);
+
+ if (!rtems_rtl_elf_relocate_rel (obj, &rel, targetsect,
+ symname, symtype, symvalue))
+ {
+ free (symname_buffer);
+ return false;
+ }
+ }
+ }
+ }
+
+ free (symname_buffer);
+
+ return true;
+}
+
+/**
+ * The structure of obj->detail is
+ *
+ * |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])|
+ * obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num])
+ *
+ */
+static bool
+rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
+{
+ struct link_map* tmp1;
+ section_detail* tmp2;
+ uint32_t obj_detail_size;
+ uint32_t pos = 0;
+ int i,j;
+
+ obj_detail_size = sizeof (struct link_map) * obj->obj_num;
+
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ obj_detail_size += (obj->sec_num[i] * sizeof (section_detail));
+ }
+
+ obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ obj_detail_size + rap->strtable_size, true);
+
+ if (!obj->detail)
+ {
+ rap->strtable_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
+ return false;
+ }
+
+ rap->strtable = obj->detail + obj_detail_size;
+
+ /* Read the obj names and section names */
+ if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtable,
+ rap->strtable_size))
+ {
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->detail);
+ return false;
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ {
+ if (rap->rpathlen > 0)
+ printf ("File rpath:\n");
+ }
+
+ while (pos < rap->rpathlen)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ {
+ printf (" %s\n", rap->strtable + pos);
+ }
+ pos = pos + strlen (rap->strtable + pos) + 1;
+ }
+
+ if (rap->rpathlen > 0)
+ pos = rap->rpathlen;
+
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ tmp1 = (struct link_map*) (obj->detail) + i;
+ tmp1->name = rap->strtable + pos;
+ tmp1->sec_num = obj->sec_num[i];
+ tmp1->rpathlen = rap->rpathlen;
+ tmp1->rpath = (char*) rap->strtable;
+ pos += strlen (tmp1->name) + 1;
+
+ if (!i)
+ {
+ tmp1->l_next = NULL;
+ tmp1->l_prev = NULL;
+ }
+ else
+ {
+ (tmp1 - 1)->l_next = tmp1;
+ tmp1->l_prev = tmp1 - 1;
+ tmp1->l_next = NULL;
+ }
+ }
+
+ tmp2 =(section_detail*) ((struct link_map*) (obj->detail) + obj->obj_num);
+
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ {
+ printf ("File %d: %s\n", i, ((struct link_map*) obj->detail + i)->name);
+ printf ("Section: %d sections\n",(unsigned int) obj->sec_num[i]);
+ }
+
+ ((struct link_map*)obj->detail + i)->sec_detail = tmp2;
+
+ for (j = 0; j < obj->sec_num[i]; ++j)
+ {
+ uint32_t name;
+ uint32_t rap_id;
+ uint32_t offset;
+ uint32_t size;
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &offset) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &size))
+ {
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->detail);
+ return false;
+ }
+
+ rap_id = offset >> 28;
+ offset = offset & 0xfffffff;
+
+ tmp2->name = rap->strtable + name;
+ tmp2->offset = offset;
+ tmp2->rap_id = rap_id;
+ tmp2->size = size;
+ pos += strlen (tmp2->name) + 1;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ {
+ printf ("name:%16s offset:0x%08x rap_id:%d size:0x%x\n",
+ tmp2->name, (unsigned int) tmp2->offset,
+ (unsigned int) tmp2->rap_id, (unsigned int) tmp2->size);
+ }
+
+ tmp2 += 1;
+ }
+ }
+ return true;
+}
+
+static bool
+rtems_rtl_rap_load_symbols (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
+{
+ rtems_rtl_obj_sym_t* gsym;
+ int sym;
+
+ obj->global_size =
+ rap->symbols * sizeof (rtems_rtl_obj_sym_t) + rap->strtab_size;
+
+ obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
+ obj->global_size, true);
+ if (!obj->global_table)
+ {
+ obj->global_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
+ return false;
+ }
+
+ obj->global_syms = rap->symbols;
+
+ rap->strtab = (((char*) obj->global_table) +
+ (rap->symbols * sizeof (rtems_rtl_obj_sym_t)));
+
+ if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtab, rap->strtab_size))
+ return false;
+
+ for (sym = 0, gsym = obj->global_table; sym < rap->symbols; ++sym)
+ {
+ rtems_rtl_obj_sect_t* symsect;
+ uint32_t data;
+ uint32_t name;
+ uint32_t value;
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &data) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &value))
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ return false;
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+ printf ("rtl: sym:load: data=0x%08lx name=0x%08lx value=0x%08lx\n",
+ data, name, value);
+
+ /*
+ * If there is a globally exported symbol already present and this
+ * symbol is not weak raise an error. If the symbol is weak and present
+ * globally ignore this symbol and use the global one and if it is not
+ * present take this symbol global or weak. We accept the first weak
+ * symbol we find and make it globally exported.
+ */
+ if (rtems_rtl_symbol_global_find (rap->strtab + name) &&
+ (ELF_ST_BIND (data & 0xffff) != STB_WEAK))
+ {
+ rtems_rtl_set_error (EINVAL,
+ "duplicate global symbol: %s", rap->strtab + name);
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ return false;
+ }
+
+ symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16);
+ if (!symsect)
+ {
+ free (obj->global_table);
+ obj->global_table = NULL;
+ obj->global_syms = 0;
+ obj->global_size = 0;
+ rtems_rtl_set_error (EINVAL, "section index not found: %lu", data >> 16);
+ return false;
+ }
+
+ rtems_chain_set_off_chain (&gsym->node);
+ gsym->name = rap->strtab + name;
+ gsym->value = (uint8_t*) (value + symsect->base);
+ gsym->data = data & 0xffff;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+ printf ("rtl: sym:add:%-2d name:%-20s bind:%-2d type:%-2d val:%8p sect:%d\n",
+ sym, gsym->name,
+ (int) ELF_ST_BIND (data & 0xffff),
+ (int) ELF_ST_TYPE (data & 0xffff),
+ gsym->value, (int) (data >> 16));
+
+ ++gsym;
+ }
+
+ return true;
+}
+
+static bool
+rtems_rtl_rap_parse_header (uint8_t* rhdr,
+ size_t* rhdr_len,
+ uint32_t* length,
+ uint32_t* version,
+ uint32_t* compression,
+ uint32_t* checksum)
+{
+ char* sptr = (char*) rhdr;
+ char* eptr;
+
+ *rhdr_len = 0;
+
+ /*
+ * "RAP," = 4 bytes, total 4
+ */
+
+ if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
+ return false;
+
+ sptr = sptr + 4;
+
+ /*
+ * "00000000," = 9 bytes, total 13
+ */
+
+ *length = strtoul (sptr, &eptr, 10);
+
+ if (*eptr != ',')
+ return false;
+
+ sptr = eptr + 1;
+
+ /*
+ * "0000," = 5 bytes, total 18
+ */
+
+ *version = strtoul (sptr, &eptr, 10);
+
+ if (*eptr != ',')
+ return false;
+
+ sptr = eptr + 1;
+
+ /*
+ * "NONE," and "LZ77," = 5 bytes, total 23
+ */
+
+ if ((sptr[0] == 'N') &&
+ (sptr[1] == 'O') &&
+ (sptr[2] == 'N') &&
+ (sptr[3] == 'E'))
+ {
+ *compression = RTEMS_RTL_COMP_NONE;
+ eptr = sptr + 4;
+ }
+ else if ((sptr[0] == 'L') &&
+ (sptr[1] == 'Z') &&
+ (sptr[2] == '7') &&
+ (sptr[3] == '7'))
+ {
+ *compression = RTEMS_RTL_COMP_LZ77;
+ eptr = sptr + 4;
+ }
+ else
+ return false;
+
+ if (*eptr != ',')
+ return false;
+
+ sptr = eptr + 1;
+
+ /*
+ * "00000000," = 9 bytes, total 32
+ */
+ *checksum = strtoul (sptr, &eptr, 16);
+
+ /*
+ * "\n" = 1 byte, total 33
+ */
+ if (*eptr != '\n')
+ return false;
+
+ *rhdr_len = ((uint8_t*) eptr) - rhdr + 1;
+
+ return true;
+}
+
+bool
+rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_obj_cache_t* header;
+ uint8_t* rhdr = NULL;
+ size_t rlen = 64;
+ uint32_t length = 0;
+ uint32_t version = 0;
+ uint32_t compression = 0;
+ uint32_t checksum = 0;
+
+ rtems_rtl_obj_caches (&header, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset,
+ (void**) &rhdr, &rlen))
+ return false;
+
+ if (!rtems_rtl_rap_parse_header (rhdr,
+ &rlen,
+ &length,
+ &version,
+ &compression,
+ &checksum))
+ return false;
+
+ return true;
+}
+
+bool
+rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_rap_t rap = { 0 };
+ uint8_t* rhdr = NULL;
+ size_t rlen = 64;
+ int section;
+
+ rtems_rtl_obj_caches (&rap.file, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read (rap.file, fd, obj->ooffset,
+ (void**) &rhdr, &rlen))
+ return false;
+
+ if (!rtems_rtl_rap_parse_header (rhdr,
+ &rlen,
+ &rap.length,
+ &rap.version,
+ &rap.compression,
+ &rap.checksum))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid RAP file format");
+ return false;
+ }
+
+ /*
+ * Set up the decompressor.
+ */
+ rtems_rtl_obj_comp (&rap.decomp, rap.file, fd, rap.compression,
+ rlen + obj->ooffset);
+
+ /*
+ * uint32_t: machinetype
+ * uint32_t: datatype
+ * uint32_t: class
+ */
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: input machine=%lu\n",
+ rtems_rtl_obj_comp_input (rap.decomp));
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.machinetype))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: machinetype=%lu\n", rap.machinetype);
+
+ if (!rtems_rtl_rap_machine_check (rap.machinetype))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid machinetype");
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.datatype))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: datatype=%lu\n", rap.datatype);
+
+ if (!rtems_rtl_rap_datatype_check (rap.datatype))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid datatype");
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.class))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: class=%lu\n", rap.class);
+
+ if (!rtems_rtl_rap_class_check (rap.class))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid class");
+ return false;
+ }
+
+ /*
+ * uint32_t: init
+ * uint32_t: fini
+ * uint32_t: symtab_size
+ * uint32_t: strtab_size
+ * uint32_t: relocs_size
+ */
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: input header=%lu\n",
+ rtems_rtl_obj_comp_input (rap.decomp));
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.init))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.fini))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.symtab_size))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtab_size))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.relocs_size))
+ return false;
+
+ rap.symbols = rap.symtab_size / (3 * sizeof (uint32_t));
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: load: symtab=%lu (%lu) strtab=%lu relocs=%lu\n",
+ rap.symtab_size, rap.symbols,
+ rap.strtab_size, rap.relocs_size);
+
+ /*
+ * Load the details
+ */
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &obj->obj_num))
+ return false;
+
+ if (obj->obj_num > 0)
+ {
+ obj->sec_num = (uint32_t*) malloc (sizeof (uint32_t) * obj->obj_num);
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.rpathlen))
+ return false;
+
+ uint32_t i;
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &(obj->sec_num[i])))
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtable_size))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ printf ("rtl: rap: details: obj_num=%lu\n", obj->obj_num);
+
+ if (!rtems_rtl_rap_load_details (&rap, obj))
+ return false;
+ }
+
+ /*
+ * uint32_t: text_size
+ * uint32_t: text_alignment
+ * uint32_t: const_size
+ * uint32_t: const_alignment
+ * uint32_t: ctor_size
+ * uint32_t: ctor_alignment
+ * uint32_t: dtor_size
+ * uint32_t: dtor_alignment
+ * uint32_t: data_size
+ * uint32_t: data_alignment
+ * uint32_t: bss_size
+ * uint32_t: bss_alignment
+ */
+
+ for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
+ {
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].size))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].alignment))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+ printf ("rtl: rap: %s: size=%lu align=%lu\n",
+ rap_sections[section].name,
+ rap.secs[section].size,
+ rap.secs[section].alignment);
+
+ if (!rtems_rtl_obj_add_section (obj,
+ section,
+ rap_sections[section].name,
+ rap.secs[section].size,
+ 0,
+ rap.secs[section].alignment,
+ 0, 0,
+ rap_sections[section].flags))
+ return false;
+ }
+
+ /** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */
+
+ if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_rap_loader, &rap))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: input symbols=%lu\n",
+ rtems_rtl_obj_comp_input (rap.decomp));
+
+ if (!rtems_rtl_rap_load_symbols (&rap, obj))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: input relocs=%lu\n",
+ rtems_rtl_obj_comp_input (rap.decomp));
+
+ if (!rtems_rtl_rap_relocate (&rap, obj))
+ return false;
+
+ return true;
+}
+
+rtems_rtl_loader_format_t*
+rtems_rtl_rap_file_sig (void)
+{
+ return &rap_sig;
+}
diff --git a/cpukit/libdl/rtl-rap.h b/cpukit/libdl/rtl-rap.h
new file mode 100644
index 0000000..54c1268
--- /dev/null
+++ b/cpukit/libdl/rtl-rap.h
@@ -0,0 +1,54 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Headers
+ */
+
+#if !defined (_RTEMS_RTL_RAP_H_)
+#define _RTEMS_RTL_RAP_H_
+
+#include "rtl-fwd.h"
+#include "rtl-obj-fwd.h"
+#include "rtl-sym.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The RAP format check handler.
+ *
+ * @param obj The object being checked.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The RAP format load handler.
+ *
+ * @param obj The object to load.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The RAP format signature handler.
+ *
+ * @return rtems_rtl_loader_format_t* The format's signature.
+ */
+rtems_rtl_loader_format_t* rtems_rtl_rap_file_sig (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
new file mode 100644
index 0000000..0e33e84
--- /dev/null
+++ b/cpukit/libdl/rtl-shell.c
@@ -0,0 +1,389 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor Shell Commands
+ *
+ * A simple RTL command to aid using the RTL.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+
+//#if SIZEOF_OFF_T == 8
+#define PRIdoff_t PRIo64
+//#elif SIZEOF_OFF_T == 4
+//#define PRIdoff_t PRIo32
+//#else
+//#error "unsupported size of off_t"
+//#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-chain-iterator.h"
+#include "rtl-shell.h"
+#include "rtl-trace.h"
+
+/**
+ * The type of the shell handlers we have.
+ */
+typedef int (*rtems_rtl_shell_handler_t) (rtems_rtl_data_t* rtl, int argc, char *argv[]);
+
+/**
+ * Table of handlers we parse to invoke the command.
+ */
+typedef struct
+{
+ const char* name; /**< The sub-command's name. */
+ rtems_rtl_shell_handler_t handler; /**< The sub-command's handler. */
+ const char* help; /**< The sub-command's help. */
+} rtems_rtl_shell_cmd_t;
+
+/**
+ * Object summary data.
+ */
+typedef struct
+{
+ int count; /**< The number of object files. */
+ size_t exec; /**< The amount of executable memory allocated. */
+ size_t symbols; /**< The amount of symbol memory allocated. */
+} rtems_rtl_obj_summary_t;
+
+/**
+ * Object summary iterator.
+ */
+static bool
+rtems_rtl_obj_summary_iterator (rtems_chain_node* node, void* data)
+{
+ rtems_rtl_obj_summary_t* summary = data;
+ rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
+ ++summary->count;
+ summary->exec += obj->exec_size;
+ summary->symbols += obj->global_size;
+ return true;
+}
+
+/**
+ * Count the number of symbols.
+ */
+static int
+rtems_rtl_count_symbols (rtems_rtl_data_t* rtl)
+{
+ int count;
+ int bucket;
+ for (count = 0, bucket = 0; bucket < rtl->globals.nbuckets; ++bucket)
+ count += rtems_rtl_chain_count (&rtl->globals.buckets[bucket]);
+ return count;
+}
+
+static int
+rtems_rtl_shell_status (rtems_rtl_data_t* rtl, int argc, char *argv[])
+{
+ rtems_rtl_obj_summary_t summary;
+ size_t total_memory;
+
+ summary.count = 0;
+ summary.exec = 0;
+ summary.symbols = 0;
+ rtems_rtl_chain_iterate (&rtl->objects,
+ rtems_rtl_obj_summary_iterator,
+ &summary);
+ /*
+ * Currently does not include the name strings in the obj struct.
+ */
+ total_memory =
+ sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj_t)) +
+ summary.exec + summary.symbols;
+
+ printf ("Runtime Linker Status:\n");
+ printf (" paths: %s\n", rtl->paths);
+ printf (" objects: %d\n", summary.count);
+ printf (" total memory: %zi\n", total_memory);
+ printf (" exec memory: %zi\n", summary.exec);
+ printf (" sym memory: %zi\n", summary.symbols);
+ printf (" symbols: %d\n", rtems_rtl_count_symbols (rtl));
+
+ return 0;
+}
+
+/**
+ * Object print data.
+ */
+typedef struct
+{
+ rtems_rtl_data_t* rtl; /**< The RTL data. */
+ int indent; /**< Spaces to indent. */
+ bool oname; /**< Print object names. */
+ bool names; /**< Print details of all names. */
+ bool memory_map; /**< Print the memory map. */
+ bool symbols; /**< Print the global symbols. */
+ bool base; /**< Include the base object file. */
+} rtems_rtl_obj_print_t;
+
+/**
+ * Return the different between 2 void*.
+ */
+static size_t
+rtems_rtl_delta_voids (void* higher, void* lower)
+{
+ char* ch = higher;
+ char* cl = lower;
+ return ch - cl;
+}
+
+/**
+ * Parse an argument.
+ */
+static bool
+rtems_rtl_parse_arg (const char* opt, int argc, char *argv[])
+{
+ int arg;
+ for (arg = 0; arg < argc; ++arg)
+ if (strncmp (opt, argv[arg], 2) == 0)
+ return true;
+ return false;
+}
+
+/**
+ * See if -b for base is set.
+ */
+static bool
+rtems_rtl_base_arg (int argc, char *argv[])
+{
+ return rtems_rtl_parse_arg ("-b", argc, argv);
+}
+
+/**
+ * See if -s for base is set.
+ */
+static bool
+rtems_rtl_symbols_arg (int argc, char *argv[])
+{
+ return rtems_rtl_parse_arg ("-s", argc, argv);
+}
+
+/**
+ * Object printer.
+ */
+static bool
+rtems_rtl_obj_printer (rtems_rtl_obj_print_t* print, rtems_rtl_obj_t* obj)
+{
+ char flags_str[33];
+
+ /*
+ * Skip the base module unless asked to show it.
+ */
+ if (!print->base && (obj == print->rtl->base))
+ return true;
+
+ if (print->oname)
+ {
+ printf ("%-*cobject name : %s\n",
+ print->indent, ' ', rtems_rtl_obj_oname (obj));
+ }
+ if (print->names)
+ {
+ printf ("%-*cfile name : %s\n",
+ print->indent, ' ', rtems_rtl_obj_fname (obj));
+ printf ("%-*carchive name : %s\n",
+ print->indent, ' ', rtems_rtl_obj_aname (obj));
+ strcpy (flags_str, "--");
+ if (obj->flags & RTEMS_RTL_OBJ_LOCKED)
+ flags_str[0] = 'L';
+ if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED)
+ flags_str[1] = 'U';
+ printf ("%-*cflags : %s\n", print->indent, ' ', flags_str);
+ printf ("%-*cfile offset : %" PRIdoff_t "\n", print->indent, ' ', obj->ooffset);
+ printf ("%-*cfile size : %zi\n", print->indent, ' ', obj->fsize);
+ }
+ if (print->memory_map)
+ {
+ printf ("%-*cexec size : %zi\n", print->indent, ' ', obj->exec_size);
+ printf ("%-*ctext base : %p (%zi)\n", print->indent, ' ',
+ obj->text_base, rtems_rtl_delta_voids (obj->const_base, obj->text_base));
+ printf ("%-*cconst base : %p (%zi)\n", print->indent, ' ',
+ obj->const_base, rtems_rtl_delta_voids (obj->data_base, obj->const_base));
+ printf ("%-*cdata base : %p (%zi)\n", print->indent, ' ',
+ obj->data_base, rtems_rtl_delta_voids (obj->bss_base, obj->data_base));
+ printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ',
+ obj->bss_base, obj->bss_size);
+ }
+ printf ("%-*cunresolved : %lu\n", print->indent, ' ', obj->unresolved);
+ printf ("%-*csymbols : %zi\n", print->indent, ' ', obj->global_syms);
+ printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size);
+ if (print->symbols)
+ {
+ int max_len = 0;
+ int s;
+ for (s = 0; s < obj->global_syms; ++s)
+ {
+ int len = strlen (obj->global_table[s].name);
+ if (len > max_len)
+ max_len = len;
+ }
+ for (s = 0; s < obj->global_syms; ++s)
+ printf ("%-*c%-*s = %p\n", print->indent + 2, ' ',
+ max_len, obj->global_table[s].name, obj->global_table[s].value);
+ }
+ printf ("\n");
+ return true;
+}
+
+/**
+ * Object unresolved symbols printer.
+ */
+static bool
+rtems_rtl_unresolved_printer (rtems_rtl_unresolv_rec_t* rec,
+ void* data)
+{
+ rtems_rtl_obj_print_t* print = (rtems_rtl_obj_print_t*) data;
+ if (rec->type == rtems_rtl_unresolved_name)
+ printf ("%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
+ return false;
+}
+
+/**
+ * Object print iterator.
+ */
+static bool
+rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data)
+{
+ rtems_rtl_obj_print_t* print = data;
+ rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
+ return rtems_rtl_obj_printer (print, obj);
+}
+
+static int
+rtems_rtl_shell_list (rtems_rtl_data_t* rtl, int argc, char *argv[])
+{
+ rtems_rtl_obj_print_t print;
+ print.rtl = rtl;
+ print.indent = 1;
+ print.oname = true;
+ print.names = true;
+ print.memory_map = true;
+ print.symbols = rtems_rtl_symbols_arg (argc, argv);
+ print.base = false;
+ rtems_rtl_chain_iterate (&rtl->objects,
+ rtems_rtl_obj_print_iterator,
+ &print);
+ return 0;
+}
+
+static int
+rtems_rtl_shell_sym (rtems_rtl_data_t* rtl, int argc, char *argv[])
+{
+ rtems_rtl_obj_print_t print;
+ print.rtl = rtl;
+ print.indent = 1;
+ print.oname = true;
+ print.names = false;
+ print.memory_map = false;
+ print.symbols = true;
+ print.base = rtems_rtl_base_arg (argc, argv);
+ rtems_rtl_chain_iterate (&rtl->objects,
+ rtems_rtl_obj_print_iterator,
+ &print);
+ printf ("Unresolved:\n");
+ rtems_rtl_unresolved_interate (rtems_rtl_unresolved_printer, &print);
+ return 0;
+}
+
+static int
+rtems_rtl_shell_object (rtems_rtl_data_t* rtl, int argc, char *argv[])
+{
+ return 0;
+}
+
+static void
+rtems_rtl_shell_usage (const char* arg)
+{
+ printf ("%s: Runtime Linker\n", arg);
+ printf (" %s [-hl] <command>\n", arg);
+ printf (" where:\n");
+ printf (" command: A n RTL command. See -l for a list plus help.\n");
+ printf (" -h: This help\n");
+ printf (" -l: The command list.\n");
+}
+
+int
+rtems_rtl_shell_command (int argc, char* argv[])
+{
+ const rtems_rtl_shell_cmd_t table[] =
+ {
+ { "status", rtems_rtl_shell_status,
+ "Display the status of the RTL" },
+ { "list", rtems_rtl_shell_list,
+ "\tList the object files currently loaded" },
+ { "sym", rtems_rtl_shell_sym,
+ "\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" },
+ { "obj", rtems_rtl_shell_object,
+ "\tDisplay the object details, obj <name>" }
+ };
+
+ int arg;
+ int t;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] != '-')
+ break;
+
+ switch (argv[arg][1])
+ {
+ case 'h':
+ rtems_rtl_shell_usage (argv[0]);
+ return 0;
+ case 'l':
+ printf ("%s: commands are:\n", argv[0]);
+ for (t = 0;
+ t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t));
+ ++t)
+ printf (" %s\t%s\n", table[t].name, table[t].help);
+ return 0;
+ default:
+ printf ("error: unknown option: %s\n", argv[arg]);
+ return 1;
+ }
+ }
+
+ if ((argc - arg) < 1)
+ printf ("error: you need to provide a command, try %s -h\n", argv[0]);
+ else
+ {
+ for (t = 0;
+ t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t));
+ ++t)
+ {
+ if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0)
+ {
+ rtems_rtl_data_t* rtl = rtems_rtl_data ();
+ int r;
+ if (!rtl)
+ {
+ printf ("error: cannot lock the linker\n");
+ return 1;
+ }
+ r = table[t].handler (rtl, argc - 1, argv + 1);
+ rtems_rtl_unlock ();
+ return r;
+ }
+ }
+ printf ("error: command not found: %s (try -h)\n", argv[arg]);
+ }
+
+ return 1;
+}
diff --git a/cpukit/libdl/rtl-shell.h b/cpukit/libdl/rtl-shell.h
new file mode 100644
index 0000000..ac9bb25
--- /dev/null
+++ b/cpukit/libdl/rtl-shell.h
@@ -0,0 +1,39 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Shell Support.
+ */
+
+#if !defined (_RTEMS_RTL_SHELL_H_)
+#define _RTEMS_RTL_SHELL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdint.h>
+
+/**
+ * The RTL single shell command contains sub-commands.
+ *
+ * @param argc The argument count.
+ * @param argv Array of argument strings.
+ * @retval 0 No error.
+ * @return int The exit code.
+ */
+int rtems_rtl_shell_command (int argc, char* argv[]);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-string.c b/cpukit/libdl/rtl-string.c
new file mode 100644
index 0000000..4a49b77
--- /dev/null
+++ b/cpukit/libdl/rtl-string.c
@@ -0,0 +1,32 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker String managment.
+ */
+
+#include <string.h>
+
+#include "rtl-allocator.h"
+#include "rtl-string.h"
+
+char*
+rtems_rtl_strdup (const char *s1)
+{
+ size_t len = strlen (s1);
+ char* s2 = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, len + 1, false);
+ if (s2)
+ {
+ memcpy (s2, s1, len);
+ s2[len] = '\0';
+ }
+ return s2;
+}
diff --git a/cpukit/libdl/rtl-string.h b/cpukit/libdl/rtl-string.h
new file mode 100644
index 0000000..a9ce6f5
--- /dev/null
+++ b/cpukit/libdl/rtl-string.h
@@ -0,0 +1,37 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker String managment.
+ */
+
+#if !defined (_RTEMS_RTL_STRING_H_)
+#define _RTEMS_RTL_STRING_H_
+
+#include "rtl-indirect-ptr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * A string duplicate that uses the RTL allocator.
+ *
+ * @param s1 The string to duplicate.
+ * @return char* The copy of the string. NULL if there is no memory.
+ */
+char* rtems_rtl_strdup (const char *s1);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-sym.c b/cpukit/libdl/rtl-sym.c
new file mode 100644
index 0000000..f806394
--- /dev/null
+++ b/cpukit/libdl/rtl-sym.c
@@ -0,0 +1,245 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Symbol Table.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-error.h"
+#include "rtl-sym.h"
+#include "rtl-trace.h"
+
+/**
+ * The single symbol forced into the global symbol table that is used to load a
+ * symbol table from an object file.
+ */
+static rtems_rtl_obj_sym_t global_sym_add =
+{
+ .name = "rtems_rtl_base_sym_global_add",
+ .value = (void*) rtems_rtl_base_sym_global_add
+};
+
+static uint_fast32_t
+rtems_rtl_symbol_hash (const char *s)
+{
+ uint_fast32_t h = 5381;
+ unsigned char c;
+ for (c = *s; c != '\0'; c = *++s)
+ h = h * 33 + c;
+ return h & 0xffffffff;
+}
+
+static void
+rtems_rtl_symbol_global_insert (rtems_rtl_symbols_t* symbols,
+ rtems_rtl_obj_sym_t* symbol)
+{
+ uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
+ rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
+ &symbol->node);
+}
+
+bool
+rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols,
+ size_t buckets)
+{
+ symbols->buckets = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
+ buckets * sizeof (rtems_chain_control),
+ true);
+ if (!symbols->buckets)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for global symbol table");
+ return false;
+ }
+ symbols->nbuckets = buckets;
+ for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
+ rtems_chain_initialize_empty (&symbols->buckets[buckets]);
+ rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
+ return true;
+}
+
+void
+rtems_rtl_symbol_table_close (rtems_rtl_symbols_t* symbols)
+{
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
+}
+
+bool
+rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
+ const unsigned char* esyms,
+ unsigned int size)
+{
+ rtems_rtl_symbols_t* symbols;
+ rtems_rtl_obj_sym_t* sym;
+ size_t count;
+ size_t s;
+ uint32_t marker;
+
+ count = 0;
+ s = 0;
+ while ((s < size) && (esyms[s] != 0))
+ {
+ int l = strlen ((char*) &esyms[s]);
+ if ((esyms[s + l] != '\0') || ((s + l) > size))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid exported symbol table");
+ return false;
+ }
+ ++count;
+ s += l + sizeof (unsigned long) + 1;
+ }
+
+ /*
+ * Check this is the correct end of the table.
+ */
+ marker = esyms[s + 1];
+ marker <<= 8;
+ marker |= esyms[s + 2];
+ marker <<= 8;
+ marker |= esyms[s + 3];
+ marker <<= 8;
+ marker |= esyms[s + 4];
+
+ if (marker != 0xdeadbeefUL)
+ {
+ rtems_rtl_set_error (ENOMEM, "invalid export symbol table");
+ return false;
+ }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
+ printf ("rtl: global symbol add: %zi\n", count);
+
+ obj->global_size = count * sizeof (rtems_rtl_obj_sym_t);
+ obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
+ obj->global_size, true);
+ if (!obj->global_table)
+ {
+ obj->global_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory for global symbols");
+ return false;
+ }
+
+ symbols = rtems_rtl_global_symbols ();
+
+ s = 0;
+ sym = obj->global_table;
+
+ while ((s < size) && (esyms[s] != 0))
+ {
+ /*
+ * Copy the void* using a union and memcpy to avoid any strict aliasing or
+ * alignment issues. The variable length of the label and the packed nature
+ * of the table means casting is not suitable.
+ */
+ union {
+ uint8_t data[sizeof (void*)];
+ void* value;
+ } copy_voidp;
+ int b;
+
+ sym->name = (const char*) &esyms[s];
+ s += strlen (sym->name) + 1;
+ for (b = 0; b < sizeof (void*); ++b, ++s)
+ copy_voidp.data[b] = esyms[s];
+ sym->value = copy_voidp.value;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
+ printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value);
+ if (rtems_rtl_symbol_global_find (sym->name) == NULL)
+ rtems_rtl_symbol_global_insert (symbols, sym);
+ ++sym;
+ }
+
+ obj->global_syms = count;
+
+ return true;
+}
+
+rtems_rtl_obj_sym_t*
+rtems_rtl_symbol_global_find (const char* name)
+{
+ rtems_rtl_symbols_t* symbols;
+ uint_fast32_t hash;
+ rtems_chain_control* bucket;
+ rtems_chain_node* node;
+
+ symbols = rtems_rtl_global_symbols ();
+
+ hash = rtems_rtl_symbol_hash (name);
+ bucket = &symbols->buckets[hash % symbols->nbuckets];
+ node = rtems_chain_first (bucket);
+
+ while (!rtems_chain_is_tail (bucket, node))
+ {
+ rtems_rtl_obj_sym_t* sym = (rtems_rtl_obj_sym_t*) node;
+ /*
+ * Use the hash. I could add this to the symbol but it uses more memory.
+ */
+ if (strcmp (name, sym->name) == 0)
+ return sym;
+ node = rtems_chain_next (node);
+ }
+
+ return NULL;
+}
+
+rtems_rtl_obj_sym_t*
+rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj, const char* name)
+{
+ rtems_rtl_obj_sym_t* sym;
+ size_t s;
+ /*
+ * Check the object file's symbols first. If not found search the
+ * global symbol table.
+ */
+ for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
+ if (strcmp (name, sym->name) == 0)
+ return sym;
+ return rtems_rtl_symbol_global_find (name);
+}
+
+void
+rtems_rtl_symbol_obj_add (rtems_rtl_obj_t* obj)
+{
+ rtems_rtl_symbols_t* symbols;
+ rtems_rtl_obj_sym_t* sym;
+ size_t s;
+
+ symbols = rtems_rtl_global_symbols ();
+
+ for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
+ rtems_rtl_symbol_global_insert (symbols, sym);
+}
+
+void
+rtems_rtl_symbol_obj_erase (rtems_rtl_obj_t* obj)
+{
+ if (obj->global_table)
+ {
+ rtems_rtl_obj_sym_t* sym;
+ size_t s;
+ for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
+ if (!rtems_chain_is_node_off_chain (&sym->node))
+ rtems_chain_extract (&sym->node);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
+ obj->global_table = NULL;
+ obj->global_size = 0;
+ obj->global_syms = 0;
+ }
+}
diff --git a/cpukit/libdl/rtl-sym.h b/cpukit/libdl/rtl-sym.h
new file mode 100644
index 0000000..b793a54
--- /dev/null
+++ b/cpukit/libdl/rtl-sym.h
@@ -0,0 +1,128 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Symbol Table.
+ */
+
+#if !defined (_RTEMS_RTL_SYM_H_)
+#define _RTEMS_RTL_SYM_H_
+
+#include <rtems.h>
+#include "rtl-obj-fwd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * An object file symbol.
+ */
+typedef struct rtems_rtl_obj_sym_s
+{
+ rtems_chain_node node; /**< The node's link in the chain. */
+ const char* name; /**< The symbol's name. */
+ void* value; /**< The value of the symbol. */
+ uint32_t data; /**< Format specific data. */
+} rtems_rtl_obj_sym_t;
+
+/**
+ * Table of symbols stored in a hash table.
+ */
+typedef struct rtems_rtl_symbols_s
+{
+ rtems_chain_control* buckets;
+ size_t nbuckets;
+} rtems_rtl_symbols_t;
+
+/**
+ * Open a symbol table with the specified number of buckets.
+ *
+ * @param symbols The symbol table to open.
+ * @param buckets The number of buckets in the hash table.
+ * @retval true The symbol is open.
+ * @retval false The symbol table could not created. The RTL
+ * error has the error.
+ */
+bool rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols,
+ size_t buckets);
+
+/**
+ * Close the table and erase the hash table.
+ *
+ * @param symbols Close the symbol table.
+ */
+void rtems_rtl_symbol_table_close (rtems_rtl_symbols_t* symbols);
+
+/**
+ * Add a table of exported symbols to the symbol table.
+ *
+ * The export table is a series of symbol records and each record has two
+ * fields:
+ *
+ * 1. label
+ * 2. address
+ *
+ * The 'label' is an ASCIIZ string of variable length. The address is of size
+ * of an unsigned long for the target running the link editor. The byte order
+ * is defined by the machine type because the table should be built by the
+ * target compiler.
+ *
+ * The table is terminated with a nul string followed by the bytes 0xDE, 0xAD,
+ * 0xBE, and 0xEF. This avoids alignments issues.
+ *
+ * @param obj The object table the symbols are for.
+ * @param esyms The exported symbol table.
+ * @param size The size of the table in bytes.
+ */
+bool rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
+ const unsigned char* esyms,
+ unsigned int size);
+
+/**
+ * Find a symbol given the symbol label in the global symbol table.
+ *
+ * @param name The name as an ASCIIZ string.
+ * @retval NULL No symbol found.
+ * @return rtems_rtl_obj_sym_t* Reference to the symbol.
+ */
+rtems_rtl_obj_sym_t* rtems_rtl_symbol_global_find (const char* name);
+
+/**
+ * Find a symbol given the symbol label in the local object file.
+ *
+ * @param obj The object file to search.
+ * @param name The name as an ASCIIZ string.
+ * @retval NULL No symbol found.
+ * @return rtems_rtl_obj_sym_t* Reference to the symbol.
+ */
+rtems_rtl_obj_sym_t* rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj,
+ const char* name);
+
+/**
+ * Add the object file's symbols to the global table.
+ *
+ * @param obj The object file the symbols are to be added.
+ */
+void rtems_rtl_symbol_obj_add (rtems_rtl_obj_t* obj);
+
+/**
+ * Erase the object file's symbols.
+ *
+ * @param obj The object file the symbols are to be erased from.
+ */
+void rtems_rtl_symbol_obj_erase (rtems_rtl_obj_t* obj);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-trace.c b/cpukit/libdl/rtl-trace.c
new file mode 100644
index 0000000..d577f99
--- /dev/null
+++ b/cpukit/libdl/rtl-trace.c
@@ -0,0 +1,134 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor Trace
+ *
+ * A configurable tracer for the RTL. See the header file for the enable and
+ * disable.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rtl-trace.h"
+
+#if RTEMS_RTL_TRACE
+static rtems_rtl_trace_mask rtems_rtl_trace_flags;
+
+bool
+rtems_rtl_trace (rtems_rtl_trace_mask mask)
+{
+ bool result = false;
+ if (mask & rtems_rtl_trace_flags)
+ result = true;
+ return result;
+}
+
+rtems_rtl_trace_mask
+rtems_rtl_trace_set_mask (rtems_rtl_trace_mask mask)
+{
+ rtems_rtl_trace_mask state = rtems_rtl_trace_flags;
+ rtems_rtl_trace_flags |= mask;
+ return state;
+}
+
+rtems_rtl_trace_mask
+rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask)
+{
+ rtems_rtl_trace_mask state = rtems_rtl_trace_flags;
+ rtems_rtl_trace_flags &= ~mask;
+ return state;
+}
+
+int
+rtems_rtl_trace_shell_command (int argc, char *argv[])
+{
+ const char* table[] =
+ {
+ "load",
+ "unload",
+ "section",
+ "symbol",
+ "reloc",
+ "global-sym",
+ "load-sect",
+ "allocator",
+ "unresolved",
+ "detail"
+ };
+
+ rtems_rtl_trace_mask set_value = 0;
+ rtems_rtl_trace_mask clear_value = 0;
+ bool set = true;
+ int arg;
+ int t;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ switch (argv[arg][1])
+ {
+ case 'h':
+ printf ("usage: %s [-hl] [set/clear] [flags]\n", argv[0]);
+ return 0;
+ case 'l':
+ printf ("%s: valid flags to set or clear are:\n", argv[0]);
+ for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++)
+ printf (" %s\n", table[t]);
+ return 0;
+ default:
+ printf ("error: unknown option\n");
+ return 1;
+ }
+ }
+ else
+ {
+ if (strcmp (argv[arg], "set") == 0)
+ set = true;
+ if (strcmp (argv[arg], "clear") == 0)
+ set = false;
+ else if (strcmp (argv[arg], "all") == 0)
+ {
+ if (set)
+ set_value = RTEMS_RTL_TRACE_ALL;
+ else
+ clear_value = RTEMS_RTL_TRACE_ALL;
+ }
+ else
+ {
+ for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++)
+ {
+ if (strcmp (argv[arg], table[t]) == 0)
+ {
+ if (set)
+ set_value = 1 << t;
+ else
+ clear_value = 1 << t;
+ break;
+ }
+ }
+ }
+
+ rtems_rtl_trace_flags |= set_value;
+ rtems_rtl_trace_flags &= ~clear_value;
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libdl/rtl-trace.h b/cpukit/libdl/rtl-trace.h
new file mode 100644
index 0000000..1a5ee97
--- /dev/null
+++ b/cpukit/libdl/rtl-trace.h
@@ -0,0 +1,100 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Trace Support.
+ */
+
+#if !defined (_RTEMS_RTL_TRACE_H_)
+#define _RTEMS_RTL_TRACE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * Set to 1 to build trace support in to the RTL code.
+ */
+#define RTEMS_RTL_TRACE 1
+
+/**
+ * The type of the mask.
+ */
+typedef uint32_t rtems_rtl_trace_mask;
+
+/**
+ * List of tracing bits for the various parts of the link editor.
+ */
+#define RTEMS_RTL_TRACE_ALL (0xffffffffUL)
+#define RTEMS_RTL_TRACE_LOAD (1UL << 0)
+#define RTEMS_RTL_TRACE_UNLOAD (1UL << 1)
+#define RTEMS_RTL_TRACE_SECTION (1UL << 2)
+#define RTEMS_RTL_TRACE_SYMBOL (1UL << 3)
+#define RTEMS_RTL_TRACE_RELOC (1UL << 4)
+#define RTEMS_RTL_TRACE_GLOBAL_SYM (1UL << 5)
+#define RTEMS_RTL_TRACE_LOAD_SECT (1UL << 6)
+#define RTEMS_RTL_TRACE_ALLOCATOR (1UL << 7)
+#define RTEMS_RTL_TRACE_UNRESOLVED (1UL << 8)
+#define RTEMS_RTL_TRACE_DETAIL (1UL << 9)
+
+/**
+ * Call to check if this part is bring traced. If RTEMS_RTL_TRACE is defined to
+ * 0 the code is dead code elminiated when built with -Os, -O2, or higher.
+ *
+ * @param mask The part of the API to trace.
+ * @retval true Tracing is active for the mask.
+ * @retval false Do not trace.
+ */
+#if RTEMS_RTL_TRACE
+bool rtems_rtl_trace (rtems_rtl_trace_mask mask);
+#else
+#define rtems_rtl_trace(_m) (0)
+#endif
+
+/**
+ * Set the mask.
+ *
+ * @param mask The mask bits to set.
+ * @return The previous mask.
+ */
+#if RTEMS_RTL_TRACE
+rtems_rtl_trace_mask rtems_rtl_trace_set_mask (rtems_rtl_trace_mask mask);
+#else
+#define rtems_rtl_trace_set_mask(_m)
+#endif
+
+/**
+ * Clear the mask.
+ *
+ * @param mask The mask bits to clear.
+ * @return The previous mask.
+ */
+#if RTEMS_RTL_TRACE
+rtems_rtl_trace_mask rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask);
+#else
+#define rtems_rtl_trace_clear_mask(_m)
+#endif
+
+/**
+ * Add shell trace shell command.
+ */
+#if RTEMS_RTL_TRACE
+int rtems_rtl_trace_shell_command (int argc, char *argv[]);
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
new file mode 100644
index 0000000..0dbde0a
--- /dev/null
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -0,0 +1,471 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Unresolved Relocations Table.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-error.h"
+#include "rtl-unresolved.h"
+#include "rtl-trace.h"
+
+static rtems_rtl_unresolv_block_t*
+rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved_t* unresolved)
+{
+ /*
+ * The block header contains a record.
+ */
+ size_t size =
+ (sizeof(rtems_rtl_unresolv_block_t) +
+ (sizeof(rtems_rtl_unresolv_rec_t) * (unresolved->block_recs - 1)));
+ rtems_rtl_unresolv_block_t* block =
+ rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true);
+ if (block)
+ rtems_chain_append (&unresolved->blocks, &block->link);
+ else
+ rtems_rtl_set_error (ENOMEM, "no memory for unresolved block");
+ return block;
+}
+
+static size_t
+rtems_rtl_unresolved_name_recs (const char* name)
+{
+ size_t length = strlen (name);
+ return ((length + sizeof(rtems_rtl_unresolv_name_t) - 1) /
+ sizeof(rtems_rtl_unresolv_name_t));
+}
+
+static int
+rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block_t* block,
+ rtems_rtl_unresolv_rec_t* rec)
+{
+ return (rec - &block->rec) / sizeof (rtems_rtl_unresolv_rec_t);
+}
+
+static rtems_rtl_unresolv_rec_t*
+rtems_rtl_unresolved_rec_first (rtems_rtl_unresolv_block_t* block)
+{
+ return &block->rec;
+}
+
+static rtems_rtl_unresolv_rec_t*
+rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec_t* rec)
+{
+
+ switch (rec->type)
+ {
+ case rtems_rtl_unresolved_empty:
+ /*
+ * Empty returns NULL. The end of the records in the block.
+ */
+ rec = NULL;
+ break;
+
+ case rtems_rtl_unresolved_name:
+ /*
+ * Determine how many records the name occupies. Round up.
+ */
+ rec += ((rec->rec.name.length + sizeof(rtems_rtl_unresolv_name_t) - 1) /
+ sizeof(rtems_rtl_unresolv_name_t));
+ break;
+
+ case rtems_rtl_unresolved_reloc:
+ ++rec;
+ break;
+
+ default:
+ break;
+ }
+
+ return rec;
+}
+
+static bool
+rtems_rtl_unresolved_rec_is_last (rtems_rtl_unresolv_block_t* block,
+ rtems_rtl_unresolv_rec_t* rec)
+{
+ int index = (rec - &block->rec) / sizeof (rec);
+ return !rec || (index >= block->recs) || (rec->type == rtems_rtl_unresolved_empty);
+}
+
+static rtems_rtl_unresolv_rec_t*
+rtems_rtl_unresolved_rec_first_free (rtems_rtl_unresolv_block_t* block)
+{
+ return &block->rec + block->recs;
+}
+
+static int
+rtems_rtl_unresolved_find_name (rtems_rtl_unresolved_t* unresolved,
+ const char* name,
+ bool update_refcount)
+{
+ size_t length = strlen (name);
+ int index = 1;
+
+ rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
+ while (!rtems_chain_is_tail (&unresolved->blocks, node))
+ {
+ rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
+ rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);
+
+ while (!rtems_rtl_unresolved_rec_is_last (block, rec))
+ {
+ if (rec->type == rtems_rtl_unresolved_name)
+ {
+ if ((rec->rec.name.length == length)
+ && (strcmp (rec->rec.name.name, name)))
+ {
+ if (update_refcount)
+ ++rec->rec.name.refs;
+ return index;
+ }
+ ++index;
+ }
+ rec = rtems_rtl_unresolved_rec_next (rec);
+ }
+
+ node = rtems_chain_next (node);
+ }
+
+ return 0 - index;
+}
+
+/**
+ * Struct to pass relocation data in the interator.
+ */
+typedef struct rtems_rtl_unresolved_reloc_data_s
+{
+ uint16_t name; /**< Name index. */
+ rtems_rtl_unresolv_rec_t* name_rec; /**< Name record. */
+ rtems_rtl_obj_sym_t* sym; /**< The symbol record. */
+} rtems_rtl_unresolved_reloc_data_t;
+
+static bool
+rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec_t* rec,
+ void* data)
+{
+ if (rec->type == rtems_rtl_unresolved_reloc)
+ {
+ rtems_rtl_unresolved_reloc_data_t* rd;
+ rd = (rtems_rtl_unresolved_reloc_data_t*) data;
+
+ if (rec->rec.reloc.name == rd->name)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: unresolv: resolve reloc: %s\n", rd->name_rec->rec.name.name);
+
+ rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym);
+
+ /*
+ * Set the object pointer to NULL to indicate the record is not used
+ * anymore. Update the reference count of the name. The sweep after
+ * relocating will remove the reloc records with obj set to NULL and
+ * names with a reference count of 0.
+ */
+ rec->rec.reloc.obj = NULL;
+ if (rd->name_rec && rd->name_rec->rec.name.refs)
+ --rd->name_rec->rec.name.refs;
+ }
+ }
+ return false;
+}
+
+static bool
+rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec_t* rec,
+ void* data)
+{
+ if (rec->type == rtems_rtl_unresolved_name)
+ {
+ rtems_rtl_unresolved_reloc_data_t* rd;
+ rd = (rtems_rtl_unresolved_reloc_data_t*) data;
+
+ ++rd->name;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: unresolv: lookup: %d: %s\n", rd->name, rec->rec.name.name);
+
+ rd->sym = rtems_rtl_symbol_global_find (rec->rec.name.name);
+
+ if (rd->sym)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: unresolv: found: %s\n", rec->rec.name.name);
+
+ rd->name_rec = rec;
+
+ rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_reloc, rd);
+
+ rd->name_rec = NULL;
+ rd->sym = NULL;
+ }
+ }
+
+ return false;
+}
+
+static void
+rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block_t* block,
+ rtems_rtl_unresolv_rec_t* rec,
+ size_t count,
+ size_t recs_per_block)
+{
+ size_t index = rtems_rtl_unresolved_rec_index (block, rec);
+ size_t bytes =
+ (block->recs - index - count) * sizeof (rtems_rtl_unresolv_rec_t);
+ if (bytes)
+ memmove (rec, rec + count, bytes);
+ --block->recs;
+ bytes = count * sizeof (rtems_rtl_unresolv_rec_t);
+ memset (&block->rec + block->recs, 0, bytes);
+}
+
+static void
+rtems_rtl_unresolved_compact (void)
+{
+ rtems_rtl_unresolved_t* unresolved = rtems_rtl_unresolved ();
+ if (unresolved)
+ {
+ /*
+ * Iterate backwards over the blocks removing any used records. A block is
+ * compacted moving up the block.
+ */
+ rtems_chain_node* node = rtems_chain_last (&unresolved->blocks);
+ while (!rtems_chain_is_head (&unresolved->blocks, node))
+ {
+ rtems_chain_node* prev = rtems_chain_previous (node);
+ rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
+ rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);
+
+ while (!rtems_rtl_unresolved_rec_is_last (block, rec))
+ {
+ bool next = true;
+
+ if (rec->type == rtems_rtl_unresolved_name)
+ {
+ if (rec->rec.name.refs == 0)
+ {
+ size_t name_recs = rtems_rtl_unresolved_name_recs (rec->rec.name.name);
+ rtems_rtl_unresolved_clean_block (block, rec, name_recs,
+ unresolved->block_recs);
+ next = false;
+ }
+ }
+ else if (rec->type == rtems_rtl_unresolved_reloc)
+ {
+ if (!rec->rec.reloc.obj)
+ {
+ rtems_rtl_unresolved_clean_block (block, rec, 1,
+ unresolved->block_recs);
+ next = false;
+ }
+ }
+
+ if (next)
+ rec = rtems_rtl_unresolved_rec_next (rec);
+ }
+
+ if (block->recs == 0)
+ {
+ rtems_chain_extract (node);
+ free (block);
+ }
+
+ node = prev;
+ }
+ }
+}
+
+bool
+rtems_rtl_unresolved_table_open (rtems_rtl_unresolved_t* unresolved,
+ size_t block_recs)
+{
+ unresolved->marker = 0xdeadf00d;
+ unresolved->block_recs = block_recs;
+ rtems_chain_initialize_empty (&unresolved->blocks);
+ return true;
+}
+
+void
+rtems_rtl_unresolved_table_close (rtems_rtl_unresolved_t* unresolved)
+{
+ rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
+ while (!rtems_chain_is_tail (&unresolved->blocks, node))
+ {
+ rtems_chain_node* next = rtems_chain_next (node);
+ free (node);
+ node = next;
+ }
+}
+
+bool
+rtems_rtl_unresolved_interate (rtems_rtl_unresolved_iterator_t iterator,
+ void* data)
+{
+ rtems_rtl_unresolved_t* unresolved = rtems_rtl_unresolved ();
+ if (unresolved)
+ {
+ rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
+ while (!rtems_chain_is_tail (&unresolved->blocks, node))
+ {
+ rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
+ rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);
+
+ while (!rtems_rtl_unresolved_rec_is_last (block, rec))
+ {
+ if (iterator (rec, data))
+ return true;
+ rec = rtems_rtl_unresolved_rec_next (rec);
+ }
+
+ node = rtems_chain_next (node);
+ }
+ }
+ return false;
+}
+
+bool
+rtems_rtl_unresolved_add (rtems_rtl_obj_t* obj,
+ const uint16_t flags,
+ const char* name,
+ const uint16_t sect,
+ const rtems_rtl_word_t* rel)
+{
+ rtems_rtl_unresolved_t* unresolved;
+ rtems_chain_node* node;
+ rtems_rtl_unresolv_block_t* block;
+ rtems_rtl_unresolv_rec_t* rec;
+ int name_index;
+ size_t name_recs;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
+ rtems_rtl_obj_oname (obj), sect, name);
+
+ unresolved = rtems_rtl_unresolved ();
+ if (!unresolved)
+ return false;
+
+ /*
+ * Find the first block with a spare record.
+ */
+ node = rtems_chain_first (&unresolved->blocks);
+ block = NULL;
+ while (!rtems_chain_is_tail (&unresolved->blocks, node))
+ {
+ block = (rtems_rtl_unresolv_block_t*) node;
+ if (block->recs < unresolved->block_recs)
+ break;
+ block = NULL;
+ node = rtems_chain_next (node);
+ }
+
+ /*
+ * No blocks with any spare records, allocate a new block.
+ */
+ if (!block)
+ {
+ block = rtems_rtl_unresolved_block_alloc (unresolved);
+ if (!block)
+ return false;
+ }
+
+ name_index = rtems_rtl_unresolved_find_name (unresolved, name, true);
+ name_recs = rtems_rtl_unresolved_name_recs (name);
+
+ /*
+ * An index less than 0 means the name is present and "0 - index" is the next
+ * index to use.
+ */
+ if (name_index < 0)
+ {
+ rtems_rtl_unresolv_block_t* name_block = block;
+
+ /*
+ * Is there enough room to fit the name ? It not add a new block.
+ */
+ if (name_recs > (unresolved->block_recs - block->recs))
+ {
+ name_block = rtems_rtl_unresolved_block_alloc (unresolved);
+ if (!name_block)
+ return false;
+ }
+
+ rec = rtems_rtl_unresolved_rec_first_free (name_block);
+ rec->type = rtems_rtl_unresolved_name;
+ rec->rec.name.refs = 1;
+ rec->rec.name.length = strlen (name) + 1;
+ memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length + 1);
+ block->recs += name_recs;
+ name_index = 0 - name_index;
+
+ /*
+ * If the name block is the reloc block and it is full allocate a new
+ * block for the relocation record.
+ */
+ if ((block == name_block) && (block->recs >= unresolved->block_recs))
+ {
+ block = rtems_rtl_unresolved_block_alloc (unresolved);
+ if (!block)
+ return false;
+ }
+ }
+
+ rec = rtems_rtl_unresolved_rec_first_free (block);
+ rec->type = rtems_rtl_unresolved_reloc;
+ rec->rec.reloc.obj = obj;
+ rec->rec.reloc.flags = flags;
+ rec->rec.reloc.name = name_index;
+ rec->rec.reloc.sect = sect;
+ rec->rec.reloc.rel[0] = rel[0];
+ rec->rec.reloc.rel[1] = rel[1];
+ rec->rec.reloc.rel[2] = rel[2];
+
+ ++block->recs;
+
+ return true;
+}
+
+void
+rtems_rtl_unresolved_resolve (void)
+{
+ rtems_rtl_unresolved_reloc_data_t rd;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: unresolv: global resolve\n");
+ rd.name = 0;
+ rd.name_rec = NULL;
+ rd.sym = NULL;
+ rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_iterator, &rd);
+ rtems_rtl_unresolved_compact ();
+}
+
+bool
+rtems_rtl_unresolved_remove (rtems_rtl_obj_t* obj,
+ const char* name,
+ const uint16_t sect,
+ const rtems_rtl_word_t* rel)
+{
+ rtems_rtl_unresolved_t* unresolved;
+ unresolved = rtems_rtl_unresolved ();
+ if (!unresolved)
+ return false;
+ return false;
+}
+
diff --git a/cpukit/libdl/rtl-unresolved.h b/cpukit/libdl/rtl-unresolved.h
new file mode 100644
index 0000000..5cc5162
--- /dev/null
+++ b/cpukit/libdl/rtl-unresolved.h
@@ -0,0 +1,212 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Unresolved Relocations Table.
+ *
+ * The unresolved relocation table holds relocations in a loaded object file
+ * which reference unresolved external symbols. The support is needed to allow
+ * dependent object files to load. In the case of dependent object files one
+ * will have unresolved externals until the dependent object file is also
+ * loaded. There is no load order that resolves this.
+ *
+ * The unresolved relocation table is a single table used by all object files
+ * with unresolved symbols. It made of blocks linked together where blocks are
+ * allocated as requiered. The table is always maintained compacted. That is as
+ * relocations are resolved and removed the table is compacted. The only
+ * pointer in the table is the object file poniter. This is used to identify
+ * which object the relocation belongs to. There are no linking or back
+ * pointers in the unresolved relocations table. The table is scanned for each
+ * object file's relocations. This is not fast but the table should be small
+ * and if it happens to grow large you have other more pressing issues to
+ * resolve in your application.
+ *
+ * The table holds two (2) types of records:
+ *
+ * # Symbol name strings.
+ * # Relocations.
+ *
+ * The symbol name a relocation references is held in a specific symbol name
+ * string record in the table the relocation record references. The record
+ * counts the number of references and the string is removed from the table
+ * when the reference count reaches 0. There can be many relocations
+ * referencing the symbol. The strings are referenced by a single 16bit
+ * unsigned integer which is the count of the string in the table.
+ *
+ * The section the relocation is for in the object is the section number. The
+ * relocation data is series of machine word sized fields:
+ *
+ * # Offset in the section.
+ * # Relocation info (format specific)
+ * # Additional format specific data.
+ */
+
+#if !defined (_RTEMS_RTL_UNRESOLVED_H_)
+#define _RTEMS_RTL_UNRESOLVED_H_
+
+#include <rtems.h>
+#include "rtl-obj-fwd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Hack to work around machine size. This needs to be cleaned up
+ * to better support 64bit targets.
+ */
+typedef uint32_t rtems_rtl_word_t;
+
+/**
+ * The types of records in the blocks.
+ */
+typedef enum rtems_rtl_unresolved_rtype_e
+{
+ rtems_rtl_unresolved_empty = 0, /**< The records is empty. Must always be 0 */
+ rtems_rtl_unresolved_name = 1, /**< The record is a name. */
+ rtems_rtl_unresolved_reloc = 2 /**< The record is a relocation record. */
+} rtems_rtl_unresolved_rtype_t;
+
+/**
+ * Unresolved externals symbol names. The names are reference counted and
+ * separate from the relocation records because a number of records could
+ * reference the same symbol name.
+ */
+typedef struct rtems_rtl_unresolv_name_s
+{
+ uint16_t refs; /**< The number of references to this name. */
+ uint16_t length; /**< The length of this name. */
+ const char name[12]; /**< The symbol name. */
+} rtems_rtl_unresolv_name_t;
+
+/**
+ * Unresolved externals symbols require the relocation records to be held
+ * and references.
+ */
+typedef struct rtems_rtl_unresolv_reloc_s
+{
+ rtems_rtl_obj_t* obj; /**< The relocation's object file. */
+ uint16_t flags; /**< Format specific flags. */
+ uint16_t name; /**< The symbol's name. */
+ uint16_t sect; /**< The target section. */
+ rtems_rtl_word_t rel[3]; /**< Relocation record. */
+} rtems_rtl_unresolv_reloc_t;
+
+/**
+ * Unresolved externals records.
+ */
+typedef struct rtems_rtl_unresolv_rec_s
+{
+ rtems_rtl_unresolved_rtype_t type;
+ union
+ {
+ rtems_rtl_unresolv_name_t name; /**< The name, or */
+ rtems_rtl_unresolv_reloc_t reloc; /**< the relocation record. */
+ } rec;
+} rtems_rtl_unresolv_rec_t;
+
+/**
+ * Unresolved blocks.
+ */
+typedef struct rtems_rtl_unresolv_block_s
+{
+ rtems_chain_node link; /**< Blocks are chained. */
+ uint32_t recs; /**< The number of records in the block. */
+ rtems_rtl_unresolv_rec_t rec; /**< The records. More follow. */
+} rtems_rtl_unresolv_block_t;
+
+/**
+ * Unresolved table holds the names and relocations.
+ */
+typedef struct rtems_rtl_unresolved_s
+{
+ uint32_t marker;
+ size_t block_recs; /**< The records per blocks allocated. */
+ rtems_chain_control blocks; /**< List of blocks. */
+} rtems_rtl_unresolved_t;
+
+/**
+ * The iterator function used to iterate over the unresolved table.
+ *
+ * @param rec The current iterator.
+ * @param data The user data.
+ * @retval true The iterator has finished.
+ * @retval false The iterator has not finished. Keep iterating.
+ */
+typedef bool rtems_rtl_unresolved_iterator_t (rtems_rtl_unresolv_rec_t* rec,
+ void* data);
+
+/**
+ * Open an unresolved relocation table.
+ *
+ * @param unresolv The unresolved table to open.
+ * @param block_records The number of records per block allocated.
+ * @retval true The table is open.
+ * @retval false The unresolved relocation table could not created. The RTL
+ * error has the error.
+ */
+bool rtems_rtl_unresolved_table_open (rtems_rtl_unresolved_t* unresolved,
+ size_t block_records);
+
+/**
+ * Close the table and erase the blocks.
+ *
+ * @param unreolved Close the unresolved table.
+ */
+void rtems_rtl_unresolved_table_close (rtems_rtl_unresolved_t* unresolved);
+
+/**
+ * Iterate over the table of unresolved entries.
+ */
+bool rtems_rtl_unresolved_interate (rtems_rtl_unresolved_iterator_t iterator,
+ void* data);
+
+/**
+ * Add a relocation to the list of unresolved relocations.
+ *
+ * @param unresolved The unresolved symbol table.
+ * @param obj The object table the symbols are for.
+ * @param flags Format specific flags.
+ * @param name The symbol name the relocation references.
+ * @param sect The target section number the relocation references.
+ * @param rel The format specific relocation data.
+ * @retval true The relocation has been added.
+ * @retval false The relocation could not be added.
+ */
+bool rtems_rtl_unresolved_add (rtems_rtl_obj_t* obj,
+ const uint16_t flags,
+ const char* name,
+ const uint16_t sect,
+ const rtems_rtl_word_t* rel);
+
+/**
+ * Resolve the unresolved symbols.
+ */
+void rtems_rtl_unresolved_resolve (void);
+
+/**
+ * Remove a relocation from the list of unresolved relocations.
+ *
+ * @param unresolved The unresolved symbol table.
+ * @param obj The object table the symbols are for.
+ * @param esyms The exported symbol table.
+ * @param size The size of the table in bytes.
+ */
+bool rtems_rtl_unresolved_remove (rtems_rtl_obj_t* obj,
+ const char* name,
+ const uint16_t sect,
+ const rtems_rtl_word_t* rel);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
new file mode 100644
index 0000000..c55cd94
--- /dev/null
+++ b/cpukit/libdl/rtl.c
@@ -0,0 +1,637 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor
+ *
+ * This is the RTL implementation.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-allocator.h"
+#include "rtl-error.h"
+#include "rtl-string.h"
+#include "rtl-trace.h"
+
+/**
+ * Semaphore configuration to create a mutex.
+ */
+#define RTEMS_MUTEX_ATTRIBS \
+ (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
+ RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
+
+/**
+ * Symbol table cache size. They can be big so the cache needs space to work.
+ */
+#define RTEMS_RTL_ELF_SYMBOL_CACHE (2048)
+
+/**
+ * String table cache size.
+ */
+#define RTEMS_RTL_ELF_STRING_CACHE (2048)
+
+/**
+ * Relocations table cache size.
+ */
+#define RTEMS_RTL_ELF_RELOC_CACHE (2048)
+
+/**
+ * Decompression output buffer.
+ */
+#define RTEMS_RTL_COMP_OUTPUT (2048)
+
+/**
+ * Static RTL data is returned to the user when the linker is locked.
+ */
+static rtems_rtl_data_t* rtl;
+
+/**
+ * Define a default base global symbol loader function that is weak
+ * so a real table can be linked in when the user wants one.
+ */
+void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak));
+void
+rtems_rtl_base_global_syms_init (void)
+{
+ /*
+ * Do nothing.
+ */
+}
+
+static bool
+rtems_rtl_data_init (void)
+{
+ /*
+ * Lock the RTL. We only create a lock if a call is made. First we test if a
+ * lock is present. If one is present we lock it. If not the libio lock is
+ * locked and we then test the lock again. If not present we create the lock
+ * then release libio lock.
+ */
+ if (!rtl)
+ {
+ rtems_libio_lock ();
+
+ if (!rtl)
+ {
+ rtems_status_code sc;
+ rtems_id lock;
+
+ /*
+ * Always in the heap.
+ */
+ rtl = malloc (sizeof (rtems_rtl_data_t));
+ if (!rtl)
+ {
+ errno = ENOMEM;
+ return false;
+ }
+
+ *rtl = (rtems_rtl_data_t) { 0 };
+
+ /*
+ * The initialise the allocator data.
+ */
+ rtems_rtl_alloc_initialise (&rtl->allocator);
+
+ /*
+ * Create the RTL lock.
+ */
+ sc = rtems_semaphore_create (rtems_build_name ('R', 'T', 'L', 'D'),
+ 1, RTEMS_MUTEX_ATTRIBS,
+ RTEMS_NO_PRIORITY, &lock);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ free (rtl);
+ return false;
+ }
+
+ sc = rtems_semaphore_obtain (lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ rtl->lock = lock;
+
+ /*
+ * Initialise the objects list and create any required services.
+ */
+ rtems_chain_initialize_empty (&rtl->objects);
+
+ if (!rtems_rtl_symbol_table_open (&rtl->globals,
+ RTEMS_RTL_SYMS_GLOBAL_BUCKETS))
+ {
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ if (!rtems_rtl_unresolved_table_open (&rtl->unresolved,
+ RTEMS_RTL_UNRESOLVED_BLOCK_SIZE))
+ {
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ if (!rtems_rtl_obj_cache_open (&rtl->symbols,
+ RTEMS_RTL_ELF_SYMBOL_CACHE))
+ {
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_rtl_unresolved_table_close (&rtl->unresolved);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ if (!rtems_rtl_obj_cache_open (&rtl->strings,
+ RTEMS_RTL_ELF_STRING_CACHE))
+ {
+ rtems_rtl_obj_cache_close (&rtl->symbols);
+ rtems_rtl_unresolved_table_close (&rtl->unresolved);
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ if (!rtems_rtl_obj_cache_open (&rtl->relocs,
+ RTEMS_RTL_ELF_RELOC_CACHE))
+ {
+ rtems_rtl_obj_cache_close (&rtl->strings);
+ rtems_rtl_obj_cache_close (&rtl->symbols);
+ rtems_rtl_unresolved_table_close (&rtl->unresolved);
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ if (!rtems_rtl_obj_comp_open (&rtl->decomp,
+ RTEMS_RTL_COMP_OUTPUT))
+ {
+ rtems_rtl_obj_cache_close (&rtl->relocs);
+ rtems_rtl_obj_cache_close (&rtl->strings);
+ rtems_rtl_obj_cache_close (&rtl->symbols);
+ rtems_rtl_unresolved_table_close (&rtl->unresolved);
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ rtl->base = rtems_rtl_obj_alloc ();
+ if (!rtl->base)
+ {
+ rtems_rtl_obj_comp_close (&rtl->decomp);
+ rtems_rtl_obj_cache_close (&rtl->relocs);
+ rtems_rtl_obj_cache_close (&rtl->strings);
+ rtems_rtl_obj_cache_close (&rtl->symbols);
+ rtems_rtl_unresolved_table_close (&rtl->unresolved);
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
+ /*
+ * Need to malloc the memory so the free does not complain.
+ */
+ rtl->base->oname = rtems_rtl_strdup ("rtems-kernel");
+
+ rtems_chain_append (&rtl->objects, &rtl->base->link);
+ }
+
+ rtems_libio_unlock ();
+
+ rtems_rtl_path_append (".");
+
+ rtems_rtl_base_global_syms_init ();
+
+ rtems_rtl_unlock ();
+ }
+ return true;
+}
+
+rtems_rtl_data_t*
+rtems_rtl_data (void)
+{
+ return rtl;
+}
+
+rtems_rtl_symbols_t*
+rtems_rtl_global_symbols (void)
+{
+ if (!rtl)
+ {
+ rtems_rtl_set_error (ENOENT, "no rtl");
+ return NULL;
+ }
+ return &rtl->globals;
+}
+
+rtems_rtl_unresolved_t*
+rtems_rtl_unresolved (void)
+{
+ if (!rtl)
+ {
+ rtems_rtl_set_error (ENOENT, "no rtl");
+ return NULL;
+ }
+ return &rtl->unresolved;
+}
+
+void
+rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols,
+ rtems_rtl_obj_cache_t** strings,
+ rtems_rtl_obj_cache_t** relocs)
+{
+ if (!rtl)
+ {
+ if (symbols)
+ *symbols = NULL;
+ if (strings)
+ *strings = NULL;
+ if (relocs)
+ *relocs = NULL;
+ }
+ else
+ {
+ if (symbols)
+ *symbols = &rtl->symbols;
+ if (strings)
+ *strings = &rtl->strings;
+ if (relocs)
+ *relocs = &rtl->relocs;
+ }
+}
+
+void
+rtems_rtl_obj_caches_flush ()
+{
+ if (rtl)
+ {
+ rtems_rtl_obj_cache_flush (&rtl->symbols);
+ rtems_rtl_obj_cache_flush (&rtl->strings);
+ rtems_rtl_obj_cache_flush (&rtl->relocs);
+ }
+}
+
+void
+rtems_rtl_obj_comp (rtems_rtl_obj_comp_t** decomp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset)
+{
+ if (!rtl)
+ {
+ *decomp = NULL;
+ }
+ else
+ {
+ *decomp = &rtl->decomp;
+ rtems_rtl_obj_comp_set (*decomp, cache, fd, compression, offset);
+ }
+}
+
+rtems_rtl_data_t*
+rtems_rtl_lock (void)
+{
+ rtems_status_code sc;
+
+ if (!rtems_rtl_data_init ())
+ return NULL;
+
+ sc = rtems_semaphore_obtain (rtl->lock,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return rtl;
+}
+
+bool
+rtems_rtl_unlock (void)
+{
+ /*
+ * Not sure any error should be returned or an assert.
+ */
+ rtems_status_code sc;
+ sc = rtems_semaphore_release (rtl->lock);
+ if ((sc != RTEMS_SUCCESSFUL) && (errno == 0))
+ {
+ errno = EINVAL;
+ return false;
+ }
+ return true;
+}
+
+rtems_rtl_obj_t*
+rtems_rtl_check_handle (void* handle)
+{
+ rtems_rtl_obj_t* obj;
+ rtems_chain_node* node;
+
+ obj = handle;
+ node = rtems_chain_first (&rtl->objects);
+
+ while (!rtems_chain_is_tail (&rtl->objects, node))
+ {
+ rtems_rtl_obj_t* check = (rtems_rtl_obj_t*) node;
+ if (check == obj)
+ return obj;
+ node = rtems_chain_next (node);
+ }
+
+ return NULL;
+}
+
+rtems_rtl_obj_t*
+rtems_rtl_find_obj (const char* name)
+{
+ rtems_chain_node* node;
+ rtems_rtl_obj_t* found = NULL;
+ const char* aname = NULL;
+ const char* oname = NULL;
+ off_t ooffset;
+
+ if (!rtems_rtl_parse_name (name, &aname, &oname, &ooffset))
+ return NULL;
+
+ node = rtems_chain_first (&rtl->objects);
+
+ while (!rtems_chain_is_tail (&rtl->objects, node))
+ {
+ rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
+ if ((aname == NULL && strcmp (obj->oname, oname) == 0) ||
+ (aname != NULL &&
+ strcmp (obj->aname, aname) == 0 && strcmp (obj->oname, oname) == 0))
+ {
+ found = obj;
+ break;
+ }
+ node = rtems_chain_next (node);
+ }
+
+ if (!aname)
+ rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) aname);
+
+ if (!oname)
+ rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) oname);
+
+ return found;
+}
+
+rtems_rtl_obj_t*
+rtems_rtl_load_object (const char* name, int mode)
+{
+ rtems_rtl_obj_t* obj;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: loading '%s'\n", name);
+
+ /*
+ * See if the object module has already been loaded.
+ */
+ obj = rtems_rtl_find_obj (name);
+ if (!obj)
+ {
+ /*
+ * Allocate a new object file descriptor and attempt to load it.
+ */
+ obj = rtems_rtl_obj_alloc ();
+ if (obj == NULL)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for object descriptor");
+ return NULL;
+ }
+
+ /*
+ * Find the file in the file system using the search path. The fname field
+ * will point to a valid file name if found.
+ */
+ if (!rtems_rtl_obj_find_file (obj, name))
+ {
+ rtems_rtl_obj_free (obj);
+ return NULL;
+ }
+
+ rtems_chain_append (&rtl->objects, &obj->link);
+
+ if (!rtems_rtl_obj_load (obj))
+ {
+ rtems_rtl_obj_free (obj);
+ return NULL;
+ }
+
+ rtems_rtl_unresolved_resolve ();
+ }
+
+ /*
+ * Increase the number of users.
+ */
+ ++obj->users;
+
+ /*
+ * FIXME: Resolving existing unresolved symbols could add more constructors
+ * lists that need to be called. Make a list in the obj load layer and
+ * invoke the list here.
+ */
+
+ /*
+ * Run any local constructors if this is the first user because the object
+ * file will have just been loaded. Unlock the linker to avoid any dead locks
+ * if the object file needs to load files or update the symbol table. We also
+ * do not want a constructor to unload this object file.
+ */
+ if (obj->users == 1)
+ {
+ obj->flags |= RTEMS_RTL_OBJ_LOCKED;
+ rtems_rtl_unlock ();
+ rtems_rtl_obj_run_ctors (obj);
+ rtems_rtl_lock ();
+ obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
+ }
+
+ return obj;
+}
+
+bool
+rtems_rtl_unload_object (rtems_rtl_obj_t* obj)
+{
+ bool ok = true;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
+ printf ("rtl: unloading '%s'\n", rtems_rtl_obj_fname (obj));
+
+ /*
+ * If the object is locked it cannot be unloaded and the unload fails.
+ */
+ if ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == RTEMS_RTL_OBJ_LOCKED)
+ {
+ rtems_rtl_set_error (EINVAL, "cannot unload when locked");
+ return false;
+ }
+
+ /*
+ * Check the number of users in a safe manner. If this is the last user unload the
+ * object file from memory.
+ */
+ if (obj->users > 0)
+ --obj->users;
+
+ if (obj->users == 0)
+ {
+ obj->flags |= RTEMS_RTL_OBJ_LOCKED;
+ rtems_rtl_unlock ();
+ rtems_rtl_obj_run_dtors (obj);
+ rtems_rtl_lock ();
+ obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
+
+ ok = rtems_rtl_obj_unload (obj);
+ }
+
+ return ok;
+}
+
+void
+rtems_rtl_run_ctors (rtems_rtl_obj_t* obj)
+{
+ rtems_rtl_obj_run_ctors (obj);
+}
+
+static bool
+rtems_rtl_path_update (bool prepend, const char* path)
+{
+ char* paths;
+ const char* src = NULL;
+ char* dst;
+ int len;
+
+ if (!rtems_rtl_lock ())
+ return false;
+
+ len = strlen (path);
+
+ if (rtl->paths)
+ len += strlen (rtl->paths) + 1;
+ else
+ prepend = true;
+
+ paths = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, len + 1, false);
+
+ if (!paths)
+ {
+ rtems_rtl_unlock ();
+ return false;
+ }
+
+ dst = paths;
+
+ if (prepend)
+ {
+ len = strlen (path);
+ src = path;
+ }
+ else if (rtl->paths)
+ {
+ len = strlen (rtl->paths);
+ src = rtl->paths;
+ }
+
+ memcpy (dst, src, len);
+
+ dst += len;
+
+ if (rtl->paths)
+ {
+ *dst = ':';
+ ++dst;
+ }
+
+ if (prepend)
+ {
+ src = rtl->paths;
+ if (src)
+ len = strlen (src);
+ }
+ else
+ {
+ len = strlen (path);
+ src = path;
+ }
+
+ if (src)
+ {
+ memcpy (dst, src, len);
+ dst += len;
+ }
+
+ *dst = '\0';
+
+ rtl->paths = paths;
+
+ rtems_rtl_unlock ();
+ return false;
+}
+
+bool
+rtems_rtl_path_append (const char* path)
+{
+ return rtems_rtl_path_update (false, path);
+}
+
+bool
+rtems_rtl_path_prepend (const char* path)
+{
+ return rtems_rtl_path_update (true, path);
+}
+
+void
+rtems_rtl_base_sym_global_add (const unsigned char* esyms,
+ unsigned int size)
+{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
+ printf ("rtl: adding global symbols, table size %u\n", size);
+
+ if (!rtems_rtl_lock ())
+ {
+ rtems_rtl_set_error (EINVAL, "global add cannot lock rtl");
+ return;
+ }
+
+ rtems_rtl_symbol_global_add (rtl->base, esyms, size);
+
+ rtems_rtl_unlock ();
+}
+
+rtems_rtl_obj_t*
+rtems_rtl_baseimage (void)
+{
+ return NULL;
+}
diff --git a/cpukit/libdl/rtl.h b/cpukit/libdl/rtl.h
new file mode 100644
index 0000000..d0a0d00
--- /dev/null
+++ b/cpukit/libdl/rtl.h
@@ -0,0 +1,320 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker
+ *
+ * This is the POSIX interface to run-time loading of code into RTEMS.
+ */
+
+#if !defined (_RTEMS_RTL_H_)
+#define _RTEMS_RTL_H_
+
+#include <link.h>
+#include <rtems.h>
+#include <rtems/chain.h>
+
+#include <rtems/rtl/rtl-allocator.h>
+#include <rtems/rtl/rtl-fwd.h>
+#include <rtems/rtl/rtl-obj.h>
+#include <rtems/rtl/rtl-obj-cache.h>
+#include <rtems/rtl/rtl-obj-comp.h>
+#include <rtems/rtl/rtl-unresolved.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup rtems_rtl RTEMS Runtime Link Editor
+ *
+ * The module implements a runtime link editor with the standard dlopen, and
+ * dlclose family of functions.
+ *
+ * The runtime link editor is different to that found on Unix type systems. The
+ * object modules are compiled for PIC or position indepentent code and
+ * therefore require relocating when loaded.
+ *
+ * The object file format is currently ELF and object files can be separate
+ * files or in an archive. Object files in an archive are referenced by
+ * specifing 'archive:object' format. For example 'libfoo.a:bar.o'.
+ */
+
+/**
+ * Macros to glue two tokens.
+ */
+#ifdef __STDC__
+#define RTL_XGLUE(a,b) a##b
+#else
+#define RTL_XGLUE(a,b) a/**/b
+#endif
+
+#define RTL_GLUE(a,b) RTL_XGLUE(a,b)
+
+/**
+ * The number of buckets in the global symbol table.
+ */
+#define RTEMS_RTL_SYMS_GLOBAL_BUCKETS (32)
+
+/**
+ * The number of relocation record per block in the unresolved table.
+ */
+#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64)
+
+/**
+ * The global debugger interface variable.
+ */
+extern struct r_debug _rtld_debug;
+
+/**
+ * Debugger break function. Call when debugging to have it read the _rtld_debug
+ * variable.
+ */
+extern void _rtld_debug_state (void);
+
+/**
+ * The type of constructor/destructor function.
+ */
+typedef void (*rtems_rtl_cdtor_t)(void);
+
+/**
+ * The global RTL data. This structure is allocated on the heap when the first
+ * call to the RTL is made and never released.
+ *
+ * The global symbol table is a hash table held in this structure and the
+ * actual symbols are part of the object's structure. If this is a problem we
+ * could look at a hash table per object file.
+ */
+struct rtems_rtl_data_s
+{
+ rtems_id lock; /**< The RTL lock id */
+ rtems_rtl_alloc_data_t allocator; /**< The allocator data. */
+ rtems_chain_control objects; /**< List if loaded object files. */
+ const char* paths; /**< Search paths for archives. */
+ rtems_rtl_symbols_t globals; /**< Global symbol table. */
+ rtems_rtl_unresolved_t unresolved; /**< Unresolved symbols. */
+ rtems_rtl_obj_t* base; /**< Base object file. */
+ rtems_rtl_obj_cache_t symbols; /**< Symbols object file cache. */
+ rtems_rtl_obj_cache_t strings; /**< Strings object file cache. */
+ rtems_rtl_obj_cache_t relocs; /**< Relocations object file cache. */
+ rtems_rtl_obj_comp_t decomp; /**< The decompression compressor. */
+ int last_errno; /**< Last error number. */
+ char last_error[64]; /**< Last error string. */
+};
+
+/**
+ * Get the RTL data with out locking. This call assmes the RTL is locked.
+ *
+ * @return rtems_rtl_data_t* The RTL data after being locked.
+ * @retval NULL The RTL data is not initialised.
+ */
+rtems_rtl_data_t* rtems_rtl_data (void);
+
+/**
+ * Get the RTL global symbol table with out locking. This call assmes the RTL
+ * is locked.
+ *
+ * @return rtems_rtl_symbols_t* The RTL global symbols after being locked.
+ * @retval NULL The RTL data is not initialised.
+ */
+rtems_rtl_symbols_t* rtems_rtl_global_symbols (void);
+
+/**
+ * Get the RTL resolved table with out locking. This call assmes the RTL
+ * is locked.
+ *
+ * @return rtems_rtl_unresolv_t* The RTL unresolved symbols and reloc records.
+ * @retval NULL The RTL data is not initialised.
+ */
+rtems_rtl_unresolved_t* rtems_rtl_unresolved (void);
+
+/**
+ * Get the RTL symbols, strings, or relocations object file caches. This call
+ * assmes the RTL is locked.
+ *
+ * @param symbols Pointer to the location to set the cache into. Returns NULL
+ * is rtl is not initialised. If NULL is passed in no value set.
+ * @param strings Pointer to the location to set the cache into. Returns NULL
+ * is rtl is not initialised. If NULL is passed in no value set.
+ * @param relocs Pointer to the location to set the cache into. Returns NULL
+ * is rtl is not initialised. If NULL is passed in no value set.
+ */
+void rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols,
+ rtems_rtl_obj_cache_t** strings,
+ rtems_rtl_obj_cache_t** relocs);
+
+/**
+ * Flush all the object file caches.
+ */
+void rtems_rtl_obj_caches_flush (void);
+
+/**
+ * Get the RTL decompressor setting the cache and the offset in the file the
+ * compressed stream starts. This call assmes the RTL is locked.
+ *
+ * @param decomp Pointer to the location to set the compressor into. Returns
+ * NULL is rtl is not initialised.
+ * @param cache The cache to read the file with. Saves needing an extrs buffer.
+ * @param offset The offset in the file the compressed stream starts.
+ */
+void rtems_rtl_obj_comp (rtems_rtl_obj_comp_t** decomp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset);
+
+/**
+ * Lock the Run-time Linker.
+ *
+ * @return rtems_rtl_data_t* The RTL data after being locked.
+ * @retval NULL The RTL data could not be initialised or locked. Typically this
+ * means the lock could not be created.
+ */
+rtems_rtl_data_t* rtems_rtl_lock (void);
+
+/**
+ * Unlock the Run-time Linker.
+ *
+ * @return True The RTL is unlocked.
+ * @return False The RTL could not be unlocked. Not much you can do.
+ */
+bool rtems_rtl_unlock (void);
+
+/**
+ * Check a pointer is a valid object file descriptor returning the pointer as
+ * that type.
+ *
+ * Assumes the RTL has been locked.
+ *
+ * @param handle Pointer to the object file to be validated.
+ * @return rtl_obj* The object file descriptor. NULL is returned if invalid.
+ */
+rtems_rtl_obj_t* rtems_rtl_check_handle (void* handle);
+
+/**
+ * Find the object given a file name.
+ *
+ * @param name The name of the object file.
+ * @retval NULL No object file with that name found.
+ * @return rtems_rtl_obj_t* The object file descriptor.
+ */
+rtems_rtl_obj_t* rtems_rtl_find_obj (const char* name);
+
+/**
+ * Load an object file into memory relocating it. It will not be resolved
+ * against other symbols in other object files or the base image.
+ *
+ * The name can be a file name for an object file or it can be encoded to
+ * reference an archive of object modules (static library). This encoding is
+ * specific to RTEMS and allows dependences to specify an archive without the
+ * searching overhead normally incurred by linkers locating object files in an
+ * archive. The file name format rules are:
+ *
+ * 1. Absolute file references a specific object file in the architecture
+ * specific location on the file system.
+ *
+ * 2. Relative file references an object format file in the search path.
+ *
+ * 3. Absolute archive and file reference to a specific location in the file
+ * system. The archive and file are encoded as 'archive:file [@offset]'
+ * where 'archive' is a valid file at the absolute path in the file system,
+ * and 'file' is a contained in the archive, and optionally an offset to
+ * the 'file' in the 'archive'. If no offset is provided the archive is
+ * searched.
+ *
+ * 4. Relative archive and file in the search path. The encoding is the same
+ * as described in item 3 of this list.
+ *
+ * Assumes the RTL has been locked.
+ *
+ * @param name The name of the object file.
+ * @param mode The mode of the load as defined by the dlopen call.
+ * @return rtl_obj* The object file descriptor. NULL is returned if the load fails.
+ */
+rtems_rtl_obj_t* rtems_rtl_load_object (const char* name, int mode);
+
+/**
+ * Unload an object file. This only happens when the user count is 0.
+ *
+ * Assumes the RTL has been locked.
+ *
+ * @param obj The object file descriptor.
+ * @retval true The object file has been unloaded.
+ * @retval false The object file could not be unloaded.
+ */
+bool rtems_rtl_unload_object (rtems_rtl_obj_t* obj);
+
+/**
+ * Run any constructor functions the object file may contain. This call
+ * assumes the linker is unlocked.
+ *
+ * @param obj The object file.
+ */
+void rtems_rtl_run_ctors (rtems_rtl_obj_t* obj);
+
+/**
+ * Get the last error message clearing it. This operation locks the run time
+ * linker and therefore keeps the RTL thread safe but this call is not thread
+ * safe is multiple threads are loading object files at the same time. This
+ * call is provided to map to the dlopen family of calls.
+ *
+ * @param message Pointer to a buffer to copy the message into.
+ * @param max_message The maximum message that can be copied.
+ * @return int The last error number.
+ */
+int rtems_rtl_get_error (char* message, size_t max_message);
+
+/**
+ * Append the path to the search path.
+ *
+ * @path The path to append.
+ * @retval false The path could not be appended.
+ * @retval true The path was appended.
+ */
+bool rtems_rtl_path_append (const char* path);
+
+/**
+ * Prepend the path to the search path.
+ *
+ * @path The path to prepend.
+ * @retval false The path could not be prepended.
+ * @retval true The path was prepended.
+ */
+
+bool rtems_rtl_path_prepend (const char* path);
+
+/**
+ * Add an exported symbol table to the global symbol table. This call is
+ * normally used by an object file when loaded that contains a global symbol
+ * table.
+ *
+ * @param esyms The exported symbol table.
+ * @param count The size of the exported symbol table.
+ */
+void rtems_rtl_base_sym_global_add (const unsigned char* esyms,
+ unsigned int count);
+
+/**
+ * Return the object file descriptor for the base image. The object file
+ * descriptor returned is created when the run time linker is initialised.
+ *
+ * Assumes the RTL has been locked.
+ *
+ * @return rtl_obj* The object file descriptor for the base image. NULL is
+ * returned if the load fails.
+ */
+rtems_rtl_obj_t* rtems_rtl_baseimage (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am
index 1d9cd53..4a6c25b 100644
--- a/cpukit/preinstall.am
+++ b/cpukit/preinstall.am
@@ -46,7 +46,6 @@ $(PROJECT_INCLUDE)/utf8proc/utf8proc.h: libmisc/utf8proc/utf8proc.h $(PROJECT_IN
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/utf8proc/utf8proc.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/utf8proc/utf8proc.h
-if NEWLIB
$(PROJECT_INCLUDE)/sys/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/sys
@: > $(PROJECT_INCLUDE)/sys/$(dirstamp)
@@ -130,6 +129,92 @@ $(PROJECT_INCLUDE)/rtems/bsdnet/_types.h: libnetworking/rtems/bsdnet/_types.h $(
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bsdnet/_types.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bsdnet/_types.h
endif
+if LIBDL
+$(PROJECT_INCLUDE)/dlfcn.h: libdl/dlfcn.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dlfcn.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/dlfcn.h
+
+$(PROJECT_INCLUDE)/link.h: libdl/include/link.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/link.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/link.h
+
+$(PROJECT_INCLUDE)/link_elf.h: libdl/include/link_elf.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/link_elf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/link_elf.h
+
+$(PROJECT_INCLUDE)/sys/cdefs_elf.h: libdl/include/sys/cdefs_elf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/cdefs_elf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/cdefs_elf.h
+
+$(PROJECT_INCLUDE)/sys/exec_elf.h: libdl/include/sys/exec_elf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/exec_elf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/exec_elf.h
+
+$(PROJECT_INCLUDE)/machine/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/machine
+ @: > $(PROJECT_INCLUDE)/machine/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/machine/$(dirstamp)
+
+$(PROJECT_INCLUDE)/machine/elf_machdep.h: libdl/include/arch/@RTEMS_CPU@/machine/elf_machdep.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/elf_machdep.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/elf_machdep.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/rtems/rtl
+ @: > $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/rtl/dlfcn-shell.h: libdl/dlfcn-shell.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/dlfcn-shell.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/dlfcn-shell.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl.h: libdl/rtl.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-allocator.h: libdl/rtl-allocator.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-allocator.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-allocator.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-fwd.h: libdl/rtl-obj-fwd.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-fwd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-fwd.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-fwd.h: libdl/rtl-fwd.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-fwd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-fwd.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj.h: libdl/rtl-obj.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-cache.h: libdl/rtl-obj-cache.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-cache.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-cache.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-comp.h: libdl/rtl-obj-comp.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-comp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-comp.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-unresolved.h: libdl/rtl-unresolved.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-unresolved.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-unresolved.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-indirect-ptr.h: libdl/rtl-indirect-ptr.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-indirect-ptr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-indirect-ptr.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h: libdl/rtl-sym.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rap.h: libdl/rap.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rap.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rap.h
+
+$(PROJECT_INCLUDE)/rtems/rtl/rap-shell.h: libdl/rap-shell.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rap-shell.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rap-shell.h
endif
$(PROJECT_INCLUDE)/rtems/bspIo.h: include/rtems/bspIo.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bspIo.h
diff --git a/cpukit/wrapup/Makefile.am b/cpukit/wrapup/Makefile.am
index e89426f..bf38cca 100644
--- a/cpukit/wrapup/Makefile.am
+++ b/cpukit/wrapup/Makefile.am
@@ -77,6 +77,10 @@ if NEWLIB
TMP_LIBS += ../libmd/libmd.a
endif
+if LIBDL
+TMP_LIBS += ../libdl/libdl.a
+endif
+
librtemscpu.a: $(TMP_LIBS)
rm -f $@
$(MKDIR_P) $(ARCH)
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index f6a2778..fbc2ac9 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -14,7 +14,7 @@ _SUBDIRS += block14
_SUBDIRS += block13
_SUBDIRS += rbheap01
_SUBDIRS += flashdisk01
-_SUBDIRS += capture01
+_SUBDIRS += capture01
_SUBDIRS += bspcmdline01 cpuuse devfs01 devfs02 devfs03 devfs04 \
deviceio01 devnullfatal01 dumpbuf01 gxx01 \
@@ -36,5 +36,9 @@ _SUBDIRS += ftp01
_SUBDIRS += syscall01
endif
+if DLTESTS
+_SUBDIRS += dl01
+endif
+
include $(top_srcdir)/../automake/test-subdirs.am
include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index e246680..f02ceee 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -41,6 +41,18 @@ AM_CONDITIONAL([HAS_COMPLEX],[test "$ac_cv_header_complex_h" = yes])
AM_CONDITIONAL(NETTESTS,test "$rtems_cv_RTEMS_NETWORKING" = "yes")
AM_CONDITIONAL(HAS_POSIX,test x"${rtems_cv_RTEMS_POSIX_API}" = x"yes")
+# Must match the list in cpukit.
+AC_MSG_CHECKING([whether CPU supports libdl])
+case $RTEMS_CPU in
+ arm | bfin | h8300 | i386 | lm32 | m32r | m68k | mips | \
+ moxie | nios2 | powerpc | sparc | v850)
+ HAVE_LIBDL=yes ;;
+ *)
+ HAVE_LIBDL=no ;;
+esac
+AM_CONDITIONAL(DLTESTS,[test x"$HAVE_LIBDL" = x"yes"])
+AC_MSG_RESULT([$HAVE_LIBDL])
+
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
newlib01/Makefile
@@ -78,6 +90,7 @@ devfs03/Makefile
devfs04/Makefile
deviceio01/Makefile
devnullfatal01/Makefile
+dl01/Makefile
dumpbuf01/Makefile
ftp01/Makefile
gxx01/Makefile
diff --git a/testsuites/libtests/dl01/Makefile.am b/testsuites/libtests/dl01/Makefile.am
new file mode 100644
index 0000000..df62d60
--- /dev/null
+++ b/testsuites/libtests/dl01/Makefile.am
@@ -0,0 +1,43 @@
+rtems_tests_PROGRAMS = dl01
+dl01_SOURCES = init.c dl-load.c dl-tar.c dl-tar.h
+
+BUILT_SOURCES = dl-tar.c dl-tar.h
+
+dist_rtems_tests_DATA = dl01.scn dl01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(dl01_OBJECTS)
+LINK_LIBS = $(dl01_LDLIBS)
+
+dl-o1.o: dl-o1.c
+
+dl.tar: dl-o1.o
+ @rm -f $@
+ $(PAX) -w -f $@ $<
+
+dl-tar.c: dl.tar
+ $(BIN2C) -C $< $@
+CLEANFILES += dl-tar.c
+
+dl-tar.h: dl.tar
+ $(BIN2C) -H $< $@
+CLEANFILES += dl-tar.h
+
+dl01.pre$(EXEEXT): $(dl01_OBJECTS) $(dl01_DEPENDENCIES)
+ @rm -f dl01.pre$(EXEEXT)
+ $(make-exe)
+
+dl-sym.o: dl01.pre$(EXEEXT)
+ rtems-syms -e -c "$(CFLAGS)" -o $@ $<
+
+dl01$(EXEEXT): $(dl01_OBJECTS) $(dl01_DEPENDENCIES) dl-sym.o
+ @rm -f dl01$(EXEEXT)
+ $(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) \
+ -o $(basename $@)$(EXEEXT) $(LINK_OBJS) dl-sym.o $(LINK_LIBS)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/libtests/dl01/dl-load.c b/testsuites/libtests/dl01/dl-load.c
new file mode 100644
index 0000000..4c21591
--- /dev/null
+++ b/testsuites/libtests/dl01/dl-load.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>. All rights reserved.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdio.h>
+
+#include <dlfcn.h>
+
+#include "dl-load.h"
+
+int dl_load_test(void)
+{
+ void* handle;
+ int unresolved;
+ char* message = "loaded";
+
+ printf("load: /dl-o1.o\n");
+
+ handle = dlopen ("/dl-o1.o", RTLD_NOW | RTLD_GLOBAL);
+ if (!handle)
+ {
+ printf("dlopen failed: %s\n", dlerror());
+ return 1;
+ }
+
+ if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0)
+ message = "dlinfo error checking unresolved status";
+ else if (unresolved)
+ message = "has unresolved externals";
+
+ printf ("handle: %p %s\n", handle, message);
+
+ if (dlclose (handle) < 0)
+ {
+ printf("dlclose failed: %s\n", dlerror());
+ return 1;
+ }
+
+ printf ("handle: %p closed\n", handle);
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl01/dl-load.h b/testsuites/libtests/dl01/dl-load.h
new file mode 100644
index 0000000..3f3910a
--- /dev/null
+++ b/testsuites/libtests/dl01/dl-load.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>. All rights reserved.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#if !defined(_DL_LOAD_H_)
+#define _DL_LOAD_H_
+
+int dl_load_test(void);
+
+#endif
diff --git a/testsuites/libtests/dl01/dl-o1.c b/testsuites/libtests/dl01/dl-o1.c
new file mode 100644
index 0000000..1351cc8
--- /dev/null
+++ b/testsuites/libtests/dl01/dl-o1.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>. All rights reserved.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ * Hello World as a loadable module.
+ */
+
+#include <stdio.h>
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main (int argc, char* argv[]);
+
+int rtems_main (int argc, char* argv[])
+{
+ printf("RTL Loaded module: Hello World\n");
+ return 0;
+}
diff --git a/testsuites/libtests/dl01/dl01.doc b/testsuites/libtests/dl01/dl01.doc
new file mode 100644
index 0000000..e69de29
diff --git a/testsuites/libtests/dl01/dl01.scn b/testsuites/libtests/dl01/dl01.scn
new file mode 100644
index 0000000..e69de29
diff --git a/testsuites/libtests/dl01/init.c b/testsuites/libtests/dl01/init.c
new file mode 100644
index 0000000..d667502
--- /dev/null
+++ b/testsuites/libtests/dl01/init.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>. All rights reserved.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl.h>
+#include <rtems/untar.h>
+
+#include "dl-load.h"
+
+const char rtems_test_name[] = "libdl (RTL) Loader 1";
+
+/* forward declarations to avoid warnings */
+static rtems_task Init(rtems_task_argument argument);
+
+#include "dl-tar.h"
+
+#define TARFILE_START dl_tar
+#define TARFILE_SIZE dl_tar_size
+
+static int test(void)
+{
+ int ret;
+ ret = dl_load_test();
+ if (ret)
+ rtems_test_exit(ret);
+ return 0;
+}
+
+static void Init(rtems_task_argument arg)
+{
+ int te;
+
+ TEST_BEGIN();
+
+ te = Untar_FromMemory((void *)TARFILE_START, (size_t)TARFILE_SIZE);
+ if (te != 0)
+ {
+ printf("untar failed: %d\n", te);
+ rtems_test_exit(1);
+ exit (1);
+ }
+
+ test();
+
+ TEST_END();
+
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MINIMUM_TASK_STACK_SIZE (8U * 1024U)
+
+#define CONFIGURE_EXTRA_TASK_STACKS (8 * 1024)
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+
--
1.9.3 (Apple Git-50)
More information about the devel
mailing list