From ae5fe7e6bca2874c5f1ef077204bb63124fb3db3 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Sun, 26 Oct 2014 18:09:41 -0700 Subject: cpukit: Add libdl with the Runtime Loader (RTL) code. 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 | 24 + testsuites/libtests/dl01/Makefile.am | 43 + testsuites/libtests/dl01/dl-load.c | 77 ++ testsuites/libtests/dl01/dl-load.h | 14 + testsuites/libtests/dl01/dl-o1.c | 31 + testsuites/libtests/dl01/dl01.doc | 0 testsuites/libtests/dl01/dl01.scn | 0 testsuites/libtests/dl01/init.c | 84 ++ 91 files changed, 14746 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 93b07c8a5d..5e0ae72ba8 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 fcf3437a1b..b3c818c861 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 ], + [#include ], [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 ]) AC_CHECK_DECLS([LONG_BIT],,,[#include ]) @@ -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 0000000000..11f1478522 --- /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-@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 0000000000..5655ab1455 --- /dev/null +++ b/cpukit/libdl/dlfcn-shell.c @@ -0,0 +1,117 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 +#include +#include +#include + +#include +#include + +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 0000000000..0406b6c784 --- /dev/null +++ b/cpukit/libdl/dlfcn-shell.h @@ -0,0 +1,17 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 0000000000..7c102022b2 --- /dev/null +++ b/cpukit/libdl/dlfcn.c @@ -0,0 +1,153 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 +#include +#include + +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 0000000000..1ac3ba1330 --- /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 +#include + +#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 0000000000..3c9d6f6f86 --- /dev/null +++ b/cpukit/libdl/fastlz.c @@ -0,0 +1,551 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@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 0000000000..f87bc7be31 --- /dev/null +++ b/cpukit/libdl/fastlz.h @@ -0,0 +1,100 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@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 0000000000..78c88b5af8 --- /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 0000000000..cf0dc19221 --- /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 0000000000..3d049157eb --- /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 0000000000..442c561a9c --- /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 0000000000..29c75b89db --- /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 0000000000..3f531cf901 --- /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 0000000000..9a987c69b5 --- /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 0000000000..d27d431835 --- /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 0000000000..3f0df23cdc --- /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 0000000000..3f3c108bf5 --- /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 0000000000..f0fdb3f33b --- /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 0000000000..e8f2b630c2 --- /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 0000000000..b76d1491d6 --- /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 0000000000..c93efd9e78 --- /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 +#else +#include +#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 0000000000..d2691b68b0 --- /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 + +#include +#include +#include + +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 0000000000..91903d6017 --- /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@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 0000000000..08da7e809e --- /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 +#else +#include +#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 +#else +#include +#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 (16),(16),. */ +#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@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 0000000000..dba6cc4d81 --- /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 0000000000..664f3a3055 --- /dev/null +++ b/cpukit/libdl/rap-shell.c @@ -0,0 +1,106 @@ +/* + * COPYRIGHT (c) 2013 Chris Johns + * + * 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 +#include +#include +#include + +#include +#include + +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 0000000000..c32529d6da --- /dev/null +++ b/cpukit/libdl/rap-shell.h @@ -0,0 +1,14 @@ +/* + * COPYRIGHT (c) 2013 Chris Johns + * + * 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 0000000000..8dec41e416 --- /dev/null +++ b/cpukit/libdl/rap.c @@ -0,0 +1,484 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 +#include +#include + +#include + +#include +#include +#include + +#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 0000000000..e53699f93f --- /dev/null +++ b/cpukit/libdl/rap.h @@ -0,0 +1,115 @@ +/* + * COPYRIGHT (c) 2013 Chris Johns + * + * 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 +#include + +#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: + * + *
+ * + * + * 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 0000000000..44a4816c5d --- /dev/null +++ b/cpukit/libdl/rtl-alloc-heap.c @@ -0,0 +1,33 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 + +#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 0000000000..d9276553e4 --- /dev/null +++ b/cpukit/libdl/rtl-alloc-heap.h @@ -0,0 +1,47 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 + +#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 0000000000..b845013fd8 --- /dev/null +++ b/cpukit/libdl/rtl-allocator.c @@ -0,0 +1,210 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 + +#include +#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 0000000000..8e90b7b81c --- /dev/null +++ b/cpukit/libdl/rtl-allocator.h @@ -0,0 +1,176 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 + +#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 0000000000..39184ee513 --- /dev/null +++ b/cpukit/libdl/rtl-chain-iterator.c @@ -0,0 +1,57 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 0000000000..b3781e07e9 --- /dev/null +++ b/cpukit/libdl/rtl-chain-iterator.h @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 + +/** + * 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 0000000000..2eff2bd055 --- /dev/null +++ b/cpukit/libdl/rtl-debugger.c @@ -0,0 +1,96 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 . 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 +#include +#include +#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 0000000000..e4f1ffc007 --- /dev/null +++ b/cpukit/libdl/rtl-elf.c @@ -0,0 +1,882 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 +#include +#include +#include +#include +#include + +#include +#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 0000000000..115c05aef9 --- /dev/null +++ b/cpukit/libdl/rtl-elf.h @@ -0,0 +1,165 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 +#include + +#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 0000000000..bc2e3e425c --- /dev/null +++ b/cpukit/libdl/rtl-error.c @@ -0,0 +1,47 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 +#include + +#include +#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 0000000000..a17db59adb --- /dev/null +++ b/cpukit/libdl/rtl-error.h @@ -0,0 +1,44 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 0000000000..589be40a10 --- /dev/null +++ b/cpukit/libdl/rtl-find-file.c @@ -0,0 +1,110 @@ +/* + * COPYRIGHT (c) 2012-2013 Chris Johns + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include +#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 0000000000..fc8a9dcf8f --- /dev/null +++ b/cpukit/libdl/rtl-find-file.h @@ -0,0 +1,45 @@ +/* + * COPYRIGHT (c) 2012-2013 Chris Johns + * + * 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 +#include + +#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 0000000000..115ba8c3bc --- /dev/null +++ b/cpukit/libdl/rtl-fwd.h @@ -0,0 +1,33 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 0000000000..5a5b43b9c0 --- /dev/null +++ b/cpukit/libdl/rtl-indirect-ptr.h @@ -0,0 +1,235 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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 + +/** + * 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 0000000000..692c8297a8 --- /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 + +#include +#include +#include +#include + +#include +#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 */ + 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