[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/build/uClibc/ldso/COPYRIGHT b/ap/build/uClibc/ldso/COPYRIGHT
new file mode 100644
index 0000000..fb34248
--- /dev/null
+++ b/ap/build/uClibc/ldso/COPYRIGHT
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, David Engel,
+ * Hongjiu Lu and Mitch D'Souza
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/* Notice of general intent:
+ *
+ * The linux operating system generally contains large amounts of code
+ * that fall under the GNU General Public License, or GPL for short.
+ * This file contains source code that by it's very nature would always
+ * be linked with an application program, and because of this a GPL
+ * type of copyright on this file would place restrictions upon the
+ * distribution of binary-only commercial software. Since the goal of
+ * the Linux project as a whole is not to discourage the development and
+ * distribution of commercial software for Linux, this file has been
+ * placed under a more relaxed BSD-style of copyright.
+ *
+ * It is the general understanding of the above contributors that a
+ * program executable linked to a library containing code that falls
+ * under the GPL or GLPL style of license is not subject to the terms of
+ * the GPL or GLPL license if the program executable(s) that are supplied
+ * are linked to a shared library form of the GPL or GLPL library, and as
+ * long as the form of the shared library is such that it is possible for
+ * the end user to modify and rebuild the library and use it in
+ * conjunction with the program executable.
+ */
diff --git a/ap/build/uClibc/ldso/Makefile b/ap/build/uClibc/ldso/Makefile
new file mode 100644
index 0000000..c8dc9b4
--- /dev/null
+++ b/ap/build/uClibc/ldso/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../
+top_builddir=../
+include $(top_builddir)Rules.mak
+all: libs
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/ldso/Makefile.in b/ap/build/uClibc/ldso/Makefile.in
new file mode 100644
index 0000000..7bbef23
--- /dev/null
+++ b/ap/build/uClibc/ldso/Makefile.in
@@ -0,0 +1,9 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+include $(top_srcdir)ldso/ldso/Makefile.in
+include $(top_srcdir)ldso/libdl/Makefile.in
diff --git a/ap/build/uClibc/ldso/README b/ap/build/uClibc/ldso/README
new file mode 100644
index 0000000..dc37ea6
--- /dev/null
+++ b/ap/build/uClibc/ldso/README
@@ -0,0 +1,841 @@
+
+Apr 20, 2001 -- Manuel Novoa III
+
+Inital port for uClibc from debian ld.so_1.9.11-9.tar.gz.
+
+Removed a.out support.
+
+****************** original ld.so.lsm file **************************
+Begin3
+Title: Linux shared, dynamic linker and utilities.
+Version: 1.9.11
+Entered-date: 01MAY99
+Description: This package contains ld.so, ld-linux.so, ldconfig,
+ ldd and libdl.
+Keywords: dynamic linker, shared library, ld.so, ld-linux.so,
+ ldconfig, ldd, libdl
+Author: david@ods.com (David Engel)
+Maintained-by: david@ods.com (David Engel)
+Primary-site: tsx-11.mit.edu /pub/linux/packages/GCC
+ ld.so-1.9.11.tar.gz
+Alternate-site: sunsite.unc.edu /pub/Linux/GCC
+ ld.so-1.9.11.tar.gz
+Platform: Linux 2.0.0 or later.
+Copying-policy: Copyrighted but freely distributable.
+End
+*********************************************************************
+ Original README starts here
+*********************************************************************
+
+This package contains my ELF dynamic linkers (ld-linux.so.1), dynamic
+linker library (libdl.so.1) and utilities (ldconfig and ldd) for Linux.
+
+You need Linux kernel 2.0.0 or later with ELF support compiled in
+(i.e. not loaded as a module) to use this package.
+
+The dynamic linker is used to bootstrap programs and load shared
+libraries at startup. The dynamic linker library is used to
+dynamically load shared libraries after a program is running.
+Ldconfig is used to automatically update the symbolic links to shared
+libraries and build the cache file used by the dynamic linker. Ldd is
+used to list the shared libraries used by a program.
+
+Please see the included manual pages for further details.
+
+To install, simply run "sh instldso.sh" as root. Ready-to-go versions
+of all end-products are provided so nothing should need to be compiled
+or linked. If you are still using libc5 as your primary development
+library, you should use the "--devfiles" option when running
+instldso.sh to install the file needed to compile with libdl.
+
+ELF versions of gcc, binutils and libc are now required to compile
+everything, including the old, unsupported, a.out dynamic linker.
+Finally, an optimization level of O2 or higher must be used to compile
+ld-linux.so and libdl.so due the use of inline functions.
+
+Notable contributors to this package include Eric Youngdale, Peter
+MacDonald, Hongjiu Lu, Linus Torvalds, Lars Wirzenius, Mitch D'Souza,
+Rik Faith, Andreas Schwab and Adam Richter (not necessarily in that
+order).
+
+###################### IMPORTANT NOTICES #############################
+
+A.OUT SUPPORT:
+
+As of ld.so-1.9.0, the old, a.out dynamic loader is no longer
+officially supported. The code is still included and built, but I
+make no promises that it will work. I will accept patches for it,
+but they will not be tested by me.
+
+GLIBC (AKA LIBC6) SUPPORT:
+
+As of ld.so-1.9.0, the main focus of this package is to ease the
+transition to libc6. No significant, new features are expected to be
+added. If you need new features, switch to libc6.
+
+Except for libpthread.so, the sonames of the core libraries provided
+with libc6 have been chosen so they do not conflict with those
+provided by libc5 and ld.so. However, the current plan is not use
+new, nonconflicting sonames for other libraries such as ncurses and
+X11. This presents two problems. First, libraries using the same
+soname for both libc5 and libc6 can not be placed in the same
+directory. Second, the dynamic linkers need to make sure not to load
+a library for the wrong version of libc.
+
+The first problem is easy. Just move the old, libc5-based libraries
+to new directories (e.g. /lib/libc5-compat, /usr/lib/libc5-compat,
+etc.) and add those directories to /etc/ld.so.conf. Then install the
+new, libc6-based versions in the standard places.
+
+The second problem is more difficult. Ideally, the dynamic linkers
+would be changed to perform a complete dependency analysis on every
+library to be loaded to make sure the wrong versions aren't used.
+This approach doesn't seem worth the added complexity, especially
+since we now have symbol versioning for ELF libraries. Instead a
+simpler approach will be used, at least initially.
+
+Ldconfig has been modified to perform a (currently simple) dependency
+analysis on libraries and to store an indication in /etc/ld.so.cache
+of whether a library is for libc5, libc6 or an unknown libc. The
+dynamic linkers then only need to make a simple check at run-time to
+make sure they don't load the wrong version of a library.
+
+The dynamic linker for libc5 provided in this package, has already
+been modified to use the new information in /etc/ld.so.cache. For
+glibc versions 2.0.1 and earlier, the dynamic linker for libc6 needs
+the patch contained in glibc.patch. You should apply the patch and
+rebuild glibc before using the new ldconfig.
+
+As stated above, the dependency analysis currently done by ldconfig is
+rather simple. Basically, it looks for the sonames used by the
+various versions of libc, libm and libdl. For any approach using a
+dependency analysis such as this to work, it is very important that
+shared libraries be built with complete dependency information. This
+can be done by using the appropriate -l options when running 'gcc
+-shared'. For example, when building libfoo.so which depends on libc
+and libbar, you should add -lbar and -lc gcc command line.
+
+######################################################################
+
+Changes in version 1.9.11:
+
+ Fixed a bug in ld-linux.so where a reference to an
+ undefined symbol could cause a segfault.
+
+ Added a clarification for LD_PRELOAD to the ld.so manual
+ page and added a symlink for ld-linux.so (Bug#33123).
+
+ Don't install ldd for Debian except for the m68k arch
+ because glibc 2.1 now includes it (Bug#35458).
+
+Changes in version 1.9.10:
+
+ Changed ldconfig to issue a warning and not overwrite a
+ regular file with a symlink (Bug#30859).
+
+ Changed Debian packaging to conflict with and replace the
+ ldconfig package (Bug#29398).
+
+Changes in version 1.9.9:
+
+ Changed ld-linux.so and libdl.so to match glibc by not
+ allowing user preloads of system libraries into setu/gid
+ binaries unless the library itself is setuid.
+
+ Fixed problems in ld-linux.so on the sparc architecture
+ (Juan Cespedes).
+
+Changes in version 1.9.8:
+
+ Changed ldconfig to allow the expected type for all
+ libraries in a directory to be optionally specified
+ (Mark Phillips). See the ldconfig man page.
+
+ Changed ldconfig to use the same type names used in the
+ change above when the -p option is used.
+
+Changes in version 1.9.7:
+
+ Changed ldd for m68k to use /lib/ld.so.1 instead of
+ /lib/ld-linux.so.2.
+
+ Added support for dladdr to libdl.so (Eduard Gode).
+
+ Fixed a small memory leak in libdl.so (Richard Garnish).
+
+ Fixed a bug in ldconfig when the -l option was used on a
+ filename without a '/' in it.
+
+ Updated the man pages (Bug#6404, Bug#9721, Bug#10652,
+ Bug#13494 and Bug#14127). They could still use some work.
+
+ No longer install the info page since it's way out of date.
+
+ Fixed minor Debian packaging problems (Bug#13160,
+ Bug#15577 and Bug#19345).
+
+Changes in version 1.9.6:
+
+ Changed ldd to not use the glibc dynamic linker when run
+ on a libc5-based shared library.
+
+ Added a -q option to ldconfig which causes warnings not
+ to be printed (Bob Tinsley).
+
+ Dropped support for the Debian libdl1-dev package.
+
+ Changed ld-linux.so to be compilable with gcc 2.8.0 (Sven
+ Verdoolaege)
+
+Changes in version 1.9.5:
+
+ Fixed a bug in ldd where ld-linux.so.2 was not called
+ correctly when run on shared libraries.
+
+ Fixed a problem in the previous version where some
+ Makefiles were not architecture independent.
+
+Changes in version 1.9.4:
+
+ Fixed a bug in ld.so introduced in the previous version
+ which broke preloads.
+
+ Turned a.out support back on by default, at least for the
+ time being. There are no promises to keep it.
+
+Changes in version 1.9.3:
+
+ Fixed buffer overflow bugs in ld-linux.so and ld.so.
+
+ Changed the README file a little to clarify a couple of
+ things.
+
+ Changed ldconfig to chroot to the specified directory when
+ the new -r option is used (Bob Tinsley).
+
+Changes in version 1.9.2:
+
+ Removed /usr/local/lib from the default /etc/ld.so.conf
+ for Debian (Bug#8181).
+
+ Changed ldconfig to be 64-bit clean (H.J. Lu).
+
+Changes in version 1.9.1:
+
+ Changed ldconfig to try to determine which libc a
+ library is for even if it doesn't have an soname.
+
+ Fixed a bug in ldconfig where an older library using
+ the glibc naming convention would be used instead of
+ a newer library.
+
+ Changed to ld-linux.so and libdl.so to not require the
+ libc5 headers in order to compile.
+
+ Changed ldconfig and ldd to be compilable with either
+ libc5 or libc6.
+
+Changes in version 1.9.0:
+
+ Changed to not build the old, a.out dynamic loader by
+ default.
+
+ Changed instldso.sh to require the --force option to
+ make sure users read the README file.
+
+ Changed instldso.sh to not install the libdl.so
+ development files unless the --devfiles option is used.
+
+ Changed instldso.sh to not strip binaries and libraries
+ if the --no-strip option is used.
+
+ Changed the Debian packaging to put the development files
+ which conflict with glibc in a new libdl1-dev package.
+
+ Changed ldd to use the glibc dynamic linker, if it is
+ available, when run on a shared library.
+
+ Changed ld-linux.so to print the load addresses of
+ libraries, ala glibc, when run by ldd.
+
+ Changed ld-linux.so to allow the libraries listed in
+ LD_PRELOAD to be separated by white space in addition to
+ colons.
+
+ Changed ld-linux.so to load the libraries listed in
+ LD_PRELOAD for setu/gid programs as long as they can be
+ loaded securely.
+
+ Changed ldconfig to update the symlinks for the dynamic
+ linkers.
+
+ Changed ldconfig to try to determine if an ELF library is
+ intended for libc5 or libc6 and save the infomation in the
+ cache. The mechanism used is rather simplistic and may
+ need to be enhanced.
+
+ Changed ldconfig to print the type of ELF library when
+ printing the cache.
+
+ Changed ld-linux.so to only load ELF shared libraries for
+ use with libc5 or an unknown libc.
+
+Changes in version 1.8.10:
+
+ Fixed a bug in ldconfig where a symlink could be used
+ instead of a regular file.
+
+ Fixed a Debian packaging problem for the sparc
+ architecture.
+
+Changes in version 1.8.9:
+
+ Changed ldconfig to only cache the symlinks it creates.
+ This make the behavior of the dynamic linkers consistent
+ with how they would behave if a cache was not used.
+
+ Changed ldconfig to cache the symlinks that it finds but
+ use the name of the symlink as the soname instead of the
+ actual soname.
+
+Changes in version 1.8.8:
+
+ Minor documentation updates to reflect recent changes.
+
+ Changed ld.so and ld-linux.so to perform more complete
+ validation on ld.so.cache before using it.
+
+ Changed ldconfig to accept libraries with inconsistent
+ sonames since glibc is going to use them. A warning is
+ still printed in debug mode.
+
+ Changed the install script to not strip _dl_debug_state
+ from ld-linux.so since gdb needs it.
+
+ More sparc fixes (Derrick Brashear).
+
+ Changed ldconfig to not issue a warning when a linker
+ script disguised as a shared library is found.
+
+ Fixed a bug in ld-linux.so where some registers were
+ not preserved on the first call to a function causing
+ problems for non-C-like languages (Tim Renouf).
+
+ Fixed a bug in ld-linux.so where global variables were
+ not always mapped correctly across dynamically loaded
+ libraries (Mikihiko Nakao).
+
+ Converted to new Debian source packaging format (Shaya
+ Potter).
+
+Changes in version 1.8.6/7:
+
+ Never released as some unofficial patches used these
+ version numbers.
+
+Changes in version 1.8.5:
+
+ Fixed a bug in ld.so introduced in the previous changes.
+
+Changes in version 1.8.4:
+
+ Changed ldconfig to completely ignore symbolic links.
+
+ Changed ldconfig to issue the warning concerning an
+ inconsistent soname in non-verbose mode.
+
+ Changed ld-linux.so back to not keep ld.so.cache mapped
+ at all times.
+
+ Changed Debian packaging to compress man pages, strip all
+ binaries (Bug#5125) and include a shlibs file.
+
+Changes in version 1.8.3:
+
+ Changed ld-linux.so to process LD_PRELOAD before
+ /etc/ld.so.preload.
+
+ Fixed a Debian packaging problem where libdl might not
+ be available if other packages were upgraded at the same
+ time (Debian Bug#4728).
+
+ Changed ldd to always exit with status 1 if any errors
+ occur (Debian Bug#4188).
+
+ Fixed some minor problems in instldso.sh (Mike Castle and
+ Wolfgang Franke).
+
+ Changed ldconfig to issue a warning in verbose mode when
+ skipping a library because the soname doesn't match.
+
+ More sparc fixes (Miguel de Icaza).
+
+ Don't link with -N when building ld.so (Alan Modra).
+
+ Changed ld-linux.so to better support position-dependant
+ libraries (NIIBE Yutaka).
+
+Changes in version 1.8.2:
+
+ Added a texinfo file for ld.so and libdl (Michael
+ Deutschmann).
+
+ Minor sparc and installation changes (Elliot Lee).
+
+ Added multiple architecture support for Debian (Leland
+ Lucius).
+
+ Changed libdl to better support RTLD_NEXT (Eric
+ Youngdale). Note: the exact meaning of ETLD_NEXT is
+ still not clear in all cases.
+
+ Removed some libc dependencies from libdl. Still need
+ to remove malloc and free.
+
+Changes in version 1.8.1:
+
+ Changed ld.so to be compiled as ELF. This also means
+ that ELF support is now required. A.out support is
+ still optional.
+
+ Changed ld-linux.so and libdl.so to use the rpath in the
+ executable instead of in the invoking shared library.
+
+ More m68k fixes (Andreas Schwab).
+
+ Various sparc fixes (Miguel de Icaza).
+
+ Changed ldcnnfig to ignore libraries ending in '~'.
+
+ Changed ldconfig to allow alternative conf and cache
+ files to be specified on the command-line.
+
+ Changed libdl.so to work when dlsym is passed a NULL
+ handle pointer.
+
+Changes in version 1.8.0:
+
+ Changed ld-linux.so to be more liberal when checking to
+ see if a library is already loaded. This should avoid
+ the duplicate loading problem for programs linkeed with
+ the -rpath option.
+
+ Various m68k fixes (Andreas Schwab).
+
+ Changed ld.so to only use LD_AOUT_LIBRARY_PATH and
+ LD_AOUT_PRELOAD and ld-linux.so to only use
+ LD_LIBRARY_PATH and LD_PRELOAD. LD_ELF_LIBRARY_PATH
+ and LD_ELF_PRELOAD are no longer supported.
+
+ Changed ld-linux.so to allow debugging of shared and
+ dynamically loaded libraries (H.J. Lu, Andreas Schwab).
+
+ Changed ld-linux.so to preload ELF shared libraries
+ listed in /etc/ld.so.preload. This allows secure
+ preloads, even for setuid/setgid programs.
+
+ Changed ld-linux.so to keep ld.so.cache mapped at all
+ times.
+
+ Changed ldconfig to allow #-style comments in ld.so.conf.
+
+ Removed various compiler warnings (Richard Sladkey and
+ David Engel).
+
+ Changed ldd to work on ELF shared libraries. This may
+ need a little more work.
+
+Changes in version 1.7.14:
+
+ Changed ldconfig to recognize ELF shared libraries
+ generated by post-2.6 versions of ld (Andreas Schwab).
+
+ Changed ldconfig to not remove stale links that do not
+ have a version number since they may be needed by ld.
+
+Changes in version 1.7.13:
+
+ Fixed a problem in ld-linux.so where a program linked
+ with a shared library that was not used could result in
+ a segmentation fault (H.J. Lu).
+
+Changes in version 1.7.12:
+
+ Fixed a problem in libdl.so where the wrong library
+ could be marked as global when RTLD_GLOBAL was used
+ (Lars Heete).
+
+ Installed dlfcn.h with libdl.so instead of requiring
+ it to be supplied with libc.
+
+ Removed support for libldso.a since it was nearly
+ impossible to use anyway.
+
+ Changed ldd to detect when the program being checked
+ exited abnormally.
+
+Changes in version 1.7.11:
+
+ Changed ld.so and ld-linux.so to delete all variations
+ of LD_PRELOAD and LD_LIBRARY_PATH for set[ug]id programs,
+ This makes it harder for broken set[ug]id programs to be
+ compromised.
+
+ Fixed a problem in libdl.so where dlsym would not accept
+ the handle returned from dlopen(0, *).
+
+Changes in version 1.7.10:
+
+ Changed ld-linux.so and libdl.so to support RTLD_GLOBAL
+ (Eric Youngdale).
+
+Changes in version 1.7.9:
+
+ Fixed a problem in ld-linux.so in detecting when the
+ new user/group information is provided by the kernel.
+
+ Fixed a problem in ld-linux.so where a buffer could be
+ overflowed if a large number of libraries were loaded
+ (Thomas Moore).
+
+Changes in version 1.7.8:
+
+ Changed the Makefiles and install scripts to support
+ a.out- and ELF-only configurations.
+
+ Changed ld-linux.so to use the user/group information
+ provided by linux 1.3.23+ instead of making syscalls
+ to get it.
+
+ Changed libdl.so to support RTLD_NEXT (Glenn Fowler).
+
+ Changed libdl.so to only execute the fini sections
+ instead of completely closing libraries at exit (Glenn
+ Fowler).
+
+ Changed ld.so and ld-linux.so to print the required
+ cache version when a mismatch is detected.
+
+ Changed ld-linux.so to not require on /dev/zero (Ralph
+ Loader).
+
+ Minor m68k cleanups (Andreas Schwab).
+
+Changes in version 1.7.7:
+
+ Fixed problems compiling with recent 1.3.x kernels.
+
+ Changed ld-linux.so to not use MAP_DENYWRITE until the
+ permission issue regarding it is resolved.
+
+Changes in version 1.7.6:
+
+ Fixed a bug in ld-linux.so dealing with a zero-length
+ LD_{ELF_}PRELOAD.
+
+ Changed ld.so and ld-linux.so to truncate all variations
+ of LD_PRELOAD and LD_LIBRARY_PATH for set[ug]id programs.
+
+Changes in version 1.7.5:
+
+ Changed ldconfig to recognize libraries without any
+ version number (eg. libXYZ.so).
+
+ Changed ldconfig to not generate a corrupt cache when
+ the disk is full or other write errors occur.
+
+ Changed ld-linux.so to map files with MAP_DENYWRITE to
+ keep them from being changed while the file is in use
+ (Rick Sladkey).
+
+ Changed libdl to not overwrite the scope pointer of a
+ library if it was already loaded (H.J. Lu).
+
+ Changed ld-linux.so so gdb can be used on constructors
+ (Eric Youngdale).
+
+ Changed ldconfig to ignore ELF libraries where the soname
+ does not match the file name on the assumption that it is
+ a used at compile-time (eg. libcurses.so -> libncruses.so).
+
+Changes in version 1.7.4:
+
+ Changed ld-linux.so and libdl to use the appropriate
+ rpaths when searching for shared libraries (Eric
+ Youngdale).
+
+ Changed ld-linux.so to search rpath before using the
+ cache. This more closely conforms to the IBCS standard.
+
+Changes in version 1.7.3:
+
+ Changed ld-linux.so to only print a library name the
+ first time it is loaded when run from ldd.
+
+ Fixed a bug in ldconfig where an invalid cache could be
+ generated if a directory was specified multiple times in
+ ld.so.conf.
+
+ Changed ld-linux.so so it will return the address of a
+ weak symbol when called from dlsym in libdl (Eric
+ Youngdale.
+
+Changes in version 1.7.2:
+
+ Changed libdl.so again to fix the undefined foobar
+ problem.
+
+Changes in version 1.7.1:
+
+ Changed libdl so it will compile at optimization level
+ O3 or higher.
+
+ Changed ldconfig to always create the cache file with
+ mode 644.
+
+ Changed ldconfig to not ingore valid symlinks.
+
+ Changed ldconfig to use the library name as the soname
+ for ELF libraries that do not have an soname entry.
+
+ Changed ld-linux.so to print the actual, requested library
+ name at the time it is loaded instead of trying to figure
+ it out after the fact.
+
+Changes in version 1.7.0:
+
+ Changed ldconfig to read the actual soname from the image
+ for ELF libraries and make it available to ld-linux.so.
+ The soname for DLL libraries is still determined by
+ truncating the minor numbers from the image file name.
+
+ Changed ldconfig to no longer support the undocumented
+ sort options.
+
+ Changed ld.so to require a valid cache to find libraries
+ in directories specified in ld.so.conf. /usr/lib and /lib
+ are still searched as a last resort. Ld-linux.so already
+ operated this way.
+
+ Fixed a bug in libldso.a where the arguments to
+ shared_loader were not parsed correctly (Wolfram Gloger).
+
+ Added support for RELA-style relocations under Linux/68k
+ (Andreas Schwab).
+
+ Changed ld-linux.so to only map the cache once for all
+ libraries instead of individually for each library.
+
+ Changed ld-linux.so continue searching the cache instead of
+ giving up when failing to load the first entry found.
+
+ Changed ld-linux.so to produce output similar to ld.so when
+ run from ldd or when errors occur.
+
+Changes in version 1.6.7:
+
+ Changed the install scripts to make sure that ld.so and
+ ld-linux.so are always usable.
+
+ Added support for Linux/Sparc (Eric Youngdale).
+
+ Added support for Linux/68k (Andreas Schwab).
+
+ Fixed various bugs in ld-linux.so dealing with closing
+ files, unmapping memory, dereferencing NULL pointers and
+ printing library names (David Engel, Eric Youngdale and
+ Andreas Schwab).
+
+ Replaced the manual page for libdl with a freely
+ distributable one (Adam Richter).
+
+ Fixed a bug in ld-linux.so where LD_LIBRARY_PATH and
+ LD_PRELOAD were not cleared for setuid/setgid programs.
+
+ Fixed a bug in libdl where dlsym would not return the
+ correct address of a symbol if it was redefined in another
+ library (Oleg Kibirev).
+
+ Changed ld-linux.so to use the following order to search
+ for libraries: LD_{ELF_}LIBRARY_PATH, ld.so.cache, rpath,
+ /usr/lib and /lib.
+
+ Changed ld-linux.so to not needlessly allocate memory when
+ using ld.so.cache.
+
+Changes in version 1.6.6:
+
+ Changed ldconfig to not warn about removing stale links
+ unless the -v option is specified.
+
+ Added manual pages for libdl (from FreeBSD/Sun)
+
+ Fixed a bug in ld.so dealing with preloading of objects
+ generated by recent versions of ld (Mitch D'Souza).
+
+ Fixed bugs in ldd where some errors were either not
+ detected or not printed.
+
+ Fixed a bug in ld-linux.so where the trailing nul in a
+ library name was not being copied (Owen Taylor).
+
+Changes in version 1.6.5:
+
+ Changed ldconfig to remove stale symbolic links.
+
+ Added debug hooks in ld-linux.so and libdl.so to be used
+ by a future version of gdb (Eric Youngdale).
+
+Changes in version 1.6.4:
+
+ Change ld-linux.so to print on stdout instead of stderr
+ when run from ldd.
+
+ Added support for Debian GNU/Linux packaging.
+
+Changes in version 1.6.3:
+
+ Fixed a bug in libdl when closing a library (H.J. Lu).
+
+Changes in version 1.6.2:
+
+ Changed the error message printed by ldd when a file is
+ not a.out or ELF. It used to only list a.out formats.
+
+ Changed ldconfig to no longer cache and set up links for
+ ld-linux.so.
+
+ Changed ld-linux.so and libdl to not conflict with upcoming
+ changes in kernel header files.
+
+ Changed ld-linux.so to not print preloaded libraries.
+
+Changes in version 1.6.1:
+
+ Updated the installation script.
+
+ Changed ld.so and ld-linux.so to look for LD_AOUT_PRELOAD
+ and LD_ELF_PRELOAD, respectively, before LD_PRELOAD.
+
+ Changed ld.so and ld-linux.so to use LD_AOUT_LIBRARY_PATH
+ and LD_ELF_LIBRARY_PATH, respectively, instead of
+ AOUT_LD_LIBRARY_PATH and ELF_LD_LIBRARY_PATH.
+
+Changes in version 1.6.0:
+
+ Changed ldconfig to process libraries which do not have
+ a minor version or patch level number.
+
+ Incorporated ld-linux.so and libdl.so.
+
+ Changed ld.so and ld-linux.so to not miss entries in the
+ cache when the fully qualified library is requested.
+
+ Changed ldconfig to use stdout instead of stderr when
+ printing the cache.
+
+Changes in version 1.5.3:
+
+ LD_PRELOAD enhancements (Tristan Gigold).
+
+ LD_PRELOAD patch for linux-68k (Andreas Schwab).
+
+Changes in version 1.5.2:
+
+ More ELF changes (Mitch D'Souza).
+
+ Changed ldconfig to also update the link for ld-linux.so.
+
+Changes in version 1.5.1:
+
+ More ELF and LD_PRELOAD changes (Mitch D'Souza).
+
+Changes in version 1.5.0:
+
+ Chnaged all executables to QMAGIC (Mitch D'Souza and Rick
+ Sladkey).
+
+ Added preliminary support for ELF to ldd and ldconfig (Eric
+ Youndale and H.J. Lu).
+
+ Added support for LD_PRELOAD to ld.so (Mitch D'Souza).
+
+ Removed the "advertising" clause from the copyright notices
+ in all source files.
+
+Changes in version 1.4.4:
+
+ Changed ldconfig to support QMAGIC libraries.
+
+ Fixed a bug in ld.so where some of the error messages had
+ transposed arguments.
+
+Changes in version 1.4.3:
+
+ Fixed an obscure bug in ld.so where an index was not being
+ incremented when a library was not found using the cache.
+
+Changes in version 1.4.2:
+
+ Changed ldconfig to issue a warning and continue instead
+ of an error and exiting when a link can't be updated.
+ This is useful when some libraries are imported on read-
+ only file systems, such as an NFS mounted /usr.
+
+ Changed ld.so to be more robust in searching for libraries.
+ A library is not considered found unless it can actually be
+ loaded. If a library is not found using the cache, the
+ standard directories are searched as in pre-cache versions.
+
+Changes in version 1.4.1:
+
+ Fixed minor Makefile problems.
+
+ Added support for linux-68k.
+
+ Fixed a bug in ld.so where libraries with absolute paths
+ were not handled correctly.
+
+ Changed ld.so to ignore the directory in the names of
+ shared libraries by default. This allows older libraries
+ with absolute paths, such as the XView libraries, to take
+ advantage of the cache support.
+
+ Added a minimal usage message to ldconfig.
+
+Changes in version 1.4:
+
+ Fixed bug in ld.so where minor version numbers were not
+ reported correctly when a minor version incompatibility
+ was found.
+
+ Fixed bug in ldconfig where libraries with subversion
+ numbers greater than 9 were not compared correctly.
+
+ Added Mitch D'Souza's support for suppressing warning
+ messages from ld.so about minor version incompatibilities.
+
+ Added Mitch D'Souza's support for using a cache to speed
+ up searching for libraries in the standard directories.
+
+ Added Mitch D'Souza's support for a debugging version of
+ ld.so. Link with -lldso if you think you are experiencing
+ dynamic linker problems.
+
+Changes in version 1.3:
+
+ Added support for libraries using absolute pathnames. If I
+ had known that the XView libraries used them, I would have
+ added this earlier.
+
+ Fixed a bug handling old libraries using a pathname beginning
+ with '/' or '/lib/'.
+
+Changes in version 1.2a:
+
+ Fixed a minor bug in ldd which caused all files, specifically
+ scripts, to be recognized as binaries. Thanks to Olaf Flebbe
+ for reporting it.
+
+David Engel
+david@sw.ods.com
diff --git a/ap/build/uClibc/ldso/include/dl-defs.h b/ap/build/uClibc/ldso/include/dl-defs.h
new file mode 100644
index 0000000..f71ba9b
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/dl-defs.h
@@ -0,0 +1,284 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+#ifndef _LD_DEFS_H
+#define _LD_DEFS_H
+
+#define FLAG_ANY -1
+#define FLAG_TYPE_MASK 0x00ff
+#define FLAG_LIBC4 0x0000
+#define FLAG_ELF 0x0001
+#define FLAG_ELF_LIBC5 0x0002
+#define FLAG_ELF_LIBC6 0x0003
+#define FLAG_ELF_UCLIBC 0x0004
+#define FLAG_REQUIRED_MASK 0xff00
+#define FLAG_SPARC_LIB64 0x0100
+#define FLAG_IA64_LIB64 0x0200
+#define FLAG_X8664_LIB64 0x0300
+#define FLAG_S390_LIB64 0x0400
+#define FLAG_POWERPC_LIB64 0x0500
+#define FLAG_MIPS64_LIBN32 0x0600
+#define FLAG_MIPS64_LIBN64 0x0700
+
+#define LIB_ANY -1
+#define LIB_DLL 0
+#define LIB_ELF 1
+#define LIB_ELF64 0x80
+#define LIB_ELF_LIBC5 2
+#define LIB_ELF_LIBC6 3
+#define LIB_ELF_LIBC0 4
+
+#if defined(__LDSO_PRELOAD_FILE_SUPPORT__) || defined(__LDSO_CACHE_SUPPORT__)
+#ifndef __LDSO_BASE_FILENAME__
+#define __LDSO_BASE_FILENAME__ "ld.so"
+#endif
+#define LDSO_BASE_PATH UCLIBC_RUNTIME_PREFIX "etc/" __LDSO_BASE_FILENAME__
+
+#ifdef __LDSO_PRELOAD_FILE_SUPPORT__
+#define LDSO_PRELOAD LDSO_BASE_PATH ".preload"
+#endif
+
+#ifdef __LDSO_CACHE_SUPPORT__
+#define LDSO_CONF LDSO_BASE_PATH ".conf"
+#define LDSO_CACHE LDSO_BASE_PATH ".cache"
+
+#define LDSO_CACHE_MAGIC "ld.so-"
+#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1)
+#define LDSO_CACHE_VER "1.7.0"
+#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1)
+
+typedef struct {
+ char magic [LDSO_CACHE_MAGIC_LEN];
+ char version [LDSO_CACHE_VER_LEN];
+ int nlibs;
+} header_t;
+
+typedef struct {
+ int flags;
+ int sooffset;
+ int liboffset;
+} libentry_t;
+
+#ifdef __ARCH_USE_MMU__
+#define LDSO_CACHE_MMAP_FLAGS (MAP_SHARED)
+#else
+#define LDSO_CACHE_MMAP_FLAGS (MAP_PRIVATE)
+#endif
+#endif /* __LDSO_CACHE_SUPPORT__ */
+
+#endif
+
+/* Provide a means for a port to pass additional arguments to the _dl_start
+ function. */
+#ifndef DL_START
+# define DL_START(X) static void * __attribute_used__ _dl_start(X)
+#endif
+
+/* Machines in which different sections may be relocated by different
+ * amounts should define this and LD_RELOC_ADDR. If you change this,
+ * make sure you change struct link_map in include/link.h accordingly
+ * such that it matches a prefix of struct elf_resolve.
+ */
+#ifndef DL_LOADADDR_TYPE
+# define DL_LOADADDR_TYPE ElfW(Addr)
+#endif
+
+/* When DL_LOADADDR_TYPE is not a scalar value, or some different
+ * computation is needed to relocate an address, define this.
+ */
+#ifndef DL_RELOC_ADDR
+# define DL_RELOC_ADDR(LOADADDR, ADDR) \
+ ((LOADADDR) + (ADDR))
+#endif
+
+/* Initialize the location of the dynamic addr. This is only called
+ * from DL_START, so additional arguments passed to it may be referenced. */
+#ifndef DL_BOOT_COMPUTE_DYN
+#define DL_BOOT_COMPUTE_DYN(DPNT, GOT, LOAD_ADDR) \
+ ((DPNT) = ((ElfW(Dyn) *) DL_RELOC_ADDR(LOAD_ADDR, GOT)))
+#endif
+
+/* Initialize the location of the global offset table. This is only called
+ * from DL_START, so additional arguments passed to it may be referenced. */
+#ifndef DL_BOOT_COMPUTE_GOT
+#define DL_BOOT_COMPUTE_GOT(GOT) \
+ ((GOT) = elf_machine_dynamic())
+#endif
+
+/* Initialize a LOADADDR representing the loader itself. It's only
+ * called from DL_START, so additional arguments passed to it may be
+ * referenced.
+ */
+#ifndef DL_INIT_LOADADDR_BOOT
+# define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+ ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Define if any declarations/definitions of local variables are
+ * needed in a function that calls DT_INIT_LOADADDR or
+ * DL_INIT_LOADADDR_HDR. Declarations must be properly terminated
+ * with a semicolon, and non-declaration statements are forbidden.
+ */
+#ifndef DL_INIT_LOADADDR_EXTRA_DECLS
+# define DL_INIT_LOADADDR_EXTRA_DECLS /* int i; */
+#endif
+
+/* Prepare a DL_LOADADDR_TYPE data structure for incremental
+ * initialization with DL_INIT_LOADADDR_HDR, given pointers to a base
+ * load address and to program headers.
+ */
+#ifndef DL_INIT_LOADADDR
+# define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+ ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Initialize a LOADADDR representing the program. It's called from
+ * DL_BOOT only.
+ */
+#ifndef DL_INIT_LOADADDR_PROG
+# define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+ ((LOADADDR) = (DL_LOADADDR_TYPE)(BASEADDR))
+#endif
+
+/* Update LOADADDR with information about PHDR, just mapped to the
+ given ADDR. */
+#ifndef DL_INIT_LOADADDR_HDR
+# define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) /* Do nothing. */
+#endif
+
+/* Convert a DL_LOADADDR_TYPE to an identifying pointer. Used mostly
+ * for debugging.
+ */
+#ifndef DL_LOADADDR_BASE
+# define DL_LOADADDR_BASE(LOADADDR) (LOADADDR)
+#endif
+
+/* Test whether a given ADDR is more likely to be within the memory
+ * region mapped to TPNT (a struct elf_resolve *) than to TFROM.
+ * Everywhere that this is used, TFROM is initially NULL, and whenever
+ * a potential match is found, it's updated. One might want to walk
+ * the chain of elf_resolve to locate the best match and return false
+ * whenever TFROM is non-NULL, or use an exact-matching algorithm
+ * using additional information encoded in DL_LOADADDR_TYPE to test
+ * for exact containment.
+ */
+#ifndef DL_ADDR_IN_LOADADDR
+# define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+ ((void*)(TPNT)->mapaddr < (void*)(ADDR) \
+ && (!(TFROM) || (TFROM)->mapaddr < (TPNT)->mapaddr))
+#endif
+
+/* This is called from dladdr() to give targets that use function descriptors
+ * a chance to map a function descriptor's address to the function's entry
+ * point before trying to find in which library it's defined. */
+#ifndef DL_LOOKUP_ADDRESS
+#define DL_LOOKUP_ADDRESS(ADDRESS) (ADDRESS)
+#endif
+
+/* On some architectures dladdr can't use st_size of all symbols this way. */
+#define DL_ADDR_SYM_MATCH(SYM_ADDR, SYM, MATCHSYM, ADDR) \
+ ((ADDR) >= (SYM_ADDR) \
+ && ((((SYM)->st_shndx == SHN_UNDEF || (SYM)->st_size == 0) \
+ && (ADDR) == (SYM_ADDR)) \
+ || (ADDR) < (SYM_ADDR) + (SYM)->st_size) \
+ && (!(MATCHSYM) || MATCHSYM < (SYM_ADDR)))
+
+/* Use this macro to convert a pointer to a function's entry point to
+ * a pointer to function. The pointer is assumed to have already been
+ * relocated. LOADADDR is passed because it may contain additional
+ * information needed to compute the pointer to function.
+ */
+#ifndef DL_ADDR_TO_FUNC_PTR
+# define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) ((void(*)(void))(ADDR))
+#endif
+
+/* On some platforms, computing a pointer to function is more
+ expensive than calling a function at a given address, so this
+ alternative is provided. The function signature must be given
+ within parentheses, as in a type cast. */
+#ifndef DL_CALL_FUNC_AT_ADDR
+# define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \
+ ((*SIGNATURE DL_ADDR_TO_FUNC_PTR ((ADDR), (LOADADDR)))(__VA_ARGS__))
+#endif
+
+/* An alignment value for a memory block returned by _dl_malloc. */
+#ifndef DL_MALLOC_ALIGN
+# define DL_MALLOC_ALIGN (__WORDSIZE / 8)
+#endif
+
+#ifdef __UCLIBC_UNDERSCORES__
+# define __C_SYMBOL_PREFIX__ "_"
+#else
+# define __C_SYMBOL_PREFIX__ ""
+#endif
+
+/* Define this if you want to modify the VALUE returned by
+ _dl_find_hash for this reloc TYPE. TPNT is the module in which the
+ matching SYM was found. */
+#ifndef DL_FIND_HASH_VALUE
+# define DL_FIND_HASH_VALUE(TPNT, TYPE, SYM) (DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value))
+#endif
+
+/* Unmap all previously-mapped segments accumulated in LOADADDR.
+ Generally used when an error occurs during loading. */
+#ifndef DL_LOADADDR_UNMAP
+# define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
+ _dl_munmap((char *) (LOADADDR), (LEN))
+#endif
+
+/* Similar to DL_LOADADDR_UNMAP, but used for libraries that have been
+ dlopen()ed successfully, when they're dlclose()d. */
+#ifndef DL_LIB_UNMAP
+# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->mapaddr, (LEN)))
+#endif
+
+/* Define this to verify that a library named LIBNAME, whose ELF
+ headers are pointed to by EPNT, is suitable for dynamic linking.
+ If it is not, print an error message (optional) and return NULL.
+ If the library can have its segments relocated independently,
+ arrange for PICLIB to be set to 2. If all segments have to be
+ relocated by the same amount, set it to 1. If it has to be loaded
+ at physical addresses as specified in the program headers, set it
+ to 0. A reasonable (?) guess for PICLIB will already be in place,
+ so it is safe to do nothing here. */
+#ifndef DL_CHECK_LIB_TYPE
+# define DL_CHECK_LIB_TYPE(EPNT, PICLIB, PROGNAME, LIBNAME) (void)0
+#endif
+
+/* Define this if you have special segment. */
+#ifndef DL_IS_SPECIAL_SEGMENT
+# define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) 0
+#endif
+
+/* Define this if you want to use special method to map the segment. */
+#ifndef DL_MAP_SEGMENT
+# define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) 0
+#endif
+
+/* Define this to declare the library offset. */
+#ifndef DL_DEF_LIB_OFFSET
+# define DL_DEF_LIB_OFFSET static unsigned long _dl_library_offset
+#endif
+
+/* Define this to get the library offset. */
+#ifndef DL_GET_LIB_OFFSET
+# define DL_GET_LIB_OFFSET() _dl_library_offset
+#endif
+
+/* Define this to set the library offset as difference beetwen the mapped
+ library address and the smallest virtual address of the first PT_LOAD
+ segment. */
+#ifndef DL_SET_LIB_OFFSET
+# define DL_SET_LIB_OFFSET(offset) (_dl_library_offset = (offset))
+#endif
+
+/* Define this to get the real object's runtime address. */
+#ifndef DL_GET_RUN_ADDR
+# define DL_GET_RUN_ADDR(loadaddr, mapaddr) (mapaddr)
+#endif
+
+#endif /* _LD_DEFS_H */
diff --git a/ap/build/uClibc/ldso/include/dl-elf.h b/ap/build/uClibc/ldso/include/dl-elf.h
new file mode 100644
index 0000000..29d1a00
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/dl-elf.h
@@ -0,0 +1,262 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+#ifndef LINUXELF_H
+#define LINUXELF_H
+
+#include <dl-string.h> /* before elf.h to get ELF_USES_RELOCA right */
+#include <elf.h>
+#include <link.h>
+
+/* Forward declarations for stuff defined in ld_hash.h */
+struct dyn_elf;
+struct elf_resolve;
+struct r_scope_elem;
+
+#include <dl-defs.h>
+#ifdef __LDSO_CACHE_SUPPORT__
+extern int _dl_map_cache(void);
+extern int _dl_unmap_cache(void);
+#else
+static __inline__ void _dl_map_cache(void) { }
+static __inline__ void _dl_unmap_cache(void) { }
+#endif
+
+#define DL_RESOLVE_SECURE 0x0001
+#define DL_RESOLVE_NOLOAD 0x0002
+
+/* Function prototypes for non-static stuff in readelflib1.c */
+extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size);
+extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size);
+extern struct elf_resolve * _dl_load_shared_library(unsigned rflags,
+ struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
+ int trace_loaded_objects);
+extern struct elf_resolve * _dl_load_elf_shared_library(unsigned rflags,
+ struct dyn_elf **rpnt, const char *libname);
+extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
+ int trace_loaded_objects);
+extern int _dl_linux_resolve(void);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag);
+extern void _dl_protect_relro (struct elf_resolve *l);
+
+/*
+ * Bitsize related settings for things ElfW()
+ * does not handle already
+ */
+#if __WORDSIZE == 64
+# define ELF_ST_BIND(val) ELF64_ST_BIND(val)
+# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
+# define ELF_R_SYM(i) ELF64_R_SYM(i)
+# define ELF_R_TYPE(i) ELF64_R_TYPE(i)
+# ifndef ELF_CLASS
+# define ELF_CLASS ELFCLASS64
+# endif
+#else
+# define ELF_ST_BIND(val) ELF32_ST_BIND(val)
+# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
+# define ELF_R_SYM(i) ELF32_R_SYM(i)
+# define ELF_R_TYPE(i) ELF32_R_TYPE(i)
+# ifndef ELF_CLASS
+# define ELF_CLASS ELFCLASS32
+# endif
+#endif
+
+/*
+ * Datatype of a relocation on this platform
+ */
+#ifdef ELF_USES_RELOCA
+# define ELF_RELOC ElfW(Rela)
+# define DT_RELOC_TABLE_ADDR DT_RELA
+# define DT_RELOC_TABLE_SIZE DT_RELASZ
+# define DT_RELOCCOUNT DT_RELACOUNT
+# define UNSUPPORTED_RELOC_TYPE DT_REL
+# define UNSUPPORTED_RELOC_STR "REL"
+#else
+# define ELF_RELOC ElfW(Rel)
+# define DT_RELOC_TABLE_ADDR DT_REL
+# define DT_RELOC_TABLE_SIZE DT_RELSZ
+# define DT_RELOCCOUNT DT_RELCOUNT
+# define UNSUPPORTED_RELOC_TYPE DT_RELA
+# define UNSUPPORTED_RELOC_STR "RELA"
+#endif
+
+/* OS and/or GNU dynamic extensions */
+
+#define OS_NUM_BASE 1 /* for DT_RELOCCOUNT */
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+# define OS_NUM_GNU_HASH 1 /* for DT_GNU_HASH entry */
+#else
+# define OS_NUM_GNU_HASH 0
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+# define OS_NUM_PRELINK 6 /* for DT_GNU_PRELINKED entry */
+#else
+# define OS_NUM_PRELINK 0
+#endif
+
+#define OS_NUM (OS_NUM_BASE + OS_NUM_GNU_HASH + OS_NUM_PRELINK)
+
+#ifndef ARCH_DYNAMIC_INFO
+ /* define in arch specific code, if needed */
+# define ARCH_NUM 0
+#endif
+
+#define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM)
+/* Keep ARCH specific entries into dynamic section at the end of the array */
+#define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+/* GNU hash comes just after the relocation count */
+# define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
+#else
+# define DT_GNU_HASH_IDX DT_RELCONT_IDX
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+/* GNU prelink comes just after the GNU hash if present */
+#define DT_GNU_PRELINKED_IDX (DT_GNU_HASH_IDX + 1)
+#define DT_GNU_CONFLICT_IDX (DT_GNU_HASH_IDX + 2)
+#define DT_GNU_CONFLICTSZ_IDX (DT_GNU_HASH_IDX + 3)
+#define DT_GNU_LIBLIST_IDX (DT_GNU_HASH_IDX + 4)
+#define DT_GNU_LIBLISTSZ_IDX (DT_GNU_HASH_IDX + 5)
+#define DT_CHECKSUM_IDX (DT_GNU_HASH_IDX + 6)
+#endif
+
+extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+ void *debug_addr, DL_LOADADDR_TYPE load_off);
+
+static __always_inline
+unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+ void *debug_addr, DL_LOADADDR_TYPE load_off)
+{
+ unsigned int rtld_flags = 0;
+
+ for (; dpnt->d_tag; dpnt++) {
+ if (dpnt->d_tag < DT_NUM) {
+ dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+#ifndef __mips__
+ /* we disable for mips because normally this page is readonly
+ * and modifying the value here needlessly dirties a page.
+ * see this post for more info:
+ * http://uclibc.org/lists/uclibc/2006-April/015224.html */
+ if (dpnt->d_tag == DT_DEBUG)
+ dpnt->d_un.d_val = (unsigned long)debug_addr;
+#endif
+ if (dpnt->d_tag == DT_BIND_NOW)
+ dynamic_info[DT_BIND_NOW] = 1;
+ if (dpnt->d_tag == DT_FLAGS &&
+ (dpnt->d_un.d_val & DF_BIND_NOW))
+ dynamic_info[DT_BIND_NOW] = 1;
+ if (dpnt->d_tag == DT_TEXTREL)
+ dynamic_info[DT_TEXTREL] = 1;
+#ifdef __LDSO_RUNPATH__
+ if (dpnt->d_tag == DT_RUNPATH)
+ dynamic_info[DT_RPATH] = 0;
+ if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH])
+ dynamic_info[DT_RPATH] = 0;
+#endif
+ } else if (dpnt->d_tag < DT_LOPROC) {
+ if (dpnt->d_tag == DT_RELOCCOUNT)
+ dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_FLAGS_1) {
+ if (dpnt->d_un.d_val & DF_1_NOW)
+ dynamic_info[DT_BIND_NOW] = 1;
+ if (dpnt->d_un.d_val & DF_1_NODELETE)
+ rtld_flags |= RTLD_NODELETE;
+ }
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ if (dpnt->d_tag == DT_GNU_HASH)
+ dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
+#endif
+#ifdef __LDSO_PRELINK_SUPPORT__
+ if (dpnt->d_tag == DT_GNU_PRELINKED)
+ dynamic_info[DT_GNU_PRELINKED_IDX] = dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_GNU_CONFLICT)
+ dynamic_info[DT_GNU_CONFLICT_IDX] = dpnt->d_un.d_ptr;
+ if (dpnt->d_tag == DT_GNU_CONFLICTSZ)
+ dynamic_info[DT_GNU_CONFLICTSZ_IDX] = dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_GNU_LIBLIST)
+ dynamic_info[DT_GNU_LIBLIST_IDX] = dpnt->d_un.d_ptr;
+ if (dpnt->d_tag == DT_GNU_LIBLISTSZ)
+ dynamic_info[DT_GNU_LIBLISTSZ_IDX] = dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_CHECKSUM)
+ dynamic_info[DT_CHECKSUM_IDX] = dpnt->d_un.d_val;
+#endif
+ }
+#ifdef ARCH_DYNAMIC_INFO
+ else {
+ ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
+ }
+#endif
+ }
+#define ADJUST_DYN_INFO(tag, load_off) \
+ do { \
+ if (dynamic_info[tag]) \
+ dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
+ } while (0)
+ /* Don't adjust .dynamic unnecessarily. For FDPIC targets,
+ we'd have to walk all the loadsegs to find out if it was
+ actually unnecessary, so skip this optimization. */
+#if !defined __FDPIC__ && !defined __DSBT__
+ if (load_off != 0)
+#endif
+ {
+ ADJUST_DYN_INFO(DT_HASH, load_off);
+ ADJUST_DYN_INFO(DT_PLTGOT, load_off);
+ ADJUST_DYN_INFO(DT_STRTAB, load_off);
+ ADJUST_DYN_INFO(DT_SYMTAB, load_off);
+ ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
+ ADJUST_DYN_INFO(DT_JMPREL, load_off);
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
+#endif
+ }
+#ifdef __DSBT__
+ /* Get the mapped address of the DSBT base. */
+ ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
+
+ /* Initialize loadmap dsbt info. */
+ load_off.map->dsbt_table = (void *)dynamic_info[DT_DSBT_BASE_IDX];
+ load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX];
+ load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX];
+#endif
+#undef ADJUST_DYN_INFO
+ return rtld_flags;
+}
+
+/* Reloc type classes as returned by elf_machine_type_class().
+ ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
+ some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
+ satisfied by any symbol in the executable. Some architectures do
+ not support copy relocations. In this case we define the macro to
+ zero so that the code for handling them gets automatically optimized
+ out. */
+#ifdef DL_NO_COPY_RELOCS
+# define ELF_RTYPE_CLASS_COPY (0x0)
+#else
+# define ELF_RTYPE_CLASS_COPY (0x2)
+#endif
+#define ELF_RTYPE_CLASS_PLT (0x1)
+
+/* dlsym() calls _dl_find_hash with this value, that enables
+ DL_FIND_HASH_VALUE to return something different than the symbol
+ itself, e.g., a function descriptor. */
+#define ELF_RTYPE_CLASS_DLSYM 0x80000000
+
+
+/* Convert between the Linux flags for page protections and the
+ ones specified in the ELF standard. */
+#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \
+ (((X) & PF_W) ? PROT_WRITE : 0) | \
+ (((X) & PF_X) ? PROT_EXEC : 0))
+
+
+#endif /* LINUXELF_H */
diff --git a/ap/build/uClibc/ldso/include/dl-hash.h b/ap/build/uClibc/ldso/include/dl-hash.h
new file mode 100644
index 0000000..c7effc5
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/dl-hash.h
@@ -0,0 +1,187 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+#ifndef _LD_HASH_H_
+#define _LD_HASH_H_
+
+#ifndef RTLD_NEXT
+#define RTLD_NEXT ((void*)-1)
+#endif
+
+struct init_fini {
+ struct elf_resolve **init_fini;
+ unsigned long nlist; /* Number of entries in init_fini */
+};
+
+struct dyn_elf {
+ struct elf_resolve * dyn;
+ struct dyn_elf * next_handle; /* Used by dlopen et al. */
+ struct init_fini init_fini;
+ struct dyn_elf * next;
+ struct dyn_elf * prev;
+};
+
+struct symbol_ref {
+ const ElfW(Sym) *sym;
+ struct elf_resolve *tpnt;
+};
+
+/* Structure to describe a single list of scope elements. The lookup
+ functions get passed an array of pointers to such structures. */
+struct r_scope_elem {
+ struct elf_resolve **r_list; /* Array of maps for the scope. */
+ unsigned int r_nlist; /* Number of entries in the scope. */
+ struct r_scope_elem *next;
+};
+
+struct elf_resolve {
+ /* These entries must be in this order to be compatible with the interface used
+ by gdb to obtain the list of symbols. */
+ DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */
+ char *libname; /* Absolute file name object was found in. */
+ ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */
+ struct elf_resolve * next;
+ struct elf_resolve * prev;
+ /* Nothing after this address is used by gdb. */
+
+#if defined(USE_TLS) && USE_TLS
+ /* Thread-local storage related info. */
+
+ /* Start of the initialization image. */
+ void *l_tls_initimage;
+ /* Size of the initialization image. */
+ size_t l_tls_initimage_size;
+ /* Size of the TLS block. */
+ size_t l_tls_blocksize;
+ /* Alignment requirement of the TLS block. */
+ size_t l_tls_align;
+ /* Offset of first byte module alignment. */
+ size_t l_tls_firstbyte_offset;
+# ifndef NO_TLS_OFFSET
+# define NO_TLS_OFFSET 0
+# endif
+ /* For objects present at startup time: offset in the static TLS block. */
+ ptrdiff_t l_tls_offset;
+ /* Index of the module in the dtv array. */
+ size_t l_tls_modid;
+ /* Nonzero if _dl_init_static_tls should be called for this module */
+ unsigned int l_need_tls_init:1;
+#endif
+
+ ElfW(Addr) mapaddr;
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ /* Store the entry point from the ELF header (e_entry) */
+ ElfW(Addr) l_entry;
+#endif
+ enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype;
+ /* This is the local scope of the shared object */
+ struct r_scope_elem symbol_scope;
+ unsigned short usage_count;
+ unsigned short int init_flag;
+ unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
+ Elf_Symndx nbucket;
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ /* Data needed to support GNU hash style */
+ Elf32_Word l_gnu_bitmask_idxbits;
+ Elf32_Word l_gnu_shift;
+ const ElfW(Addr) *l_gnu_bitmask;
+
+ union
+ {
+ const Elf32_Word *l_gnu_chain_zero;
+ const Elf_Symndx *elf_buckets;
+ };
+#else
+ Elf_Symndx *elf_buckets;
+#endif
+
+ struct init_fini_list *init_fini;
+ struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */
+ /*
+ * These are only used with ELF style shared libraries
+ */
+ Elf_Symndx nchain;
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ union
+ {
+ const Elf32_Word *l_gnu_buckets;
+ const Elf_Symndx *chains;
+ };
+#else
+ Elf_Symndx *chains;
+#endif
+ unsigned long dynamic_info[DYNAMIC_SIZE];
+
+ unsigned long n_phent;
+ ElfW(Phdr) * ppnt;
+
+ ElfW(Addr) relro_addr;
+ size_t relro_size;
+
+ dev_t st_dev; /* device */
+ ino_t st_ino; /* inode */
+
+#ifdef __powerpc__
+ /* this is used to store the address of relocation data words, so
+ * we don't have to calculate it every time, which requires a divide */
+ unsigned long data_words;
+#endif
+
+#ifdef __FDPIC__
+ /* Every loaded module holds a hashtable of function descriptors of
+ functions defined in it, such that it's easy to release the
+ memory when the module is dlclose()d. */
+ struct funcdesc_ht *funcdesc_ht;
+#endif
+};
+
+#define RELOCS_DONE 0x000001
+#define JMP_RELOCS_DONE 0x000002
+#define INIT_FUNCS_CALLED 0x000004
+#define FINI_FUNCS_CALLED 0x000008
+#define DL_OPENED 0x000010
+#define DL_RESERVED 0x000020
+
+extern struct dyn_elf * _dl_symbol_tables;
+extern struct elf_resolve * _dl_loaded_modules;
+extern struct dyn_elf * _dl_handles;
+
+extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
+ DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info,
+ unsigned long dynamic_addr, unsigned long dynamic_size);
+
+extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
+ struct elf_resolve *mytpnt, int type_class,
+ struct symbol_ref *symbol);
+
+extern int _dl_linux_dynamic_link(void);
+
+extern char * _dl_library_path;
+extern char * _dl_not_lazy;
+
+static __inline__ int _dl_symbol(char * name)
+{
+ if (name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_')
+ return 0;
+ return 1;
+}
+
+#define LD_ERROR_NOFILE 1
+#define LD_ERROR_NOZERO 2
+#define LD_ERROR_NOTELF 3
+#define LD_ERROR_NOTMAGIC 4
+#define LD_ERROR_NOTDYN 5
+#define LD_ERROR_MMAP_FAILED 6
+#define LD_ERROR_NODYNAMIC 7
+#define LD_ERROR_TLS_FAILED 8
+#define LD_WRONG_RELOCS 9
+#define LD_BAD_HANDLE 10
+#define LD_NO_SYMBOL 11
+
+#endif /* _LD_HASH_H_ */
diff --git a/ap/build/uClibc/ldso/include/dl-string.h b/ap/build/uClibc/ldso/include/dl-string.h
new file mode 100644
index 0000000..a7e2f47
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/dl-string.h
@@ -0,0 +1,365 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+#ifndef _LINUX_STRING_H_
+#define _LINUX_STRING_H_
+
+#include <dl-sysdep.h> /* for do_rem */
+#include <features.h>
+
+/* provide some sane defaults */
+#ifndef do_rem
+# define do_rem(result, n, base) ((result) = (n) % (base))
+#endif
+#ifndef do_div_10
+# define do_div_10(result, remain) ((result) /= 10)
+#endif
+
+static size_t _dl_strlen(const char *str);
+static char *_dl_strcat(char *dst, const char *src);
+static char *_dl_strcpy(char *dst, const char *src);
+static int _dl_strcmp(const char *s1, const char *s2);
+static int _dl_strncmp(const char *s1, const char *s2, size_t len);
+static char *_dl_strchr(const char *str, int c);
+static char *_dl_strrchr(const char *str, int c);
+static char *_dl_strstr(const char *s1, const char *s2);
+static void *_dl_memcpy(void *dst, const void *src, size_t len);
+static int _dl_memcmp(const void *s1, const void *s2, size_t len);
+static void *_dl_memset(void *str, int c, size_t len);
+static char *_dl_get_last_path_component(char *path);
+static char *_dl_simple_ltoa(char *local, unsigned long i);
+static char *_dl_simple_ltoahex(char *local, unsigned long i);
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+static __always_inline size_t _dl_strlen(const char *str)
+{
+ register const char *ptr = (char *) str-1;
+ while (*++ptr)
+ ;/* empty */
+ return (ptr - str);
+}
+
+static __always_inline char * _dl_strcat(char *dst, const char *src)
+{
+ register char *ptr = dst-1;
+
+ src--;
+ while (*++ptr)
+ ;/* empty */
+ ptr--;
+ while ((*++ptr = *++src) != 0)
+ ;/* empty */
+ return dst;
+}
+
+static __always_inline char * _dl_strcpy(char *dst, const char *src)
+{
+ register char *ptr = dst;
+
+ dst--;src--;
+ while ((*++dst = *++src) != 0)
+ ;/* empty */
+
+ return ptr;
+}
+
+static __always_inline int _dl_strcmp(const char *s1, const char *s2)
+{
+ register unsigned char c1, c2;
+ s1--;s2--;
+ do {
+ c1 = (unsigned char) *++s1;
+ c2 = (unsigned char) *++s2;
+ if (c1 == '\0')
+ return c1 - c2;
+ } while (c1 == c2);
+
+ return c1 - c2;
+}
+
+static __always_inline int _dl_strncmp(const char *s1, const char *s2, size_t len)
+{
+ register unsigned char c1 = '\0';
+ register unsigned char c2 = '\0';
+
+ s1--;s2--;
+ while (len > 0) {
+ c1 = (unsigned char) *++s1;
+ c2 = (unsigned char) *++s2;
+ if (c1 == '\0' || c1 != c2)
+ return c1 - c2;
+ len--;
+ }
+ return c1 - c2;
+}
+
+static __always_inline char * _dl_strchr(const char *str, int c)
+{
+ register char ch;
+ str--;
+ do {
+ if ((ch = *++str) == c)
+ return (char *) str;
+ }
+ while (ch);
+
+ return 0;
+}
+
+static __always_inline char * _dl_strrchr(const char *str, int c)
+{
+ register char *prev = 0;
+ register char *ptr = (char *) str-1;
+
+ while (*++ptr != '\0') {
+ if (*ptr == c)
+ prev = ptr;
+ }
+ if (c == '\0')
+ return(ptr);
+ return(prev);
+}
+
+static __always_inline char * _dl_strstr(const char *s1, const char *s2)
+{
+ register const char *s = s1;
+ register const char *p = s2;
+
+ do {
+ if (!*p)
+ return (char *) s1;;
+ if (*p == *s) {
+ ++p;
+ ++s;
+ } else {
+ p = s2;
+ if (!*s)
+ return NULL;
+ s = ++s1;
+ }
+ } while (1);
+}
+
+static __always_inline void * _dl_memcpy(void *dst, const void *src, size_t len)
+{
+ register char *a = dst-1;
+ register const char *b = src-1;
+
+ while (len) {
+ *++a = *++b;
+ --len;
+ }
+ return dst;
+}
+
+static __always_inline int _dl_memcmp(const void *s1, const void *s2, size_t len)
+{
+ unsigned char *c1 = (unsigned char *)s1-1;
+ unsigned char *c2 = (unsigned char *)s2-1;
+
+ while (len) {
+ if (*++c1 != *++c2)
+ return *c1 - *c2;
+ len--;
+ }
+ return 0;
+}
+
+#if defined(powerpc)
+/* Will generate smaller and faster code due to loop unrolling.*/
+static __always_inline void * _dl_memset(void *to, int c, size_t n)
+{
+ unsigned long chunks;
+ unsigned long *tmp_to;
+ unsigned char *tmp_char;
+
+ chunks = n / 4;
+ tmp_to = to + n;
+ c = c << 8 | c;
+ c = c << 16 | c;
+ if (!chunks)
+ goto lessthan4;
+ do {
+ *--tmp_to = c;
+ } while (--chunks);
+lessthan4:
+ n = n % 4;
+ if (!n)
+ return to;
+ tmp_char = (unsigned char *)tmp_to;
+ do {
+ *--tmp_char = c;
+ } while (--n);
+ return to;
+}
+#else
+static __always_inline void * _dl_memset(void *str, int c, size_t len)
+{
+ register char *a = str;
+
+ while (len--)
+ *a++ = c;
+
+ return str;
+}
+#endif
+
+static __always_inline char * _dl_get_last_path_component(char *path)
+{
+ register char *ptr = path-1;
+
+ while (*++ptr)
+ ;/* empty */
+
+ /* strip trailing slashes */
+ while (ptr != path && *--ptr == '/') {
+ *ptr = '\0';
+ }
+
+ /* find last component */
+ while (ptr != path && *--ptr != '/')
+ ;/* empty */
+ return ptr == path ? ptr : ptr+1;
+}
+
+/* Early on, we can't call printf, so use this to print out
+ * numbers using the SEND_STDERR() macro. Avoid using mod
+ * or using long division */
+static __always_inline char * _dl_simple_ltoa(char *local, unsigned long i)
+{
+ /* 20 digits plus a null terminator should be good for
+ * 64-bit or smaller ints (2^64 - 1)*/
+ char *p = &local[22];
+ *--p = '\0';
+ do {
+ char temp;
+ do_rem(temp, i, 10);
+ *--p = '0' + temp;
+ do_div_10(i, temp);
+ } while (i > 0);
+ return p;
+}
+
+static __always_inline char * _dl_simple_ltoahex(char *local, unsigned long i)
+{
+ /* 16 digits plus a leading "0x" plus a null terminator,
+ * should be good for 64-bit or smaller ints */
+ char *p = &local[22];
+ *--p = '\0';
+ do {
+ char temp = i & 0xf;
+ if (temp <= 0x09)
+ *--p = '0' + temp;
+ else
+ *--p = 'a' - 0x0a + temp;
+ i >>= 4;
+ } while (i > 0);
+ *--p = 'x';
+ *--p = '0';
+ return p;
+}
+
+
+
+
+/* The following macros may be used in dl-startup.c to debug
+ * ldso before ldso has fixed itself up to make function calls */
+
+/* On some (wierd) arches, none of this stuff works at all, so
+ * disable the whole lot... */
+#if defined(__mips__)
+
+# define SEND_STDERR(X)
+# define SEND_ADDRESS_STDERR(X, add_a_newline)
+# define SEND_NUMBER_STDERR(X, add_a_newline)
+
+#else
+
+/* On some arches constant strings are referenced through the GOT.
+ * This requires that load_addr must already be defined... */
+#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \
+ defined(__mips__) || defined(__sh__) || defined(__powerpc__) || \
+ defined(__avr32__) || defined(__xtensa__) || defined(__sparc__) || defined(__microblaze__)
+# define CONSTANT_STRING_GOT_FIXUP(X) \
+ if ((X) < (const char *) load_addr) (X) += load_addr
+# define NO_EARLY_SEND_STDERR
+#else
+# define CONSTANT_STRING_GOT_FIXUP(X)
+#endif
+
+#define SEND_STDERR(X) \
+{ \
+ const char *tmp1 = (X); \
+ CONSTANT_STRING_GOT_FIXUP(tmp1); \
+ _dl_write(2, tmp1, _dl_strlen(tmp1)); \
+}
+
+#define SEND_ADDRESS_STDERR(ADR, add_a_newline) \
+{ \
+ char tmp[26], v, *tmp2, *tmp1 = tmp; \
+ unsigned long X = (unsigned long)(ADR); \
+ CONSTANT_STRING_GOT_FIXUP(tmp1); \
+ tmp2 = tmp1 + sizeof(tmp); \
+ *--tmp2 = '\0'; \
+ if (add_a_newline) *--tmp2 = '\n'; \
+ do { \
+ v = (X) & 0xf; \
+ if (v <= 0x09) \
+ *--tmp2 = '0' + v; \
+ else \
+ *--tmp2 = 'a' - 0x0a + v; \
+ (X) >>= 4; \
+ } while ((X) > 0); \
+ *--tmp2 = 'x'; \
+ *--tmp2 = '0'; \
+ _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
+}
+
+#define SEND_NUMBER_STDERR(NUM, add_a_newline) \
+{ \
+ char tmp[26], v, *tmp2, *tmp1 = tmp; \
+ unsigned long X = (unsigned long)(NUM); \
+ CONSTANT_STRING_GOT_FIXUP(tmp1); \
+ tmp2 = tmp1 + sizeof(tmp); \
+ *--tmp2 = '\0'; \
+ if (add_a_newline) *--tmp2 = '\n'; \
+ do { \
+ do_rem(v, (X), 10); \
+ *--tmp2 = '0' + v; \
+ do_div_10((X), v); \
+ } while ((X) > 0); \
+ _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
+}
+#endif
+
+/* Some targets may have to override this to something that doesn't
+ * reference constant strings through the GOT. This macro should be
+ * preferred over SEND_STDERR for constant strings before we complete
+ * bootstrap.
+ */
+#ifndef SEND_EARLY_STDERR
+# define SEND_EARLY_STDERR(S) SEND_STDERR(S)
+#else
+# define EARLY_STDERR_SPECIAL
+#endif
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+# define SEND_STDERR_DEBUG(X) SEND_STDERR(X)
+# define SEND_EARLY_STDERR_DEBUG(X) SEND_EARLY_STDERR(X)
+# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) SEND_NUMBER_STDERR(X, add_a_newline)
+# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) SEND_ADDRESS_STDERR(X, add_a_newline)
+#else
+# define SEND_STDERR_DEBUG(X)
+# define SEND_EARLY_STDERR_DEBUG(X)
+# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline)
+# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline)
+#endif
+
+#endif
diff --git a/ap/build/uClibc/ldso/include/dl-syscall.h b/ap/build/uClibc/ldso/include/dl-syscall.h
new file mode 100644
index 0000000..547dad1
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/dl-syscall.h
@@ -0,0 +1,190 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+#ifndef _LD_SYSCALL_H_
+#define _LD_SYSCALL_H_
+
+/* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+#include "sys/syscall.h"
+extern int _dl_errno;
+#undef __set_errno
+#define __set_errno(X) {(_dl_errno) = (X);}
+
+/* Pull in the arch specific syscall implementation */
+#include <dl-syscalls.h>
+/* For MAP_ANONYMOUS -- differs between platforms */
+#define _SYS_MMAN_H 1
+#include <bits/mman.h>
+/* Pull in whatever this particular arch's kernel thinks the kernel version of
+ * struct stat should look like. It turns out that each arch has a different
+ * opinion on the subject, and different kernel revs use different names... */
+#if defined(__sparc_v9__) && (__WORDSIZE == 64)
+#define kernel_stat64 stat
+#else
+#define kernel_stat stat
+#endif
+#include <bits/kernel_stat.h>
+#include <bits/kernel_types.h>
+
+/* Protection bits. */
+#define S_ISUID 04000 /* Set user ID on execution. */
+#define S_ISGID 02000 /* Set group ID on execution. */
+
+
+/* Here are the definitions for some syscalls that are used
+ by the dynamic linker. The idea is that we want to be able
+ to call these before the errno symbol is dynamicly linked, so
+ we use our own version here. Note that we cannot assume any
+ dynamic linking at all, so we cannot return any error codes.
+ We just punt if there is an error. */
+#define __NR__dl_exit __NR_exit
+static __always_inline _syscall1(void, _dl_exit, int, status)
+
+#define __NR__dl_close __NR_close
+static __always_inline _syscall1(int, _dl_close, int, fd)
+
+#define __NR__dl_open __NR_open
+static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags,
+ __kernel_mode_t, mode)
+
+#define __NR__dl_write __NR_write
+static __always_inline _syscall3(unsigned long, _dl_write, int, fd,
+ const void *, buf, unsigned long, count)
+
+#define __NR__dl_read __NR_read
+static __always_inline _syscall3(unsigned long, _dl_read, int, fd,
+ const void *, buf, unsigned long, count)
+
+#define __NR__dl_mprotect __NR_mprotect
+static __always_inline _syscall3(int, _dl_mprotect, const void *, addr,
+ unsigned long, len, int, prot)
+
+#define __NR__dl_stat __NR_stat
+static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
+ struct stat *, buf)
+
+#define __NR__dl_fstat __NR_fstat
+static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf)
+
+#define __NR__dl_munmap __NR_munmap
+static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length)
+
+#ifdef __NR_getxuid
+# define __NR_getuid __NR_getxuid
+#endif
+#define __NR__dl_getuid __NR_getuid
+static __always_inline _syscall0(uid_t, _dl_getuid)
+
+#ifndef __NR_geteuid
+# define __NR_geteuid __NR_getuid
+#endif
+#define __NR__dl_geteuid __NR_geteuid
+static __always_inline _syscall0(uid_t, _dl_geteuid)
+
+#ifdef __NR_getxgid
+# define __NR_getgid __NR_getxgid
+#endif
+#define __NR__dl_getgid __NR_getgid
+static __always_inline _syscall0(gid_t, _dl_getgid)
+
+#ifndef __NR_getegid
+# define __NR_getegid __NR_getgid
+#endif
+#define __NR__dl_getegid __NR_getegid
+static __always_inline _syscall0(gid_t, _dl_getegid)
+
+#ifdef __NR_getxpid
+# define __NR_getpid __NR_getxpid
+#endif
+#define __NR__dl_getpid __NR_getpid
+static __always_inline _syscall0(gid_t, _dl_getpid)
+
+#define __NR__dl_readlink __NR_readlink
+static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
+ size_t, bufsiz)
+
+#ifdef __NR_pread64
+#define __NR___syscall_pread __NR_pread64
+static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
+ size_t, count, off_t, offset_hi, off_t, offset_lo)
+
+static __always_inline ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ return __syscall_pread(fd, buf, count, offset, offset >> 31);
+}
+#elif defined __NR_pread
+#define __NR___syscall_pread __NR_pread
+static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
+ size_t, count, off_t, offset_hi, off_t, offset_lo)
+
+static __always_inline ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ return __syscall_pread(fd, buf, count, __LONG_LONG_PAIR(offset >> 31, offset));
+}
+#endif
+
+#ifdef __UCLIBC_HAS_SSP__
+# include <sys/time.h>
+# define __NR__dl_gettimeofday __NR_gettimeofday
+static __always_inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
+# ifdef __USE_BSD
+ struct timezone *
+# else
+ void *
+# endif
+ , tz)
+#endif
+
+/* Some architectures always use 12 as page shift for mmap2() eventhough the
+ * real PAGE_SHIFT != 12. Other architectures use the same value as
+ * PAGE_SHIFT...
+ */
+#ifndef MMAP2_PAGE_SHIFT
+# define MMAP2_PAGE_SHIFT 12
+#endif
+
+#define MAP_FAILED ((void *) -1)
+#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
+
+static __always_inline
+void *_dl_mmap(void *addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+{
+#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
+ /* first try mmap(), syscall6() style */
+ return (void *)INLINE_SYSCALL(mmap, 6, addr, size, prot, flags, fd, offset);
+
+#elif defined(__NR_mmap2) && !defined (__mcoldfire__)
+ /* then try mmap2() */
+ unsigned long shifted;
+
+ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
+ return MAP_FAILED;
+
+ /* gcc needs help with putting things onto the stack */
+ shifted = offset >> MMAP2_PAGE_SHIFT;
+ return (void *)INLINE_SYSCALL(mmap2, 6, addr, size, prot, flags, fd, shifted);
+
+#elif defined(__NR_mmap)
+ /* finally, fall back to mmap(), syscall1() style */
+ unsigned long buffer[6];
+ buffer[0] = (unsigned long) addr;
+ buffer[1] = (unsigned long) size;
+ buffer[2] = (unsigned long) prot;
+ buffer[3] = (unsigned long) flags;
+ buffer[4] = (unsigned long) fd;
+ buffer[5] = (unsigned long) offset;
+ return (void *)INLINE_SYSCALL(mmap, 1, buffer);
+#else
+# error "Your architecture doesn't seem to provide mmap() !?"
+#endif
+}
+
+#endif /* _LD_SYSCALL_H_ */
diff --git a/ap/build/uClibc/ldso/include/dlfcn.h b/ap/build/uClibc/ldso/include/dlfcn.h
new file mode 100644
index 0000000..03afd34
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/dlfcn.h
@@ -0,0 +1,28 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+/* User functions for run-time dynamic loading. libdl version */
+#ifndef _DLFCN_H
+#define _DLFCN_H 1
+
+#include <features.h>
+#include <bits/dlfcn.h>
+
+#define RTLD_NEXT ((void *) -1l)
+#define RTLD_DEFAULT ((void *) 0)
+
+/* Structure containing information about object searched using
+ `dladdr'. */
+typedef struct
+{
+ __const char *dli_fname; /* File name of defining object. */
+ void *dli_fbase; /* Load address of that object. */
+ __const char *dli_sname; /* Name of nearest symbol. */
+ void *dli_saddr; /* Exact value of nearest symbol. */
+} Dl_info;
+
+#endif /* _DLFCN_H */
diff --git a/ap/build/uClibc/ldso/include/ldso.h b/ap/build/uClibc/ldso/include/ldso.h
new file mode 100644
index 0000000..6f3b728
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/ldso.h
@@ -0,0 +1,171 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+#ifndef _LDSO_H_
+#define _LDSO_H_
+
+#include <features.h>
+
+/* Prepare for the case that `__builtin_expect' is not available. */
+#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#ifndef likely
+# define likely(x) __builtin_expect((!!(x)),1)
+#endif
+#ifndef unlikely
+# define unlikely(x) __builtin_expect((!!(x)),0)
+#endif
+#ifndef __LINUX_COMPILER_H
+#define __LINUX_COMPILER_H
+#endif
+
+/* Pull in compiler and arch stuff */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h> /* for ptrdiff_t */
+#include <stdbool.h>
+#define _FCNTL_H
+#include <bits/fcntl.h>
+#include <bits/wordsize.h>
+/* Pull in the arch specific type information */
+#include <sys/types.h>
+/* Pull in the arch specific page size */
+#include <bits/uClibc_page.h>
+/* Pull in the MIN macro */
+#include <sys/param.h>
+/* Pull in the ldso syscalls and string functions */
+#ifndef __ARCH_HAS_NO_SHARED__
+#include <dl-syscall.h>
+#include <dl-string.h>
+#include <dlfcn.h>
+/* Now the ldso specific headers */
+#include <dl-elf.h>
+#ifdef __UCLIBC_HAS_TLS__
+/* Defines USE_TLS */
+#include <tls.h>
+#endif
+#include <dl-hash.h>
+
+/* common align masks, if not specified by sysdep headers */
+#ifndef ADDR_ALIGN
+#define ADDR_ALIGN (_dl_pagesize - 1)
+#endif
+
+#ifndef PAGE_ALIGN
+#define PAGE_ALIGN (~ADDR_ALIGN)
+#endif
+
+#ifndef OFFS_ALIGN
+#define OFFS_ALIGN (PAGE_ALIGN & ~(1ul << (sizeof(_dl_pagesize) * 8 - 1)))
+#endif
+
+/* For INIT/FINI dependency sorting. */
+struct init_fini_list {
+ struct init_fini_list *next;
+ struct elf_resolve *tpnt;
+};
+
+/* Global variables used within the shared library loader */
+extern char *_dl_library_path; /* Where we look for libraries */
+extern char *_dl_preload; /* Things to be loaded before the libs */
+#ifdef __LDSO_SEARCH_INTERP_PATH__
+extern const char *_dl_ldsopath; /* Where the shared lib loader was found */
+#endif
+extern const char *_dl_progname; /* The name of the executable being run */
+extern size_t _dl_pagesize; /* Store the page size for use later */
+#ifdef __LDSO_PRELINK_SUPPORT__
+extern char *_dl_trace_prelink; /* Library for prelinking trace */
+extern struct elf_resolve *_dl_trace_prelink_map; /* Library map for prelinking trace */
+#else
+#define _dl_trace_prelink 0
+#endif
+
+#if defined(USE_TLS) && USE_TLS
+extern void _dl_add_to_slotinfo (struct link_map *l);
+extern void ** __attribute__ ((const)) _dl_initial_error_catch_tsd (void);
+#endif
+
+#ifdef USE_TLS
+void _dl_add_to_slotinfo (struct link_map *l);
+void ** __attribute__ ((const)) _dl_initial_error_catch_tsd (void);
+#endif
+#ifdef __SUPPORT_LD_DEBUG__
+extern char *_dl_debug;
+extern char *_dl_debug_symbols;
+extern char *_dl_debug_move;
+extern char *_dl_debug_reloc;
+extern char *_dl_debug_detail;
+extern char *_dl_debug_nofixups;
+extern char *_dl_debug_bindings;
+extern int _dl_debug_file;
+# define __dl_debug_dprint(fmt, args...) \
+ _dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __func__, __LINE__, ## args);
+# define _dl_if_debug_dprint(fmt, args...) \
+ do { if (_dl_debug) __dl_debug_dprint(fmt, ## args); } while (0)
+#else
+# define __dl_debug_dprint(fmt, args...) do {} while (0)
+# define _dl_if_debug_dprint(fmt, args...) do {} while (0)
+# define _dl_debug_file 2
+#endif /* __SUPPORT_LD_DEBUG__ */
+
+#ifdef IS_IN_rtld
+# ifdef __SUPPORT_LD_DEBUG__
+# define _dl_assert(expr) \
+ do { \
+ if (!(expr)) { \
+ __dl_debug_dprint("assert(%s)\n", #expr); \
+ _dl_exit(45); \
+ } \
+ } while (0)
+# else
+# define _dl_assert(expr) ((void)0)
+# endif
+#else
+# include <assert.h>
+# define _dl_assert(expr) assert(expr)
+#endif
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+# define _dl_debug_early(fmt, args...) __dl_debug_dprint(fmt, ## args)
+#else
+# define _dl_debug_early(fmt, args...) do {} while (0)
+#endif /* __SUPPORT_LD_DEBUG_EARLY__ */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern void *_dl_malloc(size_t size);
+extern void *_dl_calloc(size_t __nmemb, size_t __size);
+extern void *_dl_realloc(void *__ptr, size_t __size);
+extern void _dl_free(void *);
+extern char *_dl_getenv(const char *symbol, char **envp);
+extern void _dl_unsetenv(const char *symbol, char **envp);
+extern char *_dl_strdup(const char *string);
+extern void _dl_dprintf(int, const char *, ...);
+
+#ifndef DL_GET_READY_TO_RUN_EXTRA_PARMS
+# define DL_GET_READY_TO_RUN_EXTRA_PARMS
+#endif
+#ifndef DL_GET_READY_TO_RUN_EXTRA_ARGS
+# define DL_GET_READY_TO_RUN_EXTRA_ARGS
+#endif
+
+extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+ ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
+ DL_GET_READY_TO_RUN_EXTRA_PARMS);
+
+#ifdef HAVE_DL_INLINES_H
+#include <dl-inlines.h>
+#endif
+
+#else /* __ARCH_HAS_NO_SHARED__ */
+#include <dl-defs.h>
+#endif
+
+#endif /* _LDSO_H_ */
diff --git a/ap/build/uClibc/ldso/include/ldsodefs.h b/ap/build/uClibc/ldso/include/ldsodefs.h
new file mode 100644
index 0000000..8f601e9
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/ldsodefs.h
@@ -0,0 +1,147 @@
+#ifndef _LDSODEFS_H
+#define _LDSODEFS_H 1
+
+#include <bits/kernel-features.h>
+
+#include <features.h>
+#include <tls.h>
+
+#ifdef __mips__
+/* The MIPS ABI specifies that the dynamic section has to be read-only. */
+
+#define DL_RO_DYN_SECTION 1
+
+/* TODO: Import in 64-bit relocations from glibc. */
+#endif
+
+#ifndef SHARED
+# define EXTERN extern
+#else
+# ifdef IS_IN_rtld
+# define EXTERN
+# else
+# define EXTERN extern
+# endif
+#endif
+
+/* Non-shared code has no support for multiple namespaces. */
+#ifdef SHARED
+# define DL_NNS 16
+#else
+# define DL_NNS 1
+#endif
+
+#define GL(x) _##x
+#define GLRO(x) _##x
+
+/* Variable pointing to the end of the stack (or close to it). This value
+ must be constant over the runtime of the application. Some programs
+ might use the variable which results in copy relocations on some
+ platforms. But this does not matter, ld.so can always use the local
+ copy. */
+extern void *__libc_stack_end;
+
+/* Determine next available module ID. */
+extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden;
+
+/* Calculate offset of the TLS blocks in the static TLS block. */
+extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden;
+
+/* Set up the data structures for TLS, when they were not set up at startup.
+ Returns nonzero on malloc failure.
+ This is called from _dl_map_object_from_fd or by libpthread. */
+extern int _dl_tls_setup (void) internal_function;
+rtld_hidden_proto (_dl_tls_setup)
+
+/* Allocate memory for static TLS block (unless MEM is nonzero) and dtv. */
+extern void *_dl_allocate_tls (void *mem) internal_function;
+
+/* Get size and alignment requirements of the static TLS block. */
+extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp)
+ internal_function;
+
+extern void _dl_allocate_static_tls (struct link_map *map)
+ internal_function attribute_hidden;
+
+/* Taken from glibc/elf/dl-reloc.c */
+#define CHECK_STATIC_TLS(sym_map) \
+ do { \
+ if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0)) \
+ _dl_allocate_static_tls (sym_map); \
+ } while (0)
+
+/* These are internal entry points to the two halves of _dl_allocate_tls,
+ only used within rtld.c itself at startup time. */
+extern void *_dl_allocate_tls_storage (void)
+ internal_function attribute_hidden;
+extern void *_dl_allocate_tls_init (void *) internal_function;
+
+/* Deallocate memory allocated with _dl_allocate_tls. */
+extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb) internal_function;
+
+extern void _dl_nothread_init_static_tls (struct link_map *) attribute_hidden;
+
+/* Highest dtv index currently needed. */
+EXTERN size_t _dl_tls_max_dtv_idx;
+/* Flag signalling whether there are gaps in the module ID allocation. */
+EXTERN bool _dl_tls_dtv_gaps;
+/* Information about the dtv slots. */
+EXTERN struct dtv_slotinfo_list
+{
+ size_t len;
+ struct dtv_slotinfo_list *next;
+ struct dtv_slotinfo
+ {
+ size_t gen;
+ bool is_static;
+ struct link_map *map;
+ } slotinfo[0];
+} *_dl_tls_dtv_slotinfo_list;
+/* Number of modules in the static TLS block. */
+EXTERN size_t _dl_tls_static_nelem;
+/* Size of the static TLS block. */
+EXTERN size_t _dl_tls_static_size;
+/* Size actually allocated in the static TLS block. */
+EXTERN size_t _dl_tls_static_used;
+/* Alignment requirement of the static TLS block. */
+EXTERN size_t _dl_tls_static_align;
+/* Function pointer for catching TLS errors. */
+EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const));
+
+/* Number of additional entries in the slotinfo array of each slotinfo
+ list element. A large number makes it almost certain take we never
+ have to iterate beyond the first element in the slotinfo list. */
+# define TLS_SLOTINFO_SURPLUS (62)
+
+/* Number of additional slots in the dtv allocated. */
+# define DTV_SURPLUS (14)
+
+/* Initial dtv of the main thread, not allocated with normal malloc. */
+EXTERN void *_dl_initial_dtv;
+/* Generation counter for the dtv. */
+EXTERN size_t _dl_tls_generation;
+
+EXTERN void (*_dl_init_static_tls) (struct link_map *);
+
+/* We have the auxiliary vector. */
+#define HAVE_AUX_VECTOR
+
+/* We can assume that the kernel always provides the AT_UID, AT_EUID,
+ AT_GID, and AT_EGID values in the auxiliary vector from 2.4.0 or so on. */
+#if __ASSUME_AT_XID
+# define HAVE_AUX_XID
+#endif
+
+/* We can assume that the kernel always provides the AT_SECURE value
+ in the auxiliary vector from 2.5.74 or so on. */
+#if __ASSUME_AT_SECURE
+# define HAVE_AUX_SECURE
+#endif
+
+/* Starting with one of the 2.4.0 pre-releases the Linux kernel passes
+ up the page size information. */
+#if __ASSUME_AT_PAGESIZE
+# define HAVE_AUX_PAGESIZE
+#endif
+
+#endif
diff --git a/ap/build/uClibc/ldso/include/unsecvars.h b/ap/build/uClibc/ldso/include/unsecvars.h
new file mode 100644
index 0000000..f1ef381
--- /dev/null
+++ b/ap/build/uClibc/ldso/include/unsecvars.h
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ *
+ * GNU Lesser General Public License version 2.1 or later.
+ */
+
+/*
+ * Environment variable to be removed for SUID programs. The names are all
+ * stuffed in a single string which means they have to be terminated with a
+ * '\0' explicitly.
+ */
+
+#define UNSECURE_ENVVARS \
+ "LD_PRELOAD\0" \
+ "LD_LIBRARY_PATH\0" \
+ "LD_DEBUG\0" \
+ "LD_DEBUG_OUTPUT\0" \
+ "LD_TRACE_LOADED_OBJECTS\0" \
+ "TMPDIR\0"
+
+/*
+ * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h
+ * though used by ldd
+ *
+ * These environment variables are defined by glibc but ignored in
+ * uClibc, but may very well have an equivalent in uClibc.
+ *
+ * LD_ORIGIN_PATH, LD_PROFILE, LD_USE_LOAD_BIAS, LD_DYNAMIC_WEAK, LD_SHOW_AUXV,
+ * GCONV_PATH, GETCONF_DIR, HOSTALIASES, LOCALDOMAIN, LOCPATH, MALLOC_TRACE,
+ * NLSPATH, RESOLV_HOST_CONF, RES_OPTIONS, TZDIR
+ */
diff --git a/ap/build/uClibc/ldso/ldso/Makefile b/ap/build/uClibc/ldso/ldso/Makefile
new file mode 100644
index 0000000..f910021
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../
+top_builddir=../../
+include $(top_builddir)Rules.mak
+all: libs
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/ldso/ldso/Makefile.in b/ap/build/uClibc/ldso/ldso/Makefile.in
new file mode 100644
index 0000000..eb1570a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/Makefile.in
@@ -0,0 +1,85 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += ldso/ldso/$(TARGET_ARCH)
+
+CFLAGS-ldso := -DNOT_IN_libc -DIS_IN_rtld $(SSP_DISABLE_FLAGS)
+
+# This stuff will not work with -fomit-frame-pointer
+CFLAGS-ldso += -fno-omit-frame-pointer
+
+CFLAGS-ldso += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso
+CFLAGS-ldso += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\"
+
+ifeq ($(DODEBUG),y)
+# Not really much point in including debugging info, since gdb
+# can't really debug ldso, since gdb requires help from ldso to
+# debug things....
+# On arm, gcc-4.3.x onwards -Os emits calls to libgcc, which calls _div0,
+# which tries to call raise(). And raise comes from libc so a catch 22.
+# Using -O2 instead. We could have use -fno-early-inlining with -Os too.
+
+CFLAGS-ldso += -O2 -g
+endif
+
+CFLAGS-ldso/ldso/$(TARGET_ARCH)/ := $(CFLAGS-ldso)
+
+CFLAGS-ldso.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" $(CFLAGS-ldso)
+
+LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-$(UCLIBC_LDSO_NAME).so := -Wl,--dsbt-index=1
+ifneq ($(SUPPORT_LD_DEBUG),y)
+LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS)
+else
+LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs
+endif
+LDFLAGS-$(UCLIBC_LDSO_NAME).so += -Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic \
+ -Wl,--export-dynamic $(CFLAG_-Wl--sort-common) -Wl,--discard-locals \
+ $(CFLAG_-Wl--discard-all) -Wl,--no-undefined
+
+ldso_FULL_NAME := $(UCLIBC_LDSO_NAME)-$(VERSION).so
+
+$(UCLIBC_LDSO_NAME)_DIR := $(top_srcdir)ldso/ldso
+$(UCLIBC_LDSO_NAME)_OUT := $(top_builddir)ldso/ldso
+
+$(UCLIBC_LDSO_NAME)_CSRC := $($(UCLIBC_LDSO_NAME)_DIR)/ldso.c
+# prerequesites
+$($(UCLIBC_LDSO_NAME)_OUT)/ldso.o $($(UCLIBC_LDSO_NAME)_OUT)/ldso.oS: \
+ $($(UCLIBC_LDSO_NAME)_DIR)/dl-debug.c \
+ $($(UCLIBC_LDSO_NAME)_DIR)/dl-startup.c \
+ $($(UCLIBC_LDSO_NAME)_DIR)/dl-array.c \
+ $($(UCLIBC_LDSO_NAME)_DIR)/dl-hash.c \
+ $($(UCLIBC_LDSO_NAME)_DIR)/dl-elf.c
+$(UCLIBC_LDSO_NAME)_COBJ := $(patsubst $($(UCLIBC_LDSO_NAME)_DIR)/%.c,$($(UCLIBC_LDSO_NAME)_OUT)/%.o,$($(UCLIBC_LDSO_NAME)_CSRC))
+
+$(UCLIBC_LDSO_NAME)_SSRC := $(wildcard $($(UCLIBC_LDSO_NAME)_DIR)/$(TARGET_ARCH)/*.S)
+$(UCLIBC_LDSO_NAME)_SOBJ := $(patsubst $($(UCLIBC_LDSO_NAME)_DIR)/$(TARGET_ARCH)/%.S,$($(UCLIBC_LDSO_NAME)_OUT)/$(TARGET_ARCH)/%.o,$($(UCLIBC_LDSO_NAME)_SSRC))
+
+$(UCLIBC_LDSO_NAME)_OBJS := $($(UCLIBC_LDSO_NAME)_COBJ) $($(UCLIBC_LDSO_NAME)_SOBJ)
+
+ldso-y := $($(UCLIBC_LDSO_NAME)_OBJS:.o=.oS)
+
+lib-so-y += $(ldso)
+objclean-y += CLEAN_ldso/ldso
+
+ifeq ($(LDSO_PRELINK_SUPPORT),y)
+# Use a specific linker script for ld.so
+LDFLAGS-$(UCLIBC_LDSO_NAME).so += -T $(ldso:.$(ABI_VERSION)=).lds
+endif
+
+$(ldso): $(ldso:.$(ABI_VERSION)=)
+$(ldso:.$(ABI_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a
+ifeq ($(LDSO_PRELINK_SUPPORT),y)
+ $(call create-lds)
+endif
+ $(call link.so,$(ldso_FULL_NAME),$(ABI_VERSION))
+
+$($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a: $(ldso-y)
+ $(Q)$(RM) $@
+ $(do_ar)
+
+CLEAN_ldso/ldso:
+ $(do_rm) $(addprefix $($(UCLIBC_LDSO_NAME)_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*.,$(d)$(e))))
diff --git a/ap/build/uClibc/ldso/ldso/arm/aeabi_read_tp.S b/ap/build/uClibc/ldso/ldso/arm/aeabi_read_tp.S
new file mode 100644
index 0000000..564f593
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/aeabi_read_tp.S
@@ -0,0 +1,63 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <features.h>
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+
+#include <sysdep.h>
+
+/* GCC will emit calls to this routine under -mtp=soft. Linux has an
+ equivalent helper function (which clobbers fewer registers than
+ a normal function call) in a high page of memory; tail call to the
+ helper.
+
+ This function is exported from libc for use by user code. libpthread, librt,
+ and the dynamic linker get their own private copies, for
+ performance (and in the case of ld.so, out of necessity); those are
+ all hidden. */
+
+#ifndef NOT_IN_libc
+ .global __aeabi_read_tp
+#else
+ .hidden __aeabi_read_tp
+#endif
+ENTRY (__aeabi_read_tp)
+ mov r0, #0xffff0fff
+ sub pc, r0, #31
+END (__aeabi_read_tp)
+
+#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */
+
diff --git a/ap/build/uClibc/ldso/ldso/arm/dl-debug.h b/ap/build/uClibc/ldso/ldso/arm/dl-debug.h
new file mode 100644
index 0000000..af14eca
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/dl-debug.h
@@ -0,0 +1,46 @@
+/* vi: set sw=4 ts=4: */
+/* ARM ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ [0] "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32",
+ [4] "R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5",
+ [8] "R_ARM_ABS8", "R_ARM_SBREL32","R_ARM_THM_PC22", "R_ARM_THM_PC8",
+ [12] "R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25",
+ [16] "R_ARM_THM_XPC22", "R_ARM_TLS_DTPMOD32", "R_ARM_TLS_DTPOFF32", "R_ARM_TLS_TPOFF32",
+ [20] "R_ARM_COPY", "R_ARM_GLOB_DAT","R_ARM_JUMP_SLOT", "R_ARM_RELATIVE",
+ [24] "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32", "R_ARM_PLT32",
+ [32] "R_ARM_ALU_PCREL_7_0","R_ARM_ALU_PCREL_15_8","R_ARM_ALU_PCREL_23_15","R_ARM_LDR_SBREL_11_0",
+ [36] "R_ARM_ALU_SBREL_19_12","R_ARM_ALU_SBREL_27_20",
+ [100] "R_ARM_GNU_VTENTRY","R_ARM_GNU_VTINHERIT","R_ARM_THM_PC11","R_ARM_THM_PC9",
+ [104] "R_ARM_TLS_GD32","R_ARM_TLS_LDM32","R_ARM_TLS_LDO32","R_ARM_TLS_IE32",
+ [108] "R_ARM_TLS_LE32","R_ARM_TLS_LDO12","R_ARM_TLS_LE12","R_ARM_TLS_IE12GP",
+ [249] "R_ARM_RXPC25", "R_ARM_RSBREL32", "R_ARM_THM_RPC22", "R_ARM_RREL32",
+ [253] "R_ARM_RABS22", "R_ARM_RPC24", "R_ARM_RBASE",
+};
diff --git a/ap/build/uClibc/ldso/ldso/arm/dl-startup.h b/ap/build/uClibc/ldso/ldso/arm/dl-startup.h
new file mode 100644
index 0000000..f7d6052
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/dl-startup.h
@@ -0,0 +1,195 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+#include <bits/arm_asm.h>
+
+#if !defined(__thumb__)
+__asm__(
+ " .text\n"
+ " .globl _start\n"
+ " .type _start,%function\n"
+ "_start:\n"
+ " @ at start time, all the args are on the stack\n"
+ " mov r0, sp\n"
+ " bl _dl_start\n"
+ " @ returns user entry point in r0\n"
+ " mov r6, r0\n"
+ " @ we are PIC code, so get global offset table\n"
+ " ldr sl, .L_GET_GOT\n"
+ " add sl, pc, sl\n"
+ ".L_GOT_GOT:\n"
+ " @ See if we were run as a command with the executable file\n"
+ " @ name as an extra leading argument.\n"
+ " ldr r4, .L_SKIP_ARGS\n"
+ " ldr r4, [sl, r4]\n"
+ " @ get the original arg count\n"
+ " ldr r1, [sp]\n"
+ " @ subtract _dl_skip_args from it\n"
+ " sub r1, r1, r4\n"
+ " @ adjust the stack pointer to skip them\n"
+ " add sp, sp, r4, lsl #2\n"
+ " @ get the argv address\n"
+ " add r2, sp, #4\n"
+ " @ store the new argc in the new stack location\n"
+ " str r1, [sp]\n"
+ " @ compute envp\n"
+ " add r3, r2, r1, lsl #2\n"
+ " add r3, r3, #4\n"
+ "\n\n"
+ " @ load the finalizer function\n"
+ " ldr r0, .L_FINI_PROC\n"
+ " ldr r0, [sl, r0]\n"
+ " @ jump to the user_s entry point\n"
+#if defined(__USE_BX__)
+ " bx r6\n"
+#else
+ " mov pc, r6\n"
+#endif
+ ".L_GET_GOT:\n"
+ " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
+ ".L_SKIP_ARGS:\n"
+ " .word _dl_skip_args(GOTOFF)\n"
+ ".L_FINI_PROC:\n"
+ " .word _dl_fini(GOT)\n"
+ "\n\n"
+ " .size _start,.-_start\n"
+ ".previous\n"
+);
+#else
+__asm__(
+ " .text\n"
+ " .arm\n"
+ " .globl _start\n"
+ " .type _start,%function\n"
+ "_start:\n"
+ " @ dumb: can't persuade the linker to make the start address\n"
+ " @ odd, so use an arm function and change to thumb (_dl_start\n"
+ " @ is thumb)\n"
+ " adr r0, __dl_thumb_start+1\n"
+ " bx r0\n"
+ "\n\n"
+ " .thumb\n"
+ " .globl __dl_thumb_start\n"
+ " .thumb_func\n"
+ " .type __dl_thumb_start,%function\n"
+ "__dl_thumb_start:\n"
+ " @ at start time, all the args are on the stack\n"
+ " mov r0, sp\n"
+ " bl _dl_start\n"
+ " @ returns user entry point in r0\n"
+ " mov r6, r0\n"
+ " @ we are PIC code, so get global offset table\n"
+ " ldr r7, .L_GET_GOT\n"
+ ".L_GOT_GOT:\n"
+ " add r7, pc\n"
+ " @ See if we were run as a command with the executable file\n"
+ " @ name as an extra leading argument.\n"
+ " ldr r4, .L_SKIP_ARGS\n"
+ " ldr r4, [r7, r4]\n"
+ " @ get the original arg count\n"
+ " ldr r1, [sp]\n"
+ " @ subtract _dl_skip_args from it\n"
+ " sub r1, r1, r4\n"
+ " @ adjust the stack pointer to skip them\n"
+ " lsl r4, r4, #2\n"
+ " add sp, r4\n"
+ " @ get the argv address\n"
+ " add r2, sp, #4\n"
+ " @ store the new argc in the new stack location\n"
+ " str r1, [sp]\n"
+ " @ compute envp\n"
+ " lsl r3, r1, #2\n"
+ " add r3, r3, r2\n"
+ " add r3, #4\n"
+ "\n\n"
+ " @ load the finalizer function\n"
+ " ldr r0, .L_FINI_PROC\n"
+ " ldr r0, [r7, r0]\n"
+ " @ jump to the user_s entry point\n"
+#if defined(__USE_BX__)
+ " bx r6\n"
+#else
+ " mov pc, r6\n"
+#endif
+ "\n\n"
+ ".L_GET_GOT:\n"
+ " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
+ ".L_SKIP_ARGS:\n"
+ " .word _dl_skip_args(GOTOFF)\n"
+ ".L_FINI_PROC:\n"
+ " .word _dl_fini(GOT)\n"
+ "\n\n"
+ " .size _start,.-_start\n"
+ ".previous\n"
+);
+#endif
+
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
+{
+ switch (ELF_R_TYPE(rpnt->r_info)) {
+ case R_ARM_NONE:
+ break;
+ case R_ARM_ABS32:
+ *reloc_addr += symbol_addr;
+ break;
+ case R_ARM_PC24:
+ {
+ unsigned long addend;
+ long newvalue, topbits;
+
+ addend = *reloc_addr & 0x00ffffff;
+ if (addend & 0x00800000) addend |= 0xff000000;
+
+ newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (topbits != 0xfe000000 && topbits != 0x00000000)
+ {
+#if 0
+ /* Don't bother with this during ldso initilization... */
+ newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
+ - (unsigned long)reloc_addr + (addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000))
+ {
+ SEND_STDERR("R_ARM_PC24 relocation out of range\n");
+ _dl_exit(1);
+ }
+#else
+ SEND_STDERR("R_ARM_PC24 relocation out of range\n");
+ _dl_exit(1);
+#endif
+ }
+ newvalue >>= 2;
+ symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
+ *reloc_addr = symbol_addr;
+ break;
+ }
+ case R_ARM_GLOB_DAT:
+ case R_ARM_JUMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_ARM_RELATIVE:
+ *reloc_addr += load_addr;
+ break;
+ case R_ARM_COPY:
+ break;
+ default:
+ SEND_STDERR("Unsupported relocation type\n");
+ _dl_exit(1);
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/arm/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/arm/dl-syscalls.h
new file mode 100644
index 0000000..195461f
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/dl-syscalls.h
@@ -0,0 +1,36 @@
+/* _call_via_rX calls are used in thumb ldso because of calls via
+ * function pointers, but ldso is not linked with anything which
+ * provides them, so define them here (only required for thumb).
+ */
+#if defined(__thumb__)
+__asm__(
+ ".macro call_via register\n"
+ " .global _call_via_\\register\n"
+ " .hidden _call_via_\\register\n"
+ " .type _call_via_\\register, %function\n"
+ " .thumb_func\n"
+ "_call_via_\\register:\n"
+ " bx \\register\n"
+ " .size _call_via_\\register, . - _call_via_\\register\n"
+ ".endm\n"
+
+ ".text\n"
+ ".thumb\n"
+ ".align 1\n"
+ " call_via r0\n"
+ " call_via r1\n"
+ " call_via r2\n"
+ " call_via r3\n"
+ " call_via r4\n"
+ " call_via r5\n"
+ " call_via r6\n"
+ " call_via r7\n"
+ " call_via r8\n"
+ " call_via r9\n"
+ " call_via r10\n"
+ " call_via r11\n"
+ " call_via r12\n"
+ " call_via r13\n"
+ " call_via r14\n"
+);
+#endif
diff --git a/ap/build/uClibc/ldso/ldso/arm/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/arm/dl-sysdep.h
new file mode 100644
index 0000000..5a2912a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/dl-sysdep.h
@@ -0,0 +1,155 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+
+#ifndef _ARCH_DL_SYSDEP
+#define _ARCH_DL_SYSDEP
+
+/* Define this if the system uses RELOCA. */
+#undef ELF_USES_RELOCA
+#include <elf.h>
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+}
+
+static __always_inline unsigned long arm_modulus(unsigned long m, unsigned long p)
+{
+ unsigned long i,t,inc;
+ i=p; t=0;
+ while (!(i&(1<<31))) {
+ i<<=1;
+ t++;
+ }
+ t--;
+ for (inc=t;inc>2;inc--) {
+ i=p<<inc;
+ if (i&(1<<31))
+ break;
+ while (m>=i) {
+ m-=i;
+ i<<=1;
+ if (i&(1<<31))
+ break;
+ if (i<p)
+ break;
+ }
+ }
+ while (m>=p) {
+ m-=p;
+ }
+ return m;
+}
+#define do_rem(result, n, base) ((result) = arm_modulus(n, base))
+#define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul))
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_ARM
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "ARM"
+
+struct elf_resolve;
+unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references should not be allowed to
+ define the value.
+
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32 \
+ || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. We used to use the PIC register to do this
+ without a constant pool reference, but GCC 4.2 will use a pseudo-register
+ for the PIC base, so it may not be in r10. */
+static __always_inline Elf32_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ Elf32_Addr dynamic;
+#if !defined __thumb__
+ __asm__ ("ldr %0, 2f\n"
+ "1: ldr %0, [pc, %0]\n"
+ "b 3f\n"
+ "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
+ "3:" : "=r" (dynamic));
+#else
+ int tmp;
+ __asm__ (".align 2\n"
+ "bx pc\n"
+ "nop\n"
+ ".arm\n"
+ "ldr %0, 2f\n"
+ "1: ldr %0, [pc, %0]\n"
+ "b 3f\n"
+ "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n"
+ "3:"
+ ".align 2\n"
+ "orr %1, pc, #1\n"
+ "bx %1\n"
+ ".force_thumb\n"
+ : "=r" (dynamic), "=&r" (tmp));
+#endif
+
+ return dynamic;
+}
+
+extern void __dl_start __asm__ ("_dl_start");
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+ Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ Elf32_Addr pcrel_addr;
+#if defined __OPTIMIZE__ && !defined __thumb__
+ __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr));
+#else
+ /* A simple adr does not work in Thumb mode because the offset is
+ negative, and for debug builds may be too large. */
+ int tmp;
+ __asm__ ("adr %1, 1f\n\t"
+ "ldr %0, [%1]\n\t"
+ "add %0, %0, %1\n\t"
+ "b 2f\n\t"
+ ".align 2\n\t"
+ "1: .word _dl_start - 1b\n\t"
+ "2:"
+ : "=r" (pcrel_addr), "=r" (tmp));
+#endif
+ return pcrel_addr - got_addr;
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rel * rpnt = (void *) rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr += load_off;
+ } while (--relative_count);
+}
+#endif /* !_ARCH_DL_SYSDEP */
+
+#ifdef __ARM_EABI__
+#define DL_MALLOC_ALIGN 8 /* EABI needs 8 byte alignment for STRD LDRD */
+#endif
diff --git a/ap/build/uClibc/ldso/ldso/arm/elfinterp.c b/ap/build/uClibc/ldso/ldso/arm/elfinterp.c
new file mode 100644
index 0000000..b6dfae2
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/elfinterp.c
@@ -0,0 +1,359 @@
+/* vi: set sw=4 ts=4: */
+/* ARM ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+#include "ldso.h"
+
+extern int _dl_linux_resolve(void);
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ char *symname;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rel_addr;
+ int symtab_index;
+ unsigned long new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+
+ rel_addr = (ELF_RELOC *) tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = rel_addr + reloc_entry;
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of jump instruction to fix up */
+ instr_addr = ((unsigned long) this_reloc->r_offset +
+ (unsigned long) tpnt->loadaddr);
+ got_addr = (char **) instr_addr;
+
+ /* Get the address of the GOT entry */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope,
+ tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit(1);
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+#if !defined __SUPPORT_LD_DEBUG_EARLY__
+ if ((unsigned long) got_addr < 0x40000000)
+#endif
+ {
+ if (_dl_debug_bindings)
+ {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+ "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = (char *)new_addr;
+ }
+#else
+ *got_addr = (char *)new_addr;
+#endif
+
+ return new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ int i;
+ char *strtab;
+ int goof = 0;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *) rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res <0))
+ {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ }
+ if (unlikely(res >0))
+ {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ goof += res;
+ }
+ }
+ return goof;
+}
+
+#if 0
+static unsigned long
+fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
+{
+ static void *fix_page;
+ static unsigned int fix_offset;
+ unsigned int *fix_address;
+ if (! fix_page)
+ {
+ fix_page = _dl_mmap (NULL, PAGE_SIZE , PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fix_offset = 0;
+ }
+
+ fix_address = (unsigned int *)(fix_page + fix_offset);
+ fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
+ fix_address[1] = value;
+
+ fix_offset += 8;
+ if (fix_offset >= PAGE_SIZE)
+ fix_page = NULL;
+
+ return (unsigned long)fix_address;
+}
+#endif
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+ struct symbol_ref sym_ref;
+ struct elf_resolve *def_mod = 0;
+ int goof = 0;
+
+ reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (symtab_index) {
+ symbol_addr = _dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+ if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+ && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
+
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ def_mod = sym_ref.tpnt;
+ } else {
+ /*
+ * Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself.
+ */
+ symbol_addr = symtab[symtab_index].st_value;
+ def_mod = tpnt;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ {
+ unsigned long old_val = *reloc_addr;
+#endif
+ switch (reloc_type) {
+ case R_ARM_NONE:
+ break;
+ case R_ARM_ABS32:
+ *reloc_addr += symbol_addr;
+ break;
+ case R_ARM_PC24:
+#if 0
+ {
+ unsigned long addend;
+ long newvalue, topbits;
+
+ addend = *reloc_addr & 0x00ffffff;
+ if (addend & 0x00800000) addend |= 0xff000000;
+
+ newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (topbits != 0xfe000000 && topbits != 0x00000000)
+ {
+ newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
+ - (unsigned long)reloc_addr + (addend << 2);
+ topbits = newvalue & 0xfe000000;
+ if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000))
+ {
+ _dl_dprintf(2,"symbol '%s': R_ARM_PC24 relocation out of range.",
+ symtab[symtab_index].st_name);
+ _dl_exit(1);
+ }
+ }
+ newvalue >>= 2;
+ symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
+ *reloc_addr = symbol_addr;
+ break;
+ }
+#else
+ _dl_dprintf(2,"R_ARM_PC24: Compile shared libraries with -fPIC!\n");
+ _dl_exit(1);
+#endif
+ case R_ARM_GLOB_DAT:
+ case R_ARM_JUMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_ARM_RELATIVE:
+ *reloc_addr += (unsigned long) tpnt->loadaddr;
+ break;
+ case R_ARM_COPY:
+ _dl_memcpy((void *) reloc_addr,
+ (void *) symbol_addr, symtab[symtab_index].st_size);
+ break;
+#if defined USE_TLS && USE_TLS
+ case R_ARM_TLS_DTPMOD32:
+ *reloc_addr = def_mod->l_tls_modid;
+ break;
+
+ case R_ARM_TLS_DTPOFF32:
+ *reloc_addr += symbol_addr;
+ break;
+
+ case R_ARM_TLS_TPOFF32:
+ CHECK_STATIC_TLS ((struct link_map *) def_mod);
+ *reloc_addr += (symbol_addr + def_mod->l_tls_offset);
+ break;
+#endif
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+ }
+
+#endif
+
+ return goof;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ unsigned long *reloc_addr;
+
+ reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ {
+ unsigned long old_val = *reloc_addr;
+#endif
+ switch (reloc_type) {
+ case R_ARM_NONE:
+ break;
+ case R_ARM_JUMP_SLOT:
+ *reloc_addr += (unsigned long) tpnt->loadaddr;
+ break;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+ }
+
+#endif
+ return 0;
+
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
diff --git a/ap/build/uClibc/ldso/ldso/arm/resolve.S b/ap/build/uClibc/ldso/ldso/arm/resolve.S
new file mode 100644
index 0000000..08889d0
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/resolve.S
@@ -0,0 +1,173 @@
+/*
+ *
+ * add ip, pc, #0xNN00000
+ * add ip, ip, #0xNN000
+ * ldr pc, [ip, #0xNNN]!
+ *
+ * So that, effectively, causes the following to happen:
+ *
+ * ip : = pc+0x0NNNNNNN
+ * pc : = *ip
+ *
+ * For thumb the above fragment is preceded by "bx pc, nop" to switch to ARM
+ * mode and the thumb 'bl' must go to PLT-4 - the PLT entry is expanded by
+ * four bytes to accomodate the trampoline code.
+ *
+ * 0x0NNNNNNN is the offset of the GOT entry for this function relative to
+ * the PLT entry for this function (where the code is). So the code in the
+ * PLT causes a branch to whatever is in the GOT, leaving the actual address
+ * of the GOT entry in ip. (Note that the GOT must follow the PLT - the
+ * added value is 28 bit unsigned).
+ *
+ * ip is a pointer to the GOT entry for this function, the first time round
+ * *ip points to this code:
+ *
+ * str lr, [sp, #-4]! @ save lr
+ * ldr lr, [pc, #4] @ lr : = *dat (&GOT_TABLE[0]-.)
+ * add lr, pc, lr @ lr += &dat (so lr == &GOT_TABLE[0])
+ * ldr pc, [lr, #8]! @ pc : = GOT_TABLE[2]
+ *dat: *.long &GOT_TABLE[0] - .
+ *
+ * (this code is actually held in the first entry of the PLT). The code
+ * preserves lr then uses it as a scratch register (this preserves the ip
+ * value calculated above). GOT_TABLE[2] is initialized by INIT_GOT in
+ * dl-sysdep.h to point to _dl_linux_resolve - this function. The first
+ * three entries in the GOT are reserved, then they are followed by the
+ * entries for the PLT entries, in order.
+ *
+ * The linker initialises the following (non-reserved) GOT entries to
+ * the offset of the PLT with an associated relocation so that on load
+ * the entry is relocated to point to the PLT - the above code.
+ *
+ * The net effect of all this is that on the first call to an external (as
+ * yet unresolved) function all seven of the above instructions are
+ * executed in sequence and the program ends up executing _dl_linux_resolve
+ * with the following important values in registers:
+ *
+ * ip - a pointer to the GOT entry for the as yet unresolved function
+ * lr - &GOT_TABLE[2]
+ *
+ * GOT_TABLE[2] has already been initialised to _dl_linux_resolve, and
+ * GOT_TABLE[1] is a pointer to the (elf_resolve*) from INIT_GOT.
+ * _dl_linux_resolve unfrobnicates the ip and lr values to obtain arguments
+ * for a call to _dl_linux_resolver (not the additional 'r' on the end) -
+ * this is in elfinterp.c in this directory. The call takes arguments:
+ *
+ * _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+ *
+ * And returns the address of the function, it also overwrites the GOT
+ * table entry so that the next time round only the first code fragment will
+ * be executed - it will call the function directly.
+ *
+ * [[Of course, this simply doesn't work on ARM 4T with a thumb target - because
+ * 4T did not do the thumb/arm change on ldr pc! It can be made to work by
+ * changing _dl_linux_resolver to return __%s_from_arm for an STT_TFUNC, but
+ * this hasn't been done, and there is no guarantee that the linker generated
+ * that glue anyway.]]
+ *
+ * _dl_linux_resolve gets the arguments to call the resolver as follows:
+ *
+ * tpnt *GOT_TABLE[1], [lr-4]
+ * reloc-entry &GOT-&GOT_TABLE[3], (ip - lr - 4)/4
+ *
+ * (I.e. 'GOT' means the table entry for this function, the thing for which
+ * ip holds the address.) The reloc-entry is passed as an index, since
+ * since the GOT table has 4 byte entries the code needs to divide this by 4
+ * to get the actual index.
+ *
+ * John Bowler, August 13, 2005 - determined by experiment and examination
+ * of generated ARM code (there was no documentation...)
+ *
+ * This code is all ARM code - not thumb - _dl_linux_resolver may, itself,
+ * be thumb, in which case the linker will insert the appropriate glue. A
+ * call from thumb to the PLT hits the trampoline code described above.
+ * This code (now) builds a proper stack frame.
+ *
+ * The code does *not* set sb (r9,v6) - to do that the basic PLT instructions
+ * would need to save sb and load the new value and that would require
+ * support in the linker since it generates those instructions. (Also note
+ * that linux/uclibc seems to be using r10 - sl - as a PIC base register - see
+ * dl-startup.c).
+ */
+
+#include <sys/syscall.h>
+#include <bits/arm_asm.h>
+
+#include <features.h>
+
+#define sl r10
+#define fp r11
+#define ip r12
+
+ .text
+ .align 4 @ 16 byte boundary and there are 32 bytes below (arm case)
+ #if !defined(__thumb__) || defined(__thumb2__)
+ .arm
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve,%function
+ .align 4;
+
+_dl_linux_resolve:
+ @ _dl_linux_resolver is a standard subroutine call, therefore it
+ @ preserves everything except r0-r3 (a1-a4), ip and lr. This
+ @ function must branch to the real function, and that expects
+ @ r0-r3 and lr to be as they were before the whole PLT stuff -
+ @ ip can be trashed.
+ @ This routine is called after pushing lr, so we must push an odd
+ @ number of words to keep the stack correctly aligned.
+
+ stmdb sp!, {r0, r1, r2, r3, r4}
+ ldr r0, [lr, #-4] @ r0 : = [lr-4] (GOT_TABLE[1])
+ sub r1, lr, ip @ r1 : = (lr-ip) (a multple of 4)
+ mvn r1, r1, ASR #2 @ r1 : = ~((lr-ip)>>2), since -x = (1+~x)
+ @ ~x = -x-1, therefore ~(r1>>2) = (-((lr-ip)>>2)-1)
+ @ = - ((lr-ip)/4) - 1 = (ip - lr - 4)/4, as required
+
+ bl _dl_linux_resolver
+
+ mov ip, r0
+ ldmia sp!, {r0, r1, r2, r3, r4, lr}
+
+#if defined(__USE_BX__)
+ bx ip
+#else
+ mov pc,ip
+#endif
+#else
+ @ In the thumb case _dl_linux_resolver is thumb. If a bl is used
+ @ from arm code the linker will insert a stub call which, with
+ @ binutils 2.16, is not PIC. Since this code is accessed by an
+ @ ldr pc the reasonable fix is to make _dl_linux_resolve thumb too.
+ .thumb
+ .globl _dl_linux_resolve
+ .thumb_func
+ .type _dl_linux_resolve,%function
+ _dl_linux_resolve:
+ @ _dl_linux_resolver is a standard subroutine call, therefore it
+ @ preserves everything except r0-r3 (a1-a4), ip and lr. This
+ @ function must branch to the real function, and that expects
+ @ r0-r3 and lr to be as they were before the whole PLT stuff -
+ @ ip can be trashed.
+ @ This routine is called after pushing lr, so we must push an odd
+ @ number of words to keep the stack correctly aligned.
+ push {r0-r4}
+ mov r1, lr @ &GOT_TABLE[2]
+ sub r0, r1, #4
+ mov r2, ip @ &GOT[n]
+ ldr r0, [r0] @ r0 := GOT_TABLE[1]
+ @ for the function call r1 := n-3
+ sub r1, r2
+ asr r1, r1, #2
+ mvn r1, r1 @ exactly as in the arm code above
+ bl _dl_linux_resolver
+ @ r0 contains the branch address, the return address is above
+ @ the saved r0..r3
+ mov ip, r0
+ ldr r1, [sp, #20]
+ mov lr, r1
+ pop {r0-r4}
+ add sp, #4
+ bx ip
+
+#endif
+.size _dl_linux_resolve, .-_dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/arm/thumb_atomics.S b/ap/build/uClibc/ldso/ldso/arm/thumb_atomics.S
new file mode 100644
index 0000000..f6ae3db
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/arm/thumb_atomics.S
@@ -0,0 +1,79 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <features.h>
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+
+#include <sysdep.h>
+
+#if defined __thumb__
+
+/* Out-of-line atomic operations that we can't do in Thumb mode.
+ This ends up in various libraries where it is needed (and
+ a few .a archives where it isn't). */
+
+ .hidden __thumb_swpb
+ENTRY (__thumb_swpb)
+ swpb r0, r0, [r1]
+ bx lr
+END (__thumb_swpb)
+
+ .hidden __thumb_swp
+ENTRY (__thumb_swp)
+ swp r0, r0, [r1]
+ bx lr
+END (__thumb_swp)
+
+ .hidden __thumb_cmpxchg
+ENTRY (__thumb_cmpxchg)
+ stmdb sp!, {r4, lr}
+ mov r4, r0
+0: ldr r3, [r2]
+ cmp r3, r4
+ bne 1f
+ mov r0, r4
+ mov r3, #0xffff0fff
+ mov lr, pc
+ add pc, r3, #(0xffff0fc0 - 0xffff0fff)
+ bcc 0b
+ mov r3, r4
+1: mov r0, r3
+ ldmia sp!, {r4, pc}
+END (__thumb_cmpxchg)
+
+#endif /* __thumb__ */
+#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */
+
diff --git a/ap/build/uClibc/ldso/ldso/avr32/dl-debug.h b/ap/build/uClibc/ldso/ldso/avr32/dl-debug.h
new file mode 100644
index 0000000..44b0c01
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/avr32/dl-debug.h
@@ -0,0 +1,45 @@
+/*
+ * AVR32 ELF shared libary loader support
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ "R_AVR32_NONE",
+ "R_AVR32_32", "R_AVR32_16", "R_AVR32_8",
+ "R_AVR32_32_PCREL", "R_AVR32_16_PCREL", "R_AVR32_8_PCREL",
+ "R_AVR32_DIFF32", "R_AVR32_DIFF16", "R_AVR32_DIFF8",
+ "R_AVR32_GOT32", "R_AVR32_GOT16", "R_AVR32_GOT8",
+ "R_AVR32_21S", "R_AVR32_16U", "R_AVR32_16S", "R_AVR32_8S", "R_AVR32_8S_EXT",
+ "R_AVR32_22H_PCREL", "R_AVR32_18W_PCREL", "R_AVR32_16B_PCREL",
+ "R_AVR32_16N_PCREL", "R_AVR32_14UW_PCREL", "R_AVR32_11H_PCREL",
+ "R_AVR32_10UW_PCREL", "R_AVR32_9H_PCREL", "R_AVR32_9UW_PCREL",
+ "R_AVR32_HI16", "R_AVR32_LO16",
+ "R_AVR32_GOTPC", "R_AVR32_GOTCALL", "R_AVR32_LDA_GOT",
+ "R_AVR32_GOT21S", "R_AVR32_GOT18SW", "R_AVR32_GOT16S", "R_AVR32_GOT7UW",
+ "R_AVR32_32_CPENT", "R_AVR32_CPCALL", "R_AVR32_16_CP", "R_AVR32_9W_CP",
+ "R_AVR32_RELATIVE", "R_AVR32_GLOB_DAT", "R_AVR32_JMP_SLOT",
+ "R_AVR32_ALIGN",
+};
diff --git a/ap/build/uClibc/ldso/ldso/avr32/dl-startup.h b/ap/build/uClibc/ldso/ldso/avr32/dl-startup.h
new file mode 100644
index 0000000..a7179e4
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/avr32/dl-startup.h
@@ -0,0 +1,103 @@
+/*
+ * Architecture specific code used by dl-startup.c
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* This is the library loader's main entry point. Let _dl_boot2 do its
+ * initializations and jump to the application's entry point
+ * afterwards. */
+__asm__(" .text\n"
+ " .global _start\n"
+ " .type _start,@function\n"
+ "_start:\n"
+ /* All arguments are on the stack initially */
+ " mov r12, sp\n"
+ " rcall _dl_start\n"
+ /* Returns user entry point in r12. Save it. */
+ " mov r0, r12\n"
+ /* We're PIC, so get the Global Offset Table */
+ " lddpc r6, .L_GOT\n"
+ ".L_RGOT:\n"
+ " rsub r6, pc\n"
+ /* Adjust argc and argv according to _dl_skip_args */
+ " ld.w r1, r6[_dl_skip_args@got]\n"
+ " ld.w r1, r1[0]\n"
+ " ld.w r2, sp++\n"
+ " sub r2, r1\n"
+ " add sp, sp, r1 << 2\n"
+ " st.w --sp, r2\n"
+ /* Load the finalizer function */
+ " ld.w r12, r6[_dl_fini@got]\n"
+ /* Jump to the user's entry point */
+ " mov pc, r0\n\n"
+
+ " .align 2\n"
+ ".L_GOT:"
+ " .long .L_RGOT - _GLOBAL_OFFSET_TABLE_\n"
+ " .size _start, . - _start\n"
+ " .previous\n");
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *)ARGS + 1)
+
+
+/* We can't call functions before the GOT has been initialized */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+/*
+ * Relocate the GOT during dynamic loader bootstrap. This will add
+ * the load address to all entries in the GOT, which is necessary
+ * because the linker doesn't generate R_AVR32_RELATIVE relocs for the
+ * GOT.
+ */
+static __always_inline
+void PERFORM_BOOTSTRAP_GOT(struct elf_resolve *tpnt)
+{
+ Elf32_Addr i, nr_got;
+ register Elf32_Addr *__r6 __asm__("r6");
+ Elf32_Addr *got = __r6;
+
+ nr_got = tpnt->dynamic_info[DT_AVR32_GOTSZ_IDX] / sizeof(*got);
+ for (i = 2; i < nr_got; i++)
+ got[i] += tpnt->loadaddr;
+}
+
+#define PERFORM_BOOTSTRAP_GOT(tpnt) PERFORM_BOOTSTRAP_GOT(tpnt)
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr,
+ unsigned long load_addr, Elf32_Sym *symtab)
+{
+ switch(ELF_R_TYPE(rpnt->r_info)) {
+ case R_AVR32_NONE:
+ break;
+ case R_AVR32_GLOB_DAT:
+ case R_AVR32_JMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_AVR32_RELATIVE:
+ SEND_STDERR_DEBUG("Applying RELATIVE relocation: ");
+ SEND_ADDRESS_STDERR_DEBUG(load_addr, 0);
+ SEND_STDERR_DEBUG(" + ");
+ SEND_ADDRESS_STDERR_DEBUG(rpnt->r_addend, 1);
+ *reloc_addr = load_addr + rpnt->r_addend;
+ break;
+ default:
+ SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc_type ");
+ SEND_NUMBER_STDERR(ELF_R_TYPE(rpnt->r_info), 1);
+ SEND_STDERR("REL, SYMBOL, LOAD: ");
+ SEND_ADDRESS_STDERR(reloc_addr, 0);
+ SEND_STDERR(", ");
+ SEND_ADDRESS_STDERR(symbol_addr, 0);
+ SEND_STDERR(", ");
+ SEND_ADDRESS_STDERR(load_addr, 1);
+ _dl_exit(1);
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/avr32/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/avr32/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/avr32/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/avr32/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/avr32/dl-sysdep.h
new file mode 100644
index 0000000..618769b
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/avr32/dl-sysdep.h
@@ -0,0 +1,103 @@
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ *
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+
+#include <elf.h>
+
+#define ARCH_NUM 1
+#define DT_AVR32_GOTSZ_IDX (DT_NUM + OS_NUM)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+ do { \
+ if (dpnt->d_tag == DT_AVR32_GOTSZ) \
+ dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \
+ } while (0)
+
+/* Initialization sequence for the application/library GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+ do { \
+ unsigned long _i, _nr_got; \
+ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ /* Add load address displacement to all GOT entries */ \
+ _nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4; \
+ for (_i = 2; _i < _nr_got; _i++) \
+ GOT_BASE[_i] += (unsigned long)MODULE->loadaddr; \
+ } while (0)
+
+#define do_rem(result, n, base) ((result) = (n) % (base))
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_AVR32
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "AVR32"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
+
+#define elf_machine_type_class(type) \
+ ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
+
+/* AVR32 doesn't need any COPY relocs */
+#define DL_NO_COPY_RELOCS
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ register Elf32_Addr *got __asm__("r6");
+ return *got;
+}
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ extern void __dl_start __asm__("_dl_start");
+ Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ Elf32_Addr pcrel_addr;
+
+ __asm__(" lddpc %0, 2f\n"
+ "1: add %0, pc\n"
+ " rjmp 3f\n"
+ " .align 2\n"
+ "2: .long _dl_start - 1b\n"
+ "3:\n"
+ : "=r"(pcrel_addr) : : "cc");
+
+ return pcrel_addr - got_addr;
+}
+
+/*
+ * Perform any RELATIVE relocations specified by DT_RELCOUNT.
+ * Currently, we don't use that tag, but we might in the future as
+ * this would reduce the startup time somewhat (although probably not by much).
+ */
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela *rpnt = (void *)rel_addr;
+
+ do {
+ Elf32_Addr *reloc_addr;
+ reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/avr32/elfinterp.c b/ap/build/uClibc/ldso/ldso/avr32/elfinterp.c
new file mode 100644
index 0000000..17f34fa
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/avr32/elfinterp.c
@@ -0,0 +1,200 @@
+/*
+ * AVR32 ELF shared library loader suppport
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)
+{
+ /*
+ * AVR32 currently does not do lazy relocation.
+ */
+#if 0
+ struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
+ ElfW(Sym) *sym;
+ unsigned long local_gotno;
+ unsigned long gotsym;
+ unsigned long new_addr;
+ char *strtab, *symname;
+ unsigned long *entry;
+ unsigned long sym_index = got_offset / 4;
+
+ local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
+ gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
+
+ sym = ((ElfW(Sym) *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
+ + sym_index;
+ strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+ symname = strtab + sym->st_name;
+
+ new_addr = (unsigned long) _dl_find_hash(symname,
+ &_dl_loaded_modules->symbol_scope, tpnt,
+ ELF_RTYPE_CLASS_PLT, NULL);
+
+ entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
+ *entry = new_addr;
+
+ return new_addr;
+#endif
+ return 0;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_func)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ElfW(Rela) *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ ElfW(Sym) *symtab;
+ ElfW(Rela) *rpnt;
+ char *strtab;
+ int i;
+
+ rpnt = (ElfW(Rela) *)rel_addr;
+ rel_size /= sizeof(ElfW(Rela));
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int symtab_index, res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_func(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (res < 0) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined(__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n",
+ _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n",
+ reloc_type);
+#endif
+ _dl_exit(-res);
+ } else {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ElfW(Rela) *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+#if defined(__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+ struct symbol_ref sym_ref;
+
+ reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (symtab_index) {
+ symbol_addr = (unsigned long)
+ _dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+
+ /* Allow undefined references to weak symbols */
+ if (!symbol_addr &&
+ ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ return 0;
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ }
+
+#if defined(__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+ switch (reloc_type) {
+ case R_AVR32_NONE:
+ break;
+ case R_AVR32_GLOB_DAT:
+ case R_AVR32_JMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_AVR32_RELATIVE:
+ *reloc_addr = (unsigned long)tpnt->loadaddr
+ + rpnt->r_addend;
+ break;
+ default:
+ return -1;
+ }
+
+#if defined(__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr);
+#endif
+
+ return 0;
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ /* TODO: Might want to support this in order to get faster
+ * startup times... */
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size,
+ _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/avr32/resolve.S b/ap/build/uClibc/ldso/ldso/avr32/resolve.S
new file mode 100644
index 0000000..e3cb7f4
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/avr32/resolve.S
@@ -0,0 +1,28 @@
+/*
+ * Linux dynamic resolving code for AVR32. Fixes up the GOT entry as
+ * indicated in register r12 and jumps to the resolved address.
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License. See the file "COPYING.LIB" in the main directory of this
+ * archive for more details.
+ *
+ * Copyright (C) 2004-2007 Atmel Corporation
+ */
+
+#define ip r5
+
+ .text
+ .global _dl_linux_resolve
+ .type _dl_linux_resolve,@function
+_dl_linux_resolve:
+ /* The PLT code pushed r8 for us. It contains the address of this
+ function's GOT entry, that is entry 0. ip contains the address
+ of the GOT entry of the function we wanted to call. */
+ stm --sp, r9-r12, lr
+ mov r11, r8
+ sub r12, ip, r8
+ rcall _dl_linux_resolver
+ mov ip, r12
+ popm r8-r12,lr
+ mov pc, ip
+ .size _dl_linux_resolve, . - _dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/bfin/dl-debug.h b/ap/build/uClibc/ldso/ldso/bfin/dl-debug.h
new file mode 100644
index 0000000..6952b61
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/dl-debug.h
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/* Blackfin ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ [0] "R_BFIN_UNUSED0", "R_BFIN_PCREL5M2",
+ [2] "R_BFIN_UNUSED1", "R_BFIN_PCREL10",
+ [4] "R_BFIN_PCREL12_JUMP", "R_BFIN_RIMM16",
+ [6] "R_BFIN_LUIMM16", "R_BFIN_HUIMM16",
+ [8] "R_BFIN_PCREL12_JUMP_S","R_BFIN_PCREL24_JUMP_X",
+ [10] "R_BFIN_PCREL24", "R_BFIN_UNUSEDB",
+ [12] "R_BFIN_UNUSEDC", "R_BFIN_PCREL24_JUMP_L",
+ [14] "R_BFIN_PCREL24_CALL_X","R_BFIN_var_eq_symb",
+ [16] "R_BFIN_BYTE_DATA", "R_BFIN_BYTE2_DATA", "R_BFIN_BYTE4_DATA",
+ [19] "R_BFIN_PCREL11",
+
+ [20] "R_BFIN_GOT17M4", "R_BFIN_GOTHI", "R_BFIN_GOTLO",
+ [23] "R_BFIN_FUNCDESC",
+ [24] "R_BFIN_FUNCDESC_GOT17M4", "R_BFIN_FUNCDESC_GOTHI", "R_BFIN_FUNCDESC_GOTLO",
+ [27] "R_BFIN_FUNCDESC_VALUE", "R_BFIN_FUNCDESC_GOTOFF17M4",
+ [29] "R_BFIN_FUNCDESC_GOTOFFHI", "R_BFIN_FUNCDESC_GOTOFFLO",
+ [31] "R_BFIN_GOTOFF17M4", "R_BFIN_GOTOFFHI", "R_BFIN_GOTOFFLO",
+#if 0
+ [200] "R_BFIN_GNU_VTINHERIT", "R_BFIN_GNU_VTENTRY"
+#endif
+};
diff --git a/ap/build/uClibc/ldso/ldso/bfin/dl-inlines.h b/ap/build/uClibc/ldso/ldso/bfin/dl-inlines.h
new file mode 100644
index 0000000..b08ce61
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/dl-inlines.h
@@ -0,0 +1,146 @@
+/* Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <bfin_sram.h>
+
+#define __dl_loadaddr_unmap __dl_loadaddr_unmap
+
+#include "../fdpic/dl-inlines.h"
+
+static __always_inline void
+__dl_loadaddr_unmap(struct elf32_fdpic_loadaddr loadaddr,
+ struct funcdesc_ht *funcdesc_ht)
+{
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++) {
+ struct elf32_fdpic_loadseg *segdata;
+ ssize_t offs;
+ segdata = loadaddr.map->segs + i;
+
+ /* FIXME:
+ * A more cleaner way is to add type for struct elf32_fdpic_loadseg,
+ * and release the memory according to the type.
+ * Currently, we hardcode the memory address of L1 SRAM.
+ */
+ if ((segdata->addr & 0xff800000) == 0xff800000) {
+ _dl_sram_free((void *)segdata->addr);
+ continue;
+ }
+
+ offs = (segdata->p_vaddr & ADDR_ALIGN);
+ _dl_munmap((void*)segdata->addr - offs,
+ segdata->p_memsz + offs);
+ }
+
+ /*
+ * _dl_unmap is only called for dlopen()ed libraries, for which
+ * calling free() is safe, or before we've completed the initial
+ * relocation, in which case calling free() is probably pointless,
+ * but still safe.
+ */
+ _dl_free(loadaddr.map);
+ if (funcdesc_ht)
+ htab_delete(funcdesc_ht);
+}
+
+static __always_inline int
+__dl_is_special_segment(Elf32_Ehdr *epnt, Elf32_Phdr *ppnt)
+{
+ if (ppnt->p_type != PT_LOAD)
+ return 0;
+
+ /* Allow read-only executable segments to be loaded into L1 inst */
+ if ((epnt->e_flags & EF_BFIN_CODE_IN_L1) &&
+ !(ppnt->p_flags & PF_W) && (ppnt->p_flags & PF_X))
+ return 1;
+
+ /* Allow writable non-executable segments to be loaded into L1 data */
+ if ((epnt->e_flags & EF_BFIN_DATA_IN_L1) &&
+ (ppnt->p_flags & PF_W) && !(ppnt->p_flags & PF_X))
+ return 1;
+
+ /*
+ * These L1 memory addresses are also used in GNU ld and linux kernel.
+ * They need to be kept synchronized.
+ */
+ switch (ppnt->p_vaddr) {
+ case 0xff700000:
+ case 0xff800000:
+ case 0xff900000:
+ case 0xffa00000:
+ case 0xfeb00000:
+ case 0xfec00000:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static __always_inline char *
+__dl_map_segment(Elf32_Ehdr *epnt, Elf32_Phdr *ppnt, int infile, int flags)
+{
+ void *addr;
+ unsigned long sram_flags = 0;
+
+ /* Handle L1 inst mappings */
+ if (((epnt->e_flags & EF_BFIN_CODE_IN_L1) || ppnt->p_vaddr == 0xffa00000) &&
+ !(ppnt->p_flags & PF_W) && (ppnt->p_flags & PF_X))
+ {
+ size_t size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
+ void *status = _dl_mmap(NULL, size, LXFLAGS(ppnt->p_flags),
+ flags | MAP_EXECUTABLE | MAP_DENYWRITE,
+ infile, ppnt->p_offset & OFFS_ALIGN);
+ if (_dl_mmap_check_error(status))
+ return NULL;
+
+ addr = _dl_sram_alloc(ppnt->p_filesz, L1_INST_SRAM);
+ if (addr)
+ _dl_dma_memcpy(addr, status + (ppnt->p_vaddr & ADDR_ALIGN), ppnt->p_filesz);
+ else
+ _dl_dprintf(2, "%s:%s: sram allocation %#x failed\n",
+ _dl_progname, __func__, ppnt->p_vaddr);
+
+ _dl_munmap(status, size);
+ return addr;
+ }
+
+ /* Handle L1 data mappings */
+ if (((epnt->e_flags & EF_BFIN_DATA_IN_L1) ||
+ ppnt->p_vaddr == 0xff700000 ||
+ ppnt->p_vaddr == 0xff800000 ||
+ ppnt->p_vaddr == 0xff900000) &&
+ (ppnt->p_flags & PF_W) && !(ppnt->p_flags & PF_X))
+ {
+ switch (ppnt->p_vaddr) {
+ case 0xff800000: sram_flags = L1_DATA_A_SRAM; break;
+ case 0xff900000: sram_flags = L1_DATA_B_SRAM; break;
+ default: sram_flags = L1_DATA_SRAM; break;
+ }
+ }
+
+ /* Handle L2 mappings */
+ if (ppnt->p_vaddr == 0xfeb00000 || ppnt->p_vaddr == 0xfec00000)
+ sram_flags = L2_SRAM;
+
+ if (sram_flags) {
+ addr = _dl_sram_alloc(ppnt->p_memsz, sram_flags);
+ if (addr) {
+ if (_DL_PREAD(infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) {
+ _dl_sram_free(addr);
+ return NULL;
+ }
+ if (ppnt->p_filesz < ppnt->p_memsz)
+ _dl_memset(addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz);
+ } else
+ _dl_dprintf(2, "%s:%s: sram allocation %#x failed\n",
+ _dl_progname, __func__, ppnt->p_vaddr);
+ return addr;
+ }
+
+ return 0;
+}
diff --git a/ap/build/uClibc/ldso/ldso/bfin/dl-startup.h b/ap/build/uClibc/ldso/ldso/bfin/dl-startup.h
new file mode 100644
index 0000000..76ae150
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/dl-startup.h
@@ -0,0 +1,144 @@
+ /* Copyright (C) 2003 Red Hat, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA. */
+
+/* Any assembly language/system dependent hacks needed to setup
+ * boot1.c so it will work as expected and cope with whatever platform
+ * specific wierdness is needed for this architecture.
+ */
+
+/* At program start-up, p0 contains a pointer to a
+ elf32_fdpic_loadmap that describes how the executable was loaded
+ into memory. p1 contains a pointer to the interpreter (our!)
+ loadmap, if there is an interpreter, or 0 if we're being run as an
+ executable. p2 holds a pointer to the interpreter's dynamic
+ section, if there is an interpreter, or to the executable's dynamic
+ section, otherwise. If the executable is not dynamic, gr18 is 0.
+
+ We rely on the fact that the linker adds a pointer to the
+ _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that
+ __self_reloc returns the relocated pointer to us, so that we can
+ use this value to initialize the PIC register. */
+
+__asm__(
+ " .text\n"
+ " .global __start\n"
+ " .type __start,@function\n"
+ /* Build system expects a "_start" for the entry point;
+ provide it as it's free to do so with aliases. */
+ " .set _start, __start\n"
+ " .global _start\n"
+ "__start:\n"
+ " call .Lcall\n"
+ ".Lcall:\n"
+ " R4 = RETS;\n"
+ " SP += -32;\n"
+ " R5 = P0;\n"
+ " R6 = P1;\n"
+ " R7 = P2;\n"
+ " R0.L = .Lcall;\n"
+ " R0.H = .Lcall;\n"
+ " R1.L = __ROFIXUP_LIST__;\n"
+ " R1.H = __ROFIXUP_LIST__;\n"
+ " R2.L = __ROFIXUP_END__;\n"
+ " R2.H = __ROFIXUP_END__;\n"
+ " R1 = R1 - R0;\n"
+ " R1 = R1 + R4;\n"
+ " R2 = R2 - R0;\n"
+ " R2 = R2 + R4;\n"
+ " R0 = P1;\n"
+ " CC = R0 == 0;\n"
+ " IF CC R0 = P0;\n"
+ " CALL ___self_reloc;\n"
+ " P3 = R0;\n"
+ " P5 = R0;\n"
+ " R1 = R5;\n"
+ " R2 = R6;\n"
+ " [SP + 12] = R7;\n"
+ " P0 = SP;\n"
+ " P0 += 24;\n"
+ " [SP + 16] = P0;\n"
+ " P0 += 8;\n"
+ " [SP + 20] = P0;\n"
+ " CALL __dl_start;\n"
+ " /* Pass our FINI ptr() to the user in P1 */\n"
+ " R7 = [P5 + __dl_fini@FUNCDESC_GOT17M4];\n"
+ " P4 = [SP + 24];\n"
+ " P3 = [SP + 28];\n"
+ " P0 = R5;\n"
+ " SP += 32;\n"
+ " JUMP (P4);\n"
+ " .size __start,.-__start\n"
+);
+
+#undef DL_START
+#define DL_START(X) \
+static void __attribute__ ((used)) \
+_dl_start (Elf32_Addr dl_boot_got_pointer, \
+ struct elf32_fdpic_loadmap *dl_boot_progmap, \
+ struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ struct funcdesc_value *dl_main_funcdesc, \
+ X)
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1)
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF_R_TYPE((RELP)->r_info)){ \
+ case R_BFIN_BYTE4_DATA: \
+ *(REL) += (SYMBOL); \
+ break; \
+ case R_BFIN_FUNCDESC_VALUE: \
+ { \
+ struct funcdesc_value fv = { \
+ (void*)((SYMBOL) + *(REL)), \
+ (LOAD).got_value \
+ }; \
+ *(struct funcdesc_value volatile *)(REL) = fv; \
+ break; \
+ } \
+ default: \
+ _dl_exit(1); \
+ }
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done. We return the address of the function's entry point to
+ * _dl_boot, see boot1_arch.h.
+ */
+#define START() do { \
+ struct elf_resolve *exec_mod = _dl_loaded_modules; \
+ dl_main_funcdesc->entry_point = _dl_elf_main; \
+ while (exec_mod->libtype != elf_executable) \
+ exec_mod = exec_mod->next; \
+ dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \
+ return; \
+} while (0)
diff --git a/ap/build/uClibc/ldso/ldso/bfin/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/bfin/dl-syscalls.h
new file mode 100644
index 0000000..29a4514
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/dl-syscalls.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2003, 2004 Red Hat, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA. */
+
+#ifdef __NR_sram_alloc
+#define __NR__dl_sram_alloc __NR_sram_alloc
+static __always_inline _syscall2(__ptr_t, _dl_sram_alloc,
+ size_t, len, unsigned long, flags)
+#endif
+
+#ifdef __NR_sram_free
+#define __NR__dl_sram_free __NR_sram_free
+static __always_inline _syscall1(int, _dl_sram_free, __ptr_t, addr)
+#endif
+
+#ifdef __NR_dma_memcpy
+#define __NR__dl_dma_memcpy __NR_dma_memcpy
+static __always_inline _syscall3(__ptr_t, _dl_dma_memcpy,
+ __ptr_t, dest, __ptr_t, src, size_t, len)
+#endif
+
+#define __UCLIBC_MMAP_HAS_6_ARGS__
diff --git a/ap/build/uClibc/ldso/ldso/bfin/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/bfin/dl-sysdep.h
new file mode 100644
index 0000000..c965263
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/dl-sysdep.h
@@ -0,0 +1,104 @@
+/* Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ * Based on ../i386/dl-sysdep.h
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#undef ELF_USES_RELOCA
+
+/* JMPREL relocs are inside the DT_RELA table. */
+#define ELF_MACHINE_PLTREL_OVERLAP
+
+#define DL_NO_COPY_RELOCS
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_BLACKFIN
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "BFIN"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
+
+#undef SEND_EARLY_STDERR
+#define SEND_EARLY_STDERR(S) \
+ do { \
+ static const char __attribute__((section(".text"))) __s[] = (S); \
+ const char *__p, *__scratch; \
+ __asm__ ("call 1f;\n1:\n\t" \
+ "%1 = RETS;\n\t" \
+ "%0 = [%3 + 1b@GOT17M4];\n\t" \
+ "%1 = %1 - %0;\n\t" \
+ "%1 = %1 + %2;\n\t" \
+ : "=&d" (__scratch), "=&d" (__p) \
+ : "d" (__s), "a" (dl_boot_got_pointer) : "RETS"); \
+ SEND_STDERR (__p); \
+ { int __t; \
+ for (__t = 0; __t < 0x1000000; __t++) __asm__ __volatile__ (""); } \
+ } while (0)
+
+/* We only support loading FDPIC independently-relocatable shared
+ libraries. It probably wouldn't be too hard to support loading
+ shared libraries that require relocation by the same amount, but we
+ don't know that they exist or would be useful, and the dynamic
+ loader code could leak the whole-library map unless we keeping a
+ bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's
+ keep things simple for now. */
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+ if (((epnt)->e_flags & EF_BFIN_FDPIC) && ! ((epnt)->e_flags & EF_BFIN_PIC)) \
+ (piclib) = 2; \
+ else \
+ { \
+ _dl_internal_error_number = LD_ERROR_NOTDYN; \
+ _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \
+ "\n", (_dl_progname), (libname)); \
+ _dl_close(infile); \
+ return NULL; \
+ } \
+\
+} \
+while (0)
+
+#define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) \
+ __dl_is_special_segment(EPNT, PPNT)
+#define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) \
+ __dl_map_segment (EPNT, PPNT, INFILE, FLAGS)
+
+#include "../fdpic/dl-sysdep.h"
+
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ /* this is never an issue on Blackfin systems, so screw it */
+ return 0;
+}
+
+static __always_inline void
+elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+#if 0
+ Elf32_Rel * rpnt = (void *) rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = DL_RELOC_ADDR (load_off, *reloc_addr);
+ } while (--relative_count);
+#endif
+}
diff --git a/ap/build/uClibc/ldso/ldso/bfin/elfinterp.c b/ap/build/uClibc/ldso/ldso/bfin/elfinterp.c
new file mode 100644
index 0000000..20966fc
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/elfinterp.c
@@ -0,0 +1,353 @@
+/* Blackfin ELF shared library loader suppport
+ Copyright (C) 2003, 2004 Red Hat, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+ Lots of code copied from ../i386/elfinterp.c, so:
+ Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ David Engel, Hongjiu Lu and Mitch D'Souza
+ Copyright (C) 2001-2002, Erik Andersen
+ All rights reserved.
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA. */
+
+#include <sys/cdefs.h> /* __attribute_used__ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+__attribute__((__visibility__("hidden")))
+struct funcdesc_value volatile *
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ struct funcdesc_value funcval;
+ struct funcdesc_value volatile *got_entry;
+ char *symname;
+ struct symbol_ref sym_ref;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname= strtab + symtab[symtab_index].st_name;
+
+ /* Address of GOT entry fix up */
+ got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
+
+ /* Get the address to be used to fill in the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref);
+ if (!new_addr) {
+ new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref);
+ if (!new_addr) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit(1);
+ }
+ }
+
+ funcval.entry_point = new_addr;
+ funcval.got_value = sym_ref.tpnt->loadaddr.got_value;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n",
+ got_entry->entry_point, got_entry->got_value,
+ funcval.entry_point, funcval.got_value,
+ got_entry);
+ }
+ if (1 || !_dl_debug_nofixups) {
+ *got_entry = funcval;
+ }
+#else
+ *got_entry = funcval;
+#endif
+
+ return got_entry;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *) rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (res <0) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (res >0) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+ return 0;
+}
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long reloc_value = 0, *reloc_addr;
+ struct { unsigned long v; } __attribute__((__packed__))
+ *reloc_addr_packed;
+ unsigned long symbol_addr;
+ struct elf_resolve *symbol_tpnt;
+ struct funcdesc_value funcval;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+ struct symbol_ref sym_ref;
+
+ reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
+ __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr));
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
+ symbol_addr = (unsigned long) DL_RELOC_ADDR(tpnt->loadaddr, symtab[symtab_index].st_value);
+ symbol_tpnt = tpnt;
+ } else {
+
+ symbol_addr = (unsigned long)
+ _dl_find_hash(symname, scope, NULL, 0, &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+
+ if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit (1);
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ symbol_tpnt = sym_ref.tpnt;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ {
+ if ((long)reloc_addr_packed & 3)
+ old_val = reloc_addr_packed->v;
+ else
+ old_val = *reloc_addr;
+ }
+ else
+ old_val = 0;
+#endif
+ switch (reloc_type) {
+ case R_BFIN_UNUSED0:
+ break;
+ case R_BFIN_BYTE4_DATA:
+ if ((long)reloc_addr_packed & 3)
+ reloc_value = reloc_addr_packed->v += symbol_addr;
+ else
+ reloc_value = *reloc_addr += symbol_addr;
+ break;
+ case R_BFIN_FUNCDESC_VALUE:
+ funcval.entry_point = (void*)symbol_addr;
+ /* The addend of FUNCDESC_VALUE
+ relocations referencing global
+ symbols must be ignored, because it
+ may hold the address of a lazy PLT
+ entry. */
+ if (ELF_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL)
+ funcval.entry_point += *reloc_addr;
+ reloc_value = (unsigned long)funcval.entry_point;
+ if (symbol_addr)
+ funcval.got_value
+ = symbol_tpnt->loadaddr.got_value;
+ else
+ funcval.got_value = 0;
+ __asm__ ("%0 = %2; %1 = %H2;"
+ : "=m" (*(struct funcdesc_value *)reloc_addr), "=m" (((long *)reloc_addr)[1])
+ : "d" (funcval));
+ break;
+ case R_BFIN_FUNCDESC:
+ if ((long)reloc_addr_packed & 3)
+ reloc_value = reloc_addr_packed->v;
+ else
+ reloc_value = *reloc_addr;
+ if (symbol_addr)
+ reloc_value = (unsigned long)_dl_funcdesc_for
+ ((char *)symbol_addr + reloc_value,
+ symbol_tpnt->loadaddr.got_value);
+ else
+ reloc_value = 0;
+ if ((long)reloc_addr_packed & 3)
+ reloc_addr_packed->v = reloc_value;
+ else
+ *reloc_addr = reloc_value;
+ break;
+ default:
+ return -1;
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail) {
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr);
+ switch (reloc_type) {
+ case R_BFIN_FUNCDESC_VALUE:
+ _dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value);
+ break;
+ case R_BFIN_FUNCDESC:
+ if (! reloc_value)
+ break;
+ _dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)",
+ ((struct funcdesc_value *)reloc_value)->entry_point,
+ ((struct funcdesc_value *)reloc_value)->got_value);
+ break;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt,
+ struct r_scope_elem *scope __attribute__((unused)),
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute__((unused)),
+ char *strtab __attribute__((unused)))
+{
+ int reloc_type;
+ struct funcdesc_value volatile *reloc_addr;
+ struct funcdesc_value funcval;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ reloc_addr = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = (unsigned long)reloc_addr->entry_point;
+#endif
+ switch (reloc_type) {
+ case R_BFIN_UNUSED0:
+ break;
+ case R_BFIN_FUNCDESC_VALUE:
+ funcval = *reloc_addr;
+ funcval.entry_point = (void *) DL_RELOC_ADDR(tpnt->loadaddr, funcval.entry_point);
+ funcval.got_value = tpnt->loadaddr.got_value;
+ *reloc_addr = funcval;
+ break;
+ default:
+ return -1;
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, reloc_addr->entry_point, reloc_addr);
+#endif
+ return 0;
+
+}
+
+void
+_dl_parse_lazy_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+{
+ _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information
+(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
+/* We don't have copy relocs. */
+
+int
+_dl_parse_copy_information
+(struct dyn_elf *rpnt __attribute__((unused)),
+ unsigned long rel_addr __attribute__((unused)),
+ unsigned long rel_size __attribute__((unused)))
+{
+ return 0;
+}
+
+#ifndef IS_IN_libdl
+# include "../../libc/sysdeps/linux/bfin/crtreloc.c"
+#endif
+
diff --git a/ap/build/uClibc/ldso/ldso/bfin/resolve.S b/ap/build/uClibc/ldso/ldso/bfin/resolve.S
new file mode 100644
index 0000000..ae7f4a4
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/bfin/resolve.S
@@ -0,0 +1,77 @@
+ /* Copyright (C) 2003 Red Hat, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA. */
+
+ /* The function below is tail-called by resolver stubs when a
+ lazily-bound function is called. It must preserve all
+ registers that could be used to pass arguments to the actual
+ function. Upon _dl_linux_resolve entry, GR14 holds the
+ address of a lazy PLT entry, so @(GR14,-4) is the lazy
+ relocation number that we have to pass to _dl_linux_resolver.
+ GR15 holds the caller's GOT, from which we extract the
+ elf_resolve* that _dl_linux_resolver needs as well.
+
+ _dl_linux_resolver() figures out where the jump symbol is
+ _really_ supposed to have jumped to and returns that to us.
+ Once we have that, we prepare to tail-call the actual
+ function, clean up after ourselves, restoring the original
+ arguments, then jump to the fixed up address. */
+
+ .text
+ .p2align 4
+
+ .hidden __dl_linux_resolve
+ .global __dl_linux_resolve
+ .type __dl_linux_resolve,@function
+
+__dl_linux_resolve:
+ /* Preserve arguments. */
+ [--SP] = RETS;
+ [--SP] = P0;
+ [--SP] = R0;
+ [--SP] = R1;
+ [--SP] = R2;
+ sp += -12;
+
+ /* Prepare to call _dl_linux_resolver. */
+ R0 = [P3 + 8];
+ /* Not aligned for space reasons. */
+ R1 = W[P1 + -4] (Z);
+ P1 += -2;
+ R1.H = W[P1];
+
+ P3 = R3;
+ CALL __dl_linux_resolver;
+
+ /* Move aside return value that contains the FUNCDESC_VALUE. */
+ P3 = R0;
+ P1 = [P3];
+ P3 = [P3 + 4];
+
+ /* Restore arguments. */
+ sp += 12;
+ R2 = [SP++];
+ R1 = [SP++];
+ R0 = [SP++];
+ P0 = [SP++];
+ RETS = [SP++];
+
+ /* Now jump to the actual function. */
+ JUMP (P1);
+ .size __dl_linux_resolve, . - __dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/c6x/dl-debug.h b/ap/build/uClibc/ldso/ldso/c6x/dl-debug.h
new file mode 100644
index 0000000..d4915bf
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/dl-debug.h
@@ -0,0 +1,49 @@
+/* C6X DSBT ELF shared library loader suppport.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ "R_C6000_NONE", /* 0 */
+ "R_C6000_ABS32",
+ "R_C6000_ABS16",
+ "R_C6000_ABS8",
+ "R_C6000_PCR_S21",
+ "R_C6000_PCR_S12", /* 5 */
+ "R_C6000_PCR_S10",
+ "R_C6000_PCR_S7",
+ "R_C6000_ABS_S16",
+ "R_C6000_ABS_L16",
+ "R_C6000_ABS_H16", /* 10 */
+ "R_C6000_SBR_U15_B",
+ "R_C6000_SBR_U15_H",
+ "R_C6000_SBR_U15_W",
+ "R_C6000_SBR_S16",
+ "R_C6000_SBR_L16_B", /* 15 */
+ "R_C6000_SBR_L16_H",
+ "R_C6000_SBR_L16_W",
+ "R_C6000_SBR_H16_B",
+ "R_C6000_SBR_H16_H",
+ "R_C6000_SBR_H16_W", /* 20 */
+ "R_C6000_SBR_GOT_U15_W",
+ "R_C6000_SBR_GOT_L16_W",
+ "R_C6000_SBR_GOT_H16_W",
+ "R_C6000_DSBT_INDEX",
+ "R_C6000_PREL31", /* 25 */
+ "R_C6000_COPY",
+ "R_C6000_JUMP_SLOT",
+ "R_C6000_SBR_GOT32",
+ "R_C6000_PCR_H16",
+ "R_C6000_PCR_L16", /* 30 */
+#if 0
+ "R_C6000_ALIGN", /* 253 */
+ "R_C6000_FPHEAD", /* 254 */
+ "R_C6000_NOCMP", /* 255 */
+#endif
+};
diff --git a/ap/build/uClibc/ldso/ldso/c6x/dl-inlines.h b/ap/build/uClibc/ldso/ldso/c6x/dl-inlines.h
new file mode 100644
index 0000000..62e1cc9
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/dl-inlines.h
@@ -0,0 +1,120 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Figure out whether the given address is in one of the mapped
+ segments. */
+static __always_inline int
+__dl_addr_in_loadaddr (void *p, struct elf32_dsbt_loadaddr loadaddr)
+{
+ struct elf32_dsbt_loadmap *map = loadaddr.map;
+ int c;
+
+ for (c = 0; c < map->nsegs; c++)
+ if ((void*)map->segs[c].addr <= p
+ && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz)
+ return 1;
+
+ return 0;
+}
+
+/* Figure out how many LOAD segments there are in the given headers,
+ and allocate a block for the load map big enough for them.
+ got_value will be properly initialized later on, with INIT_GOT. */
+static __always_inline int
+__dl_init_loadaddr (struct elf32_dsbt_loadaddr *loadaddr, Elf32_Phdr *ppnt,
+ int pcnt)
+{
+ int count = 0, i;
+ size_t size;
+
+ for (i = 0; i < pcnt; i++)
+ if (ppnt[i].p_type == PT_LOAD)
+ count++;
+
+ size = sizeof (struct elf32_dsbt_loadmap)
+ + sizeof (struct elf32_dsbt_loadseg) * count;
+ loadaddr->map = _dl_malloc (size);
+ if (! loadaddr->map)
+ _dl_exit (-1);
+
+ loadaddr->map->version = 0;
+ loadaddr->map->nsegs = 0;
+
+ return count;
+}
+
+/* Incrementally initialize a load map. */
+static __always_inline void
+__dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr, int maxsegs)
+{
+ struct elf32_dsbt_loadseg *segdata;
+
+ if (loadaddr.map->nsegs == maxsegs)
+ _dl_exit (-1);
+
+ segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
+ segdata->addr = (Elf32_Addr) addr;
+ segdata->p_vaddr = phdr->p_vaddr;
+ segdata->p_memsz = phdr->p_memsz;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ {
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+ }
+#endif
+}
+
+/* Replace an existing entry in the load map. */
+static __always_inline void
+__dl_update_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr)
+{
+ struct elf32_dsbt_loadseg *segdata;
+ void *oldaddr;
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr
+ && loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+ break;
+ if (i == loadaddr.map->nsegs)
+ _dl_exit (-1);
+
+ segdata = loadaddr.map->segs + i;
+ oldaddr = (void *)segdata->addr;
+ _dl_munmap (oldaddr, segdata->p_memsz);
+ segdata->addr = (Elf32_Addr) addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
+#endif
+}
+
+static __always_inline void
+__dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr)
+{
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ _dl_munmap ((void*)loadaddr.map->segs[i].addr,
+ loadaddr.map->segs[i].p_memsz);
+
+ /* _dl_unmap is only called for dlopen()ed libraries, for which
+ calling free() is safe, or before we've completed the initial
+ relocation, in which case calling free() is probably pointless,
+ but still safe. */
+ _dl_free (loadaddr.map);
+}
diff --git a/ap/build/uClibc/ldso/ldso/c6x/dl-startup.h b/ap/build/uClibc/ldso/ldso/c6x/dl-startup.h
new file mode 100644
index 0000000..6ad801f
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/dl-startup.h
@@ -0,0 +1,122 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#undef DL_START
+#define DL_START(X) \
+int \
+_dl_start (unsigned placeholder, \
+ struct elf32_dsbt_loadmap *dl_boot_progmap, \
+ struct elf32_dsbt_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ X)
+
+/*
+ * On entry, the kernel has set up the stack thusly:
+ *
+ * 0(sp) pad0
+ * 4(sp) pad1
+ * 8(sp) argc
+ * 12(sp) argv[0]
+ * ...
+ * (4*(argc+3))(sp) NULL
+ * (4*(argc+4))(sp) envp[0]
+ * ...
+ * NULL
+ *
+ * Register values are unspecified, except:
+ *
+ * B4 --> executable loadmap address
+ * A6 --> interpreter loadmap address
+ * B6 --> dynamic section address
+ * B14 --> our DP setup by kernel
+ *
+ * NB: DSBT index is always 0 for the executable
+ * and 1 for the interpreter
+ */
+
+__asm__(" .text\n"
+ ".globl _start\n"
+ "_start:\n"
+ " B .S2 _dl_start\n"
+ " STW .D2T2 B14, *+B14[1]\n"
+ " ADD .D1X B15,8,A8\n"
+ " ADDKPC .S2 ret_from_dl,B3,2\n"
+ "ret_from_dl:\n"
+ " B .S2X A4\n"
+ " || LDW .D2T2 *+B14[0],B14\n"
+ " ADDKPC .S2 __dl_fini,B0,0\n"
+ " MV .S1X B0,A4\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ "__dl_fini:\n"
+ " LDW .D2T2 *+B14[1],B14\n"
+ " NOP 4\n"
+ " LDW .D2T1 *+B14($GOT(_dl_fini)), A0\n"
+ " NOP 4\n"
+ " BNOP .S2X A0, 5\n");
+
+__asm__(" .text\n"
+ "__c6x_cache_sync:\n"
+ " MVK .S2 330,B0\n"
+ " SWE\n"
+ " NOP\n"
+ " BNOP .S2 B3,5\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ " NOP\n"
+ "\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1)
+
+struct elf32_dsbt_loadmap;
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF_R_TYPE((RELP)->r_info)){ \
+ case R_C6000_ABS_L16: \
+ { \
+ unsigned int opcode = *(REL); \
+ unsigned int v = (SYMBOL) + (RELP)->r_addend; \
+ opcode &= ~0x7fff80; \
+ opcode |= ((v & 0xffff) << 7); \
+ *(REL) = opcode; \
+ } \
+ break; \
+ case R_C6000_ABS_H16: \
+ { \
+ unsigned int opcode = *(REL); \
+ unsigned int v = (SYMBOL) + (RELP)->r_addend; \
+ opcode &= ~0x7fff80; \
+ opcode |= ((v >> 9) & 0x7fff80); \
+ *(REL) = opcode; \
+ } \
+ break; \
+ case R_C6000_ABS32: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ default: \
+ _dl_exit(1); \
+ }
+
+extern void __c6x_cache_sync(unsigned long start, unsigned long end)
+ attribute_hidden;
diff --git a/ap/build/uClibc/ldso/ldso/c6x/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/c6x/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/c6x/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/c6x/dl-sysdep.h
new file mode 100644
index 0000000..0dbe8bf
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/dl-sysdep.h
@@ -0,0 +1,223 @@
+/* Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <bits/elf-dsbt.h>
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA 1
+
+/* JMPREL relocs are inside the DT_RELA table. */
+/* Actually looks like a linker bug sets DT_JMPREL anyway */
+#define ELF_MACHINE_PLTREL_OVERLAP 1
+
+#undef DL_NO_COPY_RELOCS
+
+#define HAVE_DL_INLINES_H
+
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_TI_C6000
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "C6000"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+
+extern int _dl_linux_resolve(void) attribute_hidden;
+
+struct funcdesc_ht;
+struct elf32_dsbt_loadaddr;
+
+/* We must force strings used early in the bootstrap into the text
+ segment (const data), such that they are referenced relative to
+ the DP register rather than through the GOT which will not have
+ been relocated when these are used. */
+#undef SEND_EARLY_STDERR
+#define SEND_EARLY_STDERR(S) \
+ do { static char __s[] = (S); SEND_STDERR (__s); } while (0)
+
+#define DL_LOADADDR_TYPE struct elf32_dsbt_loadaddr
+
+#define DL_RELOC_ADDR(LOADADDR, ADDR) \
+ ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
+
+#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+ do { \
+ struct elf32_dsbt_loadmap *map; \
+ map = dl_boot_ldsomap ?: dl_boot_progmap; \
+ if (map->version != 0) { \
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \
+ _dl_exit(-1); \
+ } \
+ if (map->nsegs < 2) { \
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \
+ _dl_exit(-1); \
+ } \
+ (LOADADDR).map = map; \
+ } while(0)
+
+#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+ do { \
+ if (dl_boot_progmap->version != 0) { \
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \
+ _dl_exit(-1); \
+ } \
+ if (dl_boot_progmap->nsegs < 2) { \
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \
+ _dl_exit(-1); \
+ } \
+ (LOADADDR).map = dl_boot_progmap; \
+ } while(0)
+
+#define DL_INIT_LOADADDR_EXTRA_DECLS \
+ int dl_init_loadaddr_load_count;
+
+#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+ (dl_init_loadaddr_load_count = \
+ __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
+
+#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
+ dl_init_loadaddr_load_count))
+
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
+
+#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
+ (__dl_loadaddr_unmap ((LOADADDR)))
+
+#define DL_LIB_UNMAP(LIB, LEN) \
+ (__dl_loadaddr_unmap ((LIB)->loadaddr))
+
+#define DL_LOADADDR_BASE(LOADADDR) \
+ ((LOADADDR).map->dsbt_table)
+
+#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+ (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
+
+
+/* We only support loading DSBT relocatable shared libraries.
+ It probably wouldn't be too hard to support loading statically
+ linked executables that require relocation.*/
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+ (piclib) = 2; \
+} \
+while (0)
+
+/* We want want to apply all relocations in the interpreter during
+ bootstrap. Because of this, we have to skip the interpreter
+ relocations in _dl_parse_relocation_information(), see
+ elfinterp.c. */
+#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
+
+#ifdef __NR_pread64
+#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
+ (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
+#endif
+
+#define DL_GET_READY_TO_RUN_EXTRA_PARMS \
+ , struct elf32_dsbt_loadmap *dl_boot_progmap \
+ , struct elf32_dsbt_loadmap *dl_boot_ldsomap
+#define DL_GET_READY_TO_RUN_EXTRA_ARGS \
+ , dl_boot_progmap \
+ , dl_boot_ldsomap
+
+
+/*
+ * Compute the GOT address.
+ * Also setup program and interpreter DSBT table entries.
+ */
+#define DL_BOOT_COMPUTE_GOT(GOT) \
+ do { \
+ unsigned long *ldso_dsbt, *prog_dsbt; \
+ ldso_dsbt = dl_boot_ldsomap->dsbt_table; \
+ prog_dsbt = dl_boot_progmap->dsbt_table; \
+ ldso_dsbt[0] = prog_dsbt[0] = (unsigned long)prog_dsbt; \
+ ldso_dsbt[1] = prog_dsbt[1] = (unsigned long)ldso_dsbt; \
+ (GOT) = ldso_dsbt + dl_boot_ldsomap->dsbt_size; \
+ } while(0)
+
+#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
+ ((dpnt) = dl_boot_ldso_dyn_pointer)
+
+/* Define this to declare the library offset. */
+#define DL_DEF_LIB_OFFSET
+
+/* Define this to get the library offset. */
+#define DL_GET_LIB_OFFSET() 0
+
+/* Define this to set the library offset. */
+#define DL_SET_LIB_OFFSET(offset)
+
+/* Define this to get the real object's runtime address. */
+#define DL_GET_RUN_ADDR(loadaddr, mapaddr) (loadaddr)
+
+#ifdef __USE_GNU
+# include <link.h>
+#else
+# define __USE_GNU
+# include <link.h>
+# undef __USE_GNU
+#endif
+
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ /* this is never an issue on DSBT systems */
+ return 0;
+}
+
+static __always_inline void
+elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+}
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ PLT entries should not be allowed to define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_C6000_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_C6000_COPY) * ELF_RTYPE_CLASS_COPY))
+
+#define ARCH_NUM 3
+#define DT_DSBT_BASE_IDX (DT_NUM + OS_NUM)
+#define DT_DSBT_SIZE_IDX (DT_NUM + OS_NUM + 1)
+#define DT_DSBT_INDEX_IDX (DT_NUM + OS_NUM + 2)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+do { \
+if (dpnt->d_tag == DT_C6000_DSBT_BASE) \
+ dynamic[DT_DSBT_BASE_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_C6000_DSBT_SIZE) \
+ dynamic[DT_DSBT_SIZE_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_C6000_DSBT_INDEX) \
+ dynamic[DT_DSBT_INDEX_IDX] = dpnt->d_un.d_val; \
+} while (0)
diff --git a/ap/build/uClibc/ldso/ldso/c6x/elfinterp.c b/ap/build/uClibc/ldso/ldso/c6x/elfinterp.c
new file mode 100644
index 0000000..3772f90
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/elfinterp.c
@@ -0,0 +1,300 @@
+/* TI C64X DSBT ELF shared library loader suppport
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Contributed by Mark Salter <msalter@redhat.com>
+ *
+ * Borrowed heavily from frv arch:
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Lots of code copied from ../i386/elfinterp.c, so:
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+extern void __c6x_cache_sync(unsigned long start, unsigned long end)
+ attribute_hidden;
+
+static void
+_dl_c6x_flush_relocs(struct elf32_dsbt_loadmap *map)
+{
+ unsigned long s, e;
+ s = map->segs[0].addr;
+ e = s + map->segs[0].p_memsz;
+ __c6x_cache_sync(s, e);
+ s = map->segs[1].addr;
+ e = s + map->segs[1].p_memsz;
+ __c6x_cache_sync(s, e);
+}
+
+
+attribute_hidden
+char *
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of GOT entry fix up */
+ got_addr = (char **) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
+
+ /* Get the address to be used to fill in the GOT entry. */
+ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt,
+ ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (res <0) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (res >0) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+ _dl_c6x_flush_relocs(tpnt->loadaddr.map);
+ return 0;
+}
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr, sym_val;
+ long reloc_addend;
+ unsigned long old_val, new_val;
+
+ reloc_addr = (unsigned long *)(intptr_t)
+ DL_RELOC_ADDR (tpnt->loadaddr, rpnt->r_offset);
+
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ reloc_addend = rpnt->r_addend;
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
+ symbol_addr = (unsigned long)
+ DL_RELOC_ADDR (tpnt->loadaddr, symtab[symtab_index].st_value);
+ } else {
+ symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
+ scope, tpnt, elf_machine_type_class(reloc_type),
+ NULL);
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+
+ if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, strtab + symtab[symtab_index].st_name);
+ _dl_exit (1);
+ }
+ }
+ old_val = *reloc_addr;
+ sym_val = symbol_addr + reloc_addend;
+
+ switch (reloc_type) {
+ case R_C6000_NONE:
+ break;
+ case R_C6000_ABS32:
+ case R_C6000_JUMP_SLOT:
+ new_val = sym_val;
+ *reloc_addr = sym_val;
+ break;
+ case R_C6000_DSBT_INDEX:
+ new_val = (old_val & ~0x007fff00) | ((tpnt->loadaddr.map->dsbt_index & 0x7fff) << 8);
+ *reloc_addr = new_val;
+ break;
+ case R_C6000_ABS_L16:
+ new_val = (old_val & ~0x007fff80) | ((sym_val & 0xffff) << 7);
+ *reloc_addr = new_val;
+ break;
+ case R_C6000_ABS_H16:
+ new_val = (old_val & ~0x007fff80) | ((sym_val >> 9) & 0x007fff80);
+ *reloc_addr = new_val;
+ break;
+ case R_C6000_PCR_S21:
+ new_val = sym_val - (((unsigned long)reloc_addr) & ~31);
+ *reloc_addr = (old_val & ~0x0fffff80) | (((new_val >> 2) & 0x1fffff) << 7);
+ break;
+ case R_C6000_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\n%s move %d bytes from %x to %x",
+ symname, symtab[symtab_index].st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ symtab[symtab_index].st_size);
+ }
+ return 0;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail && reloc_type != R_C6000_NONE) {
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, new_val, reloc_addr);
+ }
+#endif
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt,
+ struct dyn_elf *scope attribute_unused,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab attribute_unused,
+ char *strtab attribute_unused)
+{
+ int reloc_type;
+ unsigned long *reloc_addr;
+ unsigned long old_val;
+
+ reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ old_val = *reloc_addr;
+
+ switch (reloc_type) {
+ case R_C6000_NONE:
+ break;
+ case R_C6000_JUMP_SLOT:
+ *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, old_val);
+ break;
+ default:
+ return -1;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+void
+_dl_parse_lazy_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+{
+ _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
+/* We don't have copy relocs. */
+int
+_dl_parse_copy_information
+(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return 0;
+}
+
diff --git a/ap/build/uClibc/ldso/ldso/c6x/resolve.S b/ap/build/uClibc/ldso/ldso/c6x/resolve.S
new file mode 100644
index 0000000..ce3cbe7
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/c6x/resolve.S
@@ -0,0 +1,68 @@
+;;
+;; Copyright (C) 2010 Texas Instruments Incorporated
+;; Mark Salter <msalter@redhat.com>
+;;
+;; Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+;;
+
+;; The function below is tail-called by resolver stubs when a
+;; lazily-bound function is called. It must preserve all
+;; registers that could be used to pass arguments to the actual
+;; function.
+
+;; _dl_linux_resolver() figures out where the jump symbol is
+;; _really_ supposed to have jumped to and returns that to us.
+;; Once we have that, we prepare to tail-call the actual
+;; function, clean up after ourselves, restoring the original
+;; arguments, then jump to the fixed up address. */
+
+; resolver stub - called from PLT to resolve target address and update GOT
+;
+; B0 : reloc offset (bytes from DT_RELPLT)
+; B1 : module pointer, loaded from GOT[1]
+; DP : caller's DP
+; A4,B4, etc: callee's arguments
+; B3 : return address
+
+ .text
+ .align 5
+ .global _dl_linux_resolve
+_dl_linux_resolve:
+ stw .d2t2 B14, *B15--[2]
+ stdw .d2t1 A15:A14, *B15--
+ stdw .d2t2 B13:B12, *B15--
+ stdw .d2t1 A13:A12, *B15--
+ stdw .d2t2 B11:B10, *B15--
+ stdw .d2t1 A11:A10, *B15--
+ stdw .d2t2 B9:B8, *B15--
+ stdw .d2t1 A9:A8, *B15--
+ stdw .d2t2 B7:B6, *B15--
+ stdw .d2t1 A7:A6, *B15--
+ stdw .d2t2 B5:B4, *B15--
+ stdw .d2t1 A5:A4, *B15--
+ stdw .d2t2 B3:B2, *B15--
+ stdw .d2t1 A3:A2, *B15--
+
+ ; call lookup routine
+ MV .S1X B1, A4 ; arg 1: module id
+|| MV .S2 B0,B4 ; arg 2: reloc offset
+ CALLP .S2 _dl_linux_resolver, B3 ; returns &f in A4
+ MV .S2X A4,B0 ; &f
+
+ lddw .d2t1 *++B15, A3:A2
+ lddw .d2t2 *++B15, B3:B2
+ lddw .d2t1 *++B15, A5:A4
+ lddw .d2t2 *++B15, B5:B4
+ lddw .d2t1 *++B15, A7:A6
+ lddw .d2t2 *++B15, B7:B6
+ lddw .d2t1 *++B15, A9:A8
+ lddw .d2t2 *++B15, B9:B8
+ lddw .d2t1 *++B15, A11:A10
+ lddw .d2t2 *++B15, B11:B10
+ lddw .d2t1 *++B15, A13:A12
+ lddw .d2t2 *++B15, B13:B12
+ lddw .d2t1 *++B15, A15:A14
+ ldw .d2t2 *++B15[2], B14
+
+ B .S2 B0 ; tail-call f
+ NOP 5
diff --git a/ap/build/uClibc/ldso/ldso/cris/dl-debug.h b/ap/build/uClibc/ldso/ldso/cris/dl-debug.h
new file mode 100644
index 0000000..dcd23ed
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/cris/dl-debug.h
@@ -0,0 +1,42 @@
+/*
+ * CRIS ELF shared library loader support.
+ *
+ * Program to load an elf binary on a linux system, and run it.
+ * References to symbols in sharable libraries can be resolved
+ * by either an ELF sharable library or a linux style of shared
+ * library.
+ *
+ * Copyright (C) 2002-2004, Axis Communications AB
+ * All rights reserved
+ *
+ * Author: Tobias Anderberg, <tobiasa@axis.com>
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ [0] "R_CRIS_NONE", "R_CRIS_8", "R_CRIS_16", "R_CRIS_32",
+ [4] "R_CRIS_8_PCREL", "R_CRIS_16_PCREL", "R_CRIS_32_PCREL", "R_CRIS_GNU_VTINHERIT",
+ [8] "R_CRIS_GNU_VTENTRY", "R_CRIS_COPY", "R_CRIS_GLOB_DAT", "R_CRIS_JUMP_SLOT",
+ [16] "R_CRIS_RELATIVE", "R_CRIS_16_GOT", "R_CRIS_32_GOT", "R_CRIS_16_GOTPLT",
+ [32] "R_CRIS_32_GOTPLT", "R_CRIS_32_GOTREL", "R_CRIS_32_PLT_GOTREL", "R_CRIS_32_PLT_PCREL",
+};
diff --git a/ap/build/uClibc/ldso/ldso/cris/dl-startup.h b/ap/build/uClibc/ldso/ldso/cris/dl-startup.h
new file mode 100644
index 0000000..57f84ea
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/cris/dl-startup.h
@@ -0,0 +1,81 @@
+/*
+ * Architecture specific code used by dl-startup.c
+ */
+
+/* This code fixes the stack pointer so that the dynamic linker
+ * can find argc, argv and auxvt (Auxillary Vector Table). */
+#ifdef __arch_v32
+
+__asm__("" \
+" .text\n" \
+" .globl _start\n" \
+" .type _start,@function\n" \
+"_start:\n" \
+" move.d $sp,$r10\n" \
+" lapc _dl_start,$r9\n" \
+" jsr $r9\n" \
+" nop\n" \
+" moveq 0,$r8\n" \
+" jump $r10\n" \
+" move $r8,$srp\n" \
+" .size _start,.-_start\n" \
+" .previous\n" \
+);
+
+#else
+
+__asm__("" \
+" .text\n" \
+" .globl _start\n" \
+" .type _start,@function\n" \
+"_start:\n" \
+" move.d $sp,$r10\n" \
+" move.d $pc,$r9\n" \
+" add.d _dl_start - ., $r9\n" \
+" jsr $r9\n" \
+" moveq 0,$r8\n" \
+" move $r8,$srp\n" \
+" jump $r10\n" \
+" .size _start,.-_start\n" \
+" .previous\n" \
+);
+
+#endif /* __arch_v32 */
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1)
+
+
+/* We can't call functions earlier in the dl startup process */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
+{
+ switch (ELF_R_TYPE(rpnt->r_info)) {
+ case R_CRIS_GLOB_DAT:
+ case R_CRIS_JUMP_SLOT:
+ case R_CRIS_32:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_CRIS_16_PCREL:
+ *(short *) *reloc_addr = symbol_addr + rpnt->r_addend - *reloc_addr - 2;
+ break;
+ case R_CRIS_32_PCREL:
+ *reloc_addr = symbol_addr + rpnt->r_addend - *reloc_addr - 4;
+ break;
+ case R_CRIS_NONE:
+ break;
+ case R_CRIS_RELATIVE:
+ *reloc_addr = load_addr + rpnt->r_addend;
+ break;
+ default:
+ _dl_exit(1);
+ break;
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/cris/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/cris/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/cris/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/cris/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/cris/dl-sysdep.h
new file mode 100644
index 0000000..e454c10
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/cris/dl-sysdep.h
@@ -0,0 +1,109 @@
+/* CRIS can never use Elf32_Rel relocations. */
+#define ELF_USES_RELOCA
+
+#include <elf.h>
+
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+}
+
+/* Defined some magic numbers that this ld.so should accept. */
+#define MAGIC1 EM_CRIS
+#undef MAGIC2
+#define ELF_TARGET "CRIS"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
+
+/* The union of reloc-type-classes where the reloc TYPE is a member.
+
+ TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a
+ relocation for a PLT entry, that is, for which a PLT entry should not
+ be allowed to define the value. The GNU linker for CRIS can merge a
+ .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT),
+ so we need to match both these reloc types.
+
+ TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed
+ to resolve to one of the main executable's symbols, as for a COPY
+ reloc. */
+#define elf_machine_type_class(type) \
+ ((((((type) == R_CRIS_JUMP_SLOT)) \
+ || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
+
+static __always_inline Elf32_Addr
+elf_machine_dynamic(void)
+{
+ /* Don't just set this to an asm variable "r0" since that's not logical
+ (like, the variable is uninitialized and the register is fixed) and
+ may make GCC trip over itself doing register allocation. Yes, I'm
+ paranoid. Why do you ask? */
+ Elf32_Addr *got;
+
+ __asm__ ("move.d $r0,%0" : "=rm" (got));
+ return *got;
+}
+
+/* Return the run-time load address of the shared object. We do it like
+ m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry
+ for it, and peeking into the GOT table, which is set to the link-time
+ file-relative symbol value (regardless of whether the target is REL or
+ RELA). We subtract this link-time file-relative value from the "local"
+ value we calculate from GOT position and GOT offset. FIXME: Perhaps
+ there's some other symbol we could use, that we don't *have* to force a
+ GOT entry for. */
+
+static __always_inline Elf32_Addr
+elf_machine_load_address(void)
+{
+ Elf32_Addr gotaddr_diff;
+
+#ifdef __arch_v32
+ extern char ___CRISv32_dummy[] __asm__ ("_dl_start");
+
+ __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t"
+ "lapc _dl_start,%0\n\t"
+ "sub.d [$acr],%0"
+ /* For v32, we need to force GCC to have R0 loaded with
+ _GLOBAL_OFFSET_TABLE_ at this point, which might not
+ otherwise have happened in the caller. (For v10, it's
+ loaded for non-global variables too, so we don't need
+ anything special there.) We accomplish this by faking the
+ address of a global variable (as seen by GCC) as input to
+ the asm; that address calculation goes through the GOT.
+ Use of this function happens before we've filled in the
+ GOT, so the address itself will not be correctly
+ calculated, therefore we don't use any symbol whose
+ address may be re-used later on. Let's just reuse the
+ _dl_start symbol, faking it as a global by renaming it as
+ another variable through an asm. */
+ : "=r" (gotaddr_diff)
+ : "g" (___CRISv32_dummy)
+ : "acr");
+#else
+ __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t"
+ "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff));
+#endif
+ return gotaddr_diff;
+}
+
+static __always_inline void
+elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela *rpnt = (void *)rel_addr;
+
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr =
+ (void *)(load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/cris/elfinterp.c b/ap/build/uClibc/ldso/ldso/cris/elfinterp.c
new file mode 100644
index 0000000..5ad3025
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/cris/elfinterp.c
@@ -0,0 +1,294 @@
+/*
+ * CRIS ELF shared library loader support.
+ *
+ * Program to load an elf binary on a linux system, and run it.
+ * References to symbols in sharable libraries can be resolved
+ * by either an ELF sharable library or a linux style of shared
+ * library.
+ *
+ * Copyright (C) 2002-2004, Axis Communications AB
+ * All rights reserved
+ *
+ * Author: Tobias Anderberg, <tobiasa@axis.com>
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+/* Defined in resolve.S. */
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ int symtab_index;
+ char *strtab;
+ char *symname;
+ char *new_addr;
+ char *rel_addr;
+ char **got_addr;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *this_reloc;
+ unsigned long instr_addr;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ int symtab_index;
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
+ rel_size /= sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ /* Pass over to actual relocation function. */
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n",
+ _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n",
+ reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+ struct symbol_ref sym_ref;
+
+ reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (symtab_index) {
+ if (symtab[symtab_index].st_shndx != SHN_UNDEF &&
+ ELF_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL) {
+ symbol_addr = (unsigned long)tpnt->loadaddr;
+ } else {
+ symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ }
+
+ if (unlikely(!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+ symbol_addr += rpnt->r_addend;
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_CRIS_NONE:
+ break;
+ case R_CRIS_GLOB_DAT:
+ case R_CRIS_JUMP_SLOT:
+ case R_CRIS_32:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_CRIS_COPY:
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\n%s move %d bytes from %x to %x",
+ symname, symtab[symtab_index].st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ symtab[symtab_index].st_size);
+ break;
+ case R_CRIS_RELATIVE:
+ *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+ break;
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ unsigned long *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ /* Don't care about these, just keep the compiler happy. */
+ (void)scope;
+ (void)symtab;
+ (void)strtab;
+
+ reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_CRIS_NONE:
+ break;
+ case R_CRIS_JUMP_SLOT:
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+/* External interface to the generic part of the dynamic linker. */
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/cris/resolve.S b/ap/build/uClibc/ldso/ldso/cris/resolve.S
new file mode 100644
index 0000000..9ca27b5
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/cris/resolve.S
@@ -0,0 +1,89 @@
+/*
+ * This function is _not_ called directly. It is jumped to from PLT when
+ * attempting to use a symbol that has not yet been resolved. The first time a
+ * jump symbol (such as a function call inside a shared library) is used
+ * (before it gets resolved) it will jump here. When we get called the stack
+ * contains reloc_offset and tpnt is in MOF.
+ *
+ * We save all the registers, setup R10 and R11 with the right arguments then
+ * call _dl_linux_resolver(tpnt, reloc_offset). _dl_linux_resolver() figures
+ * out where the jump symbol is _really_ supposed to have jumped to and returns
+ * that to us. Once we have that, we overwrite tpnt with this fixed up
+ * address. We then clean up after ourselves, put all the registers back how we
+ * found them, then we jump to where the fixed up address, which is where the
+ * jump symbol that got us here really wanted to jump to in the first place.
+ */
+
+.globl _dl_linux_resolve
+.type _dl_linux_resolve,@function
+
+#ifdef __arch_v32
+
+_dl_linux_resolve:
+ subq 4,$sp
+ move.d $r0,[$sp]
+ subq 4,$sp
+ move.d $r13,[$sp]
+ subq 4,$sp
+ move.d $r12,[$sp]
+ subq 4,$sp
+ move.d $r11,[$sp]
+ subq 4,$sp
+ addoq 5*4,$sp,$acr
+ move.d $r10,[$sp]
+ subq 4,$sp
+ move $mof,$r10
+ move.d $r9,[$sp]
+ subq 4,$sp
+ move.d [$acr],$r11
+ move $srp,[$sp]
+ lapc _GLOBAL_OFFSET_TABLE_,$r0
+ move.d _dl_linux_resolver:PLTG,$r9
+ add.d $r0,$r9
+ jsr $r9
+ nop
+ move.d $r10,$acr
+ move [$sp+],$srp
+ move.d [$sp+],$r9
+ move.d [$sp+],$r10
+ move.d [$sp+],$r11
+ move.d [$sp+],$r12
+ move.d [$sp+],$r13
+ move.d [$sp+],$r0
+ jump $acr
+ addq 4,$sp
+
+#else
+
+_dl_linux_resolve:
+ push $r13
+ push $r12
+ push $r11
+ push $r10
+ push $r9
+ push $r0
+ push $srp
+ move.d [$sp+7*4],$r11
+ move $mof,$r10
+#ifdef __PIC__
+ move.d $pc,$r0
+ sub.d .:GOTOFF,$r0
+ move.d _dl_linux_resolver:PLTG,$r9
+ add.d $r0,$r9
+ jsr $r9
+#else
+ jsr _dl_linux_resolver
+#endif
+ move.d $r10,[$sp+7*4]
+ pop $srp
+ pop $r0
+ pop $r9
+ pop $r10
+ pop $r11
+ pop $r12
+ pop $r13
+ jump [$sp+]
+
+#endif /* __arch_v32 */
+
+ .size _dl_linux_resolve, . - _dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/dl-array.c b/ap/build/uClibc/ldso/ldso/dl-array.c
new file mode 100644
index 0000000..dabb466
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-array.c
@@ -0,0 +1,84 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * This file contains the helper routines to run init and fini functions.
+ *
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+static void _dl_run_array_forward(unsigned long array, unsigned long size,
+ DL_LOADADDR_TYPE loadaddr)
+{
+ if (array != 0) {
+ unsigned int j;
+ unsigned int jm;
+ ElfW(Addr) *addrs;
+ jm = size / sizeof (ElfW(Addr));
+ addrs = (ElfW(Addr) *) DL_RELOC_ADDR(loadaddr, array);
+ for (j = 0; j < jm; ++j) {
+ void (*dl_elf_func) (void);
+ dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, loadaddr, (void (*)(void)));
+ }
+ }
+}
+
+void _dl_run_init_array(struct elf_resolve *tpnt);
+void _dl_run_init_array(struct elf_resolve *tpnt)
+{
+ _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY],
+ tpnt->dynamic_info[DT_INIT_ARRAYSZ],
+ tpnt->loadaddr);
+}
+
+void _dl_app_init_array(void);
+void _dl_app_init_array(void)
+{
+ _dl_run_init_array(_dl_loaded_modules);
+}
+
+void _dl_run_fini_array(struct elf_resolve *tpnt);
+void _dl_run_fini_array(struct elf_resolve *tpnt)
+{
+ if (tpnt->dynamic_info[DT_FINI_ARRAY]) {
+ ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI_ARRAY]);
+ unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr)));
+ while (i-- > 0) {
+ void (*dl_elf_func) (void);
+ dl_elf_func = (void (*)(void)) (intptr_t) array[i];
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void (*)(void)));
+ }
+ }
+}
+
+void _dl_app_fini_array(void);
+void _dl_app_fini_array(void)
+{
+ _dl_run_fini_array(_dl_loaded_modules);
+}
+
diff --git a/ap/build/uClibc/ldso/ldso/dl-debug.c b/ap/build/uClibc/ldso/ldso/dl-debug.c
new file mode 100644
index 0000000..1758bc3
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-debug.c
@@ -0,0 +1,162 @@
+/* vi: set sw=4 ts=4: */
+/* common debug code for ELF shared library loader
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ * Copyright (C) 2002-2004, Axis Communications AB
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
+ * Copyright (C) 2001-2002 David A. Schleef
+ * Copyright (C) 2004 Joakim Tjernlund
+ * Copyright (C) 2002, Stefan Allius <allius@atecom.com> and
+ * Eddie C. Dost <ecd@atecom.com>
+ * Copyright (C) 2003, 2004, 2005 Paul Mundt <lethal@linux-sh.org>
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+#if defined (__SUPPORT_LD_DEBUG__)
+
+/* include the arch-specific _dl_reltypes_tab */
+#include "dl-debug.h"
+
+static const char *_dl_reltypes(int type)
+{
+ static char buf[50];
+ const char *str;
+ int tabsize;
+
+ tabsize = (int)(sizeof(_dl_reltypes_tab) / sizeof(_dl_reltypes_tab[0]));
+
+ if (type >= tabsize || (str = _dl_reltypes_tab[type]) == NULL)
+ str = _dl_simple_ltoa(buf, (unsigned long)type);
+
+ return str;
+}
+static void debug_sym(ElfW(Sym) *symtab, char *strtab, int symtab_index)
+{
+ if (!_dl_debug_symbols || !symtab_index)
+ return;
+
+ _dl_dprintf(_dl_debug_file,
+ "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
+ strtab + symtab[symtab_index].st_name,
+ symtab[symtab_index].st_value,
+ symtab[symtab_index].st_size,
+ symtab[symtab_index].st_info,
+ symtab[symtab_index].st_other,
+ symtab[symtab_index].st_shndx);
+}
+
+static void debug_reloc(ElfW(Sym) *symtab, char *strtab, ELF_RELOC *rpnt)
+{
+ if (!_dl_debug_reloc)
+ return;
+
+ if (_dl_debug_symbols) {
+ _dl_dprintf(_dl_debug_file, "\n\t");
+ } else {
+ int symtab_index;
+ const char *sym;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
+
+ _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
+ }
+
+ _dl_dprintf(_dl_debug_file, "%s\toffset=%x",
+ _dl_reltypes(ELF_R_TYPE(rpnt->r_info)),
+ rpnt->r_offset);
+#ifdef ELF_USES_RELOCA
+ _dl_dprintf(_dl_debug_file, "\taddend=%x", rpnt->r_addend);
+#endif
+ _dl_dprintf(_dl_debug_file, "\n");
+}
+
+#else
+
+#define debug_sym(symtab, strtab, symtab_index)
+#define debug_reloc(symtab, strtab, rpnt)
+
+#endif /* __SUPPORT_LD_DEBUG__ */
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+static void
+internal_function
+_dl_debug_lookup (const char *undef_name, struct elf_resolve *undef_map,
+ const ElfW(Sym) *ref, struct symbol_ref *value, int type_class)
+{
+#ifdef SHARED
+ unsigned long symbol_addr;
+
+ if (_dl_trace_prelink)
+ {
+ int conflict = 0;
+ struct symbol_ref val = { ref, NULL };
+
+ if ((_dl_trace_prelink_map == NULL
+ || _dl_trace_prelink_map == _dl_loaded_modules)
+ && undef_map != _dl_loaded_modules)
+ {
+ symbol_addr = (unsigned long)
+ _dl_find_hash(undef_name, &undef_map->symbol_scope,
+ undef_map, type_class, &val);
+
+ if (val.sym != value->sym || val.tpnt != value->tpnt)
+ conflict = 1;
+ }
+
+ if (value->sym
+ && (__builtin_expect (ELF_ST_TYPE(value->sym->st_info)
+ == STT_TLS, 0)))
+ type_class = 4;
+
+ if (conflict
+ || _dl_trace_prelink_map == undef_map
+ || _dl_trace_prelink_map == NULL
+ || type_class == 4)
+ {
+ _dl_dprintf (1, "%s %x %x -> %x %x ",
+ conflict ? "conflict" : "lookup",
+ (size_t) undef_map->mapaddr,
+ (size_t) (((ElfW(Addr)) ref) - undef_map->mapaddr),
+ (size_t) (value->tpnt ? value->tpnt->mapaddr : 0),
+ (size_t) (value->sym ? value->sym->st_value : 0));
+ if (conflict)
+ _dl_dprintf (1, "x %x %x ",
+ (size_t) (val.tpnt ? val.tpnt->mapaddr : 0),
+ (size_t) (val.sym ? val.sym->st_value : 0));
+ _dl_dprintf (1, "/%x %s\n", type_class, undef_name);
+ }
+}
+#endif
+}
+
+#else
+#define _dl_debug_lookup(undef_name, undef_map, ref, value, type_class)
+#endif
diff --git a/ap/build/uClibc/ldso/ldso/dl-elf.c b/ap/build/uClibc/ldso/ldso/dl-elf.c
new file mode 100644
index 0000000..9e2a12c
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-elf.c
@@ -0,0 +1,1116 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * This file contains the helper routines to load an ELF shared
+ * library into memory and add the symbol table info to the chain.
+ *
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+#ifdef __LDSO_CACHE_SUPPORT__
+
+static caddr_t _dl_cache_addr = NULL;
+static size_t _dl_cache_size = 0;
+
+int _dl_map_cache(void)
+{
+ int fd;
+ struct stat st;
+ header_t *header;
+ libentry_t *libent;
+ int i, strtabsize;
+
+ if (_dl_cache_addr == MAP_FAILED)
+ return -1;
+ else if (_dl_cache_addr != NULL)
+ return 0;
+
+ if (_dl_stat(LDSO_CACHE, &st)
+ || (fd = _dl_open(LDSO_CACHE, O_RDONLY|O_CLOEXEC, 0)) < 0) {
+ _dl_cache_addr = MAP_FAILED; /* so we won't try again */
+ return -1;
+ }
+
+ _dl_cache_size = st.st_size;
+ _dl_cache_addr = _dl_mmap(0, _dl_cache_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0);
+ _dl_close(fd);
+ if (_dl_mmap_check_error(_dl_cache_addr)) {
+ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
+ _dl_progname, __LINE__, LDSO_CACHE);
+ return -1;
+ }
+
+ header = (header_t *) _dl_cache_addr;
+
+ if (_dl_cache_size < sizeof(header_t) ||
+ _dl_memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)
+ || _dl_memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)
+ || _dl_cache_size <
+ (sizeof(header_t) + header->nlibs * sizeof(libentry_t))
+ || _dl_cache_addr[_dl_cache_size - 1] != '\0')
+ {
+ _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname,
+ LDSO_CACHE);
+ goto fail;
+ }
+
+ strtabsize = _dl_cache_size - sizeof(header_t) -
+ header->nlibs * sizeof(libentry_t);
+ libent = (libentry_t *) & header[1];
+
+ for (i = 0; i < header->nlibs; i++) {
+ if (libent[i].sooffset >= strtabsize ||
+ libent[i].liboffset >= strtabsize)
+ {
+ _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname, LDSO_CACHE);
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ _dl_munmap(_dl_cache_addr, _dl_cache_size);
+ _dl_cache_addr = MAP_FAILED;
+ return -1;
+}
+
+int _dl_unmap_cache(void)
+{
+ if (_dl_cache_addr == NULL || _dl_cache_addr == MAP_FAILED)
+ return -1;
+
+#if 1
+ _dl_munmap(_dl_cache_addr, _dl_cache_size);
+ _dl_cache_addr = NULL;
+#endif
+
+ return 0;
+}
+#endif
+
+
+void
+_dl_protect_relro (struct elf_resolve *l)
+{
+ ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR(l->loadaddr, l->relro_addr);
+ ElfW(Addr) start = (base & PAGE_ALIGN);
+ ElfW(Addr) end = ((base + l->relro_size) & PAGE_ALIGN);
+ _dl_if_debug_dprint("RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end);
+ if (start != end &&
+ _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
+ _dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname);
+ _dl_exit(0);
+ }
+}
+
+/* This function's behavior must exactly match that
+ * in uClibc/ldso/util/ldd.c */
+static struct elf_resolve *
+search_for_named_library(const char *name, unsigned rflags, const char *path_list,
+ struct dyn_elf **rpnt)
+{
+ char *path, *path_n, *mylibname;
+ struct elf_resolve *tpnt;
+ int done;
+
+ if (path_list==NULL)
+ return NULL;
+
+ /* We need a writable copy of this string, but we don't
+ * need this allocated permanently since we don't want
+ * to leak memory, so use alloca to put path on the stack */
+ done = _dl_strlen(path_list);
+ path = alloca(done + 1);
+
+ /* another bit of local storage */
+ mylibname = alloca(2050);
+
+ _dl_memcpy(path, path_list, done+1);
+
+ /* Unlike ldd.c, don't bother to eliminate double //s */
+
+ /* Replace colons with zeros in path_list */
+ /* : at the beginning or end of path maps to CWD */
+ /* :: anywhere maps CWD */
+ /* "" maps to CWD */
+ done = 0;
+ path_n = path;
+ do {
+ if (*path == 0) {
+ *path = ':';
+ done = 1;
+ }
+ if (*path == ':') {
+ *path = 0;
+ if (*path_n)
+ _dl_strcpy(mylibname, path_n);
+ else
+ _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
+ _dl_strcat(mylibname, "/");
+ _dl_strcat(mylibname, name);
+ if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
+ return tpnt;
+ path_n = path+1;
+ }
+ path++;
+ } while (!done);
+ return NULL;
+}
+
+/* Used to return error codes back to dlopen et. al. */
+unsigned long _dl_error_number;
+unsigned long _dl_internal_error_number;
+
+struct elf_resolve *_dl_load_shared_library(unsigned rflags, struct dyn_elf **rpnt,
+ struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
+{
+ char *pnt;
+ struct elf_resolve *tpnt1;
+ char *libname;
+
+ _dl_internal_error_number = 0;
+ libname = full_libname;
+
+ /* quick hack to ensure mylibname buffer doesn't overflow. don't
+ allow full_libname or any directory to be longer than 1024. */
+ if (_dl_strlen(full_libname) > 1024)
+ goto goof;
+
+ /* Skip over any initial initial './' and '/' stuff to
+ * get the short form libname with no path garbage */
+ pnt = _dl_strrchr(libname, '/');
+ if (pnt) {
+ libname = pnt + 1;
+ }
+
+ _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
+ /* If the filename has any '/', try it straight and leave it at that.
+ For IBCS2 compatibility under linux, we substitute the string
+ /usr/i486-sysv4/lib for /usr/lib in library names. */
+
+ if (libname != full_libname) {
+ _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
+ tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, full_libname);
+ if (tpnt1) {
+ return tpnt1;
+ }
+ }
+
+ /*
+ * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
+ * the default path of /usr/lib. Check in rpath directories.
+ */
+#ifdef __LDSO_RUNPATH__
+ pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
+ if (pnt) {
+ pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+ _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
+ if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL)
+ return tpnt1;
+ }
+#endif
+
+#ifdef __LDSO_LD_LIBRARY_PATH__
+ /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
+ if (_dl_library_path) {
+ _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
+ if ((tpnt1 = search_for_named_library(libname, rflags, _dl_library_path, rpnt)) != NULL)
+ {
+ return tpnt1;
+ }
+ }
+#endif
+ /*
+ * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
+ */
+#ifdef __LDSO_RUNPATH__
+ pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
+ if (pnt) {
+ pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+ _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
+ if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL)
+ return tpnt1;
+ }
+#endif
+
+ /*
+ * Where should the cache be searched? There is no such concept in the
+ * ABI, so we have some flexibility here. For now, search it before
+ * the hard coded paths that follow (i.e before /lib and /usr/lib).
+ */
+#ifdef __LDSO_CACHE_SUPPORT__
+ if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
+ int i;
+ header_t *header = (header_t *) _dl_cache_addr;
+ libentry_t *libent = (libentry_t *) & header[1];
+ char *strs = (char *) &libent[header->nlibs];
+
+ _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
+ for (i = 0; i < header->nlibs; i++) {
+ if ((libent[i].flags == LIB_ELF
+ || libent[i].flags == LIB_ELF_LIBC0
+ || libent[i].flags == LIB_ELF_LIBC5)
+ && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
+ && (tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, strs + libent[i].liboffset))
+ ) {
+ return tpnt1;
+ }
+ }
+ }
+#endif
+#if defined SHARED && defined __LDSO_SEARCH_INTERP_PATH__
+ /* Look for libraries wherever the shared library loader
+ * was installed */
+ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
+ tpnt1 = search_for_named_library(libname, rflags, _dl_ldsopath, rpnt);
+ if (tpnt1 != NULL)
+ return tpnt1;
+#endif
+ /* Lastly, search the standard list of paths for the library.
+ This list must exactly match the list in uClibc/ldso/util/ldd.c */
+ _dl_if_debug_dprint("\tsearching full lib path list\n");
+ tpnt1 = search_for_named_library(libname, rflags,
+ UCLIBC_RUNTIME_PREFIX "lib:"
+ UCLIBC_RUNTIME_PREFIX "usr/lib"
+#ifndef __LDSO_CACHE_SUPPORT__
+ ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
+#endif
+ , rpnt);
+ if (tpnt1 != NULL)
+ return tpnt1;
+
+goof:
+ /* Well, we shot our wad on that one. All we can do now is punt */
+ if (_dl_internal_error_number)
+ _dl_error_number = _dl_internal_error_number;
+ else
+ _dl_error_number = LD_ERROR_NOFILE;
+ _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
+ return NULL;
+}
+
+/* Define the _dl_library_offset for the architectures that need it */
+DL_DEF_LIB_OFFSET;
+
+/*
+ * Make a writeable mapping of a segment, regardless of whether PF_W is
+ * set or not.
+ */
+static void *
+map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags,
+ unsigned long libaddr)
+{
+ int prot_flags = ppnt->p_flags | PF_W;
+ char *status, *retval;
+ char *tryaddr;
+ ssize_t size;
+ unsigned long map_size;
+ char *cpnt;
+ char *piclib2map = NULL;
+
+ if (piclib == 2 &&
+ /* We might be able to avoid this call if memsz doesn't
+ require an additional page, but this would require mmap
+ to always return page-aligned addresses and a whole
+ number of pages allocated. Unfortunately on uClinux
+ may return misaligned addresses and may allocate
+ partial pages, so we may end up doing unnecessary mmap
+ calls.
+
+ This is what we could do if we knew mmap would always
+ return aligned pages:
+
+ ((ppnt->p_vaddr + ppnt->p_filesz + ADDR_ALIGN) &
+ PAGE_ALIGN) < ppnt->p_vaddr + ppnt->p_memsz)
+
+ Instead, we have to do this: */
+ ppnt->p_filesz < ppnt->p_memsz)
+ {
+ piclib2map = (char *)
+ _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_memsz,
+ LXFLAGS(prot_flags), flags | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(piclib2map))
+ return 0;
+ }
+
+ tryaddr = piclib == 2 ? piclib2map
+ : ((char *) (piclib ? libaddr : DL_GET_LIB_OFFSET()) +
+ (ppnt->p_vaddr & PAGE_ALIGN));
+
+ size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
+
+ /* For !MMU, mmap to fixed address will fail.
+ So instead of desperately call mmap and fail,
+ we set status to MAP_FAILED to save a call
+ to mmap (). */
+#ifndef __ARCH_USE_MMU__
+ if (piclib2map == 0)
+#endif
+ status = (char *) _dl_mmap
+ (tryaddr, size, LXFLAGS(prot_flags),
+ flags | (piclib2map ? MAP_FIXED : 0),
+ infile, ppnt->p_offset & OFFS_ALIGN);
+#ifndef __ARCH_USE_MMU__
+ else
+ status = MAP_FAILED;
+#endif
+#ifdef _DL_PREAD
+ if (_dl_mmap_check_error(status) && piclib2map
+ && (_DL_PREAD (infile, tryaddr, size,
+ ppnt->p_offset & OFFS_ALIGN) == size))
+ status = tryaddr;
+#endif
+ if (_dl_mmap_check_error(status) || (tryaddr && tryaddr != status))
+ return 0;
+
+ if (piclib2map)
+ retval = piclib2map;
+ else
+ retval = status;
+
+ /* Now we want to allocate and zero-out any data from the end
+ of the region we mapped in from the file (filesz) to the
+ end of the loadable segment (memsz). We may need
+ additional pages for memsz, that we map in below, and we
+ can count on the kernel to zero them out, but we have to
+ zero out stuff in the last page that we mapped in from the
+ file. However, we can't assume to have actually obtained
+ full pages from the kernel, since we didn't ask for them,
+ and uClibc may not give us full pages for small
+ allocations. So only zero out up to memsz or the end of
+ the page, whichever comes first. */
+
+ /* CPNT is the beginning of the memsz portion not backed by
+ filesz. */
+ cpnt = (char *) (status + size);
+
+ /* MAP_SIZE is the address of the
+ beginning of the next page. */
+ map_size = (ppnt->p_vaddr + ppnt->p_filesz
+ + ADDR_ALIGN) & PAGE_ALIGN;
+
+ _dl_memset (cpnt, 0,
+ MIN (map_size
+ - (ppnt->p_vaddr
+ + ppnt->p_filesz),
+ ppnt->p_memsz
+ - ppnt->p_filesz));
+
+ if (map_size < ppnt->p_vaddr + ppnt->p_memsz && !piclib2map) {
+ tryaddr = map_size + (char*)(piclib ? libaddr : 0);
+ status = (char *) _dl_mmap(tryaddr,
+ ppnt->p_vaddr + ppnt->p_memsz - map_size,
+ LXFLAGS(prot_flags),
+ flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ if (_dl_mmap_check_error(status) || tryaddr != status)
+ return NULL;
+ }
+ return retval;
+}
+
+/*
+ * Read one ELF library into memory, mmap it into the correct locations and
+ * add the symbol info to the symbol chain. Perform any relocations that
+ * are required.
+ */
+
+struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,
+ struct dyn_elf **rpnt, const char *libname)
+{
+ ElfW(Ehdr) *epnt;
+ unsigned long dynamic_addr = 0;
+ ElfW(Dyn) *dpnt;
+ struct elf_resolve *tpnt;
+ ElfW(Phdr) *ppnt;
+#if defined(USE_TLS) && USE_TLS
+ ElfW(Phdr) *tlsppnt = NULL;
+#endif
+ char *status, *header;
+ unsigned long dynamic_info[DYNAMIC_SIZE];
+ unsigned long *lpnt;
+ unsigned long libaddr;
+ unsigned long minvma = 0xffffffff, maxvma = 0;
+ unsigned int rtld_flags;
+ int i, flags, piclib, infile;
+ ElfW(Addr) relro_addr = 0;
+ size_t relro_size = 0;
+ struct stat st;
+ uint32_t *p32;
+ DL_LOADADDR_TYPE lib_loadaddr;
+ DL_INIT_LOADADDR_EXTRA_DECLS
+
+ libaddr = 0;
+ infile = _dl_open(libname, O_RDONLY, 0);
+ if (infile < 0) {
+ _dl_internal_error_number = LD_ERROR_NOFILE;
+ return NULL;
+ }
+
+ if (_dl_fstat(infile, &st) < 0) {
+ _dl_internal_error_number = LD_ERROR_NOFILE;
+ _dl_close(infile);
+ return NULL;
+ }
+ /* If we are in secure mode (i.e. a setuid/gid binary using LD_PRELOAD),
+ we don't load the library if it isn't setuid. */
+ if (rflags & DL_RESOLVE_SECURE) {
+ if (!(st.st_mode & S_ISUID)) {
+ _dl_close(infile);
+ return NULL;
+ }
+ }
+
+ /* Check if file is already loaded */
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
+ /* Already loaded */
+ tpnt->usage_count++;
+ _dl_close(infile);
+ return tpnt;
+ }
+ }
+ if (rflags & DL_RESOLVE_NOLOAD) {
+ _dl_close(infile);
+ return NULL;
+ }
+ header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
+ if (_dl_mmap_check_error(header)) {
+ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_close(infile);
+ return NULL;
+ }
+
+ _dl_read(infile, header, _dl_pagesize);
+ epnt = (ElfW(Ehdr) *) (intptr_t) header;
+ p32 = (uint32_t*)&epnt->e_ident;
+ if (*p32 != ELFMAG_U32) {
+ _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
+ libname);
+ _dl_internal_error_number = LD_ERROR_NOTELF;
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+ }
+
+ if ((epnt->e_type != ET_DYN
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ && epnt->e_type != ET_EXEC
+#endif
+ ) || (epnt->e_machine != MAGIC1
+#ifdef MAGIC2
+ && epnt->e_machine != MAGIC2
+#endif
+ ))
+ {
+ _dl_internal_error_number =
+ (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
+ _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
+ "\n", _dl_progname, libname);
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+ }
+
+ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
+
+ piclib = 1;
+ for (i = 0; i < epnt->e_phnum; i++) {
+
+ if (ppnt->p_type == PT_DYNAMIC) {
+ if (dynamic_addr)
+ _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
+ _dl_progname, libname);
+ dynamic_addr = ppnt->p_vaddr;
+ }
+
+ if (ppnt->p_type == PT_LOAD) {
+ /* See if this is a PIC library. */
+ if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {
+ piclib = 0;
+ minvma = ppnt->p_vaddr;
+ }
+ if (piclib && ppnt->p_vaddr < minvma) {
+ minvma = ppnt->p_vaddr;
+ }
+ if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) {
+ maxvma = ppnt->p_vaddr + ppnt->p_memsz;
+ }
+ }
+ if (ppnt->p_type == PT_TLS) {
+#if defined(USE_TLS) && USE_TLS
+ if (ppnt->p_memsz == 0)
+ /* Nothing to do for an empty segment. */
+ continue;
+ else
+ /* Save for after 'tpnt' is actually allocated. */
+ tlsppnt = ppnt;
+#else
+ /*
+ * Yup, the user was an idiot and tried to sneak in a library with
+ * TLS in it and we don't support it. Let's fall on our own sword
+ * and scream at the luser while we die.
+ */
+ _dl_dprintf(2, "%s: '%s' library contains unsupported TLS\n",
+ _dl_progname, libname);
+ _dl_internal_error_number = LD_ERROR_TLS_FAILED;
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+#endif
+ }
+ ppnt++;
+ }
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ if (epnt->e_type == ET_EXEC)
+ piclib = 0;
+#endif
+
+ DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
+
+ maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
+ minvma = minvma & ~ADDR_ALIGN;
+
+ flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
+
+ if (piclib == 0 || piclib == 1) {
+ status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
+ maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(status)) {
+ cant_map:
+ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+ }
+ libaddr = (unsigned long) status;
+ flags |= MAP_FIXED;
+ }
+
+ /* Get the memory to store the library */
+ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
+
+ DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
+ /* Set _dl_library_offset to lib_loadaddr or 0. */
+ DL_SET_LIB_OFFSET(lib_loadaddr);
+
+ for (i = 0; i < epnt->e_phnum; i++) {
+ if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
+ char *addr;
+
+ addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
+ if (addr == NULL) {
+ cant_map1:
+ DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
+ goto cant_map;
+ }
+
+ DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
+ ppnt++;
+ continue;
+ }
+ if (ppnt->p_type == PT_GNU_RELRO) {
+ relro_addr = ppnt->p_vaddr;
+ relro_size = ppnt->p_memsz;
+ }
+ if (ppnt->p_type == PT_LOAD) {
+ char *tryaddr;
+ ssize_t size;
+
+ if (ppnt->p_flags & PF_W) {
+ status = map_writeable (infile, ppnt, piclib, flags, libaddr);
+ if (status == NULL)
+ goto cant_map1;
+ } else {
+ tryaddr = (piclib == 2 ? 0
+ : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
+ + (piclib ? libaddr : DL_GET_LIB_OFFSET()));
+ size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
+ status = (char *) _dl_mmap
+ (tryaddr, size, LXFLAGS(ppnt->p_flags),
+ flags | (piclib == 2 ? MAP_EXECUTABLE
+ | MAP_DENYWRITE : 0),
+ infile, ppnt->p_offset & OFFS_ALIGN);
+ if (_dl_mmap_check_error(status)
+ || (tryaddr && tryaddr != status))
+ goto cant_map1;
+ }
+ DL_INIT_LOADADDR_HDR(lib_loadaddr,
+ status + (ppnt->p_vaddr & ADDR_ALIGN),
+ ppnt);
+
+ /* if (libaddr == 0 && piclib) {
+ libaddr = (unsigned long) status;
+ flags |= MAP_FIXED;
+ } */
+ }
+ ppnt++;
+ }
+
+ /*
+ * The dynamic_addr must be take into acount lib_loadaddr value, to note
+ * it is zero when the SO has been mapped to the elf's physical addr
+ */
+#ifdef __LDSO_PRELINK_SUPPORT__
+ if (DL_GET_LIB_OFFSET()) {
+#else
+ if (piclib) {
+#endif
+ dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
+ }
+
+ /*
+ * OK, the ELF library is now loaded into VM in the correct locations
+ * The next step is to go through and do the dynamic linking (if needed).
+ */
+
+ /* Start by scanning the dynamic section to get all of the pointers */
+
+ if (!dynamic_addr) {
+ _dl_internal_error_number = LD_ERROR_NODYNAMIC;
+ _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
+ _dl_progname, libname);
+ _dl_munmap(header, _dl_pagesize);
+ _dl_close(infile);
+ return NULL;
+ }
+
+ dpnt = (ElfW(Dyn) *) dynamic_addr;
+ _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
+ rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
+ /* If the TEXTREL is set, this means that we need to make the pages
+ writable before we perform relocations. Do this now. They get set
+ back again later. */
+
+ if (dynamic_info[DT_TEXTREL]) {
+#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
+ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
+ for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
+ if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
+#ifdef __ARCH_USE_MMU__
+ _dl_mprotect((void *) ((piclib ? libaddr : DL_GET_LIB_OFFSET()) +
+ (ppnt->p_vaddr & PAGE_ALIGN)),
+ (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
+#else
+ void *new_addr;
+ new_addr = map_writeable (infile, ppnt, piclib, flags, libaddr);
+ if (!new_addr) {
+ _dl_dprintf(_dl_debug_file, "Can't modify %s's text section.",
+ libname);
+ _dl_exit(1);
+ }
+ DL_UPDATE_LOADADDR_HDR(lib_loadaddr,
+ new_addr + (ppnt->p_vaddr & ADDR_ALIGN),
+ ppnt);
+ /* This has invalidated all pointers into the previously readonly segment.
+ Update any them to point into the remapped segment. */
+ _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
+#endif
+ }
+ }
+#else
+ _dl_dprintf(_dl_debug_file, "Can't modify %s's text section."
+ " Use GCC option -fPIC for shared objects, please.\n",
+ libname);
+ _dl_exit(1);
+#endif
+ }
+
+ _dl_close(infile);
+
+ tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
+ dynamic_addr, 0);
+ tpnt->mapaddr = libaddr;
+ tpnt->relro_addr = relro_addr;
+ tpnt->relro_size = relro_size;
+ tpnt->st_dev = st.st_dev;
+ tpnt->st_ino = st.st_ino;
+ tpnt->ppnt = (ElfW(Phdr) *)
+ DL_RELOC_ADDR(DL_GET_RUN_ADDR(tpnt->loadaddr, tpnt->mapaddr),
+ epnt->e_phoff);
+ tpnt->n_phent = epnt->e_phnum;
+ tpnt->rtld_flags |= rtld_flags;
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ tpnt->l_entry = epnt->e_entry;
+#endif
+
+#if defined(USE_TLS) && USE_TLS
+ if (tlsppnt) {
+ _dl_debug_early("Found TLS header for %s\n", libname);
+# if NO_TLS_OFFSET != 0
+ tpnt->l_tls_offset = NO_TLS_OFFSET;
+# endif
+ tpnt->l_tls_blocksize = tlsppnt->p_memsz;
+ tpnt->l_tls_align = tlsppnt->p_align;
+ if (tlsppnt->p_align == 0)
+ tpnt->l_tls_firstbyte_offset = 0;
+ else
+ tpnt->l_tls_firstbyte_offset = tlsppnt->p_vaddr &
+ (tlsppnt->p_align - 1);
+ tpnt->l_tls_initimage_size = tlsppnt->p_filesz;
+ tpnt->l_tls_initimage = (void *) tlsppnt->p_vaddr;
+
+ /* Assign the next available module ID. */
+ tpnt->l_tls_modid = _dl_next_tls_modid ();
+
+ /* We know the load address, so add it to the offset. */
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ if ((tpnt->l_tls_initimage != NULL) && piclib)
+#else
+ if (tpnt->l_tls_initimage != NULL)
+#endif
+ {
+# ifdef __SUPPORT_LD_DEBUG_EARLY__
+ unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
+ tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
+ _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
+ tmp = 0;
+# else
+ tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
+# endif
+ }
+ }
+#endif
+
+ /*
+ * Add this object into the symbol chain
+ */
+ if (*rpnt
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ /* Do not create a new chain entry for the main executable */
+ && (*rpnt)->dyn
+#endif
+ ) {
+ (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));
+ _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
+ (*rpnt)->next->prev = (*rpnt);
+ *rpnt = (*rpnt)->next;
+ }
+#ifndef SHARED
+ /* When statically linked, the first time we dlopen a DSO
+ * the *rpnt is NULL, so we need to allocate memory for it,
+ * and initialize the _dl_symbol_table.
+ */
+ else {
+ *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf));
+ _dl_memset(*rpnt, 0, sizeof(struct dyn_elf));
+ }
+#endif
+ (*rpnt)->dyn = tpnt;
+ tpnt->usage_count++;
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;
+#else
+ tpnt->libtype = elf_lib;
+#endif
+
+ /*
+ * OK, the next thing we need to do is to insert the dynamic linker into
+ * the proper entry in the GOT so that the PLT symbols can be properly
+ * resolved.
+ */
+
+ lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
+
+ if (lpnt) {
+ lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
+ INIT_GOT(lpnt, tpnt);
+ }
+
+#ifdef __DSBT__
+ /* Handle DSBT initialization */
+ {
+ struct elf_resolve *t, *ref;
+ int idx = tpnt->loadaddr.map->dsbt_index;
+ unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
+
+ if (idx == 0) {
+ if (!dynamic_info[DT_TEXTREL]) {
+ /* This DSO has not been assigned an index. */
+ _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
+ _dl_progname, libname);
+ _dl_exit(1);
+ }
+ /* Find a dsbt table from another module. */
+ ref = NULL;
+ for (t = _dl_loaded_modules; t; t = t->next) {
+ if (ref == NULL && t != tpnt) {
+ ref = t;
+ break;
+ }
+ }
+ idx = tpnt->loadaddr.map->dsbt_size;
+ while (idx-- > 0)
+ if (!ref || ref->loadaddr.map->dsbt_table[idx] == NULL)
+ break;
+ if (idx <= 0) {
+ _dl_dprintf(2, "%s: '%s' caused DSBT table overflow!\n",
+ _dl_progname, libname);
+ _dl_exit(1);
+ }
+ _dl_if_debug_dprint("\n\tfile='%s'; assigned index %d\n",
+ libname, idx);
+ tpnt->loadaddr.map->dsbt_index = idx;
+
+ }
+
+ /*
+ * Setup dsbt slot for this module in dsbt of all modules.
+ */
+ ref = NULL;
+ for (t = _dl_loaded_modules; t; t = t->next) {
+ /* find a dsbt table from another module */
+ if (ref == NULL && t != tpnt) {
+ ref = t;
+
+ /* make sure index is not already used */
+ if (t->loadaddr.map->dsbt_table[idx]) {
+ struct elf_resolve *dup;
+ char *dup_name;
+
+ for (dup = _dl_loaded_modules; dup; dup = dup->next)
+ if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
+ break;
+ if (dup)
+ dup_name = dup->libname;
+ else if (idx == 1)
+ dup_name = "runtime linker";
+ else
+ dup_name = "unknown library";
+ _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
+ _dl_progname, libname, idx, dup_name);
+ _dl_exit(1);
+ }
+ }
+ t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
+ }
+ if (ref)
+ _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
+ tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
+ }
+#endif
+ _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
+ _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
+ _dl_if_debug_dprint("\t\t entry: %x phdr: %x phnum: %x\n\n",
+ DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
+
+ _dl_munmap(header, _dl_pagesize);
+
+ return tpnt;
+}
+
+/* now_flag must be RTLD_NOW or zero */
+int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
+{
+ int goof = 0;
+ struct elf_resolve *tpnt;
+ ElfW(Word) reloc_size, relative_count;
+ ElfW(Addr) reloc_addr;
+
+ if (rpnt->next)
+ goof = _dl_fixup(rpnt->next, scope, now_flag);
+ if (goof)
+ return goof;
+ tpnt = rpnt->dyn;
+
+ if (!(tpnt->init_flag & RELOCS_DONE))
+ _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
+
+ if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
+ _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
+ _dl_progname, UNSUPPORTED_RELOC_STR);
+ goof++;
+ return goof;
+ }
+
+ reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
+/* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
+ range. Note that according to the ELF spec, this is completely legal! */
+#ifdef ELF_MACHINE_PLTREL_OVERLAP
+ reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
+#endif
+ if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
+ !(tpnt->init_flag & RELOCS_DONE)) {
+ reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
+ relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
+ if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
+ reloc_size -= relative_count * sizeof(ELF_RELOC);
+#ifdef __LDSO_PRELINK_SUPPORT__
+ if (tpnt->loadaddr || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]))
+#endif
+ elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
+ reloc_addr += relative_count * sizeof(ELF_RELOC);
+ }
+ goof += _dl_parse_relocation_information(rpnt, scope,
+ reloc_addr,
+ reloc_size);
+ tpnt->init_flag |= RELOCS_DONE;
+ }
+ if (tpnt->dynamic_info[DT_BIND_NOW])
+ now_flag = RTLD_NOW;
+ if (tpnt->dynamic_info[DT_JMPREL] &&
+ (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
+ (now_flag && !(tpnt->rtld_flags & now_flag)))) {
+ tpnt->rtld_flags |= now_flag;
+ if (!(tpnt->rtld_flags & RTLD_NOW)) {
+ _dl_parse_lazy_relocation_information(rpnt,
+ tpnt->dynamic_info[DT_JMPREL],
+ tpnt->dynamic_info [DT_PLTRELSZ]);
+ } else {
+ goof += _dl_parse_relocation_information(rpnt, scope,
+ tpnt->dynamic_info[DT_JMPREL],
+ tpnt->dynamic_info[DT_PLTRELSZ]);
+ }
+ tpnt->init_flag |= JMP_RELOCS_DONE;
+ }
+
+#if 0
+/* _dl_add_to_slotinfo is called by init_tls() for initial DSO
+ or by dlopen() for dynamically loaded DSO. */
+#if defined(USE_TLS) && USE_TLS
+ /* Add object to slot information data if necessasy. */
+ if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called)
+ _dl_add_to_slotinfo ((struct link_map *) tpnt);
+#endif
+#endif
+ return goof;
+}
+
+/* Minimal printf which handles only %s, %d, and %x */
+void _dl_dprintf(int fd, const char *fmt, ...)
+{
+#if __WORDSIZE > 32
+ long int num;
+#else
+ int num;
+#endif
+ va_list args;
+ char *start, *ptr, *string;
+ char *buf;
+
+ if (!fmt)
+ return;
+
+ buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(buf)) {
+ _dl_write(fd, "mmap of a spare page failed!\n", 29);
+ _dl_exit(20);
+ }
+
+ start = ptr = buf;
+
+ if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
+ _dl_write(fd, "overflow\n", 11);
+ _dl_exit(20);
+ }
+
+ _dl_strcpy(buf, fmt);
+ va_start(args, fmt);
+
+ while (start) {
+ while (*ptr != '%' && *ptr) {
+ ptr++;
+ }
+
+ if (*ptr == '%') {
+ *ptr++ = '\0';
+ _dl_write(fd, start, _dl_strlen(start));
+
+ switch (*ptr++) {
+ case 's':
+ string = va_arg(args, char *);
+
+ if (!string)
+ _dl_write(fd, "(null)", 6);
+ else
+ _dl_write(fd, string, _dl_strlen(string));
+ break;
+
+ case 'i':
+ case 'd':
+ {
+ char tmp[22];
+#if __WORDSIZE > 32
+ num = va_arg(args, long int);
+#else
+ num = va_arg(args, int);
+#endif
+ string = _dl_simple_ltoa(tmp, num);
+ _dl_write(fd, string, _dl_strlen(string));
+ break;
+ }
+ case 'x':
+ case 'X':
+ {
+ char tmp[22];
+#if __WORDSIZE > 32
+ num = va_arg(args, long int);
+#else
+ num = va_arg(args, int);
+#endif
+ string = _dl_simple_ltoahex(tmp, num);
+ _dl_write(fd, string, _dl_strlen(string));
+ break;
+ }
+ default:
+ _dl_write(fd, "(null)", 6);
+ break;
+ }
+
+ start = ptr;
+ } else {
+ _dl_write(fd, start, _dl_strlen(start));
+ start = NULL;
+ }
+ }
+ _dl_munmap(buf, _dl_pagesize);
+ return;
+}
+
+char *_dl_strdup(const char *string)
+{
+ char *retval;
+ int len;
+
+ len = _dl_strlen(string);
+ retval = _dl_malloc(len + 1);
+ _dl_strcpy(retval, string);
+ return retval;
+}
+
+unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+ void *debug_addr, DL_LOADADDR_TYPE load_off)
+{
+ return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
+}
diff --git a/ap/build/uClibc/ldso/ldso/dl-hash.c b/ap/build/uClibc/ldso/ldso/dl-hash.c
new file mode 100644
index 0000000..9b67156
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-hash.c
@@ -0,0 +1,387 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+
+/* Various symbol table handling functions, including symbol lookup */
+/*
+ * This is the list of modules that are loaded when the image is first
+ * started. As we add more via dlopen, they get added into other
+ * chains.
+ */
+struct dyn_elf *_dl_symbol_tables = NULL;
+
+/*
+ * This is the list of modules that are loaded via dlopen. We may need
+ * to search these for RTLD_GLOBAL files.
+ */
+struct dyn_elf *_dl_handles = NULL;
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+/* This is the new hash function that is used by the ELF linker to generate the
+ * GNU hash table that each executable and library will have if --hash-style=[gnu,both]
+ * is passed to the linker. We need it to decode the GNU hash table. */
+static __inline__ Elf_Symndx _dl_gnu_hash (const unsigned char *name)
+{
+ unsigned long h = 5381;
+ unsigned char c;
+ for (c = *name; c != '\0'; c = *++name)
+ h = h * 33 + c;
+ return h & 0xffffffff;
+}
+#endif
+
+/* This is the hash function that is used by the ELF linker to generate the
+ * hash table that each executable and library is required to have. We need
+ * it to decode the hash table. */
+static __inline__ Elf_Symndx _dl_elf_hash(const unsigned char *name)
+{
+ unsigned long hash=0;
+ unsigned long tmp;
+
+ while (*name) {
+ hash = (hash << 4) + *name++;
+ tmp = hash & 0xf0000000;
+ /* The algorithm specified in the ELF ABI is as follows:
+ if (tmp != 0)
+ hash ^= tmp >> 24;
+ hash &= ~tmp;
+ But the following is equivalent and a lot
+ faster, especially on modern processors. */
+ hash ^= tmp;
+ hash ^= tmp >> 24;
+ }
+ return hash;
+}
+
+/*
+ * We call this function when we have just read an ELF library or executable.
+ * We add the relevant info to the symbol chain, so that we can resolve all
+ * externals properly.
+ */
+struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
+ DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
+ attribute_unused unsigned long dynamic_size)
+{
+ Elf_Symndx *hash_addr;
+ struct elf_resolve *tpnt;
+ int i;
+
+ tpnt = _dl_malloc(sizeof(struct elf_resolve));
+ _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
+
+ if (!_dl_loaded_modules)
+ _dl_loaded_modules = tpnt;
+ else {
+ struct elf_resolve *t = _dl_loaded_modules;
+ while (t->next)
+ t = t->next;
+ t->next = tpnt;
+ t->next->prev = t;
+ tpnt = t->next;
+ }
+
+ tpnt->next = NULL;
+ tpnt->init_flag = 0;
+ tpnt->libname = _dl_strdup(libname);
+ tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
+ tpnt->libtype = loaded_file;
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ if (dynamic_info[DT_GNU_HASH_IDX] != 0) {
+ Elf32_Word *hash32 = (Elf_Symndx*)dynamic_info[DT_GNU_HASH_IDX];
+
+ tpnt->nbucket = *hash32++;
+ Elf32_Word symbias = *hash32++;
+ Elf32_Word bitmask_nwords = *hash32++;
+ /* Must be a power of two. */
+ _dl_assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
+ tpnt->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
+ tpnt->l_gnu_shift = *hash32++;
+
+ tpnt->l_gnu_bitmask = (ElfW(Addr) *) hash32;
+ hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
+
+ tpnt->l_gnu_buckets = hash32;
+ hash32 += tpnt->nbucket;
+ tpnt->l_gnu_chain_zero = hash32 - symbias;
+ } else
+ /* Fall using old SysV hash table if GNU hash is not present */
+#endif
+
+ if (dynamic_info[DT_HASH] != 0) {
+ hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH];
+ tpnt->nbucket = *hash_addr++;
+ tpnt->nchain = *hash_addr++;
+ tpnt->elf_buckets = hash_addr;
+ hash_addr += tpnt->nbucket;
+ tpnt->chains = hash_addr;
+ }
+ tpnt->loadaddr = loadaddr;
+ for (i = 0; i < DYNAMIC_SIZE; i++)
+ tpnt->dynamic_info[i] = dynamic_info[i];
+ return tpnt;
+}
+
+
+/* Routine to check whether the symbol matches. */
+static __attribute_noinline__ const ElfW(Sym) *
+check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int type_class)
+{
+
+#if defined(USE_TLS) && USE_TLS
+ if ((sym->st_value == 0 && (ELF_ST_TYPE(sym->st_info) != STT_TLS))
+ || (type_class & (sym->st_shndx == SHN_UNDEF)))
+ /* No value or undefined symbol itself */
+ return NULL;
+
+ if (ELF_ST_TYPE(sym->st_info) > STT_FUNC
+ && ELF_ST_TYPE(sym->st_info) != STT_COMMON
+ && ELF_ST_TYPE(sym->st_info) != STT_TLS)
+ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC and STT_COMMON
+ * entries (and STT_TLS if TLS is supported) since these
+ * are no code/data definitions.
+ */
+ return NULL;
+#else
+ if (type_class & (sym->st_shndx == SHN_UNDEF))
+ /* undefined symbol itself */
+ return NULL;
+
+ if (sym->st_value == 0)
+ /* No value */
+ return NULL;
+
+ if (ELF_ST_TYPE(sym->st_info) > STT_FUNC
+ && ELF_ST_TYPE(sym->st_info) != STT_COMMON)
+ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC
+ * and STT_COMMON entries since these are no
+ * code/data definitions
+ */
+ return NULL;
+#endif
+#ifdef ARCH_SKIP_RELOC
+ if (ARCH_SKIP_RELOC(type_class, sym))
+ return NULL;
+#endif
+ if (_dl_strcmp(strtab + sym->st_name, undef_name) != 0)
+ return NULL;
+
+ /* This is the matching symbol */
+ return sym;
+}
+
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+
+static __always_inline const ElfW(Sym) *
+_dl_lookup_gnu_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash,
+ const char* undef_name, int type_class)
+{
+ Elf_Symndx symidx;
+ const ElfW(Sym) *sym;
+ char *strtab;
+
+ const ElfW(Addr) *bitmask = tpnt->l_gnu_bitmask;
+
+ ElfW(Addr) bitmask_word = bitmask[(hash / __ELF_NATIVE_CLASS) & tpnt->l_gnu_bitmask_idxbits];
+
+ unsigned int hashbit1 = hash & (__ELF_NATIVE_CLASS - 1);
+ unsigned int hashbit2 = ((hash >> tpnt->l_gnu_shift) & (__ELF_NATIVE_CLASS - 1));
+ _dl_assert (bitmask != NULL);
+
+ if (unlikely((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1)) {
+ unsigned long rem;
+ Elf32_Word bucket;
+
+ do_rem (rem, hash, tpnt->nbucket);
+ bucket = tpnt->l_gnu_buckets[rem];
+
+ if (bucket != 0) {
+ const Elf32_Word *hasharr = &tpnt->l_gnu_chain_zero[bucket];
+ do {
+ if (((*hasharr ^ hash) >> 1) == 0) {
+ symidx = hasharr - tpnt->l_gnu_chain_zero;
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
+ sym = check_match (&symtab[symidx], strtab, undef_name, type_class);
+ if (sym != NULL)
+ return sym;
+ }
+ } while ((*hasharr++ & 1u) == 0);
+ }
+ }
+ /* No symbol found. */
+ return NULL;
+}
+#endif
+
+static __always_inline const ElfW(Sym) *
+_dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, const char* undef_name, int type_class)
+{
+ unsigned long hn;
+ char *strtab;
+ const ElfW(Sym) *sym;
+ Elf_Symndx symidx;
+
+ /* Avoid calling .urem here. */
+ do_rem(hn, hash, tpnt->nbucket);
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
+
+ _dl_assert(tpnt->elf_buckets != NULL);
+
+ for (symidx = tpnt->elf_buckets[hn]; symidx != STN_UNDEF; symidx = tpnt->chains[symidx]) {
+ sym = check_match (&symtab[symidx], strtab, undef_name, type_class);
+ if (sym != NULL)
+ /* At this point the symbol is that we are looking for */
+ return sym;
+ }
+ /* No symbol found into the current module*/
+ return NULL;
+}
+
+/*
+ * This function resolves externals, and this is either called when we process
+ * relocations or when we call an entry in the PLT table for the first time.
+ */
+char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
+ int type_class, struct symbol_ref *sym_ref)
+{
+ struct elf_resolve *tpnt = NULL;
+ ElfW(Sym) *symtab;
+ int i = 0;
+
+ unsigned long elf_hash_number = 0xffffffff;
+ const ElfW(Sym) *sym = NULL;
+
+ char *weak_result = NULL;
+ struct r_scope_elem *loop_scope;
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
+#endif
+
+ if ((sym_ref) && (sym_ref->sym) && (ELF32_ST_VISIBILITY(sym_ref->sym->st_other) == STV_PROTECTED)) {
+ sym = sym_ref->sym;
+ if (mytpnt)
+ tpnt = mytpnt;
+ } else
+ for (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) {
+ for (i = 0; i < loop_scope->r_nlist; i++) {
+ tpnt = loop_scope->r_list[i];
+
+ if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
+ if (mytpnt == tpnt)
+ ;
+ else {
+ struct init_fini_list *tmp;
+
+ for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
+ if (tmp->tpnt == tpnt)
+ break;
+ }
+ if (!tmp)
+ continue;
+ }
+ }
+ /* Don't search the executable when resolving a copy reloc. */
+ if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+ continue;
+
+ /* If the hash table is empty there is nothing to do here. */
+ if (tpnt->nbucket == 0)
+ continue;
+
+ symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ /* Prefer GNU hash style, if any */
+ if (tpnt->l_gnu_bitmask) {
+ sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
+ if (sym != NULL)
+ /* If sym has been found, do not search further */
+ break;
+ } else {
+#endif
+ /* Use the old SysV-style hash table */
+
+ /* Calculate the old sysv hash number only once */
+ if (elf_hash_number == 0xffffffff)
+ elf_hash_number = _dl_elf_hash((const unsigned char *)name);
+
+ sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
+ if (sym != NULL)
+ /* If sym has been found, do not search further */
+ break;
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ }
+#endif
+ } /* End of inner for */
+ }
+
+ if (sym) {
+ if (sym_ref) {
+ sym_ref->sym = sym;
+ sym_ref->tpnt = tpnt;
+ }
+ /* At this point we have found the requested symbol, do binding */
+#if defined(USE_TLS) && USE_TLS
+ if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
+ _dl_assert(sym_ref != NULL);
+ sym_ref->tpnt = tpnt;
+ return (char *)sym->st_value;
+ }
+#endif
+
+ switch (ELF_ST_BIND(sym->st_info)) {
+ case STB_WEAK:
+#if 0
+ /* Perhaps we should support old style weak symbol handling
+ * per what glibc does when you export LD_DYNAMIC_WEAK */
+ if (!weak_result)
+ weak_result = (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym);
+ break;
+#endif
+ case STB_GLOBAL:
+#ifdef __FDPIC__
+ if (sym_ref)
+ sym_ref->tpnt = tpnt;
+#endif
+ return (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym);
+ default: /* Local symbols not handled here */
+ break;
+ }
+ }
+#ifdef __FDPIC__
+ if (sym_ref)
+ sym_ref->tpnt = tpnt;
+#endif
+ return weak_result;
+}
diff --git a/ap/build/uClibc/ldso/ldso/dl-startup.c b/ap/build/uClibc/ldso/ldso/dl-startup.c
new file mode 100644
index 0000000..4893409
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-startup.c
@@ -0,0 +1,361 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2005 by Joakim Tjernlund
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/*
+ * The main trick with this program is that initially, we ourselves are not
+ * dynamically linked. This means that we cannot access any global variables
+ * or call any functions. No globals initially, since the Global Offset Table
+ * (GOT) is initialized by the linker assuming a virtual address of 0, and no
+ * function calls initially since the Procedure Linkage Table (PLT) is not yet
+ * initialized.
+ *
+ * There are additional initial restrictions - we cannot use large switch
+ * statements, since the compiler generates tables of addresses and jumps
+ * through them. We cannot use normal syscall stubs, because these all
+ * reference the errno global variable which is not yet initialized. We _can_
+ * use all of the local stack variables that we want. We _can_ use inline
+ * functions, because these do not transfer control to a new address, but they
+ * must be static so that they are not exported from the modules.
+ *
+ * Life is further complicated by the fact that initially we do not want to do
+ * a complete dynamic linking. We want to allow the user to supply new
+ * functions to override symbols (i.e. weak symbols and/or LD_PRELOAD). So
+ * initially, we only perform relocations for variables that start with "_dl_"
+ * since ANSI specifies that the user is not supposed to redefine any of these
+ * variables.
+ *
+ * Fortunately, the linker itself leaves a few clues lying around, and when the
+ * kernel starts the image, there are a few further clues. First of all, there
+ * is Auxiliary Vector Table information sitting on the stack which is provided
+ * to us by the kernel, and which includes information about the address
+ * that the program interpreter was loaded at, the number of sections, the
+ * address the application was loaded at, and so forth. Here this information
+ * is stored in the array auxvt. For details see linux/fs/binfmt_elf.c where
+ * it calls NEW_AUX_ENT() a bunch of times....
+ *
+ * Next, we need to find the GOT. On most arches there is a register pointing
+ * to the GOT, but just in case (and for new ports) I've added some (slow) C
+ * code to locate the GOT for you.
+ *
+ * This code was originally written for SVr4, and there the kernel would load
+ * all text pages R/O, so they needed to call mprotect a zillion times to mark
+ * all text pages as writable so dynamic linking would succeed. Then when they
+ * were done, they would change the protections for all the pages back again.
+ * Well, under Linux everything is loaded writable (since Linux does copy on
+ * write anyways) so all the mprotect stuff has been disabled.
+ *
+ * Initially, we do not have access to _dl_malloc since we can't yet make
+ * function calls, so we mmap one page to use as scratch space. Later on, when
+ * we can call _dl_malloc we reuse this this memory. This is also beneficial,
+ * since we do not want to use the same memory pool as malloc anyway - esp if
+ * the user redefines malloc to do something funky.
+ *
+ * Our first task is to perform a minimal linking so that we can call other
+ * portions of the dynamic linker. Once we have done this, we then build the
+ * list of modules that the application requires, using LD_LIBRARY_PATH if this
+ * is not a suid program (/usr/lib otherwise). Once this is done, we can do
+ * the dynamic linking as required, and we must omit the things we did to get
+ * the dynamic linker up and running in the first place. After we have done
+ * this, we just have a few housekeeping chores and we can transfer control to
+ * the user's application.
+ */
+
+#include "ldso.h"
+
+/* Pull in all the arch specific stuff */
+#include "dl-startup.h"
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+/* These defined magically in the linker script. */
+extern char _begin[] attribute_hidden;
+#endif
+
+/* Static declarations */
+static int (*_dl_elf_main) (int, char **, char **);
+
+static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */
+strong_alias(__rtld_stack_end, __libc_stack_end) /* Exported version of __rtld_stack_end */
+
+/* When we enter this piece of code, the program stack looks like this:
+ argc argument counter (integer)
+ argv[0] program name (pointer)
+ argv[1..argc-1] program args (pointers)
+ NULL
+ env[0...N] environment variables (pointers)
+ NULL
+ auxvt[0...N] Auxiliary Vector Table elements (mixed types)
+*/
+DL_START(unsigned long args)
+{
+ unsigned int argc;
+ char **argv, **envp;
+ DL_LOADADDR_TYPE load_addr;
+ ElfW(Addr) got;
+ unsigned long *aux_dat;
+ ElfW(Ehdr) *header;
+ struct elf_resolve tpnt_tmp;
+ struct elf_resolve *tpnt = &tpnt_tmp;
+ ElfW(auxv_t) auxvt[AT_EGID + 1];
+ ElfW(Dyn) *dpnt;
+ uint32_t *p32;
+
+ /* WARNING! -- we cannot make _any_ function calls until we have
+ * taken care of fixing up our own relocations. Making static
+ * inline calls is ok, but _no_ function calls. Not yet
+ * anyways. */
+
+ /* First obtain the information on the stack that tells us more about
+ what binary is loaded, where it is loaded, etc, etc */
+ GET_ARGV(aux_dat, args);
+ argc = aux_dat[-1];
+ argv = (char **) aux_dat;
+ aux_dat += argc; /* Skip over the argv pointers */
+ aux_dat++; /* Skip over NULL at end of argv */
+ envp = (char **) aux_dat;
+#if !defined(NO_EARLY_SEND_STDERR)
+ SEND_EARLY_STDERR_DEBUG("argc=");
+ SEND_NUMBER_STDERR_DEBUG(argc, 0);
+ SEND_EARLY_STDERR_DEBUG(" argv=");
+ SEND_ADDRESS_STDERR_DEBUG(argv, 0);
+ SEND_EARLY_STDERR_DEBUG(" envp=");
+ SEND_ADDRESS_STDERR_DEBUG(envp, 1);
+#endif
+ while (*aux_dat)
+ aux_dat++; /* Skip over the envp pointers */
+ aux_dat++; /* Skip over NULL at end of envp */
+
+ /* Place -1 here as a checkpoint. We later check if it was changed
+ * when we read in the auxvt */
+ auxvt[AT_UID].a_type = -1;
+
+ /* The junk on the stack immediately following the environment is
+ * the Auxiliary Vector Table. Read out the elements of the auxvt,
+ * sort and store them in auxvt for later use. */
+ while (*aux_dat) {
+ ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat;
+
+ if (auxv_entry->a_type <= AT_EGID) {
+ _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));
+ }
+ aux_dat += 2;
+ }
+
+ /*
+ * Locate the dynamic linker ELF header. We need this done as soon as
+ * possible (esp since SEND_STDERR() needs this on some platforms...
+ */
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+ /*
+ * The `_begin' symbol created by the linker script points to ld.so ELF
+ * We use it if the kernel is not passing a valid address through the auxvt.
+ */
+
+ if (!auxvt[AT_BASE].a_un.a_val)
+ auxvt[AT_BASE].a_un.a_val = (Elf32_Addr) &_begin;
+ /* Note: if the dynamic linker itself is prelinked, the load_addr is 0 */
+ DL_INIT_LOADADDR_BOOT(load_addr, elf_machine_load_address());
+#else
+ if (!auxvt[AT_BASE].a_un.a_val)
+ auxvt[AT_BASE].a_un.a_val = elf_machine_load_address();
+ DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val);
+#endif
+ header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+
+ /* Check the ELF header to make sure everything looks ok. */
+ if (!header || header->e_ident[EI_CLASS] != ELF_CLASS ||
+ header->e_ident[EI_VERSION] != EV_CURRENT
+ /* Do not use an inline _dl_strncmp here or some arches
+ * will blow chunks, i.e. those that need to relocate all
+ * string constants... */
+ || *(p32 = (uint32_t*)&header->e_ident) != ELFMAG_U32
+ ) {
+ SEND_EARLY_STDERR("Invalid ELF header\n");
+ _dl_exit(0);
+ }
+ SEND_EARLY_STDERR_DEBUG("ELF header=");
+ SEND_ADDRESS_STDERR_DEBUG(
+ DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, header)), 1);
+
+ /* Locate the global offset table. Since this code must be PIC
+ * we can take advantage of the magic offset register, if we
+ * happen to know what that is for this architecture. If not,
+ * we can always read stuff out of the ELF file to find it... */
+ DL_BOOT_COMPUTE_GOT(got);
+
+ /* Now, finally, fix up the location of the dynamic stuff */
+ DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)header);
+
+ SEND_EARLY_STDERR_DEBUG("First Dynamic section entry=");
+ SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
+ _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
+ tpnt->loadaddr = load_addr;
+ /* OK, that was easy. Next scan the DYNAMIC section of the image.
+ We are only doing ourself right now - we will have to do the rest later */
+ SEND_EARLY_STDERR_DEBUG("Scanning DYNAMIC section\n");
+ tpnt->dynamic_addr = dpnt;
+#if defined(NO_FUNCS_BEFORE_BOOTSTRAP)
+ /* Some architectures cannot call functions here, must inline */
+ __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
+#else
+ _dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
+#endif
+
+ /*
+ * BIG ASSUMPTION: We assume that the dynamic loader does not
+ * have any TLS data itself. If this ever occurs
+ * more work than what is done below for the
+ * loader will have to happen.
+ */
+#if defined(USE_TLS) && USE_TLS
+ /* This was done by _dl_memset above. */
+ /* tpnt->l_tls_modid = 0; */
+# if NO_TLS_OFFSET != 0
+ tpnt->l_tls_offset = NO_TLS_OFFSET;
+# endif
+#endif
+
+ SEND_EARLY_STDERR_DEBUG("Done scanning DYNAMIC section\n");
+
+#if defined(PERFORM_BOOTSTRAP_GOT)
+ SEND_EARLY_STDERR_DEBUG("About to do specific GOT bootstrap\n");
+ /* some arches (like MIPS) we have to tweak the GOT before relocations */
+ PERFORM_BOOTSTRAP_GOT(tpnt);
+#endif
+
+#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__) || defined(__mips__)
+
+ /* OK, now do the relocations. We do not do a lazy binding here, so
+ that once we are done, we have considerably more flexibility. */
+ SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n");
+
+ {
+ int indx;
+#if defined(ELF_MACHINE_PLTREL_OVERLAP)
+# define INDX_MAX 1
+#else
+# define INDX_MAX 2
+#endif
+ for (indx = 0; indx < INDX_MAX; indx++) {
+ unsigned long rel_addr, rel_size;
+ ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
+
+ rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :
+ tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);
+ rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :
+ tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);
+
+ if (!rel_addr)
+ continue;
+
+ if (!indx && relative_count) {
+ rel_size -= relative_count * sizeof(ELF_RELOC);
+#ifdef __LDSO_PRELINK_SUPPORT__
+ if (load_addr || !tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
+#endif
+ elf_machine_relative(load_addr, rel_addr, relative_count);
+ rel_addr += relative_count * sizeof(ELF_RELOC);
+ }
+
+ /*
+ * Since ldso is linked with -Bsymbolic, all relocs should be RELATIVE. All archs
+ * that need bootstrap relocations need to define ARCH_NEEDS_BOOTSTRAP_RELOCS.
+ */
+#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS
+ {
+ ELF_RELOC *rpnt;
+ unsigned int i;
+ ElfW(Sym) *sym;
+ unsigned long symbol_addr;
+ int symtab_index;
+ unsigned long *reloc_addr;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *) rel_addr;
+ for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+ reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym = NULL;
+ if (symtab_index) {
+ char *strtab;
+ ElfW(Sym) *symtab;
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ sym = &symtab[symtab_index];
+ symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value);
+#if !defined(EARLY_STDERR_SPECIAL)
+ SEND_STDERR_DEBUG("relocating symbol: ");
+ SEND_STDERR_DEBUG(strtab + sym->st_name);
+ SEND_STDERR_DEBUG("\n");
+#endif
+ } else {
+ SEND_STDERR_DEBUG("relocating unknown symbol\n");
+ }
+ /* Use this machine-specific macro to perform the actual relocation. */
+ PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
+ }
+ }
+#else /* ARCH_NEEDS_BOOTSTRAP_RELOCS */
+ if (rel_size) {
+ SEND_EARLY_STDERR("Cannot continue, found non relative relocs during the bootstrap.\n");
+ _dl_exit(14);
+ }
+#endif
+ }
+ }
+#endif
+
+ SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n");
+
+ /* Now we have done the mandatory linking of some things. We are now
+ free to start using global variables, since these things have all been
+ fixed up by now. Still no function calls outside of this library,
+ since the dynamic resolver is not yet ready. */
+
+ __rtld_stack_end = (void *)(argv - 1);
+
+ _dl_elf_main = (int (*)(int, char **, char **))
+ _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv
+ DL_GET_READY_TO_RUN_EXTRA_ARGS);
+
+ /* Transfer control to the application. */
+ SEND_STDERR_DEBUG("transfering control to application @ ");
+ SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1);
+
+#if !defined(START)
+ return _dl_elf_main;
+#else
+ START();
+#endif
+}
diff --git a/ap/build/uClibc/ldso/ldso/dl-symbols.c b/ap/build/uClibc/ldso/ldso/dl-symbols.c
new file mode 100644
index 0000000..e5c0021
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-symbols.c
@@ -0,0 +1,21 @@
+/*
+ * This contains all symbols shared between
+ * dynamic linker ld.so and into static libc
+ *
+ * Copyright (c) 2008 STMicroelectronics Ltd
+ * Author: Carmelo Amoroso <carmelo.amoroso@st.com>
+ *
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ */
+
+/*
+ * This is the start of the linked list that describes all of the files present
+ * in the system with pointers to all of the symbol, string, and hash tables,
+ * as well as all of the other good stuff in the binary.
+ */
+#include <ldso.h>
+
+struct elf_resolve *_dl_loaded_modules = NULL;
+
diff --git a/ap/build/uClibc/ldso/ldso/dl-tls.c b/ap/build/uClibc/ldso/ldso/dl-tls.c
new file mode 100644
index 0000000..a672e74
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/dl-tls.c
@@ -0,0 +1,1039 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Thread-local storage handling in the ELF dynamic linker.
+ *
+ * Copyright (C) 2005 by Steven J. Hill <sjhill@realitydiluted.com>
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 <tls.h>
+#include <dl-tls.h>
+#include <ldsodefs.h>
+
+void *(*_dl_calloc_function) (size_t __nmemb, size_t __size) = NULL;
+void *(*_dl_realloc_function) (void *__ptr, size_t __size) = NULL;
+void *(*_dl_memalign_function) (size_t __boundary, size_t __size) = NULL;
+
+void (*_dl_free_function) (void *__ptr);
+void *_dl_memalign (size_t __boundary, size_t __size);
+struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
+
+/* Round up N to the nearest multiple of P, where P is a power of 2
+ --- without using libgcc division routines. */
+#define roundup_pow2(n, p) (((n) + (p) - 1) & ~((p) - 1))
+
+void *
+_dl_calloc (size_t __nmemb, size_t __size)
+{
+ void *result;
+ size_t size = (__size * __nmemb);
+
+ if (_dl_calloc_function)
+ return (*_dl_calloc_function) (__nmemb, __size);
+
+ if ((result = _dl_malloc(size)) != NULL) {
+ _dl_memset(result, 0, size);
+ }
+
+ return result;
+}
+
+void *
+_dl_realloc (void * __ptr, size_t __size)
+{
+ if (_dl_realloc_function)
+ return (*_dl_realloc_function) (__ptr, __size);
+
+ _dl_debug_early("NOT IMPLEMENTED PROPERLY!!!\n");
+ return NULL;
+}
+
+/* The __tls_get_addr function has two basic forms which differ in the
+ arguments. The IA-64 form takes two parameters, the module ID and
+ offset. The form used, among others, on IA-32 takes a reference to
+ a special structure which contain the same information. The second
+ form seems to be more often used (in the moment) so we default to
+ it. Users of the IA-64 form have to provide adequate definitions
+ of the following macros. */
+#ifndef GET_ADDR_ARGS
+# define GET_ADDR_ARGS tls_index *ti
+#endif
+#ifndef GET_ADDR_MODULE
+# define GET_ADDR_MODULE ti->ti_module
+#endif
+#ifndef GET_ADDR_OFFSET
+# define GET_ADDR_OFFSET ti->ti_offset
+#endif
+
+/*
+ * Amount of excess space to allocate in the static TLS area
+ * to allow dynamic loading of modules defining IE-model TLS data.
+ */
+#define TLS_STATIC_SURPLUS 64 + DL_NNS * 100
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
+
+/*
+ * We are trying to perform a static TLS relocation in MAP, but it was
+ * dynamically loaded. This can only work if there is enough surplus in
+ * the static TLS area already allocated for each running thread. If this
+ * object's TLS segment is too big to fit, we fail. If it fits,
+ * we set MAP->l_tls_offset and return.
+ * This function intentionally does not return any value but signals error
+ * directly, as static TLS should be rare and code handling it should
+ * not be inlined as much as possible.
+ */
+void
+internal_function __attribute_noinline__
+_dl_allocate_static_tls (struct link_map *map)
+{
+ /* If the alignment requirements are too high fail. */
+ if (map->l_tls_align > _dl_tls_static_align)
+ {
+fail:
+ _dl_dprintf(2, "cannot allocate memory in static TLS block");
+ _dl_exit(30);
+ }
+
+# ifdef TLS_TCB_AT_TP
+ size_t freebytes;
+ size_t n;
+ size_t blsize;
+
+ freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE;
+
+ blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
+ if (freebytes < blsize)
+ goto fail;
+
+ n = (freebytes - blsize) & ~(map->l_tls_align - 1);
+
+ size_t offset = _dl_tls_static_used + (freebytes - n
+ - map->l_tls_firstbyte_offset);
+
+ map->l_tls_offset = _dl_tls_static_used = offset;
+# elif defined(TLS_DTV_AT_TP)
+ size_t used;
+ size_t check;
+
+ size_t offset = roundup_pow2 (_dl_tls_static_used, map->l_tls_align);
+ used = offset + map->l_tls_blocksize;
+ check = used;
+
+ /* dl_tls_static_used includes the TCB at the beginning. */
+ if (check > _dl_tls_static_size)
+ goto fail;
+
+ map->l_tls_offset = offset;
+ _dl_tls_static_used = used;
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /*
+ * If the object is not yet relocated we cannot initialize the
+ * static TLS region. Delay it.
+ */
+ if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE)
+ {
+#ifdef SHARED
+ /*
+ * Update the slot information data for at least the generation of
+ * the DSO we are allocating data for.
+ */
+ if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0))
+ (void) _dl_update_slotinfo (map->l_tls_modid);
+#endif
+ _dl_init_static_tls (map);
+ }
+ else
+ map->l_need_tls_init = 1;
+}
+
+#ifdef SHARED
+/* Initialize static TLS area and DTV for current (only) thread.
+ libpthread implementations should provide their own hook
+ to handle all threads. */
+void
+attribute_hidden __attribute_noinline__
+_dl_nothread_init_static_tls (struct link_map *map)
+{
+# ifdef TLS_TCB_AT_TP
+ void *dest = (char *) THREAD_SELF - map->l_tls_offset;
+# elif defined(TLS_DTV_AT_TP)
+ void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /* Fill in the DTV slot so that a later LD/GD access will find it. */
+ dtv_t *dtv = THREAD_DTV ();
+ if (!(map->l_tls_modid <= dtv[-1].counter)) {
+ _dl_dprintf(2, "map->l_tls_modid <= dtv[-1].counter FAILED!\n");
+ _dl_exit(30);
+ }
+ dtv[map->l_tls_modid].pointer.val = dest;
+ dtv[map->l_tls_modid].pointer.is_static = true;
+
+ /* Initialize the memory. */
+ _dl_memcpy(dest, map->l_tls_initimage, map->l_tls_initimage_size);
+ _dl_memset((dest + map->l_tls_initimage_size), '\0',
+ map->l_tls_blocksize - map->l_tls_initimage_size);
+}
+#endif
+
+/* Taken from glibc/sysdeps/generic/dl-tls.c */
+static void
+oom (void)
+{
+ _dl_debug_early("cannot allocate thread-local memory: ABORT\n");
+ _dl_exit(30);
+}
+
+size_t
+internal_function
+_dl_next_tls_modid (void)
+{
+ size_t result;
+
+ if (__builtin_expect (_dl_tls_dtv_gaps, false))
+ {
+ size_t disp = 0;
+ struct dtv_slotinfo_list *runp = _dl_tls_dtv_slotinfo_list;
+
+ /* Note that this branch will never be executed during program
+ start since there are no gaps at that time. Therefore it
+ does not matter that the dl_tls_dtv_slotinfo is not allocated
+ yet when the function is called for the first times.
+
+ NB: the offset +1 is due to the fact that DTV[0] is used
+ for something else. */
+ result = _dl_tls_static_nelem + 1;
+ if (result <= _dl_tls_max_dtv_idx)
+ do
+ {
+ while (result - disp < runp->len)
+ {
+ if (runp->slotinfo[result - disp].map == NULL)
+ break;
+
+ ++result;
+ _dl_assert (result <= _dl_tls_max_dtv_idx + 1);
+ }
+
+ if (result - disp < runp->len)
+ break;
+
+ disp += runp->len;
+ }
+ while ((runp = runp->next) != NULL);
+
+ if (result > _dl_tls_max_dtv_idx)
+ {
+ /* The new index must indeed be exactly one higher than the
+ previous high. */
+ _dl_assert (result == _dl_tls_max_dtv_idx + 1);
+ /* There is no gap anymore. */
+ _dl_tls_dtv_gaps = false;
+
+ goto nogaps;
+ }
+ }
+ else
+ {
+ /* No gaps, allocate a new entry. */
+ nogaps:
+
+ result = ++_dl_tls_max_dtv_idx;
+ }
+
+ return result;
+}
+
+void
+internal_function
+_dl_determine_tlsoffset (void)
+{
+ size_t max_align = TLS_TCB_ALIGN;
+ size_t freetop = 0;
+ size_t freebottom = 0;
+
+ /* The first element of the dtv slot info list is allocated. */
+ _dl_assert (_dl_tls_dtv_slotinfo_list != NULL);
+ /* There is at this point only one element in the
+ dl_tls_dtv_slotinfo_list list. */
+ _dl_assert (_dl_tls_dtv_slotinfo_list->next == NULL);
+
+ struct dtv_slotinfo *slotinfo = _dl_tls_dtv_slotinfo_list->slotinfo;
+
+ /* Determining the offset of the various parts of the static TLS
+ block has several dependencies. In addition we have to work
+ around bugs in some toolchains.
+
+ Each TLS block from the objects available at link time has a size
+ and an alignment requirement. The GNU ld computes the alignment
+ requirements for the data at the positions *in the file*, though.
+ I.e, it is not simply possible to allocate a block with the size
+ of the TLS program header entry. The data is layed out assuming
+ that the first byte of the TLS block fulfills
+
+ p_vaddr mod p_align == &TLS_BLOCK mod p_align
+
+ This means we have to add artificial padding at the beginning of
+ the TLS block. These bytes are never used for the TLS data in
+ this module but the first byte allocated must be aligned
+ according to mod p_align == 0 so that the first byte of the TLS
+ block is aligned according to p_vaddr mod p_align. This is ugly
+ and the linker can help by computing the offsets in the TLS block
+ assuming the first byte of the TLS block is aligned according to
+ p_align.
+
+ The extra space which might be allocated before the first byte of
+ the TLS block need not go unused. The code below tries to use
+ that memory for the next TLS block. This can work if the total
+ memory requirement for the next TLS block is smaller than the
+ gap. */
+
+# ifdef TLS_TCB_AT_TP
+ /* We simply start with zero. */
+ size_t cnt, offset = 0;
+
+ for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt)
+ {
+ _dl_assert (cnt < _dl_tls_dtv_slotinfo_list->len);
+
+ size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset
+ & (slotinfo[cnt].map->l_tls_align - 1));
+ size_t off;
+ max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align);
+
+ if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize)
+ {
+ off = roundup_pow2 (freetop + slotinfo[cnt].map->l_tls_blocksize
+ - firstbyte, slotinfo[cnt].map->l_tls_align)
+ + firstbyte;
+ if (off <= freebottom)
+ {
+ freetop = off;
+
+ /* XXX For some architectures we perhaps should store the
+ negative offset. */
+ slotinfo[cnt].map->l_tls_offset = off;
+ continue;
+ }
+ }
+
+ off = roundup_pow2 (offset + slotinfo[cnt].map->l_tls_blocksize
+ - firstbyte, slotinfo[cnt].map->l_tls_align)
+ + firstbyte;
+ if (off > offset + slotinfo[cnt].map->l_tls_blocksize
+ + (freebottom - freetop))
+ {
+ freetop = offset;
+ freebottom = off - slotinfo[cnt].map->l_tls_blocksize;
+ }
+ offset = off;
+
+ /* XXX For some architectures we perhaps should store the
+ negative offset. */
+ slotinfo[cnt].map->l_tls_offset = off;
+ }
+
+ _dl_tls_static_used = offset;
+ _dl_tls_static_size = (roundup_pow2 (offset + TLS_STATIC_SURPLUS, max_align)
+ + TLS_TCB_SIZE);
+# elif defined(TLS_DTV_AT_TP)
+ /* The TLS blocks start right after the TCB. */
+ size_t offset = TLS_TCB_SIZE;
+ size_t cnt;
+
+ for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt)
+ {
+ _dl_assert (cnt < _dl_tls_dtv_slotinfo_list->len);
+
+ size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset
+ & (slotinfo[cnt].map->l_tls_align - 1));
+ size_t off;
+ max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align);
+
+ if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom)
+ {
+ off = roundup_pow2 (freebottom, slotinfo[cnt].map->l_tls_align);
+ if (off - freebottom < firstbyte)
+ off += slotinfo[cnt].map->l_tls_align;
+ if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop)
+ {
+ slotinfo[cnt].map->l_tls_offset = off - firstbyte;
+ freebottom = (off + slotinfo[cnt].map->l_tls_blocksize
+ - firstbyte);
+ continue;
+ }
+ }
+
+ off = roundup_pow2 (offset, slotinfo[cnt].map->l_tls_align);
+ if (off - offset < firstbyte)
+ off += slotinfo[cnt].map->l_tls_align;
+
+ slotinfo[cnt].map->l_tls_offset = off - firstbyte;
+ if (off - firstbyte - offset > freetop - freebottom)
+ {
+ freebottom = offset;
+ freetop = off - firstbyte;
+ }
+
+ offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte;
+ }
+
+ _dl_tls_static_used = offset;
+ _dl_tls_static_size = roundup_pow2 (offset + TLS_STATIC_SURPLUS,
+ TLS_TCB_ALIGN);
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /* The alignment requirement for the static TLS block. */
+ _dl_tls_static_align = max_align;
+}
+
+/* This is called only when the data structure setup was skipped at startup,
+ when there was no need for it then. Now we have dynamically loaded
+ something needing TLS, or libpthread needs it. */
+rtld_hidden_proto(_dl_tls_setup)
+int
+internal_function
+_dl_tls_setup (void)
+{
+ _dl_assert (_dl_tls_dtv_slotinfo_list == NULL);
+ _dl_assert (_dl_tls_max_dtv_idx == 0);
+
+ const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS;
+
+ _dl_tls_dtv_slotinfo_list
+ = _dl_calloc (1, (sizeof (struct dtv_slotinfo_list)
+ + nelem * sizeof (struct dtv_slotinfo)));
+ if (_dl_tls_dtv_slotinfo_list == NULL)
+ return -1;
+
+ _dl_tls_dtv_slotinfo_list->len = nelem;
+
+ /* Number of elements in the static TLS block. It can't be zero
+ because of various assumptions. The one element is null. */
+ _dl_tls_static_nelem = _dl_tls_max_dtv_idx = 1;
+
+ /* This initializes more variables for us. */
+ _dl_determine_tlsoffset ();
+
+ return 0;
+}
+rtld_hidden_def (_dl_tls_setup)
+
+static void *
+internal_function
+allocate_dtv (void *result)
+{
+ dtv_t *dtv;
+ size_t dtv_length;
+
+ /* We allocate a few more elements in the dtv than are needed for the
+ initial set of modules. This should avoid in most cases expansions
+ of the dtv. */
+ dtv_length = _dl_tls_max_dtv_idx + DTV_SURPLUS;
+ dtv = _dl_calloc (dtv_length + 2, sizeof (dtv_t));
+ if (dtv != NULL)
+ {
+ /* This is the initial length of the dtv. */
+ dtv[0].counter = dtv_length;
+
+ /* The rest of the dtv (including the generation counter) is
+ Initialize with zero to indicate nothing there. */
+
+ /* Add the dtv to the thread data structures. */
+ INSTALL_DTV (result, dtv);
+ }
+ else
+ result = NULL;
+
+ return result;
+}
+
+/* Get size and alignment requirements of the static TLS block. */
+void
+internal_function
+_dl_get_tls_static_info (size_t *sizep, size_t *alignp)
+{
+ *sizep = _dl_tls_static_size;
+ *alignp = _dl_tls_static_align;
+}
+
+void *
+internal_function
+_dl_allocate_tls_storage (void)
+{
+ void *result;
+ size_t size = _dl_tls_static_size;
+
+# if defined(TLS_DTV_AT_TP)
+ /* Memory layout is:
+ [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ]
+ ^ This should be returned. */
+ size += (TLS_PRE_TCB_SIZE + _dl_tls_static_align - 1)
+ & ~(_dl_tls_static_align - 1);
+# endif
+
+ /* Allocate a correctly aligned chunk of memory. */
+ result = _dl_memalign (_dl_tls_static_align, size);
+ if (__builtin_expect (result != NULL, 1))
+ {
+ /* Allocate the DTV. */
+ void *allocated = result;
+
+# ifdef TLS_TCB_AT_TP
+ /* The TCB follows the TLS blocks. */
+ result = (char *) result + size - TLS_TCB_SIZE;
+
+ /* Clear the TCB data structure. We can't ask the caller (i.e.
+ libpthread) to do it, because we will initialize the DTV et al. */
+ _dl_memset (result, '\0', TLS_TCB_SIZE);
+# elif defined(TLS_DTV_AT_TP)
+ result = (char *) result + size - _dl_tls_static_size;
+
+ /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it.
+ We can't ask the caller (i.e. libpthread) to do it, because we will
+ initialize the DTV et al. */
+ _dl_memset ((char *) result - TLS_PRE_TCB_SIZE, '\0',
+ TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
+# endif
+
+ result = allocate_dtv (result);
+ if (result == NULL)
+ _dl_free (allocated);
+ }
+
+ return result;
+}
+
+void *
+internal_function
+_dl_allocate_tls_init (void *result)
+{
+ if (result == NULL)
+ /* The memory allocation failed. */
+ return NULL;
+
+ dtv_t *dtv = GET_DTV (result);
+ struct dtv_slotinfo_list *listp;
+ size_t total = 0;
+ size_t maxgen = 0;
+
+ /* We have to prepare the dtv for all currently loaded modules using
+ TLS. For those which are dynamically loaded we add the values
+ indicating deferred allocation. */
+ listp = _dl_tls_dtv_slotinfo_list;
+ while (1)
+ {
+ size_t cnt;
+
+ for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
+ {
+ struct link_map *map;
+ void *dest;
+
+ /* Check for the total number of used slots. */
+ if (total + cnt > _dl_tls_max_dtv_idx)
+ break;
+
+ map = listp->slotinfo[cnt].map;
+ if (map == NULL)
+ /* Unused entry. */
+ continue;
+
+ /* Keep track of the maximum generation number. This might
+ not be the generation counter. */
+ maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
+
+ if (map->l_tls_offset == NO_TLS_OFFSET)
+ {
+ /* For dynamically loaded modules we simply store
+ the value indicating deferred allocation. */
+ dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+ dtv[map->l_tls_modid].pointer.is_static = false;
+ continue;
+ }
+
+ _dl_assert (map->l_tls_modid == cnt);
+ _dl_assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
+# ifdef TLS_TCB_AT_TP
+ _dl_assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize);
+ dest = (char *) result - map->l_tls_offset;
+# elif defined(TLS_DTV_AT_TP)
+ dest = (char *) result + map->l_tls_offset;
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /* Copy the initialization image and clear the BSS part. */
+ dtv[map->l_tls_modid].pointer.val = dest;
+ dtv[map->l_tls_modid].pointer.is_static = true;
+ _dl_memcpy(dest, map->l_tls_initimage, map->l_tls_initimage_size);
+ _dl_memset((dest + map->l_tls_initimage_size), '\0',
+ map->l_tls_blocksize - map->l_tls_initimage_size);
+
+ }
+
+ total += cnt;
+ if (total >= _dl_tls_max_dtv_idx)
+ break;
+
+ listp = listp->next;
+ _dl_assert (listp != NULL);
+ }
+
+ /* The DTV version is up-to-date now. */
+ dtv[0].counter = maxgen;
+
+ return result;
+}
+
+void *
+internal_function
+_dl_allocate_tls (void *mem)
+{
+ return _dl_allocate_tls_init (mem == NULL
+ ? _dl_allocate_tls_storage ()
+ : allocate_dtv (mem));
+}
+
+void
+internal_function
+_dl_deallocate_tls (void *tcb, bool dealloc_tcb)
+{
+ dtv_t *dtv = GET_DTV (tcb);
+ size_t cnt;
+
+ /* We need to free the memory allocated for non-static TLS. */
+ for (cnt = 0; cnt < dtv[-1].counter; ++cnt)
+ if (! dtv[1 + cnt].pointer.is_static
+ && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
+ _dl_free (dtv[1 + cnt].pointer.val);
+
+ /* The array starts with dtv[-1]. */
+ if (dtv != _dl_initial_dtv)
+ _dl_free (dtv - 1);
+
+ if (dealloc_tcb)
+ {
+# ifdef TLS_TCB_AT_TP
+ /* The TCB follows the TLS blocks. Back up to free the whole block. */
+ tcb -= _dl_tls_static_size - TLS_TCB_SIZE;
+# elif defined(TLS_DTV_AT_TP)
+ /* Back up the TLS_PRE_TCB_SIZE bytes. */
+ tcb -= (TLS_PRE_TCB_SIZE + _dl_tls_static_align - 1)
+ & ~(_dl_tls_static_align - 1);
+# endif
+ _dl_free (tcb);
+ }
+}
+
+static void *
+allocate_and_init (struct link_map *map)
+{
+ void *newp;
+
+ newp = _dl_memalign (map->l_tls_align, map->l_tls_blocksize);
+ if (newp == NULL)
+ {
+ _dl_dprintf(2, "%s:%d: Out of memory!!!\n", __func__, __LINE__);
+ _dl_exit(1);
+ }
+
+ /* Initialize the memory. */
+ _dl_memcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size);
+ _dl_memset ((newp + map->l_tls_initimage_size), '\0',
+ map->l_tls_blocksize - map->l_tls_initimage_size);
+
+ return newp;
+}
+
+struct link_map *
+_dl_update_slotinfo (unsigned long int req_modid)
+{
+ struct link_map *the_map = NULL;
+ dtv_t *dtv = THREAD_DTV ();
+
+ /* The global dl_tls_dtv_slotinfo array contains for each module
+ index the generation counter current when the entry was created.
+ This array never shrinks so that all module indices which were
+ valid at some time can be used to access it. Before the first
+ use of a new module index in this function the array was extended
+ appropriately. Access also does not have to be guarded against
+ modifications of the array. It is assumed that pointer-size
+ values can be read atomically even in SMP environments. It is
+ possible that other threads at the same time dynamically load
+ code and therefore add to the slotinfo list. This is a problem
+ since we must not pick up any information about incomplete work.
+ The solution to this is to ignore all dtv slots which were
+ created after the one we are currently interested. We know that
+ dynamic loading for this module is completed and this is the last
+ load operation we know finished. */
+ unsigned long int idx = req_modid;
+ struct dtv_slotinfo_list *listp = _dl_tls_dtv_slotinfo_list;
+
+ _dl_debug_early ("Updating slotinfo for module %d\n", req_modid);
+
+ while (idx >= listp->len)
+ {
+ idx -= listp->len;
+ listp = listp->next;
+ }
+
+ if (dtv[0].counter < listp->slotinfo[idx].gen)
+ {
+ /* The generation counter for the slot is higher than what the
+ current dtv implements. We have to update the whole dtv but
+ only those entries with a generation counter <= the one for
+ the entry we need. */
+ size_t new_gen = listp->slotinfo[idx].gen;
+ size_t total = 0;
+
+ /* We have to look through the entire dtv slotinfo list. */
+ listp = _dl_tls_dtv_slotinfo_list;
+ do
+ {
+ size_t cnt;
+
+ for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
+ {
+ size_t gen = listp->slotinfo[cnt].gen;
+
+ if (gen > new_gen)
+ /* This is a slot for a generation younger than the
+ one we are handling now. It might be incompletely
+ set up so ignore it. */
+ continue;
+
+ /* If the entry is older than the current dtv layout we
+ know we don't have to handle it. */
+ if (gen <= dtv[0].counter)
+ continue;
+
+ /* If there is no map this means the entry is empty. */
+ struct link_map *map = listp->slotinfo[cnt].map;
+ if (map == NULL)
+ {
+ /* If this modid was used at some point the memory
+ might still be allocated. */
+ if (! dtv[total + cnt].pointer.is_static
+ && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
+ {
+ _dl_free (dtv[total + cnt].pointer.val);
+ dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
+ }
+
+ continue;
+ }
+
+ /* Check whether the current dtv array is large enough. */
+ size_t modid = map->l_tls_modid;
+ _dl_assert (total + cnt == modid);
+ if (dtv[-1].counter < modid)
+ {
+ /* Reallocate the dtv. */
+ dtv_t *newp;
+ size_t newsize = _dl_tls_max_dtv_idx + DTV_SURPLUS;
+ size_t oldsize = dtv[-1].counter;
+
+ _dl_assert (map->l_tls_modid <= newsize);
+
+ if (dtv == _dl_initial_dtv)
+ {
+ /* This is the initial dtv that was allocated
+ during rtld startup using the dl-minimal.c
+ malloc instead of the real malloc. We can't
+ free it, we have to abandon the old storage. */
+
+ newp = _dl_malloc ((2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ _dl_memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
+ }
+ else
+ {
+ newp = _dl_realloc (&dtv[-1],
+ (2 + newsize) * sizeof (dtv_t));
+ if (newp == NULL)
+ oom ();
+ }
+
+ newp[0].counter = newsize;
+
+ /* Clear the newly allocated part. */
+ _dl_memset (newp + 2 + oldsize, '\0',
+ (newsize - oldsize) * sizeof (dtv_t));
+
+ /* Point dtv to the generation counter. */
+ dtv = &newp[1];
+
+ /* Install this new dtv in the thread data
+ structures. */
+ INSTALL_NEW_DTV (dtv);
+ }
+
+ /* If there is currently memory allocate for this
+ dtv entry free it. */
+ /* XXX Ideally we will at some point create a memory
+ pool. */
+ if (! dtv[modid].pointer.is_static
+ && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
+ /* Note that free is called for NULL is well. We
+ deallocate even if it is this dtv entry we are
+ supposed to load. The reason is that we call
+ memalign and not malloc. */
+ _dl_free (dtv[modid].pointer.val);
+
+ /* This module is loaded dynamically- We defer memory
+ allocation. */
+ dtv[modid].pointer.is_static = false;
+ dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+
+ if (modid == req_modid)
+ the_map = map;
+ }
+
+ total += listp->len;
+ }
+ while ((listp = listp->next) != NULL);
+
+ /* This will be the new maximum generation counter. */
+ dtv[0].counter = new_gen;
+ }
+
+ return the_map;
+}
+
+
+/* The generic dynamic and local dynamic model cannot be used in
+ statically linked applications. */
+void *
+__tls_get_addr (GET_ADDR_ARGS)
+{
+ dtv_t *dtv = THREAD_DTV ();
+ struct link_map *the_map = NULL;
+ void *p;
+
+ if (__builtin_expect (dtv[0].counter != _dl_tls_generation, 0))
+ {
+ the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+ dtv = THREAD_DTV ();
+ }
+
+ p = dtv[GET_ADDR_MODULE].pointer.val;
+
+ if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
+ {
+ /* The allocation was deferred. Do it now. */
+ if (the_map == NULL)
+ {
+ /* Find the link map for this module. */
+ size_t idx = GET_ADDR_MODULE;
+ struct dtv_slotinfo_list *listp = _dl_tls_dtv_slotinfo_list;
+
+ while (idx >= listp->len)
+ {
+ idx -= listp->len;
+ listp = listp->next;
+ }
+
+ the_map = listp->slotinfo[idx].map;
+ }
+
+ p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
+ dtv[GET_ADDR_MODULE].pointer.is_static = false;
+ }
+
+ return (char *) p + GET_ADDR_OFFSET;
+}
+
+void
+_dl_add_to_slotinfo (struct link_map *l)
+{
+ /* Now that we know the object is loaded successfully add
+ modules containing TLS data to the dtv info table. We
+ might have to increase its size. */
+ struct dtv_slotinfo_list *listp;
+ struct dtv_slotinfo_list *prevp;
+ size_t idx = l->l_tls_modid;
+
+ _dl_debug_early("Adding to slotinfo for %s\n", l->l_name);
+
+ /* Find the place in the dtv slotinfo list. */
+ listp = _dl_tls_dtv_slotinfo_list;
+ prevp = NULL; /* Needed to shut up gcc. */
+ do
+ {
+ /* Does it fit in the array of this list element? */
+ if (idx < listp->len)
+ break;
+ idx -= listp->len;
+ prevp = listp;
+ listp = listp->next;
+ }
+ while (listp != NULL);
+
+ if (listp == NULL)
+ {
+ /* When we come here it means we have to add a new element
+ to the slotinfo list. And the new module must be in
+ the first slot. */
+ _dl_assert (idx == 0);
+
+ listp = prevp->next = (struct dtv_slotinfo_list *)
+ _dl_malloc (sizeof (struct dtv_slotinfo_list)
+ + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ if (listp == NULL)
+ {
+ /* We ran out of memory. We will simply fail this
+ call but don't undo anything we did so far. The
+ application will crash or be terminated anyway very
+ soon. */
+
+ /* We have to do this since some entries in the dtv
+ slotinfo array might already point to this
+ generation. */
+ ++_dl_tls_generation;
+
+ _dl_dprintf (_dl_debug_file,
+ "cannot create TLS data structures: ABORT\n");
+ _dl_exit (127);
+ }
+
+ listp->len = TLS_SLOTINFO_SURPLUS;
+ listp->next = NULL;
+ _dl_memset (listp->slotinfo, '\0',
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ }
+
+ /* Add the information into the slotinfo data structure. */
+ listp->slotinfo[idx].map = l;
+ listp->slotinfo[idx].gen = _dl_tls_generation + 1;
+ /* ??? ideally this would be done once per call to dlopen. However there's
+ no easy way to indicate whether a library used TLS, so do it here
+ instead. */
+ /* Bump the TLS generation number. */
+ _dl_tls_generation++;
+}
+
+/* Taken from glibc/elf/rtld.c */
+static bool tls_init_tp_called;
+
+/* _dl_error_catch_tsd points to this for the single-threaded case.
+ It's reset by the thread library for multithreaded programs. */
+void ** __attribute__ ((const))
+_dl_initial_error_catch_tsd (void)
+{
+ static void *data;
+ return &data;
+}
+
+#ifdef SHARED
+void*
+internal_function
+init_tls (void);
+
+rtld_hidden_proto(init_tls)
+void *
+internal_function
+init_tls (void)
+{
+ /* Number of elements in the static TLS block. */
+ _dl_tls_static_nelem = _dl_tls_max_dtv_idx;
+
+ /* Do not do this twice. The audit interface might have required
+ the DTV interfaces to be set up early. */
+ if (_dl_initial_dtv != NULL)
+ return NULL;
+
+ /* Allocate the array which contains the information about the
+ dtv slots. We allocate a few entries more than needed to
+ avoid the need for reallocation. */
+ size_t nelem = _dl_tls_max_dtv_idx + 1 + TLS_SLOTINFO_SURPLUS;
+
+ /* Allocate. */
+ _dl_assert (_dl_tls_dtv_slotinfo_list == NULL);
+ _dl_tls_dtv_slotinfo_list = (struct dtv_slotinfo_list *)
+ _dl_calloc (sizeof (struct dtv_slotinfo_list)
+ + nelem * sizeof (struct dtv_slotinfo), 1);
+ /* No need to check the return value. If memory allocation failed
+ the program would have been terminated. */
+
+ struct dtv_slotinfo *slotinfo = _dl_tls_dtv_slotinfo_list->slotinfo;
+ _dl_tls_dtv_slotinfo_list->len = nelem;
+ _dl_tls_dtv_slotinfo_list->next = NULL;
+
+ /* Fill in the information from the loaded modules. No namespace
+ but the base one can be filled at this time. */
+ int i = 0;
+ struct link_map *l;
+ for (l = (struct link_map *) _dl_loaded_modules; l != NULL; l = l->l_next)
+ if (l->l_tls_blocksize != 0)
+ {
+ /* This is a module with TLS data. Store the map reference.
+ The generation counter is zero. */
+
+ /* Skeep slot[0]: it will be never used */
+ slotinfo[++i].map = l;
+ }
+ _dl_assert (i == _dl_tls_max_dtv_idx);
+
+ /* Compute the TLS offsets for the various blocks. */
+ _dl_determine_tlsoffset ();
+
+ /* Construct the static TLS block and the dtv for the initial
+ thread. For some platforms this will include allocating memory
+ for the thread descriptor. The memory for the TLS block will
+ never be freed. It should be allocated accordingly. The dtv
+ array can be changed if dynamic loading requires it. */
+ void *tcbp = _dl_allocate_tls_storage ();
+ if (tcbp == NULL) {
+ _dl_debug_early("\ncannot allocate TLS data structures for initial thread");
+ _dl_exit(30);
+ }
+
+ /* Store for detection of the special case by __tls_get_addr
+ so it knows not to pass this dtv to the normal realloc. */
+ _dl_initial_dtv = GET_DTV (tcbp);
+
+ /* And finally install it for the main thread. If ld.so itself uses
+ TLS we know the thread pointer was initialized earlier. */
+ const char *lossage = (char *)TLS_INIT_TP (tcbp, USE___THREAD);
+ if(__builtin_expect (lossage != NULL, 0)) {
+ _dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
+ _dl_exit(30);
+ }
+ tls_init_tp_called = true;
+
+ return tcbp;
+}
+rtld_hidden_def (init_tls)
+#endif
+
diff --git a/ap/build/uClibc/ldso/ldso/fdpic/dl-inlines.h b/ap/build/uClibc/ldso/ldso/fdpic/dl-inlines.h
new file mode 100644
index 0000000..14a4916
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/fdpic/dl-inlines.h
@@ -0,0 +1,472 @@
+/* Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete load map. */
+static __always_inline void
+__dl_init_loadaddr_map(struct elf32_fdpic_loadaddr *loadaddr, Elf32_Addr dl_boot_got_pointer,
+ struct elf32_fdpic_loadmap *map)
+{
+ if (map->version != 0) {
+ SEND_EARLY_STDERR("Invalid loadmap version number\n");
+ _dl_exit(-1);
+ }
+ if (map->nsegs == 0) {
+ SEND_EARLY_STDERR("Invalid segment count in loadmap\n");
+ _dl_exit(-1);
+ }
+ loadaddr->got_value = (void *)dl_boot_got_pointer;
+ loadaddr->map = map;
+}
+
+/*
+ * Figure out how many LOAD segments there are in the given headers,
+ * and allocate a block for the load map big enough for them.
+ * got_value will be properly initialized later on, with INIT_GOT.
+ */
+static __always_inline int
+__dl_init_loadaddr(struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt,
+ int pcnt)
+{
+ int count = 0, i;
+ size_t size;
+
+ for (i = 0; i < pcnt; i++)
+ if (ppnt[i].p_type == PT_LOAD)
+ count++;
+
+ loadaddr->got_value = 0;
+
+ size = sizeof(struct elf32_fdpic_loadmap) +
+ (sizeof(struct elf32_fdpic_loadseg) * count);
+ loadaddr->map = _dl_malloc(size);
+ if (!loadaddr->map)
+ _dl_exit(-1);
+
+ loadaddr->map->version = 0;
+ loadaddr->map->nsegs = 0;
+
+ return count;
+}
+
+/* Incrementally initialize a load map. */
+static __always_inline void
+__dl_init_loadaddr_hdr(struct elf32_fdpic_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr, int maxsegs)
+{
+ struct elf32_fdpic_loadseg *segdata;
+
+ if (loadaddr.map->nsegs == maxsegs)
+ _dl_exit(-1);
+
+ segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
+ segdata->addr = (Elf32_Addr)addr;
+ segdata->p_vaddr = phdr->p_vaddr;
+ segdata->p_memsz = phdr->p_memsz;
+
+#if defined(__SUPPORT_LD_DEBUG__)
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+ loadaddr.map->nsegs - 1,
+ segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+#endif
+}
+
+/* Replace an existing entry in the load map. */
+static __always_inline void
+__dl_update_loadaddr_hdr(struct elf32_fdpic_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr)
+{
+ struct elf32_fdpic_loadseg *segdata;
+ void *oldaddr;
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ if (loadaddr.map->segs[i].p_vaddr == phdr->p_vaddr &&
+ loadaddr.map->segs[i].p_memsz == phdr->p_memsz)
+ break;
+ if (i == loadaddr.map->nsegs)
+ _dl_exit(-1);
+
+ segdata = loadaddr.map->segs + i;
+ oldaddr = (void *)segdata->addr;
+ _dl_munmap(oldaddr, segdata->p_memsz);
+ segdata->addr = (Elf32_Addr)addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: changed mapping %x at %x (old %x), size %x\n",
+ loadaddr.map->nsegs - 1,
+ segdata->p_vaddr, segdata->addr, oldaddr, segdata->p_memsz);
+#endif
+}
+
+
+#ifndef __dl_loadaddr_unmap
+static __always_inline void
+__dl_loadaddr_unmap(struct elf32_fdpic_loadaddr loadaddr,
+ struct funcdesc_ht *funcdesc_ht)
+{
+ int i;
+
+ for (i = 0; i < loadaddr.map->nsegs; i++)
+ _dl_munmap((void *)loadaddr.map->segs[i].addr,
+ loadaddr.map->segs[i].p_memsz);
+
+ /*
+ * _dl_unmap is only called for dlopen()ed libraries, for which
+ * calling free() is safe, or before we've completed the initial
+ * relocation, in which case calling free() is probably pointless,
+ * but still safe.
+ */
+ _dl_free(loadaddr.map);
+ if (funcdesc_ht)
+ htab_delete(funcdesc_ht);
+}
+#endif
+
+/* Figure out whether the given address is in one of the mapped segments. */
+static __always_inline int
+__dl_addr_in_loadaddr(void *p, struct elf32_fdpic_loadaddr loadaddr)
+{
+ struct elf32_fdpic_loadmap *map = loadaddr.map;
+ int c;
+
+ for (c = 0; c < map->nsegs; c++)
+ if ((void *)map->segs[c].addr <= p &&
+ (char *)p < (char *)map->segs[c].addr + map->segs[c].p_memsz)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * The hashcode handling code below is heavily inspired in libiberty's
+ * hashtab code, but with most adaptation points and support for
+ * deleting elements removed.
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Contributed by Vladimir Makarov (vmakarov@cygnus.com).
+ */
+static __always_inline unsigned long
+higher_prime_number(unsigned long n)
+{
+ /* These are primes that are near, but slightly smaller than, a power of two. */
+ static const unsigned long primes[] = {
+ 7,
+ 13,
+ 31,
+ 61,
+ 127,
+ 251,
+ 509,
+ 1021,
+ 2039,
+ 4093,
+ 8191,
+ 16381,
+ 32749,
+ 65521,
+ 131071,
+ 262139,
+ 524287,
+ 1048573,
+ 2097143,
+ 4194301,
+ 8388593,
+ 16777213,
+ 33554393,
+ 67108859,
+ 134217689,
+ 268435399,
+ 536870909,
+ 1073741789,
+ /* 4294967291 */
+ ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
+ };
+ const unsigned long *low = &primes[0];
+ const unsigned long *high = &primes[ARRAY_SIZE(primes)];
+
+ while (low != high) {
+ const unsigned long *mid = low + (high - low) / 2;
+ if (n > *mid)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+#if 0
+ /* If we've run out of primes, abort. */
+ if (n > *low) {
+ fprintf(stderr, "Cannot find prime bigger than %lu\n", n);
+ abort();
+ }
+#endif
+
+ return *low;
+}
+
+struct funcdesc_ht
+{
+ /* Table itself */
+ struct funcdesc_value **entries;
+
+ /* Current size (in entries) of the hash table */
+ size_t size;
+
+ /* Current number of elements */
+ size_t n_elements;
+};
+
+static __always_inline int
+hash_pointer(const void *p)
+{
+ return (int) ((long)p >> 3);
+}
+
+static __always_inline struct funcdesc_ht *
+htab_create(void)
+{
+ struct funcdesc_ht *ht = _dl_malloc(sizeof(*ht));
+ size_t ent_size;
+
+ if (!ht)
+ return NULL;
+ ht->size = 3;
+ ent_size = sizeof(struct funcdesc_ht_value *) * ht->size;
+ ht->entries = _dl_malloc(ent_size);
+ if (!ht->entries)
+ return NULL;
+
+ ht->n_elements = 0;
+ _dl_memset(ht->entries, 0, ent_size);
+
+ return ht;
+}
+
+/*
+ * This is only called from _dl_loadaddr_unmap, so it's safe to call
+ * _dl_free(). See the discussion below.
+ */
+static __always_inline void
+htab_delete(struct funcdesc_ht *htab)
+{
+ size_t i;
+
+ for (i = htab->size - 1; i >= 0; i--)
+ if (htab->entries[i])
+ _dl_free(htab->entries[i]);
+
+ _dl_free(htab->entries);
+ _dl_free(htab);
+}
+
+/*
+ * Similar to htab_find_slot, but without several unwanted side effects:
+ * - Does not call htab->eq_f when it finds an existing entry.
+ * - Does not change the count of elements/searches/collisions in the
+ * hash table.
+ * This function also assumes there are no deleted entries in the table.
+ * HASH is the hash value for the element to be inserted.
+ */
+static __always_inline struct funcdesc_value **
+find_empty_slot_for_expand(struct funcdesc_ht *htab, int hash)
+{
+ size_t size = htab->size;
+ unsigned int index = hash % size;
+ struct funcdesc_value **slot = htab->entries + index;
+ int hash2;
+
+ if (!*slot)
+ return slot;
+
+ hash2 = 1 + hash % (size - 2);
+ for (;;) {
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ slot = htab->entries + index;
+ if (!*slot)
+ return slot;
+ }
+}
+
+/*
+ * The following function changes size of memory allocated for the
+ * entries and repeatedly inserts the table elements. The occupancy
+ * of the table after the call will be about 50%. Naturally the hash
+ * table must already exist. Remember also that the place of the
+ * table entries is changed. If memory allocation failures are allowed,
+ * this function will return zero, indicating that the table could not be
+ * expanded. If all goes well, it will return a non-zero value.
+ */
+static __always_inline int
+htab_expand(struct funcdesc_ht *htab)
+{
+ struct funcdesc_value **oentries;
+ struct funcdesc_value **olimit;
+ struct funcdesc_value **p;
+ struct funcdesc_value **nentries;
+ size_t nsize;
+
+ oentries = htab->entries;
+ olimit = oentries + htab->size;
+
+ /*
+ * Resize only when table after removal of unused elements is either
+ * too full or too empty.
+ */
+ if (htab->n_elements * 2 > htab->size)
+ nsize = higher_prime_number(htab->n_elements * 2);
+ else
+ nsize = htab->size;
+
+ nentries = _dl_malloc(sizeof(*nentries) * nsize);
+ _dl_memset(nentries, 0, sizeof(*nentries) * nsize);
+ if (nentries == NULL)
+ return 0;
+ htab->entries = nentries;
+ htab->size = nsize;
+
+ p = oentries;
+ do {
+ if (*p)
+ *find_empty_slot_for_expand(htab, hash_pointer((*p)->entry_point)) = *p;
+ p++;
+ } while (p < olimit);
+
+#if 0
+ /*
+ * We can't tell whether this was allocated by the _dl_malloc()
+ * built into ld.so or malloc() in the main executable or libc,
+ * and calling free() for something that wasn't malloc()ed could
+ * do Very Bad Things (TM). Take the conservative approach
+ * here, potentially wasting as much memory as actually used by
+ * the hash table, even if multiple growths occur. That's not
+ * so bad as to require some overengineered solution that would
+ * enable us to keep track of how it was allocated.
+ */
+ _dl_free(oentries);
+#endif
+ return 1;
+}
+
+/*
+ * This function searches for a hash table slot containing an entry
+ * equal to the given element. To delete an entry, call this with
+ * INSERT = 0, then call htab_clear_slot on the slot returned (possibly
+ * after doing some checks). To insert an entry, call this with
+ * INSERT = 1, then write the value you want into the returned slot.
+ * When inserting an entry, NULL may be returned if memory allocation
+ * fails.
+ */
+static __always_inline struct funcdesc_value **
+htab_find_slot(struct funcdesc_ht *htab, void *ptr, int insert)
+{
+ unsigned int index;
+ int hash, hash2;
+ size_t size;
+ struct funcdesc_value **entry;
+
+ if (htab->size * 3 <= htab->n_elements * 4 &&
+ htab_expand(htab) == 0)
+ return NULL;
+
+ hash = hash_pointer(ptr);
+
+ size = htab->size;
+ index = hash % size;
+
+ entry = &htab->entries[index];
+ if (!*entry)
+ goto empty_entry;
+ else if ((*entry)->entry_point == ptr)
+ return entry;
+
+ hash2 = 1 + hash % (size - 2);
+ for (;;) {
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ entry = &htab->entries[index];
+ if (!*entry)
+ goto empty_entry;
+ else if ((*entry)->entry_point == ptr)
+ return entry;
+ }
+
+ empty_entry:
+ if (!insert)
+ return NULL;
+
+ htab->n_elements++;
+ return entry;
+}
+
+void *
+_dl_funcdesc_for (void *entry_point, void *got_value)
+{
+ struct elf_resolve *tpnt = ((void**)got_value)[2];
+ struct funcdesc_ht *ht = tpnt->funcdesc_ht;
+ struct funcdesc_value **entry;
+
+ _dl_assert(got_value == tpnt->loadaddr.got_value);
+
+ if (!ht) {
+ ht = htab_create();
+ if (!ht)
+ return (void*)-1;
+ tpnt->funcdesc_ht = ht;
+ }
+
+ entry = htab_find_slot(ht, entry_point, 1);
+ if (*entry) {
+ _dl_assert((*entry)->entry_point == entry_point);
+ return _dl_stabilize_funcdesc(*entry);
+ }
+
+ *entry = _dl_malloc(sizeof(**entry));
+ (*entry)->entry_point = entry_point;
+ (*entry)->got_value = got_value;
+
+ return _dl_stabilize_funcdesc(*entry);
+}
+
+static __always_inline void const *
+_dl_lookup_address(void const *address)
+{
+ struct elf_resolve *rpnt;
+ struct funcdesc_value const *fd;
+
+ /* Make sure we don't make assumptions about its alignment. */
+ __asm__ ("" : "+r" (address));
+
+ if ((Elf32_Addr)address & 7)
+ /* It's not a function descriptor. */
+ return address;
+
+ fd = address;
+
+ for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
+ if (!rpnt->funcdesc_ht)
+ continue;
+
+ if (fd->got_value != rpnt->loadaddr.got_value)
+ continue;
+
+ address = htab_find_slot(rpnt->funcdesc_ht, (void *)fd->entry_point, 0);
+
+ if (address && *(struct funcdesc_value *const*)address == fd) {
+ address = (*(struct funcdesc_value *const*)address)->entry_point;
+ break;
+ } else
+ address = fd;
+ }
+
+ return address;
+}
diff --git a/ap/build/uClibc/ldso/ldso/fdpic/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/fdpic/dl-sysdep.h
new file mode 100644
index 0000000..546811a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/fdpic/dl-sysdep.h
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ * Based on ../i386/dl-sysdep.h
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#define HAVE_DL_INLINES_H
+
+/*
+ * Initialization sequence for a GOT. Copy the resolver function
+ * descriptor and the pointer to the elf_resolve/link_map data
+ * structure. Initialize the got_value in the module while at that.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ (MODULE)->loadaddr.got_value = (GOT_BASE); \
+ GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \
+ GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \
+ GOT_BASE[2] = (unsigned long) MODULE; \
+}
+
+struct elf_resolve;
+
+struct funcdesc_value
+{
+ void *entry_point;
+ void *got_value;
+} __attribute__((__aligned__(8)));
+
+struct funcdesc_ht;
+
+#define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr
+
+#define DL_RELOC_ADDR(LOADADDR, ADDR) \
+ ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
+
+#define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \
+ ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value))
+
+#define _dl_stabilize_funcdesc(val) \
+ ({ __asm__ ("" : "+m" (*(val))); (val); })
+
+#define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \
+ ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \
+ void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \
+ (* SIGNATURE pf)(__VA_ARGS__); })
+
+#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+ (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \
+ dl_boot_ldsomap ?: dl_boot_progmap))
+
+#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+ (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap))
+
+#define DL_INIT_LOADADDR_EXTRA_DECLS \
+ int dl_init_loadaddr_load_count;
+#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+ (dl_init_loadaddr_load_count = \
+ __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
+#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
+ dl_init_loadaddr_load_count))
+#define DL_UPDATE_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+ (__dl_update_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR)))
+#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
+ (__dl_loadaddr_unmap ((LOADADDR), (NULL)))
+#define DL_LIB_UNMAP(LIB, LEN) \
+ (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht))
+#define DL_LOADADDR_BASE(LOADADDR) \
+ ((LOADADDR).got_value)
+
+/* This is called from dladdr(), such that we map a function
+ descriptor's address to the function's entry point before trying to
+ find in which library it's defined. */
+#define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS))
+
+#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+ (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
+
+/*
+ * Compute the GOT address. On several platforms, we use assembly
+ * here. on FDPIC, there's no way to compute the GOT address,
+ * since the offset between text and data is not fixed, so we arrange
+ * for the ldso assembly entry point to pass this value as an argument
+ * to _dl_start. */
+#define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer)
+
+#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
+ ((dpnt) = dl_boot_ldso_dyn_pointer)
+
+/* We want want to apply all relocations in the interpreter during
+ bootstrap. Because of this, we have to skip the interpreter
+ relocations in _dl_parse_relocation_information(), see
+ elfinterp.c. */
+#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
+
+#ifdef __NR_pread
+#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
+ (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
+#endif
+
+/* We want to return to dlsym() a function descriptor if the symbol
+ turns out to be a function. */
+#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \
+ (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \
+ && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \
+ ? _dl_funcdesc_for ((void *)DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value), \
+ (TPNT)->loadaddr.got_value) \
+ : DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value))
+
+#define DL_GET_READY_TO_RUN_EXTRA_PARMS \
+ , struct elf32_fdpic_loadmap *dl_boot_progmap, Elf32_Addr dl_boot_got_pointer
+#define DL_GET_READY_TO_RUN_EXTRA_ARGS \
+ , dl_boot_progmap, dl_boot_got_pointer
+
+/* Define this to declare the library offset. */
+#define DL_DEF_LIB_OFFSET
+
+/* Define this to get the library offset. */
+#define DL_GET_LIB_OFFSET() 0
+
+/* Define this to set the library offset. */
+#define DL_SET_LIB_OFFSET(offset)
+
+/* Define this to get the real object's runtime address. */
+#define DL_GET_RUN_ADDR(loadaddr, mapaddr) (loadaddr)
+
+#ifdef __USE_GNU
+# include <link.h>
+#else
+# define __USE_GNU
+# include <link.h>
+# undef __USE_GNU
+#endif
diff --git a/ap/build/uClibc/ldso/ldso/frv/dl-debug.h b/ap/build/uClibc/ldso/ldso/frv/dl-debug.h
new file mode 100644
index 0000000..65c2386
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/dl-debug.h
@@ -0,0 +1,29 @@
+/* FR-V FDPIC ELF shared library loader suppport
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Lots of code copied from ../i386/elfinterp.c, so:
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ [0] "R_FRV_NONE", "R_FRV_32",
+ [2] "R_FRV_LABEL16", "R_FRV_LABEL24",
+ [4] "R_FRV_LO16", "R_FRV_HI16",
+ [6] "R_FRV_GPREL12", "R_FRV_GPRELU12",
+ [8] "R_FRV_GPREL32", "R_FRV_GPRELHI", "R_FRV_GPRELLO",
+ [11] "R_FRV_GOT12", "R_FRV_GOTHI", "R_FRV_GOTLO",
+ [14] "R_FRV_FUNCDESC",
+ [15] "R_FRV_FUNCDESC_GOT12", "R_FRV_FUNCDESC_GOTHI", "R_FRV_FUNCDESC_GOTLO",
+ [18] "R_FRV_FUNCDESC_VALUE", "R_FRV_FUNCDESC_GOTOFF12",
+ [20] "R_FRV_FUNCDESC_GOTOFFHI", "R_FRV_FUNCDESC_GOTOFFLO",
+ [22] "R_FRV_GOTOFF12", "R_FRV_GOTOFFHI", "R_FRV_GOTOFFLO",
+#if 0
+ [200] "R_FRV_GNU_VTINHERIT", "R_FRV_GNU_VTENTRY"
+#endif
+};
diff --git a/ap/build/uClibc/ldso/ldso/frv/dl-inlines.h b/ap/build/uClibc/ldso/ldso/frv/dl-inlines.h
new file mode 100644
index 0000000..8fdf6eb
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/dl-inlines.h
@@ -0,0 +1 @@
+#include "../fdpic/dl-inlines.h"
diff --git a/ap/build/uClibc/ldso/ldso/frv/dl-startup.h b/ap/build/uClibc/ldso/ldso/frv/dl-startup.h
new file mode 100644
index 0000000..2aa7baa
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/dl-startup.h
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/* Any assembly language/system dependent hacks needed to setup
+ * boot1.c so it will work as expected and cope with whatever platform
+ * specific wierdness is needed for this architecture.
+
+ * We override the default _dl_boot function, and replace it with a
+ * bit of asm. Then call the real _dl_boot function, which is now
+ * named _dl_boot2. */
+
+/* At program start-up, gr16 contains a pointer to a
+ elf32_fdpic_loadmap that describes how the executable was loaded
+ into memory. gr17 contains a pointer to the interpreter (our!)
+ loadmap, if there is an interpreter, or 0 if we're being run as an
+ executable. gr18 holds a pointer to the interpreter's dynamic
+ section, if there is an interpreter, or to the executable's dynamic
+ section, otherwise. If the executable is not dynamic, gr18 is 0.
+
+ We rely on the fact that the linker adds a pointer to the
+ _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that
+ __self_reloc returns the relocated pointer to us, so that we can
+ use this value to initialize the PIC register. */
+
+__asm__("" \
+" .text\n" \
+" .global _dl_boot\n" \
+" .type _dl_boot,@function\n" \
+"_dl_boot:\n" \
+" call .Lcall\n" \
+".Lcall:\n" \
+" movsg lr, gr4\n" \
+" sethi.p #gprelhi(.Lcall), gr5\n"\
+" setlo #gprello(.Lcall), gr5\n"\
+" mov.p gr17, gr8\n" \
+" cmp gr17, gr0, icc0\n" \
+" sub.p gr4, gr5, gr4\n" \
+" ckeq icc0, cc4\n" \
+" cmov.p gr16, gr8, cc4, 1\n" \
+" sethi #gprelhi(__ROFIXUP_LIST__), gr9\n" \
+" sethi.p #gprelhi(__ROFIXUP_END__), gr10\n" \
+" setlo #gprello(__ROFIXUP_LIST__), gr9\n" \
+" setlo.p #gprello(__ROFIXUP_END__), gr10\n" \
+" add gr9, gr4, gr9\n" \
+" add.p gr10, gr4, gr10\n" \
+" call __self_reloc\n" \
+" mov.p gr8, gr15\n" \
+" mov gr16, gr9\n" \
+" mov.p gr17, gr10\n" \
+" mov gr18, gr11\n" \
+" addi.p sp, #4, gr13\n" \
+" addi sp, #-8, sp\n" \
+" mov.p sp, gr12\n" \
+" call _dl_boot2\n" \
+" ldd.p @(sp, gr0), gr14\n" \
+" addi sp, #8, sp\n" \
+" movgs gr0, lr\n" \
+" jmpl @(gr14, gr0)\n" \
+" .size _dl_boot,.-_dl_boot\n" \
+);
+
+#define _dl_boot _dl_boot2
+#define DL_BOOT(X) \
+static void __attribute__ ((used)) \
+_dl_boot (void *dl_boot_got_pointer, \
+ struct elf32_fdpic_loadmap *dl_boot_progmap, \
+ struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ struct funcdesc_value *dl_main_funcdesc, \
+ X)
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS)
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF_R_TYPE((RELP)->r_info)){ \
+ case R_FRV_32: \
+ *(REL) += (SYMBOL); \
+ break; \
+ case R_FRV_FUNCDESC_VALUE: \
+ { \
+ struct funcdesc_value fv = { \
+ (void*)((SYMBOL) + *(REL)), \
+ (LOAD).got_value \
+ }; \
+ *(struct funcdesc_value volatile *)(REL) = fv; \
+ break; \
+ } \
+ default: \
+ _dl_exit(1); \
+ }
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done. We return the address of the function's entry point to
+ * _dl_boot, see boot1_arch.h.
+ */
+#define START() do { \
+ struct elf_resolve *exec_mod = _dl_loaded_modules; \
+ dl_main_funcdesc->entry_point = _dl_elf_main; \
+ while (exec_mod->libtype != elf_executable) \
+ exec_mod = exec_mod->next; \
+ dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \
+ /* _dl_dprintf(2, "entry point is (%x,%x)\n", dl_main_funcdesc->entry_point, dl_main_funcdesc->got_value); */ \
+ return; \
+} while (0)
diff --git a/ap/build/uClibc/ldso/ldso/frv/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/frv/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/frv/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/frv/dl-sysdep.h
new file mode 100644
index 0000000..f4e8b4c
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/dl-sysdep.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Based on ../i386/dl-sysdep.h
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#undef ELF_USES_RELOCA
+
+/* JMPREL relocs are inside the DT_RELA table. */
+#define ELF_MACHINE_PLTREL_OVERLAP
+
+#define DL_NO_COPY_RELOCS
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_CYGNUS_FRV
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "FR-V"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
+
+/* We must force strings used early in the bootstrap into the data
+ segment, such that they are referenced with GOTOFF instead of
+ GPREL, because GPREL needs the GOT to have already been
+ relocated. */
+#undef SEND_EARLY_STDERR
+#define SEND_EARLY_STDERR(S) \
+ do { static char __s[] = (S); SEND_STDERR (__s); } while (0)
+
+#define DL_RELOC_ADDR(ADDR, LOADADDR) \
+ (__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
+
+/* Make sure we only load libraries that use the same number of
+ general-purpose and floating-point registers the dynamic loader was
+ compiled for. */
+#define DL_CHECK_REG_COUNT(flags) \
+ (((flags & EF_FRV_GPR_MASK) == EF_FRV_GPR_32 ? __FRV_GPR__ == 32 : 1) \
+ && ((flags & EF_FRV_GPR_MASK) == EF_FRV_GPR_64 ? __FRV_GPR__ == 64 : 1) \
+ && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_32 ? __FRV_FPR__ == 32 : 1) \
+ && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_64 ? __FRV_FPR__ == 64 : 1) \
+ && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_NONE ? __FRV_FPR__ == 0 : 1))
+
+/* We only support loading FDPIC independently-relocatable shared
+ libraries. It probably wouldn't be too hard to support loading
+ shared libraries that require relocation by the same amount, but we
+ don't know that they exist or would be useful, and the dynamic
+ loader code could leak the whole-library map unless we keeping a
+ bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's
+ keep things simple for now. */
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+ if (((epnt)->e_flags & EF_FRV_FDPIC) && ! ((epnt)->e_flags & EF_FRV_PIC)) \
+ (piclib) = 2; \
+ else \
+ { \
+ _dl_internal_error_number = LD_ERROR_NOTDYN; \
+ _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \
+ "\n", (_dl_progname), (libname)); \
+ _dl_close(infile); \
+ return NULL; \
+ } \
+\
+ if (! DL_CHECK_REG_COUNT ((epnt)->e_flags)) \
+ { \
+ _dl_internal_error_number = LD_ERROR_NOTDYN; \
+ _dl_dprintf(2, "%s: '%s' assumes different register counts" \
+ "\n", (_dl_progname), (libname)); \
+ _dl_close(infile); \
+ } \
+} \
+while (0)
+
+#include "../fdpic/dl-sysdep.h"
diff --git a/ap/build/uClibc/ldso/ldso/frv/elfinterp.c b/ap/build/uClibc/ldso/ldso/frv/elfinterp.c
new file mode 100644
index 0000000..6cb09f8
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/elfinterp.c
@@ -0,0 +1,347 @@
+/* FR-V FDPIC ELF shared library loader suppport
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ * Lots of code copied from ../i386/elfinterp.c, so:
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ * All rights reserved.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+struct funcdesc_value volatile attribute_hidden *
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ struct elf_resolve *new_tpnt;
+ char *new_addr;
+ struct funcdesc_value funcval;
+ struct funcdesc_value volatile *got_entry;
+ char *symname;
+
+ rel_addr = DL_RELOC_ADDR (tpnt->dynamic_info[DT_JMPREL],
+ tpnt->loadaddr);
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)(intptr_t)
+ DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB],
+ tpnt->loadaddr);
+ strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr);
+ symname= strtab + symtab[symtab_index].st_name;
+
+ /* Address of GOT entry fix up */
+ got_entry = (struct funcdesc_value *)
+ DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr);
+
+ /* Get the address to be used to fill in the GOT entry. */
+ new_addr = _dl_find_hash_mod(symname, &_dl_loaded_modules->symbol_scope, NULL, 0,
+ &new_tpnt);
+ if (!new_addr) {
+ new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0,
+ &new_tpnt);
+ if (!new_addr) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit(1);
+ }
+ }
+
+ funcval.entry_point = new_addr;
+ funcval.got_value = new_tpnt->loadaddr.got_value;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings)
+ {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n",
+ got_entry->entry_point, got_entry->got_value,
+ funcval.entry_point, funcval.got_value,
+ got_entry);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_entry = funcval;
+ }
+#else
+ *got_entry = funcval;
+#endif
+
+ return got_entry;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *)(intptr_t) DL_RELOC_ADDR (rel_addr, tpnt->loadaddr);
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)(intptr_t)
+ DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], tpnt->loadaddr);
+ strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr);
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (res <0)
+ {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ }
+ else if (res >0)
+ {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+ return 0;
+}
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long reloc_value = 0, *reloc_addr;
+ struct { unsigned long v; } __attribute__((__packed__))
+ *reloc_addr_packed;
+ unsigned long symbol_addr;
+ struct elf_resolve *symbol_tpnt;
+ struct funcdesc_value funcval;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ reloc_addr = (unsigned long *)(intptr_t)
+ DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr);
+ __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr));
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
+ symbol_addr = (unsigned long)
+ DL_RELOC_ADDR (symtab[symtab_index].st_value,
+ tpnt->loadaddr);
+ symbol_tpnt = tpnt;
+ } else {
+
+ symbol_addr = (unsigned long)
+ _dl_find_hash_mod(symname, scope, NULL, 0, &symbol_tpnt);
+
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+
+ if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, strtab + symtab[symtab_index].st_name);
+ _dl_exit (1);
+ }
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ {
+ if ((long)reloc_addr_packed & 3)
+ old_val = reloc_addr_packed->v;
+ else
+ old_val = *reloc_addr;
+ }
+ else
+ old_val = 0;
+#endif
+ switch (reloc_type) {
+ case R_FRV_NONE:
+ break;
+ case R_FRV_32:
+ if ((long)reloc_addr_packed & 3)
+ reloc_value = reloc_addr_packed->v += symbol_addr;
+ else
+ reloc_value = *reloc_addr += symbol_addr;
+ break;
+ case R_FRV_FUNCDESC_VALUE:
+ funcval.entry_point = (void*)symbol_addr;
+ /* The addend of FUNCDESC_VALUE
+ relocations referencing global
+ symbols must be ignored, because it
+ may hold the address of a lazy PLT
+ entry. */
+ if (ELF_ST_BIND
+ (symtab[symtab_index].st_info)
+ == STB_LOCAL)
+ funcval.entry_point += *reloc_addr;
+ reloc_value = (unsigned long)funcval.entry_point;
+ if (symbol_addr)
+ funcval.got_value
+ = symbol_tpnt->loadaddr.got_value;
+ else
+ funcval.got_value = 0;
+ __asm__ ("std%I0\t%1, %M0"
+ : "=m" (*(struct funcdesc_value *)reloc_addr)
+ : "e" (funcval));
+ break;
+ case R_FRV_FUNCDESC:
+ if ((long)reloc_addr_packed & 3)
+ reloc_value = reloc_addr_packed->v;
+ else
+ reloc_value = *reloc_addr;
+ if (symbol_addr)
+ reloc_value = (unsigned long)_dl_funcdesc_for
+ ((char *)symbol_addr + reloc_value,
+ symbol_tpnt->loadaddr.got_value);
+ else
+ reloc_value = 0;
+ if ((long)reloc_addr_packed & 3)
+ reloc_addr_packed->v = reloc_value;
+ else
+ *reloc_addr = reloc_value;
+ break;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail) {
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr);
+ switch (reloc_type) {
+ case R_FRV_FUNCDESC_VALUE:
+ _dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value);
+ break;
+ case R_FRV_FUNCDESC:
+ if (! reloc_value)
+ break;
+ _dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)",
+ ((struct funcdesc_value *)reloc_value)->entry_point,
+ ((struct funcdesc_value *)reloc_value)->got_value);
+ break;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt,
+ struct r_scope_elem *scope __attribute_used__,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute_used__,
+ char *strtab __attribute_used__)
+{
+ int reloc_type;
+ struct funcdesc_value volatile *reloc_addr;
+ struct funcdesc_value funcval;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ reloc_addr = (struct funcdesc_value *)(intptr_t)
+ DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = (unsigned long)reloc_addr->entry_point;
+#endif
+ switch (reloc_type) {
+ case R_FRV_NONE:
+ break;
+ case R_FRV_FUNCDESC_VALUE:
+ funcval = *reloc_addr;
+ funcval.entry_point =
+ DL_RELOC_ADDR (funcval.entry_point,
+ tpnt->loadaddr);
+ funcval.got_value = tpnt->loadaddr.got_value;
+ *reloc_addr = funcval;
+ break;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, reloc_addr->entry_point, reloc_addr);
+#endif
+ return 0;
+
+}
+
+void
+_dl_parse_lazy_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size)
+{
+ _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information
+(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
+/* We don't have copy relocs. */
+
+int
+_dl_parse_copy_information
+(struct dyn_elf *rpnt __attribute_used__,
+ unsigned long rel_addr __attribute_used__,
+ unsigned long rel_size __attribute_used__)
+{
+ return 0;
+}
+
+#ifndef LIBDL
+# include "../../libc/sysdeps/linux/frv/crtreloc.c"
+#endif
+
diff --git a/ap/build/uClibc/ldso/ldso/frv/resolve.S b/ap/build/uClibc/ldso/ldso/frv/resolve.S
new file mode 100644
index 0000000..9dde727
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/frv/resolve.S
@@ -0,0 +1,57 @@
+/* Copyright (C) 2003 Red Hat, Inc.
+ * Contributed by Alexandre Oliva <aoliva@redhat.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+ /* The function below is tail-called by resolver stubs when a
+ lazily-bound function is called. It must preserve all
+ registers that could be used to pass arguments to the actual
+ function. Upon _dl_linux_resolve entry, GR14 holds the
+ address of a lazy PLT entry, so @(GR14,-4) is the lazy
+ relocation number that we have to pass to _dl_linux_resolver.
+ GR15 holds the caller's GOT, from which we extract the
+ elf_resolve* that _dl_linux_resolver needs as well.
+
+ _dl_linux_resolver() figures out where the jump symbol is
+ _really_ supposed to have jumped to and returns that to us.
+ Once we have that, we prepare to tail-call the actual
+ function, clean up after ourselves, restoring the original
+ arguments, then jump to the fixed up address. */
+
+ .text
+ .p2align 4
+
+ .hidden _dl_linux_resolve
+ .global _dl_linux_resolve
+ .type _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+ /* Preserve arguments. */
+ addi sp, -8*4, sp
+ stdi gr8, @(sp, 8)
+ stdi gr10, @(sp, 16)
+ stdi gr12, @(sp, 24)
+ movsg lr,gr8
+ st gr8, @(sp,gr0)
+
+ /* Prepare to call _dl_linux_resolver. */
+ ldi @(gr15, 8), gr8
+ ldi @(gr14, -4), gr9
+ mov.p gr5, gr15
+ call _dl_linux_resolver
+
+ /* Move aside return value that contains the FUNCDESC_VALUE. */
+ ldd @(gr8,gr0),gr14
+
+ /* Restore arguments. */
+ ld @(sp, gr0), gr8
+ movgs gr8,lr
+ lddi @(sp, 24), gr12
+ lddi @(sp, 16), gr10
+ lddi @(sp, 8), gr8
+ addi sp, 8*4, sp
+
+ /* Now jump to the actual function. */
+ jmpl @(gr14, gr0)
+ .size _dl_linux_resolve, . - _dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/i386/dl-debug.h b/ap/build/uClibc/ldso/ldso/i386/dl-debug.h
new file mode 100644
index 0000000..82baf1f
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/i386/dl-debug.h
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4: */
+/* i386 ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ [0] "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
+ [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT",
+ [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC",
+};
diff --git a/ap/build/uClibc/ldso/ldso/i386/dl-startup.h b/ap/build/uClibc/ldso/ldso/i386/dl-startup.h
new file mode 100644
index 0000000..973ed72
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/i386/dl-startup.h
@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+__asm__ (
+ " .text\n"
+ " .globl _start\n"
+ " .type _start,@function\n"
+ "_start:\n"
+ " call _dl_start\n"
+ " # Save the user entry point address in %edi.\n"
+ " movl %eax, %edi\n"
+ " # Point %ebx at the GOT.\n"
+ " call 1f\n"
+ "1: popl %ebx\n"
+ " addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx\n"
+ " # See if we were run as a command with the executable file\n"
+ " # name as an extra leading argument.\n"
+ " movl _dl_skip_args@GOTOFF(%ebx), %eax\n"
+ " # Pop the original argument count.\n"
+ " popl %edx\n"
+ " # Adjust the stack pointer to skip _dl_skip_args words.\n"
+ " leal (%esp,%eax,4), %esp\n"
+ " # Subtract _dl_skip_args from argc.\n"
+ " subl %eax, %edx\n"
+ " # Push argc back on the stack.\n"
+ " push %edx\n"
+ " # Pass our FINI ptr() to the user in %edx, as per ELF ABI.\n"
+ " leal _dl_fini@GOTOFF(%ebx), %edx\n"
+ " # Jump to the user's entry point.\n"
+ " jmp *%edi\n"
+ " .size _start,.-_start\n"
+ " .previous\n"
+);
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1)
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
+{
+ switch (ELF_R_TYPE(rpnt->r_info))
+ {
+ case R_386_32:
+ *reloc_addr += symbol_addr;
+ break;
+ case R_386_PC32:
+ *reloc_addr += symbol_addr - (unsigned long) reloc_addr;
+ break;
+ case R_386_GLOB_DAT:
+ case R_386_JMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_386_RELATIVE:
+ *reloc_addr += load_addr;
+ break;
+ default:
+ _dl_exit(1);
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/i386/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/i386/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/i386/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/i386/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/i386/dl-sysdep.h
new file mode 100644
index 0000000..a66c802
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/i386/dl-sysdep.h
@@ -0,0 +1,78 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+
+/* Define this if the system uses RELOCA. */
+#undef ELF_USES_RELOCA
+#include <elf.h>
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+} while(0)
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_386
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "386"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references should not be allowed to
+ define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_386_JMP_SLOT || (type) == R_386_TLS_DTPMOD32 \
+ || (type) == R_386_TLS_DTPOFF32 || (type) == R_386_TLS_TPOFF32 \
+ || (type) == R_386_TLS_TPOFF) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf32_Addr elf_machine_dynamic (void) attribute_unused;
+static __always_inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ register Elf32_Addr *got __asm__ ("%ebx");
+ return *got;
+}
+
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr elf_machine_load_address (void) attribute_unused;
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ /* It doesn't matter what variable this is, the reference never makes
+ it to assembly. We need a dummy reference to some global variable
+ via the GOT to make sure the compiler initialized %ebx in time. */
+ Elf32_Addr addr;
+ int tmp;
+ __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n"
+ "subl _dl_start@GOT(%%ebx), %0"
+ : "=r" (addr) : "m" (tmp) : "cc");
+ return addr;
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rel * rpnt = (void *) rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr += load_off;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/i386/elfinterp.c b/ap/build/uClibc/ldso/ldso/i386/elfinterp.c
new file mode 100644
index 0000000..aadb00a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/i386/elfinterp.c
@@ -0,0 +1,326 @@
+/* vi: set sw=4 ts=4: */
+/* i386 ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched: %x ==> %x @ %x",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
+ rel_size /= sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n",
+ _dl_reltypes(reloc_type), tpnt->libname);
+#else
+ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n",
+ reloc_type, tpnt->libname);
+#endif
+ return res;
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ struct elf_resolve *tls_tpnt = NULL;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+ struct symbol_ref sym_ref;
+
+ reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + symtab[symtab_index].st_name;
+
+ if (symtab_index) {
+ symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+ if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+ && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
+ return 1;
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ tls_tpnt = sym_ref.tpnt;
+ } else {
+ symbol_addr = symtab[symtab_index].st_value;
+ tls_tpnt = tpnt;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_386_NONE:
+ break;
+ case R_386_32:
+ *reloc_addr += symbol_addr;
+ break;
+ case R_386_PC32:
+ *reloc_addr += symbol_addr - (unsigned long)reloc_addr;
+ break;
+ case R_386_GLOB_DAT:
+ case R_386_JMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_386_RELATIVE:
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ case R_386_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\n%s move %d bytes from %x to %x",
+ symname, symtab[symtab_index].st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ symtab[symtab_index].st_size);
+ }
+ break;
+#if defined USE_TLS && USE_TLS
+ case R_386_TLS_DTPMOD32:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_386_TLS_DTPOFF32:
+ /* During relocation all TLS symbols are defined and used.
+ * Therefore the offset is already correct. */
+ *reloc_addr = symbol_addr;
+ break;
+ case R_386_TLS_TPOFF32:
+ /* The offset is positive, backward from the thread pointer. */
+ CHECK_STATIC_TLS((struct link_map*) tls_tpnt);
+ *reloc_addr += tls_tpnt->l_tls_offset - symbol_addr;
+ break;
+ case R_386_TLS_TPOFF:
+ /* The offset is negative, forward from the thread pointer. */
+ CHECK_STATIC_TLS((struct link_map*) tls_tpnt);
+ *reloc_addr += symbol_addr - tls_tpnt->l_tls_offset;
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ unsigned long *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ (void)scope;
+ (void)symtab;
+ (void)strtab;
+
+ reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_386_NONE:
+ break;
+ case R_386_JMP_SLOT:
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+ return -1;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/i386/resolve.S b/ap/build/uClibc/ldso/ldso/i386/resolve.S
new file mode 100644
index 0000000..e8d77bb
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/i386/resolve.S
@@ -0,0 +1,51 @@
+/*
+ * This function is _not_ called directly. It is jumped to (so no return
+ * address is on the stack) when attempting to use a symbol that has not yet
+ * been resolved. The first time a jump symbol (such as a function call inside
+ * a shared library) is used (before it gets resolved) it will jump here to
+ * _dl_linux_resolve. When we get called the stack looks like this:
+ * reloc_entry
+ * tpnt
+ *
+ * This function saves all the registers, puts a copy of reloc_entry and tpnt
+ * on the stack (as function arguments) then make the function call
+ * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out
+ * where the jump symbol is _really_ supposed to have jumped to and returns
+ * that to us. Once we have that, we overwrite tpnt with this fixed up
+ * address. We then clean up after ourselves, put all the registers back how we
+ * found them, then we jump to where the fixed up address, which is where the
+ * jump symbol that got us here really wanted to jump to in the first place.
+ * found them, then we jump to the fixed up address, which is where the jump
+ * symbol that got us here really wanted to jump to in the first place.
+ * -Erik Andersen
+ */
+
+.text
+
+.globl _dl_linux_resolve
+.type _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+ pusha /* preserve all regs */
+ lea 0x20(%esp),%eax /* eax = tpnt and reloc_entry params */
+ pushl 4(%eax) /* push copy of reloc_entry param */
+ pushl (%eax) /* push copy of tpnt param */
+
+#ifdef __PIC__
+ call .L24
+.L24:
+ popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-.L24],%ebx
+ movl _dl_linux_resolver@GOT(%ebx),%ebx /* eax = resolved func */
+ call *%ebx
+#else
+ call _dl_linux_resolver
+#endif
+ movl %eax,0x28(%esp) /* store func addr over original
+ * tpnt param */
+ addl $0x8,%esp /* remove copy parameters */
+ popa /* restore regs */
+ ret $4 /* jump to func removing original
+ * reloc_entry param from stack */
+.LFE2:
+ .size _dl_linux_resolve,.LFE2-_dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/ldso.c b/ap/build/uClibc/ldso/ldso/ldso.c
new file mode 100644
index 0000000..85d27a3
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/ldso.c
@@ -0,0 +1,1432 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2005 by Joakim Tjernlund
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+#include "unsecvars.h"
+
+/* Pull in common debug code */
+#include "dl-debug.c"
+
+#define ALLOW_ZERO_PLTGOT
+
+#if defined(USE_TLS) && USE_TLS
+#include "dl-tls.c"
+#endif
+
+/* Pull in the value of _dl_progname */
+#include LDSO_ELFINTERP
+
+/* Global variables used within the shared library loader */
+#ifdef __LDSO_LD_LIBRARY_PATH__
+char *_dl_library_path = NULL; /* Where we look for libraries */
+#endif
+#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
+char *_dl_preload = NULL; /* Things to be loaded before the libs */
+#endif
+int _dl_errno = 0; /* We can't use the real errno in ldso */
+size_t _dl_pagesize = 0; /* Store the page size for use later */
+struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
+void *(*_dl_malloc_function) (size_t size) = NULL;
+void (*_dl_free_function) (void *p) = NULL;
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+char *_dl_trace_prelink = NULL; /* Library for prelinking trace */
+struct elf_resolve *_dl_trace_prelink_map = NULL; /* Library module for prelinking trace */
+bool _dl_verbose = true; /* On by default */
+bool prelinked = false;
+#endif
+static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
+
+#ifdef __SUPPORT_LD_DEBUG__
+char *_dl_debug = NULL;
+char *_dl_debug_symbols = NULL;
+char *_dl_debug_move = NULL;
+char *_dl_debug_reloc = NULL;
+char *_dl_debug_detail = NULL;
+char *_dl_debug_nofixups = NULL;
+char *_dl_debug_bindings = NULL;
+int _dl_debug_file = 2;
+#endif
+
+#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__)
+/* Not hidden, needed for standalone execution. */
+/*
+ * FIXME: align dl_start for SH to other archs so that we can keep this symbol
+ * hidden and we don't need to handle in __uClibc_main
+ */
+
+unsigned long _dl_skip_args = 0;
+#else
+unsigned long attribute_hidden _dl_skip_args = 0;
+#endif
+
+const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */
+#include "dl-startup.c"
+#include "dl-symbols.c"
+#include "dl-array.c"
+
+/*
+ * This stub function is used by some debuggers. The idea is that they
+ * can set an internal breakpoint on it, so that we are notified when the
+ * address mapping is changed in some way.
+ */
+void _dl_debug_state(void);
+rtld_hidden_proto(_dl_debug_state, noinline);
+void _dl_debug_state(void)
+{
+ /* Make sure GCC doesn't recognize this function as pure, to avoid
+ * having the calls optimized away.
+ */
+ __asm__("");
+}
+rtld_hidden_def(_dl_debug_state);
+
+static unsigned char *_dl_malloc_addr = NULL; /* Lets _dl_malloc use the already allocated memory page */
+static unsigned char *_dl_mmap_zero = NULL; /* Also used by _dl_malloc */
+
+static struct elf_resolve **init_fini_list;
+static struct elf_resolve **scope_elem_list;
+static unsigned int nlist; /* # items in init_fini_list */
+extern void _start(void);
+
+#ifdef __UCLIBC_HAS_SSP__
+# include <dl-osinfo.h>
+static uintptr_t stack_chk_guard;
+# ifndef THREAD_SET_STACK_GUARD
+/* Only exported for architectures that don't store the stack guard canary
+ * in local thread area. */
+uintptr_t __stack_chk_guard attribute_relro;
+# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
+uintptr_t __guard attribute_relro;
+# endif
+#endif
+
+#ifdef __LDSO_SEARCH_INTERP_PATH__
+const char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
+
+static void _dl_ldsopath_init(struct elf_resolve *tpnt)
+{
+ char *ldsopath, *ptmp;
+
+ /*
+ * Store the path where the shared lib loader was found for later use.
+ * Note that this logic isn't bullet proof when it comes to relative
+ * paths: if you use "./lib/ldso.so", and then the app does chdir()
+ * followed by dlopen(), the old ldso path won't get searched. But
+ * that is a fairly pathological use case, so if you don't like that,
+ * then set a full path to your interp and be done :P.
+ */
+ ldsopath = _dl_strdup(tpnt->libname);
+ ptmp = _dl_strrchr(ldsopath, '/');
+ /*
+ * If there is no "/", then set the path to "", and the code
+ * later on will take this to implicitly mean "search $PWD".
+ */
+ if (!ptmp)
+ ptmp = ldsopath;
+ *ptmp = '\0';
+
+ _dl_ldsopath = ldsopath;
+ _dl_debug_early("Lib Loader: (%x) %s: using path: %s\n",
+ (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname,
+ _dl_ldsopath);
+}
+#else
+#define _dl_ldsopath_init(tpnt)
+#endif
+
+char *_dl_getenv(const char *symbol, char **envp)
+{
+ char *pnt;
+ const char *pnt1;
+
+ while ((pnt = *envp++)) {
+ pnt1 = symbol;
+ while (*pnt && *pnt == *pnt1)
+ pnt1++, pnt++;
+ if (!*pnt || *pnt != '=' || *pnt1)
+ continue;
+ return pnt + 1;
+ }
+ return 0;
+}
+
+void _dl_unsetenv(const char *symbol, char **envp)
+{
+ char *pnt;
+ const char *pnt1;
+ char **newenvp = envp;
+
+ for (pnt = *envp; pnt; pnt = *++envp) {
+ pnt1 = symbol;
+ while (*pnt && *pnt == *pnt1)
+ pnt1++, pnt++;
+ if (!*pnt || *pnt != '=' || *pnt1)
+ *newenvp++ = *envp;
+ }
+ *newenvp++ = *envp;
+ return;
+}
+
+static int _dl_suid_ok(void)
+{
+ __kernel_uid_t uid, euid;
+ __kernel_gid_t gid, egid;
+
+ uid = _dl_getuid();
+ euid = _dl_geteuid();
+ gid = _dl_getgid();
+ egid = _dl_getegid();
+
+ if (uid == euid && gid == egid) {
+ return 1;
+ }
+ return 0;
+}
+
+void *_dl_malloc(size_t size)
+{
+ void *retval;
+
+#if 0
+ _dl_debug_early("request for %d bytes\n", size);
+#endif
+
+ if (_dl_malloc_function)
+ return (*_dl_malloc_function) (size);
+
+ if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
+ size_t rounded_size;
+
+ /* Since the above assumes we get a full page even if
+ we request less than that, make sure we request a
+ full page, since uClinux may give us less than than
+ a full page. We might round even
+ larger-than-a-page sizes, but we end up never
+ reusing _dl_mmap_zero/_dl_malloc_addr in that case,
+ so we don't do it.
+
+ The actual page size doesn't really matter; as long
+ as we're self-consistent here, we're safe. */
+ if (size < _dl_pagesize)
+ rounded_size = (size + ADDR_ALIGN) & _dl_pagesize;
+ else
+ rounded_size = size;
+
+ _dl_debug_early("mmapping more memory\n");
+ _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
+ if (_dl_mmap_check_error(_dl_mmap_zero)) {
+ _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
+ _dl_exit(20);
+ }
+ }
+ retval = _dl_malloc_addr;
+ _dl_malloc_addr += size;
+
+ /*
+ * Align memory to DL_MALLOC_ALIGN byte boundary. Some
+ * platforms require this, others simply get better
+ * performance.
+ */
+ _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1));
+ return retval;
+}
+
+static void *_dl_zalloc(size_t size)
+{
+ void *p = _dl_malloc(size);
+ if (p)
+ _dl_memset(p, 0, size);
+ return p;
+}
+
+void _dl_free(void *p)
+{
+ if (_dl_free_function)
+ (*_dl_free_function) (p);
+}
+
+#if defined(USE_TLS) && USE_TLS
+void *_dl_memalign(size_t __boundary, size_t __size)
+{
+ void *result;
+ int i = 0;
+ size_t delta;
+ size_t rounded = 0;
+
+ if (_dl_memalign_function)
+ return (*_dl_memalign_function) (__boundary, __size);
+
+ while (rounded < __boundary) {
+ rounded = (1 << i++);
+ }
+
+ delta = (((size_t) _dl_malloc_addr + __size) & (rounded - 1));
+
+ if ((result = _dl_malloc(rounded - delta)) == NULL)
+ return result;
+
+ result = _dl_malloc(__size);
+
+ return result;
+}
+#endif
+
+static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
+{
+ unsigned int i;
+ struct elf_resolve * tpnt;
+
+ for (i = 0; i < nlist; ++i) {
+ tpnt = init_fini_list[i];
+ if (tpnt->init_flag & FINI_FUNCS_CALLED)
+ continue;
+ tpnt->init_flag |= FINI_FUNCS_CALLED;
+ _dl_run_fini_array(tpnt);
+ if (tpnt->dynamic_info[DT_FINI]) {
+ void (*dl_elf_func) (void);
+
+ dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
+ _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
+ }
+ }
+}
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+static void trace_objects(struct elf_resolve *tpnt, char *str_name)
+{
+ if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
+ _dl_trace_prelink_map = tpnt;
+ if (tpnt->libtype == elf_executable) {
+/* Main executeble */
+ _dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, tpnt->libname,
+ tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
+ } else {
+/* Preloaded, Needed or interpreter */
+ _dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname,
+ tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
+ }
+
+#if defined USE_TLS && USE_TLS
+ if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
+ _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
+ (size_t) tpnt->l_tls_offset);
+ else
+#endif
+ _dl_dprintf (1, "\n");
+}
+#endif
+
+static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
+ DL_LOADADDR_TYPE load_addr,
+ ElfW(Addr) ldso_mapaddr,
+ ElfW(auxv_t) auxvt[AT_EGID + 1],
+ struct dyn_elf *rpnt)
+{
+ ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+ ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
+ DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
+ epnt->e_phoff);
+ int j;
+ struct stat st;
+
+ tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr,
+ tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
+ 0);
+
+ tpnt->mapaddr = ldso_mapaddr;
+ if (_dl_stat(tpnt->libname, &st) >= 0) {
+ tpnt->st_dev = st.st_dev;
+ tpnt->st_ino = st.st_ino;
+ }
+ tpnt->n_phent = epnt->e_phnum;
+ tpnt->ppnt = myppnt;
+ for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
+ if (myppnt->p_type == PT_GNU_RELRO) {
+ tpnt->relro_addr = myppnt->p_vaddr;
+ tpnt->relro_size = myppnt->p_memsz;
+ break;
+ }
+ }
+ tpnt->libtype = program_interpreter;
+ if (rpnt) {
+ rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
+ rpnt->next->prev = rpnt;
+ rpnt = rpnt->next;
+ } else {
+ rpnt = _dl_zalloc(sizeof(struct dyn_elf));
+ }
+ rpnt->dyn = tpnt;
+ tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
+
+ return tpnt;
+}
+
+static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
+ struct elf_resolve *map)
+{
+ struct elf_resolve **p = list;
+ struct init_fini_list *q;
+
+ *p++ = map;
+ map->init_flag |= DL_RESERVED;
+ if (map->init_fini)
+ for (q = map->init_fini; q; q = q->next)
+ if (! (q->tpnt->init_flag & DL_RESERVED))
+ p += _dl_build_local_scope (p, q->tpnt);
+ return p - list;
+}
+
+void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+ ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
+ DL_GET_READY_TO_RUN_EXTRA_PARMS)
+{
+ ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
+ ElfW(Phdr) *ppnt;
+ ElfW(Dyn) *dpnt;
+ char *lpntstr;
+ unsigned int i, cnt, nscope_elem;
+ int unlazy = 0, trace_loaded_objects = 0;
+ struct dyn_elf *rpnt;
+ struct elf_resolve *tcurr;
+ struct elf_resolve *tpnt1;
+ struct elf_resolve *ldso_tpnt = NULL;
+ struct elf_resolve app_tpnt_tmp;
+ struct elf_resolve *app_tpnt = &app_tpnt_tmp;
+ struct r_debug *debug_addr;
+ unsigned long *lpnt;
+ unsigned long *_dl_envp; /* The environment address */
+ ElfW(Addr) relro_addr = 0;
+ size_t relro_size = 0;
+ struct r_scope_elem *global_scope;
+ struct elf_resolve **local_scope;
+
+#if defined(USE_TLS) && USE_TLS
+ void *tcbp = NULL;
+#endif
+
+ /* Wahoo!!! We managed to make a function call! Get malloc
+ * setup so we can use _dl_dprintf() to print debug noise
+ * instead of the SEND_STDERR macros used in dl-startup.c */
+
+ _dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
+
+ /* Store the page size for later use */
+ _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
+ /* Make it so _dl_malloc can use the page of memory we have already
+ * allocated. We shouldn't need to grab any more memory. This must
+ * be first since things like _dl_dprintf() use _dl_malloc()...
+ */
+ _dl_malloc_addr = (unsigned char *)_dl_pagesize;
+ _dl_mmap_zero = 0;
+
+ /* Wahoo!!! */
+ _dl_debug_early("Cool, ldso survived making function calls\n");
+
+ /* Now we have done the mandatory linking of some things. We are now
+ * free to start using global variables, since these things have all
+ * been fixed up by now. Still no function calls outside of this
+ * library, since the dynamic resolver is not yet ready.
+ */
+ if (argv[0]) {
+ _dl_progname = argv[0];
+ }
+
+#ifndef __LDSO_STANDALONE_SUPPORT__
+ if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
+ _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
+ _dl_exit(1);
+ }
+#endif
+
+ /* Start to build the tables of the modules that are required for
+ * this beast to run. We start with the basic executable, and then
+ * go from there. Eventually we will run across ourself, and we
+ * will need to properly deal with that as well.
+ */
+ rpnt = NULL;
+ if (_dl_getenv("LD_BIND_NOW", envp))
+ unlazy = RTLD_NOW;
+
+ /* Now we need to figure out what kind of options are selected.
+ * Note that for SUID programs we ignore the settings in
+ * LD_LIBRARY_PATH.
+ */
+ if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
+ (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
+ auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
+ auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
+ _dl_secure = 0;
+#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
+ _dl_preload = _dl_getenv("LD_PRELOAD", envp);
+#endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
+ _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
+#endif
+ } else {
+ static const char unsecure_envvars[] =
+#ifdef EXTRA_UNSECURE_ENVVARS
+ EXTRA_UNSECURE_ENVVARS
+#endif
+ UNSECURE_ENVVARS;
+ const char *nextp;
+ _dl_secure = 1;
+
+ nextp = unsecure_envvars;
+ do {
+ _dl_unsetenv (nextp, envp);
+ /* We could use rawmemchr but this need not be fast. */
+ nextp = _dl_strchr(nextp, '\0') + 1;
+ } while (*nextp != '\0');
+#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
+ _dl_preload = NULL;
+#endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
+ _dl_library_path = NULL;
+#endif
+ /* SUID binaries can be exploited if they do LAZY relocation. */
+ unlazy = RTLD_NOW;
+ }
+
+#if defined(USE_TLS) && USE_TLS
+ _dl_error_catch_tsd = &_dl_initial_error_catch_tsd;
+ _dl_init_static_tls = &_dl_nothread_init_static_tls;
+#endif
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
+ unsigned int *aux_dat = (unsigned int *) argv;
+ int argc = aux_dat[-1];
+
+ tpnt->libname = argv[0];
+ while (argc > 1)
+ if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
+#ifdef __LDSO_LD_LIBRARY_PATH__
+ _dl_library_path = argv[2];
+#endif
+ _dl_skip_args += 2;
+ argc -= 2;
+ argv += 2;
+ } else
+ break;
+
+ /*
+ * If we have no further argument the program was called incorrectly.
+ * Grant the user some education.
+ */
+
+ if (argc < 2) {
+ _dl_dprintf(1, "\
+Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
+You have invoked `ld.so', the helper program for shared library executables.\n\
+This program usually lives in the file `/lib/ld.so', and special directives\n\
+in executable files using ELF shared libraries tell the system's program\n\
+loader to load the helper program from this file. This helper program loads\n\
+the shared libraries needed by the program executable, prepares the program\n\
+to run, and runs it. You may invoke this helper program directly from the\n\
+command line to load and run an ELF executable file; this is like executing\n\
+that file itself, but always uses this helper program from the file you\n\
+specified, instead of the helper program file specified in the executable\n\
+file you run. This is mostly of use for maintainers to test new versions\n\
+of this helper program; chances are you did not intend to run this program.\n\
+\n\
+ --library-path PATH use given PATH instead of content of the environment\n\
+ variable LD_LIBRARY_PATH\n");
+ _dl_exit(1);
+ }
+
+ ++_dl_skip_args;
+ ++argv;
+ _dl_progname = argv[0];
+
+ _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
+ /*
+ * It needs to load the _dl_progname and to map it
+ * Usually it is the main application launched by means of the ld.so
+ * but it could be also a shared object (when ld.so used for tracing)
+ * We keep the misleading app_tpnt name to avoid variable pollution
+ */
+ app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
+ if (!app_tpnt) {
+ _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
+ _dl_exit(16);
+ }
+ /*
+ * FIXME: it needs to properly handle a PIE executable
+ * Usually for a main application, loadaddr is computed as difference
+ * between auxvt entry points and phdr, so if it is not 0, that it is a
+ * PIE executable. In this case instead we need to set the loadaddr to 0
+ * because we are actually mapping the ELF for the main application by
+ * ourselves. So the PIE case must be checked.
+ */
+
+ app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
+
+ /*
+ * This is used by gdb to locate the chain of shared libraries that are
+ * currently loaded.
+ */
+ debug_addr = _dl_zalloc(sizeof(struct r_debug));
+ ppnt = (ElfW(Phdr) *)app_tpnt->ppnt;
+ for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) {
+ if (ppnt->p_type == PT_DYNAMIC) {
+ dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
+ _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
+ }
+ }
+
+ _dl_ldsopath_init(tpnt);
+ } else {
+#endif
+
+ /* At this point we are now free to examine the user application,
+ * and figure out which libraries are supposed to be called. Until
+ * we have this list, we will not be completely ready for dynamic
+ * linking.
+ */
+
+ /* Find the runtime load address of the main executable. This may be
+ * different from what the ELF header says for ET_DYN/PIE executables.
+ */
+ {
+ unsigned int idx;
+ ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
+
+ for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
+ if (phdr->p_type == PT_PHDR) {
+ DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
+ break;
+ }
+
+ if (DL_LOADADDR_BASE(app_tpnt->loadaddr))
+ _dl_debug_early("Position Independent Executable: "
+ "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr));
+ }
+
+ /*
+ * This is used by gdb to locate the chain of shared libraries that are
+ * currently loaded.
+ */
+ debug_addr = _dl_zalloc(sizeof(struct r_debug));
+
+ ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
+ for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
+ if (ppnt->p_type == PT_GNU_RELRO) {
+ relro_addr = ppnt->p_vaddr;
+ relro_size = ppnt->p_memsz;
+ }
+ if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) {
+ app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr);
+ }
+ if (ppnt->p_type == PT_DYNAMIC) {
+ dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
+ _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
+#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
+ /* Ugly, ugly. We need to call mprotect to change the
+ * protection of the text pages so that we can do the
+ * dynamic linking. We can set the protection back
+ * again once we are done.
+ */
+ _dl_debug_early("calling mprotect on the application program\n");
+ /* Now cover the application program. */
+ if (app_tpnt->dynamic_info[DT_TEXTREL]) {
+ ElfW(Phdr) *ppnt_outer = ppnt;
+ ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
+ for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
+ if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
+ _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
+ (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
+ (unsigned long) ppnt->p_filesz,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
+ }
+ ppnt = ppnt_outer;
+ }
+#else
+ if (app_tpnt->dynamic_info[DT_TEXTREL]) {
+ _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
+ _dl_exit(1);
+ }
+#endif
+
+#ifndef ALLOW_ZERO_PLTGOT
+ /* make sure it's really there. */
+ if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
+ continue;
+#endif
+ /* OK, we have what we need - slip this one into the list. */
+ app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr,
+ app_tpnt->dynamic_info,
+ (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),
+ ppnt->p_filesz);
+ _dl_loaded_modules->libtype = elf_executable;
+ _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
+ _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
+ _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
+ rpnt->dyn = _dl_loaded_modules;
+ app_tpnt->mapaddr = app_mapaddr;
+ app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
+ app_tpnt->usage_count++;
+ lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
+#ifdef ALLOW_ZERO_PLTGOT
+ if (lpnt)
+#endif
+ INIT_GOT(lpnt, _dl_loaded_modules);
+ }
+
+ /* OK, fill this in - we did not have this before */
+ if (ppnt->p_type == PT_INTERP) {
+ tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
+
+ _dl_ldsopath_init(tpnt);
+ }
+
+ /* Discover any TLS sections if the target supports them. */
+ if (ppnt->p_type == PT_TLS) {
+#if defined(USE_TLS) && USE_TLS
+ if (ppnt->p_memsz > 0) {
+ app_tpnt->l_tls_blocksize = ppnt->p_memsz;
+ app_tpnt->l_tls_align = ppnt->p_align;
+ if (ppnt->p_align == 0)
+ app_tpnt->l_tls_firstbyte_offset = 0;
+ else
+ app_tpnt->l_tls_firstbyte_offset =
+ (ppnt->p_vaddr & (ppnt->p_align - 1));
+ app_tpnt->l_tls_initimage_size = ppnt->p_filesz;
+ app_tpnt->l_tls_initimage = (void *) ppnt->p_vaddr;
+
+ /* This image gets the ID one. */
+ _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
+
+ }
+ _dl_debug_early("Found TLS header for application program\n");
+ break;
+#else
+ _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
+ _dl_exit(1);
+#endif
+ }
+ }
+ app_tpnt->relro_addr = relro_addr;
+ app_tpnt->relro_size = relro_size;
+
+#if defined(USE_TLS) && USE_TLS
+ /*
+ * Adjust the address of the TLS initialization image in
+ * case the executable is actually an ET_DYN object.
+ */
+ if (app_tpnt->l_tls_initimage != NULL) {
+ unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
+ app_tpnt->l_tls_initimage =
+ (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
+ _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
+ tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
+ }
+#endif
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ } /* ! ldso standalone mode */
+#endif
+
+#ifdef __SUPPORT_LD_DEBUG__
+ _dl_debug = _dl_getenv("LD_DEBUG", envp);
+ if (_dl_debug) {
+ if (_dl_strstr(_dl_debug, "all")) {
+ _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
+ = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
+ } else {
+ _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
+ _dl_debug_move = _dl_strstr(_dl_debug, "move");
+ _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
+ _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
+ _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
+ _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
+ }
+ }
+
+ {
+ const char *dl_debug_output;
+
+ dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
+
+ if (dl_debug_output) {
+ char tmp[22], *tmp1, *filename;
+ int len1, len2;
+
+ _dl_memset(tmp, 0, sizeof(tmp));
+ tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
+
+ len1 = _dl_strlen(dl_debug_output);
+ len2 = _dl_strlen(tmp1);
+
+ filename = _dl_malloc(len1 + len2 + 2);
+
+ if (filename) {
+ _dl_strcpy (filename, dl_debug_output);
+ filename[len1] = '.';
+ _dl_strcpy (&filename[len1+1], tmp1);
+
+ _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644);
+ if (_dl_debug_file < 0) {
+ _dl_debug_file = 2;
+ _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename);
+ }
+ }
+ }
+ }
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+{
+ char *ld_warn = _dl_getenv ("LD_WARN", envp);
+
+ if (ld_warn && *ld_warn == '\0')
+ _dl_verbose = false;
+}
+ _dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp);
+#endif
+
+ if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
+ trace_loaded_objects++;
+ }
+
+#ifndef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects) {
+ _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
+ _dl_exit(1);
+ }
+#endif
+
+ ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
+ /*
+ * OK, fix one more thing - set up debug_addr so it will point
+ * to our chain. Later we may need to fill in more fields, but this
+ * should be enough for now.
+ */
+ debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
+ debug_addr->r_version = 1;
+ debug_addr->r_ldbase = (ElfW(Addr))
+ DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));
+ debug_addr->r_brk = (unsigned long) &_dl_debug_state;
+ _dl_debug_addr = debug_addr;
+
+ /* Do not notify the debugger until the interpreter is in the list */
+
+ /* OK, we now have the application in the list, and we have some
+ * basic stuff in place. Now search through the list for other shared
+ * libraries that should be loaded, and insert them on the list in the
+ * correct order.
+ */
+
+ _dl_map_cache();
+
+#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
+ if (_dl_preload) {
+ char c, *str, *str2;
+
+ str = _dl_preload;
+ while (*str == ':' || *str == ' ' || *str == '\t')
+ str++;
+
+ while (*str) {
+ str2 = str;
+ while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
+ str2++;
+ c = *str2;
+ *str2 = '\0';
+
+ if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
+ _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname);
+
+ tpnt1 = _dl_load_shared_library(
+ _dl_secure ? DL_RESOLVE_SECURE : 0,
+ &rpnt, NULL, str, trace_loaded_objects);
+ if (!tpnt1) {
+#ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects || _dl_trace_prelink)
+ _dl_dprintf(1, "\t%s => not found\n", str);
+ else
+#endif
+ {
+ _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
+ _dl_exit(15);
+ }
+ } else {
+ tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
+
+ _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
+
+#ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects && !_dl_trace_prelink &&
+ tpnt1->usage_count == 1) {
+ /* This is a real hack to make
+ * ldd not print the library
+ * itself when run on a
+ * library.
+ */
+ if (_dl_strcmp(_dl_progname, str) != 0)
+ _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
+ DL_LOADADDR_BASE(tpnt1->loadaddr));
+ }
+#endif
+ }
+ }
+
+ *str2 = c;
+ str = str2;
+ while (*str == ':' || *str == ' ' || *str == '\t')
+ str++;
+ }
+ }
+#endif /* __LDSO_PRELOAD_ENV_SUPPORT__ */
+
+#ifdef __LDSO_PRELOAD_FILE_SUPPORT__
+ do {
+ char *preload;
+ int fd;
+ char c, *cp, *cp2;
+ struct stat st;
+
+ if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
+ break;
+ }
+
+ if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
+ _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
+ _dl_progname, LDSO_PRELOAD);
+ break;
+ }
+
+ preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ _dl_close(fd);
+ if (preload == (caddr_t) -1) {
+ _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
+ _dl_progname, __LINE__, LDSO_PRELOAD);
+ break;
+ }
+
+ /* convert all separators and comments to spaces */
+ for (cp = preload; *cp; /*nada */ ) {
+ if (*cp == ':' || *cp == '\t' || *cp == '\n') {
+ *cp++ = ' ';
+ } else if (*cp == '#') {
+ do {
+ *cp++ = ' ';
+ } while (*cp != '\n' && *cp != '\0');
+ } else {
+ cp++;
+ }
+ }
+
+ /* find start of first library */
+ for (cp = preload; *cp && *cp == ' '; cp++)
+ /*nada */ ;
+
+ while (*cp) {
+ /* find end of library */
+ for (cp2 = cp; *cp && *cp != ' '; cp++)
+ /*nada */ ;
+ c = *cp;
+ *cp = '\0';
+
+ _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname);
+
+ tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
+ if (!tpnt1) {
+# ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects || _dl_trace_prelink)
+ _dl_dprintf(1, "\t%s => not found\n", cp2);
+ else
+# endif
+ {
+ _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
+ _dl_exit(15);
+ }
+ } else {
+ tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
+
+ _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
+
+# ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects && !_dl_trace_prelink &&
+ tpnt1->usage_count == 1) {
+ _dl_dprintf(1, "\t%s => %s (%x)\n",
+ cp2, tpnt1->libname,
+ DL_LOADADDR_BASE(tpnt1->loadaddr));
+ }
+# endif
+ }
+
+ /* find start of next library */
+ *cp = c;
+ for ( /*nada */ ; *cp && *cp == ' '; cp++)
+ /*nada */ ;
+ }
+
+ _dl_munmap(preload, st.st_size + 1);
+ } while (0);
+#endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */
+
+ nlist = 0;
+ for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
+ ElfW(Dyn) *this_dpnt;
+
+ nlist++;
+ for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) {
+ if (this_dpnt->d_tag == DT_NEEDED) {
+ char *name;
+ struct init_fini_list *tmp;
+
+ lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
+ name = _dl_get_last_path_component(lpntstr);
+ _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname);
+
+ if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
+ if (!ldso_tpnt) {
+ /* Insert the ld.so only once */
+ ldso_tpnt = add_ldso(tpnt, load_addr,
+ ldso_mapaddr, auxvt, rpnt);
+ }
+ ldso_tpnt->usage_count++;
+ tpnt1 = ldso_tpnt;
+ } else
+ tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects);
+
+ if (!tpnt1) {
+#ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects || _dl_trace_prelink) {
+ _dl_dprintf(1, "\t%s => not found\n", lpntstr);
+ continue;
+ } else
+#endif
+ {
+ _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
+ _dl_exit(16);
+ }
+ }
+
+ tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */
+ tmp->tpnt = tpnt1;
+ tmp->next = tcurr->init_fini;
+ tcurr->init_fini = tmp;
+
+ tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
+
+ _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
+
+#ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects && !_dl_trace_prelink &&
+ tpnt1->usage_count == 1) {
+ _dl_dprintf(1, "\t%s => %s (%x)\n",
+ lpntstr, tpnt1->libname,
+ DL_LOADADDR_BASE(tpnt1->loadaddr));
+ }
+#endif
+ }
+ }
+ }
+ _dl_unmap_cache();
+
+ /* Keep track of the number of elements in the global scope */
+ nscope_elem = nlist;
+
+ if (_dl_loaded_modules->libtype == elf_executable) {
+ --nlist; /* Exclude the application. */
+ tcurr = _dl_loaded_modules->next;
+ } else
+ tcurr = _dl_loaded_modules;
+ init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
+ i = 0;
+ for (; tcurr; tcurr = tcurr->next)
+ init_fini_list[i++] = tcurr;
+
+ /* Sort the INIT/FINI list in dependency order. */
+ for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+ unsigned int j, k;
+
+ for (j = 0; init_fini_list[j] != tcurr; ++j)
+ /* Empty */;
+ for (k = j + 1; k < nlist; ++k) {
+ struct init_fini_list *runp = init_fini_list[k]->init_fini;
+
+ for (; runp; runp = runp->next) {
+ if (runp->tpnt == tcurr) {
+ struct elf_resolve *here = init_fini_list[k];
+ _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j);
+ for (i = (k - j); i; --i)
+ init_fini_list[i+j] = init_fini_list[i+j-1];
+ init_fini_list[j] = here;
+ ++j;
+ break;
+ }
+ }
+ }
+ }
+#ifdef __SUPPORT_LD_DEBUG__
+ if (_dl_debug) {
+ _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n");
+ for (i = 0; i < nlist; i++) {
+ struct init_fini_list *tmp;
+
+ _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n",
+ init_fini_list[i]->libname);
+ tmp = init_fini_list[i]->init_fini;
+ for (; tmp; tmp = tmp->next)
+ _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname);
+ _dl_dprintf(_dl_debug_file, "\n");
+ }
+ }
+#endif
+
+ /*
+ * If the program interpreter is not in the module chain, add it.
+ * This will be required for dlopen to be able to access the internal
+ * functions in the dynamic linker and to relocate the interpreter
+ * again once all libs are loaded.
+ */
+ if (!ldso_tpnt) {
+ tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
+ tpnt->usage_count++;
+ nscope_elem++;
+ } else
+ tpnt = ldso_tpnt;
+
+#ifdef RERELOCATE_LDSO
+ /* Only rerelocate functions for now. */
+ tpnt->init_flag = RELOCS_DONE;
+ lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]);
+# ifdef ALLOW_ZERO_PLTGOT
+ if (tpnt->dynamic_info[DT_PLTGOT])
+# endif
+ INIT_GOT(lpnt, tpnt);
+#else
+ tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
+#endif
+ tpnt = NULL;
+
+ /*
+ * Allocate the global scope array.
+ */
+ scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+
+ for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
+ scope_elem_list[i++] = tcurr;
+
+ _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
+ _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
+ /*
+ * The symbol scope of the application, that is the first entry of the
+ * _dl_loaded_modules list, is just the global scope to be used for the
+ * symbol lookup.
+ */
+ global_scope = &_dl_loaded_modules->symbol_scope;
+
+ /* Build the local scope for each loaded modules. */
+ local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+ i = 1;
+ for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+ unsigned int k;
+ cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
+ tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+ tcurr->symbol_scope.r_nlist = cnt;
+ _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
+ /* Restoring the init_flag.*/
+ for (k = 1; k < nscope_elem; k++)
+ scope_elem_list[k]->init_flag &= ~DL_RESERVED;
+ }
+
+ _dl_free(local_scope);
+
+#ifdef __LDSO_LDD_SUPPORT__
+ /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
+ if (trace_loaded_objects && !_dl_trace_prelink)
+ _dl_exit(0);
+#endif
+
+#if defined(USE_TLS) && USE_TLS
+ /* We do not initialize any of the TLS functionality unless any of the
+ * initial modules uses TLS. This makes dynamic loading of modules with
+ * TLS impossible, but to support it requires either eagerly doing setup
+ * now or lazily doing it later. Doing it now makes us incompatible with
+ * an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
+ * used. Trying to do it lazily is too hairy to try when there could be
+ * multiple threads (from a non-TLS-using libpthread). */
+ bool was_tls_init_tp_called = tls_init_tp_called;
+ if (tcbp == NULL) {
+ _dl_debug_early("Calling init_tls()!\n");
+ tcbp = init_tls ();
+ }
+#endif
+#ifdef __UCLIBC_HAS_SSP__
+ /* Set up the stack checker's canary. */
+ stack_chk_guard = _dl_setup_stack_chk_guard ();
+# ifdef THREAD_SET_STACK_GUARD
+ THREAD_SET_STACK_GUARD (stack_chk_guard);
+# else
+ __stack_chk_guard = stack_chk_guard;
+# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
+ __guard = stack_chk_guard;
+# endif
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+ if (_dl_trace_prelink) {
+
+ unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1);
+
+ for (i = 0; i < nscope_trace; i++)
+ trace_objects(scope_elem_list[i],
+ _dl_get_last_path_component(scope_elem_list[i]->libname));
+
+ if (_dl_verbose)
+ /* Warn about undefined symbols. */
+ if (_dl_symbol_tables)
+ if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
+ _dl_exit(-1);
+ _dl_exit(0);
+ }
+
+ if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) {
+ ElfW(Lib) *liblist, *liblistend;
+ struct elf_resolve **r_list, **r_listend, *l;
+ const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB];
+
+ _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0);
+ liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX];
+ liblistend = (ElfW(Lib) *)
+ ((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]);
+ r_list = _dl_loaded_modules->symbol_scope.r_list;
+ r_listend = r_list + nscope_elem;
+
+ for (; r_list < r_listend && liblist < liblistend; r_list++) {
+ l = *r_list;
+
+ if (l == _dl_loaded_modules)
+ continue;
+
+ /* If the library is not mapped where it should, fail. */
+ if (l->loadaddr)
+ break;
+
+ /* Next, check if checksum matches. */
+ if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 ||
+ l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum)
+ break;
+
+ if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 ||
+ (l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp))
+ break;
+
+ if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0)
+ break;
+
+ ++liblist;
+ }
+
+
+ if (r_list == r_listend && liblist == liblistend)
+ prelinked = true;
+
+ }
+
+ _dl_debug_early ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
+
+ if (prelinked) {
+ if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) {
+ ELF_RELOC *conflict;
+ unsigned long conflict_size;
+
+ _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0);
+ conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX];
+ conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX];
+ _dl_parse_relocation_information(_dl_symbol_tables, global_scope,
+ (unsigned long) conflict, conflict_size);
+ }
+
+ /* Mark all the objects so we know they have been already relocated. */
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ tpnt->init_flag |= RELOCS_DONE;
+ if (tpnt->relro_size)
+ _dl_protect_relro (tpnt);
+ }
+ } else
+#endif
+
+ {
+
+ _dl_debug_early("Beginning relocation fixups\n");
+
+#ifdef __mips__
+ /*
+ * Relocation of the GOT entries for MIPS have to be done
+ * after all the libraries have been loaded.
+ */
+ _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy);
+#endif
+
+ /*
+ * OK, now all of the kids are tucked into bed in their proper
+ * addresses. Now we go through and look for REL and RELA records that
+ * indicate fixups to the GOT tables. We need to do this in reverse
+ * order so that COPY directives work correctly.
+ */
+ if (_dl_symbol_tables)
+ if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
+ _dl_exit(-1);
+
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ if (tpnt->relro_size)
+ _dl_protect_relro (tpnt);
+ }
+ } /* not prelinked */
+
+#if defined(USE_TLS) && USE_TLS
+ if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
+ ++_dl_tls_generation;
+
+ _dl_debug_early("Calling _dl_allocate_tls_init()!\n");
+
+ /* Now that we have completed relocation, the initializer data
+ for the TLS blocks has its final values and we can copy them
+ into the main thread's TLS area, which we allocated above. */
+ _dl_allocate_tls_init (tcbp);
+
+ /* And finally install it for the main thread. If ld.so itself uses
+ TLS we know the thread pointer was initialized earlier. */
+ if (! tls_init_tp_called) {
+ const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD);
+ if (__builtin_expect (lossage != NULL, 0)) {
+ _dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
+ _dl_exit(30);
+ }
+ }
+#endif /* USE_TLS */
+
+ /* OK, at this point things are pretty much ready to run. Now we need
+ * to touch up a few items that are required, and then we can let the
+ * user application have at it. Note that the dynamic linker itself
+ * is not guaranteed to be fully dynamicly linked if we are using
+ * ld.so.1, so we have to look up each symbol individually.
+ */
+
+ _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
+ if (_dl_envp)
+ *_dl_envp = (unsigned long) envp;
+
+#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
+ {
+ unsigned int j;
+ ElfW(Phdr) *myppnt;
+
+ /* We had to set the protections of all pages to R/W for
+ * dynamic linking. Set text pages back to R/O.
+ */
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
+ if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
+ _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN),
+ (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
+ }
+ }
+ }
+
+ }
+#endif
+ /* Notify the debugger we have added some objects. */
+ _dl_debug_addr->r_state = RT_ADD;
+ _dl_debug_state();
+
+ /* Run pre-initialization functions for the executable. */
+ _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
+ _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
+ _dl_loaded_modules->loadaddr);
+
+ /* Run initialization functions for loaded objects. For the
+ main executable, they will be run from __uClibc_main. */
+ for (i = nlist; i; --i) {
+ tpnt = init_fini_list[i-1];
+ tpnt->init_fini = NULL; /* Clear, since alloca was used */
+ if (tpnt->init_flag & INIT_FUNCS_CALLED)
+ continue;
+ tpnt->init_flag |= INIT_FUNCS_CALLED;
+
+ if (tpnt->dynamic_info[DT_INIT]) {
+ void (*dl_elf_func) (void);
+
+ dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
+
+ _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
+
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
+ }
+
+ _dl_run_init_array(tpnt);
+ }
+
+ /* Find the real malloc function and make ldso functions use that from now on */
+ _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
+ global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+
+#if defined(USE_TLS) && USE_TLS
+ /* Find the real functions and make ldso functions use them from now on */
+ _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+
+ _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+
+ _dl_free_function = (void (*)(void *)) (intptr_t)
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+
+ _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+
+#endif
+
+ /* Notify the debugger that all objects are now mapped in. */
+ _dl_debug_addr->r_state = RT_CONSISTENT;
+ _dl_debug_state();
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+ if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
+ return (void *) app_tpnt->l_entry;
+ else
+#endif
+ return (void *) auxvt[AT_ENTRY].a_un.a_val;
+}
+
+#include "dl-hash.c"
+#include "dl-elf.c"
diff --git a/ap/build/uClibc/ldso/ldso/m68k/dl-debug.h b/ap/build/uClibc/ldso/ldso/m68k/dl-debug.h
new file mode 100644
index 0000000..71b513a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/m68k/dl-debug.h
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4: */
+/* m68k ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Adapted to ELF/68k by Andreas Schwab.
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ [0] "R_68K_NONE",
+ [1] "R_68K_32", "R_68K_16", "R_68K_8",
+ [4] "R_68K_PC32", "R_68K_PC16", "R_68K_PC8",
+ [7] "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8",
+ [10] "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O",
+ [13] "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8",
+ [16] "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O",
+ [19] "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE",
+ [23] "R_68K_NUM"
+};
diff --git a/ap/build/uClibc/ldso/ldso/m68k/dl-startup.h b/ap/build/uClibc/ldso/ldso/m68k/dl-startup.h
new file mode 100644
index 0000000..8755ecf
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/m68k/dl-startup.h
@@ -0,0 +1,97 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
+ */
+
+/* Perform operation OP with PC-relative SRC as the first operand and
+ * DST as the second. TMP is available as a temporary if needed. */
+
+#ifdef __mcoldfire__
+#define PCREL_OP(OP, SRC, DST, TMP, PC) \
+ "move.l #" SRC " - ., " TMP "\n\t" OP " (-8, " PC ", " TMP "), " DST
+#else
+#define PCREL_OP(OP, SRC, DST, TMP, PC) \
+ OP " " SRC "(" PC "), " DST
+#endif
+
+__asm__ ("\
+ .text\n\
+ .globl _start\n\
+ .type _start,@function\n\
+_start:\n\
+ move.l %sp, -(%sp)\n\
+ jbsr _dl_start\n\
+ addq.l #4, %sp\n\
+ /* FALLTHRU */\n\
+\n\
+ .globl _dl_start_user\n\
+.type _dl_start_user,@function\n\
+_dl_start_user:\n\
+ # Save the user entry point address in %a4.\n\
+ move.l %d0, %a4\n\
+ # See if we were run as a command with the executable file\n\
+ # name as an extra leading argument.\n\
+ " PCREL_OP ("move.l", "_dl_skip_args", "%d0", "%d0", "%pc") "\n\
+ # Pop the original argument count\n\
+ move.l (%sp)+, %d1\n\
+ # Subtract _dl_skip_args from it.\n\
+ sub.l %d0, %d1\n\
+ # Adjust the stack pointer to skip _dl_skip_args words.\n\
+ lea (%sp, %d0*4), %sp\n\
+ # Push back the modified argument count.\n\
+ move.l %d1, -(%sp)\n\
+ # Pass our finalizer function to the user in %a1.\n\
+ " PCREL_OP ("lea", "_dl_fini", "%a1", "%a1", "%pc") "\n\
+ # Initialize %fp with the stack pointer.\n\
+ move.l %sp, %fp\n\
+ # Jump to the user's entry point.\n\
+ jmp (%a4)\n\
+ .size _dl_start_user, . - _dl_start_user\n\
+ .previous");
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
+{
+ switch (ELF_R_TYPE(rpnt->r_info))
+ {
+ case R_68K_8:
+ *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_68K_16:
+ *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_68K_32:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_68K_PC8:
+ *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
+ - (unsigned int) reloc_addr);
+ break;
+ case R_68K_PC16:
+ *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
+ - (unsigned int) reloc_addr);
+ break;
+ case R_68K_PC32:
+ *reloc_addr = (symbol_addr + rpnt->r_addend
+ - (unsigned int) reloc_addr);
+ break;
+ case R_68K_GLOB_DAT:
+ case R_68K_JMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_68K_RELATIVE:
+ *reloc_addr = ((unsigned int) load_addr +
+ (rpnt->r_addend ? : *reloc_addr));
+ break;
+ default:
+ _dl_exit (1);
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/m68k/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/m68k/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/m68k/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/m68k/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/m68k/dl-sysdep.h
new file mode 100644
index 0000000..b5eda4e
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/m68k/dl-sysdep.h
@@ -0,0 +1,82 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
+ */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+#include <elf.h>
+/* Initialization sequence for a GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) (MODULE); \
+} while(0)
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_68K
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "m68k"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ PLT entries should not be allowed to define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ Elf32_Addr got;
+
+ __asm__ ("move.l _DYNAMIC@GOT.w(%%a5), %0"
+ : "=a" (got));
+ return got;
+}
+
+#ifdef __mcoldfire__
+#define PCREL_OP(OP, SRC, DST, TMP, PC) \
+ "move.l #" SRC " - ., " TMP "\n\t" OP " (-8, " PC ", " TMP "), " DST
+#else
+#define PCREL_OP(OP, SRC, DST, TMP, PC) \
+ OP " " SRC "(" PC "), " DST
+#endif
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ Elf32_Addr addr;
+ __asm__ (PCREL_OP ("lea", "_dl_start", "%0", "%0", "%%pc") "\n\t"
+ "sub.l _dl_start@GOT.w(%%a5), %0"
+ : "=a" (addr));
+ return addr;
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela * rpnt = (void *)rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/m68k/elfinterp.c b/ap/build/uClibc/ldso/ldso/m68k/elfinterp.c
new file mode 100644
index 0000000..4e87142
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/m68k/elfinterp.c
@@ -0,0 +1,324 @@
+/* vi: set sw=4 ts=4: */
+/* m68k ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Adapted to ELF/68k by Andreas Schwab.
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+#include "ldso.h"
+
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ ElfW(Addr) instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups)
+#endif
+ *got_addr = new_addr;
+
+ return (unsigned int)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size /= sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ _dl_dprintf(2, "can't handle reloc type "
+#if defined (__SUPPORT_LD_DEBUG__)
+ "%s\n", _dl_reltypes(reloc_type));
+#else
+ "%x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symbol_addr = 0;
+ symname = strtab + sym_ref.sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ /*
+ * We want to allow undefined references to weak symbols - this
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+ if (unlikely(!symbol_addr && ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_68K_NONE:
+ break;
+ case R_68K_8:
+ *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_68K_16:
+ *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_68K_32:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_68K_PC8:
+ *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
+ - (unsigned int) reloc_addr);
+ break;
+ case R_68K_PC16:
+ *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
+ - (unsigned int) reloc_addr);
+ break;
+ case R_68K_PC32:
+ *reloc_addr = (symbol_addr + rpnt->r_addend
+ - (unsigned int) reloc_addr);
+ break;
+ case R_68K_GLOB_DAT:
+ case R_68K_JMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ /* handled by elf_machine_relative()
+ case R_68K_RELATIVE:
+ *reloc_addr = ((unsigned int) tpnt->loadaddr
+ / * Compatibility kludge. * /
+ + (rpnt->r_addend ? : *reloc_addr));
+ */
+ break;
+ case R_68K_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\t%s move %d bytes from %x to %x\n",
+ symname, sym_ref.sym->st_size,
+ symbol_addr, reloc_addr);
+#endif
+ _dl_memcpy ((void *) reloc_addr,
+ (void *) symbol_addr,
+ sym_ref.sym->st_size);
+ } else
+ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
+ break;
+
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+#undef LAZY_RELOC_WORKS
+#ifdef LAZY_RELOC_WORKS
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ (void)scope;
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ (void)strtab;
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_68K_NONE:
+ break;
+ case R_68K_JMP_SLOT:
+ *reloc_addr += (unsigned int) tpnt->loadaddr;
+ break;
+ default:
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+#endif
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+#ifdef LAZY_RELOC_WORKS
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+#else
+ _dl_parse_relocation_information(rpnt, &_dl_loaded_modules->symbol_scope, rel_addr, rel_size);
+#endif
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/m68k/resolve.S b/ap/build/uClibc/ldso/ldso/m68k/resolve.S
new file mode 100644
index 0000000..1bd5c00
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/m68k/resolve.S
@@ -0,0 +1,28 @@
+/*
+ * These are various helper routines that are needed to run an ELF image.
+ */
+
+.text
+.even
+
+.globl _dl_linux_resolve
+ .type _dl_linux_resolve,@function
+_dl_linux_resolve:
+ # Save %a0 (struct return address) and %a1.
+ move.l %a0, -(%sp)
+ move.l %a1, -(%sp)
+ # Call the real address resolver.
+ jbsr _dl_linux_resolver
+ # Restore register %a0 and %a1.
+ move.l (%sp)+, %a1
+ move.l (%sp)+, %a0
+ # Pop parameters
+ addq.l #8, %sp
+ # Call real function.
+#if defined __mcoldfire__
+ move.l %d0,-(%sp)
+ rts
+#else
+ jmp (%d0)
+#endif
+.size _dl_linux_resolve,.-_dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/microblaze/dl-debug.h b/ap/build/uClibc/ldso/ldso/microblaze/dl-debug.h
new file mode 100644
index 0000000..6fd7bd5
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/microblaze/dl-debug.h
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/* microblaze shared library loader suppport
+ *
+ * Copyright (C) 2011 Ryan Flux
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+ {
+ "R_MICROBLAZE_NONE",
+ "R_MICROBLAZE_32",
+ "R_MICROBLAZE_32_PCREL",
+ "R_MICROBLAZE_64_PCREL",
+ "R_MICROBLAZE_32_PCREL_LO",
+ "R_MICROBLAZE_64",
+ "R_MICROBLAZE_32_LO",
+ "R_MICROBLAZE_SRO32",
+ "R_MICROBLAZE_SRW32",
+ "R_MICROBLAZE_64_NONE",
+ "R_MICROBLAZE_32_SYM_OP_SYM",
+ "R_MICROBLAZE_GNU_VTINHERIT",
+ "R_MICROBLAZE_GNU_VTENTRY",
+ "R_MICROBLAZE_GOTPC_64",
+ "R_MICROBLAZE_GOT_64",
+ "R_MICROBLAZE_PLT_64",
+ "R_MICROBLAZE_REL",
+ "R_MICROBLAZE_JUMP_SLOT",
+ "R_MICROBLAZE_GLOB_DAT",
+ "R_MICROBLAZE_GOTOFF_64",
+ "R_MICROBLAZE_GOTOFF_32",
+ "R_MICROBLAZE_COPY",
+ };
diff --git a/ap/build/uClibc/ldso/ldso/microblaze/dl-startup.h b/ap/build/uClibc/ldso/ldso/microblaze/dl-startup.h
new file mode 100644
index 0000000..44966d6
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/microblaze/dl-startup.h
@@ -0,0 +1,102 @@
+/* Startup code for the microblaze platform, based on glibc 2.3.6, dl-machine.h */
+
+/*
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+__asm__ ("\
+ .text\n\
+ .globl _start\n\
+ .type _start,@function\n\
+_start:\n\
+ addk r5,r0,r1\n\
+ addk r3,r0,r0\n\
+1:\n\
+ addik r5,r5,4\n\
+ lw r4,r5,r0\n\
+ bneid r4,1b\n\
+ addik r3,r3,1\n\
+ addik r3,r3,-1\n\
+ addk r5,r0,r1\n\
+ sw r3,r5,r0\n\
+ addik r1,r1,-24\n\
+ sw r15,r1,r0\n\
+ brlid r15,_dl_start\n\
+ nop\n\
+ /* FALLTHRU */\n\
+\n\
+ .globl _dl_start_user\n\
+ .type _dl_start_user,@function\n\
+_dl_start_user:\n\
+ mfs r20,rpc\n\
+ addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n\
+ lwi r4,r20,_dl_skip_args@GOTOFF\n\
+ lwi r5,r1,24\n\
+ rsubk r5,r4,r5\n\
+ addk r4,r4,r4\n\
+ addk r4,r4,r4\n\
+ addk r1,r1,r4\n\
+ swi r5,r1,24\n\
+ swi r3,r1,20\n\
+ addk r6,r5,r0\n\
+ addk r5,r5,r5\n\
+ addk r5,r5,r5\n\
+ addik r7,r1,28\n\
+ addk r8,r7,r5\n\
+ addik r8,r8,4\n\
+ lwi r5,r1,24\n\
+ lwi r3,r1,20\n\
+ addk r4,r5,r5\n\
+ addk r4,r4,r4\n\
+ addik r6,r1,28\n\
+ addk r7,r6,r4\n\
+ addik r7,r7,4\n\
+ addik r15,r20,_dl_fini@GOTOFF\n\
+ addik r15,r15,-8\n\
+ brad r3\n\
+ addik r1,r1,24\n\
+ nop\n\
+ .size _dl_start_user, . - _dl_start_user\n\
+ .previous");
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
+
+/* The ld.so library requires relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
+{
+
+ switch (ELF_R_TYPE(rpnt->r_info))
+ {
+ case R_MICROBLAZE_REL:
+
+ *reloc_addr = load_addr + rpnt->r_addend;
+ break;
+
+ default:
+ _dl_exit(1);
+ break;
+
+ }
+
+}
diff --git a/ap/build/uClibc/ldso/ldso/microblaze/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/microblaze/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/microblaze/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/microblaze/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/microblaze/dl-sysdep.h
new file mode 100644
index 0000000..1f89673
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/microblaze/dl-sysdep.h
@@ -0,0 +1,85 @@
+/* elf reloc code for the microblaze platform, based on glibc 2.3.6, dl-machine.h */
+
+/*
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Use reloca */
+#define ELF_USES_RELOCA
+
+#include <elf.h>
+
+
+/* Initialise the GOT */
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+} while(0)
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_MICROBLAZE_OLD
+#undef MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "microblaze"
+
+#define elf_machine_type_class(type) \
+ (((type) == R_MICROBLAZE_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT \
+ | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ Elf32_Addr got_entry_0;
+ __asm__ __volatile__(
+ "lwi %0,r20,0"
+ :"=r"(got_entry_0)
+ );
+ return got_entry_0;
+}
+
+
+/* Return the run-time load address of the shared object. */
+static inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ /* Compute the difference between the runtime address of _DYNAMIC as seen
+ by a GOTOFF reference, and the link-time address found in the special
+ unrelocated first GOT entry. */
+ Elf32_Addr dyn;
+ __asm__ __volatile__ (
+ "addik %0,r20,_DYNAMIC@GOTOFF"
+ : "=r"(dyn)
+ );
+ return dyn - elf_machine_dynamic ();
+}
+
+
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rel * rpnt = (void *) rel_addr;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (rpnt)->r_offset);
+
+ *reloc_addr += load_off;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/microblaze/elfinterp.c b/ap/build/uClibc/ldso/ldso/microblaze/elfinterp.c
new file mode 100644
index 0000000..1f6aeff
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/microblaze/elfinterp.c
@@ -0,0 +1,330 @@
+/* vi: set sw=4 ts=4: */
+/* microblaze ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ ElfW(Addr) instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups)
+#endif
+ *got_addr = new_addr;
+
+ return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size /= sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ _dl_dprintf(2, "can't handle reloc type "
+#if defined (__SUPPORT_LD_DEBUG__)
+ "%s\n", _dl_reltypes(reloc_type));
+#else
+ "%x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+#if defined USE_TLS && USE_TLS
+ struct elf_resolve *tls_tpnt;
+#endif
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symbol_addr = 0;
+ symname = strtab + sym_ref.sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ /*
+ * We want to allow undefined references to weak symbols - this
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+ if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS)
+ && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
+ }
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = sym_ref.tpnt;
+#endif
+ } else {
+ /* Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself. */
+ symbol_addr = sym_ref.sym->st_value;
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = tpnt;
+#endif
+ }
+
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (reloc_addr) {
+ old_val = *reloc_addr;
+ } else {
+ old_val = 0;
+ }
+#endif
+
+ switch (reloc_type) {
+ case R_MICROBLAZE_NONE:
+ case R_MICROBLAZE_64_NONE:
+ break;
+
+ case R_MICROBLAZE_64:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ case R_MICROBLAZE_32:
+ case R_MICROBLAZE_32_LO:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ case R_MICROBLAZE_32_PCREL:
+ case R_MICROBLAZE_32_PCREL_LO:
+ case R_MICROBLAZE_64_PCREL:
+ case R_MICROBLAZE_SRO32:
+ case R_MICROBLAZE_SRW32:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ case R_MICROBLAZE_GLOB_DAT:
+ case R_MICROBLAZE_JUMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+/* Handled by elf_machine_relative */
+ case R_MICROBLAZE_REL:
+ *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+ break;
+
+ case R_MICROBLAZE_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\t%s move %d bytes from %x to %x\n",
+ symname, sym_ref.sym->st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ sym_ref.sym->st_size);
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ else
+ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
+#endif
+ break;
+
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ (void)scope;
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ (void)strtab;
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_MICROBLAZE_NONE:
+ break;
+ case R_MICROBLAZE_JUMP_SLOT:
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/microblaze/resolve.S b/ap/build/uClibc/ldso/ldso/microblaze/resolve.S
new file mode 100644
index 0000000..8ad94fe
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/microblaze/resolve.S
@@ -0,0 +1,52 @@
+
+/* This code is used in dl-runtime.c to call the `fixup' function
+ and then redirect to the address it returns. */
+/* We assume that R3 contain relocation offset and R4 contains
+ link_map (_DYNAMIC). This must be consistent with the JUMP_SLOT
+ layout generated by binutils. */
+
+/* Based on glibc 2.3.6, dl-machine.h */
+/*
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+.text
+.align 4
+.globl _dl_linux_resolver
+.globl _dl_linux_resolve
+.type _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+ addik r1,r1,-40
+ swi r5,r1,12
+ swi r6,r1,16
+ swi r7,r1,20
+ swi r8,r1,24
+ swi r9,r1,28
+ swi r10,r1,32
+ swi r15,r1,0
+ addk r5,r0,r4
+ brlid r15, _dl_linux_resolver
+ addk r6,r0,r3; /* delay slot */
+ lwi r10,r1,32
+ lwi r9,r1,28
+ lwi r8,r1,24
+ lwi r7,r1,20
+ lwi r6,r1,16
+ lwi r5,r1,12
+ lwi r15,r1,0
+ brad r3
+ addik r1,r1,40; /* delay slot */
+ .size _dl_linux_resolve, . - _dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/mips/README b/ap/build/uClibc/ldso/ldso/mips/README
new file mode 100644
index 0000000..9ca6a86
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/README
@@ -0,0 +1,52 @@
+Almost all of the code present in these source files was taken
+from GLIBC. In the descriptions below, all files mentioned are
+with respect to the top level GLIBC source directory accept for
+code taken from the Linux kernel.
+
+boot1_arch.h
+------------
+Contains code to fix up the stack pointer so that the dynamic
+linker can find argc, argv and Auxillary Vector Table (AVT).
+The code is taken from the function 'RTLD_START' in the file
+'sysdeps/mips/dl-machine.h'.
+
+elfinterp.c
+-----------
+Contains the runtime resolver code taken from the function
+'__dl_runtime_resolve' in 'sysdeps/mips/dl-machine.h'. Also
+contains the function to perform relocations for objects
+other than the linker itself. The code was taken from the
+function 'elf_machine_rel' in 'sysdeps/mips/dl-machine.h'.
+
+dl-syscalls.h
+-------------
+Used to contain all the macro functions for the system calls
+as well as the list of system calls supported. We now include
+<sys/syscall.h> but with the __set_errno macro defined empty
+so we can use the same file for the linker as well as userspace.
+Original code was taken from the Linux kernel source 2.4.17 and
+can be found in the file 'include/asm-mips/unistd.h'.
+
+dl-sysdep.h
+-----------
+Contains bootstrap code for the dynamic linker, magic numbers
+for detecting MIPS target types and some macros. The macro
+function 'PERFORM_BOOTSTRAP_GOT' is used to relocate the dynamic
+linker's GOT so that function calls can be made. The code is
+taken from the function 'ELF_MACHINE_BEFORE_RTLD_RELOC' in the
+file 'sysdeps/mips/dl-machine.h'. The other macro function
+'PERFORM_BOOTSTRAP_RELOC' is used to do the relocations for
+the dynamic loader. The code is taken from the function
+'elf_machine_rel' in the file 'sysdeps/mips/dl-machine.h'. The
+final macro function is 'INIT_GOT' which initializes the GOT
+for the application being dynamically linked and loaded. The
+code is taken from the functions 'elf_machine_runtime_setup'
+and 'elf_machine_got_rel' in 'sysdeps/mips/dl-machine.h'.
+
+resolve.S
+---------
+Contains the low-level assembly code for the dynamic runtime
+resolver. The code is taken from the assembly code function
+'_dl_runtime_resolve' in the file 'sysdeps/mips/dl-machine.h'.
+The code looks a bit different since we only need to pass the
+symbol index and the old GP register.
diff --git a/ap/build/uClibc/ldso/ldso/mips/dl-debug.h b/ap/build/uClibc/ldso/ldso/mips/dl-debug.h
new file mode 100644
index 0000000..33b2dc8
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/dl-debug.h
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/* mips/mipsel ELF shared library loader suppport
+ *
+ Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ [0] "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32",
+ [3] "R_MIPS_REL32", "R_MIPS_26", "R_MIPS_HI16",
+ [6] "R_MIPS_LO16", "R_MIPS_GPREL16", "R_MIPS_LITERAL",
+ [9] "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16",
+ [12] "R_MIPS_GPREL32",
+ [16] "R_MIPS_SHIFT5", "R_MIPS_SHIFT6", "R_MIPS_64",
+ [19] "R_MIPS_GOT_DISP", "R_MIPS_GOT_PAGE", "R_MIPS_GOT_OFST",
+ [22] "R_MIPS_GOT_HI16", "R_MIPS_GOT_LO16", "R_MIPS_SUB",
+ [25] "R_MIPS_INSERT_A", "R_MIPS_INSERT_B", "R_MIPS_DELETE",
+ [28] "R_MIPS_HIGHER", "R_MIPS_HIGHEST", "R_MIPS_CALL_HI16",
+ [31] "R_MIPS_CALL_LO16", "R_MIPS_SCN_DISP", "R_MIPS_REL16",
+ [34] "R_MIPS_ADD_IMMEDIATE", "R_MIPS_PJUMP", "R_MIPS_RELGOT",
+ [37] "R_MIPS_JALR",
+};
diff --git a/ap/build/uClibc/ldso/ldso/mips/dl-startup.h b/ap/build/uClibc/ldso/ldso/mips/dl-startup.h
new file mode 100644
index 0000000..31730d4
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/dl-startup.h
@@ -0,0 +1,190 @@
+/* Any assembly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture.
+ * Copyright (C) 2005 by Joakim Tjernlund
+ * Copyright (C) 2005 by Erik Andersen
+ */
+
+
+#include <sgidefs.h>
+__asm__(""
+ " .text\n"
+ " .globl _start\n"
+ " .ent _start\n"
+ " .type _start,@function\n"
+ "_start:\n"
+ " .set noreorder\n"
+ " move $25, $31\n"
+ " bal 0f\n"
+ " nop\n"
+ "0:\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+ " .cpload $31\n"
+#else /* N32 || N64 */
+ " .cpsetup $31, $2, 0b\n"
+#endif /* N32 || N64 */
+ " move $31, $25\n"
+ " .set reorder\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ " dla $4, _DYNAMIC\n"
+ " sd $4, -0x7ff0($28)\n"
+#else /* O32 || N32 */
+ " la $4, _DYNAMIC\n"
+ " sw $4, -0x7ff0($28)\n"
+#endif /* O32 || N32 */
+ " move $4, $29\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+ " subu $29, 16\n"
+#endif
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ " dla $8, .coff\n"
+#else /* O32 || N32 */
+ " la $8, .coff\n"
+#endif /* O32 || N32 */
+ " bltzal $8, .coff\n"
+ ".coff:\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ " dsubu $8, $31, $8\n"
+ " dla $25, _dl_start\n"
+ " daddu $25, $8\n"
+#else /* O32 || N32 */
+ " subu $8, $31, $8\n"
+ " la $25, _dl_start\n"
+ " addu $25, $8\n"
+#endif /* O32 || N32 */
+ " jalr $25\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+ " addiu $29, 16\n"
+#endif
+ " move $16, $28\n"
+ " move $17, $2\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ " ld $2, _dl_skip_args\n"
+ " beq $2, $0, 1f\n"
+ " ld $4, 0($29)\n"
+ " dsubu $4, $2\n"
+ " dsll $2, 2\n"
+ " daddu $29, $2\n"
+ " sd $4, 0($29)\n"
+ "1:\n"
+ " ld $5, 0($29)\n"
+ " dla $6, 8 ($29)\n"
+ " dsll $7, $5, 2\n"
+ " daddu $7, $7, $6\n"
+ " daddu $7, $7, 4\n"
+ " and $2, $29, -4 * 4\n"
+ " sd $29, -8($2)\n"
+ " dsubu $29, $2, 32\n"
+ " ld $29, 24($29)\n"
+ " dla $2, _dl_fini\n"
+#else /* O32 || N32 */
+ " lw $2, _dl_skip_args\n"
+ " beq $2, $0, 1f\n"
+ " lw $4, 0($29)\n"
+ " subu $4, $2\n"
+ " sll $2, 2\n"
+ " addu $29, $2\n"
+ " sw $4, 0($29)\n"
+ "1:\n"
+ " lw $5, 0($29)\n"
+ " la $6, 4 ($29)\n"
+ " sll $7, $5, 2\n"
+ " addu $7, $7, $6\n"
+ " addu $7, $7, 4\n"
+ " and $2, $29, -2 * 4\n"
+ " sw $29, -4($2)\n"
+ " subu $29, $2, 32\n"
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+ " .cprestore 16\n"
+#endif
+ " lw $29, 28($29)\n"
+ " la $2, _dl_fini\n"
+#endif /* O32 || N32 */
+ " move $25, $17\n"
+ " jr $25\n"
+ ".end _start\n"
+ ".size _start, . -_start\n"
+ "\n\n"
+ "\n\n"
+ ".previous\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1)
+
+
+/* We can't call functions earlier in the dl startup process */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+
+/*
+ * Here is a macro to perform the GOT relocation. This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(tpnt) \
+do { \
+ ElfW(Sym) *sym; \
+ ElfW(Addr) i; \
+ register ElfW(Addr) gp __asm__ ("$28"); \
+ ElfW(Addr) *mipsgot = elf_mips_got_from_gpreg (gp); \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
+ mipsgot[i++] += tpnt->loadaddr; \
+ \
+ /* Handle global GOT entries */ \
+ mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \
+ sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + \
+ tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \
+ i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\
+ \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF || \
+ sym->st_shndx == SHN_COMMON) \
+ *mipsgot = tpnt->loadaddr + sym->st_value; \
+ else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *mipsgot != sym->st_value) \
+ *mipsgot += tpnt->loadaddr; \
+ else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *mipsgot += tpnt->loadaddr; \
+ } \
+ else \
+ *mipsgot = tpnt->loadaddr + sym->st_value; \
+ \
+ mipsgot++; \
+ sym++; \
+ } \
+} while (0)
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader.
+ */
+#if _MIPS_SIM == _MIPS_SIM_ABI64 /* consult with glibc sysdeps/mips/dl-machine.h 1.69 */
+#define R_MIPS_BOOTSTRAP_RELOC ((R_MIPS_64 << 8) | R_MIPS_REL32)
+#else /* N32 || O32 */
+#define R_MIPS_BOOTSTRAP_RELOC R_MIPS_REL32
+#endif
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF_R_TYPE((RELP)->r_info)) { \
+ case R_MIPS_BOOTSTRAP_RELOC: \
+ if (SYMTAB) { \
+ if (symtab_index<tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])\
+ *REL += SYMBOL; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
diff --git a/ap/build/uClibc/ldso/ldso/mips/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/mips/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/mips/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/mips/dl-sysdep.h
new file mode 100644
index 0000000..6041245
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/dl-sysdep.h
@@ -0,0 +1,248 @@
+/* vi: set sw=8 ts=8: */
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* Define this if the system uses RELOCA. */
+#undef ELF_USES_RELOCA
+#include <elf.h>
+
+#ifdef __mips64 /* from glibc sysdeps/mips/elf/ldsodefs.h 1.4 */
+/* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each
+ relocation entry specifies up to three actual relocations, all at
+ the same address. The first relocation which required a symbol
+ uses the symbol in the r_sym field. The second relocation which
+ requires a symbol uses the symbol in the r_ssym field. If all
+ three relocations require a symbol, the third one uses a zero
+ value.
+
+ We define these structures in internal headers because we're not
+ sure we want to make them part of the ABI yet. Eventually, some of
+ this may move into elf/elf.h. */
+
+/* An entry in a 64 bit SHT_REL section. */
+
+typedef struct
+{
+ Elf32_Word r_sym; /* Symbol index */
+ unsigned char r_ssym; /* Special symbol for 2nd relocation */
+ unsigned char r_type3; /* 3rd relocation type */
+ unsigned char r_type2; /* 2nd relocation type */
+ unsigned char r_type1; /* 1st relocation type */
+} _Elf64_Mips_R_Info;
+
+typedef union
+{
+ Elf64_Xword r_info_number;
+ _Elf64_Mips_R_Info r_info_fields;
+} _Elf64_Mips_R_Info_union;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */
+} Elf64_Mips_Rel;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Mips_Rela;
+
+#define ELF64_MIPS_R_SYM(i) \
+ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym)
+#define ELF64_MIPS_R_TYPE(i) \
+ (((_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1 \
+ | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \
+ ).r_info_fields.r_type2 << 8) \
+ | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \
+ ).r_info_fields.r_type3 << 16) \
+ | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \
+ ).r_info_fields.r_ssym << 24))
+#define ELF64_MIPS_R_INFO(sym, type) \
+ (__extension__ (_Elf64_Mips_R_Info_union) \
+ (__extension__ (_Elf64_Mips_R_Info) \
+ { (sym), ELF64_MIPS_R_SSYM (type), \
+ ELF64_MIPS_R_TYPE3 (type), \
+ ELF64_MIPS_R_TYPE2 (type), \
+ ELF64_MIPS_R_TYPE1 (type) \
+ }).r_info_number)
+/* These macros decompose the value returned by ELF64_MIPS_R_TYPE, and
+ compose it back into a value that it can be used as an argument to
+ ELF64_MIPS_R_INFO. */
+#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff)
+#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
+#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
+#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
+#define ELF64_MIPS_R_TYPEENC(type1, type2, type3, ssym) \
+ ((type1) \
+ | ((Elf32_Word)(type2) << 8) \
+ | ((Elf32_Word)(type3) << 16) \
+ | ((Elf32_Word)(ssym) << 24))
+
+#undef ELF64_R_SYM
+#define ELF64_R_SYM(i) ELF64_MIPS_R_SYM (i)
+#undef ELF64_R_TYPE
+#define ELF64_R_TYPE(i) ELF64_MIPS_R_TYPE (i)
+#undef ELF64_R_INFO
+#define ELF64_R_INFO(sym, type) ELF64_MIPS_R_INFO ((sym), (type))
+#endif /* __mips64 */
+
+#include <link.h>
+
+#define ARCH_NUM 4
+#define DT_MIPS_GOTSYM_IDX (DT_NUM + OS_NUM)
+#define DT_MIPS_LOCAL_GOTNO_IDX (DT_NUM + OS_NUM +1)
+#define DT_MIPS_SYMTABNO_IDX (DT_NUM + OS_NUM +2)
+#define DT_MIPS_PLTGOT_IDX (DT_NUM + OS_NUM +3)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+do { \
+if (dpnt->d_tag == DT_MIPS_GOTSYM) \
+ dynamic[DT_MIPS_GOTSYM_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) \
+ dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_MIPS_SYMTABNO) \
+ dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_MIPS_PLTGOT) \
+ dynamic[DT_MIPS_PLTGOT_IDX] = dpnt->d_un.d_val; \
+else if ((dpnt->d_tag == DT_MIPS_RLD_MAP) && (dpnt->d_un.d_ptr)) \
+ *(ElfW(Addr) *)(dpnt->d_un.d_ptr) = (ElfW(Addr)) debug_addr; \
+} while (0)
+
+#define ARCH_SKIP_RELOC(type_class, sym) \
+ ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
+
+/* Initialization sequence for the application/library GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ unsigned long idx; \
+ unsigned long *pltgot; \
+ \
+ /* Check if this is the dynamic linker itself */ \
+ if (MODULE->libtype == program_interpreter) \
+ continue; \
+ \
+ /* Fill in first two GOT entries according to the ABI */ \
+ GOT_BASE[0] = (unsigned long) _dl_runtime_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ pltgot = (unsigned long *) MODULE->dynamic_info[DT_MIPS_PLTGOT_IDX]; \
+ if (pltgot) { \
+ pltgot[0] = (unsigned long) _dl_runtime_pltresolve; \
+ pltgot[1] = (unsigned long) MODULE; \
+ } \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ idx = 2; \
+ while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
+ GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \
+ \
+} while (0)
+
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_MIPS
+#define MAGIC2 EM_MIPS_RS3_LE
+
+
+/* Used for error messages */
+#define ELF_TARGET "MIPS"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+unsigned long __dl_runtime_resolve(unsigned long sym_index,
+ unsigned long old_gpreg);
+
+struct elf_resolve;
+unsigned long __dl_runtime_pltresolve(struct elf_resolve *tpnt,
+ int reloc_entry);
+
+void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
+
+/* 4096 bytes alignment */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+#define OFFS_ALIGN (0x10000000000UL-0x1000)
+#endif /* O32 || N32 */
+
+#if defined USE_TLS
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define elf_machine_type_class(type) \
+ ((((type) == R_MIPS_JUMP_SLOT || (type) == R_MIPS_TLS_DTPMOD64 \
+ || (type) == R_MIPS_TLS_DTPREL64 || (type) == R_MIPS_TLS_TPREL64) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+# else
+# define elf_machine_type_class(type) \
+ ((((type) == R_MIPS_JUMP_SLOT || (type) == R_MIPS_TLS_DTPMOD32 \
+ || (type) == R_MIPS_TLS_DTPREL32 || (type) == R_MIPS_TLS_TPREL32) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+# endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
+#else
+#define elf_machine_type_class(type) \
+ ((((type) == R_MIPS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif /* USE_TLS */
+
+#define OFFSET_GP_GOT 0x7ff0
+
+static __always_inline ElfW(Addr) *
+elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
+{
+ /* FIXME: the offset of gp from GOT may be system-dependent. */
+ return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT);
+}
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. We assume its $gp points to the primary GOT. */
+static __always_inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ register ElfW(Addr) gp __asm__ ("$28");
+ return *elf_mips_got_from_gpreg (gp);
+}
+
+#define STRINGXP(X) __STRING(X)
+#define STRINGXV(X) STRINGV_(X)
+#define STRINGV_(...) # __VA_ARGS__
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+#define PTR_LA dla
+#define PTR_SUBU dsubu
+#else
+#define PTR_LA la
+#define PTR_SUBU subu
+#endif
+
+/* Return the run-time load address of the shared object. */
+static __always_inline ElfW(Addr)
+elf_machine_load_address (void)
+{
+ ElfW(Addr) addr;
+ __asm__ (" .set noreorder\n"
+ " " STRINGXP (PTR_LA) " %0, 0f\n"
+ " bltzal $0, 0f\n"
+ " nop\n"
+ "0: " STRINGXP (PTR_SUBU) " %0, $31, %0\n"
+ " .set reorder\n"
+ : "=r" (addr)
+ : /* No inputs */
+ : "$31");
+ return addr;
+}
+
+static __always_inline void
+elf_machine_relative (ElfW(Addr) load_off, const ElfW(Addr) rel_addr,
+ ElfW(Word) relative_count)
+{
+ /* No RELATIVE relocs in MIPS? */
+}
+
+#ifdef __mips64
+#define DL_MALLOC_ALIGN 8 /* N64/N32 needs 8 byte alignment */
+#endif
diff --git a/ap/build/uClibc/ldso/ldso/mips/elfinterp.c b/ap/build/uClibc/ldso/ldso/mips/elfinterp.c
new file mode 100644
index 0000000..e57a99f
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/elfinterp.c
@@ -0,0 +1,399 @@
+/* vi: set sw=4 ts=4: */
+/* mips/mipsel ELF shared library loader suppport
+ *
+ Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+extern int _dl_runtime_resolve(void);
+extern int _dl_runtime_pltresolve(void);
+
+#define OFFSET_GP_GOT 0x7ff0
+
+unsigned long __dl_runtime_resolve(unsigned long sym_index,
+ unsigned long old_gpreg)
+{
+ unsigned long *got = (unsigned long *) (old_gpreg - OFFSET_GP_GOT);
+ struct elf_resolve *tpnt = (struct elf_resolve *) got[1];
+ ElfW(Sym) *sym;
+ char *strtab;
+ unsigned long local_gotno;
+ unsigned long gotsym;
+ unsigned long new_addr;
+ unsigned long instr_addr;
+ char **got_addr;
+ char *symname;
+
+ gotsym = tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
+ local_gotno = tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];
+
+ sym = ((ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]) + sym_index;
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + sym->st_name;
+
+ new_addr = (unsigned long) _dl_find_hash(symname,
+ &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit (1);
+ }
+
+ /* Address of jump instruction to fix up */
+ instr_addr = (unsigned long) (got + local_gotno + sym_index - gotsym);
+ got_addr = (char **) instr_addr;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings)
+ {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+ "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = (char*)new_addr;
+ }
+#else
+ *got_addr = (char*)new_addr;
+#endif
+
+ return new_addr;
+}
+
+unsigned long
+__dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched: %x ==> %x @ %x",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = new_addr;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long)new_addr;
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ /* Nothing to do */
+ return;
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *xpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ char *strtab;
+ unsigned long i;
+ unsigned long *got;
+ unsigned long *reloc_addr=NULL;
+ unsigned long symbol_addr;
+ int reloc_type, symtab_index;
+ struct elf_resolve *tpnt = xpnt->dyn;
+ char *symname = NULL;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val=0;
+#endif
+
+ struct symbol_ref sym_ref;
+ /* Now parse the relocation information */
+ rel_size = rel_size / sizeof(ElfW(Rel));
+ rpnt = (ELF_RELOC *) rel_addr;
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
+
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ reloc_addr = (unsigned long *) (tpnt->loadaddr +
+ (unsigned long) rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+ symname = strtab + symtab[symtab_index].st_name;
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (reloc_addr)
+ old_val = *reloc_addr;
+#endif
+
+ if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
+ sym_ref.tpnt = NULL;
+ sym_ref.sym = &symtab[symtab_index];
+ symbol_addr = (unsigned long)_dl_find_hash(symname,
+ scope,
+ tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ if (unlikely(!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
+ return 1;
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ }
+ if (!symtab_index) {
+ /* Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself.
+ */
+ symbol_addr = symtab[symtab_index].st_value;
+ }
+
+ switch (reloc_type) {
+#if defined USE_TLS && USE_TLS
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+ case R_MIPS_TLS_DTPMOD64:
+ case R_MIPS_TLS_DTPREL64:
+ case R_MIPS_TLS_TPREL64:
+# else
+ case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPREL32:
+ case R_MIPS_TLS_TPREL32:
+# endif
+ {
+ struct elf_resolve *tls_tpnt = NULL;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+
+ if (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) {
+ symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
+ tpnt, elf_machine_type_class(reloc_type), &sym_ref);
+ tls_tpnt = sym_ref.tpnt;
+ }
+ /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous'
+ symbol. This is the case for a static tls variable, so the lookup
+ module is just that one is referencing the tls variable. */
+ if (!tls_tpnt)
+ tls_tpnt = tpnt;
+
+ switch (reloc_type) {
+ case R_MIPS_TLS_DTPMOD64:
+ case R_MIPS_TLS_DTPMOD32:
+ if (tls_tpnt)
+ *(ElfW(Word) *)reloc_addr = tls_tpnt->l_tls_modid;
+#ifdef __SUPPORT_LD_DEBUG__
+ _dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n",
+ symname, old_val, *((unsigned int *)reloc_addr));
+#endif
+ break;
+
+ case R_MIPS_TLS_DTPREL64:
+ case R_MIPS_TLS_DTPREL32:
+ *(ElfW(Word) *)reloc_addr +=
+ TLS_DTPREL_VALUE (symbol_addr);
+#ifdef __SUPPORT_LD_DEBUG__
+ _dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n",
+ symname, old_val, *((unsigned int *)reloc_addr));
+#endif
+ break;
+
+ case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
+ CHECK_STATIC_TLS((struct link_map *)tls_tpnt);
+ *(ElfW(Word) *)reloc_addr +=
+ TLS_TPREL_VALUE (tls_tpnt, symbol_addr);
+#ifdef __SUPPORT_LD_DEBUG__
+ _dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n",
+ symname, old_val, *((unsigned int *)reloc_addr));
+#endif
+ break;
+ }
+
+ break;
+ }
+#endif /* USE_TLS */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ case (R_MIPS_64 << 8) | R_MIPS_REL32:
+#else /* O32 || N32 */
+ case R_MIPS_REL32:
+#endif /* O32 || N32 */
+ if (symtab_index) {
+ if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])
+ *reloc_addr +=
+ symtab[symtab_index].st_value +
+ (unsigned long) tpnt->loadaddr;
+ else {
+ *reloc_addr += got[symtab_index + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX] -
+ tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]];
+ }
+ }
+ else {
+ *reloc_addr += (unsigned long) tpnt->loadaddr;
+ }
+ break;
+ case R_MIPS_JUMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_MIPS_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\n%s move %d bytes from %x to %x",
+ symname, symtab[symtab_index].st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ symtab[symtab_index].st_size);
+ }
+ break;
+ case R_MIPS_NONE:
+ break;
+ default:
+ {
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", symname);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname);
+#else
+ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname);
+#endif
+ _dl_exit(1);
+ }
+ }
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail && reloc_addr)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+/* Relocate the global GOT entries for the object */
+void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
+{
+ ElfW(Sym) *sym;
+ char *strtab;
+ unsigned long i, tmp_lazy;
+ unsigned long *got_entry;
+
+ for (; tpnt ; tpnt = tpnt->next) {
+
+ /* We don't touch the dynamic linker */
+ if (tpnt->libtype == program_interpreter)
+ continue;
+
+ /* Setup the loop variables */
+ got_entry = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT])
+ + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];
+ sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc)
+ _dl_dprintf(2, "_dl_perform_mips_global_got_relocations for '%s'\n", tpnt->libname);
+#endif
+ tmp_lazy = lazy && !tpnt->dynamic_info[DT_BIND_NOW];
+ /* Relocate the global GOT entries for the object */
+ while (i--) {
+ if (sym->st_shndx == SHN_UNDEF) {
+ if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value && tmp_lazy) {
+ *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr;
+ }
+ else {
+ *got_entry = (unsigned long) _dl_find_hash(strtab +
+ sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ }
+ }
+ else if (sym->st_shndx == SHN_COMMON) {
+ *got_entry = (unsigned long) _dl_find_hash(strtab +
+ sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ }
+ else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
+ *got_entry != sym->st_value && tmp_lazy) {
+ *got_entry += (unsigned long) tpnt->loadaddr;
+ }
+ else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) {
+ if (sym->st_other == 0)
+ *got_entry += (unsigned long) tpnt->loadaddr;
+ }
+ else {
+ struct symbol_ref sym_ref;
+ sym_ref.sym = sym;
+ sym_ref.tpnt = NULL;
+ *got_entry = (unsigned long) _dl_find_hash(strtab +
+ sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, &sym_ref);
+ }
+
+ got_entry++;
+ sym++;
+ }
+ }
+}
+
diff --git a/ap/build/uClibc/ldso/ldso/mips/resolve.S b/ap/build/uClibc/ldso/ldso/mips/resolve.S
new file mode 100644
index 0000000..d7951a1
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/mips/resolve.S
@@ -0,0 +1,165 @@
+/*
+ * Linux dynamic resolving code for MIPS. Fixes up the GOT entry as
+ * indicated in register t8 and jumps to the resolved address. Shamelessly
+ * ripped from 'sysdeps/mips/dl-machine.h' in glibc-2.2.5.
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License. See the file "COPYING.LIB" in the main directory of this
+ * archive for more details.
+ *
+ * Copyright (C) 1996-2001 Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>
+ * Copyright (C) 2002 Steven J. Hill <sjhill@realitydiluted.com>
+ *
+ */
+
+#include <sgidefs.h>
+.text
+.align 2
+.globl _dl_runtime_resolve
+.type _dl_runtime_resolve,@function
+.ent _dl_runtime_resolve
+_dl_runtime_resolve:
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+ .frame $29, 40, $31
+ .set noreorder
+
+ /* Save GP. */
+ move $3, $28
+
+ /* Save arguments and sp value on stack. */
+ subu $29, 40
+
+ /* Modify t9 ($25) so as to point .cpload instruction. */
+ addiu $25, 12
+
+ /* Compute GP. */
+ .set noreorder
+ .cpload $25
+ .set reorder
+
+ /* Save slot call pc. */
+ move $2, $31
+ .cprestore 32
+
+ /* Store function arguments from registers to stack */
+ sw $15, 36($29)
+ sw $4, 16($29)
+ sw $5, 20($29)
+ sw $6, 24($29)
+ sw $7, 28($29)
+
+ /* Setup functions args and call __dl_runtime_resolve */
+ move $4, $24
+ move $5, $3
+ jal __dl_runtime_resolve
+
+ /* Restore function arguments from stack to registers */
+ lw $31, 36($29)
+ lw $4, 16($29)
+ lw $5, 20($29)
+ lw $6, 24($29)
+ lw $7, 28($29)
+
+ /* Do a tail call to the original function */
+ addiu $29, 40
+#else /* N32 || N64 */
+ .set noreorder
+
+ /* Save GP. */
+ move $3, $28
+
+ /* Save arguments and sp value on stack. */
+ dsubu $29, 80
+
+ /* Compute GP. */
+ .set noreorder
+ .cpsetup $25, 0, _dl_runtime_resolve
+ .set reorder
+
+ /* Store function arguments from registers to stack */
+ sd $15, 72($29)
+ sd $4, 8($29)
+ sd $5, 16($29)
+ sd $6, 24($29)
+ sd $7, 32($29)
+ sd $8, 40($29)
+ sd $9, 48($29)
+ sd $10, 56($29)
+ sd $11, 64($29)
+
+ /* Setup functions args and call __dl_runtime_resolve */
+ move $4, $24
+ move $5, $3
+ jal __dl_runtime_resolve
+
+ /* Restore function arguments from stack to registers */
+ ld $31, 72($29)
+ ld $4, 8($29)
+ ld $5, 16($29)
+ ld $6, 24($29)
+ ld $7, 32($29)
+ ld $8, 40($29)
+ ld $9, 48($29)
+ ld $10, 56($29)
+ ld $11, 64($29)
+
+ /* Do a tail call to the original function */
+ .cpreturn
+ daddu $29, 80
+#endif /* N32 || N64 */
+ move $25, $2
+ jr $25
+.end _dl_runtime_resolve
+.previous
+
+/* Assembler veneer called from the PLT header code when using the
+ non-PIC ABI.
+
+ Code in each PLT entry puts the caller's return address into t7 ($15),
+ the PLT entry index into t8 ($24), the address of _dl_runtime_pltresolve
+ into t9 ($25) and the address of .got.plt into gp ($28). __dl_runtime_pltresolve
+ needs a0 ($4) to hold the link map and a1 ($5) to hold the index into
+ .rel.plt (== PLT entry index * 4). */
+
+ .text
+ .align 2
+ .globl _dl_runtime_pltresolve
+ .type _dl_runtime_pltresolve,@function
+ .ent _dl_runtime_pltresolve
+_dl_runtime_pltresolve:
+ .frame $29, 40, $31
+ .set noreorder
+ # Save arguments and sp value in stack.
+ subu $29, 40
+ lw $10, 4($28)
+ # Modify t9 ($25) so as to point .cpload instruction.
+ addiu $25, 12
+ # Compute GP.
+ .cpload $25
+ .set reorder
+
+ /* Store function arguments from registers to stack */
+ sw $15, 36($29)
+ sw $4, 16($29)
+ sw $5, 20($29)
+ sw $6, 24($29)
+ sw $7, 28($29)
+
+ /* Setup functions args and call __dl_runtime_pltresolve. */
+ move $4, $10
+ sll $5, $24, 3
+ jal __dl_runtime_pltresolve
+
+ /* Restore function arguments from stack to registers */
+ lw $31, 36($29)
+ lw $4, 16($29)
+ lw $5, 20($29)
+ lw $6, 24($29)
+ lw $7, 28($29)
+
+ /* Do a tail call to the original function */
+ addiu $29, 40
+ move $25, $2
+ jr $25
+ .end _dl_runtime_pltresolve
+ .previous
diff --git a/ap/build/uClibc/ldso/ldso/powerpc/dl-debug.h b/ap/build/uClibc/ldso/ldso/powerpc/dl-debug.h
new file mode 100644
index 0000000..720536e
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/powerpc/dl-debug.h
@@ -0,0 +1,44 @@
+/* vi: set sw=4 ts=4: */
+/* powerpc shared library loader suppport
+ *
+ * Copyright (C) 2001-2002 David A. Schleef
+ * Copyright (C) 2003-2004 Erik Andersen
+ * Copyright (C) 2004 Joakim Tjernlund
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+ { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16",
+ "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA",
+ "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN",
+ "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN",
+ "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO",
+ "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24",
+ "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE",
+ "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32",
+ "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI",
+ "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF",
+ "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA",
+};
diff --git a/ap/build/uClibc/ldso/ldso/powerpc/dl-startup.h b/ap/build/uClibc/ldso/ldso/powerpc/dl-startup.h
new file mode 100644
index 0000000..d7b5548
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/powerpc/dl-startup.h
@@ -0,0 +1,89 @@
+/* Any assembly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture.
+ * Copyright (C) 2005 by Joakim Tjernlund
+ */
+
+__asm__(
+ " .text\n"
+ " .globl _start\n"
+ " .type _start,@function\n"
+ "_start:\n"
+ " mr 3,1\n" /* Pass SP to _dl_start in r3 */
+ " li 0,0\n"
+ " stwu 1,-16(1)\n" /* Make room on stack for _dl_start to store LR */
+ " stw 0,0(1)\n" /* Clear Stack frame */
+ " bl _dl_start@local\n" /* Perform relocation */
+ /* Save the address of the apps entry point in CTR register */
+ " mtctr 3\n" /* application entry point */
+#ifdef HAVE_ASM_PPC_REL16
+ " bcl 20,31,1f\n"
+ "1: mflr 31\n"
+ " addis 31,31,_GLOBAL_OFFSET_TABLE_-1b@ha\n"
+ " addi 31,31,_GLOBAL_OFFSET_TABLE_-1b@l\n"
+#else
+ " bl _GLOBAL_OFFSET_TABLE_-4@local\n" /* Put our GOT pointer in r31, */
+ " mflr 31\n"
+#endif
+ " addi 1,1,16\n" /* Restore SP */
+ " lwz 7,_dl_skip_args@got(31)\n" /* load EA of _dl_skip_args */
+ " lwz 7,0(7)\n" /* Load word from _dl_skip_args */
+ " lwz 8,0(1)\n" /* Load argc from stack */
+ " subf 8,7,8\n" /* Subtract _dl_skip_args from argc. */
+ " slwi 7,7,2\n" /* Multiply by 4 */
+ " stwux 8,1,7\n" /* Adjust the stack pointer to skip _dl_skip_args words and store adjusted argc on stack. */
+#if 0
+ /* Try beeing SVR4 ABI compliant?, even though it is not needed for uClibc on Linux */
+ /* argc */
+ " lwz 3,0(1)\n"
+ /* find argv one word offset from the stack pointer */
+ " addi 4,1,4\n"
+ /* find environment pointer (argv+argc+1) */
+ " lwz 5,0(1)\n"
+ " addi 5,5,1\n"
+ " rlwinm 5,5,2,0,29\n"
+ " add 5,5,4\n"
+ /* pass the auxilary vector in r6. This is passed to us just after _envp. */
+ "2: lwzu 0,4(6)\n"
+ " cmpwi 0,0\n"
+ " bne 2b\n"
+ " addi 6,6,4\n"
+#endif
+ /* Pass a termination function pointer (in this case _dl_fini) in r3. */
+ /* Paulus promized he would keep r3 zero in the exec ABI. */
+ " lwz 3,_dl_fini@got(31)\n"
+ " mr 7,3\n" /* Pass _dl_fini in r7 to maintain compat */
+ " bctr\n" /* Jump to entry point */
+ " .size _start,.-_start\n"
+ " .previous\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ {int type=ELF_R_TYPE((RELP)->r_info); \
+ Elf32_Addr finaladdr=(SYMBOL)+(RELP)->r_addend;\
+ if (type==R_PPC_RELATIVE) { \
+ *REL=(Elf32_Word)(LOAD)+(RELP)->r_addend;\
+ } else if (type==R_PPC_ADDR32 || type==R_PPC_GLOB_DAT) {\
+ *REL=finaladdr; \
+ } else if (type==R_PPC_JMP_SLOT) { \
+ Elf32_Sword delta=finaladdr-(Elf32_Word)(REL);\
+ *REL=OPCODE_B(delta); \
+ PPC_DCBST(REL); PPC_SYNC; PPC_ICBI(REL);\
+ } else { \
+ _dl_exit(100+ELF_R_TYPE((RELP)->r_info));\
+ } \
+ }
diff --git a/ap/build/uClibc/ldso/ldso/powerpc/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/powerpc/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/powerpc/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/powerpc/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/powerpc/dl-sysdep.h
new file mode 100644
index 0000000..a665d4e
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/powerpc/dl-sysdep.h
@@ -0,0 +1,184 @@
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA
+#include <elf.h>
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+
+/* Stuff for the PLT. */
+#define PLT_INITIAL_ENTRY_WORDS 18
+#define PLT_LONGBRANCH_ENTRY_WORDS 0
+#define PLT_TRAMPOLINE_ENTRY_WORDS 6
+#define PLT_DOUBLE_SIZE (1<<13)
+#define PLT_ENTRY_START_WORDS(entry_number) \
+ (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2 \
+ + ((entry_number) > PLT_DOUBLE_SIZE \
+ ? ((entry_number) - PLT_DOUBLE_SIZE)*2 \
+ : 0))
+#define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries)
+
+/* Macros to build PowerPC opcode words. */
+#define OPCODE_ADDI(rd,ra,simm) \
+ (0x38000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff))
+#define OPCODE_ADDIS(rd,ra,simm) \
+ (0x3c000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff))
+#define OPCODE_ADD(rd,ra,rb) \
+ (0x7c000214 | (rd) << 21 | (ra) << 16 | (rb) << 11)
+#define OPCODE_B(target) (0x48000000 | ((target) & 0x03fffffc))
+#define OPCODE_BA(target) (0x48000002 | ((target) & 0x03fffffc))
+#define OPCODE_BCTR() 0x4e800420
+#define OPCODE_LWZ(rd,d,ra) \
+ (0x80000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff))
+#define OPCODE_LWZU(rd,d,ra) \
+ (0x84000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff))
+#define OPCODE_MTCTR(rd) (0x7C0903A6 | (rd) << 21)
+#define OPCODE_RLWINM(ra,rs,sh,mb,me) \
+ (0x54000000 | (rs) << 21 | (ra) << 16 | (sh) << 11 | (mb) << 6 | (me) << 1)
+
+#define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm)
+#define OPCODE_ADDIS_HI(rd,ra,value) \
+ OPCODE_ADDIS(rd,ra,((value) + 0x8000) >> 16)
+#define OPCODE_LIS_HI(rd,value) OPCODE_ADDIS_HI(rd,0,value)
+#define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh)
+
+
+#define PPC_DCBST(where) __asm__ __volatile__ ("dcbst 0,%0" : : "r"(where) : "memory")
+#define PPC_SYNC __asm__ __volatile__ ("sync" : : : "memory")
+#define PPC_ISYNC __asm__ __volatile__ ("sync; isync" : : : "memory")
+#define PPC_ICBI(where) __asm__ __volatile__ ("icbi 0,%0" : : "r"(where) : "memory")
+#define PPC_DIE __asm__ __volatile__ ("tweq 0,0")
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_PPC
+#undef MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "powerpc"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ PLT entries should not be allowed to define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+/* We never want to use a PLT entry as the destination of a
+ reloc, when what is being relocated is a branch. This is
+ partly for efficiency, but mostly so we avoid loops. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_PPC_JMP_SLOT \
+ || (type) == R_PPC_REL24 \
+ || ((type) >= R_PPC_DTPMOD32 /* contiguous TLS */ \
+ && (type) <= R_PPC_DTPREL32) \
+ || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* The SVR4 ABI specifies that the JMPREL relocs must be inside the
+ DT_RELA table. */
+#define ELF_MACHINE_PLTREL_OVERLAP 1
+
+/* Return the value of the GOT pointer. */
+static __always_inline Elf32_Addr * __attribute__ ((const))
+ppc_got (void)
+{
+ Elf32_Addr *got;
+#ifdef HAVE_ASM_PPC_REL16
+ __asm__ (" bcl 20,31,1f\n"
+ "1:mflr %0\n"
+ " addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n"
+ " addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n"
+ : "=b" (got) : : "lr");
+#else
+ __asm__ (" bl _GLOBAL_OFFSET_TABLE_-4@local"
+ : "=l" (got));
+#endif
+ return got;
+}
+
+/* Return the link-time address of _DYNAMIC, stored as
+ the first value in the GOT. */
+static __always_inline Elf32_Addr __attribute__ ((const))
+elf_machine_dynamic (void)
+{
+ return *ppc_got();
+}
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr __attribute__ ((const))
+elf_machine_load_address (void)
+{
+ Elf32_Addr *branchaddr;
+ Elf32_Addr runtime_dynamic;
+
+ /* This is much harder than you'd expect. Possibly I'm missing something.
+ The 'obvious' way:
+
+ Apparently, "bcl 20,31,$+4" is what should be used to load LR
+ with the address of the next instruction.
+ I think this is so that machines that do bl/blr pairing don't
+ get confused.
+
+ __asm__ ("bcl 20,31,0f ;"
+ "0: mflr 0 ;"
+ "lis %0,0b@ha;"
+ "addi %0,%0,0b@l;"
+ "subf %0,%0,0"
+ : "=b" (addr) : : "r0", "lr");
+
+ doesn't work, because the linker doesn't have to (and in fact doesn't)
+ update the @ha and @l references; the loader (which runs after this
+ code) will do that.
+
+ Instead, we use the following trick:
+
+ The linker puts the _link-time_ address of _DYNAMIC at the first
+ word in the GOT. We could branch to that address, if we wanted,
+ by using an @local reloc; the linker works this out, so it's safe
+ to use now. We can't, of course, actually branch there, because
+ we'd cause an illegal instruction exception; so we need to compute
+ the address ourselves. That gives us the following code: */
+
+ /* Get address of the 'b _DYNAMIC@local'... */
+ __asm__ ("bcl 20,31,0f;"
+ "b _DYNAMIC@local;"
+ "0:"
+ : "=l"(branchaddr));
+
+ /* So now work out the difference between where the branch actually points,
+ and the offset of that location in memory from the start of the file. */
+ runtime_dynamic = ((Elf32_Addr) branchaddr
+ + ((Elf32_Sword) (*branchaddr << 6 & 0xffffff00) >> 6));
+
+ return runtime_dynamic - elf_machine_dynamic ();
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela * rpnt = (void *)rel_addr;
+ --rpnt;
+ do { /* PowerPC handles pre increment/decrement better */
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
+
+#define ARCH_NUM 1
+#define DT_PPC_GOT_IDX (DT_NUM + OS_NUM)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+do { \
+if (dpnt->d_tag == DT_PPC_GOT) \
+ dynamic[DT_PPC_GOT_IDX] = dpnt->d_un.d_ptr; \
+} while (0)
diff --git a/ap/build/uClibc/ldso/ldso/powerpc/elfinterp.c b/ap/build/uClibc/ldso/ldso/powerpc/elfinterp.c
new file mode 100644
index 0000000..fe7afe5
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/powerpc/elfinterp.c
@@ -0,0 +1,452 @@
+/* vi: set sw=4 ts=4: */
+/* powerpc shared library loader suppport
+ *
+ * Copyright (C) 2001-2002 David A. Schleef
+ * Copyright (C) 2003-2004 Erik Andersen
+ * Copyright (C) 2004 Joakim Tjernlund
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+#define TLS_DTV_OFFSET 0x8000
+#define TLS_TP_OFFSET 0x7000
+
+extern int _dl_linux_resolve(void);
+
+void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
+{
+ Elf32_Word *tramp;
+ Elf32_Word num_plt_entries;
+ Elf32_Word data_words;
+ Elf32_Word rel_offset_words;
+ Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve;
+
+ if (tpnt->dynamic_info[DT_JMPREL] == 0)
+ return;
+ if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) {
+ tpnt->dynamic_info[DT_PPC_GOT_IDX] += tpnt->loadaddr;
+ return;
+ }
+ num_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
+ rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries);
+ data_words = (Elf32_Word) (plt + rel_offset_words);
+ tpnt->data_words = data_words;
+
+ plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
+ plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
+
+ plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
+ plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
+
+ /* [4] */
+ /* [5] */
+ tramp = (Elf32_Word *) (plt + PLT_TRAMPOLINE_ENTRY_WORDS);
+
+ /* For the long entries, subtract off data_words. */
+ tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
+ tramp[1] = OPCODE_ADDI(11,11,-data_words);
+
+ /* Multiply index of entry by 3 (in r11). */
+ tramp[2] = OPCODE_SLWI(12,11,1);
+ tramp[3] = OPCODE_ADD(11,12,11);
+ if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000) {
+ /* Load address of link map in r12. */
+ tramp[4] = OPCODE_LI (12, (Elf32_Word) tpnt);
+ tramp[5] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) tpnt);
+
+ /* Call _dl_linux_resolve . */
+ tramp[6] = OPCODE_BA (dlrr);
+ } else {
+ /* Get address of _dl_linux_resolve in CTR. */
+ tramp[4] = OPCODE_LI(12,dlrr);
+ tramp[5] = OPCODE_ADDIS_HI(12,12,dlrr);
+ tramp[6] = OPCODE_MTCTR(12);
+
+ /* Load address of link map in r12. */
+ tramp[7] = OPCODE_LI(12,(Elf32_Word) tpnt);
+ tramp[8] = OPCODE_ADDIS_HI(12,12,(Elf32_Word) tpnt);
+
+ /* Call _dl_linux_resolve. */
+ tramp[9] = OPCODE_BCTR();
+ }
+ /* [16] unused */
+ /* [17] unused */
+
+ PPC_DCBST(plt);
+ PPC_DCBST(plt+4);
+ PPC_DCBST(plt+8);
+ PPC_DCBST(plt+12);
+ PPC_DCBST(plt+16-1);
+ PPC_SYNC;
+ PPC_ICBI(plt);
+ PPC_ICBI(plt+16-1);
+ PPC_ISYNC;
+}
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rel_addr;
+ int symtab_index;
+ char *symname;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) finaladdr;
+ Elf32_Sword delta;
+
+ rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (void *)rel_addr + reloc_entry;
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,this_reloc);
+
+ /* Address of dump instruction to fix up */
+ reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + this_reloc->r_offset);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, (ElfW(Addr))reloc_addr);
+#endif
+
+ /* Get the address of the GOT entry */
+ finaladdr = (ElfW(Addr)) _dl_find_hash(symname,
+ &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!finaladdr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+ finaladdr += this_reloc->r_addend;
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "%x\n", finaladdr);
+#endif
+ if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) {
+ *reloc_addr = finaladdr;
+ } else {
+ delta = finaladdr - (Elf32_Word)reloc_addr;
+ if (delta<<6>>6 == delta) {
+ *reloc_addr = OPCODE_B(delta);
+ } else if (finaladdr <= 0x01fffffc) {
+ *reloc_addr = OPCODE_BA (finaladdr);
+ } else {
+ /* Warning: we don't handle double-sized PLT entries */
+ Elf32_Word *plt, *data_words, idx, offset;
+
+ plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT];
+ offset = reloc_addr - plt;
+ idx = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
+ data_words = (Elf32_Word *)tpnt->data_words;
+ reloc_addr += 1;
+
+ data_words[idx] = finaladdr;
+ PPC_SYNC;
+ *reloc_addr = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4);
+ }
+
+ /* instructions were modified */
+ PPC_DCBST(reloc_addr);
+ PPC_SYNC;
+ PPC_ICBI(reloc_addr);
+ PPC_ISYNC;
+ }
+ return finaladdr;
+}
+
+static __inline__ int
+_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) finaladdr;
+ struct elf_resolve *tls_tpnt = NULL;
+ unsigned long symbol_addr;
+ char *symname;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ symbol_addr = tpnt->loadaddr; /* For R_PPC_RELATIVE */
+ reloc_addr = (ElfW(Addr) *)(intptr_t) (symbol_addr + (unsigned long) rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + sym_ref.sym->st_name;
+ if (symtab_index) {
+ symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ /* We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+ if (unlikely(!symbol_addr
+ && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS
+ && ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)))
+ return 1;
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ tls_tpnt = sym_ref.tpnt;
+ } else {
+ symbol_addr = sym_ref.sym->st_value;
+ tls_tpnt = tpnt;
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+ finaladdr = (ElfW(Addr)) (symbol_addr + rpnt->r_addend);
+
+ switch (reloc_type) {
+ case R_PPC_RELATIVE:
+ case R_PPC_ADDR32:
+ case R_PPC_GLOB_DAT:
+ *reloc_addr = finaladdr;
+ goto out_nocode; /* No code code modified */
+ case R_PPC_JMP_SLOT:
+ {
+ if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) {
+ *reloc_addr = finaladdr;
+ goto out_nocode; /* No code code modified */
+ } else {
+ Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
+ if (delta<<6>>6 == delta) {
+ *reloc_addr = OPCODE_B(delta);
+ } else if (finaladdr <= 0x01fffffc) {
+ *reloc_addr = OPCODE_BA (finaladdr);
+ } else {
+ /* Warning: we don't handle double-sized PLT entries */
+ Elf32_Word *plt, *data_words, idx, offset;
+
+ plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT];
+ offset = reloc_addr - plt;
+ idx = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
+ data_words = (Elf32_Word *)tpnt->data_words;
+
+ data_words[idx] = finaladdr;
+ reloc_addr[0] = OPCODE_LI(11,idx*4);
+ reloc_addr[1] = OPCODE_B((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4);
+
+ /* instructions were modified */
+ PPC_DCBST(reloc_addr+1);
+ PPC_SYNC;
+ PPC_ICBI(reloc_addr+1);
+ }
+ }
+ break;
+ }
+ case R_PPC_COPY:
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
+ symname, sym_ref.sym->st_size,
+ symbol_addr, reloc_addr);
+#endif
+ _dl_memcpy((char *) reloc_addr, (char *) finaladdr, sym_ref.sym->st_size);
+ goto out_nocode; /* No code code modified */
+ case R_PPC_ADDR16_HA:
+ finaladdr += 0x8000; /* fall through. */
+ case R_PPC_ADDR16_HI:
+ finaladdr >>= 16; /* fall through. */
+ case R_PPC_ADDR16_LO:
+ *(short *)reloc_addr = finaladdr;
+ break;
+#if USE_TLS
+ case R_PPC_DTPMOD32:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_PPC_DTPREL32:
+ /* During relocation all TLS symbols are defined and used.
+ Therefore the offset is already correct. */
+ *reloc_addr = finaladdr - TLS_DTV_OFFSET;
+ break;
+ case R_PPC_TPREL32:
+ *reloc_addr = tls_tpnt->l_tls_offset + finaladdr - TLS_TP_OFFSET;
+ break;
+#endif
+ case R_PPC_REL24:
+#if 0
+ {
+ Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
+ if (unlikely(delta<<6>>6 != delta)) {
+ _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\t"
+ "Compile shared libraries with -fPIC!\n",
+ _dl_progname, symname);
+ _dl_exit(1);
+ }
+ *reloc_addr = (*reloc_addr & 0xfc000003) | (delta & 0x3fffffc);
+ break;
+ }
+#else
+ _dl_dprintf(2,"R_PPC_REL24: Compile shared libraries with -fPIC!\n");
+ return -1;
+#endif
+ case R_PPC_NONE:
+ goto out_nocode; /* No code code modified */
+ default:
+ _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "%s ", _dl_reltypes(reloc_type));
+#endif
+ if (symtab_index)
+ _dl_dprintf(2, "'%s'\n", symname);
+ return -1;
+ }
+
+ /* instructions were modified */
+ PPC_DCBST(reloc_addr);
+ PPC_SYNC;
+ PPC_ICBI(reloc_addr);
+ PPC_ISYNC;
+ out_nocode:
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr);
+#endif
+ return 0;
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ struct elf_resolve *tpnt = rpnt->dyn;
+ Elf32_Word *plt, offset, i, num_plt_entries, rel_offset_words;
+
+ num_plt_entries = rel_size / sizeof(ELF_RELOC);
+ plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT];
+ if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) {
+ /* Secure PLT */
+ ElfW(Addr) *got = (ElfW(Addr) *)tpnt->dynamic_info[DT_PPC_GOT_IDX];
+ Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve;
+
+ got[1] = (ElfW(Addr)) dlrr;
+ got[2] = (ElfW(Addr)) tpnt;
+
+ /* Relocate everything in .plt by the load address offset. */
+ while (num_plt_entries-- != 0)
+ *plt++ += tpnt->loadaddr;
+ return;
+ }
+
+ rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries);
+
+ /* Set up the lazy PLT entries. */
+ offset = PLT_INITIAL_ENTRY_WORDS;
+ i = 0;
+ /* Warning: we don't handle double-sized PLT entries */
+ while (i < num_plt_entries) {
+ plt[offset ] = OPCODE_LI(11, i * 4);
+ plt[offset+1] = OPCODE_B((PLT_TRAMPOLINE_ENTRY_WORDS + 2 - (offset+1)) * 4);
+ i++;
+ offset += 2;
+ }
+ /* Now, we've modified code. We need to write the changes from
+ the data cache to a second-level unified cache, then make
+ sure that stale data in the instruction cache is removed.
+ (In a multiprocessor system, the effect is more complex.)
+ Most of the PLT shouldn't be in the instruction cache, but
+ there may be a little overlap at the start and the end.
+
+ Assumes that dcbst and icbi apply to lines of 16 bytes or
+ more. Current known line sizes are 16, 32, and 128 bytes. */
+ for (i = 0; i < rel_offset_words; i += 4)
+ PPC_DCBST (plt + i);
+ PPC_DCBST (plt + rel_offset_words - 1);
+ PPC_SYNC;
+ PPC_ICBI (plt);
+ PPC_ICBI (plt + rel_offset_words - 1);
+ PPC_ISYNC;
+}
+
+static __inline__ int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res==0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res <0))
+ {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname);
+#else
+ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname);
+#endif
+ return res;
+ }
+ if (unlikely(res >0))
+ {
+ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ return res;
+ }
+ }
+ return 0;
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/powerpc/resolve.S b/ap/build/uClibc/ldso/ldso/powerpc/resolve.S
new file mode 100644
index 0000000..c83337c
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/powerpc/resolve.S
@@ -0,0 +1,57 @@
+/*
+ * Stolen from glibc-2.2.2 by David Schleef <ds@schleef.org>
+ */
+
+.text
+.align 4
+
+.globl _dl_linux_resolver
+
+.globl _dl_linux_resolve
+.type _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+/* We need to save the registers used to pass parameters, and register 0,
+ which is used by _mcount; the registers are saved in a stack frame. */
+ stwu 1,-64(1)
+ stw 0,12(1)
+ stw 3,16(1)
+ stw 4,20(1)
+/* The code that calls this has put parameters for 'fixup' in r12 and r11. */
+ mr 3,12
+ stw 5,24(1)
+ mr 4,11
+ stw 6,28(1)
+ mflr 0
+/* We also need to save some of the condition register fields. */
+ stw 7,32(1)
+ stw 0,48(1)
+ stw 8,36(1)
+ mfcr 0
+ stw 9,40(1)
+ stw 10,44(1)
+ stw 0,8(1)
+ bl _dl_linux_resolver@local
+/* 'fixup' returns the address we want to branch to. */
+ mtctr 3
+/* Put the registers back... */
+ lwz 0,48(1)
+ lwz 10,44(1)
+ lwz 9,40(1)
+ mtlr 0
+ lwz 8,36(1)
+ lwz 0,8(1)
+ lwz 7,32(1)
+ lwz 6,28(1)
+ mtcrf 0xFF,0
+ lwz 5,24(1)
+ lwz 4,20(1)
+ lwz 3,16(1)
+ lwz 0,12(1)
+/* ...unwind the stack frame, and jump to the PLT entry we updated. */
+ addi 1,1,64
+ bctr
+
+.LFE2:
+ .size _dl_linux_resolve,.LFE2-_dl_linux_resolve
+
diff --git a/ap/build/uClibc/ldso/ldso/sh/dl-debug.h b/ap/build/uClibc/ldso/ldso/sh/dl-debug.h
new file mode 100644
index 0000000..ac442bf
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh/dl-debug.h
@@ -0,0 +1,43 @@
+/* vi: set sw=4 ts=4: */
+/* SuperH ELF shared library loader suppport
+ *
+ * Copyright (C) 2002, Stefan Allius <allius@atecom.com> and
+ * Eddie C. Dost <ecd@atecom.com>
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ [0] "R_SH_NONE", "R_SH_DIR32", "R_SH_REL32", "R_SH_DIR8WPN",
+ [4] "R_SH_IND12W", "R_SH_DIR8WPL", "R_SH_DIR8WPZ", "R_SH_DIR8BP",
+ [8] "R_SH_DIR8W", "R_SH_DIR8L",
+ [25] "R_SH_SWITCH16","R_SH_SWITCH32","R_SH_USES",
+ [28] "R_SH_COUNT", "R_SH_ALIGN", "R_SH_CODE", "R_SH_DATA",
+ [32] "R_SH_LABEL", "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT","R_SH_GNU_VTENTRY",
+[144] "R_SH_TLS_GD_32","R_SH_TLS_LD_32", "R_SH_TLS_LDO_32", "R_SH_TLS_IE_32",
+[148] "R_SH_TLS_LE_32","R_SH_TLS_DTPMOD32", "R_SH_TLS_DTPOFF32", "R_SH_TLS_TPOFF32",
+[160] "R_SH_GOT32", "R_SH_PLT32", "R_SH_COPY", "R_SH_GLOB_DAT",
+[164] "R_SH_JMP_SLOT","R_SH_RELATIVE","R_SH_GOTOFF", "R_SH_GOTPC",
+};
diff --git a/ap/build/uClibc/ldso/ldso/sh/dl-startup.h b/ap/build/uClibc/ldso/ldso/sh/dl-startup.h
new file mode 100644
index 0000000..2f91d0f
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh/dl-startup.h
@@ -0,0 +1,68 @@
+/* Any assembly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture. */
+
+__asm__(
+ " .text\n"
+ " .globl _start\n"
+ " .type _start,@function\n"
+ "_start:\n"
+ " mov r15, r4\n"
+ " mov.l .L_dl_start, r0\n"
+ " bsrf r0\n"
+ " add #4, r4\n"
+ ".jmp_loc:\n"
+ " mov r0, r8 ! Save the user entry point address in r8\n"
+ " mov.l .L_got, r12 ! Load the GOT on r12\n"
+ " mova .L_got, r0\n"
+ " add r0, r12\n"
+ " mov.l .L_dl_fini, r0\n"
+ " mov.l @(r0,r12), r4 ! Pass the finalizer in r4\n"
+ " jmp @r8\n"
+ " nop\n"
+ ".L_dl_start:\n"
+ " .long _dl_start-.jmp_loc\n"
+ ".L_dl_fini:\n"
+ " .long _dl_fini@GOT\n"
+ ".L_got:\n"
+ " .long _GLOBAL_OFFSET_TABLE_\n"
+ " .size _start,.-_start\n"
+ " .previous\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS)
+
+/* We can't call functions earlier in the dl startup process */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF_R_TYPE((RELP)->r_info)){ \
+ case R_SH_REL32: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend \
+ - (unsigned long)(REL); \
+ break; \
+ case R_SH_DIR32: \
+ case R_SH_GLOB_DAT: \
+ case R_SH_JMP_SLOT: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ case R_SH_RELATIVE: \
+ *(REL) = (LOAD) + (RELP)->r_addend; \
+ break; \
+ case R_SH_NONE: \
+ break; \
+ default: \
+ _dl_exit(1); \
+ }
diff --git a/ap/build/uClibc/ldso/ldso/sh/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/sh/dl-syscalls.h
new file mode 100644
index 0000000..f9f13c7
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh/dl-syscalls.h
@@ -0,0 +1,7 @@
+#if __GNUC_PREREQ (4, 1)
+#warning !!! gcc 4.1 and later have problems with __always_inline so redefined as inline
+# ifdef __always_inline
+# undef __always_inline
+# define __always_inline __inline__
+# endif
+#endif
diff --git a/ap/build/uClibc/ldso/ldso/sh/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/sh/dl-sysdep.h
new file mode 100644
index 0000000..21244ec
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh/dl-sysdep.h
@@ -0,0 +1,171 @@
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+#include <elf.h>
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) (MODULE); \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_SH
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "sh"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+static __always_inline unsigned int
+_dl_urem(unsigned int n, unsigned int base)
+{
+ int res;
+
+ __asm__ (""\
+ "mov #0, r0\n\t" \
+ "div0u\n\t" \
+ "" \
+ "! get one bit from the msb of the numerator into the T\n\t" \
+ "! bit and divide it by whats in %2. Put the answer bit\n\t" \
+ "! into the T bit so it can come out again at the bottom\n\t" \
+ "" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1 ; div1 %2, r0\n\t" \
+ "rotcl %1\n\t"
+ : "=r" (res)
+ : "0" (n), "r" (base)
+ : "r0","cc");
+
+ return n - (base * res);
+}
+
+#define do_rem(result, n, base) ((result) = _dl_urem((n), (base)))
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references should not be allowed to
+ define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+# define elf_machine_type_class(type) \
+ ((((type) == R_SH_JMP_SLOT || (type) == R_SH_TLS_DTPMOD32 \
+ || (type) == R_SH_TLS_DTPOFF32 || (type) == R_SH_TLS_TPOFF32) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf32_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ register Elf32_Addr *got;
+ __asm__ ("mov r12,%0" :"=r" (got));
+ return *got;
+}
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+ Elf32_Addr addr;
+ __asm__ ("mov.l 1f,r0\n\
+ mov.l 3f,r2\n\
+ add r12,r2\n\
+ mov.l @(r0,r12),r0\n\
+ bra 2f\n\
+ sub r0,r2\n\
+ .align 2\n\
+ 1: .long _dl_start@GOT\n\
+ 3: .long _dl_start@GOTOFF\n\
+ 2: mov r2,%0"
+ : "=r" (addr) : : "r0", "r1", "r2");
+ return addr;
+}
+
+#define COPY_UNALIGNED_WORD(swp, twp, align) \
+ { \
+ void *__s = (swp), *__t = (twp); \
+ unsigned char *__s1 = __s, *__t1 = __t; \
+ unsigned short *__s2 = __s, *__t2 = __t; \
+ unsigned long *__s4 = __s, *__t4 = __t; \
+ switch ((align)) \
+ { \
+ case 0: \
+ *__t4 = *__s4; \
+ break; \
+ case 2: \
+ *__t2++ = *__s2++; \
+ *__t2 = *__s2; \
+ break; \
+ default: \
+ *__t1++ = *__s1++; \
+ *__t1++ = *__s1++; \
+ *__t1++ = *__s1++; \
+ *__t1 = *__s1; \
+ break; \
+ } \
+ }
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Addr value;
+ Elf32_Rela * rpnt = (void *)rel_addr;
+
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + rpnt->r_offset);
+
+ if (rpnt->r_addend)
+ value = load_off + rpnt->r_addend;
+ else {
+ COPY_UNALIGNED_WORD (reloc_addr, &value, (int) reloc_addr & 3);
+ value += load_off;
+ }
+ COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3);
+ rpnt++;
+ } while (--relative_count);
+#undef COPY_UNALIGNED_WORD
+}
diff --git a/ap/build/uClibc/ldso/ldso/sh/elfinterp.c b/ap/build/uClibc/ldso/ldso/sh/elfinterp.c
new file mode 100644
index 0000000..14082ba
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh/elfinterp.c
@@ -0,0 +1,307 @@
+/* vi: set sw=4 ts=4: */
+/* SuperH ELF shared library loader suppport
+ *
+ * Copyright (C) 2002, Stefan Allius <allius@atecom.com> and
+ * Eddie C. Dost <ecd@atecom.com>
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+#include "ldso.h"
+
+extern int _dl_linux_resolve(void);
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)(intptr_t) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of jump instruction to fix up */
+ instr_addr = (unsigned long) (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **) instr_addr;
+
+ /* Get the address of the GOT entry */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long) got_addr < 0x20000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+ "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups)
+ *got_addr = new_addr;
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long) new_addr;
+}
+
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+ /* Now parse the relocation information */
+
+ rpnt = (ELF_RELOC *)(intptr_t) rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0) continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ }
+ if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+ return 0;
+}
+
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+
+ struct elf_resolve *tls_tpnt = NULL;
+ struct symbol_ref sym_ref;
+
+ reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+
+ if (symtab_index) {
+ symname = strtab + symtab[symtab_index].st_name;
+ symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+
+ if (!symbol_addr
+ && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+ && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+
+ /* Let the caller to handle the error: it may be non fatal if called from dlopen */
+ return 1;
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ tls_tpnt = sym_ref.tpnt;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+#if defined USE_TLS && USE_TLS
+ /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous'
+ symbol. This is the case for a static tls variable, so the lookup
+ module is just that one is referencing the tls variable. */
+ if (!tls_tpnt)
+ tls_tpnt = tpnt;
+#endif
+ switch (reloc_type) {
+ case R_SH_NONE:
+ break;
+ case R_SH_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
+ symname, symtab[symtab_index].st_size,
+ symbol_addr, reloc_addr);
+#endif
+ _dl_memcpy((char *) reloc_addr, (char *) symbol_addr, symtab[symtab_index].st_size);
+ }
+ return 0; /* no further LD_DEBUG messages for copy relocs */
+ case R_SH_DIR32:
+ case R_SH_GLOB_DAT:
+ case R_SH_JMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_SH_REL32:
+ *reloc_addr = symbol_addr + rpnt->r_addend -
+ (unsigned long) reloc_addr;
+ break;
+ case R_SH_RELATIVE:
+ *reloc_addr = (unsigned long) tpnt->loadaddr + rpnt->r_addend;
+ break;
+#if defined USE_TLS && USE_TLS
+ case R_SH_TLS_DTPMOD32:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_SH_TLS_DTPOFF32:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_SH_TLS_TPOFF32:
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend;
+ break;
+#endif
+ default:
+
+ return -1;
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ unsigned long *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ unsigned long old_val;
+#endif
+ (void)scope;
+ (void)symtab;
+ (void)strtab;
+
+ reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+ switch (reloc_type) {
+ case R_SH_NONE:
+ break;
+ case R_SH_JMP_SLOT:
+ *reloc_addr += (unsigned long) tpnt->loadaddr;
+ break;
+ default:
+ return -1;
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr);
+#endif
+ return 0;
+
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/sh/resolve.S b/ap/build/uClibc/ldso/ldso/sh/resolve.S
new file mode 100644
index 0000000..e66d316
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh/resolve.S
@@ -0,0 +1,98 @@
+/*
+ * Stolen from glibc-2.2.2 by Eddie C. Dost <ecd@atecom.com>
+ */
+
+ .text
+ .globl _dl_linux_resolver
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve, @function
+ .balign 16
+_dl_linux_resolve:
+ mov.l r2, @-r15 ! see Note2 below
+ mov.l r3, @-r15
+ mov.l r4, @-r15
+ mov.l r5, @-r15
+ mov.l r6, @-r15
+ mov.l r7, @-r15
+ mov.l r12, @-r15
+ movt r3 ! Save T flag
+ mov.l r3, @-r15
+
+#ifdef HAVE_FPU
+ sts.l fpscr, @-r15
+ mov #8,r3
+ swap.w r3, r3
+ lds r3, fpscr
+ fmov.s fr11, @-r15
+ fmov.s fr10, @-r15
+ fmov.s fr9, @-r15
+ fmov.s fr8, @-r15
+ fmov.s fr7, @-r15
+ fmov.s fr6, @-r15
+ fmov.s fr5, @-r15
+ fmov.s fr4, @-r15
+#endif
+ sts.l pr, @-r15
+/* Note - The PLT entries have been "optimised" not to use r2. r2 is used by
+ GCC to return the address of large structures, so it should not be
+ corrupted here. This does mean however, that those PLTs does not conform
+ to the SH PIC ABI. That spec says that r0 contains the type of the PLT
+ and r2 contains the GOT id. The GNU Plt version stores the GOT id in r0 and
+ ignores the type. We can easily detect this difference however,
+ since the type will always be 0 or 8, and the GOT ids will always be
+ greater than or equal to 12.
+
+ Found in binutils/bfd/elf32-sh.c by Stefan Allius <allius@atecom.com>
+
+ Note2 - we also have to preserve r2 on the stack as the call into
+ C code (_dl_linux_resolver) will use r2 as a scratch register and we
+ need it for the address for returning structures,
+ David McCullough <davidm@snapgear.com>.
+ */
+ mov #8 ,r5
+ cmp/gt r5, r0
+ bt 1f
+ mov r2, r0 ! link map address in r2 (SH PIC ABI)
+1:
+ mov r0, r4 ! link map address in r0 (GNUs PLT)
+ mova .LG, r0
+ mov.l .LG, r5
+ add r5, r0
+ mov.l 3f, r5
+ mov.l @(r0, r5),r5
+ jsr @r5
+ mov r1, r5 ! Reloc offset
+
+ lds.l @r15+, pr ! Get register content back
+
+#ifdef HAVE_FPU
+ fmov.s @r15+, fr4
+ fmov.s @r15+, fr5
+ fmov.s @r15+, fr6
+ fmov.s @r15+, fr7
+ fmov.s @r15+, fr8
+ fmov.s @r15+, fr9
+ fmov.s @r15+, fr10
+ fmov.s @r15+, fr11
+ lds.l @r15+, fpscr
+#endif
+
+ mov.l @r15+, r3
+ shal r3 ! Load T flag
+ mov.l @r15+, r12
+ mov.l @r15+, r7
+ mov.l @r15+, r6
+ mov.l @r15+, r5
+ mov.l @r15+, r4
+ mov.l @r15+, r3
+ jmp @r0 ! Jump to function address
+ mov.l @r15+, r2 ! see Note2 above
+
+ .balign 4
+
+3:
+ .long _dl_linux_resolver@GOT
+.LG:
+ .long _GLOBAL_OFFSET_TABLE_
+ .size _dl_linux_resolve, . - _dl_linux_resolve
+
diff --git a/ap/build/uClibc/ldso/ldso/sh64/dl-debug.h b/ap/build/uClibc/ldso/ldso/sh64/dl-debug.h
new file mode 100644
index 0000000..6d861e5
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh64/dl-debug.h
@@ -0,0 +1,79 @@
+/* vi: set sw=8 ts=8: */
+/*
+ * ldso/ldso/sh64/elfinterp.c
+ *
+ * SuperH (sh64) ELF shared library loader suppport
+ *
+ * Copyright (C) 2003, 2004, 2005 Paul Mundt <lethal@linux-sh.org>
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ /* SHcompact relocs */
+ [0] = "R_SH_NONE", "R_SH_DIR32",
+ "R_SH_REL32", "R_SH_DIR8WPN",
+ [4] = "R_SH_IND12W", "R_SH_DIR8WPL",
+ "R_SH_DIR8WPZ", "R_SH_DIR8BP",
+ [8] = "R_SH_DIR8W", "R_SH_DIR8L",
+ [25] = "R_SH_SWITCH16", "R_SH_SWITCH32",
+ "R_SH_USES", "R_SH_COUNT",
+ [29] = "R_SH_ALIGN", "R_SH_CODE",
+ "R_SH_DATA", "R_SH_LABEL",
+ [33] = "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT",
+ "R_SH_GNU_VTENTRY",
+ [160] = "R_SH_GOT32", "R_SH_PLT32",
+ "R_SH_COPY", "R_SH_GLOB_DAT",
+ [164] = "R_SH_JMP_SLOT", "R_SH_RELATIVE",
+ "R_SH_GOTOFF", "R_SH_GOTPC",
+
+ /* SHmedia relocs */
+ [45] = "R_SH_DIR5U", "R_SH_DIR6U",
+ "R_SH_DIR6S", "R_SH_DIR10S",
+ [49] = "R_SH_DIR10SW", "R_SH_DIR10SL",
+ "R_SH_DIR10SQ",
+ [169] = "R_SH_GOT_LOW16", "R_SH_GOT_MEDLOW16",
+ "R_SH_GOT_MEDHI16", "R_SH_GOT_HI16",
+ [173] = "R_SH_GOTPLT_LOW16", "R_SH_GOTPLT_MEDLOW16",
+ "R_SH_GOTPLT_MEDHI16", "R_SH_GOTPLT_HI16",
+ [177] = "R_SH_PLT_LOW16", "R_SH_PLT_MEDLOW16",
+ "R_SH_PLT_MEDHI16", "R_SH_PLT_HI16",
+ [181] = "R_SH_GOTOFF_LOW16", "R_SH_GOTOFF_MEDLOW16",
+ "R_SH_GOTOFF_MEDHI16", "R_SH_GOTOFF_HI16",
+ [185] = "R_SH_GOTPC_LOW16", "R_SH_GOTPC_MEDLOW16",
+ "R_SH_GOTPC_MEDHI16", "R_SH_GOTPC_HI16",
+ [189] = "R_SH_GOT10BY4", "R_SH_GOTPLT10BY4",
+ "R_SH_GOT10BY8", "R_SH_GOTPLT10BY8",
+ [193] = "R_SH_COPY64", "R_SH_GLOB_DAT64",
+ "R_SH_JMP_SLOT64", "R_SH_RELATIVE64",
+ [197] = "R_SH_RELATIVE_LOW16", "R_SH_RELATIVE_MEDLOW16",
+ "R_SH_RELATIVE_MEDHI16","R_SH_RELATIVE_HI16",
+ [242] = "R_SH_SHMEDIA_CODE", "R_SH_PT_16",
+ "R_SH_IMMS16", "R_SH_IMMU16",
+ [246] = "R_SH_IMM_LOW16", "R_SH_IMM_LOW16_PCREL",
+ "R_SH_IMM_MEDLOW16", "R_SH_IMM_MEDLOW16_PCREL",
+ [250] = "R_SH_IMM_MEDHI16", "R_SH_IMM_MEDHI16_PCREL",
+ "R_SH_IMM_HI16", "R_SH_IMM_HI16_PCREL",
+ [254] = "R_SH_64", "R_SH_64_PCREL",
+};
diff --git a/ap/build/uClibc/ldso/ldso/sh64/dl-startup.h b/ap/build/uClibc/ldso/ldso/sh64/dl-startup.h
new file mode 100644
index 0000000..89bfe1f
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh64/dl-startup.h
@@ -0,0 +1,117 @@
+/* Any assembly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture.
+ */
+
+__asm__("" \
+" .section .text..SHmedia32,\"ax\"\n" \
+" .globl _start\n" \
+" .type _start, @function\n" \
+" .align 5\n" \
+"_start:\n" \
+" ! Set r12 to point to GOT\n" \
+" movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) >> 16) & 0xffff), r12\n" \
+" shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) & 0xffff), r12\n" \
+".LZZZ3:\n" \
+" ptrel/u r12, tr0\n" \
+" gettr tr0, r12 ! GOT address\n" \
+" add r18, r63, r11 ! save return address - needed?\n" \
+" add r15, r63, r2 ! arg = stack pointer\n" \
+" pt _dl_start, tr0 ! should work even if PIC\n" \
+" blink tr0, r18 ! call _dl_start - user EP is in r2\n" \
+" add r2, r63, r28\n" \
+" movi (((_dl_fini@GOT) >> 16) & 0xffff), r1\n" \
+" shori ((_dl_fini@GOT) & 0xffff), r1\n" \
+" ldx.l r1, r12, r2\n" \
+" add r11, r63, r18\n" \
+" ptabs/l r28, tr0\n" \
+" blink tr0, r63\n" \
+" .size _start,.-_start\n"
+" .previous\n"
+);
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *)ARGS)+1)
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+
+#include <elf.h>
+
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ const unsigned int r_type = ELF_R_TYPE((RELP)->r_info); \
+ int lsb = !!((SYMTAB)->st_other & STO_SH5_ISA32); \
+ \
+ switch (r_type) { \
+ case R_SH_REL32: \
+ *(REL) = (SYMBOL) + (RELP)->r_addend \
+ - (unsigned long)(REL); \
+ break; \
+ case R_SH_DIR32: \
+ case R_SH_GLOB_DAT: \
+ case R_SH_JMP_SLOT: \
+ *(REL) = ((SYMBOL) + (RELP)->r_addend) | lsb; \
+ break; \
+ case R_SH_RELATIVE: \
+ *(REL) = (LOAD) + (RELP)->r_addend; \
+ break; \
+ case R_SH_RELATIVE_LOW16: \
+ case R_SH_RELATIVE_MEDLOW16: \
+ { \
+ unsigned long word, value; \
+ \
+ word = (unsigned long)(REL) & ~0x3fffc00; \
+ value = (LOAD) + (RELP)->r_addend; \
+ \
+ if (r_type == R_SH_RELATIVE_MEDLOW16) \
+ value >>= 16; \
+ \
+ word |= (value & 0xffff) << 10; \
+ *(REL) = word; \
+ break; \
+ } \
+ case R_SH_IMM_LOW16: \
+ case R_SH_IMM_MEDLOW16: \
+ { \
+ unsigned long word, value; \
+ \
+ word = (unsigned long)(REL) & ~0x3fffc00; \
+ value = ((SYMBOL) + (RELP)->r_addend) | lsb; \
+ \
+ if (r_type == R_SH_IMM_MEDLOW16) \
+ value >>= 16; \
+ \
+ word |= (value & 0xffff) << 10; \
+ *(REL) = word; \
+ break; \
+ } \
+ case R_SH_IMM_LOW16_PCREL: \
+ case R_SH_IMM_MEDLOW16_PCREL: \
+ { \
+ unsigned long word, value; \
+ \
+ word = (unsigned long)(REL) & ~0x3fffc00; \
+ value = (SYMBOL) + (RELP)->r_addend \
+ - (unsigned long)(REL); \
+ \
+ if (r_type == R_SH_IMM_MEDLOW16_PCREL) \
+ value >>= 16; \
+ \
+ word |= (value & 0xffff) << 10; \
+ *(REL) = word; \
+ break; \
+ } \
+ case R_SH_NONE: \
+ break; \
+ default: \
+ _dl_exit(1); \
+ }
diff --git a/ap/build/uClibc/ldso/ldso/sh64/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/sh64/dl-syscalls.h
new file mode 100644
index 0000000..2ea4bb7
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh64/dl-syscalls.h
@@ -0,0 +1,18 @@
+#undef __syscall_return
+#define __syscall_return(type, res) \
+do { \
+ /* \
+ * Note: when returning from kernel the return value is in r9 \
+ * \
+ * This prevents conflicts between return value and arg1 \
+ * when dispatching signal handler, in other words makes \
+ * life easier in the system call epilogue (see entry.S) \
+ */ \
+ register unsigned long __sr2 __asm__ ("r2") = res; \
+ if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+ _dl_errno = -(res); \
+ __sr2 = -1; \
+ } \
+ return (type)(__sr2); \
+} while (0)
+
diff --git a/ap/build/uClibc/ldso/ldso/sh64/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/sh64/dl-sysdep.h
new file mode 100644
index 0000000..0434139
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh64/dl-sysdep.h
@@ -0,0 +1,168 @@
+/* vi: set sw=8 ts=8: */
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+#include <elf.h>
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[2] = (unsigned long)_dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long)(MODULE); \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_SH
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "sh64"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references should not be allowed to
+ define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf32_Addr elf_machine_dynamic(void)
+{
+ register Elf32_Addr *got;
+
+ /*
+ * The toolchain adds 32768 to the GOT address, we compensate for
+ * that in the movi/sub pair.
+ *
+ * XXX: If this is cleaned up in the toolchain, we can end up
+ * saving 2 instructions and subsequently free up r1 from the
+ * clobber list..
+ */
+ __asm__ (
+ "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) >> 16) & 0xffff), r2\n\t"
+ "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) & 0xffff), r2\n\t"
+ ".LZZZ1:\tptrel/u r2, tr0\n\t"
+ "movi\t32768, r1\n\t"
+ "gettr\ttr0, r2\n\t"
+ "sub\tr2, r1, %0\n\t"
+ : "=r" (got)
+ : /* no inputs */
+ : "r1", "r2", "tr0"
+ );
+
+ return *got;
+}
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr elf_machine_load_address(void)
+{
+ Elf32_Addr addr;
+
+ __asm__ (
+ "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) >> 16) & 0xffff), r0\n\t"
+ "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) & 0xffff), r0\n\t"
+ ".LZZZ2:\tptrel/u r0, tr0\n\t"
+ "movi\t(((_dl_start@GOTOFF) >> 16) & 0xffff), r2\n\t"
+ "shori\t((_dl_start@GOTOFF) & 0xffff), r2\n\t"
+ "gettr\ttr0, r0\n\t"
+ "add\tr2, r0, r2\n\t"
+ "movi\t(((_dl_start@GOT) >> 16) & 0xffff), r1\n\t"
+ "shori\t((_dl_start@GOT) & 0xffff), r1\n\t"
+ "ldx.l\tr1, r0, r1\n\t"
+ "sub\tr2, r1, %0\n\t"
+ : "=r" (addr)
+ : /* no inputs */
+ : "r0", "r1", "r2", "tr0"
+ );
+
+ return addr;
+}
+
+/*
+ * XXX: As we don't need to worry about r25 clobbering, we could probably
+ * get away with inlining {st,ld}{x,}.l and friends here instead and
+ * forego gcc's idea of code generation.
+ */
+#define COPY_UNALIGNED_WORD(swp, twp, align) \
+{ \
+ void *__s = (swp), *__t = (twp); \
+ unsigned char *__s1 = __s, *__t1 = __t; \
+ unsigned short *__s2 = __s, *__t2 = __t; \
+ unsigned long *__s4 = __s, *__t4 = __t; \
+ \
+ switch ((align)) { \
+ case 0: \
+ *__t4 = *__s4; \
+ break; \
+ case 2: \
+ *__t2++ = *__s2++; \
+ *__t2 = *__s2; \
+ break; \
+ default: \
+ *__t1++ = *__s1++; \
+ *__t1++ = *__s1++; \
+ *__t1++ = *__s1++; \
+ *__t1 = *__s1; \
+ break; \
+ } \
+}
+
+static __always_inline void
+elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Addr value, word;
+ Elf32_Rela *rpnt = (void *)rel_addr;
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ do {
+ Elf32_Addr *const reloc_addr =
+ (void *)(load_off + rpnt->r_offset);
+ int align = (int)reloc_addr & 3;
+
+ switch (reloc_type) {
+ case R_SH_RELATIVE_LOW16:
+ COPY_UNALIGNED_WORD(reloc_addr, &word, align);
+ word &= ~0x3fffc00;
+ value = (rpnt->r_addend + load_off);
+ word |= (value & 0xffff) << 10;
+ COPY_UNALIGNED_WORD(&word, reloc_addr, align);
+ break;
+ case R_SH_RELATIVE_MEDLOW16:
+ COPY_UNALIGNED_WORD(reloc_addr, &word, align);
+ word &= ~0x3fffc00;
+ value = (rpnt->r_addend + load_off) >> 16;
+ word |= (value & 0xffff) << 10;
+ COPY_UNALIGNED_WORD(&word, reloc_addr, align);
+ break;
+ default:
+ if (rpnt->r_addend) {
+ value = load_off + rpnt->r_addend;
+ } else {
+ COPY_UNALIGNED_WORD(reloc_addr, &value, align);
+ value += load_off;
+ }
+
+ COPY_UNALIGNED_WORD(&value, reloc_addr, align);
+ break;
+ }
+
+ rpnt++;
+ } while (--relative_count);
+#undef COPY_UNALIGNED_WORD
+}
diff --git a/ap/build/uClibc/ldso/ldso/sh64/elfinterp.c b/ap/build/uClibc/ldso/ldso/sh64/elfinterp.c
new file mode 100644
index 0000000..3a59bc4
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh64/elfinterp.c
@@ -0,0 +1,345 @@
+/* vi: set sw=8 ts=8: */
+/*
+ * ldso/ldso/sh64/elfinterp.c
+ *
+ * SuperH (sh64) ELF shared library loader suppport
+ *
+ * Copyright (C) 2003, 2004, 2005 Paul Mundt <lethal@linux-sh.org>
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+#include "ldso.h"
+
+extern int _dl_linux_resolve(void);
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+ this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of jump instruction to fix up */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+
+ /* Get the address of the GOT entry */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#ifdef __SUPPORT_LD_DEBUG__
+ if ((unsigned long)got_addr < 0x20000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
+ symname);
+
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\n\tpatched %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+
+ if (!_dl_debug_nofixups)
+ *got_addr = new_addr;
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long)new_addr;
+}
+
+static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt,
+ struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab,
+ char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Now parse the relocation information */
+ rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
+ rel_size = rel_size / sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ _dl_dprintf(2, "can't handle reloc type "
+#ifdef __SUPPORT_LD_DEBUG__
+ "%s\n", _dl_reltypes(reloc_type)
+#else
+ "%x\n", reloc_type
+#endif
+ );
+
+ _dl_exit(-res);
+ }
+ if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int _dl_do_reloc(struct elf_resolve *tpnt,struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index, lsb;
+ char *symname;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+#ifdef __SUPPORT_LD_DEBUG__
+ unsigned long old_val;
+#endif
+ struct symbol_ref sym_ref;
+
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+ lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symname = strtab + symtab[symtab_index].st_name;
+ reloc_addr = (unsigned long *)(intptr_t)
+ (tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+
+ if (symtab_index) {
+ int stb;
+
+ symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+ stb = ELF_ST_BIND(symtab[symtab_index].st_info);
+
+ if (stb != STB_WEAK && !symbol_addr) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit (1);
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ }
+
+#ifdef __SUPPORT_LD_DEBUG__
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_SH_NONE:
+ break;
+ case R_SH_COPY:
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr, symtab[symtab_index].st_size);
+ break;
+ case R_SH_DIR32:
+ case R_SH_GLOB_DAT:
+ case R_SH_JMP_SLOT:
+ *reloc_addr = (symbol_addr + rpnt->r_addend) | lsb;
+ break;
+ case R_SH_REL32:
+ *reloc_addr = symbol_addr + rpnt->r_addend -
+ (unsigned long)reloc_addr;
+ break;
+ case R_SH_RELATIVE:
+ *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+ break;
+ case R_SH_RELATIVE_LOW16:
+ case R_SH_RELATIVE_MEDLOW16:
+ {
+ unsigned long word, value;
+
+ word = (unsigned long)reloc_addr & ~0x3fffc00;
+ value = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+
+ if (reloc_type == R_SH_RELATIVE_MEDLOW16)
+ value >>= 16;
+
+ word |= (value & 0xffff) << 10;
+ *reloc_addr = word;
+
+ break;
+ }
+ case R_SH_IMM_LOW16:
+ case R_SH_IMM_MEDLOW16:
+ {
+ unsigned long word, value;
+
+ word = (unsigned long)reloc_addr & ~0x3fffc00;
+ value = (symbol_addr + rpnt->r_addend) | lsb;
+
+ if (reloc_type == R_SH_IMM_MEDLOW16)
+ value >>= 16;
+
+ word |= (value & 0xffff) << 10;
+ *reloc_addr = word;
+
+ break;
+ }
+ case R_SH_IMM_LOW16_PCREL:
+ case R_SH_IMM_MEDLOW16_PCREL:
+ {
+ unsigned long word, value;
+
+ word = (unsigned long)reloc_addr & ~0x3fffc00;
+ value = symbol_addr + rpnt->r_addend -
+ (unsigned long)reloc_addr;
+
+ if (reloc_type == R_SH_IMM_MEDLOW16_PCREL)
+ value >>= 16;
+
+ word |= (value & 0xffff) << 10;
+ *reloc_addr = word;
+
+ break;
+ }
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+
+#ifdef __SUPPORT_LD_DEBUG__
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type, symtab_index, lsb;
+ unsigned long *reloc_addr;
+#ifdef __SUPPORT_LD_DEBUG__
+ unsigned long old_val;
+#endif
+
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32);
+ reloc_addr = (unsigned long *)(intptr_t)
+ (tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+
+#ifdef __SUPPORT_LD_DEBUG__
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_SH_NONE:
+ break;
+ case R_SH_JMP_SLOT:
+ *reloc_addr += (unsigned long)tpnt->loadaddr | lsb;
+ break;
+ default:
+ return -1; /*call _dl_exit(1) */
+ }
+
+#ifdef __SUPPORT_LD_DEBUG__
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/sh64/resolve.S b/ap/build/uClibc/ldso/ldso/sh64/resolve.S
new file mode 100644
index 0000000..ca915d2
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sh64/resolve.S
@@ -0,0 +1,95 @@
+/* vi: set sw=8 ts=8: */
+/*
+ * ldso/ldso/sh64/resolve.S
+ *
+ * SuperH (sh64) dynamic resolver support
+ *
+ * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+ .section .text..SHmedia32,"ax"
+ .globl _dl_linux_resolver
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve, @function
+
+ .balign 16
+_dl_linux_resolve:
+ addi r15, -72, r15 ! make room on the stack
+ pt _dl_linux_resolver, tr0
+ st.q r15, 0, r2 ! save regs
+ st.q r15, 8, r3
+ st.q r15, 16, r4
+ st.q r15, 24, r5
+ st.q r15, 32, r6
+ st.q r15, 40, r7
+ st.q r15, 48, r8
+ st.q r15, 56, r9
+ st.q r15, 64, r18
+
+#ifdef HAVE_FPU
+ addi r15, -48, r15 ! make room for FP regs
+ fst.d r15, 0, dr0 ! save FP regs
+ fst.d r15, 8, dr2
+ fst.d r15, 16, dr4
+ fst.d r15, 24, dr6
+ fst.d r15, 32, dr8
+ fst.d r15, 40, dr10
+#endif
+
+ /*
+ * Args for _dl_linux_resolver(), set in r17/r21 by PLT code
+ */
+
+ add r17, r63, r2 ! link map address
+ add r21, r63, r3 ! GOT offset
+ blink tr0, r18 ! call _dl_linux_resolver()
+ ptabs/l r2, tr0 ! save result = addr of function called
+
+#ifdef HAVE_FPU
+ fld.d r15, 0, dr0 ! restore FP regs
+ fld.d r15, 8, dr2
+ fld.d r15, 16, dr4
+ fld.d r15, 24, dr6
+ fld.d r15, 32, dr8
+ fld.d r15, 40, dr10
+ addi r15, 48, r15
+#endif
+
+ ld.q r15, 0, r2 ! restore regs
+ ld.q r15, 8, r3
+ ld.q r15, 16, r4
+ ld.q r15, 24, r5
+ ld.q r15, 32, r6
+ ld.q r15, 40, r7
+ ld.q r15, 48, r8
+ ld.q r15, 56, r9
+ ld.q r15, 64, r18
+
+ addi r15, 72, r15
+ blink tr0, r63 ! jump to function address
+
+ .size _dl_linux_resolve, . - _dl_linux_resolve
+
diff --git a/ap/build/uClibc/ldso/ldso/sparc/dl-debug.h b/ap/build/uClibc/ldso/ldso/sparc/dl-debug.h
new file mode 100644
index 0000000..5c62cef
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sparc/dl-debug.h
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/* sparc ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ "R_SPARC_NONE", "R_SPARC_8",
+ "R_SPARC_16", "R_SPARC_32", "R_SPARC_DISP8", "R_SPARC_DISP16",
+ "R_SPARC_DISP32", "R_SPARC_WDISP30", "R_SPARC_WDISP22",
+ "R_SPARC_HI22", "R_SPARC_22", "R_SPARC_13", "R_SPARC_LO10",
+ "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", "R_SPARC_PC10",
+ "R_SPARC_PC22", "R_SPARC_WPLT30", "R_SPARC_COPY",
+ "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", "R_SPARC_RELATIVE",
+ "R_SPARC_UA32"
+};
diff --git a/ap/build/uClibc/ldso/ldso/sparc/dl-startup.h b/ap/build/uClibc/ldso/ldso/sparc/dl-startup.h
new file mode 100644
index 0000000..1abad11
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sparc/dl-startup.h
@@ -0,0 +1,78 @@
+/* Any assembly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture. See arm/boot1_arch.h for an example of what
+ * can be done.
+ */
+
+__asm__ ("\
+ .text\n\
+ .global _start\n\
+ .type _start,%function\n\
+ .align 32\n\
+ .register %g2, #scratch\n\
+_start:\n\
+ /* Allocate space for functions to drop their arguments. */\n\
+ sub %sp, 6*4, %sp\n\
+ /* Pass pointer to argument block to _dl_start. */\n\
+ call _dl_start\n\
+ add %sp, 22*4, %o0\n\
+ /* FALTHRU */\n\
+ .globl _dl_start_user\n\
+ .type _dl_start_user, @function\n\
+_dl_start_user:\n\
+ /* Load the PIC register. */\n\
+1: call 2f\n\
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\
+2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\
+ add %l7, %o7, %l7\n\
+ /* Save the user entry point address in %l0 */\n\
+ mov %o0, %l0\n\
+ /* See if we were run as a command with the executable file name as an\n\
+ extra leading argument. If so, adjust the contents of the stack. */\n\
+ sethi %hi(_dl_skip_args), %g2\n\
+ or %g2, %lo(_dl_skip_args), %g2\n\
+ ld [%l7+%g2], %i0\n\
+ ld [%i0], %i0\n\
+ tst %i0\n\
+ /* Pass our finalizer function to the user in %g1. */\n\
+ sethi %hi(_dl_fini), %g1\n\
+ or %g1, %lo(_dl_fini), %g1\n\
+ ld [%l7+%g1], %g1\n\
+ /* Jump to the user's entry point and deallocate the extra stack we got. */\n\
+ jmp %l0\n\
+ add %sp, 6*4, %sp\n\
+ .size _dl_start_user, . - _dl_start_user\n\
+ .previous\n\
+");
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. We assume that argc is stored
+ * at the word just below the argvp that we return here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+switch(ELF_R_TYPE((RELP)->r_info)) { \
+ case R_SPARC_32: \
+ case R_SPARC_GLOB_DAT: \
+ *REL = SYMBOL + (RELP)->r_addend; \
+ break; \
+ case R_SPARC_JMP_SLOT: \
+ REL[1] = 0x03000000 | ((SYMBOL >> 10) & 0x3fffff); \
+ REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \
+ break; \
+ case R_SPARC_NONE: \
+ case R_SPARC_WDISP30: \
+ break; \
+ case R_SPARC_RELATIVE: \
+ *REL += (unsigned int) LOAD + (RELP)->r_addend; \
+ break; \
+ default: \
+ _dl_exit(1); \
+}
diff --git a/ap/build/uClibc/ldso/ldso/sparc/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/sparc/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sparc/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/sparc/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/sparc/dl-sysdep.h
new file mode 100644
index 0000000..d35a391
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sparc/dl-sysdep.h
@@ -0,0 +1,164 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+#include <elf.h>
+/*
+ * Initialization sequence for a GOT. For the Sparc, this points to the
+ * PLT, and we need to initialize a couple of the slots. The PLT should
+ * look like:
+ *
+ * save %sp, -64, %sp
+ * call _dl_linux_resolve
+ * nop
+ * .word implementation_dependent
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[0] = 0x9de3bfc0; /* save %sp, -64, %sp */ \
+ GOT_BASE[1] = 0x40000000 | (((unsigned int) _dl_linux_resolve - (unsigned int) GOT_BASE - 4) >> 2); \
+ GOT_BASE[2] = 0x01000000; /* nop */ \
+ GOT_BASE[3] = (int) MODULE; \
+}
+
+/* Here we define the magic numbers that this dynamic loader should accept
+ * Note that SPARCV9 doesn't use EM_SPARCV9 since the userland is still 32-bit.
+ */
+#if defined(__sparc_v9__)
+#define MAGIC1 EM_SPARC32PLUS
+#else
+#define MAGIC1 EM_SPARC
+#endif
+
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "sparc"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/*
+ * Define this if you want a dynamic loader that works on Solaris.
+ */
+
+#ifndef COMPILE_ASM
+/* Cheap modulo implementation, taken from arm/ld_sysdep.h. */
+static __always_inline unsigned long
+sparc_mod(unsigned long m, unsigned long p)
+{
+ unsigned long i, t, inc;
+
+ i = p;
+ t = 0;
+
+ while (!(i & (1 << 31))) {
+ i <<= 1;
+ t++;
+ }
+
+ t--;
+
+ for (inc = t; inc > 2; inc--) {
+ i = p << inc;
+
+ if (i & (1 << 31))
+ break;
+
+ while (m >= i) {
+ m -= i;
+ i <<= 1;
+ if (i & (1 << 31))
+ break;
+ if (i < p)
+ break;
+ }
+ }
+
+ while (m >= p)
+ m -= p;
+
+ return m;
+}
+
+#define do_rem(result, n, base) ((result) = sparc_mod(n, base))
+#endif
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ PLT entries should not be allowed to define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_SPARC_JMP_SLOT || (type) == R_SPARC_TLS_DTPMOD32 \
+ || (type) == R_SPARC_TLS_DTPOFF32 || (type) == R_SPARC_TLS_TPOFF32) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* The SPARC overlaps DT_RELA and DT_PLTREL. */
+#define ELF_MACHINE_PLTREL_OVERLAP 1
+
+/* We have to do this because elf_machine_{dynamic,load_address} can be
+ invoked from functions that have no GOT references, and thus the compiler
+ has no obligation to load the PIC register. */
+#define LOAD_PIC_REG(PIC_REG) \
+do { register Elf32_Addr pc __asm__("o7"); \
+ __asm__("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
+ "call 1f\n\t" \
+ "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \
+ "1:\tadd %1, %0, %1" \
+ : "=r" (pc), "=r" (PIC_REG)); \
+} while (0)
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ register Elf32_Addr *got __asm__ ("%l7");
+
+ LOAD_PIC_REG (got);
+
+ return *got;
+}
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ register Elf32_Addr *pc __asm__ ("%o7"), *got __asm__ ("%l7");
+
+ __asm__ ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"
+ "call 1f\n\t"
+ " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"
+ "call _DYNAMIC\n\t"
+ "call _GLOBAL_OFFSET_TABLE_\n"
+ "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got));
+
+ /* got is now l_addr + _GLOBAL_OFFSET_TABLE_
+ *got is _DYNAMIC
+ pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8
+ pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12 */
+ return (Elf32_Addr) got - *got + (pc[2] - pc[3]) * 4 - 4;
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela * rpnt = (void *)rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/sparc/elfinterp.c b/ap/build/uClibc/ldso/ldso/sparc/elfinterp.c
new file mode 100644
index 0000000..e3f0e47
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sparc/elfinterp.c
@@ -0,0 +1,377 @@
+/* vi: set sw=4 ts=4: */
+/* sparc ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+/* Program to load an ELF binary on a linux system, and run it.
+References to symbols in sharable libraries can be resolved by either
+an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+/* Some SPARC opcodes we need to use for self-modifying code. */
+#define OPCODE_NOP 0x01000000 /* nop */
+#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */
+#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */
+#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */
+#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
+#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */
+
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ ElfW(Addr) instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ /*
+ * Generate the correct relocation index into the .rela.plt section.
+ */
+ reloc_entry = (reloc_entry >> 10) - 0xc;
+
+ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups)
+#endif
+ {
+ got_addr[1] = (char *) (OPCODE_SETHI_G1 | (((unsigned int) new_addr >> 10) & 0x3fffff));
+ got_addr[2] = (char *) (OPCODE_JMP_G1 | ((unsigned int) new_addr & 0x3ff));
+ }
+
+ return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size /= sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ _dl_dprintf(2, "can't handle reloc type "
+#if defined (__SUPPORT_LD_DEBUG__)
+ "%s\n", _dl_reltypes(reloc_type));
+#else
+ "%x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ struct elf_resolve *tls_tpnt = NULL;
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symbol_addr = 0;
+ symname = strtab + sym_ref.sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ /*
+ * We want to allow undefined references to weak symbols - this
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+ if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS)
+ && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
+
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ tls_tpnt = sym_ref.tpnt;
+ } else {
+ /* Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself. */
+ symbol_addr = sym_ref.sym->st_value;
+ tls_tpnt = tpnt;
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */
+
+ switch (reloc_type) {
+ case R_SPARC_NONE:
+ break;
+
+ case R_SPARC_DISP32:
+ *reloc_addr = symbol_addr - (unsigned int) reloc_addr;
+ break;
+
+ case R_SPARC_LO10:
+ if (!symbol_addr)
+ symbol_addr = tpnt->loadaddr + rpnt->r_addend;
+ else
+ symbol_addr += rpnt->r_addend;
+ *reloc_addr = (*reloc_addr & ~0x3ff) | (symbol_addr & 0x3ff);
+ break;
+
+ case R_SPARC_GLOB_DAT:
+ case R_SPARC_32:
+ *reloc_addr = symbol_addr;
+ break;
+
+ case R_SPARC_JMP_SLOT:
+ reloc_addr[1] = OPCODE_SETHI_G1 | (( symbol_addr >> 10 ) & 0x3fffff);
+ reloc_addr[2] = OPCODE_JMP_G1 | ( symbol_addr & 0x3ff );
+ break;
+
+ case R_SPARC_RELATIVE:
+ *reloc_addr += tpnt->loadaddr + rpnt->r_addend;
+ break;
+
+ case R_SPARC_WDISP30:
+ *reloc_addr = (*reloc_addr & 0xc0000000)|
+ ((symbol_addr - (unsigned int) reloc_addr) >> 2);
+ break;
+
+ case R_SPARC_HI22:
+ if (!symbol_addr)
+ symbol_addr = tpnt->loadaddr + rpnt->r_addend;
+ else
+ symbol_addr += rpnt->r_addend;
+ *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10);
+ break;
+
+ case R_SPARC_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\t%s move %d bytes from %x to %x\n",
+ symname, sym_ref.sym->st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ sym_ref.sym->st_size);
+ } else
+ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
+ break;
+#if defined USE_TLS && USE_TLS
+ case R_SPARC_TLS_DTPMOD32:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+
+ case R_SPARC_TLS_DTPOFF32:
+ /* During relocation all TLS symbols are defined and used.
+ * Therefore the offset is already correct. */
+ *reloc_addr = sym_ref.sym->st_value + rpnt->r_addend;
+ break;
+
+ case R_SPARC_TLS_TPOFF32:
+ /* The offset is negative, forward from the thread pointer.
+ * We know the offset of the object the symbol is contained in.
+ * It is a negative value which will be added to the
+ * thread pointer. */
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = sym_ref.sym->st_value - tls_tpnt->l_tls_offset + rpnt->r_addend;
+ break;
+#endif
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+#undef __SPARC_LAZY_RELOC_WORKS
+#ifdef __SPARC_LAZY_RELOC_WORKS
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ (void)scope;
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ (void)strtab;
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_SPARC_NONE:
+ break;
+ case R_SPARC_JMP_SLOT:
+ break;
+ default:
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+#endif
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+#ifdef __SPARC_LAZY_RELOC_WORKS
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+#else
+ _dl_parse_relocation_information(rpnt, &_dl_loaded_modules->symbol_scope,
+ rel_addr, rel_size);
+#endif
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/sparc/resolve.S b/ap/build/uClibc/ldso/ldso/sparc/resolve.S
new file mode 100644
index 0000000..253400a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/sparc/resolve.S
@@ -0,0 +1,22 @@
+/*
+ * These are various helper routines that are needed to run an ELF image.
+ */
+
+.text
+.align 16
+
+.globl _dl_linux_resolve
+.type _dl_linux_resolve,#function
+_dl_linux_resolve:
+ /*
+ * Call the resolver - pass the address of the PLT so that we can
+ * figure out which module we are in.
+ */
+ mov %o7,%o1
+ call _dl_linux_resolver
+ mov %g1,%o0
+
+ jmpl %o0,%o7
+ restore
+.LFE2:
+ .size _dl_linux_resolve,.LFE2-_dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/x86_64/dl-debug.h b/ap/build/uClibc/ldso/ldso/x86_64/dl-debug.h
new file mode 100644
index 0000000..c47062b
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/x86_64/dl-debug.h
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/* x86_64 debug code for ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ */
+
+static const char * const _dl_reltypes_tab[] = {
+ [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32",
+ [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT",
+ [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S",
+ [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8",
+ [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD",
+ [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32"
+};
diff --git a/ap/build/uClibc/ldso/ldso/x86_64/dl-startup.h b/ap/build/uClibc/ldso/ldso/x86_64/dl-startup.h
new file mode 100644
index 0000000..b2ea93d
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/x86_64/dl-startup.h
@@ -0,0 +1,67 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org>
+ *
+ * Parts taken from glibc/sysdeps/x86_64/dl-machine.h
+ */
+__asm__ (
+ " .text\n"
+ " .global _start\n"
+ " .type _start,%function\n"
+ "_start:\n"
+ " movq %rsp, %rdi\n"
+ " call _dl_start\n"
+ " # Save the user entry point address in %r12.\n"
+ " movq %rax, %r12\n"
+ " # See if we were run as a command with the executable file\n"
+ " # name as an extra leading argument.\n"
+ " movl _dl_skip_args(%rip), %eax\n"
+ " # Pop the original argument count.\n"
+ " popq %rdx\n"
+ " # Adjust the stack pointer to skip _dl_skip_args words.\n"
+ " leaq (%rsp,%rax,8), %rsp\n"
+ " # Subtract _dl_skip_args from argc.\n"
+ " subl %eax, %edx\n"
+ " # Push argc back on the stack.\n"
+ " pushq %rdx\n"
+ " # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n"
+ " leaq _dl_fini(%rip), %rdx\n"
+ " # Jump to the user's entry point.\n"
+ " jmp *%r12\n"
+ " .size _start,.-_start\n"
+ " .previous\n"
+);
+
+/* Get a pointer to the argv array. On many platforms this can be just
+ * the address of the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
+
+/* Handle relocation of the symbols in the dynamic loader. */
+static __always_inline
+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr,
+ ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym)
+{
+ switch (ELF_R_TYPE(rpnt->r_info)) {
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_JUMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_X86_64_DTPMOD64:
+ *reloc_addr = 1;
+ break;
+ case R_X86_64_NONE:
+ case R_X86_64_DTPOFF64:
+ break;
+ case R_X86_64_TPOFF64:
+ *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr;
+ break;
+/*TODO: case R_X86_64_RELATIVE:
+ *reloc_addr = load_addr + rpnt->r_addend;
+ break; */
+ default:
+ _dl_exit(1);
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/x86_64/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/x86_64/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/x86_64/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/x86_64/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/x86_64/dl-sysdep.h
new file mode 100644
index 0000000..ae3542a
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/x86_64/dl-sysdep.h
@@ -0,0 +1,112 @@
+/* vi: set sw=4 ts=4: */
+/* yoinked from glibc/sysdeps/x86_64/dl-machine.h */
+/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+#include <elf.h>
+#include <link.h>
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+} while(0)
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+#define MAGIC1 EM_X86_64
+#undef MAGIC2
+
+/* Used for error messages */
+#define ELF_TARGET "x86_64"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+ TLS variable, so undefined references should not be allowed to
+ define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+ of the main executable's symbols, as for a COPY reloc. */
+#define elf_machine_type_class(type) \
+ ((((type) == R_X86_64_JUMP_SLOT \
+ || (type) == R_X86_64_DTPMOD64 \
+ || (type) == R_X86_64_DTPOFF64 \
+ || (type) == R_X86_64_TPOFF64) \
+ * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+static __always_inline Elf64_Addr __attribute__ ((unused))
+elf_machine_dynamic (void)
+{
+ Elf64_Addr addr;
+
+ /* This works because we have our GOT address available in the small PIC
+ model. */
+ addr = (Elf64_Addr) &_DYNAMIC;
+
+ return addr;
+}
+
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf64_Addr __attribute__ ((unused))
+elf_machine_load_address (void)
+{
+ register Elf64_Addr addr, tmp;
+
+ /* The easy way is just the same as on x86:
+ leaq _dl_start, %0
+ leaq _dl_start(%%rip), %1
+ subq %0, %1
+ but this does not work with binutils since we then have
+ a R_X86_64_32S relocation in a shared lib.
+
+ Instead we store the address of _dl_start in the data section
+ and compare it with the current value that we can get via
+ an RIP relative addressing mode. */
+
+ __asm__ ("movq 1f(%%rip), %1\n"
+ "0:\tleaq _dl_start(%%rip), %0\n\t"
+ "subq %1, %0\n\t"
+ ".section\t.data\n"
+ "1:\t.quad _dl_start\n\t"
+ ".previous\n\t"
+ : "=r" (addr), "=r" (tmp) : : "cc");
+
+ return addr;
+}
+
+static __always_inline void
+elf_machine_relative(Elf64_Addr load_off, const Elf64_Addr rel_addr,
+ Elf64_Word relative_count)
+{
+ Elf64_Rela *rpnt = (Elf64_Rela*)rel_addr;
+ --rpnt;
+ do {
+ Elf64_Addr *const reloc_addr = (Elf64_Addr*)(load_off + (++rpnt)->r_offset);
+
+ *reloc_addr = load_off + rpnt->r_addend;
+ } while (--relative_count);
+}
diff --git a/ap/build/uClibc/ldso/ldso/x86_64/elfinterp.c b/ap/build/uClibc/ldso/ldso/x86_64/elfinterp.c
new file mode 100644
index 0000000..75666a7
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/x86_64/elfinterp.c
@@ -0,0 +1,344 @@
+/* vi: set sw=4 ts=4: */
+/* x86_64 ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+/* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+extern int _dl_linux_resolve(void);
+
+unsigned long
+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ ElfW(Addr) instr_addr;
+ char *symname;
+
+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the jump instruction to fix up. */
+ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely(!new_addr)) {
+ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if ((unsigned long)got_addr < 0x40000000) {
+ if (_dl_debug_bindings) {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+ "\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+ if (!_dl_debug_nofixups)
+#endif
+ *got_addr = new_addr;
+
+ return (unsigned long)new_addr;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *)rel_addr;
+ rel_size /= sizeof(ELF_RELOC);
+
+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+
+ debug_sym(symtab, strtab, symtab_index);
+ debug_reloc(symtab, strtab, rpnt);
+
+ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf(2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely(res < 0)) {
+ int reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+ _dl_dprintf(2, "can't handle reloc type "
+#if defined (__SUPPORT_LD_DEBUG__)
+ "%s\n", _dl_reltypes(reloc_type));
+#else
+ "%x\n", reloc_type);
+#endif
+ _dl_exit(-res);
+ } else if (unlikely(res > 0)) {
+ _dl_dprintf(2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+static int
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+#if defined USE_TLS && USE_TLS
+ struct elf_resolve *tls_tpnt;
+#endif
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symbol_addr = 0;
+ symname = strtab + sym_ref.sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+ /*
+ * We want to allow undefined references to weak symbols - this
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+ if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS)
+ && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = sym_ref.tpnt;
+#endif
+ } else {
+ /* Relocs against STN_UNDEF are usually treated as using a
+ * symbol value of zero, and using the module containing the
+ * reloc itself. */
+ symbol_addr = sym_ref.sym->st_value;
+#if defined USE_TLS && USE_TLS
+ tls_tpnt = tpnt;
+#endif
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_X86_64_NONE:
+ break;
+
+ case R_X86_64_64:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ case R_X86_64_PC32:
+ *reloc_addr = symbol_addr + rpnt->r_addend - rpnt->r_offset;
+ break;
+
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_JUMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ /* handled by elf_machine_relative()
+ case R_X86_64_RELATIVE:
+ *reloc_addr = map->l_addr + rpnt->r_addend;
+ break;
+ */
+#if defined USE_TLS && USE_TLS
+ case R_X86_64_DTPMOD64:
+ *reloc_addr = tls_tpnt->l_tls_modid;
+ break;
+ case R_X86_64_DTPOFF64:
+ /* During relocation all TLS symbols are defined and used.
+ * Therefore the offset is already correct. */
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_X86_64_TPOFF64:
+ /* The offset is negative, forward from the thread pointer.
+ * We know the offset of the object the symbol is contained in.
+ * It is a negative value which will be added to the
+ * thread pointer. */
+ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
+ *reloc_addr = symbol_addr - tls_tpnt->l_tls_offset + rpnt->r_addend;
+ break;
+#endif
+ case R_X86_64_32:
+ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;
+ /* XXX: should check for overflow eh ? */
+ break;
+
+ case R_X86_64_COPY:
+ if (symbol_addr) {
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\t%s move %d bytes from %x to %x\n",
+ symname, sym_ref.sym->st_size,
+ symbol_addr, reloc_addr);
+#endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+ sym_ref.sym->st_size);
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ else
+ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
+#endif
+ break;
+
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+static int
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ (void)scope;
+ (void)strtab;
+
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_JUMP_SLOT:
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+ _dl_exit(1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+void
+_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information(struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/x86_64/resolve.S b/ap/build/uClibc/ldso/ldso/x86_64/resolve.S
new file mode 100644
index 0000000..ac1d182
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/x86_64/resolve.S
@@ -0,0 +1,62 @@
+/*
+ * This function is _not_ called directly. It is jumped to (so no return
+ * address is on the stack) when attempting to use a symbol that has not yet
+ * been resolved. The first time a jump symbol (such as a function call inside
+ * a shared library) is used (before it gets resolved) it will jump here to
+ * _dl_linux_resolve. When we get called the stack looks like this:
+ * reloc_entry
+ * tpnt
+ *
+ * This function saves all the registers, puts a copy of reloc_entry and tpnt
+ * on the stack (as function arguments) then make the function call
+ * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out
+ * where the jump symbol is _really_ supposed to have jumped to and returns
+ * that to us. Once we have that, we overwrite tpnt with this fixed up
+ * address. We then clean up after ourselves, put all the registers back how we
+ * found them, then we jump to where the fixed up address, which is where the
+ * jump symbol that got us here really wanted to jump to in the first place.
+ * found them, then we jump to the fixed up address, which is where the jump
+ * symbol that got us here really wanted to jump to in the first place.
+ * -Erik Andersen
+ */
+
+/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */
+
+.text
+
+.global _dl_linux_resolve
+.type _dl_linux_resolve,%function
+
+_dl_linux_resolve:
+ subq $56,%rsp
+ /* Preserve registers otherwise clobbered. */
+ movq %rax, (%rsp)
+ movq %rcx, 8(%rsp)
+ movq %rdx, 16(%rsp)
+ movq %rsi, 24(%rsp)
+ movq %rdi, 32(%rsp)
+ movq %r8, 40(%rsp)
+ movq %r9, 48(%rsp)
+
+ movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */
+ movq %rsi, %r11 /* Multiply by 24 */
+ addq %r11, %rsi
+ addq %r11, %rsi
+ shlq $3, %rsi
+ movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */
+ call _dl_linux_resolver /* Call resolver. */
+ movq %rax, %r11 /* Save return value */
+
+ /* Get register content back. */
+ movq 48(%rsp), %r9
+ movq 40(%rsp), %r8
+ movq 32(%rsp), %rdi
+ movq 24(%rsp), %rsi
+ movq 16(%rsp), %rdx
+ movq 8(%rsp), %rcx
+ movq (%rsp), %rax
+
+ addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */
+ jmp *%r11 /* Jump to function address. */
+
+.size _dl_linux_resolve,.-_dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/ldso/xtensa/dl-debug.h b/ap/build/uClibc/ldso/ldso/xtensa/dl-debug.h
new file mode 100644
index 0000000..4128d94
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/xtensa/dl-debug.h
@@ -0,0 +1,61 @@
+/* vi: set sw=4 ts=4: */
+/* Xtensa ELF shared library loader suppport
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+static const char * const _dl_reltypes_tab[] =
+{
+ "R_XTENSA_NONE",
+ "R_XTENSA_32",
+ "R_XTENSA_RTLD",
+ "R_XTENSA_GLOB_DAT",
+ "R_XTENSA_JMP_SLOT",
+ "R_XTENSA_RELATIVE",
+ "R_XTENSA_PLT",
+ "R_XTENSA_UNUSED7",
+ "R_XTENSA_OP0",
+ "R_XTENSA_OP1",
+ "R_XTENSA_OP2",
+ "R_XTENSA_ASM_EXPAND",
+ "R_XTENSA_ASM_SIMPLIFY",
+ "R_XTENSA_UNUSED13",
+ "R_XTENSA_UNUSED14",
+ "R_XTENSA_GNU_VTINHERIT",
+ "R_XTENSA_GNU_VTENTRY",
+ "R_XTENSA_DIFF8",
+ "R_XTENSA_DIFF16",
+ "R_XTENSA_DIFF32",
+ "R_XTENSA_SLOT0_OP",
+ "R_XTENSA_SLOT1_OP",
+ "R_XTENSA_SLOT2_OP",
+ "R_XTENSA_SLOT3_OP",
+ "R_XTENSA_SLOT4_OP",
+ "R_XTENSA_SLOT5_OP",
+ "R_XTENSA_SLOT6_OP",
+ "R_XTENSA_SLOT7_OP",
+ "R_XTENSA_SLOT8_OP",
+ "R_XTENSA_SLOT9_OP",
+ "R_XTENSA_SLOT10_OP",
+ "R_XTENSA_SLOT11_OP",
+ "R_XTENSA_SLOT12_OP",
+ "R_XTENSA_SLOT13_OP",
+ "R_XTENSA_SLOT14_OP",
+ "R_XTENSA_SLOT0_ALT",
+ "R_XTENSA_SLOT1_ALT",
+ "R_XTENSA_SLOT2_ALT",
+ "R_XTENSA_SLOT3_ALT",
+ "R_XTENSA_SLOT4_ALT",
+ "R_XTENSA_SLOT5_ALT",
+ "R_XTENSA_SLOT6_ALT",
+ "R_XTENSA_SLOT7_ALT",
+ "R_XTENSA_SLOT8_ALT",
+ "R_XTENSA_SLOT9_ALT",
+ "R_XTENSA_SLOT10_ALT",
+ "R_XTENSA_SLOT11_ALT",
+ "R_XTENSA_SLOT12_ALT",
+ "R_XTENSA_SLOT13_ALT",
+ "R_XTENSA_SLOT14_ALT"
+};
diff --git a/ap/build/uClibc/ldso/ldso/xtensa/dl-startup.h b/ap/build/uClibc/ldso/ldso/xtensa/dl-startup.h
new file mode 100644
index 0000000..8ae9624
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/xtensa/dl-startup.h
@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Xtensa ELF code used by dl-startup.c.
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ * Parts taken from glibc/sysdeps/xtensa/dl-machine.h.
+ */
+
+__asm__ (
+ " .text\n"
+ " .align 4\n"
+ " .global _start\n"
+ " .type _start, @function\n"
+ "_start:\n"
+ " # Compute load offset in a2: the GOT has not yet been relocated\n"
+ " # but the entries for local symbols contain the relative offsets\n"
+ " # and we can explicitly add the load offset in this code.\n"
+ " _call0 0f\n"
+ " .align 4\n"
+ "0: movi a3, _start+3\n"
+ " sub a2, a0, a3\n"
+ " # Make sure a0 is cleared to mark the top of stack.\n"
+ " movi a0, 0\n"
+ " # user_entry_point = _dl_start(pointer to argument block)\n"
+ " movi a4, _dl_start\n"
+ " mov a6, sp\n"
+ " add a4, a4, a2\n"
+ " callx4 a4\n"
+ " # Save user_entry_point so we can jump to it.\n"
+ " mov a3, a6\n"
+ " l32i a7, sp, 0 # load argc\n"
+ " # Load _dl_skip_args into a4.\n"
+ " movi a4, _dl_skip_args\n"
+ " l32i a4, a4, 0\n"
+ " bnez a4, .Lfixup_stack\n"
+ ".Lfixup_stack_ret:\n"
+ " # Pass finalizer (_dl_fini) in a2 to the user entry point.\n"
+ " movi a2, _dl_fini\n"
+ " # Jump to user's entry point (_start).\n"
+ " jx a3\n"
+ ".Lfixup_stack:\n"
+ " # argc -= _dl_skip_args (with argc @ sp+0)\n"
+ " sub a7, a7, a4\n"
+ " s32i a7, sp, 0\n"
+ " # Shift everything by _dl_skip_args.\n"
+ " addi a5, sp, 4 # a5 = destination ptr = argv\n"
+ " add a4, a5, a4 # a4 = source ptr = argv + _dl_skip_args\n"
+ " # Shift argv.\n"
+ "1: l32i a6, a4, 0\n"
+ " addi a4, a4, 4\n"
+ " s32i a6, a5, 0\n"
+ " addi a5, a5, 4\n"
+ " bnez a6, 1b\n"
+ " # Shift envp.\n"
+ "2: l32i a6, a4, 0\n"
+ " addi a4, a4, 4\n"
+ " s32i a6, a5, 0\n"
+ " addi a5, a5, 4\n"
+ " bnez a6, 2b\n"
+ " # Shift auxiliary table.\n"
+ "3: l32i a6, a4, 0\n"
+ " l32i a8, a4, 4\n"
+ " addi a4, a4, 8\n"
+ " s32i a6, a5, 0\n"
+ " s32i a8, a5, 4\n"
+ " addi a5, a5, 8\n"
+ " bnez a6, 3b\n"
+ " j .Lfixup_stack_ret");
+
+/* Get a pointer to the argv value. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+/* Function calls are not safe until the GOT relocations have been done. */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+#define PERFORM_BOOTSTRAP_GOT(tpnt) \
+do { \
+ xtensa_got_location *got_loc; \
+ unsigned long l_addr = tpnt->loadaddr; \
+ Elf32_Word relative_count; \
+ unsigned long rel_addr; \
+ int x; \
+\
+ got_loc = (xtensa_got_location *) \
+ (tpnt->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \
+\
+ for (x = 0; x < tpnt->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) { \
+ Elf32_Addr got_start, got_end; \
+ got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
+ got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
+ & ~(PAGE_SIZE - 1)); \
+ _dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \
+ PROT_READ | PROT_WRITE | PROT_EXEC); \
+ } \
+\
+ /* The following is a stripped down version of the code following \
+ the invocation of PERFORM_BOOTSTRAP_GOT in dl-startup.c. That \
+ code is skipped when PERFORM_BOOTSTRAP_GOT is defined, so it has \
+ to be done here instead. */ \
+ relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; \
+ rel_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; \
+ if (rel_addr) \
+ elf_machine_relative(load_addr, rel_addr, relative_count); \
+} while (0)
diff --git a/ap/build/uClibc/ldso/ldso/xtensa/dl-syscalls.h b/ap/build/uClibc/ldso/ldso/xtensa/dl-syscalls.h
new file mode 100644
index 0000000..f40c4fd
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/xtensa/dl-syscalls.h
@@ -0,0 +1 @@
+/* stub for arch-specific syscall issues */
diff --git a/ap/build/uClibc/ldso/ldso/xtensa/dl-sysdep.h b/ap/build/uClibc/ldso/ldso/xtensa/dl-sysdep.h
new file mode 100644
index 0000000..07b9b79
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/xtensa/dl-sysdep.h
@@ -0,0 +1,130 @@
+/* Machine-dependent ELF dynamic relocation.
+ Parts copied from glibc/sysdeps/xtensa/dl-machine.h
+ Copyright (C) 2001, 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* Define this if the system uses RELOCA. */
+#define ELF_USES_RELOCA
+#include <elf.h>
+#include <link.h>
+
+/* Translate a processor specific dynamic tag to the index
+ in l_info array. */
+#define DT_XTENSA(x) (DT_XTENSA_##x - DT_LOPROC + DT_NUM + OS_NUM)
+
+typedef struct xtensa_got_location_struct {
+ Elf32_Off offset;
+ Elf32_Word length;
+} xtensa_got_location;
+
+/* Initialization sequence for the GOT. */
+#define INIT_GOT(GOT_BASE, MODULE) \
+ do { \
+ xtensa_got_location *got_loc; \
+ Elf32_Addr l_addr = MODULE->loadaddr; \
+ int x; \
+ \
+ got_loc = (xtensa_got_location *) \
+ (MODULE->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \
+ \
+ for (x = 0; x < MODULE->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) \
+ { \
+ Elf32_Addr got_start, got_end; \
+ got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
+ got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
+ & ~(PAGE_SIZE - 1)); \
+ _dl_mprotect ((void *)(got_start + l_addr) , got_end - got_start, \
+ PROT_READ | PROT_WRITE | PROT_EXEC); \
+ } \
+ \
+ /* Fill in first GOT entry according to the ABI. */ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ } while (0)
+
+/* Parse dynamic info */
+#define ARCH_NUM 2
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+ do { \
+ if (dpnt->d_tag == DT_XTENSA_GOT_LOC_OFF) \
+ dynamic[DT_XTENSA (GOT_LOC_OFF)] = dpnt->d_un.d_ptr; \
+ else if (dpnt->d_tag == DT_XTENSA_GOT_LOC_SZ) \
+ dynamic[DT_XTENSA (GOT_LOC_SZ)] = dpnt->d_un.d_val; \
+ } while (0)
+
+/* Here we define the magic numbers that this dynamic loader should accept. */
+#define MAGIC1 EM_XTENSA
+#undef MAGIC2
+
+/* Used for error messages. */
+#define ELF_TARGET "Xtensa"
+
+/* Need bootstrap relocations */
+#define ARCH_NEEDS_BOOTSTRAP_RELOCS
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ undefined references should not be allowed to define the value. */
+#define elf_machine_type_class(type) \
+ (((type) == R_XTENSA_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
+
+/* Return the link-time address of _DYNAMIC. */
+static __always_inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+ /* This function is only used while bootstrapping the runtime linker.
+ The "_DYNAMIC" symbol is always local so its GOT entry will initially
+ contain the link-time address. */
+ return (Elf32_Addr) &_DYNAMIC;
+}
+
+/* Return the run-time load address of the shared object. */
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+ Elf32_Addr addr, tmp;
+
+ /* At this point, the runtime linker is being bootstrapped and the GOT
+ entry used for ".Lhere" will contain the link address. The CALL0 will
+ produce the dynamic address of ".Lhere" + 3. Thus, the end result is
+ equal to "dynamic_address(.Lhere) - link_address(.Lhere)". */
+ __asm__ ("\
+ movi %0, .Lhere\n\
+ mov %1, a0\n\
+.Lhere: _call0 0f\n\
+ .align 4\n\
+0: sub %0, a0, %0\n\
+ mov a0, %1"
+ : "=a" (addr), "=a" (tmp));
+
+ return addr - 3;
+}
+
+static __always_inline void
+elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+{
+ Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr;
+ while (relative_count--)
+ {
+ Elf32_Addr *const reloc_addr = (Elf32_Addr *) (load_off + rpnt->r_offset);
+ *reloc_addr += load_off + rpnt->r_addend;
+ rpnt++;
+ }
+}
diff --git a/ap/build/uClibc/ldso/ldso/xtensa/elfinterp.c b/ap/build/uClibc/ldso/ldso/xtensa/elfinterp.c
new file mode 100644
index 0000000..b4cf975
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/xtensa/elfinterp.c
@@ -0,0 +1,283 @@
+/* vi: set sw=4 ts=4: */
+/* Xtensa ELF shared library loader suppport
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 "ldso.h"
+
+unsigned long
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ char *symname;
+
+ rel_addr = (char *) tpnt->dynamic_info[DT_JMPREL];
+ this_reloc = (ELF_RELOC *) (rel_addr + reloc_entry);
+ symtab_index = ELF_R_SYM (this_reloc->r_info);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+ /* Address of the literal to fix up. */
+ got_addr = (char **) (this_reloc->r_offset + tpnt->loadaddr);
+
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash (symname, &_dl_loaded_modules->symbol_scope, tpnt,
+ ELF_RTYPE_CLASS_PLT, NULL);
+ if (unlikely (!new_addr)) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit (1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_bindings) {
+ _dl_dprintf (_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf (_dl_debug_file, "\n\tpatched %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups)
+ *got_addr = new_addr;
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long) new_addr;
+}
+
+
+static int
+_dl_parse (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ unsigned long rel_addr, unsigned long rel_size,
+ int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+{
+ unsigned int i;
+ char *strtab;
+ ElfW(Sym) *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+
+ /* Parse the relocation information. */
+ rpnt = (ELF_RELOC *) rel_addr;
+ rel_size /= sizeof (ELF_RELOC);
+
+ symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+ int res;
+
+ symtab_index = ELF_R_SYM (rpnt->r_info);
+
+ debug_sym (symtab, strtab, symtab_index);
+ debug_reloc (symtab, strtab, rpnt);
+
+ res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+ if (res == 0)
+ continue;
+
+ _dl_dprintf (2, "\n%s: ", _dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf (2, "symbol '%s': ",
+ strtab + symtab[symtab_index].st_name);
+
+ if (unlikely (res < 0)) {
+ int reloc_type = ELF_R_TYPE (rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf (2, "can't handle reloc type %s\n",
+ _dl_reltypes (reloc_type));
+#else
+ _dl_dprintf (2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit (-res);
+ }
+ if (unlikely (res > 0)) {
+ _dl_dprintf (2, "can't resolve symbol\n");
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ int symtab_index;
+ char *symname;
+ struct symbol_ref sym_ref;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE (rpnt->r_info);
+ symtab_index = ELF_R_SYM (rpnt->r_info);
+ sym_ref.sym = &symtab[symtab_index];
+ sym_ref.tpnt = NULL;
+ symbol_addr = 0;
+ symname = strtab + sym_ref.sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))
+ _dl_find_hash (symname, scope, tpnt,
+ elf_machine_type_class (reloc_type), &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+ if (unlikely (!symbol_addr &&
+ ELF_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) {
+ _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+ _dl_progname, symname);
+ _dl_exit (1);
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_XTENSA_NONE:
+ break;
+
+ case R_XTENSA_GLOB_DAT:
+ case R_XTENSA_JMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ case R_XTENSA_RTLD:
+ if (rpnt->r_addend == 1) {
+ /* Grab the function pointer stashed at the beginning of the
+ GOT by the GOT_INIT function. */
+ *reloc_addr = *(ElfW(Addr) *) tpnt->dynamic_info[DT_PLTGOT];
+ } else if (rpnt->r_addend == 2) {
+ /* Store the link map for the object. */
+ *reloc_addr = (ElfW(Addr)) tpnt;
+ } else {
+ _dl_exit (1);
+ }
+ break;
+
+ case R_XTENSA_RELATIVE:
+ *reloc_addr += tpnt->loadaddr + rpnt->r_addend;
+ break;
+
+ default:
+ return -1; /* Calls _dl_exit(1). */
+ }
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+
+ return 0;
+}
+
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+{
+ int reloc_type;
+ ElfW(Addr) *reloc_addr;
+#if defined (__SUPPORT_LD_DEBUG__)
+ ElfW(Addr) old_val;
+#endif
+
+ reloc_addr = (ElfW(Addr) *) (tpnt->loadaddr + rpnt->r_offset);
+ reloc_type = ELF_R_TYPE (rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ old_val = *reloc_addr;
+#endif
+
+ switch (reloc_type) {
+ case R_XTENSA_JMP_SLOT:
+ /* Perform a RELATIVE reloc on the GOT entry that transfers
+ to the stub function. */
+ *reloc_addr += tpnt->loadaddr;
+ break;
+ case R_XTENSA_NONE:
+ break;
+ default:
+ _dl_exit (1);
+ }
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
+ old_val, *reloc_addr, reloc_addr);
+#endif
+ return 0;
+
+}
+
+void
+_dl_parse_lazy_relocation_information (struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ (void) _dl_parse (rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information (struct dyn_elf *rpnt,
+ struct r_scope_elem *scope,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+{
+ return _dl_parse (rpnt->dyn, scope, rel_addr, rel_size,
+ _dl_do_reloc);
+}
diff --git a/ap/build/uClibc/ldso/ldso/xtensa/resolve.S b/ap/build/uClibc/ldso/ldso/xtensa/resolve.S
new file mode 100644
index 0000000..902cd82
--- /dev/null
+++ b/ap/build/uClibc/ldso/ldso/xtensa/resolve.S
@@ -0,0 +1,57 @@
+/* Xtensa dynamic resolver.
+ Parts copied from glibc/sysdeps/xtensa/dl-trampoline.S
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#define MIN_FRAME_SIZE 32
+
+#ifdef __XTENSA_EB__
+#define XTENSA_IMM12_FLD_OFFSET 8
+#else /* __XTENSA_EL__ */
+#define XTENSA_IMM12_FLD_OFFSET 12
+#endif /* __XTENSA_EL__ */
+
+ .text
+ .align 4
+ .global _dl_linux_resolve
+ .type _dl_linux_resolve, @function
+_dl_linux_resolve:
+ /* Fix up the high 2 bits of the return address. */
+ movi a13, 0f
+ slli a12, a0, 2
+0: extui a13, a13, 30, 2
+ ssai 2
+ src a12, a13, a12
+
+ /* Call the fixup function. */
+ movi a8, _dl_linux_resolver
+ callx8 a8
+
+ /* Extract the target's frame size from the ENTRY instruction. */
+ l32i a11, a10, 0
+ extui a11, a11, XTENSA_IMM12_FLD_OFFSET, 12
+ slli a11, a11, 3
+
+ addi a11, a11, -MIN_FRAME_SIZE
+ sub a11, sp, a11
+ movsp sp, a11
+
+ /* Jump to the next instruction past the ENTRY. */
+ addi a10, a10, 3
+ jx a10
+ .size _dl_linux_resolve, . - _dl_linux_resolve
diff --git a/ap/build/uClibc/ldso/libdl/Makefile b/ap/build/uClibc/ldso/libdl/Makefile
new file mode 100644
index 0000000..f910021
--- /dev/null
+++ b/ap/build/uClibc/ldso/libdl/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../
+top_builddir=../../
+include $(top_builddir)Rules.mak
+all: libs
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/ap/build/uClibc/ldso/libdl/Makefile.in b/ap/build/uClibc/ldso/libdl/Makefile.in
new file mode 100644
index 0000000..be236c8
--- /dev/null
+++ b/ap/build/uClibc/ldso/libdl/Makefile.in
@@ -0,0 +1,64 @@
+# Makefile.in for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += ldso/libdl
+
+CFLAGS-libdl := -DNOT_IN_libc -DIS_IN_libdl $(SSP_ALL_CFLAGS)
+
+CFLAGS-libdl += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso
+
+CFLAGS-libdl += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\"
+
+ifeq ($(SUPPORT_LD_DEBUG),y)
+CFLAGS-libdl += -D__SUPPORT_LD_DEBUG__
+endif
+
+CFLAGS-libdl.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\"
+
+LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-libdl.so := -Wl,--dsbt-index=3
+LDFLAGS-libdl.so := $(LDFLAGS)
+
+ifeq ($(LDSO_NO_CLEANUP),)
+LDFLAGS-libdl.so += -Wl,-fini,dl_cleanup
+endif
+
+LIBS-libdl.so := $(LIBS) $(ldso)
+
+libdl_FULL_NAME := libdl-$(VERSION).so
+
+libdl_DIR := $(top_srcdir)ldso/libdl
+libdl_OUT := $(top_builddir)ldso/libdl
+
+libdl_SRC := $(libdl_DIR)/libdl.c
+libdl_OBJ := $(patsubst $(libdl_DIR)/%.c,$(libdl_OUT)/%.o,$(libdl_SRC))
+
+resolve := $(top_builddir)ldso/ldso/$(TARGET_ARCH)/resolve.o
+
+libdl-a-y := $(libdl_OBJ) $(resolve)
+ifeq ($(DOPIC),y)
+libdl-a-y := $(libdl-a-y:.o=.os)
+endif
+libdl-so-y := $(libdl_OUT)/libdl.oS
+
+lib-a-$(HAVE_SHARED) += $(top_builddir)lib/libdl.a
+lib-so-y += $(top_builddir)lib/libdl.so
+objclean-y += CLEAN_ldso/libdl
+
+$(top_builddir)lib/libdl.so: $(libdl_OUT)/libdl_so.a $(libc.depend)
+ $(call link.so,$(libdl_FULL_NAME),$(ABI_VERSION))
+
+$(libdl_OUT)/libdl_so.a: $(libdl-so-y)
+ $(Q)$(RM) $@
+ $(do_ar)
+
+$(top_builddir)lib/libdl.a: $(libdl-a-y)
+ $(Q)$(INSTALL) -d $(dir $@)
+ $(Q)$(RM) $@
+ $(do_ar)
+
+CLEAN_ldso/libdl:
+ $(do_rm) $(addprefix $(libdl_OUT)/*., o os oS a)
diff --git a/ap/build/uClibc/ldso/libdl/libdl.c b/ap/build/uClibc/ldso/libdl/libdl.c
new file mode 100644
index 0000000..51bcf7d
--- /dev/null
+++ b/ap/build/uClibc/ldso/libdl/libdl.c
@@ -0,0 +1,1235 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2000-2006 by Erik Andersen <andersen@uclibc.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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 <ldso.h>
+#include <stdio.h>
+#include <string.h> /* Needed for 'strstr' prototype' */
+#include <stdbool.h>
+#include <bits/uClibc_mutex.h>
+
+#ifdef __UCLIBC_HAS_TLS__
+#include <tls.h>
+#endif
+
+#if defined(USE_TLS) && USE_TLS
+#include <ldsodefs.h>
+extern void _dl_add_to_slotinfo(struct link_map *l);
+#endif
+
+/* TODO: get rid of global lock and use more finegrained locking, or
+ * perhaps RCU for the global structures */
+__UCLIBC_MUTEX_STATIC(_dl_mutex, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+#ifdef SHARED
+# if defined(USE_TLS) && USE_TLS
+# include <dl-tls.h>
+extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid);
+# endif
+
+/* When libdl is loaded as a shared library, we need to load in
+ * and use a pile of symbols from ldso... */
+#include <dl-elf.h>
+#if 0
+extern struct elf_resolve * _dl_load_shared_library(unsigned, struct dyn_elf **,
+ struct elf_resolve *, char *, int);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);
+extern void _dl_protect_relro(struct elf_resolve * tpnt);
+#endif
+extern int _dl_errno;
+extern struct dyn_elf *_dl_symbol_tables;
+extern struct dyn_elf *_dl_handles;
+extern struct elf_resolve *_dl_loaded_modules;
+extern void _dl_free (void *__ptr);
+extern struct r_debug *_dl_debug_addr;
+extern unsigned long _dl_error_number;
+extern void *(*_dl_malloc_function)(size_t);
+extern void (*_dl_free_function) (void *p);
+extern void _dl_run_init_array(struct elf_resolve *);
+extern void _dl_run_fini_array(struct elf_resolve *);
+#ifdef __LDSO_CACHE_SUPPORT__
+int _dl_map_cache(void);
+int _dl_unmap_cache(void);
+#endif
+#ifdef __mips__
+extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
+#endif
+#ifdef __SUPPORT_LD_DEBUG__
+extern char *_dl_debug;
+#endif
+
+#else /* !SHARED */
+
+#define _dl_malloc malloc
+#define _dl_free free
+
+/* When libdl is linked as a static library, we need to replace all
+ * the symbols that otherwise would have been loaded in from ldso... */
+
+#ifdef __SUPPORT_LD_DEBUG__
+char *_dl_debug = NULL;
+char *_dl_debug_symbols = NULL;
+char *_dl_debug_move = NULL;
+char *_dl_debug_reloc = NULL;
+char *_dl_debug_detail = NULL;
+char *_dl_debug_nofixups = NULL;
+char *_dl_debug_bindings = NULL;
+int _dl_debug_file = 2;
+#endif
+const char *_dl_progname = ""; /* Program name */
+void *(*_dl_malloc_function)(size_t);
+void (*_dl_free_function) (void *p);
+#ifdef __LDSO_LD_LIBRARY_PATH__
+char *_dl_library_path = NULL; /* Where we look for libraries */
+#endif
+int _dl_errno = 0; /* We can't use the real errno in ldso */
+size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */
+/* This global variable is also to communicate with debuggers such as gdb. */
+struct r_debug *_dl_debug_addr = NULL;
+
+#include "../ldso/dl-array.c"
+#include "../ldso/dl-debug.c"
+
+
+# if defined(USE_TLS) && USE_TLS
+/*
+ * Giving this initialized value preallocates some surplus bytes in the
+ * static TLS area, see __libc_setup_tls (libc-tls.c).
+ */
+size_t _dl_tls_static_size = 2048;
+# endif
+#include LDSO_ELFINTERP
+#include "../ldso/dl-hash.c"
+#define _dl_trace_loaded_objects 0
+#include "../ldso/dl-elf.c"
+#endif /* SHARED */
+
+#ifdef __SUPPORT_LD_DEBUG__
+# define _dl_if_debug_print(fmt, args...) \
+ do { \
+ if (_dl_debug) \
+ fprintf(stderr, "%s():%i: " fmt, __func__, __LINE__, ## args); \
+ } while (0)
+#else
+# define _dl_if_debug_print(fmt, args...)
+#endif
+
+static int do_dlclose(void *, int need_fini);
+
+
+static const char *const dl_error_names[] = {
+ "",
+ "File not found",
+ "Unable to open /dev/zero",
+ "Not an ELF file",
+#if defined (__i386__)
+ "Not i386 binary",
+#elif defined (__sparc__)
+ "Not sparc binary",
+#elif defined (__mc68000__)
+ "Not m68k binary",
+#else
+ "Unrecognized binary type",
+#endif
+ "Not an ELF shared library",
+ "Unable to mmap file",
+ "No dynamic section",
+ "Library contains unsupported TLS",
+#ifdef ELF_USES_RELOCA
+ "Unable to process REL relocs",
+#else
+ "Unable to process RELA relocs",
+#endif
+ "Bad handle",
+ "Unable to resolve symbol"
+};
+
+
+#if defined(USE_TLS) && USE_TLS
+#ifdef SHARED
+/*
+ * Systems which do not have tls_index also probably have to define
+ * DONT_USE_TLS_INDEX.
+ */
+
+# ifndef __TLS_GET_ADDR
+# define __TLS_GET_ADDR __tls_get_addr
+# endif
+
+/*
+ * Return the symbol address given the map of the module it is in and
+ * the symbol record. This is used in dl-sym.c.
+ */
+static void *
+internal_function
+_dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value)
+{
+# ifndef DONT_USE_TLS_INDEX
+ tls_index tmp =
+ {
+ .ti_module = map->l_tls_modid,
+ .ti_offset = st_value
+ };
+
+ return __TLS_GET_ADDR (&tmp);
+# else
+ return __TLS_GET_ADDR (map->l_tls_modid, st_value);
+# endif
+}
+#endif
+
+/* Returns true when a non-empty entry was found. */
+static bool
+remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
+ bool should_be_there)
+{
+ if (idx - disp >= listp->len) {
+ if (listp->next == NULL) {
+ /*
+ * The index is not actually valid in the slotinfo list,
+ * because this object was closed before it was fully set
+ * up due to some error.
+ */
+ _dl_assert(!should_be_there);
+ } else {
+ if (remove_slotinfo(idx, listp->next, disp + listp->len,
+ should_be_there))
+ return true;
+
+ /*
+ * No non-empty entry. Search from the end of this element's
+ * slotinfo array.
+ */
+ idx = disp + listp->len;
+ }
+ } else {
+ struct link_map *old_map = listp->slotinfo[idx - disp].map;
+
+ /*
+ * The entry might still be in its unused state if we are
+ * closing an object that wasn't fully set up.
+ */
+ if (__builtin_expect(old_map != NULL, 1)) {
+ _dl_assert(old_map->l_tls_modid == idx);
+
+ /* Mark the entry as unused. */
+ listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1;
+ listp->slotinfo[idx - disp].map = NULL;
+ }
+
+ /*
+ * If this is not the last currently used entry no need to
+ * look further.
+ */
+ if (idx != _dl_tls_max_dtv_idx)
+ return true;
+ }
+
+ while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) {
+ --idx;
+
+ if (listp->slotinfo[idx - disp].map != NULL) {
+ /* Found a new last used index. */
+ _dl_tls_max_dtv_idx = idx;
+ return true;
+ }
+ }
+
+ /* No non-entry in this list element. */
+ return false;
+}
+#endif
+
+#ifndef __LDSO_NO_CLEANUP__
+void dl_cleanup(void) __attribute__ ((destructor));
+void dl_cleanup(void)
+{
+ struct dyn_elf *h, *n;
+
+ for (h = _dl_handles; h; h = n) {
+ n = h->next_handle;
+ do_dlclose(h, 1);
+ }
+}
+#endif
+
+static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
+ struct elf_resolve *map)
+{
+ struct elf_resolve **p = list;
+ struct init_fini_list *q;
+
+ *p++ = map;
+ map->init_flag |= DL_RESERVED;
+ if (map->init_fini)
+ for (q = map->init_fini; q; q = q->next)
+ if (! (q->tpnt->init_flag & DL_RESERVED))
+ p += _dl_build_local_scope (p, q->tpnt);
+ return p - list;
+}
+
+static void *do_dlopen(const char *libname, int flag)
+{
+ struct elf_resolve *tpnt, *tfrom;
+ struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
+ ElfW(Addr) from;
+ struct elf_resolve *tpnt1;
+ void (*dl_brk) (void);
+ int now_flag;
+ struct init_fini_list *tmp, *runp, *runp2, *dep_list;
+ unsigned int nlist, i;
+ struct elf_resolve **init_fini_list;
+ static bool _dl_init;
+ struct elf_resolve **local_scope;
+ struct r_scope_elem *ls;
+#if defined(USE_TLS) && USE_TLS
+ bool any_tls = false;
+#endif
+
+ /* A bit of sanity checking... */
+ if (!(flag & (RTLD_LAZY|RTLD_NOW|RTLD_NOLOAD))) {
+ _dl_error_number = LD_BAD_HANDLE;
+ return NULL;
+ }
+
+ from = (ElfW(Addr)) __builtin_return_address(0);
+
+ if (!_dl_init) {
+ _dl_init = true;
+ _dl_malloc_function = malloc;
+ _dl_free_function = free;
+ }
+ /* Cover the trivial case first */
+ if (!libname)
+ return _dl_symbol_tables;
+
+#ifndef SHARED
+# ifdef __SUPPORT_LD_DEBUG__
+ _dl_debug = getenv("LD_DEBUG");
+ if (_dl_debug) {
+ if (_dl_strstr(_dl_debug, "all")) {
+ _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
+ = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
+ } else {
+ _dl_debug_detail = strstr(_dl_debug, "detail");
+ _dl_debug_move = strstr(_dl_debug, "move");
+ _dl_debug_symbols = strstr(_dl_debug, "sym");
+ _dl_debug_reloc = strstr(_dl_debug, "reloc");
+ _dl_debug_nofixups = strstr(_dl_debug, "nofix");
+ _dl_debug_bindings = strstr(_dl_debug, "bind");
+ }
+ }
+# endif
+#endif
+
+ _dl_map_cache();
+
+ /*
+ * Try and locate the module we were called from - we
+ * need this so that we get the correct RPATH/RUNPATH. Note that
+ * this is the current behavior under Solaris, but the
+ * ABI+ specifies that we should only use the RPATH from
+ * the application. Thus this may go away at some time
+ * in the future.
+ */
+ {
+ struct dyn_elf *dpnt;
+ tfrom = NULL;
+ for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
+ tpnt = dpnt->dyn;
+ if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom))
+ tfrom = tpnt;
+ }
+ }
+ for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next)
+ continue;
+
+ relro_ptr = rpnt;
+ now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
+ if (getenv("LD_BIND_NOW"))
+ now_flag = RTLD_NOW;
+
+#if !defined SHARED && defined __LDSO_LIBRARY_PATH__
+ /* When statically linked, the _dl_library_path is not yet initialized */
+ _dl_library_path = getenv("LD_LIBRARY_PATH");
+#endif
+
+ /* Try to load the specified library */
+ _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
+ (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
+
+ tpnt = _dl_load_shared_library((flag & RTLD_NOLOAD) ? DL_RESOLVE_NOLOAD : 0,
+ &rpnt, tfrom, (char*)libname, 0);
+ if (tpnt == NULL) {
+ _dl_unmap_cache();
+ return NULL;
+ }
+ dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
+ _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
+ dyn_chain->dyn = tpnt;
+ tpnt->rtld_flags |= (flag & RTLD_GLOBAL);
+
+ dyn_chain->next_handle = _dl_handles;
+ _dl_handles = dyn_ptr = dyn_chain;
+
+ if (tpnt->usage_count > 1) {
+ _dl_if_debug_print("Lib: %s already opened\n", libname);
+ /* see if there is a handle from a earlier dlopen */
+ for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) {
+ if (handle->dyn == tpnt) {
+ dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
+ dyn_chain->init_fini.nlist = handle->init_fini.nlist;
+ for (i = 0; i < dyn_chain->init_fini.nlist; i++)
+ dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
+ dyn_chain->next = handle->next;
+ break;
+ }
+ }
+ return dyn_chain;
+ }
+
+ tpnt->init_flag |= DL_OPENED;
+
+ _dl_if_debug_print("Looking for needed libraries\n");
+ nlist = 0;
+ runp = alloca(sizeof(*runp));
+ runp->tpnt = tpnt;
+ runp->next = NULL;
+ dep_list = runp2 = runp;
+ for (; runp; runp = runp->next) {
+ ElfW(Dyn) *dpnt;
+ char *lpntstr;
+
+ nlist++;
+ runp->tpnt->init_fini = NULL; /* clear any previous dependcies */
+ for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) {
+ if (dpnt->d_tag == DT_NEEDED) {
+ lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
+ dpnt->d_un.d_val);
+ _dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
+ lpntstr, runp->tpnt->libname);
+ tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
+ if (!tpnt1)
+ goto oops;
+
+ tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
+
+ /* This list is for dlsym() and relocation */
+ dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
+ _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
+ dyn_ptr = dyn_ptr->next;
+ dyn_ptr->dyn = tpnt1;
+ /* Used to record RTLD_LOCAL scope */
+ tmp = alloca(sizeof(struct init_fini_list));
+ tmp->tpnt = tpnt1;
+ tmp->next = runp->tpnt->init_fini;
+ runp->tpnt->init_fini = tmp;
+
+ for (tmp=dep_list; tmp; tmp = tmp->next) {
+ if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
+ _dl_if_debug_print("Circular dependency, skipping '%s',\n",
+ tmp->tpnt->libname);
+ tpnt1->usage_count--;
+ break;
+ }
+ }
+ if (!tmp) { /* Don't add if circular dependency detected */
+ runp2->next = alloca(sizeof(*runp));
+ runp2 = runp2->next;
+ runp2->tpnt = tpnt1;
+ runp2->next = NULL;
+ }
+ }
+ }
+ }
+ init_fini_list = malloc(nlist * sizeof(struct elf_resolve *));
+ dyn_chain->init_fini.init_fini = init_fini_list;
+ dyn_chain->init_fini.nlist = nlist;
+ i = 0;
+ for (runp2 = dep_list; runp2; runp2 = runp2->next) {
+ init_fini_list[i++] = runp2->tpnt;
+ for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) {
+ if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) {
+ tmp = malloc(sizeof(struct init_fini_list));
+ tmp->tpnt = runp->tpnt;
+ tmp->next = runp2->tpnt->rtld_local;
+ runp2->tpnt->rtld_local = tmp;
+ }
+ }
+
+ }
+ /* Build the local scope for the dynamically loaded modules. */
+ local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */
+ for (i = 0; i < nlist; i++)
+ if (init_fini_list[i]->symbol_scope.r_nlist == 0) {
+ int k, cnt;
+ cnt = _dl_build_local_scope(local_scope, init_fini_list[i]);
+ init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+ init_fini_list[i]->symbol_scope.r_nlist = cnt;
+ _dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope,
+ cnt * sizeof (struct elf_resolve *));
+ /* Restoring the init_flag.*/
+ for (k = 0; k < nlist; k++)
+ init_fini_list[k]->init_flag &= ~DL_RESERVED;
+ }
+
+ _dl_free(local_scope);
+
+ /* Sort the INIT/FINI list in dependency order. */
+ for (runp2 = dep_list; runp2; runp2 = runp2->next) {
+ unsigned int j, k;
+ for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
+ /* Empty */;
+ for (k = j + 1; k < nlist; ++k) {
+ struct init_fini_list *ele = init_fini_list[k]->init_fini;
+
+ for (; ele; ele = ele->next) {
+ if (ele->tpnt == runp2->tpnt) {
+ struct elf_resolve *here = init_fini_list[k];
+ _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
+ for (i = (k - j); i; --i)
+ init_fini_list[i+j] = init_fini_list[i+j-1];
+ init_fini_list[j] = here;
+ ++j;
+ break;
+ }
+ }
+ }
+ }
+#ifdef __SUPPORT_LD_DEBUG__
+ if (_dl_debug) {
+ fprintf(stderr, "\nINIT/FINI order and dependencies:\n");
+ for (i = 0; i < nlist; i++) {
+ fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname);
+ runp = init_fini_list[i]->init_fini;
+ for (; runp; runp = runp->next)
+ fprintf(stderr, " %s ", runp->tpnt->libname);
+ fprintf(stderr, "\n");
+ }
+ }
+#endif
+
+ _dl_if_debug_print("Beginning dlopen relocation fixups\n");
+ /*
+ * OK, now all of the kids are tucked into bed in their proper addresses.
+ * Now we go through and look for REL and RELA records that indicate fixups
+ * to the GOT tables. We need to do this in reverse order so that COPY
+ * directives work correctly */
+
+ /* Get the tail of the list */
+ for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
+
+ /* Extend the global scope by adding the local scope of the dlopened DSO. */
+ ls->next = &dyn_chain->dyn->symbol_scope;
+#ifdef __mips__
+ /*
+ * Relocation of the GOT entries for MIPS have to be done
+ * after all the libraries have been loaded.
+ */
+ _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
+#endif
+
+ if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
+ goto oops;
+
+ if (relro_ptr) {
+ for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
+ if (rpnt->dyn->relro_size)
+ _dl_protect_relro(rpnt->dyn);
+ }
+ }
+ /* TODO: Should we set the protections of all pages back to R/O now ? */
+
+
+#if defined(USE_TLS) && USE_TLS
+
+ for (i=0; i < nlist; i++) {
+ struct elf_resolve *tmp_tpnt = init_fini_list[i];
+ /* Only add TLS memory if this object is loaded now and
+ therefore is not yet initialized. */
+
+ if (!(tmp_tpnt->init_flag & INIT_FUNCS_CALLED)
+ /* Only if the module defines thread local data. */
+ && __builtin_expect (tmp_tpnt->l_tls_blocksize > 0, 0)) {
+
+ /* Now that we know the object is loaded successfully add
+ modules containing TLS data to the slot info table. We
+ might have to increase its size. */
+ _dl_add_to_slotinfo ((struct link_map*)tmp_tpnt);
+
+ /* It is the case in which we couldn't perform TLS static
+ initialization at relocation time, and we delayed it until
+ the relocation has been completed. */
+
+ if (tmp_tpnt->l_need_tls_init) {
+ tmp_tpnt->l_need_tls_init = 0;
+# ifdef SHARED
+ /* Update the slot information data for at least the
+ generation of the DSO we are allocating data for. */
+ _dl_update_slotinfo (tmp_tpnt->l_tls_modid);
+# endif
+
+ _dl_init_static_tls((struct link_map*)tmp_tpnt);
+ _dl_assert (tmp_tpnt->l_need_tls_init == 0);
+ }
+
+ /* We have to bump the generation counter. */
+ any_tls = true;
+ }
+ }
+
+ /* Bump the generation number if necessary. */
+ if (any_tls && __builtin_expect (++_dl_tls_generation == 0, 0)) {
+ _dl_debug_early("TLS generation counter wrapped! Please report this.");
+ _dl_exit(30);
+ }
+
+#endif
+
+ /* Notify the debugger we have added some objects. */
+ if (_dl_debug_addr) {
+ dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
+ if (dl_brk != NULL) {
+ _dl_debug_addr->r_state = RT_ADD;
+ (*dl_brk) ();
+
+ _dl_debug_addr->r_state = RT_CONSISTENT;
+ (*dl_brk) ();
+ }
+ }
+
+ /* Run the ctors and setup the dtors */
+ for (i = nlist; i; --i) {
+ tpnt = init_fini_list[i-1];
+ if (tpnt->init_flag & INIT_FUNCS_CALLED)
+ continue;
+ tpnt->init_flag |= INIT_FUNCS_CALLED;
+
+ if (tpnt->dynamic_info[DT_INIT]) {
+ void (*dl_elf_func) (void);
+ dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
+ if (dl_elf_func) {
+ _dl_if_debug_print("running ctors for library %s at '%p'\n",
+ tpnt->libname, dl_elf_func);
+ DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
+ }
+ }
+
+ _dl_run_init_array(tpnt);
+ }
+
+ _dl_unmap_cache();
+ return (void *) dyn_chain;
+
+oops:
+ /* Something went wrong. Clean up and return NULL. */
+ _dl_unmap_cache();
+ do_dlclose(dyn_chain, 0);
+ return NULL;
+}
+
+void *dlopen(const char *libname, int flag)
+{
+ void *ret;
+
+ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+ ret = do_dlopen(libname, flag);
+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+ return ret;
+}
+
+static void *do_dlsym(void *vhandle, const char *name, void *caller_address)
+{
+ struct elf_resolve *tpnt, *tfrom;
+ struct dyn_elf *handle;
+ ElfW(Addr) from;
+ struct dyn_elf *rpnt;
+ void *ret;
+ struct symbol_ref sym_ref = { NULL, NULL };
+ /* Nastiness to support underscore prefixes. */
+#ifdef __UCLIBC_UNDERSCORES__
+ char tmp_buf[80];
+ char *name2 = tmp_buf;
+ size_t nlen = strlen (name) + 1;
+ if (nlen + 1 > sizeof (tmp_buf))
+ name2 = malloc (nlen + 1);
+ if (name2 == 0) {
+ _dl_error_number = LD_ERROR_MMAP_FAILED;
+ return 0;
+ }
+ name2[0] = '_';
+ memcpy (name2 + 1, name, nlen);
+#else
+ const char *name2 = name;
+#endif
+ handle = (struct dyn_elf *) vhandle;
+
+ /* First of all verify that we have a real handle
+ of some kind. Return NULL if not a valid handle. */
+
+ if (handle == NULL)
+ handle = _dl_symbol_tables;
+ else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
+ for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
+ if (rpnt == handle)
+ break;
+ if (!rpnt) {
+ _dl_error_number = LD_BAD_HANDLE;
+ ret = NULL;
+ goto out;
+ }
+ } else if (handle == RTLD_NEXT) {
+ /*
+ * Try and locate the module we were called from - we
+ * need this so that we know where to start searching
+ * from. We never pass RTLD_NEXT down into the actual
+ * dynamic loader itself, as it doesn't know
+ * how to properly treat it.
+ */
+ from = (ElfW(Addr)) caller_address;
+
+ tfrom = NULL;
+ for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
+ tpnt = rpnt->dyn;
+ if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) {
+ tfrom = tpnt;
+ handle = rpnt->next;
+ }
+ }
+ }
+ tpnt = NULL;
+ if (handle == _dl_symbol_tables)
+ tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
+ ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, &sym_ref);
+
+#if defined(USE_TLS) && USE_TLS && defined SHARED
+ if (sym_ref.sym && (ELF_ST_TYPE(sym_ref.sym->st_info) == STT_TLS) && (sym_ref.tpnt)) {
+ /* The found symbol is a thread-local storage variable.
+ Return its address for the current thread. */
+ ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
+ }
+#endif
+
+ /*
+ * Nothing found.
+ */
+ if (!ret)
+ _dl_error_number = LD_NO_SYMBOL;
+out:
+#ifdef __UCLIBC_UNDERSCORES__
+ if (name2 != tmp_buf)
+ free (name2);
+#endif
+ return ret;
+}
+
+void *dlsym(void *vhandle, const char *name)
+{
+ void *ret;
+
+ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+ ret = do_dlsym(vhandle, name, __builtin_return_address(0));
+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+ return ret;
+}
+
+#if 0
+void *dlvsym(void *vhandle, const char *name, const char *version)
+{
+ return dlsym(vhandle, name);
+}
+#endif
+
+static int do_dlclose(void *vhandle, int need_fini)
+{
+ struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
+ struct init_fini_list *runp, *tmp;
+ ElfW(Phdr) *ppnt;
+ struct elf_resolve *tpnt, *run_tpnt;
+ int (*dl_elf_fini) (void);
+ void (*dl_brk) (void);
+ struct dyn_elf *handle;
+ unsigned int end = 0, start = 0xffffffff;
+ unsigned int i, j;
+ struct r_scope_elem *ls, *ls_next = NULL;
+ struct elf_resolve **handle_rlist;
+
+#if defined(USE_TLS) && USE_TLS
+ bool any_tls = false;
+ size_t tls_free_start = NO_TLS_OFFSET;
+ size_t tls_free_end = NO_TLS_OFFSET;
+ struct link_map *tls_lmap;
+#endif
+
+ handle = (struct dyn_elf *) vhandle;
+ if (handle == _dl_symbol_tables)
+ return 0;
+ rpnt1 = NULL;
+ for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
+ if (rpnt == handle)
+ break;
+ rpnt1 = rpnt;
+ }
+
+ if (!rpnt) {
+ _dl_error_number = LD_BAD_HANDLE;
+ return 1;
+ }
+ if (rpnt1)
+ rpnt1->next_handle = rpnt->next_handle;
+ else
+ _dl_handles = rpnt->next_handle;
+ _dl_if_debug_print("%s: usage count: %d\n",
+ handle->dyn->libname, handle->dyn->usage_count);
+ if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
+ handle->dyn->usage_count--;
+ free(handle);
+ return 0;
+ }
+
+ /* Store the handle's local scope array for later removal */
+ handle_rlist = handle->dyn->symbol_scope.r_list;
+
+ /* Store references to the local scope entries for later removal */
+ for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next)
+ if (ls->next->r_list[0] == handle->dyn) {
+ break;
+ }
+ /* ls points to the previous local symbol scope */
+ if(ls && ls->next)
+ ls_next = ls->next->next;
+
+ /* OK, this is a valid handle - now close out the file */
+ for (j = 0; j < handle->init_fini.nlist; ++j) {
+ tpnt = handle->init_fini.init_fini[j];
+ tpnt->usage_count--;
+ if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) {
+ if ((tpnt->dynamic_info[DT_FINI]
+ || tpnt->dynamic_info[DT_FINI_ARRAY])
+ && need_fini
+ && !(tpnt->init_flag & FINI_FUNCS_CALLED)
+ ) {
+ tpnt->init_flag |= FINI_FUNCS_CALLED;
+ _dl_run_fini_array(tpnt);
+
+ if (tpnt->dynamic_info[DT_FINI]) {
+ dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
+ _dl_if_debug_print("running dtors for library %s at '%p'\n",
+ tpnt->libname, dl_elf_fini);
+ DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void)));
+ }
+ }
+
+ _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
+ end = 0;
+ for (i = 0, ppnt = tpnt->ppnt;
+ i < tpnt->n_phent; ppnt++, i++) {
+ if (ppnt->p_type != PT_LOAD)
+ continue;
+ if (ppnt->p_vaddr < start)
+ start = ppnt->p_vaddr;
+ if (end < ppnt->p_vaddr + ppnt->p_memsz)
+ end = ppnt->p_vaddr + ppnt->p_memsz;
+ }
+
+#if defined(USE_TLS) && USE_TLS
+ /* Do the cast to make things easy. */
+ tls_lmap = (struct link_map *) tpnt;
+
+ /* Remove the object from the dtv slotinfo array if it uses TLS. */
+ if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) {
+ any_tls = true;
+
+ if (_dl_tls_dtv_slotinfo_list != NULL
+ && ! remove_slotinfo (tls_lmap->l_tls_modid,
+ _dl_tls_dtv_slotinfo_list, 0,
+ (tpnt->init_flag & INIT_FUNCS_CALLED)))
+ /* All dynamically loaded modules with TLS are unloaded. */
+ _dl_tls_max_dtv_idx = _dl_tls_static_nelem;
+
+ if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) {
+ /*
+ * Collect a contiguous chunk built from the objects in
+ * this search list, going in either direction. When the
+ * whole chunk is at the end of the used area then we can
+ * reclaim it.
+ */
+# if defined(TLS_TCB_AT_TP)
+ if (tls_free_start == NO_TLS_OFFSET
+ || (size_t) tls_lmap->l_tls_offset == tls_free_start) {
+ /* Extend the contiguous chunk being reclaimed. */
+ tls_free_start
+ = tls_lmap->l_tls_offset -
+ tls_lmap->l_tls_blocksize;
+
+ if (tls_free_end == NO_TLS_OFFSET)
+ tls_free_end = tls_lmap->l_tls_offset;
+ } else if (tls_lmap->l_tls_offset - tls_lmap->l_tls_blocksize
+ == tls_free_end)
+ /* Extend the chunk backwards. */
+ tls_free_end = tls_lmap->l_tls_offset;
+ else {
+ /*
+ * This isn't contiguous with the last chunk freed.
+ * One of them will be leaked unless we can free
+ * one block right away.
+ */
+ if (tls_free_end == _dl_tls_static_used) {
+ _dl_tls_static_used = tls_free_start;
+ tls_free_end = tls_lmap->l_tls_offset;
+ tls_free_start
+ = tls_free_end - tls_lmap->l_tls_blocksize;
+ } else if ((size_t) tls_lmap->l_tls_offset
+ == _dl_tls_static_used)
+ _dl_tls_static_used = tls_lmap->l_tls_offset -
+ tls_lmap->l_tls_blocksize;
+ else if (tls_free_end < (size_t) tls_lmap->l_tls_offset) {
+ /*
+ * We pick the later block. It has a chance
+ * to be freed.
+ */
+ tls_free_end = tls_lmap->l_tls_offset;
+ tls_free_start = tls_free_end -
+ tls_lmap->l_tls_blocksize;
+ }
+ }
+# elif defined(TLS_DTV_AT_TP)
+ if ((size_t) tls_lmap->l_tls_offset == tls_free_end)
+ /* Extend the contiguous chunk being reclaimed. */
+ tls_free_end -= tls_lmap->l_tls_blocksize;
+ else if (tls_lmap->l_tls_offset + tls_lmap->l_tls_blocksize
+ == tls_free_start)
+ /* Extend the chunk backwards. */
+ tls_free_start = tls_lmap->l_tls_offset;
+ else {
+ /*
+ * This isn't contiguous with the last chunk
+ * freed. One of them will be leaked.
+ */
+ if (tls_free_end == _dl_tls_static_used)
+ _dl_tls_static_used = tls_free_start;
+ tls_free_start = tls_lmap->l_tls_offset;
+ tls_free_end = tls_free_start +
+ tls_lmap->l_tls_blocksize;
+ }
+# else
+# error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined
+# endif
+ } else {
+
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
+
+ dtv_t *dtv = THREAD_DTV ();
+
+ _dl_assert(!(dtv[tls_lmap->l_tls_modid].pointer.is_static));
+ if (dtv[tls_lmap->l_tls_modid].pointer.val != TLS_DTV_UNALLOCATED) {
+ /* Note that free is called for NULL is well. We
+ deallocate even if it is this dtv entry we are
+ supposed to load. The reason is that we call
+ memalign and not malloc. */
+ _dl_free (dtv[tls_lmap->l_tls_modid].pointer.val);
+ dtv[tls_lmap->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+ }
+ }
+ }
+#endif
+
+ end = (end + ADDR_ALIGN) & PAGE_ALIGN;
+ start = start & ~ADDR_ALIGN;
+ DL_LIB_UNMAP (tpnt, end - start);
+ /* Free elements in RTLD_LOCAL scope list */
+ for (runp = tpnt->rtld_local; runp; runp = tmp) {
+ tmp = runp->next;
+ free(runp);
+ }
+
+ /* Next, remove tpnt from the loaded_module list */
+ if (_dl_loaded_modules == tpnt) {
+ _dl_loaded_modules = tpnt->next;
+ if (_dl_loaded_modules)
+ _dl_loaded_modules->prev = 0;
+ } else {
+ for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) {
+ if (run_tpnt->next == tpnt) {
+ _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname);
+ run_tpnt->next = run_tpnt->next->next;
+ if (run_tpnt->next)
+ run_tpnt->next->prev = run_tpnt;
+ break;
+ }
+ }
+ }
+
+ /* Next, remove tpnt from the global symbol table list */
+ if (_dl_symbol_tables) {
+ if (_dl_symbol_tables->dyn == tpnt) {
+ _dl_symbol_tables = _dl_symbol_tables->next;
+ if (_dl_symbol_tables)
+ _dl_symbol_tables->prev = 0;
+ } else {
+ for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
+ if (rpnt1->next->dyn == tpnt) {
+ _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
+ rpnt1_tmp = rpnt1->next->next;
+ free(rpnt1->next);
+ rpnt1->next = rpnt1_tmp;
+ if (rpnt1->next)
+ rpnt1->next->prev = rpnt1;
+ break;
+ }
+ }
+ }
+ }
+ free(tpnt->libname);
+ if (handle->dyn != tpnt)
+ free(tpnt->symbol_scope.r_list);
+ free(tpnt);
+ }
+ }
+ /* Unlink and release the handle's local scope from global one */
+ if(ls)
+ ls->next = ls_next;
+ free(handle_rlist);
+
+ for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
+ rpnt1_tmp = rpnt1->next;
+ free(rpnt1);
+ }
+ free(handle->init_fini.init_fini);
+ free(handle);
+
+#if defined(USE_TLS) && USE_TLS
+ /* If we removed any object which uses TLS bump the generation counter. */
+ if (any_tls) {
+ if (__builtin_expect(++_dl_tls_generation == 0, 0)) {
+ _dl_debug_early("TLS generation counter wrapped! Please report to the uClibc mailing list.\n");
+ _dl_exit(30);
+ }
+
+ if (tls_free_end == _dl_tls_static_used)
+ _dl_tls_static_used = tls_free_start;
+ }
+#endif
+
+ if (_dl_debug_addr) {
+ dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
+ if (dl_brk != NULL) {
+ _dl_debug_addr->r_state = RT_DELETE;
+ (*dl_brk) ();
+
+ _dl_debug_addr->r_state = RT_CONSISTENT;
+ (*dl_brk) ();
+ }
+ }
+
+ return 0;
+}
+
+int dlclose(void *vhandle)
+{
+ int ret;
+
+ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+ ret = do_dlclose(vhandle, 1);
+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+ return ret;
+}
+
+char *dlerror(void)
+{
+ const char *retval;
+
+ if (!_dl_error_number)
+ return NULL;
+ retval = dl_error_names[_dl_error_number];
+ _dl_error_number = 0;
+ return (char *)retval;
+}
+
+/*
+ * Dump information to stderr about the current loaded modules
+ */
+#ifdef __USE_GNU
+static const char type[][4] = { "Lib", "Exe", "Int", "Mod" };
+
+int dlinfo(void)
+{
+ struct elf_resolve *tpnt;
+ struct dyn_elf *rpnt, *hpnt;
+
+ fprintf(stderr, "List of loaded modules\n");
+ /* First start with a complete list of all of the loaded files. */
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ fprintf(stderr, "\t%p %p %p %s %d %s\n",
+ DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope,
+ type[tpnt->libtype],
+ tpnt->usage_count, tpnt->libname);
+ }
+
+ /* Next dump the module list for the application itself */
+ fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables);
+ for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
+ fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
+
+ for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
+ fprintf(stderr, "Modules for handle %p\n", hpnt);
+ for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
+ fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
+ }
+ return 0;
+}
+
+static int do_dladdr(const void *__address, Dl_info * __info)
+{
+ struct elf_resolve *pelf;
+ struct elf_resolve *rpnt;
+
+ _dl_map_cache();
+
+ /*
+ * Try and locate the module address is in
+ */
+ pelf = NULL;
+
+ _dl_if_debug_print("__address: %p __info: %p\n", __address, __info);
+
+ __address = DL_LOOKUP_ADDRESS (__address);
+
+ for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
+ struct elf_resolve *tpnt;
+
+ tpnt = rpnt;
+
+ _dl_if_debug_print("Module \"%s\" at %p\n",
+ tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
+
+ if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
+ pelf = tpnt;
+ }
+
+ if (!pelf) {
+ return 0;
+ }
+
+ /*
+ * Try and locate the symbol of address
+ */
+
+ {
+ char *strtab;
+ ElfW(Sym) *symtab;
+ unsigned int hn, si, sn, sf;
+ ElfW(Addr) sa = 0;
+
+ /* Set the info for the object the address lies in */
+ __info->dli_fname = pelf->libname;
+ __info->dli_fbase = (void *)pelf->mapaddr;
+
+ symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
+ strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
+
+ sf = sn = 0;
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+ if (pelf->l_gnu_bitmask) {
+ for (hn = 0; hn < pelf->nbucket; hn++) {
+ si = pelf->l_gnu_buckets[hn];
+ if (!si)
+ continue;
+
+ const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
+ do {
+ ElfW(Addr) symbol_addr;
+
+ symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
+ if ((symtab[si].st_shndx != SHN_UNDEF
+ || symtab[si].st_value != 0)
+ && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
+ && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
+ (ElfW(Addr)) __address)) {
+ sa = symbol_addr;
+ sn = si;
+ sf = 1;
+ }
+ _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr);
+ ++si;
+ } while ((*hasharr++ & 1u) == 0);
+ }
+ } else
+#endif
+ for (hn = 0; hn < pelf->nbucket; hn++) {
+ for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
+ ElfW(Addr) symbol_addr;
+
+ symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
+ if ((symtab[si].st_shndx != SHN_UNDEF
+ || symtab[si].st_value != 0)
+ && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
+ && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
+ (ElfW(Addr)) __address)) {
+ sa = symbol_addr;
+ sn = si;
+ sf = 1;
+ }
+
+ _dl_if_debug_print("Symbol \"%s\" at %p\n",
+ strtab + symtab[si].st_name, symbol_addr);
+ }
+ }
+
+ if (sf) {
+ /* A nearest symbol has been found; fill the entries */
+ __info->dli_sname = strtab + symtab[sn].st_name;
+ __info->dli_saddr = (void *)sa;
+ } else {
+ /* No symbol found, fill entries with NULL value,
+ only the containing object will be returned. */
+ __info->dli_sname = NULL;
+ __info->dli_saddr = NULL;
+ }
+ return 1;
+ }
+}
+#endif
+
+int dladdr(const void *__address, Dl_info * __info)
+{
+ int ret;
+
+ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
+ ret = do_dladdr(__address, __info);
+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
+
+ return ret;
+}
diff --git a/ap/build/uClibc/ldso/man/Makefile b/ap/build/uClibc/ldso/man/Makefile
new file mode 100644
index 0000000..d36225f5
--- /dev/null
+++ b/ap/build/uClibc/ldso/man/Makefile
@@ -0,0 +1,22 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000,2001,2005 Erik Andersen <andersen@uclibc.org>
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources. Files within this library are copyright by their
+# respective copyright holders.
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+include ../Config.mk
+
+ALL = #ld.so.info
+
+all: $(ALL)
+
+ld.so.info: ld.so.texi
+ makeinfo $<
+
+clean:
+ $(RM) $(ALL) *~
diff --git a/ap/build/uClibc/ldso/man/dlopen.3 b/ap/build/uClibc/ldso/man/dlopen.3
new file mode 100644
index 0000000..8d1e09e
--- /dev/null
+++ b/ap/build/uClibc/ldso/man/dlopen.3
@@ -0,0 +1,218 @@
+.\" -*- nroff -*-
+.\" Copyright 1995 Yggdrasil Computing, Incorporated.
+.\" written by Adam J. Richter (adam@yggdrasil.com),
+.\" with typesetting help from Daniel Quinlan (quinlan@yggdrasil.com).
+.\"
+.\" This is free documentation; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2 of
+.\" the License, or (at your option) any later version.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with this manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH DLOPEN 3 "16 May 1995" "Linux" "Linux Programmer's Manual"
+.SH NAME
+dlclose, dlerror, dlopen, dlsym \- Programming interface to dynamic linking loader.
+.SH SYNOPSIS
+.B #include <dlfcn.h>
+.sp
+.BI "void *dlopen (const char *" "filename" ", int " flag ");
+.br
+.BI "const char *dlerror(void);"
+.br
+.BI "void *dlsym(void *"handle ", char *"symbol ");"
+.br
+.BI "int dladdr(void *"address ", Dl_info *"dlip ");"
+.br
+.BI "int dlclose (void *"handle ");
+.sp
+Special symbols:
+.BR "_init" ", " "_fini" ". "
+.SH DESCRIPTION
+.B dlopen
+loads a dynamic library from the file named by the null terminated
+string
+.I filename
+and returns an opaque "handle" for the dynamic library.
+If
+.I filename
+is not an absolute path (i.e., it does not begin with a "/"), then the
+file is searched for in the following locations:
+.RS
+.PP
+A colon-separated list of directories in the user's
+\fBLD_LIBRARY\fP path environment variable.
+.PP
+The list of libraries specified in \fI/etc/ld.so.cache\fP.
+.PP
+\fI/usr/lib\fP, followed by \fI/lib\fP.
+.RE
+.PP
+If
+.I filename
+is a NULL pointer, then the returned handle is for the main program.
+.PP
+External references in the library are resolved using the libraries
+in that library's dependency list and any other libraries previously
+opened with the
+.B RTLD_GLOBAL
+flag.
+If the executable was linked
+with the flag "-rdynamic", then the global symbols in the executable
+will also be used to resolve references in a dynamically loaded
+library.
+.PP
+.I flag
+must be either
+.BR RTLD_LAZY ,
+meaning resolve undefined symbols as code from the dynamic library is
+executed, or
+.BR RTLD_NOW ,
+meaning resolve all undefined symbols before
+.B dlopen
+returns, and fail if this cannot be done.
+Optionally,
+.B RTLD_GLOBAL
+may be or'ed with
+.IR flag,
+in which case the external symbols defined in the library will be
+made available to subsequently loaded libraries.
+.PP
+If the library exports a routine named
+.BR _init ,
+then that code is executed before dlopen returns.
+If the same library is loaded twice with
+.BR dlopen() ,
+the same file handle is returned. The dl library maintains link
+counts for dynamic file handles, so a dynamic library is not
+deallocated until
+.B dlclose
+has been called on it as many times as
+.B dlopen
+has succeeded on it.
+.PP
+If
+.B dlopen
+fails for any reason, it returns NULL.
+A human readable string describing the most recent error that occurred
+from any of the dl routines (dlopen, dlsym or dlclose) can be
+extracted with
+.BR dlerror() .
+.B dlerror
+returns NULL if no errors have occurred since initialization or since
+it was last called. (Calling
+.B dlerror()
+twice consecutively, will always result in the second call returning
+NULL.)
+
+.B dlsym
+takes a "handle" of a dynamic library returned by dlopen and the null
+terminated symbol name, returning the address where that symbol is
+loaded. If the symbol is not found,
+.B dlsym
+returns NULL; however, the correct way to test for an error from
+.B dlsym
+is to save the result of
+.B dlerror
+into a variable, and then check if saved value is not NULL.
+This is because the value of the symbol could actually be NULL.
+It is also necessary to save the results of
+.B dlerror
+into a variable because if
+.B dlerror
+is called again, it will return NULL.
+.PP
+.B dladdr
+returns information about the shared library containing the memory
+location specified by
+.IR address .
+.B dladdr
+returns zero on success and non-zero on error.
+.PP
+.B dlclose
+decrements the reference count on the dynamic library handle
+.IR handle .
+If the reference count drops to zero and no other loaded libraries use
+symbols in it, then the dynamic library is unloaded. If the dynamic
+library exports a routine named
+.BR _fini ,
+then that routine is called just before the library is unloaded.
+.SH EXAMPLES
+.B Load the math library, and print the cosine of 2.0:
+.RS
+.nf
+.if t .ft CW
+#include <dlfcn.h>
+
+int main(int argc, char **argv) {
+ void *handle = dlopen ("/lib/libm.so", RTLD_LAZY);
+ double (*cosine)(double) = dlsym(handle, "cos");
+ printf ("%f\\n", (*cosine)(2.0));
+ dlclose(handle);
+}
+.if t .ft P
+.fi
+.PP
+If this program were in a file named "foo.c", you would build the program
+with the following command:
+.RS
+.LP
+gcc -rdynamic -o foo foo.c -ldl
+.RE
+.RE
+.LP
+.B Do the same thing, but check for errors at every step:
+.RS
+.nf
+.if t .ft CW
+#include <stdio.h>
+#include <dlfcn.h>
+
+int main(int argc, char **argv) {
+ void *handle;
+ double (*cosine)(double);
+ char *error;
+
+ handle = dlopen ("/lib/libm.so", RTLD_LAZY);
+ if (!handle) {
+ fputs (dlerror(), stderr);
+ exit(1);
+ }
+
+ cosine = dlsym(handle, "cos");
+ if ((error = dlerror()) != NULL) {
+ fputs(error, stderr);
+ exit(1);
+ }
+
+ printf ("%f\\n", (*cosine)(2.0));
+ dlclose(handle);
+}
+.if t .ft P
+.fi
+.RE
+.SH ACKNOWLEDGEMENTS
+The dlopen interface standard comes from Solaris.
+The Linux dlopen implementation was primarily written by
+Eric Youngdale with help from Mitch D'Souza, David Engel,
+Hongjiu Lu, Andreas Schwab and others.
+The manual page was written by Adam Richter.
+.SH SEE ALSO
+.BR ld(1) ,
+.BR ld.so(8) ,
+.BR ldconfig(8) ,
+.BR ldd(1) ,
+.BR ld.so.info .
diff --git a/ap/build/uClibc/ldso/man/ld.so.8 b/ap/build/uClibc/ldso/man/ld.so.8
new file mode 100644
index 0000000..59ec853
--- /dev/null
+++ b/ap/build/uClibc/ldso/man/ld.so.8
@@ -0,0 +1,113 @@
+.TH ld.so 8 "14 March 1998"
+.SH NAME
+ld.so/ld-linux.so \- dynamic linker/loader
+.SH DESCRIPTION
+.B ld.so
+loads the shared libraries needed by a program, prepares the program
+to run, and then runs it.
+Unless explicitly specified via the
+.B \-static
+option to
+.B ld
+during compilation, all Linux programs are incomplete and require
+further linking at run time.
+.PP
+The necessary shared libraries needed by the program are searched for
+in the following order
+.IP o
+Using the environment variable
+.B LD_LIBRARY_PATH
+.RB ( LD_AOUT_LIBRARY_PATH
+for a.out programs).
+Except if the executable is a setuid/setgid binary, in which case it
+is ignored.
+.IP o
+From the cache file
+.BR /etc/ld.so.cache
+which contains a compiled list of candidate libraries previously found
+in the augmented library path.
+.IP o
+In the default path
+.BR /usr/lib ,
+and then
+.BR /lib .
+.SH ENVIRONMENT
+.TP
+.B LD_LIBRARY_PATH
+A colon-separated list of directories in which to search for
+ELF libraries at execution-time.
+Similar to the
+.B PATH
+environment variable.
+.TP
+.B LD_PRELOAD
+A whitespace-separated list of additional, user-specified, ELF shared
+libraries to be loaded before all others.
+This can be used to selectively override functions in other shared libraries.
+For setuid/setgid ELF binaries, only libraries in the standard search
+directories that are also setgid will be loaded.
+.TP
+.B LD_TRACE_LOADED_OBJECTS
+If present, causes the program to list its dynamic library dependencies,
+as if run by ldd, instead of running normally.
+.TP
+.B LD_BIND_NOW
+If present, causes the dynamic linker to resolve all symbols at program
+startup instead of when they are first referenced.
+.TP
+.B LD_AOUT_LIBRARY_PATH
+A colon-separated list of directories in which to search for
+a.out libraries at execution-time.
+Similar to the
+.B PATH
+environment variable.
+.TP
+.B LD_AOUT_PRELOAD
+The name of an additional, user-specified, a.out shared library to be loaded
+after all others.
+This can be used to selectively override functions in other shared libraries.
+.TP
+.B LD_NOWARN
+Suppress warnings about a.out libraries with incompatible minor
+version numbers.
+.TP
+.B LD_KEEPDIR
+Don't ignore the directory in the names of a.out libraries to be loaded.
+Use of this option is strongly discouraged.
+.SH FILES
+.PD 0
+.TP 20
+.B /lib/ld.so
+a.out dynamic linker/loader
+.TP 20
+.B /lib/ld-linux.so.*
+ELF dynamic linker/loader
+.TP
+.B /etc/ld.so.cache
+File containing a compiled list of directories in which to search for
+libraries and an ordered list of candidate libraries.
+.TP
+.B /etc/ld.so.preload
+File containing a whitespace separated list of ELF shared libraries to
+be loaded before the program.
+libraries and an ordered list of candidate libraries.
+.TP
+.B lib*.so*
+shared libraries
+.PD
+.SH SEE ALSO
+.BR ldd (1),
+.BR ldconfig (8).
+.SH BUGS
+.LP
+Currently
+.B ld.so
+has no means of unloading and searching for compatible or newer version of
+libraries.
+.PP
+.B ld.so
+functionality is only available for executables compiled using libc version
+4.4.3 or greater.
+.SH AUTHORS
+David Engel, Eric Youngdale, Peter MacDonald, Hongjiu Lu, Linus
+Torvalds, Lars Wirzenius and Mitch D'Souza (not necessarily in that order).
diff --git a/ap/build/uClibc/ldso/man/ld.so.texi b/ap/build/uClibc/ldso/man/ld.so.texi
new file mode 100644
index 0000000..4e5fb84
--- /dev/null
+++ b/ap/build/uClibc/ldso/man/ld.so.texi
@@ -0,0 +1,411 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename ld.so.info
+@settitle ld.so : Dynamic-Link Library support
+@c %**end of header
+
+@ifinfo
+This file documents the dynamic-link support libraries and utilities for the
+Linux OS, version 1.8.1.
+
+Copyright 1996 Michael Deutschmann
+
+This document is subject to the GNU General Public License as published by
+the Free Software foundation, version 2 or later (your choice).
+
+Note: The software described in this document is under a different copyright
+and license.
+
+@end ifinfo
+
+@titlepage
+@title ld.so
+@subtitle Dynamic Link library support for the Linux OS.
+@author David Engel
+@author Eric Youngdale
+@author Peter Macdonald
+@author Hongjiu Lu
+@author Mitch D'Souza
+@author Michael Deutschmann (this documentation)
+
+@page
+Copyright @copyright{} 1996 Michael Deutschmann
+
+This document is subject to the GNU General Public License as published by
+the Free Software foundation, version 2 or later (your choice).
+
+Note: The software described in this document is under a different copyright
+and license.
+@end titlepage
+
+@ifinfo
+@node Top
+@top
+
+The @code{ld.so} module provides dynamic linked library support in Linux.
+This file documents @code{ld.so} and its companion software.
+
+@menu
+* intro:: Introduction
+
+* ld.so:: The dynamic linker core program
+* ldd:: A utility to print out dependencies
+* ldconfig:: A utility to maintain the cache and symlinks
+* libdl:: Manual dynamic linking library
+@end menu
+
+@end ifinfo
+
+@node intro
+@unnumbered Introduction
+
+The @code{ld.so} suite contains special files and utilities needed for linux
+to handle @dfn{dynamic libraries}.
+
+Ordinary static libraries (@file{lib*.a} files) are included into executables
+that use their functions. A file that only uses static libraries needs less
+intelligence to load, but takes up more space. If many executables use the
+same library, there can be much wastage of storage space, since multiple
+copies of the library functions are scattered across the executables.
+However, static libraries are easier to make.
+
+Dynamic libraries (@file{lib*.so*} files) are not copied into executables ---
+the executable is written in such a way that it will automatically load the
+libraries. In linux, the executable will first load the special library
+@code{ld.so} or @code{ld-linux.so}, which contains the intelligence
+to load further dynamic libraries. Since multiple files end up getting
+executable data from the same file, dynamic libraries are also known as
+shared libraries.
+
+Linux executables come in two flavors, @sc{elf} and a.out.
+
+a.out is the original executable format used by Linux. It has somewhat less
+overhead than @sc{elf}. However creating shared libraries for a.out is
+@emph{very} involved, and each a.out shared library must be explicitly
+registered.
+
+@sc{elf} is a more recent format, which supports a much simpler method of
+creating libraries. @sc{elf} libraries may also be linked manually
+(@pxref{libdl}).
+
+Since many library authors prefer @sc{elf} and no longer release shared a.out
+libraries, a.out is moribund on Linux. This version of the @code{ld.so} can
+be compiled to support only @sc{elf}, or to support both formats. (The last
+release of ld.so to support a.out alone was 1.8.0.)
+
+@node ld.so
+@chapter @code{ld.so}: Dynamic linker core
+
+@code{ld.so} works behind the scenes to handle dynamic libraries in Linux.
+Users will almost never have to deal with it directly, but in special cases
+one can send instructions to it through environment variables. Also, if
+something is wrong with your libraries (usually an incorrect version) ld.so
+will give error messages.
+
+Actually @code{ld.so} is the a.out linker. The new @sc{elf} executables are
+handled by a related program @code{ld-linux.so}.
+
+@menu
+* files:: Configuration files used by the suite
+* environment:: Environment settings that tweak @code{ld.so}
+* errors:: Complaints @code{ld.so} might make
+@end menu
+
+@node files
+@section Configuration Files
+
+@table @file
+@item /etc/ld.so.cache
+A file created by @code{ldconfig} and used to speed linking. It's structure
+is private to the suite.
+
+@item /etc/ld.so.conf
+A simple list of directories to scan for libraries, in addition to
+@file{/usr/lib} and @file{/lib}, which are hardwired. It may contain
+comments started with a @samp{#}.
+
+@item /etc/ld.so.preload
+A list of libraries to preload. This allows preloading libraries for
+setuid/setgid executables securely. It may contain comments.
+@end table
+
+@node environment
+@section Environment Variables
+
+@table @code
+@item LD_AOUT_LIBRARY_PATH
+@itemx LD_LIBRARY_PATH
+These variables supply a library path for finding dynamic libraries, in the
+standard colon seperated format. These variables are ignored when executing
+setuid/setgid programs, because otherwise they would be a security hazard.
+@code{ld.so} will use @code{LD_AOUT_LIBRARY_PATH} and @code{ld-linux.so} will
+use @code{LD_LIBRARY_PATH}.
+
+@item LD_AOUT_PRELOAD
+@itemx LD_PRELOAD
+These variables allow an extra library not specified in the executable to be
+loaded. Generally this is only useful if you want to override a function.
+These are also ignored when running setuid/setgid executables. @code{ld.so}
+will use @code{LD_AOUT_PRELOAD} and @code{ld-linux.so} will use
+@code{LD_PRELOAD}.
+
+@item LD_NOWARN
+If non-empty, errors about incompatible minor revisions are suppressed.
+
+@item LD_KEEPDIR
+If non-empty, allow executables to specify absolute library names. This
+option is deprecated.
+@c FIXME:
+@c The following are things I noticed in the ld-linux.so source.
+@c I don't really understand 'em. Could someone help me?
+@c
+@c @item LD_BIND_NOW
+@c This option is used by the @code{ld-linux.so} only. I don't know
+@c what it does. (I suspect, looking at the code, that it specifies
+@c "RTLD_NOW" rather than "RTLD_LAZY" mode for the shared libraries.)
+@c
+@c @item LD_TRACE_LOADED_OBJECTS
+@c @itemx LD_WARN
+@c These seem to have something to do with the communication between the
+@c @code{ld-linux.so} and @code{ldd}. I don't know more.
+@end table
+
+@node errors
+@section Errors
+
+@table @samp
+@item Can't find library @var{library}
+The executable required a dynamically linked library that ld.so cannot find.
+Your symbolic links may be not set right, or you may have not installed a
+library needed by the program.
+
+@item Can't load library @var{library}
+The library is corrupt.
+
+@item Incompatible library @var{library}
+@itemx Require major version @var{x} and found @var{y}
+Your version of the library is incompatible with the executable. Recompiling
+the executable, or upgrading the library will fix the problem.
+
+@item using incompatible library @var{library}
+@itemx Desire minor version >= @var{x} and found @var{y}.
+Your version of the library is older than that expected by the executable,
+but not so old that the library interface has radically changed, so the
+linker will attempt to run anyway. There is a chance that it will work, but
+you should upgrade the library or recompile the software. The environment
+variable @code{LD_NOWARN} can be used to supress this message.
+
+@item too many directories in library path
+The linker only supports up to 32 library directories. You have too many.
+
+@item dynamic linker error in @var{blah}
+The linker is having trouble handling a binary - it is probably corrupt.
+
+@item can't map cache file @var{cache-file}
+@itemx cache file @var{cache-file} @var{blah}
+The linker cache file (generally @file{/etc/ld.so.cache}) is corrupt or
+non-existent. These errors can be ignored, and can be prevented by
+regenerating the cache file with @code{ldconfig}.
+@end table
+
+@node ldd
+@chapter @code{ldd}: Dependency scanner
+
+@code{ldd} is a utility that prints out the dynamic libraries that an
+executable is linked to.
+
+Actually @code{ldd} works by signalling ld.so to print the dependencies.
+For a.out executables this is done by starting the executable with
+@code{argc} equal to 0. The linker detects this and prints the dependencies.
+(This can cause problems with @emph{very} old binaries, which would run as
+normal only with an inappropriate @code{argc}.)
+
+For @sc{elf} executables, special environment variables are used to tell the
+linker to print the dependencies.
+
+@code{ldd} has a few options:
+
+@table @samp
+@item -v
+Print the version number of @code{ldd} itself
+
+@item -V
+Print the version number of the dynamic linker
+
+@item -d
+Report missing functions. This is only supported for @sc{elf} executables.
+
+@item -r
+Report missing objects. This is also only available for @sc{elf}
+executables.
+@end table
+
+@node ldconfig
+@chapter @code{ldconfig}: Setup program
+
+This utility is used by the system administrator to automatically set up
+symbolic links needed by the libraries, and also to set up the cache file.
+
+@code{ldconfig} is run after new dynamic libraries are installed, and if the
+cache file or links are damaged. It is also run when upgrading the
+@code{ld.so} suite itself.
+
+The @file{/lib} and @file{/usr/lib} directories, and any listed in the file
+@file{/etc/ld.so.conf} are scanned by default unless @samp{-n} is used.
+Additional directories may be specified on the command line.
+
+It has the following options:
+
+@table @samp
+@item -D
+Enter debug mode. Implies @samp{-N} and @samp{-X}.
+
+@item -v
+Verbose. Print out links created and directories scanned.
+
+@item -n
+Check directories specified on the commandline @emph{only}.
+
+@item -N
+Do not regenerate the cache.
+
+@item -X
+Do not rebuild symbolic links.
+
+@item -l
+Set up symbolic links for only libraries presented on the command line.
+
+@item -p
+Print out the library pathnames in the cache file (@file{/etc/ld.so.cache})
+@end table
+
+@node libdl
+@chapter User dynamic linking library
+
+The @code{ld.so} package includes a small library of functions
+(@code{libdl}) to allow manual dynamic linking. Normally programs are linked
+so that dynamic functions and objects are automagically available. These
+functions allow one to manually load and access a symbol from a library.
+They are only available for @sc{elf} executables.
+
+@menu
+* using libdl:: General points
+* functions:: How to use the functions
+* example:: A sample program
+@end menu
+
+@node using libdl
+@section Overview
+
+To access this library, add the flag @samp{-ldl} to your compile command when
+linking the executable. You also must include the header file
+@code{dlfcn.h}. You may also need the flag @samp{-rdynamic}, which enables
+resolving references in the loaded libraries against your executable.
+
+Generally, you will first use @code{dlopen} to open a library. Then you use
+@code{dlsym} one or more times to access symbols. Finally you use
+@code{dlclose} to close the library.
+
+These facilities are most useful for language interpreters that provide
+access to external libraries. Without @code{libdl}, it would be neccessary
+to link the interpreter executable with any and all external libraries
+needed by the programs it runs. With @code{libdl}, the interpreter only
+needs to be linked with the libraries it uses itself, and can dynamically
+load in additional ones if programs need it.
+
+@node functions
+@section Functions
+
+@deftypefun void *dlopen ( const char @var{filename}, int @var{flags} )
+
+This function opens the dynamic library specified by @var{filename}
+and returns an abstract handle, which can be used in subsequent calls to
+@code{dlsym}. The function will respect the @code{LD_ELF_LIBRARY_PATH} and
+@code{LD_LIBRARY_PATH} environment variables.
+
+@end deftypefun
+
+The following flags can be used with @code{dlopen}:
+
+@deftypevr Macro int RTLD_LAZY
+Resolve symbols in the library as they are needed.
+@end deftypevr
+
+@deftypevr Macro int RTLD_NOW
+Resolve all symbols in the library before returning, and fail if not all can
+be resolved. This is mutually exclusive with @code{RTLD_LAZY}.
+@end deftypevr
+
+@deftypevr Macro int RTLD_GLOBAL
+Make symbols in this library available for resolving symbols in other
+libraries loaded with @code{dlopen}.
+@end deftypevr
+
+@deftypefun int dlclose ( void *@var{handle} )
+
+This function releases a library handle.
+
+Note that if a library opened twice, the handle will be the same. However,
+a reference count is used, so you should still close the library as many
+times as you open it.
+
+@end deftypefun
+
+@deftypefun void *dlsym (void *@var{handle},char *@var{symbol-name})
+
+This function looks up the name @var{symbol-name} in the library and returns
+it in the void pointer.
+
+If there is an error, a null pointer will be returned. However, it is
+possible for a valid name in the library to have a null value, so
+@code{dlerror} should be used to check if there was an error.
+
+@end deftypefun
+
+@deftypefun {libdl function} {const char} *dlerror( void )
+
+This function is used to read the error state. It returns a human-readable
+string describing the last error, or null, meaning no error.
+
+The function resets the error value each time it is called, so the result
+should be copied into a variable. If the function is called more than once
+after an error, the second and subsequent calls will return null.
+
+@end deftypefun
+
+@node example
+@section Example program
+
+Here is an example program that prints the cosine of two by manually linking
+to the math library:
+
+@example
+@c The following was snarfed verbatim from the dlopen.3 man file.
+#include <stdio.h>
+#include <dlfcn.h>
+
+int main(int argc, char **argv) @{
+ void *handle;
+ double (*cosine)(double);
+ char *error;
+
+ handle = dlopen ("/lib/libm.so", RTLD_LAZY);
+ if (!handle) @{
+ fputs (dlerror(), stderr);
+ exit(1);
+ @}
+
+ cosine = dlsym(handle, "cos");
+ if ((error = dlerror()) != NULL) @{
+ fputs(error, stderr);
+ exit(1);
+ @}
+
+ printf ("%f\\n", (*cosine)(2.0));
+ dlclose(handle);
+@}
+@end example
+
+@contents
+
+@bye
diff --git a/ap/build/uClibc/ldso/man/ldconfig.8 b/ap/build/uClibc/ldso/man/ldconfig.8
new file mode 100644
index 0000000..8228529
--- /dev/null
+++ b/ap/build/uClibc/ldso/man/ldconfig.8
@@ -0,0 +1,189 @@
+.TH ldconfig 8 "14 March 1998"
+.SH NAME
+ldconfig \- determine run-time link bindings
+.SH SYNOPSIS
+ldconfig
+.RB [ \-DvqnNX ]
+.RB [ \-f\ conf ]
+.RB [ \-C\ cache ]
+.RB [ \-r\ root ]
+.IR directory \ ...
+.PD 0
+.PP
+.PD
+ldconfig
+.B \-l
+.RB [ \-Dvq ]
+.IR library \ ...
+.PD 0
+.PP
+.PD
+ldconfig
+.B \-p
+.SH DESCRIPTION
+.B ldconfig
+creates the necessary links and cache (for use by the run-time linker,
+.IR ld.so )
+to the most recent shared libraries found in the directories specified
+on the command line, in the file
+.IR /etc/ld.so.conf ,
+and in the trusted directories
+.RI ( /usr/lib
+and
+.IR /lib ).
+.B ldconfig
+checks the header and file names of the libraries it encounters when
+determining which versions should have their links updated.
+.B ldconfig
+ignores symbolic links when scanning for libraries.
+.PP
+.B ldconfig
+will attempt to deduce the type of ELF libs (ie. libc5 or libc6/glibc)
+based on what C libs if any the library was linked against, therefore when
+making dynamic libraries, it is wise to explicitly link against libc (use -lc).
+.PP
+Some existing libs do not contain enough information to allow the deduction of
+their type, therefore the
+.IR /etc/ld.so.conf
+file format allows the specification of an expected type. This is
+.B only
+used for those ELF libs which we can not work out. The format
+is like this "dirname=TYPE", where type can be libc4, libc5 or libc6.
+(This syntax also works on the command line). Spaces are
+.B not
+allowed. Also see the
+.B -p
+option.
+.PP
+Directory names containing an
+.B = are no longer legal
+unless they also have an expected type specifier.
+.PP
+.B ldconfig
+should normally be run by the super-user as it may require write
+permission on some root owned directories and files.
+It is normally run automatically at bootup, from /etc/rc, or manually
+whenever new DLL's are installed.
+.SH OPTIONS
+.TP
+.B \-D
+Debug mode.
+Implies
+.B \-N
+and
+.BR \-X .
+.TP
+.B \-v
+Verbose mode.
+Print current version number, the name of each directory as it
+is scanned and any links that are created.
+Overrides quiet mode.
+.TP
+.B \-q
+Quiet mode.
+Don't print warnings.
+.TP
+.B \-n
+Only process directories specified on the command line.
+Don't process the trusted directories
+.RI ( /usr/lib
+and
+.IR /lib )
+nor those specified in
+.IR /etc/ld.so.conf .
+Implies
+.BR \-N .
+.TP
+.B \-N
+Don't rebuild the cache.
+Unless
+.B \-X
+is also specified, links are still updated.
+.TP
+.B \-X
+Don't update links.
+Unless
+.B \-N
+is also specified, the cache is still rebuilt.
+.TP
+.B \-f conf
+Use
+.B conf
+instead of
+.IR /etc/ld.so.conf .
+.TP
+.B \-C cache
+Use
+.B cache
+instead of
+.IR /etc/ld.so.cache .
+.TP
+.B \-r root
+Change to and use
+.B root
+as the root directory.
+.TP
+.B \-l
+Library mode.
+Manually link individual libraries.
+Intended for use by experts only.
+.TP
+.B \-p
+Print the lists of directories and candidate libraries stored in
+the current cache.
+.SH EXAMPLES
+In the bootup file
+.I /etc/rc
+having the line
+.RS
+
+/sbin/ldconfig -v
+
+.RE
+will set up the correct links for the shared binaries and rebuild
+the cache.
+.TP
+On the command line
+.RS
+
+# /sbin/ldconfig -n /lib
+
+.RE
+as root after the installation of a new DLL, will properly update the
+shared library symbolic links in /lib.
+
+.SH FILES
+.PD 0
+.TP 20
+.B /lib/ld.so
+execution time linker/loader
+.TP 20
+.B /etc/ld.so.conf
+File containing a list of colon, space, tab, newline, or comma spearated
+directories in which to search for libraries.
+.TP 20
+.B /etc/ld.so.cache
+File containing an ordered list of libraries found in the directories
+specified in
+.BR /etc/ld.so.conf .
+.TP
+.B lib*.so.version
+shared libraries
+.PD
+.SH SEE ALSO
+.BR ldd (1),
+.BR ld.so (8).
+.SH BUGS
+.LP
+.BR ldconfig 's
+functionality, in conjunction with
+.BR ld.so ,
+is only available for executables compiled using libc version 4.4.3 or greater.
+.PP
+.BR ldconfig ,
+being a user process, must be run manually and has no means of dynamically
+determining and relinking shared libraries for use by
+.BR ld.so
+when a new DLL is installed.
+.SH AUTHORS
+David Engel and Mitch D'Souza.
diff --git a/ap/build/uClibc/ldso/man/ldd.1 b/ap/build/uClibc/ldso/man/ldd.1
new file mode 100644
index 0000000..20c5578
--- /dev/null
+++ b/ap/build/uClibc/ldso/man/ldd.1
@@ -0,0 +1,59 @@
+.\" Copyright 1995-2000 David Engel (david@ods.com)
+.\" Copyright 1995 Rickard E. Faith (faith@cs.unc.edu)
+.\" Most of this was copied from the README file. Do not restrict distribution.
+.\" May be distributed under the GNU General Public License
+.TH LDD 1 "14 March 1998"
+.SH NAME
+ldd \- print shared library dependencies
+.SH SYNOPSIS
+.B ldd
+.RB [ \-vVdr ]
+program|library ...
+.SH DESCRIPTION
+.B ldd
+prints the shared libraries required by each program or shared library
+specified on the command line.
+If a shared library name does not contain a '/',
+.B ldd
+attempts to locate the library in the standard locations.
+To run
+.B ldd
+on a shared library in the current directory, a "./" must be prepended
+to its name.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number of
+.BR ldd .
+.TP
+.B \-V
+Print the version number of the dynamic linker,
+.BR ld.so .
+.TP
+.B \-d
+Perform relocations and report any missing functions (ELF only).
+.TP
+.B \-r
+Perform relocations for both data objects and functions, and
+report any missing objects (ELF only).
+.SH BUGS
+.B ldd
+does not work very well on libc.so.5 itself.
+.PP
+.B ldd
+does not work on a.out shared libraries.
+.PP
+.B ldd
+does not work with some extremely old a.out programs which were
+built before
+.B ldd
+support was added to the compiler releases.
+If you use
+.B ldd
+on one of these programs, the program will attempt to run with argc = 0 and
+the results will be unpredictable.
+.SH AUTHOR
+David Engel.
+.SH SEE ALSO
+.BR ldconfig (8),
+.BR ld.so (8).