forked from Imagelibrary/rtems
cpukit: Add libdl with the Runtime Loader (RTL) code.
This is a merge of the RTL project.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -298,7 +298,7 @@ AC_ENABLE_MULTILIB([Makefile],[..])
|
||||
AC_MSG_CHECKING([for assignable stdio])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[#include <stdio.h>],
|
||||
[#include <stdio.h>],
|
||||
[stdin = fopen("/tmp", "r")])],
|
||||
[HAVE_ASSIGNABLE_STDIO=yes],
|
||||
[HAVE_ASSIGNABLE_STDIO=no])
|
||||
@@ -322,7 +322,7 @@ AC_CHECK_SIZEOF([time_t])
|
||||
|
||||
AC_CHECK_SIZEOF([size_t])
|
||||
|
||||
# FIXME: Mandatory in SUSv4, optional in SUSv3.
|
||||
# FIXME: Mandatory in SUSv4, optional in SUSv3.
|
||||
# Not implemented in GCC/newlib, so far.
|
||||
AC_CHECK_DECLS([WORD_BIT],,,[#include <limits.h>])
|
||||
AC_CHECK_DECLS([LONG_BIT],,,[#include <limits.h>])
|
||||
@@ -372,6 +372,19 @@ AM_CONDITIONAL([RPCTOOLS],[test "$RPCGEN" = rpcgen \
|
||||
&& test -n "$AWK" \
|
||||
&& test "$enable_rpcgen" = yes])
|
||||
|
||||
# Filter dynamic loading to only build for architectures that have
|
||||
# reloc backends
|
||||
AC_MSG_CHECKING([whether CPU supports libdl])
|
||||
case $RTEMS_CPU in
|
||||
arm | bfin | h8300 | i386 | lm32 | m32r | m68k | mips | \
|
||||
moxie | nios2 | powerpc | sparc | v850)
|
||||
HAVE_LIBDL=yes ;;
|
||||
*)
|
||||
HAVE_LIBDL=no ;;
|
||||
esac
|
||||
AM_CONDITIONAL(LIBDL,[test x"$HAVE_LIBDL" = x"yes"])
|
||||
AC_MSG_RESULT([$HAVE_LIBDL])
|
||||
|
||||
RTEMS_AMPOLISH3
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
@@ -412,6 +425,7 @@ librpc/Makefile
|
||||
libmisc/Makefile
|
||||
libi2c/Makefile
|
||||
libmd/Makefile
|
||||
libdl/Makefile
|
||||
zlib/Makefile
|
||||
ftpd/Makefile
|
||||
telnetd/Makefile
|
||||
|
||||
36
cpukit/libdl/Makefile.am
Normal file
36
cpukit/libdl/Makefile.am
Normal file
@@ -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
|
||||
117
cpukit/libdl/dlfcn-shell.c
Normal file
117
cpukit/libdl/dlfcn-shell.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor Dynamic Loading API Shell Support.
|
||||
*
|
||||
* Shell command wrappers for the Dynamic Loading API.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <rtems/rtl/dlfcn-shell.h>
|
||||
|
||||
static void*
|
||||
convert_ascii_to_voidp (const char* arg)
|
||||
{
|
||||
if (strcmp (arg, "base") == 0)
|
||||
return RTLD_DEFAULT;
|
||||
return (void*) strtoul (arg, NULL, 16);
|
||||
}
|
||||
|
||||
int
|
||||
shell_dlopen (int argc, char* argv[])
|
||||
{
|
||||
int arg;
|
||||
for (arg = 1; arg < argc; arg++)
|
||||
{
|
||||
void* handle = dlopen (argv[arg], RTLD_NOW | RTLD_GLOBAL);
|
||||
if (handle)
|
||||
{
|
||||
int unresolved;
|
||||
char* message = "loaded";
|
||||
if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0)
|
||||
message = "dlinfo error checking unresolved status";
|
||||
else if (unresolved)
|
||||
message = "has unresolved externals";
|
||||
printf ("handle: %p %s\n", handle, message);
|
||||
}
|
||||
else
|
||||
printf ("error: %s\n", dlerror ());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
shell_dlclose (int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
lookup_dlsym (void** value, int argc, char* argv[])
|
||||
{
|
||||
if (argc >= 3)
|
||||
{
|
||||
void* handle = convert_ascii_to_voidp (argv[1]);
|
||||
if (handle)
|
||||
{
|
||||
*value = dlsym (handle, argv[2]);
|
||||
if (*value)
|
||||
return true;
|
||||
else
|
||||
printf ("error: invalid handle or symbol\n");
|
||||
}
|
||||
else
|
||||
printf ("error: invalid handle");
|
||||
}
|
||||
else
|
||||
printf ("error: requires handle and symbol name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
shell_dlsym (int argc, char* argv[])
|
||||
{
|
||||
void* value;
|
||||
if (lookup_dlsym (&value, argc, argv))
|
||||
{
|
||||
printf ("%s = %p\n", argv[2], value);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef int (*call_t)(int argc, char* argv[]);
|
||||
|
||||
int
|
||||
shell_dlcall (int argc, char* argv[])
|
||||
{
|
||||
void* value;
|
||||
if (lookup_dlsym (&value, argc, argv))
|
||||
{
|
||||
call_t call = value;
|
||||
int r;
|
||||
printf ("(*%p)(%d, ....)\n", value, argc - 3);
|
||||
r = call (argc - 3, argv + 3);
|
||||
printf ("return %d\n", r);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
17
cpukit/libdl/dlfcn-shell.h
Normal file
17
cpukit/libdl/dlfcn-shell.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if !defined(_DLFCN_SHELL_H_)
|
||||
#define _DLFCN_SHELL_H_
|
||||
|
||||
int shell_dlopen (int argc, char* argv[]);
|
||||
int shell_dlclose (int argc, char* argv[]);
|
||||
int shell_dlsym (int argc, char* argv[]);
|
||||
int shell_dlcall (int argc, char* argv[]);
|
||||
|
||||
#endif
|
||||
153
cpukit/libdl/dlfcn.c
Normal file
153
cpukit/libdl/dlfcn.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtl
|
||||
*
|
||||
* @brief RTEMS POSIX Dynamic Module Loading Interface.
|
||||
*
|
||||
* This is the POSIX interface to run-time loading of code into RTEMS.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
#include <rtems/rtl/rtl.h>
|
||||
|
||||
static rtems_rtl_obj_t*
|
||||
dl_get_obj_from_handle (void* handle)
|
||||
{
|
||||
rtems_rtl_obj_t* obj;
|
||||
|
||||
/*
|
||||
* Handle the special cases provided in NetBSD and Sun documentation.
|
||||
* http://download.oracle.com/docs/cd/E19253-01/816-5168/dlsym-3c/index.html
|
||||
* We currently do not manage the loading dependences in the module mappings
|
||||
* so we cannot handle the searching based on loading order where overriding
|
||||
* can occur.
|
||||
*/
|
||||
|
||||
if ((handle == RTLD_DEFAULT) || (handle == RTLD_SELF))
|
||||
obj = rtems_rtl_baseimage ();
|
||||
else
|
||||
obj = rtems_rtl_check_handle (handle);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void*
|
||||
dlopen (const char* name, int mode)
|
||||
{
|
||||
rtems_rtl_obj_t* obj = NULL;
|
||||
|
||||
if (!rtems_rtl_lock ())
|
||||
return NULL;
|
||||
|
||||
_rtld_debug.r_state = RT_ADD;
|
||||
_rtld_debug_state ();
|
||||
|
||||
if (name)
|
||||
obj = rtems_rtl_load_object (name, mode);
|
||||
else
|
||||
obj = rtems_rtl_baseimage ();
|
||||
|
||||
_rtld_debug.r_state = RT_CONSISTENT;
|
||||
_rtld_debug_state();
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
int
|
||||
dlclose (void* handle)
|
||||
{
|
||||
rtems_rtl_obj_t* obj;
|
||||
int r;
|
||||
|
||||
if (!rtems_rtl_lock ())
|
||||
return -1;
|
||||
|
||||
obj = rtems_rtl_check_handle (handle);
|
||||
if (!obj)
|
||||
{
|
||||
rtems_rtl_unlock ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
_rtld_debug.r_state = RT_DELETE;
|
||||
_rtld_debug_state ();
|
||||
|
||||
r = rtems_rtl_unload_object (obj) ? 0 : -1;
|
||||
|
||||
_rtld_debug.r_state = RT_CONSISTENT;
|
||||
_rtld_debug_state ();
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void*
|
||||
dlsym (void* handle, const char *symbol)
|
||||
{
|
||||
rtems_rtl_obj_t* obj;
|
||||
rtems_rtl_obj_sym_t* sym;
|
||||
void* symval = NULL;
|
||||
|
||||
if (!rtems_rtl_lock ())
|
||||
return NULL;
|
||||
|
||||
obj = dl_get_obj_from_handle (handle);
|
||||
if (obj)
|
||||
{
|
||||
sym = rtems_rtl_symbol_obj_find (obj, symbol);
|
||||
if (sym)
|
||||
symval = sym->value;
|
||||
}
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
|
||||
return symval;
|
||||
}
|
||||
|
||||
const char*
|
||||
dlerror (void)
|
||||
{
|
||||
static char msg[64];
|
||||
rtems_rtl_get_error (msg, sizeof (msg));
|
||||
return msg;
|
||||
}
|
||||
|
||||
int
|
||||
dlinfo (void* handle, int request, void* p)
|
||||
{
|
||||
rtems_rtl_obj_t* obj;
|
||||
int rc = -1;
|
||||
|
||||
if (!rtems_rtl_lock () || !p)
|
||||
return -1;
|
||||
|
||||
obj = dl_get_obj_from_handle (handle);
|
||||
if (obj)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case RTLD_DI_UNRESOLVED:
|
||||
*((int*) p) = rtems_rtl_obj_unresolved (obj) ? 1 : 0;
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
|
||||
return rc;
|
||||
}
|
||||
112
cpukit/libdl/dlfcn.h
Normal file
112
cpukit/libdl/dlfcn.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* $NetBSD: dlfcn.h,v 1.21 2010/01/07 07:35:35 skrll Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Paul Kranenburg.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DLFCN_H_
|
||||
#define _DLFCN_H_
|
||||
|
||||
//#include <sys/featuretest.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
typedef struct _dl_info {
|
||||
const char *dli_fname; /* File defining the symbol */
|
||||
void *dli_fbase; /* Base address */
|
||||
const char *dli_sname; /* Symbol name */
|
||||
const void *dli_saddr; /* Symbol address */
|
||||
} Dl_info;
|
||||
#endif /* defined(_NETBSD_SOURCE) */
|
||||
|
||||
/*
|
||||
* User interface to the run-time linker.
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
void *dlopen(const char *, int);
|
||||
int dlclose(void *);
|
||||
void *dlsym(void * __restrict, const char * __restrict);
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
int dladdr(void * __restrict, Dl_info * __restrict);
|
||||
int dlctl(void *, int, void *);
|
||||
#endif
|
||||
int dlinfo(void *, int, void *);
|
||||
const char *dlerror(void);
|
||||
__END_DECLS
|
||||
|
||||
/* Values for dlopen `mode'. */
|
||||
#define RTLD_LAZY 1
|
||||
#define RTLD_NOW 2
|
||||
#define RTLD_GLOBAL 0x100 /* Allow global searches in object */
|
||||
#define RTLD_LOCAL 0x200
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define DL_LAZY RTLD_LAZY /* Compat */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special handle arguments for dlsym().
|
||||
*/
|
||||
#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
|
||||
#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
|
||||
#define RTLD_SELF ((void *) -3) /* Search the caller itself. */
|
||||
|
||||
/*
|
||||
* dlctl() commands
|
||||
*/
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define DL_GETERRNO 1
|
||||
#define DL_GETSYMBOL 2
|
||||
#if 0
|
||||
#define DL_SETSRCHPATH x
|
||||
#define DL_GETLIST x
|
||||
#define DL_GETREFCNT x
|
||||
#define DL_GETLOADADDR x
|
||||
#endif /* 0 */
|
||||
#endif /* defined(_NETBSD_SOURCE) */
|
||||
|
||||
/*
|
||||
* dlinfo() commands
|
||||
*
|
||||
* From Solaris: http://docs.sun.com/app/docs/doc/816-5168/dlinfo-3c?a=view
|
||||
*/
|
||||
#define RTLD_DI_UNRESOLVED 10
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define RTLD_DI_LINKMAP 3
|
||||
#if 0
|
||||
#define RTLD_DI_ARGSINFO 1
|
||||
#define RTLD_DI_CONFIGADDR 2
|
||||
#define RTLD_DI_LMID 4
|
||||
#define RTLD_DI_SERINFO 5
|
||||
#define RTLD_DI_SERINFOSIZE 6
|
||||
#define RTLD_DI_ORIGIN 7
|
||||
#define RTLD_DI_GETSIGNAL 8
|
||||
#define RTLD_DI_SETSIGNAL 9
|
||||
#endif
|
||||
#endif /* _NETBSD_SOURCE */
|
||||
|
||||
#endif /* !defined(_DLFCN_H_) */
|
||||
551
cpukit/libdl/fastlz.c
Normal file
551
cpukit/libdl/fastlz.c
Normal file
@@ -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) */
|
||||
100
cpukit/libdl/fastlz.h
Normal file
100
cpukit/libdl/fastlz.h
Normal file
@@ -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 */
|
||||
131
cpukit/libdl/include/arch/arm/machine/elf_machdep.h
Normal file
131
cpukit/libdl/include/arch/arm/machine/elf_machdep.h
Normal file
@@ -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
|
||||
28
cpukit/libdl/include/arch/bfin/machine/elf_machdep.h
Normal file
28
cpukit/libdl/include/arch/bfin/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
59
cpukit/libdl/include/arch/h8300/machine/elf_machdep.h
Normal file
59
cpukit/libdl/include/arch/h8300/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
63
cpukit/libdl/include/arch/i386/machine/elf_machdep.h
Normal file
63
cpukit/libdl/include/arch/i386/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
34
cpukit/libdl/include/arch/lm32/machine/elf_machdep.h
Normal file
34
cpukit/libdl/include/arch/lm32/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
39
cpukit/libdl/include/arch/m32r/machine/elf_machdep.h
Normal file
39
cpukit/libdl/include/arch/m32r/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
47
cpukit/libdl/include/arch/m68k/machine/elf_machdep.h
Normal file
47
cpukit/libdl/include/arch/m68k/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
196
cpukit/libdl/include/arch/mips/machine/elf_machdep.h
Normal file
196
cpukit/libdl/include/arch/mips/machine/elf_machdep.h
Normal file
@@ -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_ */
|
||||
15
cpukit/libdl/include/arch/moxie/machine/elf_machdep.h
Normal file
15
cpukit/libdl/include/arch/moxie/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
46
cpukit/libdl/include/arch/nios2/machine/elf_machdep.h
Normal file
46
cpukit/libdl/include/arch/nios2/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
105
cpukit/libdl/include/arch/powerpc/machine/elf_machdep.h
Normal file
105
cpukit/libdl/include/arch/powerpc/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
92
cpukit/libdl/include/arch/sparc/machine/elf_machdep.h
Normal file
92
cpukit/libdl/include/arch/sparc/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
74
cpukit/libdl/include/arch/v850/machine/elf_machdep.h
Normal file
74
cpukit/libdl/include/arch/v850/machine/elf_machdep.h
Normal file
@@ -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)
|
||||
45
cpukit/libdl/include/link.h
Normal file
45
cpukit/libdl/include/link.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* $NetBSD: link.h,v 1.13 2008/04/28 20:22:54 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LINK_H_
|
||||
#define _LINK_H_
|
||||
|
||||
/*
|
||||
* Pull in the correct definitions for our toolchain target.
|
||||
*/
|
||||
#ifdef __ELF__
|
||||
#include <link_elf.h>
|
||||
#else
|
||||
#include <link_aout.h>
|
||||
#endif
|
||||
|
||||
#endif /* _LINK_H_ */
|
||||
79
cpukit/libdl/include/link_elf.h
Normal file
79
cpukit/libdl/include/link_elf.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* $NetBSD: link_elf.h,v 1.8 2009/11/04 19:28:03 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* This only exists for GDB.
|
||||
*/
|
||||
|
||||
#ifndef _LINK_ELF_H_
|
||||
#define _LINK_ELF_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <machine/elf_machdep.h>
|
||||
#include <stdint.h>
|
||||
#include <rtems/rtl/rtl-obj-fwd.h>
|
||||
|
||||
enum sections
|
||||
{
|
||||
rap_text = 0,
|
||||
rap_const = 1,
|
||||
rap_ctor = 2,
|
||||
rap_dtor = 3,
|
||||
rap_data = 4,
|
||||
rap_bss = 5,
|
||||
rap_secs = 6
|
||||
};
|
||||
|
||||
/**
|
||||
* Object details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const char* name; /**< Section name. */
|
||||
uint32_t offset; /**< The offset in the elf file. */
|
||||
uint32_t size; /**< The size of the section. */
|
||||
uint32_t rap_id; /**< Which obj does this section belongs to. */
|
||||
}section_detail;
|
||||
|
||||
/**
|
||||
* link map structure will be used for GDB support.
|
||||
*/
|
||||
struct link_map {
|
||||
const char* name; /**< Name of the obj. */
|
||||
uint32_t sec_num; /**< The count of section. */
|
||||
section_detail* sec_detail; /**< The section details. */
|
||||
uint32_t* sec_addr[rap_secs]; /**< The RAP section addr. */
|
||||
uint32_t rpathlen; /**< The length of the path. */
|
||||
char* rpath; /**< The path of object files. */
|
||||
struct link_map* l_next; /**< Linked list of mapped libs. */
|
||||
struct link_map* l_prev;
|
||||
};
|
||||
|
||||
/**
|
||||
* r_debug is used to manage the debug related structures.
|
||||
*/
|
||||
struct r_debug {
|
||||
int r_version; /* not used */
|
||||
struct link_map *r_map; /* list of loaded images */
|
||||
enum {
|
||||
RT_CONSISTENT, /* things are stable */
|
||||
RT_ADD, /* adding a shared library */
|
||||
RT_DELETE /* removing a shared library */
|
||||
} r_state;
|
||||
};
|
||||
|
||||
/*
|
||||
* stub function. It is empty.
|
||||
*/
|
||||
void _rtld_debug_state (void);
|
||||
|
||||
/*
|
||||
* add link map to the list.
|
||||
*/
|
||||
int _rtld_linkmap_add (rtems_rtl_obj_t* obj);
|
||||
|
||||
/*
|
||||
* Remove link map from the list.
|
||||
*/
|
||||
void _rtld_linkmap_delete (rtems_rtl_obj_t* obj);
|
||||
#endif /* _LINK_ELF_H_ */
|
||||
152
cpukit/libdl/include/sys/cdefs_elf.h
Normal file
152
cpukit/libdl/include/sys/cdefs_elf.h
Normal file
@@ -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_ */
|
||||
1097
cpukit/libdl/include/sys/exec_elf.h
Normal file
1097
cpukit/libdl/include/sys/exec_elf.h
Normal file
File diff suppressed because it is too large
Load Diff
7
cpukit/libdl/preinstall.am
Normal file
7
cpukit/libdl/preinstall.am
Normal file
@@ -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
|
||||
|
||||
106
cpukit/libdl/rap-shell.c
Normal file
106
cpukit/libdl/rap-shell.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2013 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Application Loader.
|
||||
*
|
||||
* Shell command wrappers for the RTEMS Application loader.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/rtl/rap.h>
|
||||
#include <rtems/rtl/rap-shell.h>
|
||||
|
||||
static void
|
||||
shell_rap_command_help (void)
|
||||
{
|
||||
printf ("usage: rap [cmd] [arg]\n" \
|
||||
"Commands and options:\n" \
|
||||
"ls: List the loaded applications (also list)\n" \
|
||||
"ld: Load an application (also load)\n" \
|
||||
"un: Unload an application (also unload)\n");
|
||||
}
|
||||
|
||||
static void
|
||||
shell_rap_get_error (const char* what)
|
||||
{
|
||||
char message[64];
|
||||
int error;
|
||||
error = rtems_rap_get_error (message, sizeof (message));
|
||||
printf ("error: %s: (%d) %s\n", what, error, message);
|
||||
}
|
||||
|
||||
static bool
|
||||
shell_rap_list_handler (void* handle)
|
||||
{
|
||||
printf (" %-10p %-10p %-s\n",
|
||||
handle, rtems_rap_dl_handle (handle), rtems_rap_name (handle));
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
shell_rap_list (int argc, char* argv[])
|
||||
{
|
||||
printf (" App DL Handle Name\n");
|
||||
return rtems_rap_iterate (shell_rap_list_handler) ? 0 : 1;
|
||||
}
|
||||
|
||||
static int
|
||||
shell_rap_load (int argc, char* argv[])
|
||||
{
|
||||
int r = 0;
|
||||
if (argc == 0)
|
||||
{
|
||||
printf ("error: no application name\n");
|
||||
return 0;
|
||||
}
|
||||
if (rtems_rap_load (argv[0], 0, argc - 1, (const char**) (argv + 1)))
|
||||
printf ("%s loaded\n", argv[0]);
|
||||
else
|
||||
{
|
||||
r = 1;
|
||||
shell_rap_get_error ("loading");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
shell_rap (int argc, char* argv[])
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
shell_rap_command_help ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((strcmp (argv[1], "ls") == 0) ||
|
||||
(strcmp (argv[1], "list") == 0))
|
||||
{
|
||||
return shell_rap_list (argc - 2, argv + 2);
|
||||
}
|
||||
else if ((strcmp (argv[1], "ld") == 0) ||
|
||||
(strcmp (argv[1], "load") == 0))
|
||||
{
|
||||
return shell_rap_load (argc - 2, argv + 2);
|
||||
}
|
||||
|
||||
printf ("error: invalid command: %s\n", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
14
cpukit/libdl/rap-shell.h
Normal file
14
cpukit/libdl/rap-shell.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2013 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if !defined(_RAP_SHELL_H_)
|
||||
#define _RAP_SHELL_H_
|
||||
|
||||
int shell_rap (int argc, char* argv[]);
|
||||
|
||||
#endif
|
||||
484
cpukit/libdl/rap.c
Normal file
484
cpukit/libdl/rap.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rap
|
||||
*
|
||||
* @brief RTEMS Application Loader
|
||||
*
|
||||
* This is the RAP implementation.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <rtems/rtl/rap.h>
|
||||
#include <rtems/rtl/rtl.h>
|
||||
|
||||
#include "rtl-find-file.h"
|
||||
|
||||
/**
|
||||
* The global RAP data. This structure is allocated on the heap when the first
|
||||
* call to location an application and is never released.
|
||||
*/
|
||||
typedef struct rtems_rap_data_s
|
||||
{
|
||||
rtems_id lock; /**< The RAP lock id */
|
||||
rtems_chain_control apps; /**< List if loaded application. */
|
||||
int last_errno; /**< Last error number. */
|
||||
char last_error[64]; /**< Last error string. */
|
||||
} rtems_rap_data_t;
|
||||
|
||||
/**
|
||||
* The RAP file data. This structure is allocated on the heap when a file is
|
||||
* loaded.
|
||||
*/
|
||||
typedef struct rtems_rap_app_s
|
||||
{
|
||||
rtems_chain_node node; /**< The node's link in the chain. */
|
||||
const char* name; /**< The file name */
|
||||
void* handle; /**< The dlopen handle. */
|
||||
} rtems_rap_app_t;
|
||||
|
||||
/**
|
||||
* Semaphore configuration to create a mutex.
|
||||
*/
|
||||
#define RTEMS_MUTEX_ATTRIBS \
|
||||
(RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
|
||||
RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
|
||||
|
||||
/**
|
||||
* RTL entry.
|
||||
*/
|
||||
#if (RTL_GLUE(__USER_LABEL_PREFIX__, 1) == RTL_GLUE(_, 1))
|
||||
#define RTL_ENTRY_POINT "_rtems"
|
||||
#else
|
||||
#define RTL_ENTRY_POINT "rtems"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Static RAP data is returned to the user when the loader is locked.
|
||||
*/
|
||||
static rtems_rap_data_t rap_;
|
||||
|
||||
/**
|
||||
* Verbose level for the RAP loader.
|
||||
*/
|
||||
static bool rap_verbose;
|
||||
|
||||
/**
|
||||
* RAP entry call signature.
|
||||
*/
|
||||
typedef int (*rtems_rap_entry_t)(int argc, const char* argv[]);
|
||||
|
||||
/**
|
||||
* Forward decl.
|
||||
*/
|
||||
static bool rtems_rap_unlock (void);
|
||||
|
||||
static bool
|
||||
rtems_rap_data_init (void)
|
||||
{
|
||||
/*
|
||||
* Lock the RAP. We only create a lock if a call is made. First we test if a
|
||||
* lock is present. If one is present we lock it. If not the libio lock is
|
||||
* locked and we then test the lock again. If not present we create the lock
|
||||
* then release libio lock.
|
||||
*/
|
||||
if (!rap_.lock)
|
||||
{
|
||||
rtems_libio_lock ();
|
||||
|
||||
if (!rap_.lock)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id lock;
|
||||
|
||||
/*
|
||||
* Create the RAP lock.
|
||||
*/
|
||||
sc = rtems_semaphore_create (rtems_build_name ('R', 'A', 'P', '_'),
|
||||
1, RTEMS_MUTEX_ATTRIBS,
|
||||
RTEMS_NO_PRIORITY, &lock);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
return false;
|
||||
|
||||
sc = rtems_semaphore_obtain (lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_semaphore_delete (lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
rap_.lock = lock;
|
||||
|
||||
/*
|
||||
* Initialise the objects list and create any required services.
|
||||
*/
|
||||
rtems_chain_initialize_empty (&rap_.apps);
|
||||
}
|
||||
|
||||
rtems_libio_unlock ();
|
||||
|
||||
rtems_rap_unlock ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static rtems_rap_data_t*
|
||||
rtems_rap_lock (void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
|
||||
if (!rtems_rap_data_init ())
|
||||
return NULL;
|
||||
|
||||
sc = rtems_semaphore_obtain (rap_.lock,
|
||||
RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &rap_;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rap_unlock (void)
|
||||
{
|
||||
/*
|
||||
* Not sure any error should be returned or an assert.
|
||||
*/
|
||||
rtems_status_code sc;
|
||||
sc = rtems_semaphore_release (rap_.lock);
|
||||
if ((sc != RTEMS_SUCCESSFUL) && (errno == 0))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static rtems_rap_app_t*
|
||||
rtems_rap_check_handle (void* handle)
|
||||
{
|
||||
rtems_rap_app_t* app;
|
||||
rtems_chain_node* node;
|
||||
|
||||
app = handle;
|
||||
node = rtems_chain_first (&rap_.apps);
|
||||
|
||||
while (!rtems_chain_is_tail (&rap_.apps, node))
|
||||
{
|
||||
rtems_rap_app_t* check = (rtems_rap_app_t*) node;
|
||||
if (check == app)
|
||||
return app;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static rtems_rap_app_t*
|
||||
rtems_rap_app_alloc (void)
|
||||
{
|
||||
rtems_rap_app_t* app = malloc (sizeof (rtems_rap_app_t));
|
||||
memset (app, 0, sizeof (rtems_rap_app_t));
|
||||
rtems_chain_append (&rap_.apps, &app->node);
|
||||
return app;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rap_app_free (rtems_rap_app_t* app)
|
||||
{
|
||||
if (app->handle)
|
||||
{
|
||||
dlclose (app->handle);
|
||||
app->handle = NULL;
|
||||
}
|
||||
|
||||
if (!rtems_chain_is_node_off_chain (&app->node))
|
||||
rtems_chain_extract (&app->node);
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rap_match_name (rtems_rap_app_t* app, const char* name)
|
||||
{
|
||||
const char* a;
|
||||
|
||||
/*
|
||||
* Assume the app name is absolute, ie points to the file on disk. This means
|
||||
* there is at least one delimiter in the name.
|
||||
*/
|
||||
|
||||
if (strncmp (app->name, name, strlen (name)) == 0)
|
||||
return true;
|
||||
|
||||
a = app->name + strlen (app->name) - 1;
|
||||
|
||||
while (a >= app->name)
|
||||
{
|
||||
if (rtems_filesystem_is_delimiter (*a))
|
||||
{
|
||||
const char* n = name;
|
||||
|
||||
++a;
|
||||
|
||||
while (*a && *n)
|
||||
{
|
||||
if (*a == '.')
|
||||
{
|
||||
if (*n == '\0')
|
||||
return true;
|
||||
}
|
||||
|
||||
++a;
|
||||
++n;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
--a;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rap_get_rtl_error (void)
|
||||
{
|
||||
rap_.last_errno =
|
||||
rtems_rtl_get_error (rap_.last_error, sizeof (rap_.last_error));
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rap_set_error (int error, const char* format, ...)
|
||||
{
|
||||
rtems_rap_data_t* rap = rtems_rap_lock ();
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
rap->last_errno = error;
|
||||
vsnprintf (rap->last_error, sizeof (rap->last_error), format, ap);
|
||||
rtems_rap_unlock ();
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rap_load (const char* name, int mode, int argc, const char* argv[])
|
||||
{
|
||||
rtems_rap_data_t* rap = rtems_rap_lock ();
|
||||
|
||||
if (!rap)
|
||||
return false;
|
||||
|
||||
if (rap_verbose)
|
||||
printf ("rap: loading '%s'\n", name);
|
||||
|
||||
/*
|
||||
* See if the app has already been loaded.
|
||||
*/
|
||||
if (!rtems_rap_find (name))
|
||||
{
|
||||
rtems_rap_app_t* app;
|
||||
rtems_rap_entry_t init;
|
||||
rtems_rap_entry_t fini;
|
||||
size_t size = 0;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Allocate a new application descriptor and attempt to load it.
|
||||
*/
|
||||
app = rtems_rap_app_alloc ();
|
||||
if (app == NULL)
|
||||
{
|
||||
rtems_rap_set_error (ENOMEM, "no memory for application");
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the file in the file system using the search path.
|
||||
*/
|
||||
if (!rtems_rtl_find_file (name, getenv ("PATH"), &app->name, &size))
|
||||
{
|
||||
rtems_rap_set_error (ENOENT, "file not found");
|
||||
rtems_rap_app_free (app);
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
app->handle = dlopen (app->name, RTLD_NOW | mode);
|
||||
if (!app->handle)
|
||||
{
|
||||
rtems_rap_get_rtl_error ();
|
||||
rtems_rap_app_free (app);
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
init = dlsym (app->handle, RTL_ENTRY_POINT);
|
||||
if (!init)
|
||||
{
|
||||
rtems_rap_get_rtl_error ();
|
||||
rtems_rap_app_free (app);
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
fini = dlsym (app->handle, RTL_ENTRY_POINT);
|
||||
if (!fini)
|
||||
{
|
||||
rtems_rap_get_rtl_error ();
|
||||
rtems_rap_app_free (app);
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
r = init (argc, argv);
|
||||
if (r != 0)
|
||||
{
|
||||
rtems_rap_set_error (r, "init call failure");
|
||||
rtems_rap_app_free (app);
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
rtems_rap_unlock ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rap_unload (const char* name)
|
||||
{
|
||||
rtems_rap_app_t* app;
|
||||
rtems_rap_entry_t fini;
|
||||
int r;
|
||||
|
||||
rtems_rap_lock ();
|
||||
|
||||
app = rtems_rap_find (name);
|
||||
|
||||
if (rap_verbose)
|
||||
printf ("rap: unloading '%s'\n", name);
|
||||
|
||||
if (!app)
|
||||
{
|
||||
rtems_rap_set_error (ENOENT, "invalid handle");
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
fini = dlsym (app->handle, RTL_ENTRY_POINT);
|
||||
if (!fini)
|
||||
{
|
||||
rtems_rap_get_rtl_error ();
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
r = fini (0, NULL);
|
||||
if (r != 0)
|
||||
{
|
||||
rtems_rap_set_error (r, "fini failure");
|
||||
rtems_rap_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
rtems_rap_app_free (app);
|
||||
rtems_rap_unlock ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void*
|
||||
rtems_rap_find (const char* name)
|
||||
{
|
||||
rtems_rap_data_t* rap = rtems_rap_lock ();
|
||||
rtems_chain_node* node;
|
||||
|
||||
node = rtems_chain_first (&rap->apps);
|
||||
|
||||
while (!rtems_chain_is_tail (&rap->apps, node))
|
||||
{
|
||||
rtems_rap_app_t* app = (rtems_rap_app_t*) node;
|
||||
if (rtems_rap_match_name (app, name))
|
||||
{
|
||||
rtems_rap_unlock ();
|
||||
return app;
|
||||
}
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
rtems_rap_unlock ();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rap_iterate (rtems_rap_iterator_t iterator)
|
||||
{
|
||||
rtems_rap_data_t* rap = rtems_rap_lock ();
|
||||
rtems_chain_node* node;
|
||||
bool result = true;
|
||||
|
||||
node = rtems_chain_first (&rap->apps);
|
||||
|
||||
while (!rtems_chain_is_tail (&rap->apps, node))
|
||||
{
|
||||
rtems_rap_app_t* app = (rtems_rap_app_t*) node;
|
||||
result = iterator (app);
|
||||
if (!result)
|
||||
break;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
rtems_rap_unlock ();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char*
|
||||
rtems_rap_name (void* handle)
|
||||
{
|
||||
rtems_rap_app_t* app = rtems_rap_check_handle (handle);
|
||||
if (app)
|
||||
return app->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
rtems_rap_dl_handle (void* handle)
|
||||
{
|
||||
rtems_rap_app_t* app = rtems_rap_check_handle (handle);
|
||||
if (app)
|
||||
return app->handle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
rtems_rap_get_error (char* message, size_t max_message)
|
||||
{
|
||||
rtems_rap_data_t* rap = rtems_rap_lock ();
|
||||
int last_errno = rap->last_errno;
|
||||
strncpy (message, rap->last_error, sizeof (rap->last_error));
|
||||
rtems_rap_unlock ();
|
||||
return last_errno;
|
||||
}
|
||||
115
cpukit/libdl/rap.h
Normal file
115
cpukit/libdl/rap.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2013 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rap
|
||||
*
|
||||
* @brief RTEMS Application Loader
|
||||
*
|
||||
* This is the RTEMS Application loader for files in the RAP format.
|
||||
*/
|
||||
|
||||
#if !defined (_RAP_H_)
|
||||
#define _RAP_H_
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup rtems_rap RTEMS Application Loader
|
||||
*
|
||||
* The module implements an application loader for files in the RAP format. The
|
||||
* RAP format is:
|
||||
*
|
||||
* <header>
|
||||
* <compressed container>
|
||||
*
|
||||
* The compressed container is a stream of ELF relocatable object files.
|
||||
*
|
||||
* TBD.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The module iterator handle.
|
||||
*/
|
||||
typedef bool (*rtems_rap_iterator_t) (void* handle);
|
||||
|
||||
/**
|
||||
* Load an application.
|
||||
*
|
||||
* @param name The name of the application file.
|
||||
* @return bool True if the module loads else an error.
|
||||
*/
|
||||
bool rtems_rap_load (const char* name, int mode, int argc, const char* argv[]);
|
||||
|
||||
/**
|
||||
* Unload an application.
|
||||
*
|
||||
* @param obj The application descriptor.
|
||||
* @retval true The application file has been unloaded.
|
||||
* @retval false The application could not be unloaded.
|
||||
*/
|
||||
bool rtems_rap_unload (const char* name);
|
||||
|
||||
/**
|
||||
* Find the application handle given a file name.
|
||||
*
|
||||
* @param name The name of the application file. It can be absolute or
|
||||
* relative. Relative names can the basename with an extension.
|
||||
* @retval NULL No application file with that name found.
|
||||
* @return void* The application descriptor.
|
||||
*/
|
||||
void* rtems_rap_find (const char* name);
|
||||
|
||||
/**
|
||||
* Run an iterator over the modules calling the iterator function.
|
||||
*
|
||||
* @param iterator The iterator function.
|
||||
* @retval true The iterator function returned did not return false.
|
||||
* @retval false The iterator function returned false..
|
||||
*/
|
||||
bool rtems_rap_iterate (rtems_rap_iterator_t iterator);
|
||||
|
||||
/**
|
||||
* Return the name of the module given a handle.
|
||||
*
|
||||
* @param handle The module handle.
|
||||
* @return const char* The name of the module if the handle is valid else it
|
||||
* is NULL.
|
||||
*/
|
||||
const char* rtems_rap_name (void* handle);
|
||||
|
||||
/**
|
||||
* Return the DL handle used to load the module given the RAP handle.
|
||||
*
|
||||
* @param handle The module handle.
|
||||
* @return void* The DL handle returned by the dlopen call.
|
||||
*/
|
||||
void* rtems_rap_dl_handle (void* handle);
|
||||
|
||||
/**
|
||||
* Get the last error message clearing it. This call is not thread safe is
|
||||
* multiple threads are loading object files at the same time. This call
|
||||
* follows the model provided by the dlopen family of calls.
|
||||
*
|
||||
* @param message Pointer to a buffer to copy the message into.
|
||||
* @param max_message The maximum message that can be copied.
|
||||
* @return int The last error number.
|
||||
*/
|
||||
int rtems_rap_get_error (char* message, size_t max_message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
33
cpukit/libdl/rtl-alloc-heap.c
Normal file
33
cpukit/libdl/rtl-alloc-heap.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Allocator for the standard heap.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtl-alloc-heap.h"
|
||||
|
||||
void
|
||||
rtems_rtl_alloc_heap (bool allocate,
|
||||
rtems_rtl_alloc_tag_t tag,
|
||||
void** address,
|
||||
size_t size)
|
||||
{
|
||||
if (allocate)
|
||||
*address = malloc (size);
|
||||
else
|
||||
{
|
||||
free (*address);
|
||||
*address = NULL;
|
||||
}
|
||||
}
|
||||
47
cpukit/libdl/rtl-alloc-heap.h
Normal file
47
cpukit/libdl/rtl-alloc-heap.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Allocator for the standard heap.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_ALLOC_HEAP_H_)
|
||||
#define _RTEMS_RTL_ALLOC_HEAP_H_
|
||||
|
||||
#include <rtems/rtl/rtl-allocator.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Allocator handler for the standard libc heap.
|
||||
*
|
||||
* @param allocation If true the request is to allocate memory else free.
|
||||
* @param tag The type of allocation request.
|
||||
* @param address Pointer to the memory address. If an allocation the value is
|
||||
* unspecific on entry and the allocated address or NULL on
|
||||
* exit. The NULL value means the allocation failed. If a delete
|
||||
* or free request the memory address is the block to free. A
|
||||
* free request of NULL is silently ignored.
|
||||
* @param size The size of the allocation if an allocation request and
|
||||
* not used if deleting or freeing a previous allocation.
|
||||
*/
|
||||
void rtems_rtl_alloc_heap(bool allocate,
|
||||
rtems_rtl_alloc_tag_t tag,
|
||||
void** address,
|
||||
size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
210
cpukit/libdl/rtl-allocator.c
Normal file
210
cpukit/libdl/rtl-allocator.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Allocator
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-alloc-heap.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
/**
|
||||
* Tags as symbols for tracing.
|
||||
*/
|
||||
#if RTEMS_RTL_TRACE
|
||||
static const char* tag_labels[6] =
|
||||
{
|
||||
"OBJECT",
|
||||
"SYMBOL",
|
||||
"EXTERNAL",
|
||||
"READ",
|
||||
"READ_WRITE",
|
||||
"READ_EXEC",
|
||||
};
|
||||
#define rtems_rtl_trace_tag_label(_l) tag_labels[_l]
|
||||
#else
|
||||
#define rtems_rtl_trace_tag_label(_l) ""
|
||||
#endif
|
||||
|
||||
void
|
||||
rtems_rtl_alloc_initialise (rtems_rtl_alloc_data_t* data)
|
||||
{
|
||||
int c;
|
||||
data->allocator = rtems_rtl_alloc_heap;
|
||||
for (c = 0; c < RTEMS_RTL_ALLOC_TAGS; ++c)
|
||||
rtems_chain_initialize_empty (&data->indirects[c]);
|
||||
}
|
||||
|
||||
void*
|
||||
rtems_rtl_alloc_new (rtems_rtl_alloc_tag_t tag, size_t size, bool zero)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
void* address = NULL;
|
||||
|
||||
if (rtl)
|
||||
rtl->allocator.allocator (true, tag, &address, size);
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
|
||||
printf ("rtl: alloc: new: %s addr=%p size=%zu\n",
|
||||
rtems_rtl_trace_tag_label (tag), address, size);
|
||||
|
||||
if (zero)
|
||||
memset (address, 0, size);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_alloc_del (rtems_rtl_alloc_tag_t tag, void* address)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
|
||||
printf ("rtl: alloc: del: %s addr=%p\n",
|
||||
rtems_rtl_trace_tag_label (tag), address);
|
||||
|
||||
if (rtl && address)
|
||||
rtl->allocator.allocator (false, tag, &address, 0);
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
}
|
||||
|
||||
rtems_rtl_allocator_t
|
||||
rtems_rtl_alloc_hook (rtems_rtl_allocator_t handler)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
rtems_rtl_allocator_t previous = rtl->allocator.allocator;
|
||||
rtl->allocator.allocator = handler;
|
||||
rtems_rtl_unlock ();
|
||||
return previous;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag,
|
||||
rtems_rtl_ptr_t* handle,
|
||||
size_t size)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
|
||||
{
|
||||
if (!rtems_rtl_ptr_null (handle))
|
||||
printf ("rtl: alloc: inew: %s handle=%p: not null\n",
|
||||
rtems_rtl_trace_tag_label (tag), handle);
|
||||
printf ("rtl: alloc: inew: %s handle=%p size=%zd\n",
|
||||
rtems_rtl_trace_tag_label (tag), handle, size);
|
||||
}
|
||||
|
||||
if (rtl)
|
||||
{
|
||||
rtems_rtl_alloc_data_t* allocator = &rtl->allocator;
|
||||
handle->pointer = rtems_rtl_alloc_new (tag, size, false);
|
||||
if (!rtems_rtl_ptr_null (handle))
|
||||
rtems_chain_append_unprotected (&allocator->indirects[tag],
|
||||
&handle->node);
|
||||
}
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag,
|
||||
rtems_rtl_ptr_t* handle)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
|
||||
{
|
||||
if (rtems_rtl_ptr_null (handle))
|
||||
printf ("rtl: alloc: idel: %s handle=%p: is null\n",
|
||||
rtems_rtl_trace_tag_label (tag), handle);
|
||||
printf ("rtl: alloc: idel: %s handle=%p\n",
|
||||
rtems_rtl_trace_tag_label (tag), handle);
|
||||
}
|
||||
|
||||
if (rtl && !rtems_rtl_ptr_null (handle))
|
||||
{
|
||||
rtems_chain_extract_unprotected (&handle->node);
|
||||
rtems_rtl_alloc_del (tag, &handle->pointer);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
|
||||
void** const_base, size_t const_size,
|
||||
void** data_base, size_t data_size,
|
||||
void** bss_base, size_t bss_size)
|
||||
{
|
||||
*text_base = *const_base = *data_base = *bss_base = NULL;
|
||||
|
||||
if (text_size)
|
||||
{
|
||||
*text_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_EXEC,
|
||||
text_size, false);
|
||||
if (!*text_base)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (const_size)
|
||||
{
|
||||
*const_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ,
|
||||
const_size, false);
|
||||
if (!*const_base)
|
||||
{
|
||||
rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (data_size)
|
||||
{
|
||||
*data_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE,
|
||||
data_size, false);
|
||||
if (!*data_base)
|
||||
{
|
||||
rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bss_size)
|
||||
{
|
||||
*bss_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE,
|
||||
bss_size, false);
|
||||
if (!*bss_base)
|
||||
{
|
||||
rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_alloc_module_del (void** text_base,
|
||||
void** const_base,
|
||||
void** data_base,
|
||||
void** bss_base)
|
||||
{
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *bss_base);
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *data_base);
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *const_base);
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_EXEC, *text_base);
|
||||
*text_base = *const_base = *data_base = *bss_base = NULL;
|
||||
}
|
||||
176
cpukit/libdl/rtl-allocator.h
Normal file
176
cpukit/libdl/rtl-allocator.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Allocator
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_ALLOCATOR_H_)
|
||||
#define _RTEMS_RTL_ALLOCATOR_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "rtl-indirect-ptr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Define the types of allocation the loader requires.
|
||||
*
|
||||
* @note It is best to use the object tag for general memory allocation and to
|
||||
* leave the tags with specific access properties to the module data
|
||||
*/
|
||||
enum rtems_rtl_alloc_tags_e {
|
||||
RTEMS_RTL_ALLOC_OBJECT, /**< A generic memory object. */
|
||||
RTEMS_RTL_ALLOC_SYMBOL, /**< Memory used for symbols. */
|
||||
RTEMS_RTL_ALLOC_EXTERNAL, /**< Memory used for external symbols. */
|
||||
RTEMS_RTL_ALLOC_READ, /**< The memory is read only. */
|
||||
RTEMS_RTL_ALLOC_READ_WRITE, /**< The memory is read and write. */
|
||||
RTEMS_RTL_ALLOC_READ_EXEC /**< The memory is read and executable. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The allocator tag type.
|
||||
*/
|
||||
typedef enum rtems_rtl_alloc_tags_e rtems_rtl_alloc_tag_t;
|
||||
|
||||
/**
|
||||
* The number of tags.
|
||||
*/
|
||||
#define RTEMS_RTL_ALLOC_TAGS ((size_t) (RTEMS_RTL_ALLOC_READ_EXEC + 1))
|
||||
|
||||
/**
|
||||
* Allocator handler handles all RTL allocations. It can be hooked and
|
||||
* overridded for customised allocation schemes or memory maps.
|
||||
*
|
||||
* @param allocation If true the request is to allocate memory else free.
|
||||
* @param tag The type of allocation request.
|
||||
* @param address Pointer to the memory address. If an allocation the value is
|
||||
* unspecific on entry and the allocated address or NULL on
|
||||
* exit. The NULL value means the allocation failed. If a delete
|
||||
* or free request the memory address is the block to free. A
|
||||
* free request of NULL is silently ignored.
|
||||
* @param size The size of the allocation if an allocation request and
|
||||
* not used if deleting or freeing a previous allocation.
|
||||
*/
|
||||
typedef void (*rtems_rtl_allocator_t)(bool allocate,
|
||||
rtems_rtl_alloc_tag_t tag,
|
||||
void** address,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* The allocator data.
|
||||
*/
|
||||
struct rtems_rtl_alloc_data_s {
|
||||
/**< The memory allocator handler. */
|
||||
rtems_rtl_allocator_t allocator;
|
||||
/**< The indirect pointer chains. */
|
||||
rtems_chain_control indirects[RTEMS_RTL_ALLOC_TAGS];
|
||||
};
|
||||
|
||||
typedef struct rtems_rtl_alloc_data_s rtems_rtl_alloc_data_t;
|
||||
|
||||
/**
|
||||
* Initialise the allocate data.
|
||||
*
|
||||
* @param data The data to initialise.
|
||||
*/
|
||||
void rtems_rtl_alloc_initialise (rtems_rtl_alloc_data_t* data);
|
||||
|
||||
/**
|
||||
* The Runtime Loader allocator new allocates new memory and optionally clear
|
||||
* the memory if requested.
|
||||
*
|
||||
* @param tag The type of allocation request.
|
||||
* @param size The size of the allocation.
|
||||
* @param zero If true the memory is cleared.
|
||||
* @return void* The memory address or NULL is not memory available.
|
||||
*/
|
||||
void* rtems_rtl_alloc_new (rtems_rtl_alloc_tag_t tag, size_t size, bool zero);
|
||||
|
||||
/**
|
||||
* The Runtime Loader allocator delete deletes allocated memory.
|
||||
*
|
||||
* @param tag The type of allocation request.
|
||||
* @param address The memory address to delete. A NULL is ignored.
|
||||
*/
|
||||
void rtems_rtl_alloc_del (rtems_rtl_alloc_tag_t tag, void* address);
|
||||
|
||||
/**
|
||||
* Hook the Runtime Loader allocatior. A handler can call the previous handler
|
||||
* in the chain to use it for specific tags. The default handler uses the
|
||||
* system heap. Do not unhook your handler if memory it allocates has not been
|
||||
* returned.
|
||||
*
|
||||
* @param handler The handler to use as the allocator.
|
||||
* @return rtems_rtl_alloc_handler_t The previous handler.
|
||||
*/
|
||||
rtems_rtl_allocator_t rtems_rtl_alloc_hook (rtems_rtl_allocator_t handler);
|
||||
|
||||
/**
|
||||
* Allocate memory to an indirect handle.
|
||||
*
|
||||
* @param tag The type of allocation request.
|
||||
* @param handle The handle to allocate the memory to.
|
||||
* @param size The size of the allocation.
|
||||
*/
|
||||
void rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag,
|
||||
rtems_rtl_ptr_t* handle,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* Free memory from an indirect handle.
|
||||
*
|
||||
* @param tag The type of allocation request.
|
||||
* @param handle The handle to free the memory from.
|
||||
*/
|
||||
void rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag,
|
||||
rtems_rtl_ptr_t* handle);
|
||||
|
||||
/**
|
||||
* Allocate the memory for a module given the size of the text, const, data and
|
||||
* bss sections. If any part of the allocation fails the no memory is
|
||||
* allocated.
|
||||
*
|
||||
* @param text_base Pointer to the text base pointer.
|
||||
* @param text_size The size of the read/exec section.
|
||||
* @param const_base Pointer to the const base pointer.
|
||||
* @param const_size The size of the read only section.
|
||||
* @param data_base Pointer to the data base pointer.
|
||||
* @prarm data_size The size of the read/write secton.
|
||||
* @param bss_base Pointer to the bss base pointer.
|
||||
* @param bss_size The size of the read/write.
|
||||
* @retval true The memory has been allocated.
|
||||
* @retval false The allocation of memory has failed.
|
||||
*/
|
||||
bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
|
||||
void** const_base, size_t const_size,
|
||||
void** data_base, size_t data_size,
|
||||
void** bss_base, size_t bss_size);
|
||||
|
||||
/**
|
||||
* Free the memory allocated to a module.
|
||||
*
|
||||
* @param text_base Pointer to the text base pointer.
|
||||
* @param const_base Pointer to the const base pointer.
|
||||
* @param data_base Pointer to the data base pointer.
|
||||
* @param bss_base Pointer to the bss base pointer.
|
||||
*/
|
||||
void rtems_rtl_alloc_module_del (void** text_base, void** const_base,
|
||||
void** data_base, void** bss_base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
57
cpukit/libdl/rtl-chain-iterator.c
Normal file
57
cpukit/libdl/rtl-chain-iterator.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor Chain Iterator
|
||||
*
|
||||
* A means of executing an iterator on a chain.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "rtl-chain-iterator.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_chain_iterate (rtems_chain_control* chain,
|
||||
rtems_chain_iterator iterator,
|
||||
void* data)
|
||||
{
|
||||
rtems_chain_node* node = rtems_chain_first (chain);
|
||||
while (!rtems_chain_is_tail (chain, node))
|
||||
{
|
||||
rtems_chain_node* next_node = rtems_chain_next (node);
|
||||
if (!iterator (node, data))
|
||||
return false;
|
||||
node = next_node;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count iterator.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_count_iterator (rtems_chain_node* node, void* data)
|
||||
{
|
||||
int* count = data;
|
||||
++(*count);
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
rtems_rtl_chain_count (rtems_chain_control* chain)
|
||||
{
|
||||
int count = 0;
|
||||
rtems_rtl_chain_iterate (chain, rtems_rtl_count_iterator, &count);
|
||||
return count;
|
||||
}
|
||||
59
cpukit/libdl/rtl-chain-iterator.h
Normal file
59
cpukit/libdl/rtl-chain-iterator.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Chain Iterator.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_CHAIN_ITERATOR_H_)
|
||||
#define _RTEMS_RTL_CHAIN_ITERATOR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <rtems/chain.h>
|
||||
|
||||
/**
|
||||
* Chain iterator handler.
|
||||
*/
|
||||
typedef bool (*rtems_chain_iterator) (rtems_chain_node* node, void* data);
|
||||
|
||||
/**
|
||||
* Iterate a chain of nodes invoking the iterator handler. Supply a data
|
||||
* pointer the iterator moves data between the invoker and the iterator.
|
||||
*
|
||||
* The iterator allows removal of the node from the chain.
|
||||
*
|
||||
* @param chain The chain of nodes to iterator over.
|
||||
* @param iterator The iterator handler called once for each node.
|
||||
* @param data Pointer to the data used by the iterator.
|
||||
* @retval true The whole chain was iterated over.
|
||||
* @retval false The iterator returned false.
|
||||
*/
|
||||
bool
|
||||
rtems_rtl_chain_iterate (rtems_chain_control* chain,
|
||||
rtems_chain_iterator iterator,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Count the number of nodes on the chain.
|
||||
*
|
||||
* @param chain The chain to count the nodes of.
|
||||
* @return int The number of nodes.
|
||||
*/
|
||||
int rtems_rtl_chain_count (rtems_chain_control* chain);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
96
cpukit/libdl/rtl-debugger.c
Normal file
96
cpukit/libdl/rtl-debugger.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtl
|
||||
*
|
||||
* @brief RTEMS Module Loading Debugger Interface.
|
||||
*
|
||||
* Inspection of run-time linkers in NetBSD and Android show a common type of
|
||||
* structure that is used to interface to GDB. The NetBSD definition of this
|
||||
* interface is being used and is defined in <link.h>. It defines a protocol
|
||||
* that is used by GDB to inspect the state of dynamic libraries. I have not
|
||||
* checked GDB code at when writing this comment but I suspect GDB sets a break
|
||||
* point on the r_brk field of _rtld_debug and it has code that detects this
|
||||
* break point being hit. When this happens it reads the state and performs the
|
||||
* operation based on the r_state field.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <link.h>
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-trace.h"
|
||||
#include "rtl-obj-fwd.h"
|
||||
|
||||
struct r_debug _rtld_debug;
|
||||
|
||||
void
|
||||
_rtld_debug_state (void)
|
||||
{
|
||||
/*
|
||||
* Empty. GDB only needs to hit this location.
|
||||
*/
|
||||
}
|
||||
|
||||
int
|
||||
_rtld_linkmap_add (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
struct link_map* l = (struct link_map*)obj->detail;
|
||||
struct link_map* prev;
|
||||
uint32_t obj_num = obj->obj_num;
|
||||
int i;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
printf ("rtl: linkmap_add\n");
|
||||
|
||||
for (i = 0; i < obj_num; ++i)
|
||||
{
|
||||
l[i].sec_addr[rap_text] = obj->text_base;
|
||||
l[i].sec_addr[rap_const] = obj->const_base;
|
||||
l[i].sec_addr[rap_data] = obj->data_base;
|
||||
l[i].sec_addr[rap_bss] = obj->bss_base;
|
||||
}
|
||||
|
||||
if (_rtld_debug.r_map == NULL)
|
||||
{
|
||||
_rtld_debug.r_map = l;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next);
|
||||
|
||||
l->l_prev = prev;
|
||||
prev->l_next = l;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
_rtld_linkmap_delete (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
struct link_map* l = (struct link_map*)obj->detail;
|
||||
/* link_maps are allocated together if not 1 */
|
||||
struct link_map* e = l + obj->obj_num - 1;
|
||||
|
||||
while (e && e->l_next) e = e->l_next;
|
||||
|
||||
if (l->l_prev == NULL)
|
||||
{
|
||||
if ((_rtld_debug.r_map = e->l_next) != NULL)
|
||||
e->l_next->l_prev = NULL;
|
||||
return;
|
||||
}
|
||||
if ((l->l_prev->l_next = e->l_next) != NULL)
|
||||
e->l_next->l_prev = l->l_prev;
|
||||
return;
|
||||
}
|
||||
882
cpukit/libdl/rtl-elf.c
Normal file
882
cpukit/libdl/rtl-elf.c
Normal file
@@ -0,0 +1,882 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor
|
||||
*
|
||||
* This is the RTL implementation.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
#include "rtl-unresolved.h"
|
||||
|
||||
/**
|
||||
* The offsets in the unresolved array.
|
||||
*/
|
||||
#define REL_R_OFFSET (0)
|
||||
#define REL_R_INFO (1)
|
||||
#define REL_R_ADDEND (2)
|
||||
|
||||
/**
|
||||
* The ELF format signature.
|
||||
*/
|
||||
static rtems_rtl_loader_format_t elf_sig =
|
||||
{
|
||||
.label = "ELF",
|
||||
.flags = RTEMS_RTL_FMT_ELF
|
||||
};
|
||||
|
||||
static bool
|
||||
rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
|
||||
{
|
||||
/*
|
||||
* This code is determined by the NetBSD machine headers.
|
||||
*/
|
||||
switch (ehdr->e_machine)
|
||||
{
|
||||
ELFDEFNNAME (MACHDEP_ID_CASES)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj,
|
||||
const Elf_Sym* sym,
|
||||
const char* symname,
|
||||
Elf_Word* value)
|
||||
{
|
||||
rtems_rtl_obj_sect_t* sect;
|
||||
|
||||
if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE)
|
||||
{
|
||||
rtems_rtl_obj_sym_t* symbol = rtems_rtl_symbol_global_find (symname);
|
||||
if (!symbol)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = (Elf_Word) symbol->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
|
||||
if (!sect)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "reloc symbol's section not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = sym->st_value + (Elf_Word) sect->base;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_elf_relocator (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
void* data)
|
||||
{
|
||||
rtems_rtl_obj_cache_t* symbols;
|
||||
rtems_rtl_obj_cache_t* strings;
|
||||
rtems_rtl_obj_cache_t* relocs;
|
||||
rtems_rtl_obj_sect_t* targetsect;
|
||||
rtems_rtl_obj_sect_t* symsect;
|
||||
rtems_rtl_obj_sect_t* strtab;
|
||||
bool is_rela;
|
||||
size_t reloc_size;
|
||||
int reloc;
|
||||
|
||||
/*
|
||||
* First check if the section the relocations are for exists. If it does not
|
||||
* exist ignore these relocations. They are most probably debug sections.
|
||||
*/
|
||||
targetsect = rtems_rtl_obj_find_section_by_index (obj, sect->info);
|
||||
if (!targetsect)
|
||||
return true;
|
||||
|
||||
rtems_rtl_obj_caches (&symbols, &strings, &relocs);
|
||||
|
||||
if (!symbols || !strings || !relocs)
|
||||
return false;
|
||||
|
||||
symsect = rtems_rtl_obj_find_section (obj, ".symtab");
|
||||
if (!symsect)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "no .symtab section");
|
||||
return false;
|
||||
}
|
||||
|
||||
strtab = rtems_rtl_obj_find_section (obj, ".strtab");
|
||||
if (!strtab)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "no .strtab section");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: relocation: %s, syms:%s\n", sect->name, symsect->name);
|
||||
|
||||
/*
|
||||
* Handle the different relocation record types.
|
||||
*/
|
||||
is_rela = ((sect->flags & RTEMS_RTL_OBJ_SECT_RELA) ==
|
||||
RTEMS_RTL_OBJ_SECT_RELA) ? true : false;
|
||||
reloc_size = is_rela ? sizeof (Elf_Rela) : sizeof (Elf_Rel);
|
||||
|
||||
for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
|
||||
{
|
||||
uint8_t relbuf[reloc_size];
|
||||
const Elf_Rela* rela = (const Elf_Rela*) relbuf;
|
||||
const Elf_Rel* rel = (const Elf_Rel*) relbuf;
|
||||
Elf_Sym sym;
|
||||
const char* symname = NULL;
|
||||
off_t off;
|
||||
Elf_Word type;
|
||||
Elf_Word symvalue = 0;
|
||||
bool relocate;
|
||||
|
||||
off = obj->ooffset + sect->offset + (reloc * reloc_size);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (relocs, fd, off,
|
||||
&relbuf[0], reloc_size))
|
||||
return false;
|
||||
|
||||
if (is_rela)
|
||||
off = (obj->ooffset + symsect->offset +
|
||||
(ELF_R_SYM (rela->r_info) * sizeof (sym)));
|
||||
else
|
||||
off = (obj->ooffset + symsect->offset +
|
||||
(ELF_R_SYM (rel->r_info) * sizeof (sym)));
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
|
||||
&sym, sizeof (sym)))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Only need the name of the symbol if global.
|
||||
*/
|
||||
if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE)
|
||||
{
|
||||
size_t len;
|
||||
off = obj->ooffset + strtab->offset + sym.st_name;
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd, off,
|
||||
(void**) &symname, &len))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the record references an external symbol. If it does find the
|
||||
* symbol value. If the symbol cannot be found flag the object file as
|
||||
* having unresolved externals and store the externals. The load of an
|
||||
* object after this one may provide the unresolved externals.
|
||||
*/
|
||||
if (is_rela)
|
||||
type = ELF_R_TYPE(rela->r_info);
|
||||
else
|
||||
type = ELF_R_TYPE(rel->r_info);
|
||||
|
||||
relocate = true;
|
||||
|
||||
if (rtems_rtl_elf_rel_resolve_sym (type))
|
||||
{
|
||||
if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue))
|
||||
{
|
||||
uint16_t flags = 0;
|
||||
rtems_rtl_word_t rel_words[3];
|
||||
|
||||
relocate = false;
|
||||
|
||||
if (is_rela)
|
||||
{
|
||||
flags = 1;
|
||||
rel_words[REL_R_OFFSET] = rela->r_offset;
|
||||
rel_words[REL_R_INFO] = rela->r_info;
|
||||
rel_words[REL_R_ADDEND] = rela->r_addend;
|
||||
}
|
||||
else
|
||||
{
|
||||
rel_words[REL_R_OFFSET] = rel->r_offset;
|
||||
rel_words[REL_R_INFO] = rel->r_info;
|
||||
rel_words[REL_R_ADDEND] = 0;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_unresolved_add (obj,
|
||||
flags,
|
||||
symname,
|
||||
targetsect->section,
|
||||
rel_words))
|
||||
return false;
|
||||
|
||||
++obj->unresolved;
|
||||
}
|
||||
}
|
||||
|
||||
if (relocate)
|
||||
{
|
||||
if (is_rela)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: rela: sym:%s(%-2d)=%08lx type:%-2d off:%08lx addend:%d\n",
|
||||
symname, (int) ELF_R_SYM (rela->r_info), symvalue,
|
||||
(int) ELF_R_TYPE (rela->r_info), rela->r_offset, (int) rela->r_addend);
|
||||
if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
|
||||
symname, sym.st_info, symvalue))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: rel: sym:%s(%-2d)=%08lx type:%-2d off:%08lx\n",
|
||||
symname, (int) ELF_R_SYM (rel->r_info), symvalue,
|
||||
(int) ELF_R_TYPE (rel->r_info), rel->r_offset);
|
||||
if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
|
||||
symname, sym.st_info, symvalue))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the unresolved externals status if there are unresolved externals.
|
||||
*/
|
||||
if (obj->unresolved)
|
||||
obj->flags |= RTEMS_RTL_OBJ_UNRESOLVED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc_t* reloc,
|
||||
rtems_rtl_obj_sym_t* sym)
|
||||
{
|
||||
rtems_rtl_obj_sect_t* sect;
|
||||
bool is_rela;
|
||||
Elf_Word symvalue;
|
||||
|
||||
is_rela =reloc->flags & 1;
|
||||
|
||||
sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
|
||||
if (!sect)
|
||||
{
|
||||
rtems_rtl_set_error (ENOEXEC, "unresolved sect not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
symvalue = (Elf_Word) (intptr_t) sym->value;
|
||||
if (is_rela)
|
||||
{
|
||||
Elf_Rela rela;
|
||||
rela.r_offset = reloc->rel[REL_R_OFFSET];
|
||||
rela.r_info = reloc->rel[REL_R_INFO];
|
||||
rela.r_addend = reloc->rel[REL_R_ADDEND];
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: rela: sym:%-2d type:%-2d off:%08lx addend:%d\n",
|
||||
(int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
|
||||
rela.r_offset, (int) rela.r_addend);
|
||||
if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
|
||||
sym->name, sym->data, symvalue))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf_Rel rel;
|
||||
rel.r_offset = reloc->rel[REL_R_OFFSET];
|
||||
rel.r_info = reloc->rel[REL_R_INFO];
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: rel: sym:%-2d type:%-2d off:%08lx\n",
|
||||
(int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
|
||||
rel.r_offset);
|
||||
if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
|
||||
sym->name, sym->data, symvalue))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reloc->obj->unresolved)
|
||||
{
|
||||
--reloc->obj->unresolved;
|
||||
if (!reloc->obj->unresolved)
|
||||
reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_elf_symbols (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
void* data)
|
||||
{
|
||||
rtems_rtl_obj_cache_t* symbols;
|
||||
rtems_rtl_obj_cache_t* strings;
|
||||
rtems_rtl_obj_sect_t* strtab;
|
||||
int globals;
|
||||
int string_space;
|
||||
char* string;
|
||||
int sym;
|
||||
|
||||
strtab = rtems_rtl_obj_find_section (obj, ".strtab");
|
||||
if (!strtab)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "no .strtab section");
|
||||
return false;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_caches (&symbols, &strings, NULL);
|
||||
|
||||
if (!symbols || !strings)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Find the number of globals and the amount of string space
|
||||
* needed. Also check for duplicate symbols.
|
||||
*/
|
||||
|
||||
globals = 0;
|
||||
string_space = 0;
|
||||
|
||||
for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
|
||||
{
|
||||
Elf_Sym symbol;
|
||||
off_t off;
|
||||
const char* name;
|
||||
size_t len;
|
||||
|
||||
off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
|
||||
&symbol, sizeof (symbol)))
|
||||
return false;
|
||||
|
||||
off = obj->ooffset + strtab->offset + symbol.st_name;
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Only keep the functions and global or weak symbols.
|
||||
*/
|
||||
if ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
|
||||
(ELF_ST_TYPE (symbol.st_info) == STT_FUNC))
|
||||
{
|
||||
if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
|
||||
(ELF_ST_BIND (symbol.st_info) == STB_WEAK))
|
||||
{
|
||||
/*
|
||||
* If there is a globally exported symbol already present and this
|
||||
* symbol is not weak raise an error. If the symbol is weak and present
|
||||
* globally ignore this symbol and use the global one and if it is not
|
||||
* present take this symbol global or weak. We accept the first weak
|
||||
* symbol we find and make it globally exported.
|
||||
*/
|
||||
if (rtems_rtl_symbol_global_find (name) &&
|
||||
(ELF_ST_BIND (symbol.st_info) != STB_WEAK))
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
++globals;
|
||||
string_space += strlen (name) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (globals)
|
||||
{
|
||||
rtems_rtl_obj_sym_t* gsym;
|
||||
|
||||
obj->global_size = globals * sizeof (rtems_rtl_obj_sym_t) + string_space;
|
||||
obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
|
||||
obj->global_size, true);
|
||||
if (!obj->global_table)
|
||||
{
|
||||
obj->global_size = 0;
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
|
||||
return false;
|
||||
}
|
||||
|
||||
obj->global_syms = globals;
|
||||
|
||||
for (sym = 0,
|
||||
gsym = obj->global_table,
|
||||
string = (((char*) obj->global_table) +
|
||||
(globals * sizeof (rtems_rtl_obj_sym_t)));
|
||||
sym < (sect->size / sizeof (Elf_Sym));
|
||||
++sym)
|
||||
{
|
||||
Elf_Sym symbol;
|
||||
off_t off;
|
||||
const char* name;
|
||||
size_t len;
|
||||
|
||||
off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
|
||||
&symbol, sizeof (symbol)))
|
||||
{
|
||||
free (obj->global_table);
|
||||
obj->global_table = NULL;
|
||||
obj->global_syms = 0;
|
||||
obj->global_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
off = obj->ooffset + strtab->offset + symbol.st_name;
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
|
||||
return false;
|
||||
|
||||
if (((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
|
||||
(ELF_ST_TYPE (symbol.st_info) == STT_FUNC)) &&
|
||||
((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
|
||||
(ELF_ST_BIND (symbol.st_info) == STB_WEAK)))
|
||||
{
|
||||
rtems_rtl_obj_sect_t* symsect;
|
||||
symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
|
||||
if (!symsect)
|
||||
{
|
||||
free (obj->global_table);
|
||||
obj->global_table = NULL;
|
||||
obj->global_syms = 0;
|
||||
obj->global_size = 0;
|
||||
rtems_rtl_set_error (EINVAL, "sym section not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
rtems_chain_set_off_chain (&gsym->node);
|
||||
|
||||
memcpy (string, name, strlen (name) + 1);
|
||||
gsym->name = string;
|
||||
string += strlen (name) + 1;
|
||||
gsym->value = symbol.st_value + (uint8_t*) symsect->base;
|
||||
gsym->data = symbol.st_info;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
|
||||
printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d type:%-2d val:%8p sect:%d size:%d\n",
|
||||
sym, (int) symbol.st_name, gsym->name,
|
||||
(int) ELF_ST_BIND (symbol.st_info),
|
||||
(int) ELF_ST_TYPE (symbol.st_info),
|
||||
gsym->value, symbol.st_shndx,
|
||||
(int) symbol.st_size);
|
||||
|
||||
++gsym;
|
||||
}
|
||||
}
|
||||
|
||||
rtems_rtl_symbol_obj_add (obj);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_elf_loader (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
void* data)
|
||||
{
|
||||
uint8_t* base_offset;
|
||||
size_t len;
|
||||
|
||||
if (lseek (fd, obj->ooffset + sect->offset, SEEK_SET) < 0)
|
||||
{
|
||||
rtems_rtl_set_error (errno, "section load seek failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
base_offset = sect->base;
|
||||
len = sect->size;
|
||||
|
||||
while (len)
|
||||
{
|
||||
ssize_t r = read (fd, base_offset, len);
|
||||
if (r <= 0)
|
||||
{
|
||||
rtems_rtl_set_error (errno, "section load read failed");
|
||||
return false;
|
||||
}
|
||||
base_offset += r;
|
||||
len -= r;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr)
|
||||
{
|
||||
rtems_rtl_obj_cache_t* sects;
|
||||
rtems_rtl_obj_cache_t* strings;
|
||||
int section;
|
||||
off_t sectstroff;
|
||||
off_t off;
|
||||
Elf_Shdr shdr;
|
||||
|
||||
rtems_rtl_obj_caches (§s, &strings, NULL);
|
||||
|
||||
if (!sects || !strings)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Get the offset to the section string table.
|
||||
*/
|
||||
off = obj->ooffset + ehdr->e_shoff + (ehdr->e_shstrndx * ehdr->e_shentsize);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
|
||||
return false;
|
||||
|
||||
if (shdr.sh_type != SHT_STRTAB)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "bad .sectstr section type");
|
||||
return false;
|
||||
}
|
||||
|
||||
sectstroff = obj->ooffset + shdr.sh_offset;
|
||||
|
||||
for (section = 0; section < ehdr->e_shnum; ++section)
|
||||
{
|
||||
uint32_t flags;
|
||||
|
||||
off = obj->ooffset + ehdr->e_shoff + (section * ehdr->e_shentsize);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
|
||||
return false;
|
||||
|
||||
flags = 0;
|
||||
|
||||
switch (shdr.sh_type)
|
||||
{
|
||||
case SHT_NULL:
|
||||
/*
|
||||
* Ignore.
|
||||
*/
|
||||
break;
|
||||
|
||||
case SHT_PROGBITS:
|
||||
/*
|
||||
* There are 2 program bits sections. One is the program text and the
|
||||
* other is the program data. The program text is flagged
|
||||
* alloc/executable and the program data is flagged alloc/writable.
|
||||
*/
|
||||
if ((shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC)
|
||||
{
|
||||
if ((shdr.sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR)
|
||||
flags = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD;
|
||||
else if ((shdr.sh_flags & SHF_WRITE) == SHF_WRITE)
|
||||
flags = RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD;
|
||||
else
|
||||
flags = RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD;
|
||||
}
|
||||
break;
|
||||
|
||||
case SHT_NOBITS:
|
||||
/*
|
||||
* There is 1 NOBIT section which is the .bss section. There is nothing
|
||||
* but a definition as the .bss is just a clear region of memory.
|
||||
*/
|
||||
if ((shdr.sh_flags & (SHF_ALLOC | SHF_WRITE)) == (SHF_ALLOC | SHF_WRITE))
|
||||
flags = RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO;
|
||||
break;
|
||||
|
||||
case SHT_RELA:
|
||||
flags = RTEMS_RTL_OBJ_SECT_RELA;
|
||||
break;
|
||||
|
||||
case SHT_REL:
|
||||
/*
|
||||
* The sh_link holds the section index for the symbol table. The sh_info
|
||||
* holds the section index the relocations apply to.
|
||||
*/
|
||||
flags = RTEMS_RTL_OBJ_SECT_REL;
|
||||
break;
|
||||
|
||||
case SHT_SYMTAB:
|
||||
flags = RTEMS_RTL_OBJ_SECT_SYM;
|
||||
break;
|
||||
|
||||
case SHT_STRTAB:
|
||||
flags = RTEMS_RTL_OBJ_SECT_STR;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
|
||||
section, (int) shdr.sh_type, (int) shdr.sh_flags);
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
char* name;
|
||||
size_t len;
|
||||
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd,
|
||||
sectstroff + shdr.sh_name,
|
||||
(void**) &name, &len))
|
||||
return false;
|
||||
|
||||
if (strcmp (".ctors", name) == 0)
|
||||
flags |= RTEMS_RTL_OBJ_SECT_CTOR;
|
||||
if (strcmp (".dtors", name) == 0)
|
||||
flags |= RTEMS_RTL_OBJ_SECT_DTOR;
|
||||
|
||||
if (!rtems_rtl_obj_add_section (obj, section, name,
|
||||
shdr.sh_size, shdr.sh_offset,
|
||||
shdr.sh_addralign, shdr.sh_link,
|
||||
shdr.sh_info, flags))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd)
|
||||
{
|
||||
rtems_rtl_obj_cache_t* header;
|
||||
Elf_Ehdr ehdr;
|
||||
|
||||
rtems_rtl_obj_caches (&header, NULL, NULL);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
|
||||
&ehdr, sizeof (ehdr)))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Check we have a valid ELF file.
|
||||
*/
|
||||
if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
|
||||
|| ehdr.e_ident[EI_CLASS] != ELFCLASS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
|
||||
|| (ehdr.e_version != EV_CURRENT)
|
||||
|| (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
rtems_chain_control* sections = NULL;
|
||||
rtems_chain_node* node = NULL;
|
||||
size_t mask = 0;
|
||||
struct link_map* l = NULL;
|
||||
int sec_num = 0;
|
||||
int i = 0;
|
||||
|
||||
/* caculate the size of sections' name. */
|
||||
|
||||
for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
|
||||
mask <= RTEMS_RTL_OBJ_SECT_BSS;
|
||||
mask <<= 1)
|
||||
{
|
||||
sections = &obj->sections;
|
||||
node = rtems_chain_first (sections);
|
||||
while (!rtems_chain_is_tail (sections, node))
|
||||
{
|
||||
rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
|
||||
|
||||
if ((sect->size != 0) && ((sect->flags & mask) != 0))
|
||||
{
|
||||
++sec_num;
|
||||
}
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
}
|
||||
|
||||
obj->obj_num = 1;
|
||||
obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
|
||||
sizeof(struct link_map) +
|
||||
sec_num * sizeof (section_detail), true);
|
||||
if (!obj->detail)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
|
||||
return false;
|
||||
}
|
||||
|
||||
l = (struct link_map*) obj->detail;
|
||||
l->name = obj->oname;
|
||||
l->sec_num = sec_num;
|
||||
l->sec_detail = (section_detail*) (l + 1);
|
||||
l->rpathlen = 0;
|
||||
l->rpath = NULL;
|
||||
l->l_next = NULL;
|
||||
l->l_prev = NULL;
|
||||
l->sec_addr[rap_text] = obj->text_base;
|
||||
l->sec_addr[rap_const] = obj->const_base;
|
||||
l->sec_addr[rap_data] = obj->data_base;
|
||||
l->sec_addr[rap_bss] = obj->bss_base;
|
||||
|
||||
|
||||
section_detail* sd = l->sec_detail;
|
||||
sections = &obj->sections;
|
||||
node = rtems_chain_first (sections);
|
||||
for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
|
||||
mask <= RTEMS_RTL_OBJ_SECT_BSS;
|
||||
mask <<= 1)
|
||||
{
|
||||
sections = &obj->sections;
|
||||
node = rtems_chain_first (sections);
|
||||
while (!rtems_chain_is_tail (sections, node))
|
||||
{
|
||||
rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node;
|
||||
|
||||
if ((sect->size != 0) && ((sect->flags & mask) != 0))
|
||||
{
|
||||
sd[i].name = sect->name;
|
||||
sd[i].size = sect->size;
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_TEXT)
|
||||
{
|
||||
sd[i].rap_id = rap_text;
|
||||
sd[i].offset = sect->base - obj->text_base;
|
||||
}
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_CONST)
|
||||
{
|
||||
sd[i].rap_id = rap_const;
|
||||
sd[i].offset = sect->base - obj->const_base;
|
||||
}
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_DATA)
|
||||
{
|
||||
sd[i].rap_id = rap_data;
|
||||
sd[i].offset = sect->base - obj->data_base;
|
||||
}
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_BSS)
|
||||
{
|
||||
sd[i].rap_id = rap_bss;
|
||||
sd[i].offset = sect->base - obj->bss_base;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd)
|
||||
{
|
||||
rtems_rtl_obj_cache_t* header;
|
||||
Elf_Ehdr ehdr;
|
||||
|
||||
rtems_rtl_obj_caches (&header, NULL, NULL);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
|
||||
&ehdr, sizeof (ehdr)))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Check we have a valid ELF file.
|
||||
*/
|
||||
if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
|
||||
|| ehdr.e_ident[EI_CLASS] != ELFCLASS)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid ELF file format");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
|
||||
|| (ehdr.e_version != EV_CURRENT)
|
||||
|| (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "unsupported ELF file version");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_elf_machine_check (&ehdr))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "unsupported machine type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ehdr.e_type == ET_DYN)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "unsupported ELF file type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ehdr.e_phentsize != 0)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "ELF file contains program headers");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ehdr.e_shentsize != sizeof (Elf_Shdr))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid ELF section header size");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the section information first so we have the memory map of the object
|
||||
* file and the memory allocated. Any further allocations we make to complete
|
||||
* the load will not fragment the memory.
|
||||
*/
|
||||
if (!rtems_rtl_elf_parse_sections (obj, fd, &ehdr))
|
||||
return false;
|
||||
|
||||
obj->entry = (void*)(uintptr_t) ehdr.e_entry;
|
||||
|
||||
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_elf_load_details (obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
rtems_rtl_loader_format_t*
|
||||
rtems_rtl_elf_file_sig (void)
|
||||
{
|
||||
return &elf_sig;
|
||||
}
|
||||
165
cpukit/libdl/rtl-elf.h
Normal file
165
cpukit/libdl/rtl-elf.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker ELF Headers
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_ELF_H_)
|
||||
#define _RTEMS_RTL_ELF_H_
|
||||
|
||||
#include "rtl-fwd.h"
|
||||
#include "rtl-obj-fwd.h"
|
||||
#include "rtl-sym.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
** Imported NetBSD ELF Specifics Start.
|
||||
**/
|
||||
|
||||
/*
|
||||
* Always 32bit for RTEMS at the moment. Do not add '()'. Leave plain.
|
||||
*/
|
||||
#define ELFSIZE 32
|
||||
|
||||
/*
|
||||
* Define _STANDALONE then remove after.
|
||||
*/
|
||||
#define _STANDALONE 1
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/exec_elf.h>
|
||||
|
||||
#undef _STANDALONE
|
||||
|
||||
/**
|
||||
** Imported NetBSD ELF Specifics End.
|
||||
**/
|
||||
|
||||
/**
|
||||
* Maximum string length. This a read buffering limit rather than a
|
||||
* specific ELF length. I hope this is ok as I am concerned about
|
||||
* some C++ symbol lengths.
|
||||
*/
|
||||
#define RTEMS_RTL_ELF_STRING_MAX (256)
|
||||
|
||||
/**
|
||||
* Architecture specific handler to check is a relocation record's type is
|
||||
* required to resolve a symbol.
|
||||
*
|
||||
* @param type The type field in the relocation record.
|
||||
* @retval true The relocation record require symbol resolution.
|
||||
* @retval false The relocation record does not require symbol resolution.
|
||||
*/
|
||||
bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type);
|
||||
|
||||
/**
|
||||
* Architecture specific relocation handler compiled in for a specific
|
||||
* architecture by the build system. The handler applies the relocation
|
||||
* to the target.
|
||||
*
|
||||
* @param obj The object file being relocated.
|
||||
* @param rel The ELF relocation record.
|
||||
* @param sect The section of the object file the relocation is for.
|
||||
* @param symname The symbol's name.
|
||||
* @param syminfo The ELF symbol info field.
|
||||
* @param symvalue If a symbol is referenced, this is the symbols value.
|
||||
* @retval bool The relocation has been applied.
|
||||
* @retval bool The relocation could not be applied.
|
||||
*/
|
||||
bool rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue);
|
||||
|
||||
/**
|
||||
* Architecture specific relocation handler compiled in for a specific
|
||||
* architecture by the build system. The handler applies the relocation
|
||||
* to the target.
|
||||
*
|
||||
* @param obj The object file being relocated.
|
||||
* @param rela The ELF addend relocation record.
|
||||
* @param sect The section of the object file the relocation is for.
|
||||
* @param symname The symbol's name.
|
||||
* @param syminfo The ELF symbol info field.
|
||||
* @param symvalue If a symbol is referenced, this is the symbols value.
|
||||
* @retval bool The relocation has been applied.
|
||||
* @retval bool The relocation could not be applied.
|
||||
*/
|
||||
bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue);
|
||||
|
||||
/**
|
||||
* Find the symbol. The symbol is passed as an ELF type symbol with the name
|
||||
* and the value returned is the absolute address of the symbol.
|
||||
*
|
||||
* If the symbol type is STT_NOTYPE the symbol references a global symbol. The
|
||||
* gobal symbol table is searched to find it and that value returned. If the
|
||||
* symbol is local to the object module the section for the symbol is located
|
||||
* and it's base added to the symbol's value giving an absolute location.
|
||||
*
|
||||
* @param obj The object the symbol is being resolved for.
|
||||
* @param sym The ELF type symbol.
|
||||
* @param symname The sym's name read from the symbol string table.
|
||||
* @param value Return the value of the symbol. Only valid if the return value
|
||||
* is true.
|
||||
* @retval true The symbol resolved.
|
||||
* @retval false The symbol could not be result. The RTL error is set.
|
||||
*/
|
||||
bool rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj,
|
||||
const Elf_Sym* sym,
|
||||
const char* symname,
|
||||
Elf_Word* value);
|
||||
|
||||
/**
|
||||
* The ELF format check handler.
|
||||
*
|
||||
* @param obj The object being checked.
|
||||
* @param fd The file descriptor.
|
||||
*/
|
||||
bool rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* The ELF file details handler.
|
||||
*
|
||||
* @param obj Load the details of the obj.
|
||||
*/
|
||||
bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The ELF format load handler.
|
||||
*
|
||||
* @param obj The object to load.
|
||||
* @param fd The file descriptor.
|
||||
*/
|
||||
bool rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* The ELF format signature handler.
|
||||
*
|
||||
* @return rtems_rtl_loader_format_t* The format's signature.
|
||||
*/
|
||||
rtems_rtl_loader_format_t* rtems_rtl_elf_file_sig (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
47
cpukit/libdl/rtl-error.c
Normal file
47
cpukit/libdl/rtl-error.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Error
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-error.h"
|
||||
|
||||
void
|
||||
rtems_rtl_set_error (int error, const char* format, ...)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
rtl->last_errno = error;
|
||||
vsnprintf (rtl->last_error, sizeof (rtl->last_error), format, ap);
|
||||
rtems_rtl_unlock ();
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
int
|
||||
rtems_rtl_get_error (char* message, size_t max_message)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_lock ();
|
||||
int last_errno = rtl->last_errno;
|
||||
strncpy (message, rtl->last_error, sizeof (rtl->last_error));
|
||||
rtems_rtl_unlock ();
|
||||
return last_errno;
|
||||
}
|
||||
|
||||
44
cpukit/libdl/rtl-error.h
Normal file
44
cpukit/libdl/rtl-error.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Error
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_ERROR_H_)
|
||||
#define _RTEMS_RTL_ERROR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if __GNUC__
|
||||
#define RTEMS_RTL_PRINTF_ATTR __attribute__((__format__(__printf__,2,3)))
|
||||
#else
|
||||
#define RTEMS_RTL_PRINTF_ATTR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sets the error.
|
||||
*
|
||||
* Assumes the RTL has been locked.
|
||||
*
|
||||
* @param error The errno error number.
|
||||
* @param format The error format string.
|
||||
* @param ... The variable arguments that depend on the format string.
|
||||
*/
|
||||
void rtems_rtl_set_error (int error, const char* format, ...) RTEMS_RTL_PRINTF_ATTR;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
110
cpukit/libdl/rtl-find-file.c
Normal file
110
cpukit/libdl/rtl-find-file.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012-2013 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Error
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-find-file.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-string.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
#if WAF_BUILD
|
||||
#define rtems_filesystem_is_delimiter rtems_filesystem_is_separator
|
||||
#endif
|
||||
|
||||
bool
|
||||
rtems_rtl_find_file (const char* name,
|
||||
const char* paths,
|
||||
const char** file_name,
|
||||
size_t* size)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
*file_name = NULL;
|
||||
*size = 0;
|
||||
|
||||
if (rtems_filesystem_is_delimiter (name[0]) || (name[0] == '.'))
|
||||
{
|
||||
if (stat (name, &sb) == 0)
|
||||
*file_name = rtems_rtl_strdup (name);
|
||||
}
|
||||
else if (paths)
|
||||
{
|
||||
const char* start;
|
||||
const char* end;
|
||||
int len;
|
||||
char* fname;
|
||||
|
||||
start = paths;
|
||||
end = start + strlen (paths);
|
||||
len = strlen (name);
|
||||
|
||||
while (!*file_name && (start != end))
|
||||
{
|
||||
const char* delimiter = strchr (start, ':');
|
||||
|
||||
if (delimiter == NULL)
|
||||
delimiter = end;
|
||||
|
||||
/*
|
||||
* Allocate the path fragment, separator, name, terminating nul. Form the
|
||||
* path then see if the stat call works.
|
||||
*/
|
||||
|
||||
fname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
|
||||
(delimiter - start) + 1 + len + 1, true);
|
||||
if (!fname)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory searching for file");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy (fname, start, delimiter - start);
|
||||
fname[delimiter - start] = '/';
|
||||
memcpy (fname + (delimiter - start) + 1, name, len);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: find-file: path: %s\n", fname);
|
||||
|
||||
if (stat (fname, &sb) < 0)
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, fname);
|
||||
else
|
||||
*file_name = fname;
|
||||
|
||||
start = delimiter;
|
||||
if (start != end)
|
||||
++start;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*file_name)
|
||||
return false;
|
||||
|
||||
*size = sb.st_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
45
cpukit/libdl/rtl-find-file.h
Normal file
45
cpukit/libdl/rtl-find-file.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012-2013 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object Support.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_FIND_FILE_H_)
|
||||
#define _RTEMS_RTL_FIND_FILE_H_
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Find a file on disk given a name and a path.
|
||||
*
|
||||
* @param name The file name to find. Can be relative or absolute.
|
||||
* @param paths The paths to search.
|
||||
* @param file_name Place the full path in this location if found.
|
||||
* @param size The size of the file if found as returned by the 'stat' call.
|
||||
* @retval true The file was found.
|
||||
* @retval false The file was not found.
|
||||
*/
|
||||
bool rtems_rtl_find_file (const char* name,
|
||||
const char* paths,
|
||||
const char** file_name,
|
||||
size_t* size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
33
cpukit/libdl/rtl-fwd.h
Normal file
33
cpukit/libdl/rtl-fwd.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker ELF Headers
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_FWD_H_)
|
||||
#define _RTEMS_RTL_FWD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* The forward declaration of the obj structure.
|
||||
*/
|
||||
struct rtems_rtl_data_s;
|
||||
typedef struct rtems_rtl_data_s rtems_rtl_data_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
235
cpukit/libdl/rtl-indirect-ptr.h
Normal file
235
cpukit/libdl/rtl-indirect-ptr.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Indirect Pointer Management allows memory
|
||||
* compaction in the allocator.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_INDIRECT_PTR_H_)
|
||||
#define _RTEMS_RTL_INDIRECT_PTR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <rtems/chain.h>
|
||||
|
||||
/**
|
||||
* The RTL Indirect pointer.
|
||||
*/
|
||||
struct rtems_rtl_ptr_s {
|
||||
rtems_chain_node node; /**< Indirect pointers are held on lists. */
|
||||
void* pointer; /**< The actual pointer. */
|
||||
};
|
||||
|
||||
typedef struct rtems_rtl_ptr_s rtems_rtl_ptr_t;
|
||||
|
||||
/**
|
||||
* The RTL Indirect size and pointer.
|
||||
*/
|
||||
struct rtems_rtl_sptr_s {
|
||||
rtems_rtl_ptr_t ptr; /**< The indirect pointer. */
|
||||
size_t size; /**< The size of the memory block. */
|
||||
};
|
||||
|
||||
typedef struct rtems_rtl_sptr_s rtems_rtl_sptr_t;
|
||||
|
||||
/**
|
||||
* A chain of indirect pointers for users to chain in applications.
|
||||
*
|
||||
* @note The chain the pointer is on is internal to the allocator and cannot be
|
||||
* used by applications.
|
||||
*/
|
||||
struct rtems_rtl_ptr_chain_s {
|
||||
rtems_chain_node node; /**< Chain of indirect pointers. */
|
||||
rtems_rtl_ptr_t ptr; /**< The indirect pointer. */
|
||||
};
|
||||
|
||||
typedef struct rtems_rtl_ptr_chain_s rtems_rtl_ptr_chain_t;
|
||||
|
||||
/**
|
||||
* A chain of indirect sized pointers for users to chain in applications.
|
||||
*
|
||||
* @note The chain the pointer is on is internal to the allocator and cannot be
|
||||
* used by applications.
|
||||
*/
|
||||
struct rtems_rtl_sptr_chain_s {
|
||||
rtems_chain_node node; /**< Chain of indirect pointers. */
|
||||
rtems_rtl_sptr_t ptr; /**< The indirect pointer. */
|
||||
};
|
||||
|
||||
typedef struct rtems_rtl_sptr_chain_s rtems_rtl_sptr_chain_t;
|
||||
|
||||
/**
|
||||
* Get the pointer given an indirect handle.
|
||||
*
|
||||
* @param handle The handle the pointer is returned from.
|
||||
* @return void* The pointer held in the handle.
|
||||
*/
|
||||
static inline void* rtems_rtl_ptr_get (rtems_rtl_ptr_t* handle)
|
||||
{
|
||||
return handle->pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pointer given an indirect handle and the pointer.
|
||||
*
|
||||
* @param handle The handle the pointer is returned from.
|
||||
* @param pointer The pointer to set in the handle.
|
||||
*/
|
||||
static inline void rtems_rtl_ptr_set (rtems_rtl_ptr_t* handle, void* pointer)
|
||||
{
|
||||
handle->pointer = pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the indirect handle.
|
||||
*
|
||||
* @param handle The handle to initialise.
|
||||
*/
|
||||
static inline void rtems_rtl_ptr_init (rtems_rtl_ptr_t* handle)
|
||||
{
|
||||
rtems_chain_set_off_chain (&handle->node);
|
||||
handle->pointer = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the indirect handle NULL ?
|
||||
*
|
||||
* @param handle The handle to test.
|
||||
* @return bool True if the pointer is NULL.
|
||||
*/
|
||||
static inline bool rtems_rtl_ptr_null (rtems_rtl_ptr_t* handle)
|
||||
{
|
||||
return handle->pointer == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the allocated pointer from one handle to another. The source handle is
|
||||
* cleared and removed from the list of handles.
|
||||
*
|
||||
* @param src The source handle to move the pointer from.
|
||||
* @param dst The destination handle to receive the pointer.
|
||||
*/
|
||||
static inline void rtems_rtl_ptr_move (rtems_rtl_ptr_t* dst, rtems_rtl_ptr_t* src)
|
||||
{
|
||||
/*
|
||||
* We do not know which chain the src handle resides on so insert the dst
|
||||
* handle after the src handle then extract the src handle.
|
||||
*/
|
||||
rtems_chain_insert_unprotected (&src->node, &dst->node);
|
||||
rtems_chain_extract_unprotected (&src->node);
|
||||
dst->pointer = src->pointer;
|
||||
rtems_rtl_ptr_init (src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pointer as the type provided.
|
||||
*
|
||||
* @param _h The handle.
|
||||
* @param _t The type.
|
||||
*/
|
||||
#define rtems_rtl_ptr_type_get(_h, _t) ((_t*) rtems_rtl_ptr_get (_h))
|
||||
|
||||
/**
|
||||
* Get the pointer given an indirect handle.
|
||||
*
|
||||
* @param handle The handle the pointer is returned from.
|
||||
* @return void* The pointer held in the handle.
|
||||
*/
|
||||
static inline void* rtems_rtl_sptr_get (rtems_rtl_sptr_t* handle)
|
||||
{
|
||||
return rtems_rtl_ptr_get (&handle->ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pointer given an indirect handle and the pointer.
|
||||
*
|
||||
* @param handle The handle the pointer is returned from.
|
||||
* @param pointer The pointer to set in the handle.
|
||||
*/
|
||||
static inline void rtems_rtl_sptr_set (rtems_rtl_sptr_t* handle, void* pointer)
|
||||
{
|
||||
rtems_rtl_ptr_set (&handle->ptr, pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the indirect handle.
|
||||
*
|
||||
* @param handle The handle to initialise.
|
||||
*/
|
||||
static inline void rtems_rtl_sptr_init (rtems_rtl_sptr_t* handle)
|
||||
{
|
||||
rtems_rtl_ptr_init (&handle->ptr);
|
||||
handle->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the indirect handle NULL ?
|
||||
*
|
||||
* @param handle The handle to test.
|
||||
* @return bool True if the pointer is NULL.
|
||||
*/
|
||||
static inline bool rtems_rtl_sptr_null (rtems_rtl_sptr_t* handle)
|
||||
{
|
||||
return rtems_rtl_ptr_null (&handle->ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the allocated pointer from one handle to another. The source handle is
|
||||
* cleared and removed from the list of handles.
|
||||
*
|
||||
* @param src The source handle to move the pointer from.
|
||||
* @param dst The destination handle to receive the pointer.
|
||||
*/
|
||||
static inline void rtems_rtl_sptr_move (rtems_rtl_sptr_t* dst, rtems_rtl_sptr_t* src)
|
||||
{
|
||||
rtems_rtl_ptr_move (&dst->ptr, &src->ptr);
|
||||
dst->size = src->size;
|
||||
src->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size.
|
||||
*
|
||||
* @param handle The handle to get the size from.
|
||||
* @return size_t The size_t.
|
||||
*/
|
||||
static inline size_t rtems_rtl_sptr_get_size (rtems_rtl_sptr_t* handle)
|
||||
{
|
||||
return handle->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size.
|
||||
*
|
||||
* @param handle The handle to set the size.
|
||||
* @param size The size to set..
|
||||
*/
|
||||
static inline void rtems_rtl_sptr_set_size (rtems_rtl_sptr_t* handle, size_t size)
|
||||
{
|
||||
handle->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pointer as the type provided.
|
||||
*
|
||||
* @param _h The handle.
|
||||
* @param _t The type.
|
||||
*/
|
||||
#define rtems_rtl_sptr_type_get(_h, _t) ((_t*) rtems_rtl_sptr_get (_h))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
323
cpukit/libdl/rtl-mdreloc-arm.c
Normal file
323
cpukit/libdl/rtl-mdreloc-arm.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Taken from NetBSD and stripped of the relocations not needed on RTEMS.
|
||||
*/
|
||||
|
||||
/* $NetBSD: mdreloc.c,v 1.33 2010/01/14 12:12:07 skrll Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
/*
|
||||
* It is possible for the compiler to emit relocations for unaligned data.
|
||||
* We handle this situation with these inlines.
|
||||
*/
|
||||
#define RELOC_ALIGNED_P(x) \
|
||||
(((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
|
||||
|
||||
static inline Elf_Addr
|
||||
load_ptr(void *where)
|
||||
{
|
||||
Elf_Addr res;
|
||||
|
||||
memcpy(&res, where, sizeof(res));
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
static inline void
|
||||
store_ptr(void *where, Elf_Addr val)
|
||||
{
|
||||
|
||||
memcpy(where, &val, sizeof(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* The address of Thumb function symbols is it's real address plus one.
|
||||
* This is done by compiler, thus do not consider symtype here.
|
||||
*/
|
||||
static inline int
|
||||
isThumb(Elf_Word symvalue)
|
||||
{
|
||||
if ((symvalue & 0x1) == 0x1)
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf_Addr tmp;
|
||||
Elf_Word insn, addend;
|
||||
Elf_Word sign, i1, i2;
|
||||
uint16_t lower_insn, upper_insn;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rel->r_offset);
|
||||
|
||||
switch (ELF_R_TYPE(rel->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(CALL): /* BL/BLX */
|
||||
case R_TYPE(JUMP24): /* B/BL<cond> */
|
||||
insn = *where;
|
||||
|
||||
if (insn & 0x00800000)
|
||||
addend = insn | 0xff000000;
|
||||
else addend = insn & 0x00ffffff;
|
||||
|
||||
if (isThumb(symvalue)) {
|
||||
if ((insn & 0xfe000000) == 0xfa000000); /* Already blx */
|
||||
else {
|
||||
if ((insn & 0xff000000) == 0xeb000000) { /* BL <label> */
|
||||
*where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
|
||||
} else {
|
||||
printf("JUMP24 is not suppored from arm to thumb\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = symvalue + (addend << 2) - (Elf_Addr)where;
|
||||
tmp = (Elf_Sword)tmp >> 2;
|
||||
|
||||
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
|
||||
printf("CALL/JUMP24 Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*where = (*where & 0xff000000) | (tmp & 0xffffff);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
|
||||
break;
|
||||
|
||||
case R_TYPE(V4BX):
|
||||
/* Miscellaneous, ignore */
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf ("rtl: V4BX %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TYPE(MOVT_ABS):
|
||||
case R_TYPE(MOVW_ABS_NC):
|
||||
insn = *where;
|
||||
|
||||
addend = ((insn >> 4) & 0xf000) | (insn & 0x0fff);
|
||||
if (addend & 0x8000)
|
||||
addend |= 0xffff0000;
|
||||
|
||||
tmp = symvalue + addend;
|
||||
|
||||
if (ELF_R_TYPE(rel->r_info) == R_TYPE(MOVW_ABS_NC))
|
||||
tmp &= 0xffff;
|
||||
else {
|
||||
tmp = (Elf_Sword)tmp >> 16;
|
||||
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
|
||||
printf("MOVT_ABS Overflow\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*where = (insn & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
|
||||
case R_TYPE(REL32): /* word32 (S + A) | T - P */
|
||||
case R_TYPE(ABS32): /* word32 (S + A) | T */
|
||||
case R_TYPE(GLOB_DAT): /* word32 (S + A) | T */
|
||||
if (__predict_true(RELOC_ALIGNED_P(where))) {
|
||||
tmp = *where + symvalue;
|
||||
if (isThumb(symvalue))
|
||||
tmp |= 1;
|
||||
if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32))
|
||||
tmp -= (Elf_Addr)where;
|
||||
*where = tmp;
|
||||
} else {
|
||||
tmp = load_ptr(where) + symvalue;
|
||||
if (isThumb(symvalue))
|
||||
tmp |= 1;
|
||||
if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32))
|
||||
tmp -= (Elf_Addr)where;
|
||||
store_ptr(where, tmp);
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: REL32/ABS32/GLOB_DAT %p @ %p in %s",
|
||||
(void *)tmp, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(THM_MOVT_ABS):
|
||||
case R_TYPE(THM_MOVW_ABS_NC):
|
||||
upper_insn = *(uint16_t *)where;
|
||||
lower_insn = *((uint16_t *)where + 1);
|
||||
|
||||
addend = ((upper_insn & 0x000f) << 12) | ((upper_insn & 0x0400) << 1) |
|
||||
((lower_insn & 0x7000) >> 4) | (lower_insn & 0x00ff);
|
||||
addend = (addend ^ 0x8000) - 0x8000;
|
||||
|
||||
tmp = addend + symvalue;
|
||||
if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
|
||||
tmp >>= 16;
|
||||
|
||||
*(uint16_t *)where = (uint16_t)((upper_insn & 0xfbf0) |
|
||||
((tmp & 0xf000) >> 12) |
|
||||
((tmp & 0x0800) >> 1));
|
||||
*((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0x8f00) |
|
||||
((tmp & 0x0700) << 4) |
|
||||
(tmp & 0x00ff));
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case R_TYPE(THM_JUMP24):
|
||||
/* same to THM_CALL; insn b.w */
|
||||
case R_TYPE(THM_CALL):
|
||||
upper_insn = *(uint16_t *)where;
|
||||
lower_insn = *((uint16_t *)where + 1);
|
||||
sign = (upper_insn & (1 << 10)) >> 10;
|
||||
i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
|
||||
i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
|
||||
tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
|
||||
addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
|
||||
|
||||
if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */
|
||||
else {
|
||||
if (ELF_R_TYPE(rel->r_info) == R_TYPE(THM_JUMP24)) {
|
||||
tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */
|
||||
printf("THM_JUMP24 to arm not supported\n");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* THM_CALL bl-->blx */
|
||||
lower_insn &=~(1<<12);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = symvalue + addend;
|
||||
tmp = tmp - (Elf_Addr)where;
|
||||
|
||||
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
|
||||
printf("THM_CALL/JUMP24 overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
sign = (tmp >> 24) & 1;
|
||||
*(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
|
||||
((tmp >> 12) & 0x3ff));
|
||||
|
||||
*((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)|
|
||||
((sign ^ (~(tmp >> 23) & 1)) << 13) |
|
||||
((sign ^ (~(tmp >> 22) & 1)) << 11) |
|
||||
((tmp >> 1) & 0x7ff));
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){
|
||||
printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case R_TYPE(THM_JUMP19):
|
||||
|
||||
if (!isThumb(symvalue)) {
|
||||
printf("THM_JUMP19 to arm not supported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
upper_insn = *(uint16_t *)where;
|
||||
lower_insn = *((uint16_t *)where + 1);
|
||||
sign = (upper_insn >> 10) & 0x1;
|
||||
|
||||
if ((((upper_insn & 0x3f) >> 7) & 0x7) == 0x7) {
|
||||
printf("THM_JUMP19 failed\n");
|
||||
return false; /*if cond <3:1> == '111', see Related codings in armv7a manual */
|
||||
}
|
||||
|
||||
i1 = (lower_insn >> 13) & 0x1;
|
||||
i2 = (lower_insn >> 11) & 0x1;
|
||||
|
||||
tmp = ((i2 << 19) | (i1 << 18) | ((upper_insn & 0x3f) << 12) | ((lower_insn & 0x7ff) << 1));
|
||||
addend = (tmp | ((sign ? 0 : 1) << 20)) - (1 << 20);
|
||||
tmp = symvalue + addend;
|
||||
|
||||
tmp = tmp - (Elf_Addr)where;
|
||||
|
||||
if (((Elf_Sword)tmp > 0x7ffffe) || ((Elf_Sword)tmp < -0x800000)) {
|
||||
rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
|
||||
"THM_JUMP19 relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
|
||||
return false;
|
||||
}
|
||||
|
||||
sign = (tmp >> 20) & 0x1;
|
||||
i2 = (tmp >> 19) & 0x1;
|
||||
i1 = (tmp >> 18) & 0x1;
|
||||
|
||||
*(uint16_t*)where = (upper_insn & 0xfbc0) | (sign << 10) | ((tmp >> 12) & 0x3f);
|
||||
*((uint16_t*)where + 1) = (lower_insn & 0xd000) | (i1 << 13) |
|
||||
(i2 << 11) | ((tmp >> 1) & 0x7ff);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: THM_JUMP19 %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
|
||||
"contents = %p\n",
|
||||
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
|
||||
(void *)rel->r_offset, (void *)*where);
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %ld "
|
||||
"in non-PLT relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
115
cpukit/libdl/rtl-mdreloc-bfin.c
Normal file
115
cpukit/libdl/rtl-mdreloc-bfin.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <rtl.h>
|
||||
#include <errno.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline Elf_Addr
|
||||
load_ptr(void *where)
|
||||
{
|
||||
Elf_Addr res;
|
||||
|
||||
memcpy(&res, where, sizeof(res));
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr target = 0;
|
||||
Elf_Addr *where;
|
||||
Elf_Word tmp;
|
||||
Elf_Word size; //byte
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("rela relocation type is %d relocated address 0x%08x",
|
||||
ELF_R_TYPE(rela->r_info), where);
|
||||
}
|
||||
|
||||
tmp = symvalue;
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(UNUSED0):
|
||||
break;
|
||||
|
||||
case R_TYPE(HUIMM16):
|
||||
tmp = symvalue >> 16;
|
||||
case R_TYPE(LUIMM16):
|
||||
case R_TYPE(RIMM16):
|
||||
size = 2;
|
||||
break;
|
||||
|
||||
case R_TYPE(BYTE4_DATA):
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case R_TYPE(PCREL24):
|
||||
case R_TYPE(PCREL24_JU):
|
||||
where = (Elf_Addr*)((Elf_Addr)where - 2); /* Back 2 bytes */
|
||||
tmp = symvalue - (Elf_Addr)where;
|
||||
tmp >>= 1;
|
||||
if ((tmp & 0x20000000) == 0x20000000)
|
||||
tmp |= 0xc0000000;
|
||||
|
||||
if ((tmp & 0xff000000) && (~tmp & 0xff800000)) {
|
||||
printf("PCREL24/PCREL24_JU Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
tmp = (load_ptr(where) & 0x0000ff00) | ((tmp & 0x0000ffff) << 16) |
|
||||
((tmp & 0x00ff0000) >> 16);
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case R_TYPE(PCREL12_JUMP_S):
|
||||
tmp = symvalue - (Elf_Addr)where;
|
||||
tmp >>= 1;
|
||||
if ((tmp & 0x20000000) == 0x20000000)
|
||||
tmp |= 0xc0000000;
|
||||
|
||||
if ((tmp & 0xfffff000) && (~tmp & 0xfffff800)) {
|
||||
printf("PCREL12_JUMP_S Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
tmp = ((*(uint16_t *)where) & 0xf000) | (tmp & 0xfff);
|
||||
size = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unspported rela type\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy((void*)where, &tmp, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rel type record not supported");
|
||||
return false;
|
||||
}
|
||||
101
cpukit/libdl/rtl-mdreloc-h8300.c
Normal file
101
cpukit/libdl/rtl-mdreloc-h8300.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf_Word tmp;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
|
||||
printf("relocated address 0x%08lx\n", (Elf_Addr)where);
|
||||
}
|
||||
|
||||
tmp = symvalue;
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(DIR16):
|
||||
*(uint16_t *)where += symvalue + rela->r_addend;
|
||||
break;
|
||||
|
||||
case R_TYPE(DIR32):
|
||||
case R_TYPE(DIR32A16):
|
||||
*where += symvalue + rela->r_addend;
|
||||
break;
|
||||
|
||||
case R_TYPE(DIR24A8):
|
||||
if (ELF32_R_SYM(rela->r_info))
|
||||
*where += symvalue + rela->r_addend;
|
||||
break;
|
||||
|
||||
case R_TYPE(DIR24R8):
|
||||
where = (uint32_t *)((uint32_t)where - 1);
|
||||
*where = (*where & 0xff000000) | ((*where & 0xffffff) + symvalue + rela->r_addend);
|
||||
break;
|
||||
|
||||
case R_TYPE(PCREL8):
|
||||
/* bcc instruction */
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where - 1;
|
||||
if (((Elf32_Sword)tmp > 0x7f) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x80)){
|
||||
printf("PCREL8 overflow\n");
|
||||
return false;
|
||||
} else {
|
||||
*(uint8_t *)where = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TYPE(PCREL16):
|
||||
/* bcc instruction */
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where - 2;
|
||||
if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x8000)){
|
||||
printf("PCREL16 overflow\n");
|
||||
return false;
|
||||
} else {
|
||||
*(uint16_t *)where = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
printf("Unsupported reloc types\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rel type record not supported");
|
||||
return false;
|
||||
}
|
||||
103
cpukit/libdl/rtl-mdreloc-i386.c
Normal file
103
cpukit/libdl/rtl-mdreloc-i386.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Taken from NetBSD and stripped of the relocations not needed on RTEMS.
|
||||
*/
|
||||
|
||||
/* $NetBSD: mdreloc.c,v 1.31 2010/01/14 11:58:32 skrll Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr target = 0;
|
||||
Elf_Addr* where;
|
||||
Elf_Addr tmp;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rel->r_offset);
|
||||
|
||||
switch (ELF_R_TYPE(rel->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(PC32):
|
||||
target = (Elf_Addr) symvalue;
|
||||
*where += target - (Elf_Addr)where;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc PC32 in %s --> %p (%p @ %p) in %s\n",
|
||||
sect->name, (void*) symvalue,
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(GOT32):
|
||||
case R_TYPE(32):
|
||||
case R_TYPE(GLOB_DAT):
|
||||
target = (Elf_Addr) symvalue;
|
||||
|
||||
tmp = target + *where;
|
||||
if (*where != tmp)
|
||||
*where = tmp;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc 32/GLOB_DAT in %s --> %p @ %p in %s\n",
|
||||
sect->name, (void *)*where, where,
|
||||
rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(RELATIVE):
|
||||
*where += (Elf_Addr)sect->base;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc RELATIVE in %s --> %p @ %p\n",
|
||||
rtems_rtl_obj_oname (obj), (void *)*where, where);
|
||||
break;
|
||||
|
||||
case R_TYPE(COPY):
|
||||
printf ("rtl: reloc COPY (please report)\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
|
||||
"contents = %p\n",
|
||||
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
|
||||
(void *)rel->r_offset, (void *)*where);
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %ld "
|
||||
"in non-PLT relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
120
cpukit/libdl/rtl-mdreloc-lm32.c
Normal file
120
cpukit/libdl/rtl-mdreloc-lm32.c
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf32_Word tmp;
|
||||
Elf32_Word insn;
|
||||
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(HI16):
|
||||
insn = *where;
|
||||
/* orhi/mvhi instruction
|
||||
* 31--------26|25-21|20-16|15----0|
|
||||
* |0 1 1 1 1 0 |rY |rX |imm16 |
|
||||
*/
|
||||
if (0x1e == (insn >> 26)) {
|
||||
insn &= 0xffff0000;
|
||||
insn |= ((symvalue + rela->r_addend) >> 16);
|
||||
*where = insn;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TYPE(LO16):
|
||||
insn = *where;
|
||||
/* ori instruction
|
||||
* 31--------26|25-21|20-16|15----0|
|
||||
* |0 0 1 1 1 0 |rY |rX |imm16 |
|
||||
*/
|
||||
if (0xe == (insn >> 26)) {
|
||||
insn &= 0xffff0000;
|
||||
insn |= ((symvalue + rela->r_addend) & 0xffff);
|
||||
*where = insn;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TYPE(CALL):
|
||||
insn = *where;
|
||||
/*
|
||||
* calli instruction
|
||||
* 31-------26|25---0|
|
||||
* |1 1 1 1 1 0|imm26 |
|
||||
* Syntax: call imm26
|
||||
* Operation: ra = pc + 4; pc = pc + sign_extend(imm26<<2)
|
||||
*/
|
||||
if (0x3e == (insn >> 26)) {
|
||||
Elf_Sword imm26 = symvalue +rela->r_addend - (Elf_Addr)where;
|
||||
imm26 = (imm26 >> 2) & 0x3ffffff;
|
||||
insn = 0xf8000000 + imm26;
|
||||
*where = insn;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TYPE(BRANCH):
|
||||
insn = *where;
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
tmp = (Elf32_Sword)tmp >> 2;
|
||||
if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -0x8000)){
|
||||
printf("BRANCH Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*where = (*where & 0xffff0000) | (tmp & 0xffff);
|
||||
break;
|
||||
|
||||
case R_TYPE(32):
|
||||
*where = symvalue + rela->r_addend;
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
printf("Unsupported reloc types\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
|
||||
printf("relocated address 0x%08lx\n", (Elf_Addr)where);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
return false;
|
||||
}
|
||||
156
cpukit/libdl/rtl-mdreloc-m32r.c
Normal file
156
cpukit/libdl/rtl-mdreloc-m32r.c
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
static inline Elf_Addr
|
||||
load_ptr(void *where)
|
||||
{
|
||||
Elf_Addr res;
|
||||
|
||||
memcpy(&res, where, sizeof(res));
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
static inline void
|
||||
store_ptr(void *where, Elf_Addr val)
|
||||
{
|
||||
memcpy(where, &val, sizeof(val));
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
|
||||
Elf_Addr *where;
|
||||
Elf_Word tmp;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("relocated address 0x%08lx\n", (Elf_Addr)where);
|
||||
}
|
||||
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(16_RELA):
|
||||
/*
|
||||
* half16: S + A
|
||||
*/
|
||||
*(uint16_t *)where = (symvalue + rela->r_addend) & 0xffff;
|
||||
break;
|
||||
|
||||
case R_TYPE(24_RELA):
|
||||
/*
|
||||
* imm24: (S + A) & 0xFFFFFF
|
||||
*/
|
||||
tmp = symvalue + rela->r_addend;
|
||||
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
|
||||
printf("24_RELA Overflow\n");
|
||||
return false;
|
||||
}
|
||||
*where = (*where & 0xff000000) | tmp & 0xffffff;
|
||||
break;
|
||||
|
||||
case R_TYPE(32_RELA):
|
||||
/*
|
||||
* word32: S + A
|
||||
*/
|
||||
*where += symvalue + rela->r_addend;
|
||||
break;
|
||||
|
||||
case R_TYPE(26_PCREL_RELA):
|
||||
/*
|
||||
* disp24: ((S + A - P) >> 2) & 0xFFFFFF
|
||||
*/
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
tmp = (Elf_Sword)tmp >> 2;
|
||||
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
|
||||
printf("26_PCREL_RELA Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*where = (*where & 0xff000000) | (tmp & 0xffffff);
|
||||
break;
|
||||
|
||||
case R_TYPE(18_PCREL_RELA):
|
||||
/*
|
||||
* disp16: ((S + A - P) >> 2) & 0xFFFFFF
|
||||
*/
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
tmp = (Elf_Sword)tmp >> 2;
|
||||
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
|
||||
printf("18_PCREL_RELA Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*where = (*where & 0xffff0000) | (tmp & 0xffff);
|
||||
break;
|
||||
|
||||
case R_TYPE(HI16_ULO_RELA):
|
||||
/*
|
||||
* imm16: ((S + A) >> 16)
|
||||
*/
|
||||
tmp = *where;
|
||||
tmp += ((symvalue + rela->r_addend) >> 16) & 0xffff;
|
||||
*where = tmp;
|
||||
break;
|
||||
|
||||
case R_TYPE(HI16_SLO_RELA):
|
||||
/*
|
||||
* imm16: ((S + A) >> 16) or ((S + A + 0x10000) >> 16)
|
||||
*/
|
||||
tmp = symvalue + rela->r_addend;
|
||||
if (tmp & 0x8000) tmp += 0x10000;
|
||||
tmp = (tmp >> 16) & 0xffff;
|
||||
*where += tmp;
|
||||
break;
|
||||
|
||||
case R_TYPE(LO16_RELA):
|
||||
/*
|
||||
* imm16: (S + A) & 0xFFFF
|
||||
*/
|
||||
tmp = symvalue + rela->r_addend;
|
||||
*where = (*where & 0xffff0000) | (tmp & 0xffff);
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
printf("Unsupported rela reloc types\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
|
||||
rtems_rtl_set_error (EINVAL, "rel type record not supported");
|
||||
return true;
|
||||
}
|
||||
148
cpukit/libdl/rtl-mdreloc-m68k.c
Normal file
148
cpukit/libdl/rtl-mdreloc-m68k.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Taken from NetBSD and stripped of the relocations not needed on RTEMS.
|
||||
*/
|
||||
|
||||
/* $NetBSD: mdreloc.c,v 1.26 2010/01/14 11:58:32 skrll Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
static inline int overflow_8_check(int value)
|
||||
{
|
||||
if ((value & 0xffffff00) && (~value & 0xffffff80))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int overflow_16_check(int value)
|
||||
{
|
||||
if ((value & 0xffff0000) && (~value & 0xffff8000))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symnane,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr target = 0;
|
||||
Elf_Addr* where;
|
||||
Elf_Word tmp;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(PC8):
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
if (overflow_8_check(tmp))
|
||||
return false;
|
||||
|
||||
*(uint8_t *)where = tmp;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
|
||||
sect->name, (void*) (symvalue + rela->r_addend),
|
||||
(void *)*where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(PC16):
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
if (overflow_16_check(tmp))
|
||||
return false;
|
||||
|
||||
*(uint16_t*)where = tmp;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
|
||||
sect->name, (void*) (symvalue + rela->r_addend),
|
||||
(void *)*where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
case R_TYPE(PC32):
|
||||
target = (Elf_Addr) symvalue + rela->r_addend;
|
||||
*where += target - (Elf_Addr)where;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
|
||||
sect->name, (void*) (symvalue + rela->r_addend),
|
||||
(void *)*where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(GOT32):
|
||||
case R_TYPE(32):
|
||||
case R_TYPE(GLOB_DAT):
|
||||
target = (Elf_Addr) symvalue + rela->r_addend;
|
||||
|
||||
if (*where != target)
|
||||
*where = target;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
|
||||
sect->name, (void *)*where,
|
||||
rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(RELATIVE):
|
||||
*where += (Elf_Addr) sect->base + rela->r_addend;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc RELATIVE in %s --> %p\n",
|
||||
rtems_rtl_obj_oname (obj), (void *)*where);
|
||||
break;
|
||||
|
||||
case R_TYPE(COPY):
|
||||
/*
|
||||
* These are deferred until all other relocations have
|
||||
* been done. All we do here is make sure that the
|
||||
* COPY relocation is not in a shared library. They
|
||||
* are allowed only in executable files.
|
||||
*/
|
||||
printf ("rtl: reloc COPY (please report)\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
|
||||
"contents = %p\n",
|
||||
ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
|
||||
(void *)rela->r_offset, (void *)*where);
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %ld "
|
||||
"in non-PLT relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rel type record not supported");
|
||||
return false;
|
||||
}
|
||||
190
cpukit/libdl/rtl-mdreloc-mips.c
Normal file
190
cpukit/libdl/rtl-mdreloc-mips.c
Normal file
@@ -0,0 +1,190 @@
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. _gp_disp symbol are not considered in this file.
|
||||
* 2. There is a local/external column;
|
||||
* local corresponds to (STB_LOCAL & STT_SECTION) and
|
||||
* all others are external. Because if the type of a
|
||||
* symbol is STT_SECTION, it must be STB_LOCAL. Thus
|
||||
* just consider symtype here.
|
||||
*/
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf_Word tmp;
|
||||
Elf_Word addend = (Elf_Word)0;
|
||||
Elf_Word local = 0;
|
||||
uint32_t t;
|
||||
|
||||
|
||||
static Elf_Addr *where_hi16;
|
||||
static Elf_Addr ahl;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rel->r_offset);
|
||||
addend = *where;
|
||||
|
||||
if (syminfo == STT_SECTION)
|
||||
local = 1;
|
||||
|
||||
switch (ELF_R_TYPE(rel->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(16):
|
||||
tmp = addend & 0xffff;
|
||||
if ((tmp & 0x8000) == 0x8000)
|
||||
tmp |= 0xffff0000; /* Sign extend */
|
||||
tmp = symvalue + (int)tmp;
|
||||
if ((tmp & 0xffff0000) != 0) {
|
||||
printf("R_MIPS_16 Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*where = (tmp & 0xffff) | (*where & 0xffff0000);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: R_MIPS_16 %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(32):
|
||||
tmp = symvalue + addend;
|
||||
if (addend != tmp)
|
||||
*where = tmp;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: R_MIPS_32 %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(26):
|
||||
|
||||
addend &= 0x03ffffff;
|
||||
addend <<= 2;
|
||||
|
||||
if (local == 1) { /* STB_LOCAL and STT_SECTION */
|
||||
tmp = symvalue + (((Elf_Addr)where & 0xf0000000) | addend);
|
||||
tmp >>= 2;
|
||||
|
||||
} else { /* external */
|
||||
|
||||
tmp = addend;
|
||||
|
||||
if ((tmp & 0x08000000) == 0x08000000)
|
||||
tmp |= 0xf0000000; /* Sign extened */
|
||||
tmp = ((int)tmp + symvalue) >> 2;
|
||||
|
||||
}
|
||||
|
||||
*where &= ~0x03ffffff;
|
||||
*where |= tmp & 0x03ffffff;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: R_MIPS_26 local=%d %p @ %p in %s\n",
|
||||
local, (void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(HI16):
|
||||
ahl = addend << 16;
|
||||
where_hi16 = where;
|
||||
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: R_MIPS_HI16 %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(LO16):
|
||||
//ahl += (int16_t)addend;
|
||||
t = ahl + (int16_t)addend;
|
||||
tmp = symvalue;
|
||||
if (tmp == 0)
|
||||
return false;
|
||||
|
||||
addend &= 0xffff0000;
|
||||
addend |= (uint16_t)(t + tmp);
|
||||
*where = addend;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf("*where %x where %x\n", *where, where);
|
||||
|
||||
addend = *where_hi16;
|
||||
addend &= 0xffff0000;
|
||||
addend |= ((t + tmp) - (int16_t)(t + tmp)) >> 16;
|
||||
*where_hi16 = addend;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf("*where_hi %x where_hi %x\n", *where_hi16, where_hi16);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: R_MIPS_LO16 %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(PC16):
|
||||
tmp = addend & 0xffff;
|
||||
if ((tmp & 0x8000) == 0x8000)
|
||||
tmp |= 0xffff0000; /* Sign extend */
|
||||
tmp = symvalue + ((int)tmp*4) - (Elf_Addr)where;
|
||||
tmp = (Elf_Sword)tmp >> 2;
|
||||
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
|
||||
printf("R_MIPS_PC16 Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*where = (tmp & 0xffff) | (*where & 0xffff0000);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: R_MIPS_PC16 %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
|
||||
"contents = %p\n",
|
||||
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
|
||||
(void *)rel->r_offset, (void *)*where);
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %ld "
|
||||
"in non-PLT relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
88
cpukit/libdl/rtl-mdreloc-moxie.c
Normal file
88
cpukit/libdl/rtl-mdreloc-moxie.c
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf_Sword tmp;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
|
||||
/* Handle the not 4byte aligned address carefully */
|
||||
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(32):
|
||||
*(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
|
||||
*((uint16_t *)where + 1) = (symvalue + rela->r_addend) & 0xffff;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("*where 0x%04x%04x\n", *((uint16_t *)where + 1), *(uint16_t *)where);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TYPE(PCREL10):
|
||||
/* beq, bge, bgeu, bgt, bgtu, ble, bleu, blt, bltu, bne */
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("*where %x\n", *(uint16_t *)where);
|
||||
printf("symvalue - where %x\n", (int)(symvalue - (Elf_Word)where));
|
||||
}
|
||||
tmp = (symvalue + rela->r_addend - ((Elf_Word)where + 2)); /* pc is the next instruction */
|
||||
tmp = (Elf_Sword)tmp >> 1;
|
||||
if (((Elf32_Sword)tmp > 0x1ff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x200)){
|
||||
printf("Overflow for PCREL10: %d exceed -0x200:0x1ff\n", tmp);
|
||||
return false;
|
||||
}
|
||||
|
||||
*(uint16_t *)where = (*(uint16_t *)where & 0xfc00) | (tmp & 0x3ff);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("*where 0x%04x\n", *(uint16_t *)where);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
printf("Unsupported reloc types\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rel type record not supported");
|
||||
return false;
|
||||
}
|
||||
44
cpukit/libdl/rtl-mdreloc-nios2.c
Normal file
44
cpukit/libdl/rtl-mdreloc-nios2.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Taken from NetBSD and stripped of the relocations not needed on RTEMS.
|
||||
*/
|
||||
|
||||
/* $NetBSD: mdreloc.c,v 1.26 2010/01/14 11:58:32 skrll Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
Elf_Word symvalue)
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
Elf_Word symvalue)
|
||||
{
|
||||
printf ("rtl: rel type record not supported; please report\n");
|
||||
return false;
|
||||
}
|
||||
186
cpukit/libdl/rtl-mdreloc-powerpc.c
Normal file
186
cpukit/libdl/rtl-mdreloc-powerpc.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Taken from NetBSD and stripped of the relocations not needed on RTEMS.
|
||||
*/
|
||||
|
||||
/* $NetBSD: ppc_reloc.c,v 1.44 2010/01/13 20:17:22 christos Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
|
||||
((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
|
||||
#define l(x) ((u_int32_t)(x) & 0xffff)
|
||||
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr target = 0;
|
||||
Elf_Addr* where;
|
||||
Elf_Word tmp;
|
||||
uint32_t mask = 0;
|
||||
uint32_t bits = 0;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(32):
|
||||
/*
|
||||
* value:1; Field: word32; Expression: S + A
|
||||
*/
|
||||
*where = symvalue + rela->r_addend;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: ADDR32 %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(14):
|
||||
/*
|
||||
* value:7; Field: low14*; Expression: (S + A) >> 2
|
||||
*/
|
||||
case R_TYPE(24):
|
||||
/*
|
||||
* value:2; Field: low24*; Expression: (S + A) >> 2
|
||||
*/
|
||||
if (ELF_R_TYPE(rela->r_info) == R_TYPE(14)) {
|
||||
bits = 14;
|
||||
mask = 0xfffc;
|
||||
} else {
|
||||
bits = 24;
|
||||
mask = 0x3fffffc;
|
||||
}
|
||||
tmp = (symvalue + rela->r_addend) >> 2;
|
||||
if (tmp > (1<<bits -1 )) {
|
||||
printf("Overflow ADDR14/ADDR24\n");
|
||||
return false;
|
||||
}
|
||||
tmp = *where;
|
||||
tmp &= ~mask;
|
||||
tmp |= (symvalue + rela->r_addend) & mask;
|
||||
*where = tmp;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(16_HA):
|
||||
/*
|
||||
* value:6; Field:half16; Expression: #ha(S+A)
|
||||
*/
|
||||
|
||||
tmp = symvalue + rela->r_addend;
|
||||
*(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: 16_HA %p @ %p in %s\n",
|
||||
(void *)*(where), where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(16_HI):
|
||||
/*
|
||||
* value:5; Field:half16; Expression: #hi(S+A)
|
||||
*/
|
||||
*(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: 16_HI %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
case R_TYPE(16_LO):
|
||||
/*
|
||||
* value:4; Field:half16; Expression: #lo(S+A)
|
||||
*/
|
||||
*(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: 16_LO %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(REL14):
|
||||
/*
|
||||
* value:11; Field:low14*; Expression:(S+A-P)>>2
|
||||
*/
|
||||
case R_TYPE(REL24):
|
||||
/*
|
||||
* value:10; Field:low24*; Expression:(S+A-P)>>2
|
||||
*/
|
||||
if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL24)) {
|
||||
mask = 0x3fffffc;
|
||||
bits = 24;
|
||||
}
|
||||
else if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL14)) {
|
||||
mask = 0xfffc;
|
||||
bits = 14;
|
||||
}
|
||||
|
||||
tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
|
||||
if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
|
||||
((Elf_Sword)tmp < -(1<<(bits-1)))) {
|
||||
printf("Overflow REL14/REL24\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
tmp = *where;
|
||||
tmp &= ~mask;
|
||||
tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
|
||||
*where = tmp;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: REL24/REL14 %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(REL32):
|
||||
/*
|
||||
* value:26; Field:word32*; Expression:S+A-P
|
||||
*/
|
||||
*where = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: REL32 %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
|
||||
"contents = %p\n",
|
||||
ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
|
||||
(void *)rela->r_offset, (void *)*where);
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %ld "
|
||||
"in non-PLT relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
printf ("rtl: rel type record not supported; please report\n");
|
||||
return false;
|
||||
}
|
||||
261
cpukit/libdl/rtl-mdreloc-sparc.c
Normal file
261
cpukit/libdl/rtl-mdreloc-sparc.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Taken from NetBSD and stripped of the relocations not needed on RTEMS.
|
||||
*/
|
||||
|
||||
/* $NetBSD: mdreloc.c,v 1.43 2010/01/13 20:17:22 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Paul Kranenburg and by Charles M. Hannum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
/*
|
||||
* The following table holds for each relocation type:
|
||||
* - the width in bits of the memory location the relocation
|
||||
* applies to (not currently used)
|
||||
* - the number of bits the relocation value must be shifted to the
|
||||
* right (i.e. discard least significant bits) to fit into
|
||||
* the appropriate field in the instruction word.
|
||||
* - flags indicating whether
|
||||
* * the relocation involves a symbol
|
||||
* * the relocation is relative to the current position
|
||||
* * the relocation is for a GOT entry
|
||||
* * the relocation is relative to the load address
|
||||
*
|
||||
*/
|
||||
#define _RF_S 0x80000000 /* Resolve symbol */
|
||||
#define _RF_A 0x40000000 /* Use addend */
|
||||
#define _RF_P 0x20000000 /* Location relative */
|
||||
#define _RF_G 0x10000000 /* GOT offset */
|
||||
#define _RF_B 0x08000000 /* Load address relative */
|
||||
#define _RF_U 0x04000000 /* Unaligned */
|
||||
#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */
|
||||
#define _RF_RS(s) ( (s) & 0xff) /* right shift */
|
||||
|
||||
static const uint32_t reloc_target_flags[] = {
|
||||
0, /* NONE */
|
||||
_RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */
|
||||
_RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */
|
||||
_RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */
|
||||
_RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */
|
||||
_RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */
|
||||
_RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */
|
||||
_RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */
|
||||
_RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */
|
||||
_RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */
|
||||
_RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */
|
||||
_RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */
|
||||
_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */
|
||||
_RF_SZ(32) | _RF_RS(0), /* COPY */
|
||||
_RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */
|
||||
_RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */
|
||||
_RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* RELATIVE */
|
||||
_RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */
|
||||
};
|
||||
|
||||
#define NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
|
||||
#ifdef NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
|
||||
static const char *reloc_names[] = {
|
||||
"NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
|
||||
"DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
|
||||
"22", "13", "LO10", "GOT10", "GOT13",
|
||||
"GOT22", "PC10", "PC22", "WPLT30", "COPY",
|
||||
"GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32"
|
||||
};
|
||||
#endif
|
||||
|
||||
#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0)
|
||||
#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0)
|
||||
#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0)
|
||||
#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0)
|
||||
#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0)
|
||||
#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff)
|
||||
#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff)
|
||||
|
||||
static const int reloc_target_bitmask[] = {
|
||||
#define _BM(x) (~(-(1ULL << (x))))
|
||||
0, /* NONE */
|
||||
_BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */
|
||||
_BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */
|
||||
_BM(30), _BM(22), /* WDISP30, WDISP22 */
|
||||
_BM(22), _BM(22), /* HI22, _22 */
|
||||
_BM(13), _BM(10), /* RELOC_13, _LO10 */
|
||||
_BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */
|
||||
_BM(10), _BM(22), /* _PC10, _PC22 */
|
||||
_BM(30), 0, /* _WPLT30, _COPY */
|
||||
-1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
|
||||
_BM(32) /* _UA32 */
|
||||
#undef _BM
|
||||
};
|
||||
#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return RELOC_RESOLVE_SYMBOL (type) ? true : false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf_Word type, value, mask;
|
||||
|
||||
where = (Elf_Addr *) (sect->base + rela->r_offset);
|
||||
|
||||
type = ELF_R_TYPE(rela->r_info);
|
||||
if (type == R_TYPE(NONE))
|
||||
return true;
|
||||
|
||||
/* We do JMP_SLOTs in _rtld_bind() below */
|
||||
if (type == R_TYPE(JMP_SLOT))
|
||||
return true;
|
||||
|
||||
/* COPY relocs are also handled elsewhere */
|
||||
if (type == R_TYPE(COPY))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* We use the fact that relocation types are an `enum'
|
||||
* Note: R_SPARC_6 is currently numerically largest.
|
||||
*/
|
||||
if (type > R_TYPE(6))
|
||||
return false;
|
||||
|
||||
value = rela->r_addend;
|
||||
|
||||
/*
|
||||
* Handle relative relocs here, as an optimization.
|
||||
*/
|
||||
if (type == R_TYPE (RELATIVE)) {
|
||||
*where += (Elf_Addr)(sect->base + value);
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: reloc relative in %s --> %p",
|
||||
rtems_rtl_obj_oname (obj), (void *)*where);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (RELOC_RESOLVE_SYMBOL (type)) {
|
||||
/* Add in the symbol's absolute address */
|
||||
value += symvalue;
|
||||
}
|
||||
|
||||
if (RELOC_PC_RELATIVE (type)) {
|
||||
value -= (Elf_Word)where;
|
||||
}
|
||||
|
||||
if (RELOC_BASE_RELATIVE (type)) {
|
||||
/*
|
||||
* Note that even though sparcs use `Elf_rela'
|
||||
* exclusively we still need the implicit memory addend
|
||||
* in relocations referring to GOT entries.
|
||||
* Undoubtedly, someone f*cked this up in the distant
|
||||
* past, and now we're stuck with it in the name of
|
||||
* compatibility for all eternity..
|
||||
*
|
||||
* In any case, the implicit and explicit should be
|
||||
* mutually exclusive. We provide a check for that
|
||||
* here.
|
||||
*/
|
||||
#define DIAGNOSTIC
|
||||
#ifdef DIAGNOSTIC
|
||||
if (value != 0 && *where != 0) {
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf("rtl: reloc base_rel(%s): where=%p, *where 0x%lx, "
|
||||
"addend=0x%lx, base %p\n",
|
||||
rtems_rtl_obj_oname (obj),
|
||||
where, *where, rela->r_addend, sect->base);
|
||||
}
|
||||
#endif
|
||||
value += (Elf_Word)(sect->base + *where);
|
||||
}
|
||||
|
||||
mask = RELOC_VALUE_BITMASK (type);
|
||||
value >>= RELOC_VALUE_RIGHTSHIFT (type);
|
||||
value &= mask;
|
||||
|
||||
if (RELOC_UNALIGNED(type)) {
|
||||
/* Handle unaligned relocations. */
|
||||
Elf_Addr tmp = 0;
|
||||
char *ptr = (char *)where;
|
||||
int i, size = RELOC_TARGET_SIZE (type) / 8;
|
||||
|
||||
/* Read it in one byte at a time. */
|
||||
for (i=0; i<size; i++)
|
||||
tmp = (tmp << 8) | ptr[i];
|
||||
|
||||
tmp &= ~mask;
|
||||
tmp |= value;
|
||||
|
||||
/* Write it back out. */
|
||||
for (i=0; i<size; i++)
|
||||
ptr[i] = ((tmp >> (8*i)) & 0xff);
|
||||
|
||||
} else {
|
||||
*where &= ~mask;
|
||||
*where |= value;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: %s %p @ %p in %s\n",
|
||||
reloc_names[type], (void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
printf ("rtl: rel type record not supported; please report\n");
|
||||
return false;
|
||||
}
|
||||
97
cpukit/libdl/rtl-mdreloc-v850.c
Normal file
97
cpukit/libdl/rtl-mdreloc-v850.c
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rela* rela,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
Elf_Addr *where;
|
||||
Elf_Word tmp;
|
||||
|
||||
where = (Elf_Addr *)(sect->base + rela->r_offset);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
|
||||
printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
|
||||
printf("relocated address 0x%08lx\n", (Elf_Addr)where);
|
||||
}
|
||||
|
||||
switch (ELF_R_TYPE(rela->r_info)) {
|
||||
case R_TYPE(NONE):
|
||||
break;
|
||||
|
||||
case R_TYPE(HI16_S):
|
||||
tmp = (Elf_Sword)(symvalue + rela->r_addend) >> 16;
|
||||
((uint16_t *)where)[0] = tmp & 0xffff;
|
||||
break;
|
||||
|
||||
case R_TYPE(LO16):
|
||||
tmp = symvalue + rela->r_addend;
|
||||
((uint16_t *)where)[0] = tmp & 0xffff;
|
||||
break;
|
||||
|
||||
case R_TYPE(LO16_S1):
|
||||
tmp = symvalue + rela->r_addend;
|
||||
((uint16_t *)where)[0] = tmp & 0xfffe | 0x1;
|
||||
break;
|
||||
|
||||
case R_TYPE(22_PCREL):
|
||||
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
|
||||
if (((Elf_Sword)tmp > 0x1fffff) || ((Elf_Sword)tmp < -0x200000)) {
|
||||
printf("Overflow\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
((uint16_t *)where)[0] = (*(uint16_t *)where & 0xffc0) |
|
||||
((tmp >> 16) & 0x3f);
|
||||
((uint16_t *)where)[1] = (tmp & 0xfffe);
|
||||
|
||||
break;
|
||||
|
||||
case R_TYPE(ABS32):
|
||||
tmp = symvalue + rela->r_addend;
|
||||
tmp += ((uint16_t *)where)[0];
|
||||
tmp += ((uint16_t *)where)[1] << 16;
|
||||
((uint16_t *)where)[0] = tmp & 0xffff;
|
||||
((uint16_t *)where)[1] = (tmp >> 16) & 0xffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_rtl_set_error (EINVAL, "rela type record not supported");
|
||||
printf("error reloc type\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
|
||||
const Elf_Rel* rel,
|
||||
const rtems_rtl_obj_sect_t* sect,
|
||||
const char* symname,
|
||||
const Elf_Byte syminfo,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "rel type record not supported");
|
||||
return false;
|
||||
}
|
||||
197
cpukit/libdl/rtl-obj-cache.c
Normal file
197
cpukit/libdl/rtl-obj-cache.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File cache buffers a section of the
|
||||
* object file in a buffer to localise read performance.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/rtl/rtl-allocator.h>
|
||||
#include "rtl-obj-cache.h"
|
||||
#include "rtl-error.h"
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size)
|
||||
{
|
||||
cache->fd = -1;
|
||||
cache->file_size = 0;
|
||||
cache->offset = 0;
|
||||
cache->size = size;
|
||||
cache->level = 0;
|
||||
cache->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
|
||||
if (!cache->buffer)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for cache buffer");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache)
|
||||
{
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer);
|
||||
cache->fd = -1;
|
||||
cache->file_size = 0;
|
||||
cache->level = 0;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache)
|
||||
{
|
||||
cache->fd = -1;
|
||||
cache->file_size = 0;
|
||||
cache->level = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
off_t offset,
|
||||
void** buffer,
|
||||
size_t* length)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (*length > cache->size)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "read size larger than cache size");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cache->fd == fd)
|
||||
{
|
||||
if (offset > cache->file_size)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "offset past end of file: offset=%i size=%i",
|
||||
(int) offset, (int) cache->file_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((offset + *length) > cache->file_size)
|
||||
*length = cache->file_size - offset;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t buffer_offset = 0;
|
||||
size_t buffer_read = cache->size;
|
||||
|
||||
/*
|
||||
* Is the data in the cache for this file ?
|
||||
*/
|
||||
if (fd == cache->fd)
|
||||
{
|
||||
/*
|
||||
* Is any part of the data in the cache ?
|
||||
*/
|
||||
if ((offset >= cache->offset) &&
|
||||
(offset < (cache->offset + cache->level)))
|
||||
{
|
||||
buffer_offset = offset - cache->offset;
|
||||
|
||||
/*
|
||||
* Return the location of the data in the cache.
|
||||
*/
|
||||
*buffer = cache->buffer + buffer_offset;
|
||||
|
||||
/*
|
||||
* Is all the data in the cache or just a part ?
|
||||
*/
|
||||
if (*length <= (cache->level - buffer_offset))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy down the data in the buffer and then fill the remaining
|
||||
* space with as much data we are able to read.
|
||||
*/
|
||||
memmove (cache->buffer,
|
||||
cache->buffer + buffer_offset,
|
||||
cache->size - buffer_offset);
|
||||
|
||||
buffer_read = buffer_offset;
|
||||
buffer_offset = cache->size - buffer_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0)
|
||||
{
|
||||
rtems_rtl_set_error (errno, "file seek failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop reading the data from the file until either an error or 0 is
|
||||
* returned and if data has been read check if the amount is what we
|
||||
* want. If not it is an error. A POSIX read can read data in fragments.
|
||||
*/
|
||||
cache->level = buffer_read;
|
||||
while (buffer_read)
|
||||
{
|
||||
int r = read (fd, cache->buffer + buffer_offset, buffer_read);
|
||||
if (r < 0)
|
||||
{
|
||||
rtems_rtl_set_error (errno, "file read failed");
|
||||
return false;
|
||||
}
|
||||
if ((r == 0) && buffer_read)
|
||||
{
|
||||
cache->level = cache->level - buffer_read;
|
||||
buffer_read = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_read -= r;
|
||||
buffer_offset += r;
|
||||
}
|
||||
}
|
||||
|
||||
cache->fd = fd;
|
||||
cache->offset = offset;
|
||||
|
||||
if (fstat (cache->fd, &sb) < 0)
|
||||
{
|
||||
rtems_rtl_set_error (errno, "file stat failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
cache->file_size = sb.st_size;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
off_t offset,
|
||||
void* buffer,
|
||||
size_t length)
|
||||
{
|
||||
void* cbuffer = 0;
|
||||
size_t len = length;
|
||||
bool ok = rtems_rtl_obj_cache_read (cache, fd, offset, &cbuffer, &len);
|
||||
if (ok && (len != length))
|
||||
ok = false;
|
||||
if (ok)
|
||||
memcpy (buffer, cbuffer, length);
|
||||
return ok;
|
||||
}
|
||||
132
cpukit/libdl/rtl-obj-cache.h
Normal file
132
cpukit/libdl/rtl-obj-cache.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File cache buffers a section of the
|
||||
* object file in a buffer to localise read performance.
|
||||
*
|
||||
* This is a simple object file cache that holds a buffer of data from the
|
||||
* offset in the file the read is requested from. Writes are not supported.
|
||||
*
|
||||
* The cache holds the file descriptor, the offset into the file and the amount
|
||||
* of valid data in the cache. If the file is ever modified the user of the
|
||||
* cache to responsible for flushing the cache. For example the cache should be
|
||||
* flused if the file is closed.
|
||||
*
|
||||
* The cache can return by reference or by value. By reference allow access to
|
||||
* the cache buffer. Do not modify the cache's data. By value will copy the
|
||||
* requested data into the user supplied buffer.
|
||||
*
|
||||
* The read by reference call allows you to probe the file's data. For example
|
||||
* a string in an object file can be an unknown length. You can request a read
|
||||
* up to the cache's size by reference. The code will attempt to have this data
|
||||
* in the buffer. If there is not enough data in the file the length will be
|
||||
* modifed to reflect this.
|
||||
*
|
||||
* You can have more than one cache for a single file all looking at different
|
||||
* parts of the file.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_OBJ_CACHE_H_)
|
||||
#define _RTEMS_RTL_OBJ_CACHE_H_
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* The buffer cache.
|
||||
*/
|
||||
typedef struct rtems_rtl_obj_cache_s
|
||||
{
|
||||
int fd; /**< The file descriptor of the data in the cache. */
|
||||
size_t file_size; /**< The size of the file. */
|
||||
off_t offset; /**< The base offset of the buffer. */
|
||||
size_t size; /**< The size of the cache. */
|
||||
size_t level; /**< The amount of data in the cache. A file can be
|
||||
* smaller than the cache file. */
|
||||
uint8_t* buffer; /**< The buffer */
|
||||
} rtems_rtl_obj_cache_t;
|
||||
|
||||
/**
|
||||
* Open a cache allocating a single buffer of the size passed. The default
|
||||
* state of the cache is flushed. No already open checks are made.
|
||||
*
|
||||
* @param cache The cache to initialise.
|
||||
* @param size The size of the cache.
|
||||
* @retval true The cache is open.
|
||||
* @retval false The cache is not open. The RTL error is set.
|
||||
*/
|
||||
bool rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size);
|
||||
|
||||
/**
|
||||
* Close a cache.
|
||||
*
|
||||
* @param cache The cache to close.
|
||||
*/
|
||||
void rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache);
|
||||
|
||||
/**
|
||||
* Flush the cache. Any further read will read the data from the file.
|
||||
*
|
||||
* @param cache The cache to flush.
|
||||
*/
|
||||
void rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache);
|
||||
|
||||
/**
|
||||
* Read data by reference. The length contains the amount of data that should
|
||||
* be available in the cache and referenced by the buffer handle. It must be
|
||||
* less than or equal to the size of the cache. This call will return the
|
||||
* amount of data that is available. It can be less than you ask if the offset
|
||||
* and size is past the end of the file.
|
||||
*
|
||||
* @param cache The cache to reference data from.
|
||||
* @param fd The file descriptor. Must be an open file.
|
||||
* @param offset The offset in the file to reference the data to.
|
||||
* @param buffer The location to reference the data from.
|
||||
* @param length The length of data to reference. Can be modified to a
|
||||
* lesser value and true is still returned so check it.
|
||||
* @retval true The data referenced is in the cache.
|
||||
* @retval false The read failed and the RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
off_t offset,
|
||||
void** buffer,
|
||||
size_t* length);
|
||||
|
||||
/**
|
||||
* Read data by value. The data is copied to the user supplied buffer.
|
||||
*
|
||||
* @param cache The cache to read the data from.
|
||||
* @param fd The file descriptor. Must be an open file.
|
||||
* @param offset The offset in the file to read the data from.
|
||||
* @param buffer The location the data is written into.
|
||||
* @param length The length of data to read.
|
||||
* @retval true The data has been read from the cache.
|
||||
* @retval false The read failed and the RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
off_t offset,
|
||||
void* buffer,
|
||||
size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
179
cpukit/libdl/rtl-obj-comp.c
Normal file
179
cpukit/libdl/rtl-obj-comp.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object Compression manages a compress
|
||||
* stream of data.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/rtl/rtl-allocator.h>
|
||||
#include "rtl-obj-comp.h"
|
||||
#include "rtl-error.h"
|
||||
|
||||
#include "fastlz.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp,
|
||||
size_t size)
|
||||
{
|
||||
comp->cache = NULL;
|
||||
comp->fd = -1;
|
||||
comp->compression = RTEMS_RTL_COMP_LZ77;
|
||||
comp->offset = 0;
|
||||
comp->size = size;
|
||||
comp->level = 0;
|
||||
comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
|
||||
if (!comp->buffer)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
|
||||
return false;
|
||||
}
|
||||
comp->read = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp)
|
||||
{
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
|
||||
comp->cache = NULL;
|
||||
comp->fd = -1;
|
||||
comp->compression = RTEMS_RTL_COMP_LZ77;
|
||||
comp->level = 0;
|
||||
comp->size = 0;
|
||||
comp->offset = 0;
|
||||
comp->read = 0;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t* comp,
|
||||
rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
int compression,
|
||||
off_t offset)
|
||||
{
|
||||
comp->cache = cache;
|
||||
comp->fd = fd;
|
||||
comp->compression = compression;
|
||||
comp->offset = offset;
|
||||
comp->level = 0;
|
||||
comp->read = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
|
||||
void* buffer,
|
||||
size_t length)
|
||||
{
|
||||
uint8_t* bin = buffer;
|
||||
|
||||
if (!comp->cache)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "not open");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (comp->fd != comp->cache->fd)
|
||||
{
|
||||
comp->level = 0;
|
||||
}
|
||||
|
||||
while (length)
|
||||
{
|
||||
size_t buffer_level;
|
||||
|
||||
buffer_level = length > comp->level ? comp->level : length;
|
||||
|
||||
if (buffer_level)
|
||||
{
|
||||
memcpy (bin, comp->buffer, buffer_level);
|
||||
|
||||
if ((comp->level - buffer_level) != 0)
|
||||
{
|
||||
memmove (comp->buffer,
|
||||
comp->buffer + buffer_level,
|
||||
comp->level - buffer_level);
|
||||
}
|
||||
|
||||
bin += buffer_level;
|
||||
length -= buffer_level;
|
||||
comp->level -= buffer_level;
|
||||
comp->read += buffer_level;
|
||||
}
|
||||
|
||||
if (length)
|
||||
{
|
||||
uint8_t* input = NULL;
|
||||
uint16_t block_size;
|
||||
size_t in_length = sizeof (block_size);
|
||||
int decompressed;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
|
||||
(void**) &input, &in_length))
|
||||
return false;
|
||||
|
||||
block_size = (input[0] << 8) | input[1];
|
||||
|
||||
comp->offset += sizeof (block_size);
|
||||
|
||||
in_length = block_size;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
|
||||
(void**) &input, &in_length))
|
||||
return false;
|
||||
|
||||
if (in_length != block_size)
|
||||
{
|
||||
rtems_rtl_set_error (EIO, "compressed read failed: bs=%u in=%u",
|
||||
block_size, in_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (comp->compression)
|
||||
{
|
||||
case RTEMS_RTL_COMP_NONE:
|
||||
memcpy (comp->buffer, input, in_length);
|
||||
decompressed = in_length;
|
||||
break;
|
||||
|
||||
case RTEMS_RTL_COMP_LZ77:
|
||||
decompressed = fastlz_decompress (input, in_length,
|
||||
comp->buffer, comp->size);
|
||||
if (decompressed == 0)
|
||||
{
|
||||
rtems_rtl_set_error (EBADF, "decompression failed");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_rtl_set_error (EINVAL, "bad compression type");
|
||||
return false;
|
||||
}
|
||||
|
||||
comp->offset += block_size;
|
||||
|
||||
comp->level = decompressed;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
122
cpukit/libdl/rtl-obj-comp.h
Normal file
122
cpukit/libdl/rtl-obj-comp.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File Compression manages a
|
||||
* compressed stream of data.
|
||||
*
|
||||
* This is a simple interface to the object file cache to stream data from
|
||||
* from a compressed object file. There is no ability to seek with the
|
||||
* data from a compressed file. The module exists to allocate the output
|
||||
* buffer when the loader starts and use the cache buffers will have been
|
||||
* allocated.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_OBJ_COMP_H_)
|
||||
#define _RTEMS_RTL_OBJ_COMP_H_
|
||||
|
||||
#include <rtems/rtl/rtl-obj-cache.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* The amount of input data read at a time from the file.
|
||||
*/
|
||||
#define RTEMS_RTL_DECOMP_INPUT_SIZE (256)
|
||||
|
||||
/**
|
||||
* The types of supported compression.
|
||||
*/
|
||||
#define RTEMS_RTL_COMP_NONE (0)
|
||||
#define RTEMS_RTL_COMP_LZ77 (1)
|
||||
|
||||
/**
|
||||
* The compressed file.
|
||||
*/
|
||||
typedef struct rtems_rtl_obj_cpmp_s
|
||||
{
|
||||
rtems_rtl_obj_cache_t* cache; /**< The cache provides the input
|
||||
* buffer. */
|
||||
int fd; /**< The file descriptor. */
|
||||
int compression; /**< The type of compression. */
|
||||
off_t offset; /**< The base offset of the buffer. */
|
||||
size_t size; /**< The size of the output buffer. */
|
||||
size_t level; /**< The amount of data in the buffer. */
|
||||
uint8_t* buffer; /**< The buffer */
|
||||
uint32_t read; /**< The amount of data read. */
|
||||
} rtems_rtl_obj_comp_t;
|
||||
|
||||
/**
|
||||
* Return the input level.
|
||||
*/
|
||||
static inline uint32_t rtems_rtl_obj_comp_input (rtems_rtl_obj_comp_t* comp)
|
||||
{
|
||||
return comp->read;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a compressor allocating the output buffer.
|
||||
*
|
||||
* @param comp The compressor to initialise.
|
||||
* @param size The size of the compressor's output buffer.
|
||||
* @retval true The compressor is open.
|
||||
* @retval false The compressor is not open. The RTL error is set.
|
||||
*/
|
||||
bool rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* Close a compressor.
|
||||
*
|
||||
* @param comp The compressor to close.
|
||||
*/
|
||||
void rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp);
|
||||
|
||||
/**
|
||||
* Set the cache and offset in the file the compressed stream starts.
|
||||
*
|
||||
* @param comp The compressor to set the offset in.
|
||||
* @param cache The cache to read the file in by.
|
||||
* @param fd The file descriptor. Must be an open file.
|
||||
* @param compression The type of compression being streamed.
|
||||
* @param offset The offset in the file the compressed stream starts.
|
||||
*/
|
||||
void rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t* comp,
|
||||
rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
int compression,
|
||||
off_t offset);
|
||||
|
||||
/**
|
||||
* Read decompressed data. The length contains the amount of data that should
|
||||
* be available in the cache and referenced by the buffer handle. It must be
|
||||
* less than or equal to the size of the cache. This call will return the
|
||||
* amount of data that is available. It can be less than you ask if the offset
|
||||
* and size is past the end of the file.
|
||||
*
|
||||
* @param comp The compressor to read data from.
|
||||
* @param buffer The buffer the output is written too.
|
||||
* @param length The length of data to read. Can be modified to a
|
||||
* lesser value and true is still returned so check it.
|
||||
* @retval true The data referenced is in the cache.
|
||||
* @retval false The read failed and the RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
|
||||
void* buffer,
|
||||
size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
39
cpukit/libdl/rtl-obj-fwd.h
Normal file
39
cpukit/libdl/rtl-obj-fwd.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker ELF Headers
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_OBJ_FWD_H_)
|
||||
#define _RTEMS_RTL_OBJ_FWD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* The forward declaration of the obj section structure.
|
||||
*/
|
||||
struct rtems_rtl_obj_sect_s;
|
||||
typedef struct rtems_rtl_obj_sect_s rtems_rtl_obj_sect_t;
|
||||
|
||||
/**
|
||||
* The forward declaration of the obj structure.
|
||||
*/
|
||||
struct rtems_rtl_obj_s;
|
||||
typedef struct rtems_rtl_obj_s rtems_rtl_obj_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
1031
cpukit/libdl/rtl-obj.c
Normal file
1031
cpukit/libdl/rtl-obj.c
Normal file
File diff suppressed because it is too large
Load Diff
580
cpukit/libdl/rtl-obj.h
Normal file
580
cpukit/libdl/rtl-obj.h
Normal file
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object Support.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_OBJ_H_)
|
||||
#define _RTEMS_RTL_OBJ_H_
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
#include <rtems/rtl/rtl-sym.h>
|
||||
#include <rtems/rtl/rtl-unresolved.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Loader format flags.
|
||||
*/
|
||||
#define RTEMS_RTL_FMT_ELF (1 << 0)
|
||||
#define RTEMS_RTL_FMT_COMP (1 << 1)
|
||||
#define RTEMS_RTL_FMT_PRIVATE (1 << 16)
|
||||
|
||||
/**
|
||||
* Loader format definition.
|
||||
*/
|
||||
typedef struct rtems_rtl_loader_format_s
|
||||
{
|
||||
/**
|
||||
* The format label. This can be used to determine and manage
|
||||
* specific formats.
|
||||
*/
|
||||
const char* label;
|
||||
|
||||
/**
|
||||
* The format flags.
|
||||
*/
|
||||
uint32_t flags;
|
||||
} rtems_rtl_loader_format_t;
|
||||
|
||||
/**
|
||||
* The type of the format loader check handler. This handler checks the format
|
||||
* and if it is detected as suitable it returns true.
|
||||
*/
|
||||
typedef bool (*rtems_rtl_loader_check) (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* The type of the format loader handler. This handler loads the specific
|
||||
* format.
|
||||
*/
|
||||
typedef bool (*rtems_rtl_loader_load) (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* The type of the format loader handler. This handler loads the specific
|
||||
* format.
|
||||
*/
|
||||
typedef rtems_rtl_loader_format_t* (*rtems_rtl_loader_sig) (void);
|
||||
|
||||
/**
|
||||
* Table for supported loadable formats.
|
||||
*/
|
||||
typedef struct rtems_rtl_loader_table_s
|
||||
{
|
||||
rtems_rtl_loader_check check; /**< The check handler. */
|
||||
rtems_rtl_loader_load load; /**< The loader. */
|
||||
rtems_rtl_loader_sig signature; /**< The loader's signature. */
|
||||
} rtems_rtl_loader_table_t;
|
||||
|
||||
/**
|
||||
* Flags for the various section types.
|
||||
*/
|
||||
#define RTEMS_RTL_OBJ_SECT_TEXT (1 << 0) /**< Section holds program text. */
|
||||
#define RTEMS_RTL_OBJ_SECT_CONST (1 << 1) /**< Section holds program text. */
|
||||
#define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */
|
||||
#define RTEMS_RTL_OBJ_SECT_REL (1 << 4) /**< Section holds relocation records. */
|
||||
#define RTEMS_RTL_OBJ_SECT_RELA (1 << 5) /**< Section holds relocation addend
|
||||
* records. */
|
||||
#define RTEMS_RTL_OBJ_SECT_SYM (1 << 6) /**< Section holds symbols. */
|
||||
#define RTEMS_RTL_OBJ_SECT_STR (1 << 7) /**< Section holds strings. */
|
||||
#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 8) /**< Section allocates runtime memory. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 9) /**< Section is loaded from object file. */
|
||||
#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 10) /**< Section is writable, ie data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 11) /**< Section is executable. */
|
||||
#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 12) /**< Section is preset to zero. */
|
||||
#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 13) /**< Section contains constructors. */
|
||||
#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 14) /**< Section contains destructors. */
|
||||
|
||||
/**
|
||||
* An object file is made up of sections and the can be more than
|
||||
* one of a specific type of sections. All sections and grouped
|
||||
* together in memory.
|
||||
*/
|
||||
struct rtems_rtl_obj_sect_s
|
||||
{
|
||||
rtems_chain_node node; /**< The node's link in the chain. */
|
||||
int section; /**< The section number. */
|
||||
const char* name; /**< The section's name. */
|
||||
size_t size; /**< The size of the section in memory. */
|
||||
off_t offset; /**< Offset into the object file. Relative to
|
||||
* the start of the object file. */
|
||||
uint32_t alignment; /**< Alignment of this section. */
|
||||
int link; /**< Section link field. */
|
||||
int info; /**< Secfion info field. */
|
||||
uint32_t flags; /**< The section's flags. */
|
||||
void* base; /**< The base address of the section in
|
||||
* memory. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Object file descriptor flags.
|
||||
*/
|
||||
#define RTEMS_RTL_OBJ_LOCKED (1 << 0) /**< Lock the object file so it cannot
|
||||
* be unloaded. */
|
||||
#define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved
|
||||
* external symbols. */
|
||||
|
||||
/**
|
||||
* RTL Object. There is one for each object module loaded plus one for the base
|
||||
* kernel image.
|
||||
*/
|
||||
struct rtems_rtl_obj_s
|
||||
{
|
||||
rtems_chain_node link; /**< The node's link in the chain. */
|
||||
uint32_t flags; /**< The status of the object file. */
|
||||
uint32_t users; /**< References to the object file. */
|
||||
const char* fname; /**< The file name for the object. */
|
||||
const char* oname; /**< The object file name. Can be
|
||||
* relative. */
|
||||
const char* aname; /**< The archive name containing the
|
||||
* object. NULL means the object is not
|
||||
* in a lib */
|
||||
off_t ooffset; /**< The object offset in the archive. */
|
||||
size_t fsize; /**< Size of the object file. */
|
||||
rtems_chain_control sections; /**< The sections of interest in the
|
||||
* object file. */
|
||||
rtems_rtl_obj_sym_t* global_table; /**< Global symbol table. */
|
||||
size_t global_syms; /**< Global symbol count. */
|
||||
size_t global_size; /**< Global symbol memory usage. */
|
||||
uint32_t unresolved; /**< The number of unresolved relocations. */
|
||||
void* text_base; /**< The base address of the text section
|
||||
* in memory. */
|
||||
void* const_base; /**< The base address of the const section
|
||||
* in memory. */
|
||||
void* data_base; /**< The base address of the data section
|
||||
* in memory. */
|
||||
void* bss_base; /**< The base address of the bss section
|
||||
* in memory. */
|
||||
size_t bss_size; /**< The size of the bss section. */
|
||||
size_t exec_size; /**< The amount of executable memory
|
||||
* allocated */
|
||||
void* entry; /**< The entry point of the module. */
|
||||
uint32_t checksum; /**< The checksum of the text sections. A
|
||||
* zero means do not checksum. */
|
||||
void* detail; /**< The file details. It contains the elf file
|
||||
* detail, mainly including elf file name,
|
||||
* section offset, section size, which
|
||||
* elf this section belongs to.*/
|
||||
uint32_t* sec_num; /**< The sec nums of each obj. */
|
||||
uint32_t obj_num; /**< The count of elf files in an rtl obj. */
|
||||
struct link_map* linkmap; /**< For GDB. */
|
||||
};
|
||||
|
||||
/**
|
||||
* A section handler is called once for each section that needs to be
|
||||
* processed by this handler.
|
||||
*
|
||||
* @param obj The object file's descriptor the section belongs too.
|
||||
* @param fd The file descriptor of the object file beling loaded.
|
||||
* @param sect The section the handler is being invoked to handle.
|
||||
* @param data A user supplied data variable.
|
||||
* @retval true The operation was successful.
|
||||
* @retval false The operation failed and the RTL has been set.
|
||||
*/
|
||||
typedef bool (*rtems_rtl_obj_sect_handler_t)(rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Get the file name.
|
||||
*
|
||||
* @param obj The object file.
|
||||
* @return const char* The string.
|
||||
*/
|
||||
static inline const char* rtems_rtl_obj_fname (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return obj->fname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the file name valid ?
|
||||
*
|
||||
* @param obj The object file.
|
||||
* @return bool There is a file name
|
||||
*/
|
||||
static inline bool rtems_rtl_obj_fname_valid (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return obj->fname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object name.
|
||||
*
|
||||
* @param obj The object file.
|
||||
* @return const char* The string.
|
||||
*/
|
||||
static inline const char* rtems_rtl_obj_oname (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return obj->oname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the object name valid ?
|
||||
*
|
||||
* @param obj The object file.
|
||||
* @return bool There is an object name
|
||||
*/
|
||||
static inline bool rtems_rtl_obj_oname_valid (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return obj->oname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the archive name.
|
||||
*
|
||||
* @param obj The object file.
|
||||
* @return const char* The string.
|
||||
*/
|
||||
static inline const char* rtems_rtl_obj_aname (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return obj->aname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the archive name valid ?
|
||||
*
|
||||
* @param obj The object file.
|
||||
* @return bool There is an archive name
|
||||
*/
|
||||
static inline bool rtems_rtl_obj_aname_valid (const rtems_rtl_obj_t* obj)
|
||||
{
|
||||
return obj->aname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate an object structure on the heap.
|
||||
*
|
||||
* @retval NULL No memory for the object.
|
||||
*/
|
||||
rtems_rtl_obj_t* rtems_rtl_obj_alloc (void);
|
||||
|
||||
/**
|
||||
* Free the object structure and related resources.
|
||||
*
|
||||
* @param obj The object file's descriptor to free.
|
||||
* @retval false The object has dependences.
|
||||
* @retval true The object has been freed.
|
||||
*/
|
||||
bool rtems_rtl_obj_free (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Does the object file have unresolved external references ? If it does the
|
||||
* results of executing code is unpredictable.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @retval true The object file has unresolved externals.
|
||||
* @retval false The object file has all external references resolved.
|
||||
*/
|
||||
bool rtems_rtl_obj_unresolved (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Parses a filename and returns newly allocated strings with the archive name,
|
||||
* object name, and the object's offset
|
||||
*
|
||||
* @param name The filename of the object
|
||||
* @param aname Address of a string pointer that holds the archive name
|
||||
* @param oname Address of a string pointer that holds the object name
|
||||
* @param ooffset Address of an int that holds the object offset
|
||||
* @retval true The parsing was successful
|
||||
* @retval false The parsing was unsuccessful
|
||||
*/
|
||||
bool rtems_rtl_parse_name (const char* name,
|
||||
const char** aname,
|
||||
const char** oname,
|
||||
off_t* ooffset);
|
||||
|
||||
/**
|
||||
* Load the object file.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param fd The file descriptor.
|
||||
* @param load_syms Load symbols.
|
||||
* @param load_dep Load dependent object files.
|
||||
* @retval true The load was successful.
|
||||
* @retval false The load failed. The RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* Check of the name matches the object file's object name.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param name The name to match.
|
||||
*/
|
||||
bool rtems_rtl_match_name (rtems_rtl_obj_t* obj, const char* name);
|
||||
|
||||
/**
|
||||
* Find an object file on disk that matches the name. The object descriptor is
|
||||
* fill in with the various parts of a name. A name can have archive, object
|
||||
* file and offset components. The search path in the RTL is searched.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param name The name to locate on disk.
|
||||
* @retval true The file has been found.
|
||||
* @retval false The file could not be located. The RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_find_file (rtems_rtl_obj_t* obj, const char* name);
|
||||
|
||||
/**
|
||||
* Add a section to the object descriptor.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param section The section's index number.
|
||||
* @param name The name of the section.
|
||||
* @param size The size of the section in memory.
|
||||
* @param offset The offset of the section in the object file.
|
||||
* @param alignment The alignment of the section in memory.
|
||||
* @param link The section's link field (from the ELF format).
|
||||
* @param info The section's info field (from the ELF format).
|
||||
* @param flags The section's flags.
|
||||
* @retval true The section has been added.
|
||||
* @retval false The section has not been added. See the RTL error.
|
||||
*/
|
||||
bool rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj,
|
||||
int section,
|
||||
const char* name,
|
||||
size_t size,
|
||||
off_t offset,
|
||||
uint32_t alignment,
|
||||
int link,
|
||||
int info,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Erase the object file descriptor's sections.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
*/
|
||||
void rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Find the section given a name.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param name The name of the section to find.
|
||||
* @retval NULL The section was not found.
|
||||
* @return rtems_rtl_obj_sect_t* The named section.
|
||||
*/
|
||||
rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj,
|
||||
const char* name);
|
||||
|
||||
/**
|
||||
* Find a section given a section's index number.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param index The section's index to find.
|
||||
* @retval NULL The section was not found.
|
||||
* @return rtems_rtl_obj_sect_t* The found section.
|
||||
*/
|
||||
rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj,
|
||||
int index);
|
||||
|
||||
/**
|
||||
* The text size of the object file. Only use once all the sections has been
|
||||
* added. It includes alignments between sections that are part of the object's
|
||||
* text area. The consts sections are included in this section.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return size_t The size of the text area of the object file.
|
||||
*/
|
||||
size_t rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The text section alignment of the object file. Only use once all the
|
||||
* sections has been added. The section alignment is the alignment of the first
|
||||
* text type section loaded the text section.
|
||||
*
|
||||
* You can assume the alignment is a positive integral power of 2 if not 0 or
|
||||
* 1. If 0 or 1 then there is no alignment.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
|
||||
*/
|
||||
uint32_t rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The const size of the object file. Only use once all the sections has been
|
||||
* added. It includes alignments between sections that are part of the object's
|
||||
* const area. The consts sections are included in this section.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return size_t The size of the const area of the object file.
|
||||
*/
|
||||
size_t rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The const section alignment of the object file. Only use once all the
|
||||
* sections has been added. The section alignment is the alignment of the first
|
||||
* const type section loaded the const section.
|
||||
*
|
||||
* You can assume the alignment is a positive integral power of 2 if not 0 or
|
||||
* 1. If 0 or 1 then there is no alignment.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
|
||||
*/
|
||||
uint32_t rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The data size of the object file. Only use once all the sections has been
|
||||
* added. It includes alignments between sections that are part of the object's
|
||||
* data area.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return size_t The size of the data area of the object file.
|
||||
*/
|
||||
size_t rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The data section alignment of the object file. Only use once all the
|
||||
* sections has been added. The section alignment is the alignment of the first
|
||||
* data type section loaded the data section.
|
||||
*
|
||||
* You can assume the alignment is a positive integral power of 2 if not 0 or
|
||||
* 1. If 0 or 1 then there is no alignment.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
|
||||
*/
|
||||
uint32_t rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The bss size of the object file. Only use once all the sections has been
|
||||
* added. It includes alignments between sections that are part of the object's
|
||||
* bss area.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return size_t The size of the bss area of the object file.
|
||||
*/
|
||||
size_t rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* The bss section alignment of the object file. Only use once all the
|
||||
* sections has been added. The section alignment is the alignment of the first
|
||||
* bss type section loaded the bss section.
|
||||
*
|
||||
* You can assume the alignment is a positive integral power of 2 if not 0 or
|
||||
* 1. If 0 or 1 then there is no alignment.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment.
|
||||
*/
|
||||
uint32_t rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Relocate the object file. The object file's section are parsed for any
|
||||
* relocation type sections.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param fd The object file's file descriptor.
|
||||
* @param handler The object file's format specific relocation handler.
|
||||
* @param data User specific data handle.
|
||||
* @retval true The object file was relocated.
|
||||
* @retval false The relocation failed. The RTL error is set.
|
||||
*/
|
||||
bool rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_handler_t handler,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Relocate an object file's unresolved reference.
|
||||
*
|
||||
* @param rec The unresolved relocation record.
|
||||
* @param sym The unresolved relocation's referenced symbol.
|
||||
* @retval true The object file record was relocated.
|
||||
* @retval false The relocation failed. The RTL error is set.
|
||||
*/
|
||||
bool rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc_t* reloc,
|
||||
rtems_rtl_obj_sym_t* sym);
|
||||
|
||||
/**
|
||||
* Load the symbols from the object file. Only the exported or public symbols
|
||||
* are read into memory and held in the global symbol table.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param fd The object file's file descriptor.
|
||||
* @param handler The object file's format specific symbol handler.
|
||||
* @param data User specific data handle.
|
||||
* @retval true The object file's symbol where loaded.
|
||||
* @retval false The symbol loading failed. The RTL error is set.
|
||||
*/
|
||||
bool rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_handler_t handler,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Load the sections that have been allocated memory in the target. The bss
|
||||
* type section does not load any data, it is set to 0. The text and data
|
||||
* sections read the detault data from the object file into the target memory.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @param fd The object file's file descriptor.
|
||||
* @param handler The object file's format specific load handler.
|
||||
* @param data User specific data handle.
|
||||
* @retval true The object has been sucessfully loaded.
|
||||
* @retval false The load failed. The RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_handler_t handler,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Invoke the constructors the object has. Constructors are a table of pointers
|
||||
* to "void (*)(void);" where NULL pointers are skipped. The table's size is
|
||||
* taken from the section's size. The objet ELF specific code is responisble
|
||||
* for flagging which sections contain constructors.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
*/
|
||||
void rtems_rtl_obj_run_ctors (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Invoke the destructors the object has. Destructors are a table of pointers
|
||||
* to "void (*)(void);" where NULL pointers are skipped. The table's size is
|
||||
* taken from the section's size. The objet ELF specific code is responisble
|
||||
* for flagging which sections contain destructors.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
*/
|
||||
void rtems_rtl_obj_run_dtors (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Load the object file, reading all sections into memory, symbols and
|
||||
* performing any relocation fixups.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @retval true The object file has been loaded.
|
||||
* @retval false The load failed. The RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_load (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Unload the object file, erasing all symbols and releasing all memory.
|
||||
*
|
||||
* @param obj The object file's descriptor.
|
||||
* @retval true The object file has been unloaded.
|
||||
* @retval false The unload failed. The RTL error has been set.
|
||||
*/
|
||||
bool rtems_rtl_obj_unload (rtems_rtl_obj_t* obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
980
cpukit/libdl/rtl-rap.c
Normal file
980
cpukit/libdl/rtl-rap.c
Normal file
@@ -0,0 +1,980 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012-2013 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor
|
||||
*
|
||||
* This is the RAP format loader support..
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-elf.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-obj-comp.h"
|
||||
#include "rtl-rap.h"
|
||||
#include "rtl-trace.h"
|
||||
#include "rtl-unresolved.h"
|
||||
|
||||
/**
|
||||
* The offsets in the unresolved array.
|
||||
*/
|
||||
#define REL_R_OFFSET (0)
|
||||
#define REL_R_INFO (1)
|
||||
#define REL_R_ADDEND (2)
|
||||
|
||||
/**
|
||||
* The ELF format signature.
|
||||
*/
|
||||
static rtems_rtl_loader_format_t rap_sig =
|
||||
{
|
||||
.label = "RAP",
|
||||
.flags = RTEMS_RTL_FMT_COMP
|
||||
};
|
||||
|
||||
/**
|
||||
* The section definitions found in a RAP file.
|
||||
*/
|
||||
typedef struct rtems_rtl_rap_sectdef_s
|
||||
{
|
||||
const char* name; /**< Name of the section. */
|
||||
const uint32_t flags; /**< Section flags. */
|
||||
} rtems_rtl_rap_sectdef_t;
|
||||
|
||||
/**
|
||||
* The section indexes. These are fixed.
|
||||
*/
|
||||
#define RTEMS_RTL_RAP_TEXT_SEC (0)
|
||||
#define RTEMS_RTL_RAP_CONST_SEC (1)
|
||||
#define RTEMS_RTL_RAP_CTOR_SEC (2)
|
||||
#define RTEMS_RTL_RAP_DTOR_SEC (3)
|
||||
#define RTEMS_RTL_RAP_DATA_SEC (4)
|
||||
#define RTEMS_RTL_RAP_BSS_SEC (5)
|
||||
#define RTEMS_RTL_RAP_SECS (6)
|
||||
|
||||
/**
|
||||
* The sections as loaded from a RAP file.
|
||||
*/
|
||||
static const rtems_rtl_rap_sectdef_t rap_sections[RTEMS_RTL_RAP_SECS] =
|
||||
{
|
||||
{ ".text", RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD },
|
||||
{ ".const", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD },
|
||||
{ ".ctor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CTOR },
|
||||
{ ".dtor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DTOR },
|
||||
{ ".data", RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD },
|
||||
{ ".bss", RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO }
|
||||
};
|
||||
|
||||
/**
|
||||
* The section definitions found in a RAP file.
|
||||
*/
|
||||
typedef struct rtems_rtl_rap_section_s
|
||||
{
|
||||
uint32_t size; /**< The size of the section. */
|
||||
uint32_t alignment; /**< The alignment of the section. */
|
||||
} rtems_rtl_rap_section_t;
|
||||
|
||||
/**
|
||||
* The RAP loader.
|
||||
*/
|
||||
typedef struct rtems_rtl_rap_s
|
||||
{
|
||||
rtems_rtl_obj_cache_t* file; /**< The file cache for the RAP file. */
|
||||
rtems_rtl_obj_comp_t* decomp; /**< The decompression streamer. */
|
||||
uint32_t length; /**< The file length. */
|
||||
uint32_t version; /**< The RAP file version. */
|
||||
uint32_t compression; /**< The type of compression. */
|
||||
uint32_t checksum; /**< The checksum. */
|
||||
uint32_t machinetype; /**< The ELF machine type. */
|
||||
uint32_t datatype; /**< The ELF data type. */
|
||||
uint32_t class; /**< The ELF class. */
|
||||
uint32_t init; /**< The initialisation strtab offset. */
|
||||
uint32_t fini; /**< The finish strtab offset. */
|
||||
rtems_rtl_rap_section_t secs[RTEMS_RTL_RAP_SECS]; /**< The sections. */
|
||||
uint32_t symtab_size; /**< The symbol table size. */
|
||||
char* strtab; /**< The string table. */
|
||||
uint32_t strtab_size; /**< The string table size. */
|
||||
uint32_t relocs_size; /**< The relocation table size. */
|
||||
uint32_t symbols; /**< The number of symbols. */
|
||||
uint32_t strtable_size;/**< The size of section names and obj names. */
|
||||
uint32_t rpathlen; /**< The length of rpath. */
|
||||
char* strtable; /**< The detail string which resides in obj detail. */
|
||||
} rtems_rtl_rap_t;
|
||||
|
||||
/**
|
||||
* Check the machine type.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_rap_machine_check (uint32_t machinetype)
|
||||
{
|
||||
/*
|
||||
* This code is determined by the machine headers.
|
||||
*/
|
||||
switch (machinetype)
|
||||
{
|
||||
ELFDEFNNAME (MACHDEP_ID_CASES)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the data type.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_rap_datatype_check (uint32_t datatype)
|
||||
{
|
||||
/*
|
||||
* This code is determined by the machine headers.
|
||||
*/
|
||||
if (datatype != ELFDEFNNAME (MACHDEP_ENDIANNESS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the class of executable.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_rap_class_check (uint32_t class)
|
||||
{
|
||||
/*
|
||||
* This code is determined by the machine headers.
|
||||
*/
|
||||
switch (class)
|
||||
{
|
||||
case ELFCLASS32:
|
||||
if (ARCH_ELFSIZE == 32)
|
||||
return true;
|
||||
break;
|
||||
case ELFCLASS64:
|
||||
if (ARCH_ELFSIZE == 64)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
rtems_rtl_rap_get_uint32 (const uint8_t* buffer)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
int b;
|
||||
for (b = 0; b < sizeof (uint32_t); ++b)
|
||||
{
|
||||
value <<= 8;
|
||||
value |= buffer[b];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp_t* comp, uint32_t* value)
|
||||
{
|
||||
uint8_t buffer[sizeof (uint32_t)];
|
||||
|
||||
if (!rtems_rtl_obj_comp_read (comp, buffer, sizeof (uint32_t)))
|
||||
return false;
|
||||
|
||||
*value = rtems_rtl_rap_get_uint32 (buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_rap_loader (rtems_rtl_obj_t* obj,
|
||||
int fd,
|
||||
rtems_rtl_obj_sect_t* sect,
|
||||
void* data)
|
||||
{
|
||||
rtems_rtl_rap_t* rap = (rtems_rtl_rap_t*) data;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: input %s=%lu\n",
|
||||
sect->name, rtems_rtl_obj_comp_input (rap->decomp));
|
||||
|
||||
return rtems_rtl_obj_comp_read (rap->decomp, sect->base, sect->size);
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_rap_relocate (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
|
||||
{
|
||||
#define SYMNAME_BUFFER_SIZE (1024)
|
||||
char* symname_buffer = NULL;
|
||||
int section;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: relocation\n");
|
||||
|
||||
symname_buffer = malloc (SYMNAME_BUFFER_SIZE);
|
||||
if (!symname_buffer)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for local symbol name buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
|
||||
{
|
||||
rtems_rtl_obj_sect_t* targetsect;
|
||||
uint32_t header = 0;
|
||||
int relocs;
|
||||
bool is_rela;
|
||||
int r;
|
||||
|
||||
targetsect = rtems_rtl_obj_find_section (obj, rap_sections[section].name);
|
||||
|
||||
if (!targetsect)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "no target section found");
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap->decomp, &header))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit 31 of the header indicates if the relocations for this section
|
||||
* have a valid addend field.
|
||||
*/
|
||||
|
||||
is_rela = (header & (1 << 31)) != 0 ? true : false;
|
||||
relocs = header & ~(1 << 31);
|
||||
|
||||
if (relocs && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: relocation: %s: header: %08lx relocs: %d %s\n",
|
||||
rap_sections[section].name,
|
||||
header, relocs, is_rela ? "rela" : "rel");
|
||||
|
||||
for (r = 0; r < relocs; ++r)
|
||||
{
|
||||
uint32_t info = 0;
|
||||
uint32_t offset = 0;
|
||||
uint32_t addend = 0;
|
||||
Elf_Word type;
|
||||
const char* symname = NULL;
|
||||
uint32_t symname_size;
|
||||
Elf_Word symtype = 0;
|
||||
Elf_Word symvalue = 0;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap->decomp, &info))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap->decomp, &offset))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The types are:
|
||||
*
|
||||
* 0 Section symbol offset in addend.
|
||||
* 1 Symbol appended to the relocation record.
|
||||
* 2 Symbol is in the strtabl.
|
||||
*
|
||||
* If type 2 bits 30:8 is the offset in the strtab. If type 1 the bits
|
||||
* are the size of the string. The lower 8 bits of the info field if the
|
||||
* ELF relocation type field.
|
||||
*/
|
||||
|
||||
if (((info & (1 << 31)) == 0) || is_rela)
|
||||
{
|
||||
if (!rtems_rtl_rap_read_uint32 (rap->decomp, &addend))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf (" %2d: info=%08lx offset=%lu addend=%lu\n",
|
||||
r, info, offset, addend);
|
||||
|
||||
type = info & 0xff;
|
||||
|
||||
if ((info & (1 << 31)) == 0)
|
||||
{
|
||||
rtems_rtl_obj_sect_t* symsect;
|
||||
|
||||
symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8);
|
||||
if (!symsect)
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
symvalue = (Elf_Word) symsect->base + addend;
|
||||
}
|
||||
else if (rtems_rtl_elf_rel_resolve_sym (type))
|
||||
{
|
||||
rtems_rtl_obj_sym_t* symbol;
|
||||
|
||||
symname_size = (info & ~(3 << 30)) >> 8;
|
||||
|
||||
if ((info & (1 << 30)) != 0)
|
||||
{
|
||||
symname = rap->strtab + symname_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (symname_size > (SYMNAME_BUFFER_SIZE - 1))
|
||||
{
|
||||
free (symname_buffer);
|
||||
rtems_rtl_set_error (EINVAL, "reloc symbol too big");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
symname_buffer[symname_size] = '\0';
|
||||
symname = symname_buffer;
|
||||
}
|
||||
|
||||
symbol = rtems_rtl_symbol_obj_find (obj, symname);
|
||||
|
||||
if (!symbol)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
symvalue = (Elf_Word) symbol->value;
|
||||
}
|
||||
|
||||
if (is_rela)
|
||||
{
|
||||
Elf_Rela rela;
|
||||
|
||||
rela.r_offset = offset;
|
||||
rela.r_info = type;
|
||||
|
||||
if ((info & (1 << 31)) == 0)
|
||||
rela.r_addend = 0;
|
||||
else rela.r_addend = addend;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf (" %2d: rela: type:%-2d off:%lu addend:%d" \
|
||||
" symname=%s symtype=%lu symvalue=0x%08lx\n",
|
||||
r, (int) type, offset, (int) addend,
|
||||
symname, symtype, symvalue);
|
||||
|
||||
if (!rtems_rtl_elf_relocate_rela (obj, &rela, targetsect,
|
||||
symname, symtype, symvalue))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf_Rel rel;
|
||||
|
||||
rel.r_offset = offset;
|
||||
rel.r_info = type;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf (" %2d: rel: type:%-2d off:%lu" \
|
||||
" symname=%s symtype=%lu symvalue=0x%08lx\n",
|
||||
r, (int) type, offset,
|
||||
symname, symtype, symvalue);
|
||||
|
||||
if (!rtems_rtl_elf_relocate_rel (obj, &rel, targetsect,
|
||||
symname, symtype, symvalue))
|
||||
{
|
||||
free (symname_buffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (symname_buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The structure of obj->detail is
|
||||
*
|
||||
* |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])|
|
||||
* obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num])
|
||||
*
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
|
||||
{
|
||||
struct link_map* tmp1;
|
||||
section_detail* tmp2;
|
||||
uint32_t obj_detail_size;
|
||||
uint32_t pos = 0;
|
||||
int i,j;
|
||||
|
||||
obj_detail_size = sizeof (struct link_map) * obj->obj_num;
|
||||
|
||||
for (i = 0; i < obj->obj_num; ++i)
|
||||
{
|
||||
obj_detail_size += (obj->sec_num[i] * sizeof (section_detail));
|
||||
}
|
||||
|
||||
obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
|
||||
obj_detail_size + rap->strtable_size, true);
|
||||
|
||||
if (!obj->detail)
|
||||
{
|
||||
rap->strtable_size = 0;
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
|
||||
return false;
|
||||
}
|
||||
|
||||
rap->strtable = obj->detail + obj_detail_size;
|
||||
|
||||
/* Read the obj names and section names */
|
||||
if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtable,
|
||||
rap->strtable_size))
|
||||
{
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->detail);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
{
|
||||
if (rap->rpathlen > 0)
|
||||
printf ("File rpath:\n");
|
||||
}
|
||||
|
||||
while (pos < rap->rpathlen)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
{
|
||||
printf (" %s\n", rap->strtable + pos);
|
||||
}
|
||||
pos = pos + strlen (rap->strtable + pos) + 1;
|
||||
}
|
||||
|
||||
if (rap->rpathlen > 0)
|
||||
pos = rap->rpathlen;
|
||||
|
||||
for (i = 0; i < obj->obj_num; ++i)
|
||||
{
|
||||
tmp1 = (struct link_map*) (obj->detail) + i;
|
||||
tmp1->name = rap->strtable + pos;
|
||||
tmp1->sec_num = obj->sec_num[i];
|
||||
tmp1->rpathlen = rap->rpathlen;
|
||||
tmp1->rpath = (char*) rap->strtable;
|
||||
pos += strlen (tmp1->name) + 1;
|
||||
|
||||
if (!i)
|
||||
{
|
||||
tmp1->l_next = NULL;
|
||||
tmp1->l_prev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
(tmp1 - 1)->l_next = tmp1;
|
||||
tmp1->l_prev = tmp1 - 1;
|
||||
tmp1->l_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
tmp2 =(section_detail*) ((struct link_map*) (obj->detail) + obj->obj_num);
|
||||
|
||||
for (i = 0; i < obj->obj_num; ++i)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
{
|
||||
printf ("File %d: %s\n", i, ((struct link_map*) obj->detail + i)->name);
|
||||
printf ("Section: %d sections\n",(unsigned int) obj->sec_num[i]);
|
||||
}
|
||||
|
||||
((struct link_map*)obj->detail + i)->sec_detail = tmp2;
|
||||
|
||||
for (j = 0; j < obj->sec_num[i]; ++j)
|
||||
{
|
||||
uint32_t name;
|
||||
uint32_t rap_id;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
|
||||
!rtems_rtl_rap_read_uint32 (rap->decomp, &offset) ||
|
||||
!rtems_rtl_rap_read_uint32 (rap->decomp, &size))
|
||||
{
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->detail);
|
||||
return false;
|
||||
}
|
||||
|
||||
rap_id = offset >> 28;
|
||||
offset = offset & 0xfffffff;
|
||||
|
||||
tmp2->name = rap->strtable + name;
|
||||
tmp2->offset = offset;
|
||||
tmp2->rap_id = rap_id;
|
||||
tmp2->size = size;
|
||||
pos += strlen (tmp2->name) + 1;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
{
|
||||
printf ("name:%16s offset:0x%08x rap_id:%d size:0x%x\n",
|
||||
tmp2->name, (unsigned int) tmp2->offset,
|
||||
(unsigned int) tmp2->rap_id, (unsigned int) tmp2->size);
|
||||
}
|
||||
|
||||
tmp2 += 1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_rap_load_symbols (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
|
||||
{
|
||||
rtems_rtl_obj_sym_t* gsym;
|
||||
int sym;
|
||||
|
||||
obj->global_size =
|
||||
rap->symbols * sizeof (rtems_rtl_obj_sym_t) + rap->strtab_size;
|
||||
|
||||
obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
|
||||
obj->global_size, true);
|
||||
if (!obj->global_table)
|
||||
{
|
||||
obj->global_size = 0;
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
|
||||
return false;
|
||||
}
|
||||
|
||||
obj->global_syms = rap->symbols;
|
||||
|
||||
rap->strtab = (((char*) obj->global_table) +
|
||||
(rap->symbols * sizeof (rtems_rtl_obj_sym_t)));
|
||||
|
||||
if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtab, rap->strtab_size))
|
||||
return false;
|
||||
|
||||
for (sym = 0, gsym = obj->global_table; sym < rap->symbols; ++sym)
|
||||
{
|
||||
rtems_rtl_obj_sect_t* symsect;
|
||||
uint32_t data;
|
||||
uint32_t name;
|
||||
uint32_t value;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap->decomp, &data) ||
|
||||
!rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
|
||||
!rtems_rtl_rap_read_uint32 (rap->decomp, &value))
|
||||
{
|
||||
free (obj->global_table);
|
||||
obj->global_table = NULL;
|
||||
obj->global_syms = 0;
|
||||
obj->global_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
|
||||
printf ("rtl: sym:load: data=0x%08lx name=0x%08lx value=0x%08lx\n",
|
||||
data, name, value);
|
||||
|
||||
/*
|
||||
* If there is a globally exported symbol already present and this
|
||||
* symbol is not weak raise an error. If the symbol is weak and present
|
||||
* globally ignore this symbol and use the global one and if it is not
|
||||
* present take this symbol global or weak. We accept the first weak
|
||||
* symbol we find and make it globally exported.
|
||||
*/
|
||||
if (rtems_rtl_symbol_global_find (rap->strtab + name) &&
|
||||
(ELF_ST_BIND (data & 0xffff) != STB_WEAK))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"duplicate global symbol: %s", rap->strtab + name);
|
||||
free (obj->global_table);
|
||||
obj->global_table = NULL;
|
||||
obj->global_syms = 0;
|
||||
obj->global_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16);
|
||||
if (!symsect)
|
||||
{
|
||||
free (obj->global_table);
|
||||
obj->global_table = NULL;
|
||||
obj->global_syms = 0;
|
||||
obj->global_size = 0;
|
||||
rtems_rtl_set_error (EINVAL, "section index not found: %lu", data >> 16);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtems_chain_set_off_chain (&gsym->node);
|
||||
gsym->name = rap->strtab + name;
|
||||
gsym->value = (uint8_t*) (value + symsect->base);
|
||||
gsym->data = data & 0xffff;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
|
||||
printf ("rtl: sym:add:%-2d name:%-20s bind:%-2d type:%-2d val:%8p sect:%d\n",
|
||||
sym, gsym->name,
|
||||
(int) ELF_ST_BIND (data & 0xffff),
|
||||
(int) ELF_ST_TYPE (data & 0xffff),
|
||||
gsym->value, (int) (data >> 16));
|
||||
|
||||
++gsym;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_rap_parse_header (uint8_t* rhdr,
|
||||
size_t* rhdr_len,
|
||||
uint32_t* length,
|
||||
uint32_t* version,
|
||||
uint32_t* compression,
|
||||
uint32_t* checksum)
|
||||
{
|
||||
char* sptr = (char*) rhdr;
|
||||
char* eptr;
|
||||
|
||||
*rhdr_len = 0;
|
||||
|
||||
/*
|
||||
* "RAP," = 4 bytes, total 4
|
||||
*/
|
||||
|
||||
if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
|
||||
return false;
|
||||
|
||||
sptr = sptr + 4;
|
||||
|
||||
/*
|
||||
* "00000000," = 9 bytes, total 13
|
||||
*/
|
||||
|
||||
*length = strtoul (sptr, &eptr, 10);
|
||||
|
||||
if (*eptr != ',')
|
||||
return false;
|
||||
|
||||
sptr = eptr + 1;
|
||||
|
||||
/*
|
||||
* "0000," = 5 bytes, total 18
|
||||
*/
|
||||
|
||||
*version = strtoul (sptr, &eptr, 10);
|
||||
|
||||
if (*eptr != ',')
|
||||
return false;
|
||||
|
||||
sptr = eptr + 1;
|
||||
|
||||
/*
|
||||
* "NONE," and "LZ77," = 5 bytes, total 23
|
||||
*/
|
||||
|
||||
if ((sptr[0] == 'N') &&
|
||||
(sptr[1] == 'O') &&
|
||||
(sptr[2] == 'N') &&
|
||||
(sptr[3] == 'E'))
|
||||
{
|
||||
*compression = RTEMS_RTL_COMP_NONE;
|
||||
eptr = sptr + 4;
|
||||
}
|
||||
else if ((sptr[0] == 'L') &&
|
||||
(sptr[1] == 'Z') &&
|
||||
(sptr[2] == '7') &&
|
||||
(sptr[3] == '7'))
|
||||
{
|
||||
*compression = RTEMS_RTL_COMP_LZ77;
|
||||
eptr = sptr + 4;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (*eptr != ',')
|
||||
return false;
|
||||
|
||||
sptr = eptr + 1;
|
||||
|
||||
/*
|
||||
* "00000000," = 9 bytes, total 32
|
||||
*/
|
||||
*checksum = strtoul (sptr, &eptr, 16);
|
||||
|
||||
/*
|
||||
* "\n" = 1 byte, total 33
|
||||
*/
|
||||
if (*eptr != '\n')
|
||||
return false;
|
||||
|
||||
*rhdr_len = ((uint8_t*) eptr) - rhdr + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd)
|
||||
{
|
||||
rtems_rtl_obj_cache_t* header;
|
||||
uint8_t* rhdr = NULL;
|
||||
size_t rlen = 64;
|
||||
uint32_t length = 0;
|
||||
uint32_t version = 0;
|
||||
uint32_t compression = 0;
|
||||
uint32_t checksum = 0;
|
||||
|
||||
rtems_rtl_obj_caches (&header, NULL, NULL);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset,
|
||||
(void**) &rhdr, &rlen))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_parse_header (rhdr,
|
||||
&rlen,
|
||||
&length,
|
||||
&version,
|
||||
&compression,
|
||||
&checksum))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
|
||||
{
|
||||
rtems_rtl_rap_t rap = { 0 };
|
||||
uint8_t* rhdr = NULL;
|
||||
size_t rlen = 64;
|
||||
int section;
|
||||
|
||||
rtems_rtl_obj_caches (&rap.file, NULL, NULL);
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (rap.file, fd, obj->ooffset,
|
||||
(void**) &rhdr, &rlen))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_parse_header (rhdr,
|
||||
&rlen,
|
||||
&rap.length,
|
||||
&rap.version,
|
||||
&rap.compression,
|
||||
&rap.checksum))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid RAP file format");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the decompressor.
|
||||
*/
|
||||
rtems_rtl_obj_comp (&rap.decomp, rap.file, fd, rap.compression,
|
||||
rlen + obj->ooffset);
|
||||
|
||||
/*
|
||||
* uint32_t: machinetype
|
||||
* uint32_t: datatype
|
||||
* uint32_t: class
|
||||
*/
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: input machine=%lu\n",
|
||||
rtems_rtl_obj_comp_input (rap.decomp));
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.machinetype))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: machinetype=%lu\n", rap.machinetype);
|
||||
|
||||
if (!rtems_rtl_rap_machine_check (rap.machinetype))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid machinetype");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.datatype))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: datatype=%lu\n", rap.datatype);
|
||||
|
||||
if (!rtems_rtl_rap_datatype_check (rap.datatype))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid datatype");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.class))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: class=%lu\n", rap.class);
|
||||
|
||||
if (!rtems_rtl_rap_class_check (rap.class))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid class");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* uint32_t: init
|
||||
* uint32_t: fini
|
||||
* uint32_t: symtab_size
|
||||
* uint32_t: strtab_size
|
||||
* uint32_t: relocs_size
|
||||
*/
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: input header=%lu\n",
|
||||
rtems_rtl_obj_comp_input (rap.decomp));
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.init))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.fini))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.symtab_size))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtab_size))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.relocs_size))
|
||||
return false;
|
||||
|
||||
rap.symbols = rap.symtab_size / (3 * sizeof (uint32_t));
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: load: symtab=%lu (%lu) strtab=%lu relocs=%lu\n",
|
||||
rap.symtab_size, rap.symbols,
|
||||
rap.strtab_size, rap.relocs_size);
|
||||
|
||||
/*
|
||||
* Load the details
|
||||
*/
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &obj->obj_num))
|
||||
return false;
|
||||
|
||||
if (obj->obj_num > 0)
|
||||
{
|
||||
obj->sec_num = (uint32_t*) malloc (sizeof (uint32_t) * obj->obj_num);
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.rpathlen))
|
||||
return false;
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < obj->obj_num; ++i)
|
||||
{
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &(obj->sec_num[i])))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtable_size))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
printf ("rtl: rap: details: obj_num=%lu\n", obj->obj_num);
|
||||
|
||||
if (!rtems_rtl_rap_load_details (&rap, obj))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* uint32_t: text_size
|
||||
* uint32_t: text_alignment
|
||||
* uint32_t: const_size
|
||||
* uint32_t: const_alignment
|
||||
* uint32_t: ctor_size
|
||||
* uint32_t: ctor_alignment
|
||||
* uint32_t: dtor_size
|
||||
* uint32_t: dtor_alignment
|
||||
* uint32_t: data_size
|
||||
* uint32_t: data_alignment
|
||||
* uint32_t: bss_size
|
||||
* uint32_t: bss_alignment
|
||||
*/
|
||||
|
||||
for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
|
||||
{
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].size))
|
||||
return false;
|
||||
|
||||
if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].alignment))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
|
||||
printf ("rtl: rap: %s: size=%lu align=%lu\n",
|
||||
rap_sections[section].name,
|
||||
rap.secs[section].size,
|
||||
rap.secs[section].alignment);
|
||||
|
||||
if (!rtems_rtl_obj_add_section (obj,
|
||||
section,
|
||||
rap_sections[section].name,
|
||||
rap.secs[section].size,
|
||||
0,
|
||||
rap.secs[section].alignment,
|
||||
0, 0,
|
||||
rap_sections[section].flags))
|
||||
return false;
|
||||
}
|
||||
|
||||
/** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */
|
||||
|
||||
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_rap_loader, &rap))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: input symbols=%lu\n",
|
||||
rtems_rtl_obj_comp_input (rap.decomp));
|
||||
|
||||
if (!rtems_rtl_rap_load_symbols (&rap, obj))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: rap: input relocs=%lu\n",
|
||||
rtems_rtl_obj_comp_input (rap.decomp));
|
||||
|
||||
if (!rtems_rtl_rap_relocate (&rap, obj))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
rtems_rtl_loader_format_t*
|
||||
rtems_rtl_rap_file_sig (void)
|
||||
{
|
||||
return &rap_sig;
|
||||
}
|
||||
54
cpukit/libdl/rtl-rap.h
Normal file
54
cpukit/libdl/rtl-rap.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker ELF Headers
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_RAP_H_)
|
||||
#define _RTEMS_RTL_RAP_H_
|
||||
|
||||
#include "rtl-fwd.h"
|
||||
#include "rtl-obj-fwd.h"
|
||||
#include "rtl-sym.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* The RAP format check handler.
|
||||
*
|
||||
* @param obj The object being checked.
|
||||
* @param fd The file descriptor.
|
||||
*/
|
||||
bool rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* The RAP format load handler.
|
||||
*
|
||||
* @param obj The object to load.
|
||||
* @param fd The file descriptor.
|
||||
*/
|
||||
bool rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd);
|
||||
|
||||
/**
|
||||
* The RAP format signature handler.
|
||||
*
|
||||
* @return rtems_rtl_loader_format_t* The format's signature.
|
||||
*/
|
||||
rtems_rtl_loader_format_t* rtems_rtl_rap_file_sig (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
389
cpukit/libdl/rtl-shell.c
Normal file
389
cpukit/libdl/rtl-shell.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor Shell Commands
|
||||
*
|
||||
* A simple RTL command to aid using the RTL.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
//#if SIZEOF_OFF_T == 8
|
||||
#define PRIdoff_t PRIo64
|
||||
//#elif SIZEOF_OFF_T == 4
|
||||
//#define PRIdoff_t PRIo32
|
||||
//#else
|
||||
//#error "unsupported size of off_t"
|
||||
//#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-chain-iterator.h"
|
||||
#include "rtl-shell.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
/**
|
||||
* The type of the shell handlers we have.
|
||||
*/
|
||||
typedef int (*rtems_rtl_shell_handler_t) (rtems_rtl_data_t* rtl, int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Table of handlers we parse to invoke the command.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const char* name; /**< The sub-command's name. */
|
||||
rtems_rtl_shell_handler_t handler; /**< The sub-command's handler. */
|
||||
const char* help; /**< The sub-command's help. */
|
||||
} rtems_rtl_shell_cmd_t;
|
||||
|
||||
/**
|
||||
* Object summary data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int count; /**< The number of object files. */
|
||||
size_t exec; /**< The amount of executable memory allocated. */
|
||||
size_t symbols; /**< The amount of symbol memory allocated. */
|
||||
} rtems_rtl_obj_summary_t;
|
||||
|
||||
/**
|
||||
* Object summary iterator.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_obj_summary_iterator (rtems_chain_node* node, void* data)
|
||||
{
|
||||
rtems_rtl_obj_summary_t* summary = data;
|
||||
rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
|
||||
++summary->count;
|
||||
summary->exec += obj->exec_size;
|
||||
summary->symbols += obj->global_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of symbols.
|
||||
*/
|
||||
static int
|
||||
rtems_rtl_count_symbols (rtems_rtl_data_t* rtl)
|
||||
{
|
||||
int count;
|
||||
int bucket;
|
||||
for (count = 0, bucket = 0; bucket < rtl->globals.nbuckets; ++bucket)
|
||||
count += rtems_rtl_chain_count (&rtl->globals.buckets[bucket]);
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_shell_status (rtems_rtl_data_t* rtl, int argc, char *argv[])
|
||||
{
|
||||
rtems_rtl_obj_summary_t summary;
|
||||
size_t total_memory;
|
||||
|
||||
summary.count = 0;
|
||||
summary.exec = 0;
|
||||
summary.symbols = 0;
|
||||
rtems_rtl_chain_iterate (&rtl->objects,
|
||||
rtems_rtl_obj_summary_iterator,
|
||||
&summary);
|
||||
/*
|
||||
* Currently does not include the name strings in the obj struct.
|
||||
*/
|
||||
total_memory =
|
||||
sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj_t)) +
|
||||
summary.exec + summary.symbols;
|
||||
|
||||
printf ("Runtime Linker Status:\n");
|
||||
printf (" paths: %s\n", rtl->paths);
|
||||
printf (" objects: %d\n", summary.count);
|
||||
printf (" total memory: %zi\n", total_memory);
|
||||
printf (" exec memory: %zi\n", summary.exec);
|
||||
printf (" sym memory: %zi\n", summary.symbols);
|
||||
printf (" symbols: %d\n", rtems_rtl_count_symbols (rtl));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object print data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
rtems_rtl_data_t* rtl; /**< The RTL data. */
|
||||
int indent; /**< Spaces to indent. */
|
||||
bool oname; /**< Print object names. */
|
||||
bool names; /**< Print details of all names. */
|
||||
bool memory_map; /**< Print the memory map. */
|
||||
bool symbols; /**< Print the global symbols. */
|
||||
bool base; /**< Include the base object file. */
|
||||
} rtems_rtl_obj_print_t;
|
||||
|
||||
/**
|
||||
* Return the different between 2 void*.
|
||||
*/
|
||||
static size_t
|
||||
rtems_rtl_delta_voids (void* higher, void* lower)
|
||||
{
|
||||
char* ch = higher;
|
||||
char* cl = lower;
|
||||
return ch - cl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an argument.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_parse_arg (const char* opt, int argc, char *argv[])
|
||||
{
|
||||
int arg;
|
||||
for (arg = 0; arg < argc; ++arg)
|
||||
if (strncmp (opt, argv[arg], 2) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if -b for base is set.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_base_arg (int argc, char *argv[])
|
||||
{
|
||||
return rtems_rtl_parse_arg ("-b", argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if -s for base is set.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_symbols_arg (int argc, char *argv[])
|
||||
{
|
||||
return rtems_rtl_parse_arg ("-s", argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Object printer.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_obj_printer (rtems_rtl_obj_print_t* print, rtems_rtl_obj_t* obj)
|
||||
{
|
||||
char flags_str[33];
|
||||
|
||||
/*
|
||||
* Skip the base module unless asked to show it.
|
||||
*/
|
||||
if (!print->base && (obj == print->rtl->base))
|
||||
return true;
|
||||
|
||||
if (print->oname)
|
||||
{
|
||||
printf ("%-*cobject name : %s\n",
|
||||
print->indent, ' ', rtems_rtl_obj_oname (obj));
|
||||
}
|
||||
if (print->names)
|
||||
{
|
||||
printf ("%-*cfile name : %s\n",
|
||||
print->indent, ' ', rtems_rtl_obj_fname (obj));
|
||||
printf ("%-*carchive name : %s\n",
|
||||
print->indent, ' ', rtems_rtl_obj_aname (obj));
|
||||
strcpy (flags_str, "--");
|
||||
if (obj->flags & RTEMS_RTL_OBJ_LOCKED)
|
||||
flags_str[0] = 'L';
|
||||
if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED)
|
||||
flags_str[1] = 'U';
|
||||
printf ("%-*cflags : %s\n", print->indent, ' ', flags_str);
|
||||
printf ("%-*cfile offset : %" PRIdoff_t "\n", print->indent, ' ', obj->ooffset);
|
||||
printf ("%-*cfile size : %zi\n", print->indent, ' ', obj->fsize);
|
||||
}
|
||||
if (print->memory_map)
|
||||
{
|
||||
printf ("%-*cexec size : %zi\n", print->indent, ' ', obj->exec_size);
|
||||
printf ("%-*ctext base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->text_base, rtems_rtl_delta_voids (obj->const_base, obj->text_base));
|
||||
printf ("%-*cconst base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->const_base, rtems_rtl_delta_voids (obj->data_base, obj->const_base));
|
||||
printf ("%-*cdata base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->data_base, rtems_rtl_delta_voids (obj->bss_base, obj->data_base));
|
||||
printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->bss_base, obj->bss_size);
|
||||
}
|
||||
printf ("%-*cunresolved : %lu\n", print->indent, ' ', obj->unresolved);
|
||||
printf ("%-*csymbols : %zi\n", print->indent, ' ', obj->global_syms);
|
||||
printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size);
|
||||
if (print->symbols)
|
||||
{
|
||||
int max_len = 0;
|
||||
int s;
|
||||
for (s = 0; s < obj->global_syms; ++s)
|
||||
{
|
||||
int len = strlen (obj->global_table[s].name);
|
||||
if (len > max_len)
|
||||
max_len = len;
|
||||
}
|
||||
for (s = 0; s < obj->global_syms; ++s)
|
||||
printf ("%-*c%-*s = %p\n", print->indent + 2, ' ',
|
||||
max_len, obj->global_table[s].name, obj->global_table[s].value);
|
||||
}
|
||||
printf ("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object unresolved symbols printer.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_unresolved_printer (rtems_rtl_unresolv_rec_t* rec,
|
||||
void* data)
|
||||
{
|
||||
rtems_rtl_obj_print_t* print = (rtems_rtl_obj_print_t*) data;
|
||||
if (rec->type == rtems_rtl_unresolved_name)
|
||||
printf ("%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object print iterator.
|
||||
*/
|
||||
static bool
|
||||
rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data)
|
||||
{
|
||||
rtems_rtl_obj_print_t* print = data;
|
||||
rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
|
||||
return rtems_rtl_obj_printer (print, obj);
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_shell_list (rtems_rtl_data_t* rtl, int argc, char *argv[])
|
||||
{
|
||||
rtems_rtl_obj_print_t print;
|
||||
print.rtl = rtl;
|
||||
print.indent = 1;
|
||||
print.oname = true;
|
||||
print.names = true;
|
||||
print.memory_map = true;
|
||||
print.symbols = rtems_rtl_symbols_arg (argc, argv);
|
||||
print.base = false;
|
||||
rtems_rtl_chain_iterate (&rtl->objects,
|
||||
rtems_rtl_obj_print_iterator,
|
||||
&print);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_shell_sym (rtems_rtl_data_t* rtl, int argc, char *argv[])
|
||||
{
|
||||
rtems_rtl_obj_print_t print;
|
||||
print.rtl = rtl;
|
||||
print.indent = 1;
|
||||
print.oname = true;
|
||||
print.names = false;
|
||||
print.memory_map = false;
|
||||
print.symbols = true;
|
||||
print.base = rtems_rtl_base_arg (argc, argv);
|
||||
rtems_rtl_chain_iterate (&rtl->objects,
|
||||
rtems_rtl_obj_print_iterator,
|
||||
&print);
|
||||
printf ("Unresolved:\n");
|
||||
rtems_rtl_unresolved_interate (rtems_rtl_unresolved_printer, &print);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_shell_object (rtems_rtl_data_t* rtl, int argc, char *argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_shell_usage (const char* arg)
|
||||
{
|
||||
printf ("%s: Runtime Linker\n", arg);
|
||||
printf (" %s [-hl] <command>\n", arg);
|
||||
printf (" where:\n");
|
||||
printf (" command: A n RTL command. See -l for a list plus help.\n");
|
||||
printf (" -h: This help\n");
|
||||
printf (" -l: The command list.\n");
|
||||
}
|
||||
|
||||
int
|
||||
rtems_rtl_shell_command (int argc, char* argv[])
|
||||
{
|
||||
const rtems_rtl_shell_cmd_t table[] =
|
||||
{
|
||||
{ "status", rtems_rtl_shell_status,
|
||||
"Display the status of the RTL" },
|
||||
{ "list", rtems_rtl_shell_list,
|
||||
"\tList the object files currently loaded" },
|
||||
{ "sym", rtems_rtl_shell_sym,
|
||||
"\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" },
|
||||
{ "obj", rtems_rtl_shell_object,
|
||||
"\tDisplay the object details, obj <name>" }
|
||||
};
|
||||
|
||||
int arg;
|
||||
int t;
|
||||
|
||||
for (arg = 1; arg < argc; arg++)
|
||||
{
|
||||
if (argv[arg][0] != '-')
|
||||
break;
|
||||
|
||||
switch (argv[arg][1])
|
||||
{
|
||||
case 'h':
|
||||
rtems_rtl_shell_usage (argv[0]);
|
||||
return 0;
|
||||
case 'l':
|
||||
printf ("%s: commands are:\n", argv[0]);
|
||||
for (t = 0;
|
||||
t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t));
|
||||
++t)
|
||||
printf (" %s\t%s\n", table[t].name, table[t].help);
|
||||
return 0;
|
||||
default:
|
||||
printf ("error: unknown option: %s\n", argv[arg]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - arg) < 1)
|
||||
printf ("error: you need to provide a command, try %s -h\n", argv[0]);
|
||||
else
|
||||
{
|
||||
for (t = 0;
|
||||
t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t));
|
||||
++t)
|
||||
{
|
||||
if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0)
|
||||
{
|
||||
rtems_rtl_data_t* rtl = rtems_rtl_data ();
|
||||
int r;
|
||||
if (!rtl)
|
||||
{
|
||||
printf ("error: cannot lock the linker\n");
|
||||
return 1;
|
||||
}
|
||||
r = table[t].handler (rtl, argc - 1, argv + 1);
|
||||
rtems_rtl_unlock ();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
printf ("error: command not found: %s (try -h)\n", argv[arg]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
39
cpukit/libdl/rtl-shell.h
Normal file
39
cpukit/libdl/rtl-shell.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker ELF Shell Support.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_SHELL_H_)
|
||||
#define _RTEMS_RTL_SHELL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* The RTL single shell command contains sub-commands.
|
||||
*
|
||||
* @param argc The argument count.
|
||||
* @param argv Array of argument strings.
|
||||
* @retval 0 No error.
|
||||
* @return int The exit code.
|
||||
*/
|
||||
int rtems_rtl_shell_command (int argc, char* argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
32
cpukit/libdl/rtl-string.c
Normal file
32
cpukit/libdl/rtl-string.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker String managment.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "rtl-allocator.h"
|
||||
#include "rtl-string.h"
|
||||
|
||||
char*
|
||||
rtems_rtl_strdup (const char *s1)
|
||||
{
|
||||
size_t len = strlen (s1);
|
||||
char* s2 = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, len + 1, false);
|
||||
if (s2)
|
||||
{
|
||||
memcpy (s2, s1, len);
|
||||
s2[len] = '\0';
|
||||
}
|
||||
return s2;
|
||||
}
|
||||
37
cpukit/libdl/rtl-string.h
Normal file
37
cpukit/libdl/rtl-string.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker String managment.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_STRING_H_)
|
||||
#define _RTEMS_RTL_STRING_H_
|
||||
|
||||
#include "rtl-indirect-ptr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* A string duplicate that uses the RTL allocator.
|
||||
*
|
||||
* @param s1 The string to duplicate.
|
||||
* @return char* The copy of the string. NULL if there is no memory.
|
||||
*/
|
||||
char* rtems_rtl_strdup (const char *s1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
245
cpukit/libdl/rtl-sym.c
Normal file
245
cpukit/libdl/rtl-sym.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File Symbol Table.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-sym.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
/**
|
||||
* The single symbol forced into the global symbol table that is used to load a
|
||||
* symbol table from an object file.
|
||||
*/
|
||||
static rtems_rtl_obj_sym_t global_sym_add =
|
||||
{
|
||||
.name = "rtems_rtl_base_sym_global_add",
|
||||
.value = (void*) rtems_rtl_base_sym_global_add
|
||||
};
|
||||
|
||||
static uint_fast32_t
|
||||
rtems_rtl_symbol_hash (const char *s)
|
||||
{
|
||||
uint_fast32_t h = 5381;
|
||||
unsigned char c;
|
||||
for (c = *s; c != '\0'; c = *++s)
|
||||
h = h * 33 + c;
|
||||
return h & 0xffffffff;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_symbol_global_insert (rtems_rtl_symbols_t* symbols,
|
||||
rtems_rtl_obj_sym_t* symbol)
|
||||
{
|
||||
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
|
||||
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
|
||||
&symbol->node);
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols,
|
||||
size_t buckets)
|
||||
{
|
||||
symbols->buckets = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
|
||||
buckets * sizeof (rtems_chain_control),
|
||||
true);
|
||||
if (!symbols->buckets)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for global symbol table");
|
||||
return false;
|
||||
}
|
||||
symbols->nbuckets = buckets;
|
||||
for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
|
||||
rtems_chain_initialize_empty (&symbols->buckets[buckets]);
|
||||
rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_symbol_table_close (rtems_rtl_symbols_t* symbols)
|
||||
{
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
|
||||
const unsigned char* esyms,
|
||||
unsigned int size)
|
||||
{
|
||||
rtems_rtl_symbols_t* symbols;
|
||||
rtems_rtl_obj_sym_t* sym;
|
||||
size_t count;
|
||||
size_t s;
|
||||
uint32_t marker;
|
||||
|
||||
count = 0;
|
||||
s = 0;
|
||||
while ((s < size) && (esyms[s] != 0))
|
||||
{
|
||||
int l = strlen ((char*) &esyms[s]);
|
||||
if ((esyms[s + l] != '\0') || ((s + l) > size))
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "invalid exported symbol table");
|
||||
return false;
|
||||
}
|
||||
++count;
|
||||
s += l + sizeof (unsigned long) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check this is the correct end of the table.
|
||||
*/
|
||||
marker = esyms[s + 1];
|
||||
marker <<= 8;
|
||||
marker |= esyms[s + 2];
|
||||
marker <<= 8;
|
||||
marker |= esyms[s + 3];
|
||||
marker <<= 8;
|
||||
marker |= esyms[s + 4];
|
||||
|
||||
if (marker != 0xdeadbeefUL)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "invalid export symbol table");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
|
||||
printf ("rtl: global symbol add: %zi\n", count);
|
||||
|
||||
obj->global_size = count * sizeof (rtems_rtl_obj_sym_t);
|
||||
obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
|
||||
obj->global_size, true);
|
||||
if (!obj->global_table)
|
||||
{
|
||||
obj->global_size = 0;
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for global symbols");
|
||||
return false;
|
||||
}
|
||||
|
||||
symbols = rtems_rtl_global_symbols ();
|
||||
|
||||
s = 0;
|
||||
sym = obj->global_table;
|
||||
|
||||
while ((s < size) && (esyms[s] != 0))
|
||||
{
|
||||
/*
|
||||
* Copy the void* using a union and memcpy to avoid any strict aliasing or
|
||||
* alignment issues. The variable length of the label and the packed nature
|
||||
* of the table means casting is not suitable.
|
||||
*/
|
||||
union {
|
||||
uint8_t data[sizeof (void*)];
|
||||
void* value;
|
||||
} copy_voidp;
|
||||
int b;
|
||||
|
||||
sym->name = (const char*) &esyms[s];
|
||||
s += strlen (sym->name) + 1;
|
||||
for (b = 0; b < sizeof (void*); ++b, ++s)
|
||||
copy_voidp.data[b] = esyms[s];
|
||||
sym->value = copy_voidp.value;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
|
||||
printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value);
|
||||
if (rtems_rtl_symbol_global_find (sym->name) == NULL)
|
||||
rtems_rtl_symbol_global_insert (symbols, sym);
|
||||
++sym;
|
||||
}
|
||||
|
||||
obj->global_syms = count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_sym_t*
|
||||
rtems_rtl_symbol_global_find (const char* name)
|
||||
{
|
||||
rtems_rtl_symbols_t* symbols;
|
||||
uint_fast32_t hash;
|
||||
rtems_chain_control* bucket;
|
||||
rtems_chain_node* node;
|
||||
|
||||
symbols = rtems_rtl_global_symbols ();
|
||||
|
||||
hash = rtems_rtl_symbol_hash (name);
|
||||
bucket = &symbols->buckets[hash % symbols->nbuckets];
|
||||
node = rtems_chain_first (bucket);
|
||||
|
||||
while (!rtems_chain_is_tail (bucket, node))
|
||||
{
|
||||
rtems_rtl_obj_sym_t* sym = (rtems_rtl_obj_sym_t*) node;
|
||||
/*
|
||||
* Use the hash. I could add this to the symbol but it uses more memory.
|
||||
*/
|
||||
if (strcmp (name, sym->name) == 0)
|
||||
return sym;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_sym_t*
|
||||
rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj, const char* name)
|
||||
{
|
||||
rtems_rtl_obj_sym_t* sym;
|
||||
size_t s;
|
||||
/*
|
||||
* Check the object file's symbols first. If not found search the
|
||||
* global symbol table.
|
||||
*/
|
||||
for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
|
||||
if (strcmp (name, sym->name) == 0)
|
||||
return sym;
|
||||
return rtems_rtl_symbol_global_find (name);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_symbol_obj_add (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
rtems_rtl_symbols_t* symbols;
|
||||
rtems_rtl_obj_sym_t* sym;
|
||||
size_t s;
|
||||
|
||||
symbols = rtems_rtl_global_symbols ();
|
||||
|
||||
for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
|
||||
rtems_rtl_symbol_global_insert (symbols, sym);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_symbol_obj_erase (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
if (obj->global_table)
|
||||
{
|
||||
rtems_rtl_obj_sym_t* sym;
|
||||
size_t s;
|
||||
for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
|
||||
if (!rtems_chain_is_node_off_chain (&sym->node))
|
||||
rtems_chain_extract (&sym->node);
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
|
||||
obj->global_table = NULL;
|
||||
obj->global_size = 0;
|
||||
obj->global_syms = 0;
|
||||
}
|
||||
}
|
||||
128
cpukit/libdl/rtl-sym.h
Normal file
128
cpukit/libdl/rtl-sym.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File Symbol Table.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_SYM_H_)
|
||||
#define _RTEMS_RTL_SYM_H_
|
||||
|
||||
#include <rtems.h>
|
||||
#include "rtl-obj-fwd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* An object file symbol.
|
||||
*/
|
||||
typedef struct rtems_rtl_obj_sym_s
|
||||
{
|
||||
rtems_chain_node node; /**< The node's link in the chain. */
|
||||
const char* name; /**< The symbol's name. */
|
||||
void* value; /**< The value of the symbol. */
|
||||
uint32_t data; /**< Format specific data. */
|
||||
} rtems_rtl_obj_sym_t;
|
||||
|
||||
/**
|
||||
* Table of symbols stored in a hash table.
|
||||
*/
|
||||
typedef struct rtems_rtl_symbols_s
|
||||
{
|
||||
rtems_chain_control* buckets;
|
||||
size_t nbuckets;
|
||||
} rtems_rtl_symbols_t;
|
||||
|
||||
/**
|
||||
* Open a symbol table with the specified number of buckets.
|
||||
*
|
||||
* @param symbols The symbol table to open.
|
||||
* @param buckets The number of buckets in the hash table.
|
||||
* @retval true The symbol is open.
|
||||
* @retval false The symbol table could not created. The RTL
|
||||
* error has the error.
|
||||
*/
|
||||
bool rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols,
|
||||
size_t buckets);
|
||||
|
||||
/**
|
||||
* Close the table and erase the hash table.
|
||||
*
|
||||
* @param symbols Close the symbol table.
|
||||
*/
|
||||
void rtems_rtl_symbol_table_close (rtems_rtl_symbols_t* symbols);
|
||||
|
||||
/**
|
||||
* Add a table of exported symbols to the symbol table.
|
||||
*
|
||||
* The export table is a series of symbol records and each record has two
|
||||
* fields:
|
||||
*
|
||||
* 1. label
|
||||
* 2. address
|
||||
*
|
||||
* The 'label' is an ASCIIZ string of variable length. The address is of size
|
||||
* of an unsigned long for the target running the link editor. The byte order
|
||||
* is defined by the machine type because the table should be built by the
|
||||
* target compiler.
|
||||
*
|
||||
* The table is terminated with a nul string followed by the bytes 0xDE, 0xAD,
|
||||
* 0xBE, and 0xEF. This avoids alignments issues.
|
||||
*
|
||||
* @param obj The object table the symbols are for.
|
||||
* @param esyms The exported symbol table.
|
||||
* @param size The size of the table in bytes.
|
||||
*/
|
||||
bool rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
|
||||
const unsigned char* esyms,
|
||||
unsigned int size);
|
||||
|
||||
/**
|
||||
* Find a symbol given the symbol label in the global symbol table.
|
||||
*
|
||||
* @param name The name as an ASCIIZ string.
|
||||
* @retval NULL No symbol found.
|
||||
* @return rtems_rtl_obj_sym_t* Reference to the symbol.
|
||||
*/
|
||||
rtems_rtl_obj_sym_t* rtems_rtl_symbol_global_find (const char* name);
|
||||
|
||||
/**
|
||||
* Find a symbol given the symbol label in the local object file.
|
||||
*
|
||||
* @param obj The object file to search.
|
||||
* @param name The name as an ASCIIZ string.
|
||||
* @retval NULL No symbol found.
|
||||
* @return rtems_rtl_obj_sym_t* Reference to the symbol.
|
||||
*/
|
||||
rtems_rtl_obj_sym_t* rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj,
|
||||
const char* name);
|
||||
|
||||
/**
|
||||
* Add the object file's symbols to the global table.
|
||||
*
|
||||
* @param obj The object file the symbols are to be added.
|
||||
*/
|
||||
void rtems_rtl_symbol_obj_add (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Erase the object file's symbols.
|
||||
*
|
||||
* @param obj The object file the symbols are to be erased from.
|
||||
*/
|
||||
void rtems_rtl_symbol_obj_erase (rtems_rtl_obj_t* obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
134
cpukit/libdl/rtl-trace.c
Normal file
134
cpukit/libdl/rtl-trace.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor Trace
|
||||
*
|
||||
* A configurable tracer for the RTL. See the header file for the enable and
|
||||
* disable.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rtl-trace.h"
|
||||
|
||||
#if RTEMS_RTL_TRACE
|
||||
static rtems_rtl_trace_mask rtems_rtl_trace_flags;
|
||||
|
||||
bool
|
||||
rtems_rtl_trace (rtems_rtl_trace_mask mask)
|
||||
{
|
||||
bool result = false;
|
||||
if (mask & rtems_rtl_trace_flags)
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
rtems_rtl_trace_mask
|
||||
rtems_rtl_trace_set_mask (rtems_rtl_trace_mask mask)
|
||||
{
|
||||
rtems_rtl_trace_mask state = rtems_rtl_trace_flags;
|
||||
rtems_rtl_trace_flags |= mask;
|
||||
return state;
|
||||
}
|
||||
|
||||
rtems_rtl_trace_mask
|
||||
rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask)
|
||||
{
|
||||
rtems_rtl_trace_mask state = rtems_rtl_trace_flags;
|
||||
rtems_rtl_trace_flags &= ~mask;
|
||||
return state;
|
||||
}
|
||||
|
||||
int
|
||||
rtems_rtl_trace_shell_command (int argc, char *argv[])
|
||||
{
|
||||
const char* table[] =
|
||||
{
|
||||
"load",
|
||||
"unload",
|
||||
"section",
|
||||
"symbol",
|
||||
"reloc",
|
||||
"global-sym",
|
||||
"load-sect",
|
||||
"allocator",
|
||||
"unresolved",
|
||||
"detail"
|
||||
};
|
||||
|
||||
rtems_rtl_trace_mask set_value = 0;
|
||||
rtems_rtl_trace_mask clear_value = 0;
|
||||
bool set = true;
|
||||
int arg;
|
||||
int t;
|
||||
|
||||
for (arg = 1; arg < argc; arg++)
|
||||
{
|
||||
if (argv[arg][0] == '-')
|
||||
{
|
||||
switch (argv[arg][1])
|
||||
{
|
||||
case 'h':
|
||||
printf ("usage: %s [-hl] [set/clear] [flags]\n", argv[0]);
|
||||
return 0;
|
||||
case 'l':
|
||||
printf ("%s: valid flags to set or clear are:\n", argv[0]);
|
||||
for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++)
|
||||
printf (" %s\n", table[t]);
|
||||
return 0;
|
||||
default:
|
||||
printf ("error: unknown option\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp (argv[arg], "set") == 0)
|
||||
set = true;
|
||||
if (strcmp (argv[arg], "clear") == 0)
|
||||
set = false;
|
||||
else if (strcmp (argv[arg], "all") == 0)
|
||||
{
|
||||
if (set)
|
||||
set_value = RTEMS_RTL_TRACE_ALL;
|
||||
else
|
||||
clear_value = RTEMS_RTL_TRACE_ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++)
|
||||
{
|
||||
if (strcmp (argv[arg], table[t]) == 0)
|
||||
{
|
||||
if (set)
|
||||
set_value = 1 << t;
|
||||
else
|
||||
clear_value = 1 << t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtems_rtl_trace_flags |= set_value;
|
||||
rtems_rtl_trace_flags &= ~clear_value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
100
cpukit/libdl/rtl-trace.h
Normal file
100
cpukit/libdl/rtl-trace.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker ELF Trace Support.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_TRACE_H_)
|
||||
#define _RTEMS_RTL_TRACE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Set to 1 to build trace support in to the RTL code.
|
||||
*/
|
||||
#define RTEMS_RTL_TRACE 1
|
||||
|
||||
/**
|
||||
* The type of the mask.
|
||||
*/
|
||||
typedef uint32_t rtems_rtl_trace_mask;
|
||||
|
||||
/**
|
||||
* List of tracing bits for the various parts of the link editor.
|
||||
*/
|
||||
#define RTEMS_RTL_TRACE_ALL (0xffffffffUL)
|
||||
#define RTEMS_RTL_TRACE_LOAD (1UL << 0)
|
||||
#define RTEMS_RTL_TRACE_UNLOAD (1UL << 1)
|
||||
#define RTEMS_RTL_TRACE_SECTION (1UL << 2)
|
||||
#define RTEMS_RTL_TRACE_SYMBOL (1UL << 3)
|
||||
#define RTEMS_RTL_TRACE_RELOC (1UL << 4)
|
||||
#define RTEMS_RTL_TRACE_GLOBAL_SYM (1UL << 5)
|
||||
#define RTEMS_RTL_TRACE_LOAD_SECT (1UL << 6)
|
||||
#define RTEMS_RTL_TRACE_ALLOCATOR (1UL << 7)
|
||||
#define RTEMS_RTL_TRACE_UNRESOLVED (1UL << 8)
|
||||
#define RTEMS_RTL_TRACE_DETAIL (1UL << 9)
|
||||
|
||||
/**
|
||||
* Call to check if this part is bring traced. If RTEMS_RTL_TRACE is defined to
|
||||
* 0 the code is dead code elminiated when built with -Os, -O2, or higher.
|
||||
*
|
||||
* @param mask The part of the API to trace.
|
||||
* @retval true Tracing is active for the mask.
|
||||
* @retval false Do not trace.
|
||||
*/
|
||||
#if RTEMS_RTL_TRACE
|
||||
bool rtems_rtl_trace (rtems_rtl_trace_mask mask);
|
||||
#else
|
||||
#define rtems_rtl_trace(_m) (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the mask.
|
||||
*
|
||||
* @param mask The mask bits to set.
|
||||
* @return The previous mask.
|
||||
*/
|
||||
#if RTEMS_RTL_TRACE
|
||||
rtems_rtl_trace_mask rtems_rtl_trace_set_mask (rtems_rtl_trace_mask mask);
|
||||
#else
|
||||
#define rtems_rtl_trace_set_mask(_m)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Clear the mask.
|
||||
*
|
||||
* @param mask The mask bits to clear.
|
||||
* @return The previous mask.
|
||||
*/
|
||||
#if RTEMS_RTL_TRACE
|
||||
rtems_rtl_trace_mask rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask);
|
||||
#else
|
||||
#define rtems_rtl_trace_clear_mask(_m)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Add shell trace shell command.
|
||||
*/
|
||||
#if RTEMS_RTL_TRACE
|
||||
int rtems_rtl_trace_shell_command (int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
471
cpukit/libdl/rtl-unresolved.c
Normal file
471
cpukit/libdl/rtl-unresolved.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File Unresolved Relocations Table.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-unresolved.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
static rtems_rtl_unresolv_block_t*
|
||||
rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved_t* unresolved)
|
||||
{
|
||||
/*
|
||||
* The block header contains a record.
|
||||
*/
|
||||
size_t size =
|
||||
(sizeof(rtems_rtl_unresolv_block_t) +
|
||||
(sizeof(rtems_rtl_unresolv_rec_t) * (unresolved->block_recs - 1)));
|
||||
rtems_rtl_unresolv_block_t* block =
|
||||
rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true);
|
||||
if (block)
|
||||
rtems_chain_append (&unresolved->blocks, &block->link);
|
||||
else
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for unresolved block");
|
||||
return block;
|
||||
}
|
||||
|
||||
static size_t
|
||||
rtems_rtl_unresolved_name_recs (const char* name)
|
||||
{
|
||||
size_t length = strlen (name);
|
||||
return ((length + sizeof(rtems_rtl_unresolv_name_t) - 1) /
|
||||
sizeof(rtems_rtl_unresolv_name_t));
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block_t* block,
|
||||
rtems_rtl_unresolv_rec_t* rec)
|
||||
{
|
||||
return (rec - &block->rec) / sizeof (rtems_rtl_unresolv_rec_t);
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_rec_t*
|
||||
rtems_rtl_unresolved_rec_first (rtems_rtl_unresolv_block_t* block)
|
||||
{
|
||||
return &block->rec;
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_rec_t*
|
||||
rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec_t* rec)
|
||||
{
|
||||
|
||||
switch (rec->type)
|
||||
{
|
||||
case rtems_rtl_unresolved_empty:
|
||||
/*
|
||||
* Empty returns NULL. The end of the records in the block.
|
||||
*/
|
||||
rec = NULL;
|
||||
break;
|
||||
|
||||
case rtems_rtl_unresolved_name:
|
||||
/*
|
||||
* Determine how many records the name occupies. Round up.
|
||||
*/
|
||||
rec += ((rec->rec.name.length + sizeof(rtems_rtl_unresolv_name_t) - 1) /
|
||||
sizeof(rtems_rtl_unresolv_name_t));
|
||||
break;
|
||||
|
||||
case rtems_rtl_unresolved_reloc:
|
||||
++rec;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rec;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_unresolved_rec_is_last (rtems_rtl_unresolv_block_t* block,
|
||||
rtems_rtl_unresolv_rec_t* rec)
|
||||
{
|
||||
int index = (rec - &block->rec) / sizeof (rec);
|
||||
return !rec || (index >= block->recs) || (rec->type == rtems_rtl_unresolved_empty);
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_rec_t*
|
||||
rtems_rtl_unresolved_rec_first_free (rtems_rtl_unresolv_block_t* block)
|
||||
{
|
||||
return &block->rec + block->recs;
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_unresolved_find_name (rtems_rtl_unresolved_t* unresolved,
|
||||
const char* name,
|
||||
bool update_refcount)
|
||||
{
|
||||
size_t length = strlen (name);
|
||||
int index = 1;
|
||||
|
||||
rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
|
||||
rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);
|
||||
|
||||
while (!rtems_rtl_unresolved_rec_is_last (block, rec))
|
||||
{
|
||||
if (rec->type == rtems_rtl_unresolved_name)
|
||||
{
|
||||
if ((rec->rec.name.length == length)
|
||||
&& (strcmp (rec->rec.name.name, name)))
|
||||
{
|
||||
if (update_refcount)
|
||||
++rec->rec.name.refs;
|
||||
return index;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
rec = rtems_rtl_unresolved_rec_next (rec);
|
||||
}
|
||||
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
return 0 - index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Struct to pass relocation data in the interator.
|
||||
*/
|
||||
typedef struct rtems_rtl_unresolved_reloc_data_s
|
||||
{
|
||||
uint16_t name; /**< Name index. */
|
||||
rtems_rtl_unresolv_rec_t* name_rec; /**< Name record. */
|
||||
rtems_rtl_obj_sym_t* sym; /**< The symbol record. */
|
||||
} rtems_rtl_unresolved_reloc_data_t;
|
||||
|
||||
static bool
|
||||
rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec_t* rec,
|
||||
void* data)
|
||||
{
|
||||
if (rec->type == rtems_rtl_unresolved_reloc)
|
||||
{
|
||||
rtems_rtl_unresolved_reloc_data_t* rd;
|
||||
rd = (rtems_rtl_unresolved_reloc_data_t*) data;
|
||||
|
||||
if (rec->rec.reloc.name == rd->name)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: resolve reloc: %s\n", rd->name_rec->rec.name.name);
|
||||
|
||||
rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym);
|
||||
|
||||
/*
|
||||
* Set the object pointer to NULL to indicate the record is not used
|
||||
* anymore. Update the reference count of the name. The sweep after
|
||||
* relocating will remove the reloc records with obj set to NULL and
|
||||
* names with a reference count of 0.
|
||||
*/
|
||||
rec->rec.reloc.obj = NULL;
|
||||
if (rd->name_rec && rd->name_rec->rec.name.refs)
|
||||
--rd->name_rec->rec.name.refs;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec_t* rec,
|
||||
void* data)
|
||||
{
|
||||
if (rec->type == rtems_rtl_unresolved_name)
|
||||
{
|
||||
rtems_rtl_unresolved_reloc_data_t* rd;
|
||||
rd = (rtems_rtl_unresolved_reloc_data_t*) data;
|
||||
|
||||
++rd->name;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: lookup: %d: %s\n", rd->name, rec->rec.name.name);
|
||||
|
||||
rd->sym = rtems_rtl_symbol_global_find (rec->rec.name.name);
|
||||
|
||||
if (rd->sym)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: found: %s\n", rec->rec.name.name);
|
||||
|
||||
rd->name_rec = rec;
|
||||
|
||||
rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_reloc, rd);
|
||||
|
||||
rd->name_rec = NULL;
|
||||
rd->sym = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block_t* block,
|
||||
rtems_rtl_unresolv_rec_t* rec,
|
||||
size_t count,
|
||||
size_t recs_per_block)
|
||||
{
|
||||
size_t index = rtems_rtl_unresolved_rec_index (block, rec);
|
||||
size_t bytes =
|
||||
(block->recs - index - count) * sizeof (rtems_rtl_unresolv_rec_t);
|
||||
if (bytes)
|
||||
memmove (rec, rec + count, bytes);
|
||||
--block->recs;
|
||||
bytes = count * sizeof (rtems_rtl_unresolv_rec_t);
|
||||
memset (&block->rec + block->recs, 0, bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_unresolved_compact (void)
|
||||
{
|
||||
rtems_rtl_unresolved_t* unresolved = rtems_rtl_unresolved ();
|
||||
if (unresolved)
|
||||
{
|
||||
/*
|
||||
* Iterate backwards over the blocks removing any used records. A block is
|
||||
* compacted moving up the block.
|
||||
*/
|
||||
rtems_chain_node* node = rtems_chain_last (&unresolved->blocks);
|
||||
while (!rtems_chain_is_head (&unresolved->blocks, node))
|
||||
{
|
||||
rtems_chain_node* prev = rtems_chain_previous (node);
|
||||
rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
|
||||
rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);
|
||||
|
||||
while (!rtems_rtl_unresolved_rec_is_last (block, rec))
|
||||
{
|
||||
bool next = true;
|
||||
|
||||
if (rec->type == rtems_rtl_unresolved_name)
|
||||
{
|
||||
if (rec->rec.name.refs == 0)
|
||||
{
|
||||
size_t name_recs = rtems_rtl_unresolved_name_recs (rec->rec.name.name);
|
||||
rtems_rtl_unresolved_clean_block (block, rec, name_recs,
|
||||
unresolved->block_recs);
|
||||
next = false;
|
||||
}
|
||||
}
|
||||
else if (rec->type == rtems_rtl_unresolved_reloc)
|
||||
{
|
||||
if (!rec->rec.reloc.obj)
|
||||
{
|
||||
rtems_rtl_unresolved_clean_block (block, rec, 1,
|
||||
unresolved->block_recs);
|
||||
next = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (next)
|
||||
rec = rtems_rtl_unresolved_rec_next (rec);
|
||||
}
|
||||
|
||||
if (block->recs == 0)
|
||||
{
|
||||
rtems_chain_extract (node);
|
||||
free (block);
|
||||
}
|
||||
|
||||
node = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_unresolved_table_open (rtems_rtl_unresolved_t* unresolved,
|
||||
size_t block_recs)
|
||||
{
|
||||
unresolved->marker = 0xdeadf00d;
|
||||
unresolved->block_recs = block_recs;
|
||||
rtems_chain_initialize_empty (&unresolved->blocks);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_unresolved_table_close (rtems_rtl_unresolved_t* unresolved)
|
||||
{
|
||||
rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
rtems_chain_node* next = rtems_chain_next (node);
|
||||
free (node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_unresolved_interate (rtems_rtl_unresolved_iterator_t iterator,
|
||||
void* data)
|
||||
{
|
||||
rtems_rtl_unresolved_t* unresolved = rtems_rtl_unresolved ();
|
||||
if (unresolved)
|
||||
{
|
||||
rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
rtems_rtl_unresolv_block_t* block = (rtems_rtl_unresolv_block_t*) node;
|
||||
rtems_rtl_unresolv_rec_t* rec = rtems_rtl_unresolved_rec_first (block);
|
||||
|
||||
while (!rtems_rtl_unresolved_rec_is_last (block, rec))
|
||||
{
|
||||
if (iterator (rec, data))
|
||||
return true;
|
||||
rec = rtems_rtl_unresolved_rec_next (rec);
|
||||
}
|
||||
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_unresolved_add (rtems_rtl_obj_t* obj,
|
||||
const uint16_t flags,
|
||||
const char* name,
|
||||
const uint16_t sect,
|
||||
const rtems_rtl_word_t* rel)
|
||||
{
|
||||
rtems_rtl_unresolved_t* unresolved;
|
||||
rtems_chain_node* node;
|
||||
rtems_rtl_unresolv_block_t* block;
|
||||
rtems_rtl_unresolv_rec_t* rec;
|
||||
int name_index;
|
||||
size_t name_recs;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
|
||||
rtems_rtl_obj_oname (obj), sect, name);
|
||||
|
||||
unresolved = rtems_rtl_unresolved ();
|
||||
if (!unresolved)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Find the first block with a spare record.
|
||||
*/
|
||||
node = rtems_chain_first (&unresolved->blocks);
|
||||
block = NULL;
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
block = (rtems_rtl_unresolv_block_t*) node;
|
||||
if (block->recs < unresolved->block_recs)
|
||||
break;
|
||||
block = NULL;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
/*
|
||||
* No blocks with any spare records, allocate a new block.
|
||||
*/
|
||||
if (!block)
|
||||
{
|
||||
block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!block)
|
||||
return false;
|
||||
}
|
||||
|
||||
name_index = rtems_rtl_unresolved_find_name (unresolved, name, true);
|
||||
name_recs = rtems_rtl_unresolved_name_recs (name);
|
||||
|
||||
/*
|
||||
* An index less than 0 means the name is present and "0 - index" is the next
|
||||
* index to use.
|
||||
*/
|
||||
if (name_index < 0)
|
||||
{
|
||||
rtems_rtl_unresolv_block_t* name_block = block;
|
||||
|
||||
/*
|
||||
* Is there enough room to fit the name ? It not add a new block.
|
||||
*/
|
||||
if (name_recs > (unresolved->block_recs - block->recs))
|
||||
{
|
||||
name_block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!name_block)
|
||||
return false;
|
||||
}
|
||||
|
||||
rec = rtems_rtl_unresolved_rec_first_free (name_block);
|
||||
rec->type = rtems_rtl_unresolved_name;
|
||||
rec->rec.name.refs = 1;
|
||||
rec->rec.name.length = strlen (name) + 1;
|
||||
memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length + 1);
|
||||
block->recs += name_recs;
|
||||
name_index = 0 - name_index;
|
||||
|
||||
/*
|
||||
* If the name block is the reloc block and it is full allocate a new
|
||||
* block for the relocation record.
|
||||
*/
|
||||
if ((block == name_block) && (block->recs >= unresolved->block_recs))
|
||||
{
|
||||
block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!block)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
rec = rtems_rtl_unresolved_rec_first_free (block);
|
||||
rec->type = rtems_rtl_unresolved_reloc;
|
||||
rec->rec.reloc.obj = obj;
|
||||
rec->rec.reloc.flags = flags;
|
||||
rec->rec.reloc.name = name_index;
|
||||
rec->rec.reloc.sect = sect;
|
||||
rec->rec.reloc.rel[0] = rel[0];
|
||||
rec->rec.reloc.rel[1] = rel[1];
|
||||
rec->rec.reloc.rel[2] = rel[2];
|
||||
|
||||
++block->recs;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_unresolved_resolve (void)
|
||||
{
|
||||
rtems_rtl_unresolved_reloc_data_t rd;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: global resolve\n");
|
||||
rd.name = 0;
|
||||
rd.name_rec = NULL;
|
||||
rd.sym = NULL;
|
||||
rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_iterator, &rd);
|
||||
rtems_rtl_unresolved_compact ();
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_unresolved_remove (rtems_rtl_obj_t* obj,
|
||||
const char* name,
|
||||
const uint16_t sect,
|
||||
const rtems_rtl_word_t* rel)
|
||||
{
|
||||
rtems_rtl_unresolved_t* unresolved;
|
||||
unresolved = rtems_rtl_unresolved ();
|
||||
if (!unresolved)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
212
cpukit/libdl/rtl-unresolved.h
Normal file
212
cpukit/libdl/rtl-unresolved.h
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker Object File Unresolved Relocations Table.
|
||||
*
|
||||
* The unresolved relocation table holds relocations in a loaded object file
|
||||
* which reference unresolved external symbols. The support is needed to allow
|
||||
* dependent object files to load. In the case of dependent object files one
|
||||
* will have unresolved externals until the dependent object file is also
|
||||
* loaded. There is no load order that resolves this.
|
||||
*
|
||||
* The unresolved relocation table is a single table used by all object files
|
||||
* with unresolved symbols. It made of blocks linked together where blocks are
|
||||
* allocated as requiered. The table is always maintained compacted. That is as
|
||||
* relocations are resolved and removed the table is compacted. The only
|
||||
* pointer in the table is the object file poniter. This is used to identify
|
||||
* which object the relocation belongs to. There are no linking or back
|
||||
* pointers in the unresolved relocations table. The table is scanned for each
|
||||
* object file's relocations. This is not fast but the table should be small
|
||||
* and if it happens to grow large you have other more pressing issues to
|
||||
* resolve in your application.
|
||||
*
|
||||
* The table holds two (2) types of records:
|
||||
*
|
||||
* # Symbol name strings.
|
||||
* # Relocations.
|
||||
*
|
||||
* The symbol name a relocation references is held in a specific symbol name
|
||||
* string record in the table the relocation record references. The record
|
||||
* counts the number of references and the string is removed from the table
|
||||
* when the reference count reaches 0. There can be many relocations
|
||||
* referencing the symbol. The strings are referenced by a single 16bit
|
||||
* unsigned integer which is the count of the string in the table.
|
||||
*
|
||||
* The section the relocation is for in the object is the section number. The
|
||||
* relocation data is series of machine word sized fields:
|
||||
*
|
||||
* # Offset in the section.
|
||||
* # Relocation info (format specific)
|
||||
* # Additional format specific data.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_UNRESOLVED_H_)
|
||||
#define _RTEMS_RTL_UNRESOLVED_H_
|
||||
|
||||
#include <rtems.h>
|
||||
#include "rtl-obj-fwd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Hack to work around machine size. This needs to be cleaned up
|
||||
* to better support 64bit targets.
|
||||
*/
|
||||
typedef uint32_t rtems_rtl_word_t;
|
||||
|
||||
/**
|
||||
* The types of records in the blocks.
|
||||
*/
|
||||
typedef enum rtems_rtl_unresolved_rtype_e
|
||||
{
|
||||
rtems_rtl_unresolved_empty = 0, /**< The records is empty. Must always be 0 */
|
||||
rtems_rtl_unresolved_name = 1, /**< The record is a name. */
|
||||
rtems_rtl_unresolved_reloc = 2 /**< The record is a relocation record. */
|
||||
} rtems_rtl_unresolved_rtype_t;
|
||||
|
||||
/**
|
||||
* Unresolved externals symbol names. The names are reference counted and
|
||||
* separate from the relocation records because a number of records could
|
||||
* reference the same symbol name.
|
||||
*/
|
||||
typedef struct rtems_rtl_unresolv_name_s
|
||||
{
|
||||
uint16_t refs; /**< The number of references to this name. */
|
||||
uint16_t length; /**< The length of this name. */
|
||||
const char name[12]; /**< The symbol name. */
|
||||
} rtems_rtl_unresolv_name_t;
|
||||
|
||||
/**
|
||||
* Unresolved externals symbols require the relocation records to be held
|
||||
* and references.
|
||||
*/
|
||||
typedef struct rtems_rtl_unresolv_reloc_s
|
||||
{
|
||||
rtems_rtl_obj_t* obj; /**< The relocation's object file. */
|
||||
uint16_t flags; /**< Format specific flags. */
|
||||
uint16_t name; /**< The symbol's name. */
|
||||
uint16_t sect; /**< The target section. */
|
||||
rtems_rtl_word_t rel[3]; /**< Relocation record. */
|
||||
} rtems_rtl_unresolv_reloc_t;
|
||||
|
||||
/**
|
||||
* Unresolved externals records.
|
||||
*/
|
||||
typedef struct rtems_rtl_unresolv_rec_s
|
||||
{
|
||||
rtems_rtl_unresolved_rtype_t type;
|
||||
union
|
||||
{
|
||||
rtems_rtl_unresolv_name_t name; /**< The name, or */
|
||||
rtems_rtl_unresolv_reloc_t reloc; /**< the relocation record. */
|
||||
} rec;
|
||||
} rtems_rtl_unresolv_rec_t;
|
||||
|
||||
/**
|
||||
* Unresolved blocks.
|
||||
*/
|
||||
typedef struct rtems_rtl_unresolv_block_s
|
||||
{
|
||||
rtems_chain_node link; /**< Blocks are chained. */
|
||||
uint32_t recs; /**< The number of records in the block. */
|
||||
rtems_rtl_unresolv_rec_t rec; /**< The records. More follow. */
|
||||
} rtems_rtl_unresolv_block_t;
|
||||
|
||||
/**
|
||||
* Unresolved table holds the names and relocations.
|
||||
*/
|
||||
typedef struct rtems_rtl_unresolved_s
|
||||
{
|
||||
uint32_t marker;
|
||||
size_t block_recs; /**< The records per blocks allocated. */
|
||||
rtems_chain_control blocks; /**< List of blocks. */
|
||||
} rtems_rtl_unresolved_t;
|
||||
|
||||
/**
|
||||
* The iterator function used to iterate over the unresolved table.
|
||||
*
|
||||
* @param rec The current iterator.
|
||||
* @param data The user data.
|
||||
* @retval true The iterator has finished.
|
||||
* @retval false The iterator has not finished. Keep iterating.
|
||||
*/
|
||||
typedef bool rtems_rtl_unresolved_iterator_t (rtems_rtl_unresolv_rec_t* rec,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Open an unresolved relocation table.
|
||||
*
|
||||
* @param unresolv The unresolved table to open.
|
||||
* @param block_records The number of records per block allocated.
|
||||
* @retval true The table is open.
|
||||
* @retval false The unresolved relocation table could not created. The RTL
|
||||
* error has the error.
|
||||
*/
|
||||
bool rtems_rtl_unresolved_table_open (rtems_rtl_unresolved_t* unresolved,
|
||||
size_t block_records);
|
||||
|
||||
/**
|
||||
* Close the table and erase the blocks.
|
||||
*
|
||||
* @param unreolved Close the unresolved table.
|
||||
*/
|
||||
void rtems_rtl_unresolved_table_close (rtems_rtl_unresolved_t* unresolved);
|
||||
|
||||
/**
|
||||
* Iterate over the table of unresolved entries.
|
||||
*/
|
||||
bool rtems_rtl_unresolved_interate (rtems_rtl_unresolved_iterator_t iterator,
|
||||
void* data);
|
||||
|
||||
/**
|
||||
* Add a relocation to the list of unresolved relocations.
|
||||
*
|
||||
* @param unresolved The unresolved symbol table.
|
||||
* @param obj The object table the symbols are for.
|
||||
* @param flags Format specific flags.
|
||||
* @param name The symbol name the relocation references.
|
||||
* @param sect The target section number the relocation references.
|
||||
* @param rel The format specific relocation data.
|
||||
* @retval true The relocation has been added.
|
||||
* @retval false The relocation could not be added.
|
||||
*/
|
||||
bool rtems_rtl_unresolved_add (rtems_rtl_obj_t* obj,
|
||||
const uint16_t flags,
|
||||
const char* name,
|
||||
const uint16_t sect,
|
||||
const rtems_rtl_word_t* rel);
|
||||
|
||||
/**
|
||||
* Resolve the unresolved symbols.
|
||||
*/
|
||||
void rtems_rtl_unresolved_resolve (void);
|
||||
|
||||
/**
|
||||
* Remove a relocation from the list of unresolved relocations.
|
||||
*
|
||||
* @param unresolved The unresolved symbol table.
|
||||
* @param obj The object table the symbols are for.
|
||||
* @param esyms The exported symbol table.
|
||||
* @param size The size of the table in bytes.
|
||||
*/
|
||||
bool rtems_rtl_unresolved_remove (rtems_rtl_obj_t* obj,
|
||||
const char* name,
|
||||
const uint16_t sect,
|
||||
const rtems_rtl_word_t* rel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
637
cpukit/libdl/rtl.c
Normal file
637
cpukit/libdl/rtl.c
Normal file
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtld
|
||||
*
|
||||
* @brief RTEMS Run-Time Link Editor
|
||||
*
|
||||
* This is the RTL implementation.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include "rtl-allocator.h"
|
||||
#include "rtl-error.h"
|
||||
#include "rtl-string.h"
|
||||
#include "rtl-trace.h"
|
||||
|
||||
/**
|
||||
* Semaphore configuration to create a mutex.
|
||||
*/
|
||||
#define RTEMS_MUTEX_ATTRIBS \
|
||||
(RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
|
||||
RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
|
||||
|
||||
/**
|
||||
* Symbol table cache size. They can be big so the cache needs space to work.
|
||||
*/
|
||||
#define RTEMS_RTL_ELF_SYMBOL_CACHE (2048)
|
||||
|
||||
/**
|
||||
* String table cache size.
|
||||
*/
|
||||
#define RTEMS_RTL_ELF_STRING_CACHE (2048)
|
||||
|
||||
/**
|
||||
* Relocations table cache size.
|
||||
*/
|
||||
#define RTEMS_RTL_ELF_RELOC_CACHE (2048)
|
||||
|
||||
/**
|
||||
* Decompression output buffer.
|
||||
*/
|
||||
#define RTEMS_RTL_COMP_OUTPUT (2048)
|
||||
|
||||
/**
|
||||
* Static RTL data is returned to the user when the linker is locked.
|
||||
*/
|
||||
static rtems_rtl_data_t* rtl;
|
||||
|
||||
/**
|
||||
* Define a default base global symbol loader function that is weak
|
||||
* so a real table can be linked in when the user wants one.
|
||||
*/
|
||||
void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak));
|
||||
void
|
||||
rtems_rtl_base_global_syms_init (void)
|
||||
{
|
||||
/*
|
||||
* Do nothing.
|
||||
*/
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_data_init (void)
|
||||
{
|
||||
/*
|
||||
* Lock the RTL. We only create a lock if a call is made. First we test if a
|
||||
* lock is present. If one is present we lock it. If not the libio lock is
|
||||
* locked and we then test the lock again. If not present we create the lock
|
||||
* then release libio lock.
|
||||
*/
|
||||
if (!rtl)
|
||||
{
|
||||
rtems_libio_lock ();
|
||||
|
||||
if (!rtl)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_id lock;
|
||||
|
||||
/*
|
||||
* Always in the heap.
|
||||
*/
|
||||
rtl = malloc (sizeof (rtems_rtl_data_t));
|
||||
if (!rtl)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return false;
|
||||
}
|
||||
|
||||
*rtl = (rtems_rtl_data_t) { 0 };
|
||||
|
||||
/*
|
||||
* The initialise the allocator data.
|
||||
*/
|
||||
rtems_rtl_alloc_initialise (&rtl->allocator);
|
||||
|
||||
/*
|
||||
* Create the RTL lock.
|
||||
*/
|
||||
sc = rtems_semaphore_create (rtems_build_name ('R', 'T', 'L', 'D'),
|
||||
1, RTEMS_MUTEX_ATTRIBS,
|
||||
RTEMS_NO_PRIORITY, &lock);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
sc = rtems_semaphore_obtain (lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtl->lock = lock;
|
||||
|
||||
/*
|
||||
* Initialise the objects list and create any required services.
|
||||
*/
|
||||
rtems_chain_initialize_empty (&rtl->objects);
|
||||
|
||||
if (!rtems_rtl_symbol_table_open (&rtl->globals,
|
||||
RTEMS_RTL_SYMS_GLOBAL_BUCKETS))
|
||||
{
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_unresolved_table_open (&rtl->unresolved,
|
||||
RTEMS_RTL_UNRESOLVED_BLOCK_SIZE))
|
||||
{
|
||||
rtems_rtl_symbol_table_close (&rtl->globals);
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_obj_cache_open (&rtl->symbols,
|
||||
RTEMS_RTL_ELF_SYMBOL_CACHE))
|
||||
{
|
||||
rtems_rtl_symbol_table_close (&rtl->globals);
|
||||
rtems_rtl_unresolved_table_close (&rtl->unresolved);
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_obj_cache_open (&rtl->strings,
|
||||
RTEMS_RTL_ELF_STRING_CACHE))
|
||||
{
|
||||
rtems_rtl_obj_cache_close (&rtl->symbols);
|
||||
rtems_rtl_unresolved_table_close (&rtl->unresolved);
|
||||
rtems_rtl_symbol_table_close (&rtl->globals);
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_obj_cache_open (&rtl->relocs,
|
||||
RTEMS_RTL_ELF_RELOC_CACHE))
|
||||
{
|
||||
rtems_rtl_obj_cache_close (&rtl->strings);
|
||||
rtems_rtl_obj_cache_close (&rtl->symbols);
|
||||
rtems_rtl_unresolved_table_close (&rtl->unresolved);
|
||||
rtems_rtl_symbol_table_close (&rtl->globals);
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rtems_rtl_obj_comp_open (&rtl->decomp,
|
||||
RTEMS_RTL_COMP_OUTPUT))
|
||||
{
|
||||
rtems_rtl_obj_cache_close (&rtl->relocs);
|
||||
rtems_rtl_obj_cache_close (&rtl->strings);
|
||||
rtems_rtl_obj_cache_close (&rtl->symbols);
|
||||
rtems_rtl_unresolved_table_close (&rtl->unresolved);
|
||||
rtems_rtl_symbol_table_close (&rtl->globals);
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtl->base = rtems_rtl_obj_alloc ();
|
||||
if (!rtl->base)
|
||||
{
|
||||
rtems_rtl_obj_comp_close (&rtl->decomp);
|
||||
rtems_rtl_obj_cache_close (&rtl->relocs);
|
||||
rtems_rtl_obj_cache_close (&rtl->strings);
|
||||
rtems_rtl_obj_cache_close (&rtl->symbols);
|
||||
rtems_rtl_unresolved_table_close (&rtl->unresolved);
|
||||
rtems_rtl_symbol_table_close (&rtl->globals);
|
||||
rtems_semaphore_delete (lock);
|
||||
free (rtl);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to malloc the memory so the free does not complain.
|
||||
*/
|
||||
rtl->base->oname = rtems_rtl_strdup ("rtems-kernel");
|
||||
|
||||
rtems_chain_append (&rtl->objects, &rtl->base->link);
|
||||
}
|
||||
|
||||
rtems_libio_unlock ();
|
||||
|
||||
rtems_rtl_path_append (".");
|
||||
|
||||
rtems_rtl_base_global_syms_init ();
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
rtems_rtl_data_t*
|
||||
rtems_rtl_data (void)
|
||||
{
|
||||
return rtl;
|
||||
}
|
||||
|
||||
rtems_rtl_symbols_t*
|
||||
rtems_rtl_global_symbols (void)
|
||||
{
|
||||
if (!rtl)
|
||||
{
|
||||
rtems_rtl_set_error (ENOENT, "no rtl");
|
||||
return NULL;
|
||||
}
|
||||
return &rtl->globals;
|
||||
}
|
||||
|
||||
rtems_rtl_unresolved_t*
|
||||
rtems_rtl_unresolved (void)
|
||||
{
|
||||
if (!rtl)
|
||||
{
|
||||
rtems_rtl_set_error (ENOENT, "no rtl");
|
||||
return NULL;
|
||||
}
|
||||
return &rtl->unresolved;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols,
|
||||
rtems_rtl_obj_cache_t** strings,
|
||||
rtems_rtl_obj_cache_t** relocs)
|
||||
{
|
||||
if (!rtl)
|
||||
{
|
||||
if (symbols)
|
||||
*symbols = NULL;
|
||||
if (strings)
|
||||
*strings = NULL;
|
||||
if (relocs)
|
||||
*relocs = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (symbols)
|
||||
*symbols = &rtl->symbols;
|
||||
if (strings)
|
||||
*strings = &rtl->strings;
|
||||
if (relocs)
|
||||
*relocs = &rtl->relocs;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_caches_flush ()
|
||||
{
|
||||
if (rtl)
|
||||
{
|
||||
rtems_rtl_obj_cache_flush (&rtl->symbols);
|
||||
rtems_rtl_obj_cache_flush (&rtl->strings);
|
||||
rtems_rtl_obj_cache_flush (&rtl->relocs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_obj_comp (rtems_rtl_obj_comp_t** decomp,
|
||||
rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
int compression,
|
||||
off_t offset)
|
||||
{
|
||||
if (!rtl)
|
||||
{
|
||||
*decomp = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*decomp = &rtl->decomp;
|
||||
rtems_rtl_obj_comp_set (*decomp, cache, fd, compression, offset);
|
||||
}
|
||||
}
|
||||
|
||||
rtems_rtl_data_t*
|
||||
rtems_rtl_lock (void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
|
||||
if (!rtems_rtl_data_init ())
|
||||
return NULL;
|
||||
|
||||
sc = rtems_semaphore_obtain (rtl->lock,
|
||||
RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rtl;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_unlock (void)
|
||||
{
|
||||
/*
|
||||
* Not sure any error should be returned or an assert.
|
||||
*/
|
||||
rtems_status_code sc;
|
||||
sc = rtems_semaphore_release (rtl->lock);
|
||||
if ((sc != RTEMS_SUCCESSFUL) && (errno == 0))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_t*
|
||||
rtems_rtl_check_handle (void* handle)
|
||||
{
|
||||
rtems_rtl_obj_t* obj;
|
||||
rtems_chain_node* node;
|
||||
|
||||
obj = handle;
|
||||
node = rtems_chain_first (&rtl->objects);
|
||||
|
||||
while (!rtems_chain_is_tail (&rtl->objects, node))
|
||||
{
|
||||
rtems_rtl_obj_t* check = (rtems_rtl_obj_t*) node;
|
||||
if (check == obj)
|
||||
return obj;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_t*
|
||||
rtems_rtl_find_obj (const char* name)
|
||||
{
|
||||
rtems_chain_node* node;
|
||||
rtems_rtl_obj_t* found = NULL;
|
||||
const char* aname = NULL;
|
||||
const char* oname = NULL;
|
||||
off_t ooffset;
|
||||
|
||||
if (!rtems_rtl_parse_name (name, &aname, &oname, &ooffset))
|
||||
return NULL;
|
||||
|
||||
node = rtems_chain_first (&rtl->objects);
|
||||
|
||||
while (!rtems_chain_is_tail (&rtl->objects, node))
|
||||
{
|
||||
rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
|
||||
if ((aname == NULL && strcmp (obj->oname, oname) == 0) ||
|
||||
(aname != NULL &&
|
||||
strcmp (obj->aname, aname) == 0 && strcmp (obj->oname, oname) == 0))
|
||||
{
|
||||
found = obj;
|
||||
break;
|
||||
}
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
|
||||
if (!aname)
|
||||
rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) aname);
|
||||
|
||||
if (!oname)
|
||||
rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) oname);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
rtems_rtl_obj_t*
|
||||
rtems_rtl_load_object (const char* name, int mode)
|
||||
{
|
||||
rtems_rtl_obj_t* obj;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
|
||||
printf ("rtl: loading '%s'\n", name);
|
||||
|
||||
/*
|
||||
* See if the object module has already been loaded.
|
||||
*/
|
||||
obj = rtems_rtl_find_obj (name);
|
||||
if (!obj)
|
||||
{
|
||||
/*
|
||||
* Allocate a new object file descriptor and attempt to load it.
|
||||
*/
|
||||
obj = rtems_rtl_obj_alloc ();
|
||||
if (obj == NULL)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "no memory for object descriptor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the file in the file system using the search path. The fname field
|
||||
* will point to a valid file name if found.
|
||||
*/
|
||||
if (!rtems_rtl_obj_find_file (obj, name))
|
||||
{
|
||||
rtems_rtl_obj_free (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtems_chain_append (&rtl->objects, &obj->link);
|
||||
|
||||
if (!rtems_rtl_obj_load (obj))
|
||||
{
|
||||
rtems_rtl_obj_free (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtems_rtl_unresolved_resolve ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase the number of users.
|
||||
*/
|
||||
++obj->users;
|
||||
|
||||
/*
|
||||
* FIXME: Resolving existing unresolved symbols could add more constructors
|
||||
* lists that need to be called. Make a list in the obj load layer and
|
||||
* invoke the list here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Run any local constructors if this is the first user because the object
|
||||
* file will have just been loaded. Unlock the linker to avoid any dead locks
|
||||
* if the object file needs to load files or update the symbol table. We also
|
||||
* do not want a constructor to unload this object file.
|
||||
*/
|
||||
if (obj->users == 1)
|
||||
{
|
||||
obj->flags |= RTEMS_RTL_OBJ_LOCKED;
|
||||
rtems_rtl_unlock ();
|
||||
rtems_rtl_obj_run_ctors (obj);
|
||||
rtems_rtl_lock ();
|
||||
obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_unload_object (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
|
||||
printf ("rtl: unloading '%s'\n", rtems_rtl_obj_fname (obj));
|
||||
|
||||
/*
|
||||
* If the object is locked it cannot be unloaded and the unload fails.
|
||||
*/
|
||||
if ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == RTEMS_RTL_OBJ_LOCKED)
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "cannot unload when locked");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the number of users in a safe manner. If this is the last user unload the
|
||||
* object file from memory.
|
||||
*/
|
||||
if (obj->users > 0)
|
||||
--obj->users;
|
||||
|
||||
if (obj->users == 0)
|
||||
{
|
||||
obj->flags |= RTEMS_RTL_OBJ_LOCKED;
|
||||
rtems_rtl_unlock ();
|
||||
rtems_rtl_obj_run_dtors (obj);
|
||||
rtems_rtl_lock ();
|
||||
obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
|
||||
|
||||
ok = rtems_rtl_obj_unload (obj);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_run_ctors (rtems_rtl_obj_t* obj)
|
||||
{
|
||||
rtems_rtl_obj_run_ctors (obj);
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_path_update (bool prepend, const char* path)
|
||||
{
|
||||
char* paths;
|
||||
const char* src = NULL;
|
||||
char* dst;
|
||||
int len;
|
||||
|
||||
if (!rtems_rtl_lock ())
|
||||
return false;
|
||||
|
||||
len = strlen (path);
|
||||
|
||||
if (rtl->paths)
|
||||
len += strlen (rtl->paths) + 1;
|
||||
else
|
||||
prepend = true;
|
||||
|
||||
paths = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, len + 1, false);
|
||||
|
||||
if (!paths)
|
||||
{
|
||||
rtems_rtl_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
dst = paths;
|
||||
|
||||
if (prepend)
|
||||
{
|
||||
len = strlen (path);
|
||||
src = path;
|
||||
}
|
||||
else if (rtl->paths)
|
||||
{
|
||||
len = strlen (rtl->paths);
|
||||
src = rtl->paths;
|
||||
}
|
||||
|
||||
memcpy (dst, src, len);
|
||||
|
||||
dst += len;
|
||||
|
||||
if (rtl->paths)
|
||||
{
|
||||
*dst = ':';
|
||||
++dst;
|
||||
}
|
||||
|
||||
if (prepend)
|
||||
{
|
||||
src = rtl->paths;
|
||||
if (src)
|
||||
len = strlen (src);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = strlen (path);
|
||||
src = path;
|
||||
}
|
||||
|
||||
if (src)
|
||||
{
|
||||
memcpy (dst, src, len);
|
||||
dst += len;
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
|
||||
rtl->paths = paths;
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_path_append (const char* path)
|
||||
{
|
||||
return rtems_rtl_path_update (false, path);
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_path_prepend (const char* path)
|
||||
{
|
||||
return rtems_rtl_path_update (true, path);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_base_sym_global_add (const unsigned char* esyms,
|
||||
unsigned int size)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
|
||||
printf ("rtl: adding global symbols, table size %u\n", size);
|
||||
|
||||
if (!rtems_rtl_lock ())
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "global add cannot lock rtl");
|
||||
return;
|
||||
}
|
||||
|
||||
rtems_rtl_symbol_global_add (rtl->base, esyms, size);
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
}
|
||||
|
||||
rtems_rtl_obj_t*
|
||||
rtems_rtl_baseimage (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
320
cpukit/libdl/rtl.h
Normal file
320
cpukit/libdl/rtl.h
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup rtems_rtl
|
||||
*
|
||||
* @brief RTEMS Run-Time Linker
|
||||
*
|
||||
* This is the POSIX interface to run-time loading of code into RTEMS.
|
||||
*/
|
||||
|
||||
#if !defined (_RTEMS_RTL_H_)
|
||||
#define _RTEMS_RTL_H_
|
||||
|
||||
#include <link.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
|
||||
#include <rtems/rtl/rtl-allocator.h>
|
||||
#include <rtems/rtl/rtl-fwd.h>
|
||||
#include <rtems/rtl/rtl-obj.h>
|
||||
#include <rtems/rtl/rtl-obj-cache.h>
|
||||
#include <rtems/rtl/rtl-obj-comp.h>
|
||||
#include <rtems/rtl/rtl-unresolved.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup rtems_rtl RTEMS Runtime Link Editor
|
||||
*
|
||||
* The module implements a runtime link editor with the standard dlopen, and
|
||||
* dlclose family of functions.
|
||||
*
|
||||
* The runtime link editor is different to that found on Unix type systems. The
|
||||
* object modules are compiled for PIC or position indepentent code and
|
||||
* therefore require relocating when loaded.
|
||||
*
|
||||
* The object file format is currently ELF and object files can be separate
|
||||
* files or in an archive. Object files in an archive are referenced by
|
||||
* specifing 'archive:object' format. For example 'libfoo.a:bar.o'.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Macros to glue two tokens.
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
#define RTL_XGLUE(a,b) a##b
|
||||
#else
|
||||
#define RTL_XGLUE(a,b) a/**/b
|
||||
#endif
|
||||
|
||||
#define RTL_GLUE(a,b) RTL_XGLUE(a,b)
|
||||
|
||||
/**
|
||||
* The number of buckets in the global symbol table.
|
||||
*/
|
||||
#define RTEMS_RTL_SYMS_GLOBAL_BUCKETS (32)
|
||||
|
||||
/**
|
||||
* The number of relocation record per block in the unresolved table.
|
||||
*/
|
||||
#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64)
|
||||
|
||||
/**
|
||||
* The global debugger interface variable.
|
||||
*/
|
||||
extern struct r_debug _rtld_debug;
|
||||
|
||||
/**
|
||||
* Debugger break function. Call when debugging to have it read the _rtld_debug
|
||||
* variable.
|
||||
*/
|
||||
extern void _rtld_debug_state (void);
|
||||
|
||||
/**
|
||||
* The type of constructor/destructor function.
|
||||
*/
|
||||
typedef void (*rtems_rtl_cdtor_t)(void);
|
||||
|
||||
/**
|
||||
* The global RTL data. This structure is allocated on the heap when the first
|
||||
* call to the RTL is made and never released.
|
||||
*
|
||||
* The global symbol table is a hash table held in this structure and the
|
||||
* actual symbols are part of the object's structure. If this is a problem we
|
||||
* could look at a hash table per object file.
|
||||
*/
|
||||
struct rtems_rtl_data_s
|
||||
{
|
||||
rtems_id lock; /**< The RTL lock id */
|
||||
rtems_rtl_alloc_data_t allocator; /**< The allocator data. */
|
||||
rtems_chain_control objects; /**< List if loaded object files. */
|
||||
const char* paths; /**< Search paths for archives. */
|
||||
rtems_rtl_symbols_t globals; /**< Global symbol table. */
|
||||
rtems_rtl_unresolved_t unresolved; /**< Unresolved symbols. */
|
||||
rtems_rtl_obj_t* base; /**< Base object file. */
|
||||
rtems_rtl_obj_cache_t symbols; /**< Symbols object file cache. */
|
||||
rtems_rtl_obj_cache_t strings; /**< Strings object file cache. */
|
||||
rtems_rtl_obj_cache_t relocs; /**< Relocations object file cache. */
|
||||
rtems_rtl_obj_comp_t decomp; /**< The decompression compressor. */
|
||||
int last_errno; /**< Last error number. */
|
||||
char last_error[64]; /**< Last error string. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the RTL data with out locking. This call assmes the RTL is locked.
|
||||
*
|
||||
* @return rtems_rtl_data_t* The RTL data after being locked.
|
||||
* @retval NULL The RTL data is not initialised.
|
||||
*/
|
||||
rtems_rtl_data_t* rtems_rtl_data (void);
|
||||
|
||||
/**
|
||||
* Get the RTL global symbol table with out locking. This call assmes the RTL
|
||||
* is locked.
|
||||
*
|
||||
* @return rtems_rtl_symbols_t* The RTL global symbols after being locked.
|
||||
* @retval NULL The RTL data is not initialised.
|
||||
*/
|
||||
rtems_rtl_symbols_t* rtems_rtl_global_symbols (void);
|
||||
|
||||
/**
|
||||
* Get the RTL resolved table with out locking. This call assmes the RTL
|
||||
* is locked.
|
||||
*
|
||||
* @return rtems_rtl_unresolv_t* The RTL unresolved symbols and reloc records.
|
||||
* @retval NULL The RTL data is not initialised.
|
||||
*/
|
||||
rtems_rtl_unresolved_t* rtems_rtl_unresolved (void);
|
||||
|
||||
/**
|
||||
* Get the RTL symbols, strings, or relocations object file caches. This call
|
||||
* assmes the RTL is locked.
|
||||
*
|
||||
* @param symbols Pointer to the location to set the cache into. Returns NULL
|
||||
* is rtl is not initialised. If NULL is passed in no value set.
|
||||
* @param strings Pointer to the location to set the cache into. Returns NULL
|
||||
* is rtl is not initialised. If NULL is passed in no value set.
|
||||
* @param relocs Pointer to the location to set the cache into. Returns NULL
|
||||
* is rtl is not initialised. If NULL is passed in no value set.
|
||||
*/
|
||||
void rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols,
|
||||
rtems_rtl_obj_cache_t** strings,
|
||||
rtems_rtl_obj_cache_t** relocs);
|
||||
|
||||
/**
|
||||
* Flush all the object file caches.
|
||||
*/
|
||||
void rtems_rtl_obj_caches_flush (void);
|
||||
|
||||
/**
|
||||
* Get the RTL decompressor setting the cache and the offset in the file the
|
||||
* compressed stream starts. This call assmes the RTL is locked.
|
||||
*
|
||||
* @param decomp Pointer to the location to set the compressor into. Returns
|
||||
* NULL is rtl is not initialised.
|
||||
* @param cache The cache to read the file with. Saves needing an extrs buffer.
|
||||
* @param offset The offset in the file the compressed stream starts.
|
||||
*/
|
||||
void rtems_rtl_obj_comp (rtems_rtl_obj_comp_t** decomp,
|
||||
rtems_rtl_obj_cache_t* cache,
|
||||
int fd,
|
||||
int compression,
|
||||
off_t offset);
|
||||
|
||||
/**
|
||||
* Lock the Run-time Linker.
|
||||
*
|
||||
* @return rtems_rtl_data_t* The RTL data after being locked.
|
||||
* @retval NULL The RTL data could not be initialised or locked. Typically this
|
||||
* means the lock could not be created.
|
||||
*/
|
||||
rtems_rtl_data_t* rtems_rtl_lock (void);
|
||||
|
||||
/**
|
||||
* Unlock the Run-time Linker.
|
||||
*
|
||||
* @return True The RTL is unlocked.
|
||||
* @return False The RTL could not be unlocked. Not much you can do.
|
||||
*/
|
||||
bool rtems_rtl_unlock (void);
|
||||
|
||||
/**
|
||||
* Check a pointer is a valid object file descriptor returning the pointer as
|
||||
* that type.
|
||||
*
|
||||
* Assumes the RTL has been locked.
|
||||
*
|
||||
* @param handle Pointer to the object file to be validated.
|
||||
* @return rtl_obj* The object file descriptor. NULL is returned if invalid.
|
||||
*/
|
||||
rtems_rtl_obj_t* rtems_rtl_check_handle (void* handle);
|
||||
|
||||
/**
|
||||
* Find the object given a file name.
|
||||
*
|
||||
* @param name The name of the object file.
|
||||
* @retval NULL No object file with that name found.
|
||||
* @return rtems_rtl_obj_t* The object file descriptor.
|
||||
*/
|
||||
rtems_rtl_obj_t* rtems_rtl_find_obj (const char* name);
|
||||
|
||||
/**
|
||||
* Load an object file into memory relocating it. It will not be resolved
|
||||
* against other symbols in other object files or the base image.
|
||||
*
|
||||
* The name can be a file name for an object file or it can be encoded to
|
||||
* reference an archive of object modules (static library). This encoding is
|
||||
* specific to RTEMS and allows dependences to specify an archive without the
|
||||
* searching overhead normally incurred by linkers locating object files in an
|
||||
* archive. The file name format rules are:
|
||||
*
|
||||
* 1. Absolute file references a specific object file in the architecture
|
||||
* specific location on the file system.
|
||||
*
|
||||
* 2. Relative file references an object format file in the search path.
|
||||
*
|
||||
* 3. Absolute archive and file reference to a specific location in the file
|
||||
* system. The archive and file are encoded as 'archive:file [@offset]'
|
||||
* where 'archive' is a valid file at the absolute path in the file system,
|
||||
* and 'file' is a contained in the archive, and optionally an offset to
|
||||
* the 'file' in the 'archive'. If no offset is provided the archive is
|
||||
* searched.
|
||||
*
|
||||
* 4. Relative archive and file in the search path. The encoding is the same
|
||||
* as described in item 3 of this list.
|
||||
*
|
||||
* Assumes the RTL has been locked.
|
||||
*
|
||||
* @param name The name of the object file.
|
||||
* @param mode The mode of the load as defined by the dlopen call.
|
||||
* @return rtl_obj* The object file descriptor. NULL is returned if the load fails.
|
||||
*/
|
||||
rtems_rtl_obj_t* rtems_rtl_load_object (const char* name, int mode);
|
||||
|
||||
/**
|
||||
* Unload an object file. This only happens when the user count is 0.
|
||||
*
|
||||
* Assumes the RTL has been locked.
|
||||
*
|
||||
* @param obj The object file descriptor.
|
||||
* @retval true The object file has been unloaded.
|
||||
* @retval false The object file could not be unloaded.
|
||||
*/
|
||||
bool rtems_rtl_unload_object (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Run any constructor functions the object file may contain. This call
|
||||
* assumes the linker is unlocked.
|
||||
*
|
||||
* @param obj The object file.
|
||||
*/
|
||||
void rtems_rtl_run_ctors (rtems_rtl_obj_t* obj);
|
||||
|
||||
/**
|
||||
* Get the last error message clearing it. This operation locks the run time
|
||||
* linker and therefore keeps the RTL thread safe but this call is not thread
|
||||
* safe is multiple threads are loading object files at the same time. This
|
||||
* call is provided to map to the dlopen family of calls.
|
||||
*
|
||||
* @param message Pointer to a buffer to copy the message into.
|
||||
* @param max_message The maximum message that can be copied.
|
||||
* @return int The last error number.
|
||||
*/
|
||||
int rtems_rtl_get_error (char* message, size_t max_message);
|
||||
|
||||
/**
|
||||
* Append the path to the search path.
|
||||
*
|
||||
* @path The path to append.
|
||||
* @retval false The path could not be appended.
|
||||
* @retval true The path was appended.
|
||||
*/
|
||||
bool rtems_rtl_path_append (const char* path);
|
||||
|
||||
/**
|
||||
* Prepend the path to the search path.
|
||||
*
|
||||
* @path The path to prepend.
|
||||
* @retval false The path could not be prepended.
|
||||
* @retval true The path was prepended.
|
||||
*/
|
||||
|
||||
bool rtems_rtl_path_prepend (const char* path);
|
||||
|
||||
/**
|
||||
* Add an exported symbol table to the global symbol table. This call is
|
||||
* normally used by an object file when loaded that contains a global symbol
|
||||
* table.
|
||||
*
|
||||
* @param esyms The exported symbol table.
|
||||
* @param count The size of the exported symbol table.
|
||||
*/
|
||||
void rtems_rtl_base_sym_global_add (const unsigned char* esyms,
|
||||
unsigned int count);
|
||||
|
||||
/**
|
||||
* Return the object file descriptor for the base image. The object file
|
||||
* descriptor returned is created when the run time linker is initialised.
|
||||
*
|
||||
* Assumes the RTL has been locked.
|
||||
*
|
||||
* @return rtl_obj* The object file descriptor for the base image. NULL is
|
||||
* returned if the load fails.
|
||||
*/
|
||||
rtems_rtl_obj_t* rtems_rtl_baseimage (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -46,7 +46,6 @@ $(PROJECT_INCLUDE)/utf8proc/utf8proc.h: libmisc/utf8proc/utf8proc.h $(PROJECT_IN
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/utf8proc/utf8proc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/utf8proc/utf8proc.h
|
||||
|
||||
if NEWLIB
|
||||
$(PROJECT_INCLUDE)/sys/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/sys
|
||||
@: > $(PROJECT_INCLUDE)/sys/$(dirstamp)
|
||||
@@ -130,6 +129,92 @@ $(PROJECT_INCLUDE)/rtems/bsdnet/_types.h: libnetworking/rtems/bsdnet/_types.h $(
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bsdnet/_types.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bsdnet/_types.h
|
||||
endif
|
||||
if LIBDL
|
||||
$(PROJECT_INCLUDE)/dlfcn.h: libdl/dlfcn.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dlfcn.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/dlfcn.h
|
||||
|
||||
$(PROJECT_INCLUDE)/link.h: libdl/include/link.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/link.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/link.h
|
||||
|
||||
$(PROJECT_INCLUDE)/link_elf.h: libdl/include/link_elf.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/link_elf.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/link_elf.h
|
||||
|
||||
$(PROJECT_INCLUDE)/sys/cdefs_elf.h: libdl/include/sys/cdefs_elf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/cdefs_elf.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/cdefs_elf.h
|
||||
|
||||
$(PROJECT_INCLUDE)/sys/exec_elf.h: libdl/include/sys/exec_elf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/exec_elf.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/exec_elf.h
|
||||
|
||||
$(PROJECT_INCLUDE)/machine/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/machine
|
||||
@: > $(PROJECT_INCLUDE)/machine/$(dirstamp)
|
||||
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/machine/$(dirstamp)
|
||||
|
||||
$(PROJECT_INCLUDE)/machine/elf_machdep.h: libdl/include/arch/@RTEMS_CPU@/machine/elf_machdep.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/elf_machdep.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/elf_machdep.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/rtems/rtl
|
||||
@: > $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/dlfcn-shell.h: libdl/dlfcn-shell.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/dlfcn-shell.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/dlfcn-shell.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl.h: libdl/rtl.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-allocator.h: libdl/rtl-allocator.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-allocator.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-allocator.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-fwd.h: libdl/rtl-obj-fwd.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-fwd.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-fwd.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-fwd.h: libdl/rtl-fwd.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-fwd.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-fwd.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj.h: libdl/rtl-obj.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-cache.h: libdl/rtl-obj-cache.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-cache.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-cache.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-comp.h: libdl/rtl-obj-comp.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-comp.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-obj-comp.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-unresolved.h: libdl/rtl-unresolved.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-unresolved.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-unresolved.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-indirect-ptr.h: libdl/rtl-indirect-ptr.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-indirect-ptr.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-indirect-ptr.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h: libdl/rtl-sym.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rap.h: libdl/rap.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rap.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rap.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/rtl/rap-shell.h: libdl/rap-shell.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rap-shell.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rap-shell.h
|
||||
endif
|
||||
$(PROJECT_INCLUDE)/rtems/bspIo.h: include/rtems/bspIo.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bspIo.h
|
||||
|
||||
@@ -77,6 +77,10 @@ if NEWLIB
|
||||
TMP_LIBS += ../libmd/libmd.a
|
||||
endif
|
||||
|
||||
if LIBDL
|
||||
TMP_LIBS += ../libdl/libdl.a
|
||||
endif
|
||||
|
||||
librtemscpu.a: $(TMP_LIBS)
|
||||
rm -f $@
|
||||
$(MKDIR_P) $(ARCH)
|
||||
|
||||
@@ -14,7 +14,7 @@ _SUBDIRS += block14
|
||||
_SUBDIRS += block13
|
||||
_SUBDIRS += rbheap01
|
||||
_SUBDIRS += flashdisk01
|
||||
_SUBDIRS += capture01
|
||||
_SUBDIRS += capture01
|
||||
|
||||
_SUBDIRS += bspcmdline01 cpuuse devfs01 devfs02 devfs03 devfs04 \
|
||||
deviceio01 devnullfatal01 dumpbuf01 gxx01 top\
|
||||
@@ -36,5 +36,9 @@ _SUBDIRS += ftp01
|
||||
_SUBDIRS += syscall01
|
||||
endif
|
||||
|
||||
if DLTESTS
|
||||
_SUBDIRS += dl01
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/../automake/test-subdirs.am
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
|
||||
@@ -41,6 +41,29 @@ AM_CONDITIONAL([HAS_COMPLEX],[test "$ac_cv_header_complex_h" = yes])
|
||||
AM_CONDITIONAL(NETTESTS,test "$rtems_cv_RTEMS_NETWORKING" = "yes")
|
||||
AM_CONDITIONAL(HAS_POSIX,test x"${rtems_cv_RTEMS_POSIX_API}" = x"yes")
|
||||
|
||||
# Must match the list in cpukit.
|
||||
AC_MSG_CHECKING([whether CPU supports libdl])
|
||||
case $RTEMS_CPU in
|
||||
arm | bfin | h8300 | i386 | lm32 | m32r | m68k | mips | \
|
||||
moxie | nios2 | powerpc | sparc | v850)
|
||||
HAVE_LIBDL=yes ;;
|
||||
*)
|
||||
HAVE_LIBDL=no ;;
|
||||
esac
|
||||
AM_CONDITIONAL(DLTESTS,[test x"$HAVE_LIBDL" = x"yes"])
|
||||
AC_MSG_RESULT([$HAVE_LIBDL])
|
||||
|
||||
AS_IF([test x"$HAVE_LIBDL" = x"yes"],[
|
||||
AC_CHECK_PROG(RTEMS_LD_CHECK,rtems-ld,yes)
|
||||
if test x"$RTEMS_LD_CHECK" != x"yes" ; then
|
||||
AC_MSG_ERROR([Please install rtems-tools.])
|
||||
fi
|
||||
AC_CHECK_PROG(RTEMS_SYMS_CHECK,rtems-syms,yes)
|
||||
if test x"$RTEMS_SYMS_CHECK" != x"yes" ; then
|
||||
AC_MSG_ERROR([Please install rtems-tools.])
|
||||
fi
|
||||
])
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile
|
||||
newlib01/Makefile
|
||||
@@ -78,6 +101,7 @@ devfs03/Makefile
|
||||
devfs04/Makefile
|
||||
deviceio01/Makefile
|
||||
devnullfatal01/Makefile
|
||||
dl01/Makefile
|
||||
dumpbuf01/Makefile
|
||||
ftp01/Makefile
|
||||
gxx01/Makefile
|
||||
|
||||
43
testsuites/libtests/dl01/Makefile.am
Normal file
43
testsuites/libtests/dl01/Makefile.am
Normal file
@@ -0,0 +1,43 @@
|
||||
rtems_tests_PROGRAMS = dl01
|
||||
dl01_SOURCES = init.c dl-load.c dl-tar.c dl-tar.h
|
||||
|
||||
BUILT_SOURCES = dl-tar.c dl-tar.h
|
||||
|
||||
dist_rtems_tests_DATA = dl01.scn dl01.doc
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../automake/compile.am
|
||||
include $(top_srcdir)/../automake/leaf.am
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
|
||||
|
||||
LINK_OBJS = $(dl01_OBJECTS)
|
||||
LINK_LIBS = $(dl01_LDLIBS)
|
||||
|
||||
dl-o1.o: dl-o1.c
|
||||
|
||||
dl.tar: dl-o1.o
|
||||
@rm -f $@
|
||||
$(PAX) -w -f $@ $<
|
||||
|
||||
dl-tar.c: dl.tar
|
||||
$(BIN2C) -C $< $@
|
||||
CLEANFILES += dl-tar.c
|
||||
|
||||
dl-tar.h: dl.tar
|
||||
$(BIN2C) -H $< $@
|
||||
CLEANFILES += dl-tar.h
|
||||
|
||||
dl01.pre$(EXEEXT): $(dl01_OBJECTS) $(dl01_DEPENDENCIES)
|
||||
@rm -f dl01.pre$(EXEEXT)
|
||||
$(make-exe)
|
||||
|
||||
dl-sym.o: dl01.pre$(EXEEXT)
|
||||
rtems-syms -e -c "$(CFLAGS)" -o $@ $<
|
||||
|
||||
dl01$(EXEEXT): $(dl01_OBJECTS) $(dl01_DEPENDENCIES) dl-sym.o
|
||||
@rm -f dl01$(EXEEXT)
|
||||
$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) \
|
||||
-o $(basename $@)$(EXEEXT) $(LINK_OBJS) dl-sym.o $(LINK_LIBS)
|
||||
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
77
testsuites/libtests/dl01/dl-load.c
Normal file
77
testsuites/libtests/dl01/dl-load.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "dl-load.h"
|
||||
|
||||
typedef int (*call_t)(int argc, char* argv[]);
|
||||
|
||||
|
||||
static const char* call_1[] = { "Line 1", "Line 2" };
|
||||
static const char* call_2[] = { "Call 2, line 1",
|
||||
"Call 2, line 2",
|
||||
"Call 2, line 3" };
|
||||
|
||||
int dl_load_test(void)
|
||||
{
|
||||
void* handle;
|
||||
call_t call;
|
||||
int call_ret;
|
||||
int unresolved;
|
||||
char* message = "loaded";
|
||||
|
||||
printf("load: /dl-o1.o\n");
|
||||
|
||||
handle = dlopen ("/dl-o1.o", RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!handle)
|
||||
{
|
||||
printf("dlopen failed: %s\n", dlerror());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0)
|
||||
message = "dlinfo error checking unresolved status";
|
||||
else if (unresolved)
|
||||
message = "has unresolved externals";
|
||||
|
||||
printf ("handle: %p %s\n", handle, message);
|
||||
|
||||
call = dlsym (handle, "rtems_main");
|
||||
if (call == NULL)
|
||||
{
|
||||
printf("dlsym failed: symbol not found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
call_ret = call (2, call_1);
|
||||
if (call_ret != 2)
|
||||
{
|
||||
printf("dlsym call failed: ret value bad\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
call_ret = call (3, call_2);
|
||||
if (call_ret != 3)
|
||||
{
|
||||
printf("dlsym call failed: ret value bad\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dlclose (handle) < 0)
|
||||
{
|
||||
printf("dlclose failed: %s\n", dlerror());
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf ("handle: %p closed\n", handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
14
testsuites/libtests/dl01/dl-load.h
Normal file
14
testsuites/libtests/dl01/dl-load.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if !defined(_DL_LOAD_H_)
|
||||
#define _DL_LOAD_H_
|
||||
|
||||
int dl_load_test(void);
|
||||
|
||||
#endif
|
||||
31
testsuites/libtests/dl01/dl-o1.c
Normal file
31
testsuites/libtests/dl01/dl-o1.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Hello World as a loadable module.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Yes a decl in the source. This is a modules main and I could not find which
|
||||
* header main is defined in.
|
||||
*/
|
||||
int rtems_main (int argc, char* argv[]);
|
||||
|
||||
int rtems_main (int argc, char* argv[])
|
||||
{
|
||||
int arg;
|
||||
printf("Loaded module: argc:%d [%s]\n", argc, __FILE__);
|
||||
for (arg = 0; arg < argc; ++arg)
|
||||
printf(" %d: %s\n", arg, argv[arg]);
|
||||
return argc;
|
||||
}
|
||||
0
testsuites/libtests/dl01/dl01.doc
Normal file
0
testsuites/libtests/dl01/dl01.doc
Normal file
0
testsuites/libtests/dl01/dl01.scn
Normal file
0
testsuites/libtests/dl01/dl01.scn
Normal file
84
testsuites/libtests/dl01/init.c
Normal file
84
testsuites/libtests/dl01/init.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tmacros.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/rtl/rtl.h>
|
||||
#include <rtems/untar.h>
|
||||
|
||||
#include "dl-load.h"
|
||||
|
||||
const char rtems_test_name[] = "libdl (RTL) Loader 1";
|
||||
|
||||
/* forward declarations to avoid warnings */
|
||||
static rtems_task Init(rtems_task_argument argument);
|
||||
|
||||
#include "dl-tar.h"
|
||||
|
||||
#define TARFILE_START dl_tar
|
||||
#define TARFILE_SIZE dl_tar_size
|
||||
|
||||
static int test(void)
|
||||
{
|
||||
int ret;
|
||||
ret = dl_load_test();
|
||||
if (ret)
|
||||
rtems_test_exit(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Init(rtems_task_argument arg)
|
||||
{
|
||||
int te;
|
||||
|
||||
TEST_BEGIN();
|
||||
|
||||
te = Untar_FromMemory((void *)TARFILE_START, (size_t)TARFILE_SIZE);
|
||||
if (te != 0)
|
||||
{
|
||||
printf("untar failed: %d\n", te);
|
||||
rtems_test_exit(1);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
test();
|
||||
|
||||
TEST_END();
|
||||
|
||||
rtems_test_exit(0);
|
||||
}
|
||||
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
|
||||
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
|
||||
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 1
|
||||
|
||||
#define CONFIGURE_MINIMUM_TASK_STACK_SIZE (8U * 1024U)
|
||||
|
||||
#define CONFIGURE_EXTRA_TASK_STACKS (8 * 1024)
|
||||
|
||||
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
#define CONFIGURE_INIT
|
||||
|
||||
#include <rtems/confdefs.h>
|
||||
|
||||
Reference in New Issue
Block a user