Select the version of uClibc you wish to use.
config BR2_UCLIBC_VERSION_0_9_28_3
- depends !BR2_avr32 && BR2_DEPRECATED
+ depends BR2_DEPRECATED
bool "uClibc 0.9.28.3"
depends BR2_EXT_UCLIBC_VERSION_0_9_28_3
depends BR2_EXT_UCLIBC_VERSION_0_9_29
config BR2_UCLIBC_VERSION_SNAPSHOT
- depends !BR2_avr32
bool "daily snapshot"
endchoice
--- /dev/null
+ uClibc and Glibc are not the same -- there are a number of differences which
+may or may not cause you problems. This document attempts to list these
+differences and, when completed, will contain a full list of all relevant
+differences.
+
+
+1) uClibc is smaller than glibc. We attempt to maintain a glibc compatible
+interface, allowing applications that compile with glibc to easily compile with
+uClibc. However, we do not include _everything_ that glibc includes, and
+therefore some applications may not compile. If this happens to you, please
+report the failure to the uclibc mailing list, with detailed error messages.
+
+2) uClibc is much more configurable then glibc. This means that a developer
+may have compiled uClibc in such a way that significant amounts of
+functionality have been omitted.
+
+3) uClibc does not even attempt to ensure binary compatibility across releases.
+When a new version of uClibc is released, you may or may not need to recompile
+all your binaries.
+
+4) malloc(0) in glibc returns a valid pointer to something(!?!?) while in
+uClibc calling malloc(0) returns a NULL. The behavior of malloc(0) is listed
+as implementation-defined by SuSv3, so both libraries are equally correct.
+This difference also applies to realloc(NULL, 0). I personally feel glibc's
+behavior is not particularly safe. To enable glibc behavior, one has to
+explicitly enable the MALLOC_GLIBC_COMPAT option.
+
+4.1) glibc's malloc() implementation has behavior that is tunable via the
+MALLOC_CHECK_ environment variable. This is primarily used to provide extra
+malloc debugging features. These extended malloc debugging features are not
+available within uClibc. There are many good malloc debugging libraries
+available for Linux (dmalloc, electric fence, valgrind, etc) that work much
+better than the glibc extended malloc debugging. So our omitting this
+functionality from uClibc is not a great loss.
+
+5) uClibc does not provide a database library (libdb).
+
+6) uClibc does not support NSS (/lib/libnss_*), which allows glibc to easily
+support various methods of authentication and DNS resolution. uClibc only
+supports flat password files and shadow password files for storing
+authentication information. If you need something more complex than this,
+you can compile and install pam.
+
+7) uClibc's libresolv is only a stub. Some, but not all of the functionality
+provided by glibc's libresolv is provided internal to uClibc. Other functions
+are not at all implemented.
+
+8) libnsl provides support for Network Information Service (NIS) which was
+originally called "Yellow Pages" or "YP", which is an extension of RPC invented
+by Sun to share Unix password files over the network. I personally think NIS
+is an evil abomination and should not be used. These days, using ldap is much
+more effective mechanism for doing the same thing. uClibc provides a stub
+libnsl, but has no actual support for Network Information Service (NIS).
+We therefore, also do not provide any of the headers files provided by glibc
+under /usr/include/rpcsvc.
+
+9) uClibc's locale support is not 100% complete yet. We are working on it.
+
+10) uClibc's math library only supports long double as inlines, and even
+then the long double support is quite limited. Also, very few of the
+float math functions are implemented. Stick with double and you should
+be just fine.
+
+11) uClibc's libcrypt does not support the reentrant crypt_r, setkey_r and
+encrypt_r, since these are not required by SuSv3.
+
+12) uClibc directly uses kernel types to define most opaque data types.
+
+13) uClibc directly uses the linux kernel's arch specific 'stuct stat'.
+
+14) uClibc's librt library currently lacks all aio routines, all clock
+ routines, and all shm routines (only the timer routines and the mq
+ routines are implemented).
+
+<other things as we notice them>
+
+
+
+****************************** Manuel's Notes ******************************
+
+Some general comments...
+
+The intended target for all my uClibc code is ANSI/ISO C99 and SUSv3
+compliance. While some glibc extensions are present, many will eventually
+be configurable. Also, even when present, the glibc-like extensions may
+differ slightly or be more restrictive than the native glibc counterparts.
+They are primarily meant to be porting _aides_ and not necessarily
+drop-in replacements.
+
+Now for some details...
+
+time functions
+--------------
+1) Leap seconds are not supported.
+2) /etc/timezone and the whole zoneinfo directory tree are not supported.
+ To set the timezone, set the TZ environment variable as specified in
+ http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html
+ or you may also create an /etc/TZ file of a single line, ending with a
+ newline, containing the TZ setting. For example
+ echo CST6CDT > /etc/TZ
+3) Currently, locale specific eras and alternate digits are not supported.
+ They are on my TODO list.
+
+wide char support
+-----------------
+1) The only multibyte encoding currently supported is UTF-8. The various
+ ISO-8859-* encodings are (optionally) supported. The internal
+ representation of wchar's is assumed to be 31 bit unicode values in
+ native endian representation. Also, the underlying char encoding is
+ assumed to match ASCII in the range 0-0x7f.
+2) In the next iteration of locale support, I plan to add support for
+ (at least some) other multibyte encodings.
+
+locale support
+--------------
+1) The target for support is SUSv3 locale functionality. While nl_langinfo
+ has been extended, similar to glibc, it only returns values for related
+ locale entries.
+2) Currently, all SUSv3 libc locale functionality should be implemented
+ except for wcsftime and collating item support in regex.
+
+stdio
+-----
+1) Conversion of large magnitude floating-point values by printf suffers a loss
+ of precision due to the algorithm used.
+2) uClibc's printf is much stricter than glibcs, especially regarding positional
+ args. The entire format string is parsed first and an error is returned if
+ a problem is detected. In locales other than C, the format string is checked
+ to be a valid multibyte sequence as well. Also, currently at most 10 positional
+ args are allowed (although this is configurable).
+3) BUFSIZ is configurable, but no attempt is made at automatic tuning of internal
+ buffer sizes for stdio streams. In fact, the stdio code in general sacrifices
+ sophistication/performace for minimal size.
+4) uClibc allows glibc-like custom printf functions. However, while not
+ currently checked, the specifier must be <= 0x7f.
+5) uClibc allows glibc-like custom streams. However, no in-buffer seeking is
+ done.
+6) The functions fcloseall() and __fpending() can behave differently than their
+ glibc counterparts.
+7) uClibc's setvbuf is more restrictive about when it can be called than glibc's
+ is. The standards specify that setvbuf must occur before any other operations
+ take place on the stream.
+8) Right now, %m is not handled properly by printf when the format uses positional
+ args.
+9) The FILEs created by glibc's fmemopen(), open_memstream(), and fopencookie()
+ are not capable of wide orientation. The corresponding uClibc routines do
+ not have this limitation.
+10) For scanf, the C99 standard states "The fscanf function returns the value of
+ the macro EOF if an input failure occurs before any conversion." But glibc's
+ scanf does not respect conversions for which assignment was surpressed, even
+ though the standard states that the value is converted but not stored.
+
+glibc bugs that Ulrich Drepper has refused to acknowledge or comment on
+ ( http://sources.redhat.com/ml/libc-alpha/2003-09/ )
+-----------------------------------------------------------------------
+1) The C99 standard says that for printf, a %s conversion makes no special
+ provisions for multibyte characters. SUSv3 is even more clear, stating
+ that bytes are written and a specified precision is in bytes. Yet glibc
+ treats the arg as a multibyte string when a precision is specified and
+ not otherwise.
+2) Both C99 and C89 state that the %c conversion for scanf reads the exact
+ number of bytes specified by the optional field width (or 1 if not specified).
+ uClibc complies with the standard. There is an argument that perhaps the
+ specified width should be treated as an upper bound, based on some historical
+ use. However, such behavior should be mentioned in the Conformance document.
+3) glibc's scanf is broken regarding some numeric patterns. Some invalid
+ strings are accepted as valid ("0x.p", "1e", digit grouped strings).
+ In spite of my posting examples clearly illustrating the bugs, they remain
+ unacknowledged by the glibc developers.
+4) glibc's scanf seems to require a 'p' exponent for hexadecimal float strings.
+ According to the standard, this is optional.
+5) C99 requires that once an EOF is encountered, the stream should be treated
+ as if at end-of-file even if more data becomes available. Further reading
+ can be attempted by clearing the EOF flag though, via clearerr() or a file
+ positioning function. For details concerning the original change, see
+ Defect Report #141. glibc is currently non-compliant, and the developers
+ did not comment when I asked for their official position on this issue.
+6) glibc's collation routines and/or localedef are broken regarding implicit
+ and explicit UNDEFINED rules.
+
+More to follow as I think of it...
+
+
+
+
+Profiling:
+-------------------------------------------------------------------
+
+uClibc no longer supports 'gcc -fprofile-arcs -pg' style profiling, which
+causes your application to generate a 'gmon.out' file that can then be analyzed
+by 'gprof'. Not only does this require explicit extra support in uClibc, it
+requires that you rebuild everything with profiling support. There is both a
+size and performance penalty to profiling your applications this way, as well
+as Heisenberg effects, where the act of measuring changes what is measured.
+
+There exist a number of less invasive alternatives that do not require you to
+specially instrument your application, and recompile and relink everything.
+
+The OProfile system-wide profiler is an excellent alternative:
+ http://oprofile.sourceforge.net/
+
+Many people have had good results using the combination of Valgrind
+to generate profiling information and KCachegrind for analysis:
+ http://developer.kde.org/~sewardj/
+ http://kcachegrind.sourceforge.net/
+
+Prospect is another alternative based on OProfile:
+ http://prospect.sourceforge.net/
+
+And the Linux Trace Toolkit (LTT) is also a fine tool:
+ http://www.opersys.com/LTT/
+
+FunctionCheck:
+ http://www710.univ-lyon1.fr/~yperret/fnccheck/
+
--- /dev/null
+--- uClibc-0.9.28/Makefile.orig 2006-12-11 21:06:42.000000000 -0700
++++ uClibc-0.9.28/Makefile 2006-12-11 21:06:53.000000000 -0700
+@@ -158,7 +158,7 @@
+ $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)lib
+ $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)include
+ -$(INSTALL) -m 644 lib/*.[ao] $(PREFIX)$(DEVEL_PREFIX)lib/
+- if [ "$(KERNEL_SOURCE)" == "$(DEVEL_PREFIX)" ] ; then \
++ if [ "$(KERNEL_SOURCE)" = "$(DEVEL_PREFIX)" ] ; then \
+ extra_exclude="--exclude include/linux --exclude include/asm'*'" ; \
+ else \
+ extra_exclude="" ; \
+--- uClibc-0.9.28/extra/scripts/fix_includes.sh.orig 2006-12-13 05:44:21.000000000 -0700
++++ uClibc-0.9.28/extra/scripts/fix_includes.sh 2006-12-13 05:44:35.000000000 -0700
+@@ -1,183 +1,155 @@
+ #!/bin/sh
+-# Copyright (C) 2003 Erik Andersen <andersen@uclibc.org>
+ #
+-# This program is free software; you can redistribute it and/or
+-# modify it under the terms of the GNU Library General Public
+-# License as published by the Free Software Foundation; either
+-# version 2 of the License, or (at your option) any later
+-# version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU Library General Public License for more details.
+-#
+-# You should have received a copy of the GNU Library General
+-# Public License along with this program; if not, write to the
+-# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+-# Boston, MA 02111-1307 USA
+-
+-usage () {
+- echo ""
+- echo "usage: "`basename $0`" -k KERNEL_SOURCE_DIRECTORY -t TARGET_ARCH"
+- echo ""
+- echo "This utility scans the KERNEL_SOURCE_DIRECTORY directory and"
+- echo "checks that it contains well formed kernel headers suitable"
+- echo "for inclusion as the include/linux/ directory provided by"
+- echo "uClibc."
+- echo ""
+- echo "If the specified kernel headers are present and already"
+- echo "configured for the architecture specified by TARGET_ARCH,"
+- echo "they will be used as-is."
+- echo ""
+- echo "If the specified kernel headers are missing entirely, this"
+- echo "script will return an error."
+- echo ""
+- echo "If the specified kernel headers are present, but are either"
+- echo "not yet configured or are configured for an architecture"
+- echo "different than that specified by TARGET_ARCH, this script"
+- echo "will attempt to 'fix' the kernel headers and make them"
+- echo "suitable for use by uClibc. This fixing process may fail."
+- echo "It is therefore best to always provide kernel headers that"
+- echo "are already configured for the selected architecture."
+- echo ""
+- echo "Most Linux distributions provide 'kernel-headers' packages"
+- echo "that are suitable for use by uClibc."
+- echo ""
+- echo ""
+- exit 1;
++# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
++#
++# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
++#
++
++usage() {
++ echo ""
++ echo "usage: "`basename $0`" -k KERNEL_SOURCE_DIRECTORY -t TARGET_ARCH"
++ echo ""
++ echo "This utility scans the KERNEL_SOURCE_DIRECTORY directory and"
++ echo "checks that it contains well formed kernel headers suitable"
++ echo "for inclusion as the include/linux/ directory provided by"
++ echo "uClibc."
++ echo ""
++ echo "If the specified kernel headers are present and already"
++ echo "configured for the architecture specified by TARGET_ARCH,"
++ echo "they will be used as-is."
++ echo ""
++ echo "If the specified kernel headers are missing entirely, this"
++ echo "script will return an error."
++ echo ""
++ echo "If the specified kernel headers are present, but are either"
++ echo "not yet configured or are configured for an architecture"
++ echo "different than that specified by TARGET_ARCH, this script"
++ echo "will attempt to 'fix' the kernel headers and make them"
++ echo "suitable for use by uClibc. This fixing process may fail."
++ echo "It is therefore best to always provide kernel headers that"
++ echo "are already configured for the selected architecture."
++ echo ""
++ echo "Most Linux distributions provide 'kernel-headers' packages"
++ echo "that are suitable for use by uClibc."
++ echo ""
++ echo ""
++ exit 1
+ }
+
+-HAS_MMU="y";
++
++#
++# Parse our arguments
++#
++HAS_MMU="y"
+ while [ -n "$1" ]; do
+- case $1 in
+- -k ) shift; if [ -n "$1" ]; then KERNEL_SOURCE=$1; shift; else usage; fi; ;;
+- -t ) shift; if [ -n "$1" ]; then TARGET_ARCH=$1; shift; else usage; fi; ;;
+- -n ) shift; HAS_MMU="n"; ;;
+- -* ) usage; ;;
+- * ) usage; ;;
+- esac;
+-done;
++ case $1 in
++ -k ) shift; if [ -n "$1" ]; then KERNEL_SOURCE=$1; shift; else usage; fi; ;;
++ -t ) shift; if [ -n "$1" ]; then TARGET_ARCH=$1; shift; else usage; fi; ;;
++ -n ) shift; HAS_MMU="n"; ;;
++ -* ) usage; ;;
++ * ) usage; ;;
++ esac
++done
+
+-if [ ! -f "$KERNEL_SOURCE/Makefile" -a ! -f "$KERNEL_SOURCE/include/linux/version.h" ]; then
+- echo "";
+- echo "";
+- echo "The file $KERNEL_SOURCE/Makefile or $KERNEL_SOURCE/include/linux/version.h is missing!";
+- echo "Perhaps your kernel source is broken?"
+- echo "";
+- echo "";
+- exit 1;
+-fi;
+
+-if [ ! -d "$KERNEL_SOURCE" ]; then
+- echo "";
+- echo "";
+- echo "$KERNEL_SOURCE is not a directory";
+- echo "";
+- echo "";
+- exit 1;
+-fi;
+-
+-if [ -f "$KERNEL_SOURCE/Makefile" ] ; then
+-# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
+-eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $KERNEL_SOURCE/Makefile`
+-else
+-ver=`grep UTS_RELEASE $KERNEL_SOURCE/include/linux/version.h | cut -d '"' -f 2`
+-VERSION=`echo "$ver" | cut -d '.' -f 1`
+-PATCHLEVEL=`echo "$ver" | cut -d '.' -f 2`
+-if echo "$ver" | grep -q '-' ; then
+-SUBLEVEL=`echo "$ver" | sed "s/${VERSION}.${PATCHLEVEL}.//" | cut -d '-' -f 1`
+-EXTRAVERSION=`echo "$ver" | sed "s/${VERSION}.${PATCHLEVEL}.${SUBLEVEL}-//"`
+-else
+-SUBLEVEL=`echo "$ver" | cut -d '.' -f 3`
+-#EXTRAVERSION=
+-fi
++#
++# Perform some sanity checks on our kernel sources
++#
++if [ ! -f "$KERNEL_SOURCE/Makefile" -a ! -f "$KERNEL_SOURCE/include/linux/version.h" ]; then
++ echo ""
++ echo ""
++ echo "The file $KERNEL_SOURCE/Makefile or $KERNEL_SOURCE/include/linux/version.h is missing!"
++ echo "Perhaps your kernel source is broken?"
++ echo ""
++ echo ""
++ exit 1
+ fi
+-if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
+-then
+- echo "Unable to determine version for kernel headers"
+- echo -e "\tprovided in directory $KERNEL_SOURCE"
+- exit 1
++if [ ! -d "$KERNEL_SOURCE" ]; then
++ echo ""
++ echo ""
++ echo "$KERNEL_SOURCE is not a directory"
++ echo ""
++ echo ""
++ exit 1
+ fi
+
+-if [ "$MAKE_IS_SILENT" != "y" ]; then
+-echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
+-echo -e "\n"
+-echo "Using kernel headers from $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} for architecture '$TARGET_ARCH'"
+-echo -e "\tprovided in directory $KERNEL_SOURCE"
+-echo -e "\n"
+-fi
+
++#
+ # Create a symlink to include/asm
+-
++#
+ rm -f include/asm*
+ if [ ! -d "$KERNEL_SOURCE/include/asm" ]; then
+- echo "";
+- echo "";
+- echo "The symlink $KERNEL_SOURCE/include/asm is missing\!";
+- echo "Perhaps you forgot to configure your kernel source?";
+- echo "You really should configure your kernel source tree so I";
+- echo "do not have to try and guess about this sort of thing.";
+- echo ""
+- echo "Attempting to guess a usable value....";
+- echo ""
+- echo "";
+- sleep 1;
+-
+- if [ "$TARGET_ARCH" = "powerpc" ];then
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-ppc include/asm;
+- set +x;
+- elif [ "$TARGET_ARCH" = "mips" ];then
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-mips include/asm;
+- set +x;
+- elif [ "$TARGET_ARCH" = "arm" ];then
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-arm include/asm;
+- set +x;
+- if [ ! -L $KERNEL_SOURCE/include/asm-arm/proc ] ; then
+- if [ ! -L proc ] ; then
+- (cd include/asm;
+- ln -fs proc-armv proc;
+- ln -fs arch-ebsa285 arch);
+- fi
++ echo ""
++ echo ""
++ echo "The symlink $KERNEL_SOURCE/include/asm is missing\!"
++ echo "Perhaps you forgot to configure your kernel source?"
++ echo "You really should configure your kernel source tree so I"
++ echo "do not have to try and guess about this sort of thing."
++ echo ""
++ echo "Attempting to guess a usable value...."
++ echo ""
++ echo ""
++ sleep 1
++
++ if [ "$TARGET_ARCH" = "powerpc" ]; then
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-ppc include/asm
++ set +x
++ elif [ "$TARGET_ARCH" = "mips" ]; then
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-mips include/asm
++ set +x
++ elif [ "$TARGET_ARCH" = "arm" ]; then
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-arm include/asm
++ set +x
++ if [ ! -L $KERNEL_SOURCE/include/asm-arm/proc ]; then
++ if [ ! -L proc ]; then
++ (
++ cd include/asm
++ ln -fs proc-armv proc
++ ln -fs arch-ebsa285 arch
++ )
++ fi
++ fi
++ elif [ "$TARGET_ARCH" = "cris" ]; then
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-cris include/asm
++ set +x
++ elif [ "$HAS_MMU" != "y" ]; then
++ if [ -d $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu ]; then
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu include/asm
++ set +x
++ else
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm
++ set +x
++ fi
++ else
++ set -x
++ ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm
++ set +x
+ fi;
+- elif [ "$TARGET_ARCH" = "cris" ]; then
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-cris include/asm;
+- set +x;
+- elif [ "$HAS_MMU" != "y" ]; then
+- if [ -d $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu ] ; then
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu include/asm;
+- set +x;
+- else
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm;
+- set +x;
+- fi;
+- else
+- set -x;
+- ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm;
+- set +x;
+- fi;
+ else
+-# No guessing required.....
+-ln -fs $KERNEL_SOURCE/include/asm include/asm
+-if [ -e $KERNEL_SOURCE/include/asm-$TARGET_ARCH ] ; then
+-ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm-$TARGET_ARCH
++ # No guessing required.....
++ for x in $KERNEL_SOURCE/include/asm* ; do
++ ln -fs ${x} include/
++ done
+ fi
+-fi;
+
+
++#
+ # Annoyingly, 2.6.x kernel headers also need an include/asm-generic/ directory
+-if [ $VERSION -eq 2 ] && [ $PATCHLEVEL -ge 6 ] ; then
+- ln -fs $KERNEL_SOURCE/include/asm-generic include/asm-generic
+-fi;
++#
++if [ -e $KERNEL_SOURCE/include/asm-generic ]; then
++ rm -f include/asm-generic
++ ln -fs $KERNEL_SOURCE/include/asm-generic include/asm-generic
++fi
+
+
++#
+ # Create the include/linux symlink.
++#
+ rm -f include/linux
+ ln -fs $KERNEL_SOURCE/include/linux include/linux
+-
--- /dev/null
+This patch supports cross-development for embedded systems by allowing the
+host version of ldconfig (ldconfig.host) to build ld.so.cache for the target.
+Changes include:
+ 1) LDSO_CACHE_SUPPORT is defined for the host build.
+ 2) A little-endian host can create a big-endian ld.so.cache, and vice versa.
+ 3) Can use -r option without chroot(), so no need to run as superuser.
+
+Dan Howell <dahowell@directv.com>
+
+diff -urN uClibc-orig/utils/chroot_realpath.c uClibc-20050502/utils/chroot_realpath.c
+--- uClibc-orig/utils/chroot_realpath.c 1969-12-31 16:00:00.000000000 -0800
++++ uClibc-20050502/utils/chroot_realpath.c 2005-09-12 18:30:29.000000000 -0700
+@@ -0,0 +1,163 @@
++/*
++ * chroot_realpath.c -- reslove pathname as if inside chroot
++ * Based on realpath.c Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Library Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Library Public License for more details.
++ *
++ * 2005/09/12: Dan Howell (modified from realpath.c to emulate chroot)
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <sys/types.h>
++#include <unistd.h>
++#include <stdio.h>
++#include <string.h>
++#include <strings.h>
++#include <limits.h> /* for PATH_MAX */
++#include <sys/param.h> /* for MAXPATHLEN */
++#include <errno.h>
++#ifndef __set_errno
++#define __set_errno(val) ((errno) = (val))
++#endif
++
++#include <sys/stat.h> /* for S_IFLNK */
++
++#ifndef PATH_MAX
++#define PATH_MAX _POSIX_PATH_MAX
++#endif
++
++#define MAX_READLINKS 32
++
++char *chroot_realpath(const char *chroot, const char *path, char resolved_path[])
++{
++ char copy_path[PATH_MAX];
++ char link_path[PATH_MAX];
++ char got_path[PATH_MAX];
++ char *got_path_root = got_path;
++ char *new_path = got_path;
++ char *max_path;
++ int readlinks = 0;
++ int n;
++ int chroot_len;
++
++ /* Trivial case. */
++ if (chroot == NULL || *chroot == '\0' ||
++ (*chroot == '/' && chroot[1] == '\0')) {
++ strcpy(resolved_path, path);
++ return resolved_path;
++ }
++
++ chroot_len = strlen(chroot);
++
++ if (chroot_len + strlen(path) >= PATH_MAX - 3) {
++ __set_errno(ENAMETOOLONG);
++ return NULL;
++ }
++
++ /* Make a copy of the source path since we may need to modify it. */
++ strcpy(copy_path, path);
++ path = copy_path;
++ max_path = copy_path + PATH_MAX - chroot_len - 3;
++
++ /* Start with the chroot path. */
++ strcpy(new_path, chroot);
++ new_path += chroot_len;
++ while (*new_path == '/' && new_path > got_path)
++ new_path--;
++ got_path_root = new_path;
++ *new_path++ = '/';
++
++ /* Expand each slash-separated pathname component. */
++ while (*path != '\0') {
++ /* Ignore stray "/". */
++ if (*path == '/') {
++ path++;
++ continue;
++ }
++ if (*path == '.') {
++ /* Ignore ".". */
++ if (path[1] == '\0' || path[1] == '/') {
++ path++;
++ continue;
++ }
++ if (path[1] == '.') {
++ if (path[2] == '\0' || path[2] == '/') {
++ path += 2;
++ /* Ignore ".." at root. */
++ if (new_path == got_path_root + 1)
++ continue;
++ /* Handle ".." by backing up. */
++ while ((--new_path)[-1] != '/');
++ continue;
++ }
++ }
++ }
++ /* Safely copy the next pathname component. */
++ while (*path != '\0' && *path != '/') {
++ if (path > max_path) {
++ __set_errno(ENAMETOOLONG);
++ return NULL;
++ }
++ *new_path++ = *path++;
++ }
++ if (*path == '\0')
++ /* Don't follow symlink for last pathname component. */
++ break;
++#ifdef S_IFLNK
++ /* Protect against infinite loops. */
++ if (readlinks++ > MAX_READLINKS) {
++ __set_errno(ELOOP);
++ return NULL;
++ }
++ /* See if latest pathname component is a symlink. */
++ *new_path = '\0';
++ n = readlink(got_path, link_path, PATH_MAX - 1);
++ if (n < 0) {
++ /* EINVAL means the file exists but isn't a symlink. */
++ if (errno != EINVAL) {
++ /* Make sure it's null terminated. */
++ *new_path = '\0';
++ strcpy(resolved_path, got_path);
++ return NULL;
++ }
++ } else {
++ /* Note: readlink doesn't add the null byte. */
++ link_path[n] = '\0';
++ if (*link_path == '/')
++ /* Start over for an absolute symlink. */
++ new_path = got_path_root;
++ else
++ /* Otherwise back up over this component. */
++ while (*(--new_path) != '/');
++ /* Safe sex check. */
++ if (strlen(path) + n >= PATH_MAX - 2) {
++ __set_errno(ENAMETOOLONG);
++ return NULL;
++ }
++ /* Insert symlink contents into path. */
++ strcat(link_path, path);
++ strcpy(copy_path, link_path);
++ path = copy_path;
++ }
++#endif /* S_IFLNK */
++ *new_path++ = '/';
++ }
++ /* Delete trailing slash but don't whomp a lone slash. */
++ if (new_path != got_path + 1 && new_path[-1] == '/')
++ new_path--;
++ /* Make sure it's null terminated. */
++ *new_path = '\0';
++ strcpy(resolved_path, got_path);
++ return resolved_path;
++}
+diff -urN uClibc-orig/utils/ldconfig.c uClibc-20050502/utils/ldconfig.c
+--- uClibc-orig/utils/ldconfig.c 2005-05-01 23:10:12.000000000 -0700
++++ uClibc-20050502/utils/ldconfig.c 2005-09-16 19:26:33.000000000 -0700
+@@ -22,6 +22,8 @@
+ *
+ * This program may be used for any purpose as long as this
+ * copyright notice is kept.
++ *
++ * 2005/09/16: Dan Howell (modified for cross-development)
+ */
+
+ #include <stdio.h>
+@@ -37,6 +39,7 @@
+ #include <errno.h>
+ #include <sys/stat.h>
+ #include <sys/mman.h>
++#include "bswap.h"
+ #include "dl-defs.h"
+
+ #define BUFFER_SIZE 4096
+@@ -56,6 +59,7 @@
+ #if !defined (N_MAGIC)
+ #define N_MAGIC(exec) ((exec).a_info & 0xffff)
+ #endif
++#define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff)
+ /* Code indicating object file or impure executable. */
+ #define OMAGIC 0407
+ /* Code indicating pure executable. */
+@@ -97,6 +101,8 @@
+ char *conffile = LDSO_CONF; /* default conf file */
+ char *cachefile = LDSO_CACHE; /* default cache file */
+ #endif
++char *chroot_dir = NULL;
++int byteswap = 0;
+
+ struct needed_tab
+ {
+@@ -117,6 +123,8 @@
+ { NULL, LIB_ELF }
+ };
+
++extern char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]);
++
+
+ /* These two are used internally -- you shouldn't need to use them */
+ static void verror_msg(const char *s, va_list p)
+@@ -242,6 +250,8 @@
+ ElfW(Ehdr) *elf_hdr;
+ struct stat statbuf;
+ char buff[BUFFER_SIZE];
++ char real[BUFFER_SIZE];
++ static int byteswapflag = -1; /* start with byte-order unknown */
+
+ /* see if name is of the form *.so* */
+ if (name[strlen(name)-1] != '~' && (cp = strstr(name, ".so")))
+@@ -256,8 +266,12 @@
+ sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ?
+ "/" : "", name);
+
++ /* get real path in case of chroot */
++ if (!chroot_realpath(chroot_dir, buff, real))
++ warn("can't resolve %s in chroot %s", buff, chroot_dir);
++
+ /* first, make sure it's a regular file */
+- if (lstat(buff, &statbuf))
++ if (lstat(real, &statbuf))
+ warn("skipping %s", buff);
+ else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
+ warnx("%s is not a regular file or symlink, skipping", buff);
+@@ -267,14 +281,15 @@
+ *islink = S_ISLNK(statbuf.st_mode);
+
+ /* then try opening it */
+- if (!(file = fopen(buff, "rb")))
++ if (!(file = fopen(real, "rb")))
+ warn("skipping %s", buff);
+ else
+ {
+ /* now make sure it's a shared library */
+ if (fread(&exec, sizeof exec, 1, file) < 1)
+ warnx("can't read header from %s, skipping", buff);
+- else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC)
++ else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC &&
++ N_MAGIC_SWAP(exec) != ZMAGIC && N_MAGIC_SWAP(exec) != QMAGIC)
+ {
+ elf_hdr = (ElfW(Ehdr) *) &exec;
+ if (elf_hdr->e_ident[0] != 0x7f ||
+@@ -294,6 +309,9 @@
+ *type = LIB_ELF;
+ good = readsoname(buff, file, expected_type, type,
+ elf_hdr->e_ident[EI_CLASS]);
++ if (byteswapflag == -1)
++ /* byte-order detected */
++ byteswapflag = byteswap;
+ if (good == NULL || *islink)
+ {
+ if (good != NULL)
+@@ -313,6 +331,12 @@
+ }
+ else
+ {
++ /* Determine byte-order */
++ byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1;
++ if (byteswapflag == -1)
++ /* byte-order detected */
++ byteswapflag = byteswap;
++
+ if (*islink)
+ good = xstrdup(name);
+ else
+@@ -330,6 +354,14 @@
+ *type = LIB_DLL;
+ }
+ fclose(file);
++
++ if (byteswapflag >= 0 && byteswap != byteswapflag)
++ {
++ byteswapflag = -2;
++ warnx("mixed byte-order detected, using host byte-order...");
++ }
++ if (byteswapflag == -2)
++ byteswap = 0;
+ }
+ }
+ }
+@@ -343,18 +375,24 @@
+ int change = 1;
+ char libname[BUFFER_SIZE];
+ char linkname[BUFFER_SIZE];
++ char reallibname[BUFFER_SIZE];
++ char reallinkname[BUFFER_SIZE];
+ struct stat libstat;
+ struct stat linkstat;
+
+ /* construct the full path names */
+ sprintf(libname, "%s/%s", dir, file);
+ sprintf(linkname, "%s/%s", dir, so);
++ if (!chroot_realpath(chroot_dir, libname, reallibname))
++ warn("can't resolve %s in chroot %s", libname, chroot_dir);
++ if (!chroot_realpath(chroot_dir, linkname, reallinkname))
++ warn("can't resolve %s in chroot %s", linkname, chroot_dir);
+
+ /* see if a link already exists */
+- if (!stat(linkname, &linkstat))
++ if (!stat(reallinkname, &linkstat))
+ {
+ /* now see if it's the one we want */
+- if (stat(libname, &libstat))
++ if (stat(reallibname, &libstat))
+ warn("can't stat %s", libname);
+ else if (libstat.st_dev == linkstat.st_dev &&
+ libstat.st_ino == linkstat.st_ino)
+@@ -364,14 +402,14 @@
+ /* then update the link, if required */
+ if (change > 0 && !nolinks)
+ {
+- if (!lstat(linkname, &linkstat))
++ if (!lstat(reallinkname, &linkstat))
+ {
+ if (!S_ISLNK(linkstat.st_mode))
+ {
+ warnx("%s is not a symlink", linkname);
+ change = -1;
+ }
+- else if (remove(linkname))
++ else if (remove(reallinkname))
+ {
+ warn("can't unlink %s", linkname);
+ change = -1;
+@@ -379,7 +417,7 @@
+ }
+ if (change > 0)
+ {
+- if (symlink(file, linkname))
++ if (symlink(file, reallinkname))
+ {
+ warn("can't link %s to %s", linkname, file);
+ change = -1;
+@@ -441,6 +479,7 @@
+ char *so, *path, *path_n;
+ struct lib *lp, *libs = NULL;
+ int i, libtype, islink, expected_type = LIB_ANY;
++ char realname[BUFFER_SIZE];
+
+ /* We need a writable copy of this string */
+ path = strdup(rawname);
+@@ -500,8 +539,12 @@
+ if (verbose > 0)
+ printf("%s:\n", name);
+
++ /* get real path in case of chroot */
++ if (!chroot_realpath(chroot_dir, name, realname))
++ warn("can't resolve %s in chroot %s", name, chroot_dir);
++
+ /* if we can't open it, we can't do anything */
+- if ((dir = opendir(name)) == NULL)
++ if ((dir = opendir(realname)) == NULL)
+ {
+ warn("skipping %s", name);
+ free(path);
+@@ -596,8 +639,12 @@
+ char *res = NULL, *cp;
+ FILE *file;
+ struct stat stat;
++ char realconffile[BUFFER_SIZE];
++
++ if (!chroot_realpath(chroot_dir, conffile, realconffile))
++ return NULL;
+
+- if ((file = fopen(conffile, "r")) != NULL)
++ if ((file = fopen(realconffile, "r")) != NULL)
+ {
+ fstat(fileno(file), &stat);
+ res = xmalloc(stat.st_size + 1);
+@@ -678,22 +725,38 @@
+ {
+ int cachefd;
+ int stroffset = 0;
++ char realcachefile[BUFFER_SIZE];
+ char tempfile[BUFFER_SIZE];
++ header_t swap_magic;
++ header_t *magic_ptr;
++ libentry_t swap_lib;
++ libentry_t *lib_ptr;
+ liblist_t *cur_lib;
+
+ if (!magic.nlibs)
+ return;
+
+- sprintf(tempfile, "%s~", cachefile);
++ if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
++ err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)",
++ cachefile, chroot_dir, strerror(errno));
++
++ sprintf(tempfile, "%s~", realcachefile);
+
+ if (unlink(tempfile) && errno != ENOENT)
+- err(EXIT_FATAL,"can't unlink %s (%s)", tempfile, strerror(errno));
++ err(EXIT_FATAL,"can't unlink %s~ (%s)", cachefile, strerror(errno));
+
+ if ((cachefd = creat(tempfile, 0644)) < 0)
+- err(EXIT_FATAL,"can't create %s (%s)", tempfile, strerror(errno));
++ err(EXIT_FATAL,"can't create %s~ (%s)", cachefile, strerror(errno));
+
+- if (write(cachefd, &magic, sizeof (header_t)) != sizeof (header_t))
+- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
++ if (byteswap) {
++ swap_magic = magic;
++ swap_magic.nlibs = bswap_32(swap_magic.nlibs);
++ magic_ptr = &swap_magic;
++ } else {
++ magic_ptr = &magic;
++ }
++ if (write(cachefd, magic_ptr, sizeof (header_t)) != sizeof (header_t))
++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
+
+ for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next)
+ {
+@@ -701,29 +764,37 @@
+ stroffset += strlen(cur_lib->soname) + 1;
+ cur_lib->liboffset = stroffset;
+ stroffset += strlen(cur_lib->libname) + 1;
+- if (write(cachefd, cur_lib, sizeof (libentry_t)) !=
+- sizeof (libentry_t))
+- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
++ if (byteswap) {
++ swap_lib.flags = bswap_32(cur_lib->flags);
++ swap_lib.sooffset = bswap_32(cur_lib->sooffset);
++ swap_lib.liboffset = bswap_32(cur_lib->liboffset);
++ lib_ptr = &swap_lib;
++ } else {
++ lib_ptr = (libentry_t *)cur_lib;
++ }
++ if (write(cachefd, lib_ptr, sizeof (libentry_t)) !=
++ sizeof (libentry_t))
++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
+ }
+
+ for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next)
+ {
+ if (write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1)
+ != strlen(cur_lib->soname) + 1)
+- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
+ if (write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1)
+ != strlen(cur_lib->libname) + 1)
+- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
++ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
+ }
+
+ if (close(cachefd))
+- err(EXIT_FATAL,"can't close %s (%s)", tempfile, strerror(errno));
++ err(EXIT_FATAL,"can't close %s~ (%s)", cachefile, strerror(errno));
+
+ if (chmod(tempfile, 0644))
+- err(EXIT_FATAL,"can't chmod %s (%s)", tempfile, strerror(errno));
++ err(EXIT_FATAL,"can't chmod %s~ (%s)", cachefile, strerror(errno));
+
+- if (rename(tempfile, cachefile))
+- err(EXIT_FATAL,"can't rename %s (%s)", tempfile, strerror(errno));
++ if (rename(tempfile, realcachefile))
++ err(EXIT_FATAL,"can't rename %s~ (%s)", cachefile, strerror(errno));
+ }
+
+ void cache_print(void)
+@@ -734,8 +805,13 @@
+ char *strs;
+ header_t *header;
+ libentry_t *libent;
++ char realcachefile[BUFFER_SIZE];
++
++ if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
++ err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)",
++ cachefile, chroot_dir, strerror(errno));
+
+- if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY))<0)
++ if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY))<0)
+ err(EXIT_FATAL,"can't read %s (%s)", cachefile, strerror(errno));
+ if ((c = mmap(0,st.st_size, PROT_READ, MAP_SHARED ,fd, 0)) == (caddr_t)-1)
+ err(EXIT_FATAL,"can't map %s (%s)", cachefile, strerror(errno));
+@@ -828,7 +904,6 @@
+ int nodefault = 0;
+ char *cp, *dir, *so;
+ int libtype, islink;
+- char *chroot_dir = NULL;
+ int printcache = 0;
+ #ifdef __LDSO_CACHE_SUPPORT__
+ char *extpath;
+@@ -891,10 +966,16 @@
+ }
+
+ if (chroot_dir && *chroot_dir) {
+- if (chroot(chroot_dir) < 0)
+- err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
+- if (chdir("/") < 0)
+- err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno));
++ if (chroot(chroot_dir) < 0) {
++ if (chdir(chroot_dir) < 0)
++ err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
++ }
++ else
++ {
++ if (chdir("/") < 0)
++ err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno));
++ chroot_dir = NULL;
++ }
+ }
+
+ /* allow me to introduce myself, hi, my name is ... */
+diff -urN uClibc-orig/utils/Makefile uClibc-20050502/utils/Makefile
+--- uClibc-orig/utils/Makefile 2005-05-01 23:10:12.000000000 -0700
++++ uClibc-20050502/utils/Makefile 2005-09-16 19:28:55.000000000 -0700
+@@ -29,6 +29,12 @@
+ TARGET_ICONV =
+ endif
+
++ifeq ($(strip $(LDSO_CACHE_SUPPORT)),y)
++HOST_LDSO_CACHE_FLAG = -D__LDSO_CACHE_SUPPORT__=1
++else
++HOST_LDSO_CACHE_FLAG =
++endif
++
+ # NOTE: We build the utils AFTER we have a uClibc-targeted toolchain.
+
+ ifeq ($(strip $(HAVE_SHARED)),y)
+@@ -51,7 +57,7 @@
+ else
+ LDCONFIG_CFLAGS := $(PIEFLAG) $(LDPIEFLAG)
+ endif
+-ldconfig: ldconfig.c
++ldconfig: ldconfig.c chroot_realpath.c
+ $(CC) $(CFLAGS) $(LDCONFIG_CFLAGS) \
+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+ -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
+@@ -79,13 +85,13 @@
+
+ ldd.host: ldd.c
+ $(HOSTCC) $(HOSTCFLAGS) -Wl,-s \
+- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
++ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \
+ -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
+ $^ -o $@
+
+-ldconfig.host: ldconfig.c
++ldconfig.host: ldconfig.c chroot_realpath.c
+ $(HOSTCC) $(HOSTCFLAGS) -Wl,-s \
+- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
++ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \
+ -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
+ $^ -o $@
+
+diff -urN uClibc-orig/utils/readsoname2.c uClibc-20050502/utils/readsoname2.c
+--- uClibc-orig/utils/readsoname2.c 2005-05-01 23:10:12.000000000 -0700
++++ uClibc-20050502/utils/readsoname2.c 2005-09-16 17:48:59.000000000 -0700
+@@ -26,7 +26,7 @@
+
+ if (fstat(fileno(infile), &st))
+ return NULL;
+- header = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(infile), 0);
++ header = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(infile), 0);
+ if (header == (caddr_t)-1)
+ return NULL;
+
+@@ -34,6 +34,19 @@
+ if ((char *)(epnt+1) > (char *)(header + st.st_size))
+ goto skip;
+
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++ byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0;
++#elif __BYTE_ORDER == __BIG_ENDIAN
++ byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0;
++#else
++#error Unknown host byte order!
++#endif
++ /* Be very lazy, and only byteswap the stuff we use */
++ if (byteswap==1) {
++ epnt->e_phoff=bswap_32(epnt->e_phoff);
++ epnt->e_phnum=bswap_16(epnt->e_phnum);
++ }
++
+ ppnt = (ElfW(Phdr) *)&header[epnt->e_phoff];
+ if ((char *)ppnt < (char *)header ||
+ (char *)(ppnt+epnt->e_phnum) > (char *)(header + st.st_size))
+@@ -41,6 +54,14 @@
+
+ for(i = 0; i < epnt->e_phnum; i++)
+ {
++ /* Be very lazy, and only byteswap the stuff we use */
++ if (byteswap==1) {
++ ppnt->p_type=bswap_32(ppnt->p_type);
++ ppnt->p_vaddr=bswap_32(ppnt->p_vaddr);
++ ppnt->p_offset=bswap_32(ppnt->p_offset);
++ ppnt->p_filesz=bswap_32(ppnt->p_filesz);
++ }
++
+ if (loadaddr == -1 && ppnt->p_type == PT_LOAD)
+ loadaddr = (ppnt->p_vaddr & ~(page_size-1)) -
+ (ppnt->p_offset & ~(page_size-1));
+@@ -58,11 +79,20 @@
+ (char *)(dpnt+dynamic_size) > (char *)(header + st.st_size))
+ goto skip;
+
++ if (byteswap==1) {
++ dpnt->d_tag=bswap_32(dpnt->d_tag);
++ dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val);
++ }
++
+ while (dpnt->d_tag != DT_NULL)
+ {
+ if (dpnt->d_tag == DT_STRTAB)
+ strtab_val = dpnt->d_un.d_val;
+ dpnt++;
++ if (byteswap==1) {
++ dpnt->d_tag=bswap_32(dpnt->d_tag);
++ dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val);
++ }
+ };
+
+ if (!strtab_val)
--- /dev/null
+diff -urN uClibc-0.9.28.orig/include/elf.h uClibc-0.9.28/include/elf.h
+--- uClibc-0.9.28.orig/include/elf.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/include/elf.h 2006-04-28 00:14:35.000000000 -0600
+@@ -142,6 +142,7 @@
+ #define ELFOSABI_HPUX 1 /* HP-UX */
+ #define ELFOSABI_NETBSD 2 /* NetBSD. */
+ #define ELFOSABI_LINUX 3 /* Linux. */
++#define ELFOSABI_HURD 4 /* GNU/Hurd */
+ #define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
+ #define ELFOSABI_AIX 7 /* IBM AIX. */
+ #define ELFOSABI_IRIX 8 /* SGI Irix. */
+@@ -149,6 +150,9 @@
+ #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
+ #define ELFOSABI_MODESTO 11 /* Novell Modesto. */
+ #define ELFOSABI_OPENBSD 12 /* OpenBSD. */
++#define ELFOSABI_OPENVMS 13 /* OpenVMS */
++#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */
++#define ELFOSABI_AROS 15 /* Amiga Research OS */
+ #define ELFOSABI_ARM 97 /* ARM */
+ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+@@ -177,6 +181,7 @@
+ #define EM_386 3 /* Intel 80386 */
+ #define EM_68K 4 /* Motorola m68k family */
+ #define EM_88K 5 /* Motorola m88k family */
++#define EM_486 6 /* Intel 80486 *//* Reserved for future use */
+ #define EM_860 7 /* Intel 80860 */
+ #define EM_MIPS 8 /* MIPS R3000 big-endian */
+ #define EM_S370 9 /* IBM System/370 */
+@@ -193,7 +198,8 @@
+ #define EM_V800 36 /* NEC V800 series */
+ #define EM_FR20 37 /* Fujitsu FR20 */
+ #define EM_RH32 38 /* TRW RH-32 */
+-#define EM_RCE 39 /* Motorola RCE */
++#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */
++#define EM_RCE 39 /* Old name for MCore */
+ #define EM_ARM 40 /* ARM */
+ #define EM_FAKE_ALPHA 41 /* Digital Alpha */
+ #define EM_SH 42 /* Renesas SH */
+@@ -248,18 +254,105 @@
+ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
++#define EM_IP2K 101 /* Ubicom IP2022 micro controller */
++#define EM_CR 103 /* National Semiconductor CompactRISC */
++#define EM_MSP430 105 /* TI msp430 micro controller */
++#define EM_BLACKFIN 106 /* Analog Devices Blackfin */
++#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
++#define EM_CRX 114 /* National Semiconductor CRX */
+ #define EM_NUM 95
+
+-/* If it is necessary to assign new unofficial EM_* values, please
+- pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+- chances of collision with official or non-GNU unofficial values. */
++/* If it is necessary to assign new unofficial EM_* values, please pick large
++ random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
++ with official or non-GNU unofficial values.
+
+-/* Fujitsu FR-V. */
++ NOTE: Do not just increment the most recent number by one.
++ Somebody else somewhere will do exactly the same thing, and you
++ will have a collision. Instead, pick a random number.
++
++ Normally, each entity or maintainer responsible for a machine with an
++ unofficial e_machine number should eventually ask registry@caldera.com for
++ an officially blessed number to be added to the list above. */
++
++/* picoJava */
++#define EM_PJ_OLD 99
++
++/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */
++#define EM_CYGNUS_POWERPC 0x9025
++
++/* Old version of Sparc v9, from before the ABI; this should be
++ removed shortly. */
++#define EM_OLD_SPARCV9 11
++
++/* Old version of PowerPC, this should be removed shortly. */
++#define EM_PPC_OLD 17
++
++/* (Deprecated) Temporary number for the OpenRISC processor. */
++#define EM_OR32 0x8472
++
++/* Renesas M32C and M16C. */
++#define EM_M32C 0xFEB0
++
++/* Cygnus M32R ELF backend. Written in the absence of an ABI. */
++#define EM_CYGNUS_M32R 0x9041
++
++/* old S/390 backend magic number. Written in the absence of an ABI. */
++#define EM_S390_OLD 0xa390
++
++/* D10V backend magic number. Written in the absence of an ABI. */
++#define EM_CYGNUS_D10V 0x7650
++
++/* D30V backend magic number. Written in the absence of an ABI. */
++#define EM_CYGNUS_D30V 0x7676
++
++/* V850 backend magic number. Written in the absense of an ABI. */
++#define EM_CYGNUS_V850 0x9080
++
++/* mn10200 and mn10300 backend magic numbers.
++ Written in the absense of an ABI. */
++#define EM_CYGNUS_MN10200 0xdead
++#define EM_CYGNUS_MN10300 0xbeef
++
++/* FR30 magic number - no EABI available. */
++#define EM_CYGNUS_FR30 0x3330
++
++/* AVR magic number
++ Written in the absense of an ABI. */
++#define EM_AVR_OLD 0x1057
++
++/* OpenRISC magic number
++ Written in the absense of an ABI. */
++#define EM_OPENRISC_OLD 0x3426
++
++/* DLX magic number
++ Written in the absense of an ABI. */
++#define EM_DLX 0x5aa5
++
++#define EM_XSTORMY16 0xad45
++
++/* FRV magic number - no EABI available??. */
+ #define EM_CYGNUS_FRV 0x5441
+
++/* Ubicom IP2xxx; no ABI */
++#define EM_IP2K_OLD 0x8217
++
++#define EM_MT 0x2530 /* Morpho MT; no ABI */
++
++/* MSP430 magic number
++ Written in the absense everything. */
++#define EM_MSP430_OLD 0x1059
++
++/* Vitesse IQ2000. */
++#define EM_IQ2000 0xFEBA
++
++/* Old, unofficial value for Xtensa. */
++#define EM_XTENSA_OLD 0xabc7
++
++/* Alpha backend magic number. Written in the absence of an ABI. */
+ #define EM_ALPHA 0x9026
+-#define EM_NIOS32 0xfebb /* Altera Nios 32 */
+-#define EM_ALTERA_NIOS2 0x9ee5 /* Altera Nios II */
++
++/* NIOS magic number - no EABI available. */
++#define EM_NIOS32 0xFEBB
+
+ /* V850 backend magic number. Written in the absense of an ABI. */
+ #define EM_CYGNUS_V850 0x9080
+@@ -2498,6 +2591,12 @@
+ #define R_390_NUM 61
+
+
++/* CRIS flags. */
++#define EF_CRIS_VARIANT_MASK 0x0000000e
++#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000
++#define EF_CRIS_VARIANT_V32 0x00000002
++#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004
++
+ /* CRIS relocations. */
+ #define R_CRIS_NONE 0
+ #define R_CRIS_8 1
+@@ -2688,6 +2787,7 @@
+ #define R_V850_NUM 25
+
+
++/* Renesas H8/300 Relocations */
+ #define R_H8_NONE 0
+ #define R_H8_DIR32 1
+ #define R_H8_DIR32_28 2
+@@ -2731,8 +2831,7 @@
+ #define R_H8_DIR32A16 63
+ #define R_H8_ABS32 65
+ #define R_H8_ABS32A16 127
+-
+-/* Altera NIOS specific definitions. */
++#define R_H8_NUM 128
+
+ /* NIOS relocations. */
+ #define R_NIOS_NONE 0
+diff -urN uClibc-0.9.28.orig/include/errno.h uClibc-0.9.28/include/errno.h
+--- uClibc-0.9.28.orig/include/errno.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/include/errno.h 2006-04-28 00:14:35.000000000 -0600
+@@ -43,9 +43,11 @@
+ variable. This redeclaration using the macro still works, but it
+ will be a function declaration without a prototype and may trigger
+ a -Wstrict-prototypes warning. */
++#ifndef __ASSEMBLER__
+ #ifndef errno
+ extern int errno;
+ #endif
++#endif
+
+ #if 0 /*def __USE_GNU uClibc note: not supported */
+
+diff -urN uClibc-0.9.28.orig/ldso/Makefile uClibc-0.9.28/ldso/Makefile
+--- uClibc-0.9.28.orig/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600
+@@ -37,15 +37,12 @@
+
+ LN_HEADERS := $(patsubst %, include/%, elf.h)
+ LN_ARCH_HEADERS := $(patsubst %, include/%, dl-startup.h dl-syscalls.h dl-sysdep.h dl-debug.h)
+-HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS) include/dl-progname.h
++HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS)
+ headers: $(HEADERS)
+ $(LN_HEADERS):
+ $(LN) -fs $(TOPDIR)../$@ $@
+ $(LN_ARCH_HEADERS):
+ $(LN) -fs ../ldso/$(TARGET_ARCH)/$(patsubst include/%,%,$@) $@
+-include/dl-progname.h:
+- echo '#include "$(TARGET_ARCH)/elfinterp.c"' \
+- > include/dl-progname.h
+
+ clean:
+ set -e ; for d in $(DIRS) ; do $(MAKE) -C $$d $@ ; done
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-defs.h uClibc-0.9.28/ldso/include/dl-defs.h
+--- uClibc-0.9.28.orig/ldso/include/dl-defs.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-defs.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,6 +1,29 @@
++/* 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_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
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-elf.h uClibc-0.9.28/ldso/include/dl-elf.h
+--- uClibc-0.9.28.orig/ldso/include/dl-elf.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-elf.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* 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
+
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-hash.h uClibc-0.9.28/ldso/include/dl-hash.h
+--- uClibc-0.9.28.orig/ldso/include/dl-hash.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-hash.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* 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_HASH_H_
+ #define _LD_HASH_H_
+
+@@ -32,15 +39,15 @@
+ unsigned short usage_count;
+ unsigned short int init_flag;
+ unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
+- Elf32_Word nbucket;
+- Elf32_Word *elf_buckets;
++ Elf_Symndx nbucket;
++ Elf_Symndx *elf_buckets;
+ 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
+ */
+- Elf32_Word nchain;
+- Elf32_Word *chains;
++ Elf_Symndx nchain;
++ Elf_Symndx *chains;
+ unsigned long dynamic_info[DYNAMIC_SIZE];
+
+ unsigned long n_phent;
+@@ -49,6 +56,9 @@
+ 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 */
+@@ -66,7 +76,6 @@
+ extern struct elf_resolve * _dl_loaded_modules;
+ extern struct dyn_elf * _dl_handles;
+
+-extern struct elf_resolve * _dl_check_hashed_files(const char * libname);
+ extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
+ char * loadaddr, unsigned long * dynamic_info,
+ unsigned long dynamic_addr, unsigned long dynamic_size);
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-string.h uClibc-0.9.28/ldso/include/dl-string.h
+--- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-string.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,9 +1,24 @@
++/* 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 <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);
+@@ -26,8 +41,8 @@
+ static __always_inline size_t _dl_strlen(const char * str)
+ {
+ register const char *ptr = (char *) str-1;
+-
+- while (*++ptr);
++ while (*++ptr)
++ ;/* empty */
+ return (ptr - str);
+ }
+
+@@ -49,7 +64,8 @@
+ register char *ptr = dst;
+
+ dst--;src--;
+- while ((*++dst = *++src) != 0);
++ while ((*++dst = *++src) != 0)
++ ;/* empty */
+
+ return ptr;
+ }
+@@ -63,8 +79,7 @@
+ c2 = (unsigned char) *++s2;
+ if (c1 == '\0')
+ return c1 - c2;
+- }
+- while (c1 == c2);
++ } while (c1 == c2);
+
+ return c1 - c2;
+ }
+@@ -98,43 +113,41 @@
+ return 0;
+ }
+
+-static inline char * _dl_strrchr(const char *str, int c)
++static __always_inline char * _dl_strrchr(const char *str, int c)
+ {
+- register char *prev = 0;
+- register char *ptr = (char *) str-1;
++ 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);
++ while (*++ptr != '\0') {
++ if (*ptr == c)
++ prev = ptr;
++ }
++ if (c == '\0')
++ return(ptr);
++ return(prev);
+ }
+
+-static inline char * _dl_strstr(const char *s1, const char *s2)
++static __always_inline char * _dl_strstr(const char *s1, const char *s2)
+ {
+- register const char *s = s1;
+- register const char *p = 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);
++ do {
++ if (!*p)
++ return (char *) s1;;
++ if (*p == *s) {
++ ++p;
++ ++s;
++ } else {
++ p = s2;
++ if (!*s)
++ return NULL;
++ s = ++s1;
++ }
++ } while (1);
+ }
+
+-static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
++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;
+@@ -163,27 +176,28 @@
+ /* 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 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;
++ 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)
+@@ -225,10 +239,10 @@
+ char *p = &local[22];
+ *--p = '\0';
+ do {
+- char temp;
+- do_rem(temp, i, 10);
+- *--p = '0' + temp;
+- i /= 10;
++ char temp;
++ do_rem(temp, i, 10);
++ *--p = '0' + temp;
++ do_div_10(i, temp);
+ } while (i > 0);
+ return p;
+ }
+@@ -242,9 +256,9 @@
+ do {
+ char temp = i & 0xf;
+ if (temp <= 0x09)
+- *--p = '0' + temp;
++ *--p = '0' + temp;
+ else
+- *--p = 'a' - 0x0a + temp;
++ *--p = 'a' - 0x0a + temp;
+ i >>= 4;
+ } while (i > 0);
+ *--p = 'x';
+@@ -270,8 +284,8 @@
+
+ /* 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(__mips__) \
+- || defined(__sh__) || defined(__powerpc__)
++#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \
++ defined(__mips__) || defined(__sh__) || defined(__powerpc__)
+ # define CONSTANT_STRING_GOT_FIXUP(X) \
+ if ((X) < (const char *) load_addr) (X) += load_addr
+ # define NO_EARLY_SEND_STDERR
+@@ -318,7 +332,7 @@
+ do { \
+ do_rem(v, (X), 10); \
+ *--tmp2 = '0' + v; \
+- (X) /= 10; \
++ do_div_10((X), v); \
+ } while ((X) > 0); \
+ _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
+ }
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-syscall.h uClibc-0.9.28/ldso/include/dl-syscall.h
+--- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* 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_
+
+@@ -12,9 +19,8 @@
+ #include <bits/kernel_stat.h>
+ #include <bits/kernel_types.h>
+
+-
+ /* _dl_open() parameters */
+-#define O_RDONLY 0x0000
++#define O_RDONLY 00
+ #define O_WRONLY 01
+ #define O_RDWR 02
+ #define O_CREAT 0100
+@@ -39,18 +45,6 @@
+ #define S_IWRITE 0200 /* Write by owner. */
+ #define S_IEXEC 0100 /* Execute by owner. */
+
+-/* Stuff for _dl_mmap */
+-#if 0
+-#define MAP_FAILED ((void *) -1)
+-#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
+-#else
+-#ifndef _dl_MAX_ERRNO
+-#define _dl_MAX_ERRNO 4096
+-#endif
+-#define _dl_mmap_check_error(__res) \
+- (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
+-#endif
+-
+
+
+ /* Here are the definitions for some syscalls that are used
+@@ -66,54 +60,125 @@
+ static inline _syscall1(int, _dl_close, int, fd);
+
+ #define __NR__dl_open __NR_open
+-static inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode);
++static inline _syscall3(int, _dl_open, const char *, fn, int, flags,
++ __kernel_mode_t, mode);
+
+ #define __NR__dl_write __NR_write
+ static inline _syscall3(unsigned long, _dl_write, int, fd,
+- const void *, buf, unsigned long, count);
++ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_read __NR_read
+ static inline _syscall3(unsigned long, _dl_read, int, fd,
+- const void *, buf, unsigned long, count);
++ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_mprotect __NR_mprotect
+-static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot);
++static inline _syscall3(int, _dl_mprotect, const void *, addr,
++ unsigned long, len, int, prot);
+
+ #define __NR__dl_stat __NR_stat
+-static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);
++static inline _syscall2(int, _dl_stat, const char *, file_name,
++ struct stat *, buf);
++
++#define __NR__dl_fstat __NR_fstat
++static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
+
+ #define __NR__dl_munmap __NR_munmap
+ static 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 inline _syscall0(uid_t, _dl_getuid);
+
++#ifndef __NR_geteuid
++# define __NR_geteuid __NR_getuid
++#endif
+ #define __NR__dl_geteuid __NR_geteuid
+ static inline _syscall0(uid_t, _dl_geteuid);
+
++#ifdef __NR_getxgid
++# define __NR_getgid __NR_getxgid
++#endif
+ #define __NR__dl_getgid __NR_getgid
+ static inline _syscall0(gid_t, _dl_getgid);
+
++#ifndef __NR_getegid
++# define __NR_getegid __NR_getgid
++#endif
+ #define __NR__dl_getegid __NR_getegid
+ static inline _syscall0(gid_t, _dl_getegid);
+
++#ifdef __NR_getxpid
++# define __NR_getpid __NR_getxpid
++#endif
+ #define __NR__dl_getpid __NR_getpid
+ static inline _syscall0(gid_t, _dl_getpid);
+
+ #define __NR__dl_readlink __NR_readlink
+-static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
++static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
++ size_t, bufsiz);
+
+-#ifdef __NR_mmap
+-#ifdef MMAP_HAS_6_ARGS
+-#define __NR__dl_mmap __NR_mmap
+-static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
+- int, prot, int, flags, int, fd, off_t, offset);
++#ifdef __UCLIBC_HAS_SSP__
++# include <sys/time.h>
++# define __NR__dl_gettimeofday __NR_gettimeofday
++static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
++# ifdef __USE_BSD
++ struct timezone *, tz);
++# else
++ void *, tz);
++# endif
++#endif
++
++
++/* handle all the fun mmap intricacies */
++#if (defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)) || !defined(__NR_mmap2)
++# define _dl_MAX_ERRNO 4096
++# define _dl_mmap_check_error(__res) \
++ (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
+ #else
+-#define __NR__dl_mmap_real __NR_mmap
+-static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++# define MAP_FAILED ((void *) -1)
++# define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
++#endif
++
++/* first try mmap(), syscall6() style */
++#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
++
++# define __NR__dl_mmap __NR_mmap
++static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
++ int, prot, int, flags, int, fd, off_t, offset);
++
++/* then try mmap2() */
++#elif defined(__NR_mmap2)
++
++# define __NR___syscall_mmap2 __NR_mmap2
++static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
++ int, prot, int, flags, int, fd, off_t, offset);
++
++/* 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
+
+ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+- int flags, int fd, unsigned long offset)
++ int flags, int fd, unsigned long offset)
++{
++ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
++ return MAP_FAILED;
++ return __syscall_mmap2(addr, size, prot, flags,
++ fd, (off_t) (offset >> MMAP2_PAGE_SHIFT));
++}
++
++/* finally, fall back to mmap(), syscall1() style */
++#elif defined(__NR_mmap)
++
++# define __NR__dl_mmap_real __NR_mmap
++static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++ int flags, int fd, unsigned long offset)
+ {
+ unsigned long buffer[6];
+
+@@ -125,24 +190,9 @@
+ buffer[5] = (unsigned long) offset;
+ return (void *) _dl_mmap_real(buffer);
+ }
+-#endif
+-#elif defined __NR_mmap2
+-#define __NR___syscall_mmap2 __NR_mmap2
+-static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
+- size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+-/*always 12, even on architectures where PAGE_SHIFT != 12 */
+-#define MMAP2_PAGE_SHIFT 12
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+- int flags, int fd, unsigned long offset)
+-{
+- if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
+- return MAP_FAILED;
+- return(__syscall_mmap2(addr, size, prot, flags,
+- fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
+-}
++
+ #else
+-#error "Your architecture doesn't seem to provide mmap() !?"
++# error "Your architecture doesn't seem to provide mmap() !?"
+ #endif
+
+ #endif /* _LD_SYSCALL_H_ */
+-
+diff -urN uClibc-0.9.28.orig/ldso/include/dlfcn.h uClibc-0.9.28/ldso/include/dlfcn.h
+--- uClibc-0.9.28.orig/ldso/include/dlfcn.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dlfcn.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* 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
+diff -urN uClibc-0.9.28.orig/ldso/include/ldso.h uClibc-0.9.28/ldso/include/ldso.h
+--- uClibc-0.9.28.orig/ldso/include/ldso.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/ldso.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* 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_
+
+@@ -20,13 +27,15 @@
+ /* Pull in compiler and arch stuff */
+ #include <stdlib.h>
+ #include <stdarg.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>
++#define attribute_unused __attribute__ ((unused))
+ /* Pull in the ldso syscalls and string functions */
+ #include <dl-syscall.h>
+ #include <dl-string.h>
+-/* Pull in the arch specific page size */
+-#include <bits/uClibc_page.h>
+ /* Now the ldso specific headers */
+ #include <dl-elf.h>
+ #include <dl-hash.h>
+diff -urN uClibc-0.9.28.orig/ldso/include/unsecvars.h uClibc-0.9.28/ldso/include/unsecvars.h
+--- uClibc-0.9.28.orig/ldso/include/unsecvars.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/unsecvars.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* 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
+@@ -5,22 +12,21 @@
+ */
+
+ #define UNSECURE_ENVVARS \
+- "LD_AOUT_PRELOAD\0" \
+- "LD_AOUT_LIBRARY_PATH\0" \
+ "LD_PRELOAD\0" \
+ "LD_LIBRARY_PATH\0" \
+ "LD_DEBUG\0" \
+ "LD_DEBUG_OUTPUT\0" \
+ "LD_TRACE_LOADED_OBJECTS\0" \
+- "HOSTALIASES\0" \
+- "LOCALDOMAIN\0" \
+- "RES_OPTIONS\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.
+ *
+- * MALLOC_TRACE, RESOLV_HOST_CONF, TZDIR, GCONV_PATH, LD_USE_LOAD_BIAS,
+- * LD_PROFILE, LD_ORIGIN_PATH, LOCPATH, NLSPATH
++ * 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 -urN uClibc-0.9.28.orig/ldso/ldso/Makefile uClibc-0.9.28/ldso/ldso/Makefile
+--- uClibc-0.9.28.orig/ldso/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600
+@@ -42,7 +42,9 @@
+ endif
+ XXFLAGS+= -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \
+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include
++ -fno-builtin -nostdinc -D_LIBC \
++ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \
++ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include
+
+ # BEWARE!!! At least mips* will die if -O0 is used!!!
+ XXFLAGS:=$(XXFLAGS:-O0=-O1)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h uClibc-0.9.28/ldso/ldso/arm/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,10 +1,15 @@
+ /* vi: set sw=4 ts=4: */
+ /*
+ * Architecture specific code used by dl-startup.c
+- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
++ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
++ *
++ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+-asm(
++#include <features.h>
++
++#if !defined(__thumb__)
++__asm__(
+ " .text\n"
+ " .globl _start\n"
+ " .type _start,%function\n"
+@@ -40,7 +45,78 @@
+ " 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"
+@@ -51,6 +127,7 @@
+ " .size _start,.-_start\n"
+ ".previous\n"
+ );
++#endif
+
+
+ /* Get a pointer to the argv array. On many platforms this can be just
+@@ -115,9 +192,3 @@
+ _dl_exit(1);
+ }
+ }
+-
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,6 +1,7 @@
+ /* 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);}
+-#include "sys/syscall.h"
+
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -43,6 +43,7 @@
+ 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
+@@ -85,7 +86,25 @@
+ extern void __dl_start asm ("_dl_start");
+ Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ Elf32_Addr pcrel_addr;
++#if !defined __thumb__
+ asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
++#else
++ int tmp;
++ /* The above adr will not work on thumb because it
++ * is negative. The only safe way is to temporarily
++ * swap to arm.
++ */
++ asm( ".align 2\n"
++ " bx pc\n"
++ " nop \n"
++ " .arm \n"
++ " adr %0, _dl_start\n"
++ " .align 2\n"
++ " orr %1, pc, #1\n"
++ " bx %1\n"
++ " .force_thumb\n"
++ : "=r" (pcrel_addr), "=&r" (tmp));
++#endif
+ return pcrel_addr - got_addr;
+ }
+
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c uClibc-0.9.28/ldso/ldso/arm/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -38,6 +38,8 @@
+ 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)
+@@ -63,7 +65,6 @@
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+-
+ if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) {
+ _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
+ _dl_progname);
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h uClibc-0.9.28/ldso/ldso/cris/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -4,22 +4,43 @@
+
+ /* 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" \
++" 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 if the first argument, on other platforms we need to
+@@ -58,8 +79,3 @@
+ break;
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,5 +1,6 @@
+ /* 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);}
+-#include "sys/syscall.h"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -18,8 +18,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 8192 bytes alignment */
+ #define PAGE_ALIGN 0xffffe000
+ #define ADDR_ALIGN 0x1fff
+@@ -68,8 +66,32 @@
+ {
+ 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;
+ }
+
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S uClibc-0.9.28/ldso/ldso/cris/resolve.S
+--- uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/resolve.S 2006-04-28 00:14:35.000000000 -0600
+@@ -17,33 +17,73 @@
+ .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
++ 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
++ 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
++ 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+]
++ 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 -urN uClibc-0.9.28.orig/ldso/ldso/dl-elf.c uClibc-0.9.28/ldso/ldso/dl-elf.c
+--- uClibc-0.9.28.orig/ldso/ldso/dl-elf.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/dl-elf.c 2006-05-02 13:50:58.000000000 -0600
+@@ -3,7 +3,7 @@
+ * 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-2004 by Erik Andersen <andersen@codepoet.org>
++ * 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
+ *
+@@ -60,8 +60,8 @@
+ _dl_cache_addr = (caddr_t) _dl_mmap(0, _dl_cache_size, PROT_READ, MAP_SHARED, fd, 0);
+ _dl_close(fd);
+ if (_dl_mmap_check_error(_dl_cache_addr)) {
+- _dl_dprintf(2, "%s: can't map cache '%s'\n",
+- _dl_progname, LDSO_CACHE);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
++ _dl_progname, __LINE__, LDSO_CACHE);
+ return -1;
+ }
+
+@@ -115,7 +115,7 @@
+ #endif
+
+
+-void
++void
+ _dl_protect_relro (struct elf_resolve *l)
+ {
+ ElfW(Addr) start = ((l->loadaddr + l->relro_addr)
+@@ -136,27 +136,41 @@
+ search_for_named_library(const char *name, int secure, const char *path_list,
+ struct dyn_elf **rpnt)
+ {
+- char *path, *path_n;
+- char mylibname[2050];
++ char *path, *path_n, *mylibname;
+ struct elf_resolve *tpnt;
+- int done = 0;
++ int done;
+
+ if (path_list==NULL)
+ return NULL;
+
+- /* We need a writable copy of this string */
+- path = _dl_strdup(path_list);
+- if (!path) {
++ /* 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);
++
++ /* gcc inlines alloca using a single instruction adjusting
++ * the stack pointer and no stack overflow check and thus
++ * no NULL error return. No point leaving in dead code... */
++#if 0
++ if (!path || !mylibname) {
+ _dl_dprintf(2, "Out of memory!\n");
+ _dl_exit(0);
+ }
++#endif
++
++ _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 */
++ /* "" maps to CWD */
++ done = 0;
+ path_n = path;
+ do {
+ if (*path == 0) {
+@@ -180,71 +194,6 @@
+ return NULL;
+ }
+
+-/* Check if the named library is already loaded... */
+-struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
+- int trace_loaded_objects)
+-{
+- const char *pnt, *pnt1;
+- struct elf_resolve *tpnt1;
+- const char *libname, *libname2;
+- static const char libc[] = "libc.so.";
+- static const char aborted_wrong_lib[] = "%s: aborted attempt to load %s!\n";
+-
+- pnt = libname = full_libname;
+-
+- _dl_if_debug_dprint("Checking if '%s' is already loaded\n", 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)
+- return NULL;
+-
+- /* Skip over any initial initial './' and '/' stuff to
+- * get the short form libname with no path garbage */
+- pnt1 = _dl_strrchr(pnt, '/');
+- if (pnt1) {
+- libname = pnt1 + 1;
+- }
+-
+- /* Make sure they are not trying to load the wrong C library!
+- * This sometimes happens esp with shared libraries when the
+- * library path is somehow wrong! */
+-#define isdigit(c) (c >= '0' && c <= '9')
+- if ((_dl_strncmp(libname, libc, 8) == 0) && _dl_strlen(libname) >=8 &&
+- isdigit(libname[8]))
+- {
+- /* Abort attempts to load glibc, libc5, etc */
+- if ( libname[8]!='0') {
+- if (!trace_loaded_objects) {
+- _dl_dprintf(2, aborted_wrong_lib, libname, _dl_progname);
+- _dl_exit(1);
+- }
+- return NULL;
+- }
+- }
+-
+- /* Critical step! Weed out duplicates early to avoid
+- * function aliasing, which wastes memory, and causes
+- * really bad things to happen with weaks and globals. */
+- for (tpnt1 = _dl_loaded_modules; tpnt1; tpnt1 = tpnt1->next) {
+-
+- /* Skip over any initial initial './' and '/' stuff to
+- * get the short form libname with no path garbage */
+- libname2 = tpnt1->libname;
+- pnt1 = _dl_strrchr(libname2, '/');
+- if (pnt1) {
+- libname2 = pnt1 + 1;
+- }
+-
+- if (_dl_strcmp(libname2, libname) == 0) {
+- /* Well, that was certainly easy */
+- return tpnt1;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-
+ /* Used to return error codes back to dlopen et. al. */
+ unsigned long _dl_error_number;
+ unsigned long _dl_internal_error_number;
+@@ -271,14 +220,6 @@
+ libname = pnt + 1;
+ }
+
+- /* Critical step! Weed out duplicates early to avoid
+- * function aliasing, which wastes memory, and causes
+- * really bad things to happen with weaks and globals. */
+- if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) {
+- tpnt1->usage_count++;
+- return tpnt1;
+- }
+-
+ _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
+@@ -290,7 +231,6 @@
+ if (tpnt1) {
+ return tpnt1;
+ }
+- //goto goof;
+ }
+
+ /*
+@@ -411,56 +351,45 @@
+ int i, flags, piclib, infile;
+ ElfW(Addr) relro_addr = 0;
+ size_t relro_size = 0;
+-
+- /* If this file is already loaded, skip this step */
+- tpnt = _dl_check_hashed_files(libname);
+- if (tpnt) {
+- if (*rpnt) {
+- (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
+- _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
+- (*rpnt)->next->prev = (*rpnt);
+- *rpnt = (*rpnt)->next;
+- (*rpnt)->dyn = tpnt;
+- tpnt->symbol_scope = _dl_symbol_tables;
+- }
+- tpnt->usage_count++;
+- tpnt->libtype = elf_lib;
+- _dl_if_debug_dprint("file='%s'; already loaded\n", libname);
+- return tpnt;
+- }
+-
+- /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
+- we don't load the library if it isn't setuid. */
+-
+- if (secure) {
+- struct stat st;
+-
+- if (_dl_stat(libname, &st) || !(st.st_mode & S_ISUID))
+- return NULL;
+- }
++ struct stat st;
+
+ libaddr = 0;
+ infile = _dl_open(libname, O_RDONLY, 0);
+ if (infile < 0) {
+-#if 0
+- /*
+- * NO! When we open shared libraries we may search several paths.
+- * it is inappropriate to generate an error here.
+- */
+- _dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
+-#endif
+ _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 setu/gid binary using LD_PRELOAD),
++ we don't load the library if it isn't setuid. */
++ if (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;
++ }
++ }
+ header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(header)) {
+- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
++ _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;
+@@ -475,7 +404,7 @@
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1
+ #ifdef MAGIC2
+@@ -490,7 +419,7 @@
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
+
+@@ -502,7 +431,7 @@
+ _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. */
+@@ -518,7 +447,7 @@
+ }
+ }
+ ppnt++;
+- };
++ }
+
+ maxvma = (maxvma + ADDR_ALIGN) & ~ADDR_ALIGN;
+ minvma = minvma & ~0xffffU;
+@@ -530,12 +459,12 @@
+ status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
+ maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(status)) {
+- _dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
++ _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;
+
+@@ -567,14 +496,14 @@
+ ppnt->p_offset & OFFS_ALIGN);
+
+ if (_dl_mmap_check_error(status)) {
+- _dl_dprintf(2, "%s: can't map '%s'\n",
+- _dl_progname, libname);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
++ _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_munmap((char *) libaddr, maxvma - minvma);
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ /* Pad the last page with zeroes. */
+ cpnt = (char *) (status + (ppnt->p_vaddr & ADDR_ALIGN) +
+@@ -601,21 +530,21 @@
+ ppnt->p_filesz, LXFLAGS(ppnt->p_flags), flags,
+ infile, ppnt->p_offset & OFFS_ALIGN);
+ if (_dl_mmap_check_error(status)) {
+- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_munmap((char *) libaddr, maxvma - minvma);
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ /* if(libaddr == 0 && piclib) {
+ libaddr = (unsigned long) status;
+ flags |= MAP_FIXED;
+- }; */
+- };
++ } */
++ }
+ ppnt++;
+- };
++ }
+ _dl_close(infile);
+
+ /* For a non-PIC library, the addresses are all absolute */
+@@ -665,6 +594,8 @@
+ dynamic_addr, 0);
+ 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) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
+ tpnt->n_phent = epnt->e_phnum;
+
+@@ -693,7 +624,7 @@
+ if (lpnt) {
+ lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
+ INIT_GOT(lpnt, tpnt);
+- };
++ }
+
+ _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
+ _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, libaddr);
+@@ -714,10 +645,12 @@
+ ElfW(Addr) reloc_addr;
+
+ if (rpnt->next)
+- goof += _dl_fixup(rpnt->next, now_flag);
++ goof = _dl_fixup(rpnt->next, now_flag);
++ if (goof)
++ return goof;
+ tpnt = rpnt->dyn;
+
+- if(!(tpnt->init_flag & RELOCS_DONE))
++ if(!(tpnt->init_flag & RELOCS_DONE))
+ _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
+
+ if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
+@@ -735,7 +668,6 @@
+ #endif
+ if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
+ !(tpnt->init_flag & RELOCS_DONE)) {
+- 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 */
+@@ -746,14 +678,14 @@
+ goof += _dl_parse_relocation_information(rpnt,
+ 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;
+- tpnt->init_flag |= JMP_RELOCS_DONE;
++ tpnt->rtld_flags |= now_flag;
+ if (!(tpnt->rtld_flags & RTLD_NOW)) {
+ _dl_parse_lazy_relocation_information(rpnt,
+ tpnt->dynamic_info[DT_JMPREL],
+@@ -763,6 +695,7 @@
+ tpnt->dynamic_info[DT_JMPREL],
+ tpnt->dynamic_info[DT_PLTRELSZ]);
+ }
++ tpnt->init_flag |= JMP_RELOCS_DONE;
+ }
+ return goof;
+ }
+@@ -770,11 +703,18 @@
+ /* Minimal printf which handles only %s, %d, and %x */
+ void _dl_dprintf(int fd, const char *fmt, ...)
+ {
+- long num;
++#if __WORDSIZE > 32
++ long int num;
++#else
++ int num;
++#endif
+ va_list args;
+ char *start, *ptr, *string;
+ static 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)) {
+@@ -784,9 +724,6 @@
+
+ start = ptr = buf;
+
+- if (!fmt)
+- return;
+-
+ if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
+ _dl_write(fd, "overflow\n", 11);
+ _dl_exit(20);
+@@ -818,8 +755,11 @@
+ case 'd':
+ {
+ char tmp[22];
+- num = va_arg(args, long);
+-
++#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;
+@@ -828,8 +768,11 @@
+ case 'X':
+ {
+ char tmp[22];
+- num = va_arg(args, long);
+-
++#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;
+@@ -864,8 +807,10 @@
+ {
+ __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
+ }
++
++/* we want this in ldso.so and libdl.a but nowhere else */
+ #ifdef __USE_GNU
+-#if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
++#if ! defined SHARED || (! defined PIC && ! defined __PIC__)
+ int
+ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data)
+ {
+@@ -884,6 +829,6 @@
+ }
+ return ret;
+ }
+-strong_alias(__dl_iterate_phdr, dl_iterate_phdr);
++strong_alias(__dl_iterate_phdr, dl_iterate_phdr)
+ #endif
+ #endif
+diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-hash.c uClibc-0.9.28/ldso/ldso/dl-hash.c
+--- uClibc-0.9.28.orig/ldso/ldso/dl-hash.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2006-04-28 00:14:35.000000000 -0600
+@@ -57,7 +57,7 @@
+ /* 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 Elf32_Word _dl_elf_hash(const char *name)
++static inline Elf_Symndx _dl_elf_hash(const char *name)
+ {
+ unsigned long hash=0;
+ unsigned long tmp;
+@@ -77,21 +77,6 @@
+ return hash;
+ }
+
+-/* Check to see if a library has already been added to the hash chain. */
+-struct elf_resolve *_dl_check_hashed_files(const char *libname)
+-{
+- struct elf_resolve *tpnt;
+- int len = _dl_strlen(libname);
+-
+- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+- if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
+- (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
+- return tpnt;
+- }
+-
+- return NULL;
+-}
+-
+ /*
+ * 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
+@@ -99,9 +84,10 @@
+ */
+ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
+ char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
++ //attribute_unused
+ unsigned long dynamic_size)
+ {
+- Elf32_Word *hash_addr;
++ Elf_Symndx *hash_addr;
+ struct elf_resolve *tpnt;
+ int i;
+
+@@ -125,7 +111,7 @@
+ tpnt->libtype = loaded_file;
+
+ if (dynamic_info[DT_HASH] != 0) {
+- hash_addr = (Elf32_Word*)dynamic_info[DT_HASH];
++ hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH];
+ tpnt->nbucket = *hash_addr++;
+ tpnt->nchain = *hash_addr++;
+ tpnt->elf_buckets = hash_addr;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-startup.c uClibc-0.9.28/ldso/ldso/dl-startup.c
+--- uClibc-0.9.28.orig/ldso/ldso/dl-startup.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/dl-startup.c 2006-04-28 00:14:35.000000000 -0600
+@@ -98,7 +98,7 @@
+ 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 */
++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)
+@@ -307,5 +307,11 @@
+ SEND_STDERR_DEBUG("transfering control to application @ ");
+ _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val;
+ SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1);
++
++#ifndef START
++ return _dl_elf_main;
++#else
++#warning You need to update your arch ldso code
+ START();
++#endif
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -20,9 +20,10 @@
+
+ /* 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);}
+-#include "sys/syscall.h"
+ #include <sys/mman.h>
+
+ /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
+diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -65,8 +65,6 @@
+
+ extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 16KiB page alignment. Should perhaps be made dynamic using
+ getpagesize(), based on AT_PAGESZ from auxvt? */
+ #define PAGE_ALIGN 0xffffc000
+diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c uClibc-0.9.28/ldso/ldso/frv/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/frv/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -24,7 +24,7 @@
+ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ USA. */
+
+-#include <sys/cdefs.h> /* __attribute_used__ */
++#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
+@@ -37,7 +37,7 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+-struct funcdesc_value volatile *__attribute__((__visibility__("hidden")))
++struct funcdesc_value volatile attribute_hidden *
+ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+ {
+ int reloc_type;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h uClibc-0.9.28/ldso/ldso/i386/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -3,7 +3,7 @@
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+-asm(
++__asm__ (
+ " .text\n"
+ " .align 16\n"
+ " .globl _start\n"
+@@ -41,9 +41,9 @@
+ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1)
+
+ /* Handle relocation of the symbols in the dynamic loader. */
+-static inline
++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)
++ unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
+ {
+ switch (ELF32_R_TYPE(rpnt->r_info))
+ {
+@@ -64,8 +64,3 @@
+ _dl_exit(1);
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,5 +1,6 @@
+ /* 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);}
+-#include "sys/syscall.h"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,8 +25,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+@@ -44,16 +42,18 @@
+ /* 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 __attribute__ ((unused))
++static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused;
++static inline Elf32_Addr
+ elf_machine_dynamic (void)
+ {
+- register Elf32_Addr *got asm ("%ebx");
++ register Elf32_Addr *got __asm__ ("%ebx");
+ return *got;
+ }
+
+
+ /* Return the run-time load address of the shared object. */
+-static inline Elf32_Addr __attribute__ ((unused))
++static inline Elf32_Addr elf_machine_load_address (void) attribute_unused;
++static inline Elf32_Addr
+ elf_machine_load_address (void)
+ {
+ /* It doesn't matter what variable this is, the reference never makes
+@@ -61,7 +61,7 @@
+ via the GOT to make sure the compiler initialized %ebx in time. */
+ extern int _dl_errno;
+ Elf32_Addr addr;
+- asm ("leal _dl_start@GOTOFF(%%ebx), %0\n"
++ __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n"
+ "subl _dl_start@GOT(%%ebx), %0"
+ : "=r" (addr) : "m" (_dl_errno) : "cc");
+ return addr;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c uClibc-0.9.28/ldso/ldso/i386/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -67,12 +67,6 @@
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+- if (unlikely(reloc_type != R_386_JMP_SLOT)) {
+- _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
+- _dl_progname);
+- _dl_exit(1);
+- }
+-
+ /* Address of the jump instruction to fix up. */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+@@ -81,7 +75,7 @@
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ if (unlikely(!new_addr)) {
+- _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+@@ -147,15 +141,15 @@
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "can't handle reloc type %s\n",
+- _dl_reltypes(reloc_type));
++ _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\n",
+- reloc_type);
++ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n",
++ reloc_type, tpnt->libname);
+ #endif
+- _dl_exit(-res);
++ return res;
+ } else if (unlikely(res > 0)) {
+- _dl_dprintf(2, "can't resolve symbol\n");
++ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ return res;
+ }
+ }
+@@ -191,10 +185,8 @@
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+- if (unlikely(!symbol_addr && ELF32_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 (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
++ return 1;
+ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -233,7 +225,7 @@
+ }
+ break;
+ default:
+- return -1; /* Calls _dl_exit(1). */
++ return -1;
+ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -273,7 +265,7 @@
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+- return -1; /* Calls _dl_exit(1). */
++ return -1;
+ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/ldso.c uClibc-0.9.28/ldso/ldso/ldso.c
+--- uClibc-0.9.28.orig/ldso/ldso/ldso.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/ldso.c 2006-05-02 13:55:54.000000000 -0600
+@@ -39,7 +39,7 @@
+ #define ALLOW_ZERO_PLTGOT
+
+ /* Pull in the value of _dl_progname */
+-#include "dl-progname.h"
++#include LDSO_ELFINTERP
+
+ /* Global variables used within the shared library loader */
+ char *_dl_library_path = 0; /* Where we look for libraries */
+@@ -74,7 +74,8 @@
+ * 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)
++void _dl_debug_state(void);
++void _dl_debug_state()
+ {
+ }
+
+@@ -82,9 +83,78 @@
+ static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */
+
+ static struct elf_resolve **init_fini_list;
+-static int nlist; /* # items in init_fini_list */
++static unsigned int nlist; /* # items in init_fini_list */
+ extern void _start(void);
+
++#ifdef __UCLIBC_HAS_SSP__
++#ifndef __UCLIBC_HAS_SSP_COMPAT__
++#define __UCLIBC_HAS_SSP_COMPAT__ 1
++#endif
++# include <dl-osinfo.h>
++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;
++# ifdef __UCLIBC_HAS_SSP_COMPAT__
++strong_alias(__stack_chk_guard,__guard)
++# endif
++# elif __UCLIBC_HAS_SSP_COMPAT__
++uintptr_t __guard attribute_relro;
++# endif
++#endif
++
++static void _dl_run_array_forward(unsigned long array, unsigned long size,
++ ElfW(Addr) loadaddr)
++{
++ if (array != 0) {
++ unsigned int j;
++ unsigned int jm;
++ ElfW(Addr) *addrs;
++ jm = size / sizeof (ElfW(Addr));
++ addrs = (ElfW(Addr) *) (array + loadaddr);
++ for (j = 0; j < jm; ++j) {
++ void (*dl_elf_func) (void);
++ dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
++ (*dl_elf_func) ();
++ }
++ }
++}
++
++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) *) (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_elf_func) ();
++ }
++ }
++}
++
++void _dl_app_fini_array(void);
++void _dl_app_fini_array(void)
++{
++ _dl_run_fini_array(_dl_loaded_modules);
++}
++
+ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
+ {
+ int i;
+@@ -95,6 +165,7 @@
+ 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);
+
+@@ -112,7 +183,8 @@
+ ElfW(Phdr) *ppnt;
+ ElfW(Dyn) *dpnt;
+ char *lpntstr;
+- int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
++ unsigned int i;
++ int unlazy = 0, trace_loaded_objects = 0;
+ struct dyn_elf *rpnt;
+ struct elf_resolve *tcurr;
+ struct elf_resolve *tpnt1;
+@@ -128,6 +200,7 @@
+ * 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, 0x00, 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;
+@@ -168,8 +241,8 @@
+ * Note that for SUID programs we ignore the settings in
+ * LD_LIBRARY_PATH.
+ */
+- if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
+- (auxvt[AT_UID].a_un.a_val != -1 &&
++ 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;
+@@ -196,6 +269,20 @@
+ unlazy = RTLD_NOW;
+ }
+
++ /* sjhill: your TLS init should go before this */
++#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);
++# ifdef __UCLIBC_HAS_SSP_COMPAT__
++ __guard = stack_chk_guard;
++# endif
++# else
++ __stack_chk_guard = stack_chk_guard;
++# endif
++#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
+@@ -206,12 +293,12 @@
+ * different from what the ELF header says for ET_DYN/PIE executables.
+ */
+ {
+- int i;
+- ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
++ unsigned int idx;
++ ElfW(Phdr) *phdr = (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_PHDR) {
+- app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
++ for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
++ if (phdr->p_type == PT_PHDR) {
++ app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
+ break;
+ }
+
+@@ -459,8 +546,8 @@
+ PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ _dl_close(fd);
+ if (preload == (caddr_t) -1) {
+- _dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n",
+- _dl_progname, LDSO_PRELOAD);
++ _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
++ _dl_progname, __LINE__, LDSO_PRELOAD);
+ break;
+ }
+
+@@ -528,15 +615,15 @@
+
+ nlist = 0;
+ for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
+- ElfW(Dyn) *dpnt;
++ ElfW(Dyn) *this_dpnt;
+
+ nlist++;
+- for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
+- if (dpnt->d_tag == DT_NEEDED) {
++ 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] + dpnt->d_un.d_val);
++ lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
+ name = _dl_get_last_path_component(lpntstr);
+ if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
+ continue;
+@@ -633,7 +720,7 @@
+ ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+ ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
+ int j;
+-
++
+ tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
+ tpnt->dynamic_info,
+ (unsigned long)tpnt->dynamic_addr,
+@@ -703,16 +790,14 @@
+ * order so that COPY directives work correctly.
+ */
+ if (_dl_symbol_tables)
+- goof += _dl_fixup(_dl_symbol_tables, unlazy);
++ if (_dl_fixup(_dl_symbol_tables, unlazy))
++ _dl_exit(-1);
+
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ if (tpnt->relro_size)
+ _dl_protect_relro (tpnt);
+ }
+
+-
+-
+-
+ /* 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
+@@ -746,6 +831,14 @@
+ /* 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 */
+@@ -762,17 +855,9 @@
+
+ (*dl_elf_func) ();
+ }
+- }
+-#ifdef _DL_FINI_CRT_COMPAT
+- /* arches that have moved their ldso FINI handling should skip this part */
+- {
+- int (*_dl_atexit) (void *) = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit",
+- _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
+
+- if (_dl_atexit)
+- (*_dl_atexit) (_dl_fini);
++ _dl_run_init_array(tpnt);
+ }
+-#endif
+
+ /* 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("malloc",
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -4,23 +4,48 @@
+ * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
+ */
+
+-asm(
+- " .text\n"
+- " .globl _start\n"
+- " .type _start,@function\n"
+- "_start:\n"
+- " .set _start,_dl_start\n"
+- " .size _start,.-_start\n"
+- " .previous\n"
+-);
++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\
++ move.l _dl_skip_args(%pc), %d0\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\
++ lea _dl_fini(%pc), %a1\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 if the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+-#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned int *) & ARGS)
++#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+ /* Handle relocation of the symbols in the dynamic loader. */
+-static inline
++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)
+ {
+@@ -59,12 +84,3 @@
+ _dl_exit (1);
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() \
+- __asm__ volatile ( \
+- "unlk %%a6\n\t" \
+- "jmp %0@" \
+- : : "a" (_dl_elf_main));
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,5 +1,6 @@
+ /* 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);}
+-#include "sys/syscall.h"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,10 +25,6 @@
+ struct elf_resolve;
+ extern unsigned int _dl_linux_resolver (struct elf_resolve *, int);
+
+-/* Define this because we do not want to call .udiv in the library.
+- Not needed for m68k. */
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -40,6 +40,8 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ unsigned int
+@@ -48,20 +50,20 @@
+ int reloc_type;
+ ELF_RELOC *this_reloc;
+ char *strtab;
+- Elf32_Sym *symtab;
++ ElfW(Sym) *symtab;
+ int symtab_index;
+- ELF_RELOC *rel_addr;
++ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+- unsigned int instr_addr;
++ ElfW(Addr) instr_addr;
+ char *symname;
+
+- rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL];
+- this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+- reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+- symtab_index = ELF32_R_SYM(this_reloc->r_info);
++ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
++ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
++ reloc_type = ELF_R_TYPE(this_reloc->r_info);
++ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+- symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+@@ -72,7 +74,7 @@
+ }
+
+ /* Address of the jump instruction to fix up. */
+- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
++ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+@@ -88,159 +90,237 @@
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+- "\n\tpatched: %x ==> %x @ %x",
++ "\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+- if (!_dl_debug_nofixups) {
+- *got_addr = new_addr;
+- }
+-#else
+- *got_addr = new_addr;
++ if (!_dl_debug_nofixups)
+ #endif
++ *got_addr = new_addr;
+
+- return (unsigned int)new_addr;
++ return (unsigned int)new_addr;
+ }
+
+-void
+-_dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
++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))
+ {
+- int i;
++ unsigned int i;
+ char *strtab;
+- int reloc_type;
++ ElfW(Sym) *symtab;
++ ELF_RELOC *rpnt;
+ int symtab_index;
+- Elf32_Sym *symtab;
+- Elf32_Rela *rpnt;
+- unsigned int *reloc_addr;
+- struct elf_resolve *tpnt = arg_rpnt->dyn;
+-
+- /* Now parse the relocation information. */
+- rpnt = (Elf32_Rela *)rel_addr;
+- rel_size = rel_size / sizeof (Elf32_Rela);
+
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
++ /* 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++) {
+- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE (rpnt->r_info);
+- symtab_index = ELF32_R_SYM (rpnt->r_info);
++ int res;
+
+- switch (reloc_type)
+- {
+- case R_68K_NONE:
+- break;
+- case R_68K_JMP_SLOT:
+- *reloc_addr += (unsigned int) tpnt->loadaddr;
+- break;
+- default:
+- _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
++ 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__)
+- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]);
++ "%s\n", _dl_reltypes(reloc_type));
++#else
++ "%x\n", reloc_type);
+ #endif
+- if (symtab_index)
+- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
+- _dl_dprintf (2, "\n");
+- _dl_exit (1);
++ _dl_exit(-res);
++ } else if (unlikely(res > 0)) {
++ _dl_dprintf(2, "can't resolve symbol\n");
++ return res;
+ }
+ }
++
++ return 0;
+ }
+
+-int
+-_dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
++static int
++_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+ {
+- int i;
+- char *strtab;
+ int reloc_type;
+- int goof = 0;
+- Elf32_Sym *symtab;
+- Elf32_Rela *rpnt;
+- unsigned int *reloc_addr;
+- unsigned int symbol_addr;
+ int symtab_index;
+- struct elf_resolve *tpnt = arg_rpnt->dyn;
+- /* Now parse the relocation information */
++ char *symname;
++ ElfW(Sym) *sym;
++ ElfW(Addr) *reloc_addr;
++ ElfW(Addr) symbol_addr;
++#if defined (__SUPPORT_LD_DEBUG__)
++ ElfW(Addr) old_val;
++#endif
+
+- rpnt = (Elf32_Rela *)rel_addr;
+- rel_size = rel_size / sizeof (Elf32_Rela);
++ 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 = &symtab[symtab_index];
++ symbol_addr = 0;
++ symname = strtab + sym->st_name;
++
++ if (symtab_index) {
++ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
++ elf_machine_type_class(reloc_type));
++ /*
++ * 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->st_info) != STB_WEAK)) {
++ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_exit(1);
++ };
++ }
+
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
++#if defined (__SUPPORT_LD_DEBUG__)
++ old_val = *reloc_addr;
++#endif
+
+- for (i = 0; i < rel_size; i++, rpnt++) {
+- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE (rpnt->r_info);
+- symtab_index = ELF32_R_SYM (rpnt->r_info);
+- symbol_addr = 0;
+- if (symtab_index) {
+- symbol_addr = (unsigned int)
+- _dl_find_hash (strtab + symtab[symtab_index].st_name,
+- tpnt->symbol_scope, tpnt,
+- elf_machine_type_class(reloc_type));
+-
+- /* 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
+- && ELF32_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);
+- }
+- }
+- 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;
+- break;
+- case R_68K_RELATIVE:
+- *reloc_addr = ((unsigned int) tpnt->loadaddr
+- /* Compatibility kludge. */
+- + (rpnt->r_addend ? : *reloc_addr));
+- break;
+- case R_68K_COPY:
++ 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->st_size,
++ symbol_addr, reloc_addr);
++#endif
+ _dl_memcpy ((void *) reloc_addr,
+ (void *) symbol_addr,
+- symtab[symtab_index].st_size);
+- break;
+- default:
+- _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
+-#if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]);
+-#endif
+- if (symtab_index)
+- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
+- _dl_dprintf (2, "\n");
+- _dl_exit (1);
+- }
++ 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 dyn_elf *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);
+ }
+- return goof;
++
++#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, rel_addr, rel_size);
++#endif
++}
++
++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);
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S uClibc-0.9.28/ldso/ldso/m68k/resolve.S
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/resolve.S 2006-04-28 00:14:35.000000000 -0600
+@@ -8,14 +8,16 @@
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve,@function
+ _dl_linux_resolve:
+- moveml %a0/%a1,%sp@-
+-#ifdef __PIC__
+- bsrl _dl_linux_resolver@PLTPC
+-#else
+- jbsr _dl_linux_resolver
+-#endif
+- moveml %sp@+,%a0/%a1
+- addql #8,%sp
+- jmp @(%d0)
+-.LFE2:
+- .size _dl_linux_resolve,.LFE2-_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.
++ jmp (%d0)
++.size _dl_linux_resolve,.-_dl_linux_resolve
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h uClibc-0.9.28/ldso/ldso/mips/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -136,13 +136,3 @@
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
+-
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function. For MIPS, we do it in assembly
+- * because the stack doesn't get properly restored otherwise. Got look
+- * at boot1_arch.h
+- */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h 2006-05-02 13:39:25.000000000 -0600
+@@ -1,7 +1,8 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+-
+-#define MMAP_HAS_6_ARGS
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -30,7 +30,7 @@
+ /* Initialization sequence for the application/library GOT. */
+ #define INIT_GOT(GOT_BASE,MODULE) \
+ do { \
+- unsigned long i; \
++ unsigned long idx; \
+ \
+ /* Check if this is the dynamic linker itself */ \
+ if (MODULE->libtype == program_interpreter) \
+@@ -41,9 +41,9 @@
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+- i = 2; \
+- while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
+- GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
++ idx = 2; \
++ while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
++ GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \
+ \
+ } while (0)
+
+@@ -63,8 +63,6 @@
+ struct elf_resolve;
+ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c uClibc-0.9.28/ldso/ldso/mips/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -27,6 +27,8 @@
+ * SUCH DAMAGE.
+ */
+
++#include "ldso.h"
++
+ extern int _dl_runtime_resolve(void);
+
+ #define OFFSET_GP_GOT 0x7ff0
+@@ -146,7 +148,6 @@
+ break;
+ default:
+ {
+- int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -42,8 +42,10 @@
+ " bne 2b\n"
+ " addi 6,6,4\n"
+ #endif
+- /* Pass a termination function pointer (in this case _dl_fini) in r7. */
+- " lwz 7,_dl_fini@got(31)\n"
++ /* 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"
+@@ -78,9 +80,3 @@
+ _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\
+ } \
+ }
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function.
+- */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 13:39:14.000000000 -0600
+@@ -1,251 +1,8 @@
+-/*
+- * This file contains the system call macros and syscall
+- * numbers used by the shared library loader.
+- */
+-
+-#define MMAP_HAS_6_ARGS
+-
+-#define __NR_exit 1
+-#define __NR_read 3
+-#define __NR_write 4
+-#define __NR_open 5
+-#define __NR_close 6
+-#define __NR_getpid 20
+-#define __NR_getuid 24
+-#define __NR_geteuid 49
+-#define __NR_getgid 47
+-#define __NR_getegid 50
+-#define __NR_readlink 85
+-#define __NR_mmap 90
+-#define __NR_munmap 91
+-#define __NR_stat 106
+-#define __NR_mprotect 125
+-
+-
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+-extern int _dl_errno;
+-
+-/* Here are the macros which define how this platform makes
+- * system calls. This particular variant does _not_ set
+- * errno (note how it is disabled in __syscall_return) since
+- * these will get called before the errno symbol is dynamicly
+- * linked. */
+-
+-#undef __syscall_return
+-#define __syscall_return(type) \
+- return (__sc_err & 0x10000000 ? _dl_errno = __sc_ret, __sc_ret = -1 : 0), \
+- (type) __sc_ret
+-
+-#undef __syscall_clobbers
+-#define __syscall_clobbers \
+- "r9", "r10", "r11", "r12"
+- //"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+-
+-#undef _syscall0
+-#define _syscall0(type,name) \
+-type name(void) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0) \
+- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall1
+-#define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0) \
+- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall2
+-#define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1, type2 arg2) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4) \
+- : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall3
+-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1, type2 arg2, type3 arg3) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5) \
+- : "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall4
+-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_6 = (unsigned long) (arg4); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5), \
+- "r" (__sc_6) \
+- : "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall5
+-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- register unsigned long __sc_7 __asm__ ("r7"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_6 = (unsigned long) (arg4); \
+- __sc_7 = (unsigned long) (arg5); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5), \
+- "r" (__sc_6), \
+- "r" (__sc_7) \
+- : "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-
+-#undef _syscall6
+-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- register unsigned long __sc_7 __asm__ ("r7"); \
+- register unsigned long __sc_8 __asm__ ("r8"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_6 = (unsigned long) (arg4); \
+- __sc_7 = (unsigned long) (arg5); \
+- __sc_8 = (unsigned long) (arg6); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5), \
+- "r" (__sc_6), \
+- "r" (__sc_7), \
+- "r" (__sc_8) \
+- : "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
++#define __UCLIBC_MMAP_HAS_6_ARGS__
+
++#include "sys/syscall.h"
++extern int _dl_errno;
++#undef __set_errno
++#define __set_errno(X) {(_dl_errno) = (X);}
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -67,9 +67,6 @@
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+ void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt);
+
+-
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -29,6 +29,8 @@
+ * SUCH DAMAGE.
+ */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
+@@ -138,7 +140,7 @@
+ finaladdr = (Elf32_Addr) _dl_find_hash(symname,
+ tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ if (unlikely(!finaladdr)) {
+- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
++ _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;
+@@ -379,15 +381,15 @@
+ {
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ #if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
++ _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\n", reloc_type);
++ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname);
+ #endif
+- _dl_exit(-res);
++ return res;
+ }
+ if (unlikely(res >0))
+ {
+- _dl_dprintf(2, "can't resolve symbol\n");
++ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ return res;
+ }
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h uClibc-0.9.28/ldso/ldso/sh/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -55,11 +55,3 @@
+ default: \
+ _dl_exit(1); \
+ }
+-
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function.
+- */
+-#define START() return _dl_elf_main;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h 2006-05-02 13:39:28.000000000 -0600
+@@ -1,7 +1,8 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+-
+-#define MMAP_HAS_6_ARGS
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,7 +25,7 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-static __inline__ unsigned int
++static inline unsigned int
+ _dl_urem(unsigned int n, unsigned int base)
+ {
+ int res;
+@@ -104,7 +104,7 @@
+ elf_machine_dynamic (void)
+ {
+ register Elf32_Addr *got;
+- asm ("mov r12,%0" :"=r" (got));
++ __asm__ ("mov r12,%0" :"=r" (got));
+ return *got;
+ }
+
+@@ -113,7 +113,7 @@
+ elf_machine_load_address (void)
+ {
+ Elf32_Addr addr;
+- asm ("mov.l 1f,r0\n\
++ __asm__ ("mov.l 1f,r0\n\
+ mov.l 3f,r2\n\
+ add r12,r2\n\
+ mov.l @(r0,r12),r0\n\
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c uClibc-0.9.28/ldso/ldso/sh/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -39,6 +39,8 @@
+ 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)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -115,12 +115,3 @@
+ default: \
+ _dl_exit(1); \
+ }
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function.
+- */
+-
+-#define START() return _dl_elf_main;
+-
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,8 +1,9 @@
+ /* 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);}
+-#include "sys/syscall.h"
+
+ #undef __syscall_return
+ #define __syscall_return(type, res) \
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,8 +25,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -41,6 +41,8 @@
+ 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)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -3,15 +3,46 @@
+ * 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"
+- "_start:\n"
+- " .set _start,_dl_start\n"
+- " .size _start,.-_start\n"
+- " .previous\n"
+-);
++
++asm ("\
++ .text\n\
++ .global _start\n\
++ .type _start,%function\n\
++ .align 32\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
+@@ -19,17 +50,15 @@
+ * 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) __asm__("\tadd %%fp,68,%0\n" : "=r" (ARGVP));
++#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(ELF32_R_TYPE((RELP)->r_info)) { \
++switch(ELF_R_TYPE((RELP)->r_info)) { \
+ case R_SPARC_32: \
+- *REL = SYMBOL + (RELP)->r_addend; \
+- break; \
+ case R_SPARC_GLOB_DAT: \
+ *REL = SYMBOL + (RELP)->r_addend; \
+ break; \
+@@ -38,7 +67,6 @@
+ REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \
+ break; \
+ case R_SPARC_NONE: \
+- break; \
+ case R_SPARC_WDISP30: \
+ break; \
+ case R_SPARC_RELATIVE: \
+@@ -46,18 +74,4 @@
+ break; \
+ default: \
+ _dl_exit(1); \
+- }
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. The crt calls atexit with $g1 if not null, so we need to
+- * ensure that it contains NULL.
+- */
+-
+-#define START() \
+- __asm__ volatile ( \
+- "add %%g0,%%g0,%%g1\n\t" \
+- "jmpl %0, %%o7\n\t" \
+- "restore %%g0,%%g0,%%g0\n\t" \
+- : /*"=r" (status) */ : \
+- "r" (_dl_elf_main): "g1", "o0", "o1")
++}
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 13:39:21.000000000 -0600
+@@ -1,187 +1,8 @@
+-/*
+- * This file contains the system call macros and syscall
+- * numbers used by the shared library loader.
+- *
+- * NOTE: This should be integrated/moved to
+- * sysdeps/linux/sparc/bits/syscalls.h at some point ...
+- */
+-
+-#define MMAP_HAS_6_ARGS
+-
+-#define __NR_exit 1
+-#define __NR_read 3
+-#define __NR_write 4
+-#define __NR_open 5
+-#define __NR_close 6
+-#define __NR_getpid 20
+-#define __NR_getuid 24
+-#define __NR_getgid 47
+-#define __NR_geteuid 49
+-#define __NR_getegid 50
+-#define __NR_readlink 58
+-#define __NR_mmap 71
+-#define __NR_munmap 73
+-#define __NR_stat 38
+-#define __NR_mprotect 74
+-
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-
+-/* Here are the macros which define how this platform makes
+- * system calls. This particular variant does _not_ set
+- * errno (note how _dl_errno is used in __syscall_return) since
+- * these will get called before the errno symbol is dynamicly
+- * linked. */
+-
+-#define __syscall_return(type, res) \
+-do { \
+- if (res < -255 || res >= 0) \
+- return (type) res; \
+- __set_errno(-res); \
+- res = -1; \
+- return (type) res; \
+-} while (0)
+-
+-#define _syscall0(type,name) \
+-type name(void) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res)\
+- : "r" (__g1) \
+- : "o0", "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1,type2 arg2) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1,type2 arg2,type3 arg3) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- register long __o3 __asm__ ("o3") = (long)(arg4); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+- type5,arg5) \
+-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- register long __o3 __asm__ ("o3") = (long)(arg4); \
+- register long __o4 __asm__ ("o4") = (long)(arg5); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+- type5,arg5,type6,arg6) \
+-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- register long __o3 __asm__ ("o3") = (long)(arg4); \
+- register long __o4 __asm__ ("o4") = (long)(arg5); \
+- register long __o5 __asm__ ("o5") = (long)(arg6); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,9 +1,9 @@
+-
++/* vi: set sw=4 ts=4: */
+ /*
+ * Various assmbly 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 LINUXBIN
+
+ /* Define this if the system uses RELOCA. */
+ #define ELF_USES_RELOCA
+@@ -31,19 +31,14 @@
+ #undef MAGIC2
+
+ /* Used for error messages */
+-#define ELF_TARGET "Sparc"
++#define ELF_TARGET "sparc"
+
+-#ifndef COMPILE_ASM
+-extern unsigned int _dl_linux_resolver(unsigned int reloc_entry,
+- unsigned int * i);
+-#endif
++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 __linux__
+-#define SOLARIS_COMPATIBLE
+-#endif
+
+ #ifndef COMPILE_ASM
+ /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */
+@@ -87,13 +82,6 @@
+ #define do_rem(result, n, base) ((result) = sparc_mod(n, base))
+ #endif
+
+-/*
+- * dbx wants the binder to have a specific name. Mustn't disappoint it.
+- */
+-#ifdef SOLARIS_COMPATIBLE
+-#define _dl_linux_resolve _elf_rtbndr
+-#endif
+-
+ /* 4096 bytes alignment */
+ /* ...but 8192 is required for mmap() on sparc64 kernel */
+ #define PAGE_ALIGN 0xffffe000
+@@ -160,7 +148,7 @@
+ elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+ {
+- Elf32_Rela * rpnt = (void *)rel_addr;
++ Elf32_Rela * rpnt = (void *)rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -33,236 +33,340 @@
+ 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. */
++ 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 int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
++unsigned long
++_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+ {
+- int reloc_type;
+- Elf32_Rela * this_reloc;
+- char * strtab;
+- Elf32_Sym * symtab;
+- Elf32_Rela * rel_addr;
+- struct elf_resolve * tpnt;
+- int symtab_index;
+- char * new_addr;
+- char ** got_addr;
+- unsigned int instr_addr;
+- tpnt = (struct elf_resolve *) plt[2];
+-
+- rel_addr = (Elf32_Rela *)tpnt->dynamic_info[DT_JMPREL];
+-
+- /*
+- * Generate the correct relocation index into the .rela.plt section.
+- */
+- reloc_entry = (reloc_entry >> 10) - 0xc;
+-
+- this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
+-
+- reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+- symtab_index = ELF32_R_SYM(this_reloc->r_info);
+-
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+-
+-#ifdef __SUPPORT_LD_DEBUG__
+- if (_dl_debug_symbols) {
+- _dl_dprintf(2, "tpnt = %x\n", tpnt);
+- _dl_dprintf(2, "reloc = %x\n", this_reloc);
+- _dl_dprintf(2, "symtab = %x\n", symtab);
+- _dl_dprintf(2, "strtab = %x\n", strtab);
+- }
+-#endif
+-
+-
+- if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
+- _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
+- _dl_progname, reloc_type);
+- _dl_exit(30);
+- };
+-
+- /* Address of jump instruction to fix up */
+- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
+- got_addr = (char **) instr_addr;
+-
+-#ifdef __SUPPORT_LD_DEBUG__
+- if (_dl_debug_symbols) {
+- _dl_dprintf(2, "symtab_index %x\n", symtab_index);
+-
+- _dl_dprintf(2, "Resolving symbol %s\n",
+- strtab + symtab[symtab_index].st_name);
+- }
+-#endif
+-
+- /* Get the address of the GOT entry */
+- new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
+- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+- if(unlikely(!new_addr)) {
+- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+- _dl_progname, strtab + symtab[symtab_index].st_name);
+- _dl_exit(31);
+- };
++ int reloc_type;
++ 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);
++ reloc_type = ELF_R_TYPE(this_reloc->r_info);
++ 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;
++
++ if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
++ _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
++ _dl_progname);
++ _dl_exit(1);
++ }
++
++ /* 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, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
++ 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",
+- strtab + symtab[symtab_index].st_name);
+- if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+- "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
++ 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) {
++ if (!_dl_debug_nofixups)
++#endif
++ {
+ got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
+ got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
+ }
++
++ return (unsigned long)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;
++
++ /* 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
+- got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
+- got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
++ "%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;
++}
+
+- _dl_dprintf(2, "Address = %x\n",new_addr);
+- _dl_exit(32);
++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;
++ ElfW(Sym) *sym;
++ 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 = &symtab[symtab_index];
++ symbol_addr = 0;
++ symname = strtab + sym->st_name;
++
++ if (symtab_index) {
++ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
++ elf_machine_type_class(reloc_type));
++ /*
++ * 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->st_info) != STB_WEAK)) {
++ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_exit(1);
++ }
++ }
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ old_val = *reloc_addr;
++#endif
+
+- return (unsigned int) new_addr;
++ symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */
++
++ switch (reloc_type) {
++ case R_SPARC_NONE:
++ break;
++
++#if 0 /* these dont really seem to be useful */
++ case R_SPARC_8:
++ *(char *) reloc_addr = symbol_addr;
++ break;
++ case R_SPARC_16:
++ *(short *) reloc_addr = symbol_addr;
++ break;
++ case R_SPARC_DISP8:
++ *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr;
++ break;
++ case R_SPARC_DISP16:
++ *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr;
++ break;
++#endif
++
++ 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:
++/*
++value = symbol_addr;
++value += reloc->r_addend;
++disp = value - reloc_addr;
++reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff);
++reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10);
++ reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff);
++ reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10);
++*/
++ reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
++ reloc_addr[2] = 0x81c06000 | (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->st_size,
++ symbol_addr, reloc_addr);
++#endif
++
++ _dl_memcpy((char *)reloc_addr,
++ (char *)symbol_addr,
++ 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 __SPARC_LAZY_RELOC_WORKS
++#ifdef __SPARC_LAZY_RELOC_WORKS
++static int
++_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *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 *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
+-{
+- int i;
+- char * strtab;
+- int reloc_type;
+- int symtab_index;
+- Elf32_Sym * symtab;
+- Elf32_Rela * rpnt;
+- unsigned int * reloc_addr;
+- struct elf_resolve * tpnt = arg_rpnt->dyn;
+-
+- /* Now parse the relocation information */
+- rpnt = (Elf32_Rela *)rel_addr;
+-
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
+-
+- for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
+- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE(rpnt->r_info);
+- symtab_index = ELF32_R_SYM(rpnt->r_info);
+-
+- switch(reloc_type){
+- case R_SPARC_NONE:
+- break;
+- case R_SPARC_JMP_SLOT:
+- break;
+- default:
+- _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
+-#if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]);
+-#endif
+- if(symtab_index) _dl_dprintf(2, "'%s'\n",
+- strtab + symtab[symtab_index].st_name);
+- _dl_exit(33);
+- };
+- };
+-}
+-
+-int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
+-{
+- int i;
+- char * strtab;
+- int reloc_type;
+- int goof = 0;
+- Elf32_Sym * symtab;
+- Elf32_Rela * rpnt;
+- unsigned int * reloc_addr;
+- unsigned int symbol_addr;
+- int symtab_index;
+- struct elf_resolve * tpnt = arg_rpnt->dyn;
+- /* Now parse the relocation information */
+-
+- rpnt = (Elf32_Rela *)rel_addr;
+-
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
+-
+- for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
+- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE(rpnt->r_info);
+- symtab_index = ELF32_R_SYM(rpnt->r_info);
+- symbol_addr = 0;
+-
+- if(symtab_index) {
+-
+- symbol_addr = (unsigned int)
+- _dl_find_hash(strtab + symtab[symtab_index].st_name,
+- tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type));
+-
+- if(!symbol_addr &&
+- ELF32_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);
+- };
+- };
+- switch(reloc_type){
+- case R_SPARC_NONE:
+- break;
+- case R_SPARC_32:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_SPARC_DISP32:
+- *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
+- break;
+- case R_SPARC_GLOB_DAT:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_SPARC_JMP_SLOT:
+- reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
+- reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
+- break;
+- case R_SPARC_RELATIVE:
+- *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
+- 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_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_WDISP30:
+- *reloc_addr = (*reloc_addr & 0xc0000000)|
+- ((symbol_addr - (unsigned int) reloc_addr) >> 2);
+- break;
+- case R_SPARC_COPY:
+- _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size);
+- break;
+- default:
+- _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+-#if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]);
+-#endif
+- if (symtab_index)
+- _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+- _dl_exit(34);
+- };
++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, rel_addr, rel_size);
++#endif
++}
+
+- };
+- return goof;
++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);
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h 2006-04-28 00:14:35.000000000 -0600
+@@ -30,7 +30,10 @@
+ */
+
+ static const char *_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"
++ [ 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 -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -6,7 +6,7 @@
+ *
+ * Parts taken from glibc/sysdeps/x86_64/dl-machine.h
+ */
+-asm(
++__asm__ (
+ " .text\n"
+ " .align 16\n"
+ " .global _start\n"
+@@ -42,10 +42,10 @@
+
+ /* 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, Elf64_Sym *sym)
++void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr,
++ ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym)
+ {
+- switch (ELF64_R_TYPE(rpnt->r_info)) {
++ 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;
+@@ -63,8 +63,3 @@
+ _dl_exit(1);
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 13:39:17.000000000 -0600
+@@ -1,7 +1,8 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+-
+-#define MMAP_HAS_6_ARGS
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -41,8 +41,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+@@ -90,7 +88,7 @@
+ and compare it with the current value that we can get via
+ an RIP relative addressing mode. */
+
+- asm ("movq 1f(%%rip), %1\n"
++ __asm__ ("movq 1f(%%rip), %1\n"
+ "0:\tleaq _dl_start(%%rip), %0\n\t"
+ "subq %1, %0\n\t"
+ ".section\t.data\n"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -165,6 +165,7 @@
+ int reloc_type;
+ int symtab_index;
+ char *symname;
++ ElfW(Sym) *sym;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -174,8 +175,9 @@
+ 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 = &symtab[symtab_index];
+ symbol_addr = 0;
+- symname = strtab + symtab[symtab_index].st_name;
++ symname = strtab + sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+@@ -185,7 +187,7 @@
+ * 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(symtab[symtab_index].st_info) != STB_WEAK)) {
++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ };
+@@ -209,7 +211,7 @@
+
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_JUMP_SLOT:
+- *reloc_addr = symbol_addr;
++ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ /* handled by elf_machine_relative()
+@@ -217,33 +219,33 @@
+ *reloc_addr = map->l_addr + rpnt->r_addend;
+ break;
+ */
+-#if 0
+ case R_X86_64_DTPMOD64:
++ *reloc_addr = 1;
+ break;
+ case R_X86_64_DTPOFF64:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
++ *reloc_addr = sym->st_value + rpnt->r_addend;
+ break;
+ case R_X86_64_TPOFF64:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
++ *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr;
+ break;
+ case R_X86_64_32:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
++ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;
++ /* XXX: should check for overflow eh ? */
+ break;
+
+-#endif
+ 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, symtab[symtab_index].st_size,
++ symname, sym->st_size,
+ symbol_addr, reloc_addr);
+ #endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+- symtab[symtab_index].st_size);
++ sym->st_size);
+ } else
+ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
+ break;
+@@ -261,7 +263,6 @@
+ return 0;
+ }
+
+-#if 0
+ static int
+ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+@@ -288,7 +289,7 @@
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_JUMP_SLOT:
+- *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value;
++ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+ _dl_exit(1);
+@@ -302,17 +303,13 @@
+
+ return 0;
+ }
+-#endif
+
+ void
+ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+ {
+- _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
+-/* jump slot isnt working
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+-*/
+ }
+
+ int
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S uClibc-0.9.28/ldso/ldso/x86_64/resolve.S
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S 1969-12-31 17:00:00.000000000 -0700
++++ uClibc-0.9.28/ldso/ldso/x86_64/resolve.S 2006-04-28 00:14:35.000000000 -0600
+@@ -0,0 +1,63 @@
++/*
++ * 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
++.align 16
++
++_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 -urN uClibc-0.9.28.orig/ldso/libdl/Makefile uClibc-0.9.28/ldso/libdl/Makefile
+--- uClibc-0.9.28.orig/ldso/libdl/Makefile 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/libdl/Makefile 2006-04-28 00:14:35.000000000 -0600
+@@ -29,12 +29,14 @@
+ endif
+ XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) \
+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I. -I$(TOPDIR)include
++ -fno-builtin -nostdinc -D_LIBC \
++ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \
++ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include
+
+ XXFLAGS+=-isystem $(shell $(CC) -print-file-name=include)
+ XXFLAGS_NOPIC:=$(XXFLAGS)
+ ifeq ($(DOPIC),y)
+- XXFLAGS += $(PICFLAG) -D__LIBDL_SHARED__
++ XXFLAGS += $(PICFLAG) -DSHARED
+ endif
+ ifeq ($(strip $(SUPPORT_LD_DEBUG)),y)
+ XXFLAGS+=-D__SUPPORT_LD_DEBUG__
+diff -urN uClibc-0.9.28.orig/ldso/libdl/libdl.c uClibc-0.9.28/ldso/libdl/libdl.c
+--- uClibc-0.9.28.orig/ldso/libdl/libdl.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/libdl/libdl.c 2006-04-28 00:14:35.000000000 -0600
+@@ -3,7 +3,7 @@
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
++ * 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
+ *
+@@ -30,12 +30,12 @@
+ */
+
+
+-#define _GNU_SOURCE
++#define _GNU_SOURCE
+ #include <ldso.h>
+ #include <stdio.h>
+
+
+-#if defined (__LIBDL_SHARED__)
++#ifdef SHARED
+
+ /* When libdl is loaded as a shared library, we need to load in
+ * and use a pile of symbols from ldso... */
+@@ -52,6 +51,8 @@
+ extern struct r_debug *_dl_debug_addr;
+ extern unsigned long _dl_error_number;
+ extern void *(*_dl_malloc_function)(size_t);
++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);
+@@ -64,7 +65,7 @@
+ #endif
+
+
+-#else /* __LIBDL_SHARED__ */
++#else /* SHARED */
+
+ /* When libdl is linked as a static library, we need to replace all
+ * the symbols that otherwise would have been loaded in from ldso... */
+@@ -81,11 +82,11 @@
+ struct r_debug *_dl_debug_addr = NULL;
+ #define _dl_malloc malloc
+ #include "../ldso/dl-debug.c"
+-#include "dl-progname.h"
++#include LDSO_ELFINTERP
+ #include "../ldso/dl-hash.c"
+ #define _dl_trace_loaded_objects 0
+ #include "../ldso/dl-elf.c"
+-#endif /* __LIBDL_SHARED__ */
++#endif /* SHARED */
+
+ #ifdef __SUPPORT_LD_DEBUG__
+ # define _dl_if_debug_print(fmt, args...) \
+@@ -126,7 +127,8 @@
+ "Unable to resolve symbol"
+ };
+
+-void __attribute__ ((destructor)) dl_cleanup(void)
++void dl_cleanup(void) __attribute__ ((destructor));
++void dl_cleanup(void)
+ {
+ struct dyn_elf *d;
+ for (d = _dl_handles; d; d = d->next_handle) {
+@@ -138,13 +140,12 @@
+ {
+ struct elf_resolve *tpnt, *tfrom;
+ struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
+- struct dyn_elf *dpnt;
+ ElfW(Addr) from;
+ struct elf_resolve *tpnt1;
+ void (*dl_brk) (void);
+ int now_flag;
+ struct init_fini_list *tmp, *runp, *runp2, *dep_list;
+- int nlist, i;
++ unsigned int nlist, i;
+ struct elf_resolve **init_fini_list;
+
+ /* A bit of sanity checking... */
+@@ -169,12 +170,15 @@
+ * the application. Thus this may go away at some time
+ * in the future.
+ */
+- tfrom = NULL;
+- for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
+- tpnt = dpnt->dyn;
+- if (tpnt->loadaddr < from
+- && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
+- tfrom = tpnt;
++ {
++ struct dyn_elf *dpnt;
++ tfrom = NULL;
++ for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
++ tpnt = dpnt->dyn;
++ if (tpnt->loadaddr < from
++ && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
++ tfrom = tpnt;
++ }
+ }
+ for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next);
+
+@@ -233,11 +237,8 @@
+ 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) {
+- char *name;
+-
+ lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
+ dpnt->d_un.d_val);
+- name = _dl_get_last_path_component(lpntstr);
+ _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);
+@@ -297,14 +298,14 @@
+ }
+ /* Sort the INIT/FINI list in dependency order. */
+ for (runp2 = dep_list; runp2; runp2 = runp2->next) {
+- int j, k;
++ 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 *runp = init_fini_list[k]->init_fini;
++ struct init_fini_list *ele = init_fini_list[k]->init_fini;
+
+- for (; runp; runp = runp->next) {
+- if (runp->tpnt == runp2->tpnt) {
++ 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)
+@@ -367,7 +368,7 @@
+ }
+ }
+
+-#if defined (__LIBDL_SHARED__)
++#ifdef SHARED
+ /* Run the ctors and setup the dtors */
+ for (i = nlist; i; --i) {
+ tpnt = init_fini_list[i-1];
+@@ -384,8 +385,11 @@
+ (*dl_elf_func) ();
+ }
+ }
++
++ _dl_run_init_array(tpnt);
+ }
+-#endif
++#endif /* SHARED */
++
+ _dl_unmap_cache();
+ return (void *) dyn_chain;
+
+@@ -450,9 +454,16 @@
+ 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;
++ struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
+ struct init_fini_list *runp, *tmp;
+ ElfW(Phdr) *ppnt;
+ struct elf_resolve *tpnt, *run_tpnt;
+@@ -460,7 +471,7 @@
+ void (*dl_brk) (void);
+ struct dyn_elf *handle;
+ unsigned int end;
+- int i = 0, j;
++ unsigned int i, j;
+
+ handle = (struct dyn_elf *) vhandle;
+ if (handle == _dl_symbol_tables)
+@@ -491,13 +502,21 @@
+ for (j = 0; j < handle->init_fini.nlist; ++j) {
+ tpnt = handle->init_fini.init_fini[j];
+ if (--tpnt->usage_count == 0) {
+- if (tpnt->dynamic_info[DT_FINI] && need_fini &&
++ 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_elf_fini = (int (*)(void)) (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_elf_fini) ();
++#ifdef SHARED
++ _dl_run_fini_array(tpnt);
++#endif
++
++ if (tpnt->dynamic_info[DT_FINI]) {
++ dl_elf_fini = (int (*)(void)) (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_elf_fini) ();
++ }
+ }
+
+ _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
+@@ -541,8 +560,9 @@
+ 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->next->next;
++ rpnt1->next = rpnt1_tmp;
+ if (rpnt1->next)
+ rpnt1->next->prev = rpnt1;
+ break;
+@@ -588,8 +608,9 @@
+ }
+
+ /*
+- * Dump information to stderrr about the current loaded modules
++ * Dump information to stderr about the current loaded modules
+ */
++#if 1
+ static char *type[] = { "Lib", "Exe", "Int", "Mod" };
+
+ int dlinfo(void)
+@@ -660,16 +681,14 @@
+ {
+ char *strtab;
+ ElfW(Sym) *symtab;
+- int hn, si;
+- int sf;
+- int sn = 0;
++ unsigned int hn, si, sn, sf;
+ ElfW(Addr) sa;
+
+ sa = 0;
+ symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
+ strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
+
+- sf = 0;
++ sf = sn = 0;
+ for (hn = 0; hn < pelf->nbucket; hn++) {
+ for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
+ ElfW(Addr) symbol_addr;
+@@ -696,3 +715,4 @@
+ return 1;
+ }
+ }
++#endif
+diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -4,17 +4,15 @@
+ # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+ #endif
+
++#include <errno.h>
++
+ /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
+ * header files. It also defines the traditional `SYS_<name>' macros for older
+ * programs. */
+ #include <bits/sysnum.h>
+
+-#ifndef __set_errno
+-# define __set_errno(val) (*__errno_location ()) = (val)
+-#endif
+-
+ /*
+- Some of the sneaky macros in the code were taken from
++ Some of the sneaky macros in the code were taken from
+ glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h
+ */
+
+@@ -22,7 +20,8 @@
+
+ /* We need some help from the assembler to generate optimal code. We
+ define some macros here which later will be used. */
+-asm (".L__X'%ebx = 1\n\t"
++
++__asm__ (".L__X'%ebx = 1\n\t"
+ ".L__X'%ecx = 2\n\t"
+ ".L__X'%edx = 2\n\t"
+ ".L__X'%eax = 3\n\t"
+@@ -56,7 +55,6 @@
+ ".endif\n\t"
+ ".endm\n\t");
+
+-
+ #undef _syscall0
+ #define _syscall0(type,name) \
+ type name(void) \
+@@ -90,7 +88,7 @@
+ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+ { \
+ return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \
+-}
++}
+
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+@@ -100,10 +98,18 @@
+ return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \
+ }
+
++#undef _syscall6
++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
++ type5,arg5,type6,arg6) \
++type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \
++{ \
++return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \
++}
++
+ #define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ unsigned int resultvar; \
+- asm volatile ( \
++ __asm__ __volatile__ ( \
+ LOADARGS_##nr \
+ "movl %1, %%eax\n\t" \
+ "int $0x80\n\t" \
+@@ -125,6 +131,7 @@
+ #define LOADARGS_3 LOADARGS_1
+ #define LOADARGS_4 LOADARGS_1
+ #define LOADARGS_5 LOADARGS_1
++#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t"
+
+ #define RESTOREARGS_0
+ #define RESTOREARGS_1 \
+@@ -133,6 +140,7 @@
+ #define RESTOREARGS_3 RESTOREARGS_1
+ #define RESTOREARGS_4 RESTOREARGS_1
+ #define RESTOREARGS_5 RESTOREARGS_1
++#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1
+
+ #define ASMFMT_0()
+ #define ASMFMT_1(arg1) \
+@@ -145,7 +153,8 @@
+ , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
+ #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
+ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
+-
++#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \
++ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6)
+
+ #endif /* __ASSEMBLER__ */
+ #endif /* _BITS_SYSCALLS_H */
+diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -5,67 +5,164 @@
+ # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+ #endif
+
++#include <errno.h>
++
+ /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
+ * header files. It also defines the traditional `SYS_<name>' macros for older
+ * programs. */
+ #include <bits/sysnum.h>
+
+-
+-#define __STRINGIFY(s) __STRINGIFY2 (s)
+-#define __STRINGIFY2(s) #s
+-
+-#undef JUMPTARGET
+-#ifdef __PIC__
+-#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall@plt)
++/* Define a macro which expands inline into the wrapper code for a system
++ call. This use is for internal calls that do not need to handle errors
++ normally. It will never touch errno.
++ On powerpc a system call basically clobbers the same registers like a
++ function call, with the exception of LR (which is needed for the
++ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
++ an error return status). */
++
++# undef INLINE_SYSCALL
++#if 1
++# define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ INTERNAL_SYSCALL_DECL (sc_err); \
++ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
++ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
++ { \
++ __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
++ sc_ret = -1L; \
++ } \
++ sc_ret; \
++ })
+ #else
+-#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall)
++# define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ INTERNAL_SYSCALL_DECL (sc_err); \
++ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
++ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
++ { \
++ sc_ret = __syscall_error(INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));\
++ } \
++ sc_ret; \
++ })
+ #endif
+
+-#define unified_syscall_body(name) \
+- __asm__ ( \
+- ".section \".text\"\n\t" \
+- ".align 2\n\t" \
+- ".globl " __STRINGIFY(name) "\n\t" \
+- ".type " __STRINGIFY(name) ",@function\n\t" \
+- #name":\tli 0," __STRINGIFY(__NR_##name) "\n\t" \
+- "b " __MAKE_SYSCALL "\n\t" \
+- ".size\t" __STRINGIFY(name) ",.""-" __STRINGIFY(name) "\n" \
+- )
++/* Define a macro which expands inline into the wrapper code for a system
++ call. This use is for internal calls that do not need to handle errors
++ normally. It will never touch errno.
++ On powerpc a system call basically clobbers the same registers like a
++ function call, with the exception of LR (which is needed for the
++ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
++ an error return status). */
++
++# undef INTERNAL_SYSCALL_DECL
++# define INTERNAL_SYSCALL_DECL(err) long int err
++
++# undef INTERNAL_SYSCALL
++# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
++ ({ \
++ register long int r0 __asm__ ("r0"); \
++ register long int r3 __asm__ ("r3"); \
++ register long int r4 __asm__ ("r4"); \
++ register long int r5 __asm__ ("r5"); \
++ register long int r6 __asm__ ("r6"); \
++ register long int r7 __asm__ ("r7"); \
++ register long int r8 __asm__ ("r8"); \
++ register long int r9 __asm__ ("r9"); \
++ register long int r10 __asm__ ("r10"); \
++ register long int r11 __asm__ ("r11"); \
++ register long int r12 __asm__ ("r12"); \
++ LOADARGS_##nr(name, args); \
++ __asm__ __volatile__ \
++ ("sc \n\t" \
++ "mfcr %0" \
++ : "=&r" (r0), \
++ "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
++ "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
++ : ASM_INPUT_##nr \
++ : "cr0", "ctr", "memory"); \
++ err = r0; \
++ (int) r3; \
++ })
++# define INTERNAL_SYSCALL(name, err, nr, args...) \
++ INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
++
++# undef INTERNAL_SYSCALL_ERROR_P
++# define INTERNAL_SYSCALL_ERROR_P(val, err) \
++ ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
++
++# undef INTERNAL_SYSCALL_ERRNO
++# define INTERNAL_SYSCALL_ERRNO(val, err) (val)
++
++# define LOADARGS_0(name, dummy) \
++ r0 = (long int)name
++# define LOADARGS_1(name, __arg1) \
++ LOADARGS_0(name, 0); \
++ r3 = (long int)__arg1
++# define LOADARGS_2(name, __arg1, __arg2) \
++ LOADARGS_1(name, __arg1); \
++ r4 = (long int)__arg2
++# define LOADARGS_3(name, __arg1, __arg2, __arg3) \
++ LOADARGS_2(name, __arg1, __arg2); \
++ r5 = (long int)__arg3
++# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
++ LOADARGS_3(name, __arg1, __arg2, __arg3); \
++ r6 = (long int)__arg4
++# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
++ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
++ r7 = (long int)__arg5
++# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
++ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
++ r8 = (long int)__arg6
++
++# define ASM_INPUT_0 "0" (r0)
++# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
++# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
++# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
++# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
++# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
++# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
+
+ #undef _syscall0
+-#define _syscall0(type,name) \
+-type name(void); \
+-unified_syscall_body(name)
++#define _syscall0(type,name) \
++type name(void){ \
++ return (type) INLINE_SYSCALL(name, 0); \
++}
+
+ #undef _syscall1
+ #define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1); \
+-unified_syscall_body(name)
++type name(type1 arg1){ \
++ return (type) INLINE_SYSCALL(name, 1, arg1); \
++}
+
+ #undef _syscall2
+ #define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1, type2 arg2); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2){ \
++ return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \
++}
+
+ #undef _syscall3
+ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1, type2 arg2, type3 arg3); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3){ \
++ return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \
++}
+
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \
++ return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \
++}
+
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \
++ return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \
++}
+
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \
++ return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \
++}
+
+ #endif /* _BITS_SYSCALLS_H */
+
--- /dev/null
+Index: uclibc/libm/fp_private.h
+===================================================================
+--- uclibc/libm/fp_private.h (revision 12879)
++++ uclibc/libm/fp_private.h (working copy)
+@@ -70,10 +70,11 @@
+ *******************************************************************************/
+
+ #include <stdint.h>
++#include <endian.h>
+
+ typedef struct /* Hex representation of a double. */
+ {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint32_t high;
+ uint32_t low;
+ #else
+Index: uclibc/libm/powerpc/s_ceil.c
+===================================================================
+--- uclibc/libm/powerpc/s_ceil.c (revision 12879)
++++ uclibc/libm/powerpc/s_ceil.c (working copy)
+@@ -21,13 +21,15 @@
+ * *
+ *******************************************************************************/
+
++#include <endian.h>
++
+ static const double twoTo52 = 4503599627370496.0;
+ static const unsigned long signMask = 0x80000000ul;
+
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/s_ldexp.c
+===================================================================
+--- uclibc/libm/powerpc/s_ldexp.c (revision 12879)
++++ uclibc/libm/powerpc/s_ldexp.c (working copy)
+@@ -21,11 +21,12 @@
+
+ #include <limits.h>
+ #include <math.h>
++#include <endian.h>
+
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/s_rint.c
+===================================================================
+--- uclibc/libm/powerpc/s_rint.c (revision 12879)
++++ uclibc/libm/powerpc/s_rint.c (working copy)
+@@ -46,13 +46,14 @@
+
+ #include <limits.h>
+ #include <math.h>
++#include <endian.h>
+
+ #define SET_INVALID 0x01000000UL
+
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/s_floor.c
+===================================================================
+--- uclibc/libm/powerpc/s_floor.c (revision 12879)
++++ uclibc/libm/powerpc/s_floor.c (working copy)
+@@ -21,13 +21,15 @@
+ * *
+ *******************************************************************************/
+
++#include <endian.h>
++
+ static const double twoTo52 = 4503599627370496.0;
+ static const unsigned long signMask = 0x80000000ul;
+
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/s_logb.c
+===================================================================
+--- uclibc/libm/powerpc/s_logb.c (revision 12879)
++++ uclibc/libm/powerpc/s_logb.c (working copy)
+@@ -32,10 +32,12 @@
+ * Standard 754. *
+ *******************************************************************************/
+
++#include <endian.h>
++
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/s_frexp.c
+===================================================================
+--- uclibc/libm/powerpc/s_frexp.c (revision 12879)
++++ uclibc/libm/powerpc/s_frexp.c (working copy)
+@@ -21,13 +21,14 @@
+
+ #include <limits.h>
+ #include <math.h>
++#include <endian.h>
+
+ static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
+
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/s_modf.c
+===================================================================
+--- uclibc/libm/powerpc/s_modf.c (revision 12879)
++++ uclibc/libm/powerpc/s_modf.c (working copy)
+@@ -45,13 +45,14 @@
+
+ #include <limits.h>
+ #include <math.h>
++#include <endian.h>
+
+ #define SET_INVALID 0x01000000UL
+
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libm/powerpc/w_scalb.c
+===================================================================
+--- uclibc/libm/powerpc/w_scalb.c (revision 12879)
++++ uclibc/libm/powerpc/w_scalb.c (working copy)
+@@ -19,10 +19,12 @@
+ **
+ ***********************************************************************/
+
++#include <endian.h>
++
+ typedef union
+ {
+ struct {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long int hi;
+ unsigned long int lo;
+ #else
+Index: uclibc/libc/string/sh64/strcpy.S
+===================================================================
+--- uclibc/libc/string/sh64/strcpy.S (revision 12879)
++++ uclibc/libc/string/sh64/strcpy.S (working copy)
+@@ -6,7 +6,9 @@
+ !
+ ! SH5 code Copyright 2002 SuperH Ltd.
+
+-#ifdef __LITTLE_ENDIAN__
++#include <endian.h>
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
+ #define SHHI shlld
+ #define SHLO shlrd
+ #else
+@@ -67,7 +69,7 @@
+ add r5, r63, r4
+ addi r0, 8, r0
+ shortstring:
+-#ifndef __LITTLE_ENDIAN__
++#if __BYTE_ORDER != __LITTLE_ENDIAN
+ pta/l shortstring2,tr1
+ byterev r4,r4
+ #endif
+Index: uclibc/libc/string/sh64/memset.S
+===================================================================
+--- uclibc/libc/string/sh64/memset.S (revision 12879)
++++ uclibc/libc/string/sh64/memset.S (working copy)
+@@ -9,7 +9,9 @@
+ ! Copyright 2002 SuperH Ltd.
+ !
+
+-#ifdef __LITTLE_ENDIAN__
++#include <endian.h>
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
+ #define SHHI shlld
+ #define SHLO shlrd
+ #else
+Index: uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h
+===================================================================
+--- uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h (revision 12879)
++++ uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h (working copy)
+@@ -30,10 +30,10 @@
+ };
+
+ struct kernel_stat64 {
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned char __pad0b[6];
+ unsigned short st_dev;
+-#elif defined(__LITTLE_ENDIAN__)
++#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
+ unsigned short st_dev;
+ unsigned char __pad0b[6];
+ #else
+@@ -48,7 +48,7 @@
+ unsigned long st_uid;
+ unsigned long st_gid;
+
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned char __pad3b[6];
+ unsigned short st_rdev;
+ #else /* Must be little */
+@@ -60,7 +60,7 @@
+ long long st_size;
+ unsigned long st_blksize;
+
+-#if defined(__BIG_ENDIAN__)
++#if (__BYTE_ORDER == __BIG_ENDIAN)
+ unsigned long __pad4; /* Future possible st_blocks hi bits */
+ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
+ #else /* Must be little */
--- /dev/null
+diff --git a/include/printf.h b/include/printf.h
+index 340b6cb..2dea58f 100644
+--- a/include/printf.h
++++ b/include/printf.h
+@@ -75,6 +75,7 @@ struct printf_info
+ unsigned int is_short:1; /* h flag. */
+ unsigned int is_long:1; /* l flag. */
+ unsigned int is_long_double:1;/* L flag. */
++ unsigned int __padding:20;/* non-gnu -- total of 32 bits on 32bit arch */
+
+ #elif __BYTE_ORDER == __BIG_ENDIAN
+
+diff --git a/include/pthread.h b/include/pthread.h
+index 8c01172..cee112b 100644
+--- a/include/pthread.h
++++ b/include/pthread.h
+@@ -644,7 +644,8 @@ extern void _pthread_cleanup_pop (struct
+ /* Install a cleanup handler as pthread_cleanup_push does, but also
+ saves the current cancellation type and set it to deferred cancellation. */
+
+-#ifdef __USE_GNU
++/* #ifdef __USE_GNU */
++#if defined(__USE_GNU) || defined(_LIBC)
+ # define pthread_cleanup_push_defer_np(routine,arg) \
+ { struct _pthread_cleanup_buffer _buffer; \
+ _pthread_cleanup_push_defer (&_buffer, (routine), (arg));
+diff --git a/libc/inet/getnetent.c b/libc/inet/getnetent.c
+index 181c5ad..659bf5d 100644
+--- a/libc/inet/getnetent.c
++++ b/libc/inet/getnetent.c
+@@ -22,18 +22,9 @@
+ #include <netdb.h>
+ #include <arpa/inet.h>
+
++#include <bits/uClibc_mutex.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
+-
+-
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ #define MAXALIASES 35
+ static const char NETDB[] = _PATH_NETWORKS;
+@@ -46,25 +37,25 @@ int _net_stayopen;
+
+ void setnetent(int f)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (netf == NULL)
+- netf = fopen(NETDB, "r" );
++ netf = fopen(NETDB, "r" );
+ else
+- rewind(netf);
++ rewind(netf);
+ _net_stayopen |= f;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return;
+ }
+
+ void endnetent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (netf) {
+- fclose(netf);
+- netf = NULL;
++ fclose(netf);
++ netf = NULL;
+ }
+ _net_stayopen = 0;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ static char * any(register char *cp, char *match)
+@@ -72,10 +63,10 @@ static char * any(register char *cp, cha
+ register char *mp, c;
+
+ while ((c = *cp)) {
+- for (mp = match; *mp; mp++)
+- if (*mp == c)
+- return (cp);
+- cp++;
++ for (mp = match; *mp; mp++)
++ if (*mp == c)
++ return (cp);
++ cp++;
+ }
+ return ((char *)0);
+ }
+@@ -84,59 +75,62 @@ struct netent * getnetent(void)
+ {
+ char *p;
+ register char *cp, **q;
++ struct netent *rv = NULL;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) {
+- UNLOCK;
+- return (NULL);
++ goto DONE;
+ }
+-again:
++ again:
+
+ if (!line) {
+- line = malloc(BUFSIZ + 1);
+- if (!line)
+- abort();
++ line = malloc(BUFSIZ + 1);
++ if (!line)
++ abort();
+ }
+
+ p = fgets(line, BUFSIZ, netf);
+ if (p == NULL) {
+- UNLOCK;
+- return (NULL);
++ goto DONE;
+ }
+ if (*p == '#')
+- goto again;
++ goto again;
+ cp = any(p, "#\n");
+ if (cp == NULL)
+- goto again;
++ goto again;
+ *cp = '\0';
+ net.n_name = p;
+ cp = any(p, " \t");
+ if (cp == NULL)
+- goto again;
++ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+- cp++;
++ cp++;
+ p = any(cp, " \t");
+ if (p != NULL)
+- *p++ = '\0';
++ *p++ = '\0';
+ net.n_net = inet_network(cp);
+ net.n_addrtype = AF_INET;
+ q = net.n_aliases = net_aliases;
+ if (p != NULL)
+- cp = p;
++ cp = p;
+ while (cp && *cp) {
+- if (*cp == ' ' || *cp == '\t') {
+- cp++;
+- continue;
+- }
+- if (q < &net_aliases[MAXALIASES - 1])
+- *q++ = cp;
+- cp = any(cp, " \t");
+- if (cp != NULL)
+- *cp++ = '\0';
++ if (*cp == ' ' || *cp == '\t') {
++ cp++;
++ continue;
++ }
++ if (q < &net_aliases[MAXALIASES - 1])
++ *q++ = cp;
++ cp = any(cp, " \t");
++ if (cp != NULL)
++ *cp++ = '\0';
+ }
+ *q = NULL;
+- UNLOCK;
+- return (&net);
++
++ rv = &net;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
++ return rv;
+ }
+
+diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c
+index c9f35f1..3665d89 100644
+--- a/libc/inet/getproto.c
++++ b/libc/inet/getproto.c
+@@ -62,17 +62,9 @@
+ #include <string.h>
+ #include <errno.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
+-
++#include <bits/uClibc_mutex.h>
+
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ #define MAXALIASES 35
+ #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES))
+@@ -85,109 +77,114 @@ static int proto_stayopen;
+ static void __initbuf(void)
+ {
+ if (!static_aliases) {
+- static_aliases = malloc(SBUFSIZE);
+- if (!static_aliases)
+- abort();
++ static_aliases = malloc(SBUFSIZE);
++ if (!static_aliases)
++ abort();
+ }
+ }
+
+ void setprotoent(int f)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (protof == NULL)
+- protof = fopen(_PATH_PROTOCOLS, "r" );
++ protof = fopen(_PATH_PROTOCOLS, "r" );
+ else
+- rewind(protof);
++ rewind(protof);
+ proto_stayopen |= f;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ void endprotoent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (protof) {
+- fclose(protof);
+- protof = NULL;
++ fclose(protof);
++ protof = NULL;
+ }
+ proto_stayopen = 0;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ int getprotoent_r(struct protoent *result_buf,
+- char *buf, size_t buflen,
+- struct protoent **result)
++ char *buf, size_t buflen,
++ struct protoent **result)
+ {
+ char *p;
+ register char *cp, **q;
+ char **proto_aliases;
+ char *line;
++ int rv;
+
+ *result = NULL;
+
+ if (buflen < sizeof(*proto_aliases)*MAXALIASES) {
+- errno=ERANGE;
+- return errno;
++ errno=ERANGE;
++ return errno;
+ }
+- LOCK;
++
++ __UCLIBC_MUTEX_LOCK(mylock);
+ proto_aliases=(char **)buf;
+ buf+=sizeof(*proto_aliases)*MAXALIASES;
+ buflen-=sizeof(*proto_aliases)*MAXALIASES;
+
+ if (buflen < BUFSIZ+1) {
+- UNLOCK;
+- errno=ERANGE;
+- return errno;
++ errno=rv=ERANGE;
++ goto DONE;
+ }
+ line=buf;
+ buf+=BUFSIZ+1;
+ buflen-=BUFSIZ+1;
+
+ if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) {
+- UNLOCK;
+- return errno;
++ rv=errno;
++ goto DONE;
+ }
+-again:
++ again:
+ if ((p = fgets(line, BUFSIZ, protof)) == NULL) {
+- UNLOCK;
+- return TRY_AGAIN;
++ rv=TRY_AGAIN;
++ goto DONE;
+ }
+
+ if (*p == '#')
+- goto again;
++ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+- goto again;
++ goto again;
+ *cp = '\0';
+ result_buf->p_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+- goto again;
++ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+- cp++;
++ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+- *p++ = '\0';
++ *p++ = '\0';
+ result_buf->p_proto = atoi(cp);
+ q = result_buf->p_aliases = proto_aliases;
+ if (p != NULL) {
+- cp = p;
+- while (cp && *cp) {
+- if (*cp == ' ' || *cp == '\t') {
+- cp++;
+- continue;
+- }
+- if (q < &proto_aliases[MAXALIASES - 1])
+- *q++ = cp;
+- cp = strpbrk(cp, " \t");
+- if (cp != NULL)
+- *cp++ = '\0';
+- }
++ cp = p;
++ while (cp && *cp) {
++ if (*cp == ' ' || *cp == '\t') {
++ cp++;
++ continue;
++ }
++ if (q < &proto_aliases[MAXALIASES - 1])
++ *q++ = cp;
++ cp = strpbrk(cp, " \t");
++ if (cp != NULL)
++ *cp++ = '\0';
++ }
+ }
+ *q = NULL;
+ *result=result_buf;
+- UNLOCK;
+- return 0;
++
++ rv = 0;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
++ return rv;
+ }
+
+ struct protoent * getprotoent(void)
+@@ -201,26 +198,26 @@ struct protoent * getprotoent(void)
+
+
+ int getprotobyname_r(const char *name,
+- struct protoent *result_buf,
+- char *buf, size_t buflen,
+- struct protoent **result)
++ struct protoent *result_buf,
++ char *buf, size_t buflen,
++ struct protoent **result)
+ {
+ register char **cp;
+ int ret;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ setprotoent(proto_stayopen);
+ while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) {
+- if (strcmp(result_buf->p_name, name) == 0)
+- break;
+- for (cp = result_buf->p_aliases; *cp != 0; cp++)
+- if (strcmp(*cp, name) == 0)
+- goto found;
++ if (strcmp(result_buf->p_name, name) == 0)
++ break;
++ for (cp = result_buf->p_aliases; *cp != 0; cp++)
++ if (strcmp(*cp, name) == 0)
++ goto found;
+ }
+-found:
++ found:
+ if (!proto_stayopen)
+- endprotoent();
+- UNLOCK;
++ endprotoent();
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return *result?0:ret;
+ }
+
+@@ -236,20 +233,20 @@ struct protoent * getprotobyname(const c
+
+
+ int getprotobynumber_r (int proto_num,
+- struct protoent *result_buf,
+- char *buf, size_t buflen,
+- struct protoent **result)
++ struct protoent *result_buf,
++ char *buf, size_t buflen,
++ struct protoent **result)
+ {
+ int ret;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ setprotoent(proto_stayopen);
+ while (!(ret=getprotoent_r(result_buf, buf, buflen, result)))
+- if (result_buf->p_proto == proto_num)
+- break;
++ if (result_buf->p_proto == proto_num)
++ break;
+ if (!proto_stayopen)
+- endprotoent();
+- UNLOCK;
++ endprotoent();
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return *result?0:ret;
+ }
+
+diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c
+index cbe5c50..b666057 100644
+--- a/libc/inet/getservice.c
++++ b/libc/inet/getservice.c
+@@ -65,20 +65,9 @@
+ #include <arpa/inet.h>
+ #include <errno.h>
+
++#include <bits/uClibc_mutex.h>
+
+-
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
+-
+-
+-
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ #define MAXALIASES 35
+ #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES))
+@@ -91,32 +80,32 @@ static int serv_stayopen;
+ static void __initbuf(void)
+ {
+ if (!servbuf) {
+- servbuf = malloc(SBUFSIZE);
+- if (!servbuf)
+- abort();
++ servbuf = malloc(SBUFSIZE);
++ if (!servbuf)
++ abort();
+ }
+ }
+
+ void setservent(int f)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (servf == NULL)
+- servf = fopen(_PATH_SERVICES, "r" );
++ servf = fopen(_PATH_SERVICES, "r" );
+ else
+- rewind(servf);
++ rewind(servf);
+ serv_stayopen |= f;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ void endservent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (servf) {
+- fclose(servf);
+- servf = NULL;
++ fclose(servf);
++ servf = NULL;
+ }
+ serv_stayopen = 0;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ struct servent * getservent(void)
+@@ -149,127 +138,129 @@ struct servent * getservbyport(int port,
+ }
+
+ int getservent_r(struct servent * result_buf,
+- char * buf, size_t buflen,
+- struct servent ** result)
++ char * buf, size_t buflen,
++ struct servent ** result)
+ {
+ char *p;
+ register char *cp, **q;
+ char **serv_aliases;
+ char *line;
++ int rv;
+
+ *result=NULL;
+
+ if (buflen < sizeof(*serv_aliases)*MAXALIASES) {
+- errno=ERANGE;
+- return errno;
++ errno=ERANGE;
++ return errno;
+ }
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ serv_aliases=(char **)buf;
+ buf+=sizeof(*serv_aliases)*MAXALIASES;
+ buflen-=sizeof(*serv_aliases)*MAXALIASES;
+
+ if (buflen < BUFSIZ+1) {
+- UNLOCK;
+- errno=ERANGE;
+- return errno;
++ errno=rv=ERANGE;
++ goto DONE;
+ }
+ line=buf;
+ buf+=BUFSIZ+1;
+ buflen-=BUFSIZ+1;
+
+ if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) {
+- UNLOCK;
+- errno=EIO;
+- return errno;
++ errno=rv=EIO;
++ goto DONE;
+ }
+-again:
++ again:
+ if ((p = fgets(line, BUFSIZ, servf)) == NULL) {
+- UNLOCK;
+- errno=EIO;
+- return errno;
++ errno=rv=EIO;
++ goto DONE;
+ }
+ if (*p == '#')
+- goto again;
++ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+- goto again;
++ goto again;
+ *cp = '\0';
+ result_buf->s_name = p;
+ p = strpbrk(p, " \t");
+ if (p == NULL)
+- goto again;
++ goto again;
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+- p++;
++ p++;
+ cp = strpbrk(p, ",/");
+ if (cp == NULL)
+- goto again;
++ goto again;
+ *cp++ = '\0';
+ result_buf->s_port = htons((u_short)atoi(p));
+ result_buf->s_proto = cp;
+ q = result_buf->s_aliases = serv_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+- *cp++ = '\0';
++ *cp++ = '\0';
+ while (cp && *cp) {
+- if (*cp == ' ' || *cp == '\t') {
+- cp++;
+- continue;
+- }
+- if (q < &serv_aliases[MAXALIASES - 1])
+- *q++ = cp;
+- cp = strpbrk(cp, " \t");
+- if (cp != NULL)
+- *cp++ = '\0';
++ if (*cp == ' ' || *cp == '\t') {
++ cp++;
++ continue;
++ }
++ if (q < &serv_aliases[MAXALIASES - 1])
++ *q++ = cp;
++ cp = strpbrk(cp, " \t");
++ if (cp != NULL)
++ *cp++ = '\0';
+ }
+ *q = NULL;
+ *result=result_buf;
+- UNLOCK;
+- return 0;
++
++ rv = 0;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
++ return rv;
+ }
+
+ int getservbyname_r(const char *name, const char *proto,
+- struct servent * result_buf, char * buf, size_t buflen,
+- struct servent ** result)
++ struct servent * result_buf, char * buf, size_t buflen,
++ struct servent ** result)
+ {
+ register char **cp;
+ int ret;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ setservent(serv_stayopen);
+ while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
+- if (strcmp(name, result_buf->s_name) == 0)
+- goto gotname;
+- for (cp = result_buf->s_aliases; *cp; cp++)
+- if (strcmp(name, *cp) == 0)
+- goto gotname;
+- continue;
+-gotname:
+- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
+- break;
++ if (strcmp(name, result_buf->s_name) == 0)
++ goto gotname;
++ for (cp = result_buf->s_aliases; *cp; cp++)
++ if (strcmp(name, *cp) == 0)
++ goto gotname;
++ continue;
++ gotname:
++ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
++ break;
+ }
+ if (!serv_stayopen)
+- endservent();
+- UNLOCK;
++ endservent();
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return *result?0:ret;
+ }
+
+ int getservbyport_r(int port, const char *proto,
+- struct servent * result_buf, char * buf,
+- size_t buflen, struct servent ** result)
++ struct servent * result_buf, char * buf,
++ size_t buflen, struct servent ** result)
+ {
+ int ret;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ setservent(serv_stayopen);
+ while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
+- if (result_buf->s_port != port)
+- continue;
+- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
+- break;
++ if (result_buf->s_port != port)
++ continue;
++ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
++ break;
+ }
+ if (!serv_stayopen)
+- endservent();
+- UNLOCK;
++ endservent();
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return *result?0:ret;
+ }
+diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
+index 27b60ef..0f583ab 100644
+--- a/libc/inet/resolv.c
++++ b/libc/inet/resolv.c
+@@ -7,7 +7,7 @@
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+-*/
++ */
+
+ /*
+ * Portions Copyright (c) 1985, 1993
+@@ -153,6 +153,11 @@
+ #include <sys/utsname.h>
+ #include <sys/un.h>
+
++#include <bits/uClibc_mutex.h>
++
++__UCLIBC_MUTEX_EXTERN(__resolv_lock);
++
++
+ #define MAX_RECURSE 5
+ #define REPLY_TIMEOUT 10
+ #define MAX_RETRIES 3
+@@ -180,18 +185,6 @@ extern char * __nameserver[MAX_SERVERS];
+ extern int __searchdomains;
+ extern char * __searchdomain[MAX_SEARCH];
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-extern pthread_mutex_t __resolv_lock;
+-# define BIGLOCK __pthread_mutex_lock(&__resolv_lock)
+-# define BIGUNLOCK __pthread_mutex_unlock(&__resolv_lock);
+-#else
+-# define BIGLOCK
+-# define BIGUNLOCK
+-#endif
+-
+-
+-
+ /* Structs */
+ struct resolv_header {
+ int id;
+@@ -229,49 +222,49 @@ enum etc_hosts_action {
+
+ /* function prototypes */
+ extern int __get_hosts_byname_r(const char * name, int type,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop);
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop);
+ extern int __get_hosts_byaddr_r(const char * addr, int len, int type,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop);
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop);
+ extern void __open_etc_hosts(FILE **fp);
+ extern int __read_etc_hosts_r(FILE *fp, const char * name, int type,
+- enum etc_hosts_action action,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop);
++ enum etc_hosts_action action,
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop);
+ extern int __dns_lookup(const char * name, int type, int nscount,
+- char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
++ char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
+
+ extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen);
+ extern int __decode_dotted(const unsigned char * message, int offset,
+- char * dest, int maxlen);
++ char * dest, int maxlen);
+ extern int __length_dotted(const unsigned char * message, int offset);
+ extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);
+ extern int __decode_header(unsigned char * data, struct resolv_header * h);
+ extern int __encode_question(struct resolv_question * q,
+- unsigned char * dest, int maxlen);
++ unsigned char * dest, int maxlen);
+ extern int __decode_question(unsigned char * message, int offset,
+- struct resolv_question * q);
++ struct resolv_question * q);
+ extern int __encode_answer(struct resolv_answer * a,
+- unsigned char * dest, int maxlen);
++ unsigned char * dest, int maxlen);
+ extern int __decode_answer(unsigned char * message, int offset,
+- struct resolv_answer * a);
++ struct resolv_answer * a);
+ extern int __length_question(unsigned char * message, int offset);
+ extern int __open_nameservers(void);
+ extern void __close_nameservers(void);
+ extern int __dn_expand(const u_char *, const u_char *, const u_char *,
+- char *, int);
++ char *, int);
+ extern int __ns_name_uncompress(const u_char *, const u_char *,
+- const u_char *, char *, size_t);
++ const u_char *, char *, size_t);
+ extern int __ns_name_ntop(const u_char *, char *, size_t);
+ extern int __ns_name_unpack(const u_char *, const u_char *, const u_char *,
+- u_char *, size_t);
++ u_char *, size_t);
+
+
+ #ifdef L_encodeh
+@@ -361,7 +354,7 @@ int __encode_dotted(const char *dotted,
+ This routine understands compressed data. */
+
+ int __decode_dotted(const unsigned char *data, int offset,
+- char *dest, int maxlen)
++ char *dest, int maxlen)
+ {
+ int l;
+ int measure = 1;
+@@ -435,7 +428,7 @@ int __length_dotted(const unsigned char
+
+ #ifdef L_encodeq
+ int __encode_question(struct resolv_question *q,
+- unsigned char *dest, int maxlen)
++ unsigned char *dest, int maxlen)
+ {
+ int i;
+
+@@ -460,7 +453,7 @@ int __encode_question(struct resolv_ques
+
+ #ifdef L_decodeq
+ int __decode_question(unsigned char *message, int offset,
+- struct resolv_question *q)
++ struct resolv_question *q)
+ {
+ char temp[256];
+ int i;
+@@ -525,7 +518,7 @@ int __encode_answer(struct resolv_answer
+
+ #ifdef L_decodea
+ int __decode_answer(unsigned char *message, int offset,
+- struct resolv_answer *a)
++ struct resolv_answer *a)
+ {
+ char temp[256];
+ int i;
+@@ -557,11 +550,11 @@ int __decode_answer(unsigned char *messa
+
+ #ifdef L_encodep
+ int __encode_packet(struct resolv_header *h,
+- struct resolv_question **q,
+- struct resolv_answer **an,
+- struct resolv_answer **ns,
+- struct resolv_answer **ar,
+- unsigned char *dest, int maxlen)
++ struct resolv_question **q,
++ struct resolv_answer **an,
++ struct resolv_answer **ns,
++ struct resolv_answer **ar,
++ unsigned char *dest, int maxlen)
+ {
+ int i, total = 0;
+ int j;
+@@ -621,7 +614,7 @@ int __decode_packet(unsigned char *data,
+
+ #ifdef L_formquery
+ int __form_query(int id, const char *name, int type, unsigned char *packet,
+- int maxlen)
++ int maxlen)
+ {
+ struct resolv_header h;
+ struct resolv_question q;
+@@ -649,14 +642,7 @@ int __form_query(int id, const char *nam
+
+ #ifdef L_dnslookup
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ /* Just for the record, having to lock __dns_lookup() just for these two globals
+ * is pretty lame. I think these two variables can probably be de-global-ized,
+@@ -665,7 +651,7 @@ static pthread_mutex_t mylock = PTHREAD_
+ static int ns=0, id=1;
+
+ int __dns_lookup(const char *name, int type, int nscount, char **nsip,
+- unsigned char **outpacket, struct resolv_answer *a)
++ unsigned char **outpacket, struct resolv_answer *a)
+ {
+ int i, j, len, fd, pos, rc;
+ struct timeval tv;
+@@ -693,10 +679,10 @@ int __dns_lookup(const char *name, int t
+ DPRINTF("Looking up type %d answer for '%s'\n", type, name);
+
+ /* Mess with globals while under lock */
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ local_ns = ns % nscount;
+ local_id = id;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ while (retries < MAX_RETRIES) {
+ if (fd != -1)
+@@ -722,13 +708,13 @@ int __dns_lookup(const char *name, int t
+
+ strncpy(lookup,name,MAXDNAME);
+ if (variant >= 0) {
+- BIGLOCK;
+- if (variant < __searchdomains) {
+- strncat(lookup,".", MAXDNAME);
+- strncat(lookup,__searchdomain[variant], MAXDNAME);
+- }
+- BIGUNLOCK;
+- }
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
++ if (variant < __searchdomains) {
++ strncat(lookup,".", MAXDNAME);
++ strncat(lookup,__searchdomain[variant], MAXDNAME);
++ }
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
++ }
+ DPRINTF("lookup name: %s\n", lookup);
+ q.dotted = (char *)lookup;
+ q.qtype = type;
+@@ -750,7 +736,7 @@ int __dns_lookup(const char *name, int t
+ fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ #endif
+ if (fd < 0) {
+- retries++;
++ retries++;
+ continue;
+ }
+
+@@ -772,11 +758,11 @@ int __dns_lookup(const char *name, int t
+ #endif
+ if (rc < 0) {
+ if (errno == ENETUNREACH) {
+- /* routing error, presume not transient */
+- goto tryall;
++ /* routing error, presume not transient */
++ goto tryall;
+ } else
+- /* retry */
+- retries++;
++ /* retry */
++ retries++;
+ continue;
+ }
+
+@@ -838,55 +824,55 @@ int __dns_lookup(const char *name, int t
+
+ first_answer = 1;
+ for (j=0;j<h.ancount;j++,pos += i)
+- {
+- i = __decode_answer(packet, pos, &ma);
++ {
++ i = __decode_answer(packet, pos, &ma);
+
+- if (i<0) {
+- DPRINTF("failed decode %d\n", i);
+- goto again;
+- }
++ if (i<0) {
++ DPRINTF("failed decode %d\n", i);
++ goto again;
++ }
+
+- if ( first_answer )
+- {
+- ma.buf = a->buf;
+- ma.buflen = a->buflen;
+- ma.add_count = a->add_count;
+- memcpy(a, &ma, sizeof(ma));
+- if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA)))
+- {
+- break;
+- }
+- if (a->atype != type)
+- {
+- free(a->dotted);
+- continue;
+- }
+- a->add_count = h.ancount - j - 1;
+- if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen)
+- {
+- break;
+- }
+- a->add_count = 0;
+- first_answer = 0;
+- }
+- else
+- {
+- free(ma.dotted);
+- if (ma.atype != type)
+- {
+- continue;
+- }
+- if (a->rdlength != ma.rdlength)
+- {
+- free(a->dotted);
+- DPRINTF("Answer address len(%u) differs from original(%u)\n",
+- ma.rdlength, a->rdlength);
+- goto again;
++ if ( first_answer )
++ {
++ ma.buf = a->buf;
++ ma.buflen = a->buflen;
++ ma.add_count = a->add_count;
++ memcpy(a, &ma, sizeof(ma));
++ if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA)))
++ {
++ break;
++ }
++ if (a->atype != type)
++ {
++ free(a->dotted);
++ continue;
++ }
++ a->add_count = h.ancount - j - 1;
++ if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen)
++ {
++ break;
++ }
++ a->add_count = 0;
++ first_answer = 0;
++ }
++ else
++ {
++ free(ma.dotted);
++ if (ma.atype != type)
++ {
++ continue;
++ }
++ if (a->rdlength != ma.rdlength)
++ {
++ free(a->dotted);
++ DPRINTF("Answer address len(%u) differs from original(%u)\n",
++ ma.rdlength, a->rdlength);
++ goto again;
++ }
++ memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength);
++ ++a->add_count;
++ }
+ }
+- memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength);
+- ++a->add_count;
+- }
+- }
+
+ DPRINTF("Answer name = |%s|\n", a->dotted);
+ DPRINTF("Answer type = |%d|\n", a->atype);
+@@ -900,48 +886,48 @@ int __dns_lookup(const char *name, int t
+ free(lookup);
+
+ /* Mess with globals while under lock */
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ ns = local_ns;
+ id = local_id;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ return (len); /* success! */
+
+- tryall:
++ tryall:
+ /* if there are other nameservers, give them a go,
+ otherwise return with error */
+ {
+ variant = -1;
+- local_ns = (local_ns + 1) % nscount;
+- if (local_ns == 0)
+- retries++;
++ local_ns = (local_ns + 1) % nscount;
++ if (local_ns == 0)
++ retries++;
+
+- continue;
++ continue;
+ }
+
+- again:
++ again:
+ /* if there are searchdomains, try them or fallback as passed */
+ {
+ int sdomains;
+- BIGLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ sdomains=__searchdomains;
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+
+ if (variant < sdomains - 1) {
+- /* next search */
+- variant++;
++ /* next search */
++ variant++;
+ } else {
+- /* next server, first search */
+- local_ns = (local_ns + 1) % nscount;
+- if (local_ns == 0)
+- retries++;
++ /* next server, first search */
++ local_ns = (local_ns + 1) % nscount;
++ if (local_ns == 0)
++ retries++;
+
+- variant = -1;
++ variant = -1;
+ }
+ }
+ }
+
+-fail:
++ fail:
+ if (fd != -1)
+ close(fd);
+ if (lookup)
+@@ -951,10 +937,10 @@ fail:
+ h_errno = NETDB_INTERNAL;
+ /* Mess with globals while under lock */
+ if (local_ns != -1) {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ ns = local_ns;
+ id = local_id;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+ return -1;
+ }
+@@ -966,9 +952,8 @@ int __nameservers;
+ char * __nameserver[MAX_SERVERS];
+ int __searchdomains;
+ char * __searchdomain[MAX_SEARCH];
+-#ifdef __UCLIBC_HAS_THREADS__
+-pthread_mutex_t __resolv_lock = PTHREAD_MUTEX_INITIALIZER;
+-#endif
++
++__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER);
+
+ /*
+ * we currently read formats not quite the same as that on normal
+@@ -982,60 +967,63 @@ int __open_nameservers()
+ #define RESOLV_ARGS 5
+ char szBuffer[128], *p, *argv[RESOLV_ARGS];
+ int argc;
++ int rv = 0;
+
+- BIGLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ if (__nameservers > 0) {
+- BIGUNLOCK;
+- return 0;
++ goto DONE;
+ }
+
+ if ((fp = fopen("/etc/resolv.conf", "r")) ||
+- (fp = fopen("/etc/config/resolv.conf", "r")))
+- {
+-
+- while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
++ (fp = fopen("/etc/config/resolv.conf", "r")))
++ {
+
+- for (p = szBuffer; *p && isspace(*p); p++)
+- /* skip white space */;
+- if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
+- continue;
+- argc = 0;
+- while (*p && argc < RESOLV_ARGS) {
+- argv[argc++] = p;
+- while (*p && !isspace(*p) && *p != '\n')
+- p++;
+- while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
+- *p++ = '\0';
+- }
++ while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
+
+- if (strcmp(argv[0], "nameserver") == 0) {
+- for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {
+- __nameserver[__nameservers++] = strdup(argv[i]);
+- DPRINTF("adding nameserver %s\n", argv[i]);
++ for (p = szBuffer; *p && isspace(*p); p++)
++ /* skip white space */;
++ if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
++ continue;
++ argc = 0;
++ while (*p && argc < RESOLV_ARGS) {
++ argv[argc++] = p;
++ while (*p && !isspace(*p) && *p != '\n')
++ p++;
++ while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
++ *p++ = '\0';
+ }
+- }
+
+- /* domain and search are mutually exclusive, the last one wins */
+- if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
+- while (__searchdomains > 0) {
+- free(__searchdomain[--__searchdomains]);
+- __searchdomain[__searchdomains] = NULL;
++ if (strcmp(argv[0], "nameserver") == 0) {
++ for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {
++ __nameserver[__nameservers++] = strdup(argv[i]);
++ DPRINTF("adding nameserver %s\n", argv[i]);
++ }
+ }
+- for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {
+- __searchdomain[__searchdomains++] = strdup(argv[i]);
+- DPRINTF("adding search %s\n", argv[i]);
++
++ /* domain and search are mutually exclusive, the last one wins */
++ if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
++ while (__searchdomains > 0) {
++ free(__searchdomain[--__searchdomains]);
++ __searchdomain[__searchdomains] = NULL;
++ }
++ for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {
++ __searchdomain[__searchdomains++] = strdup(argv[i]);
++ DPRINTF("adding search %s\n", argv[i]);
++ }
+ }
+ }
++ fclose(fp);
++ DPRINTF("nameservers = %d\n", __nameservers);
++ goto DONE;
+ }
+- fclose(fp);
+- DPRINTF("nameservers = %d\n", __nameservers);
+- BIGUNLOCK;
+- return 0;
+- }
+ DPRINTF("failed to open %s\n", "resolv.conf");
+ h_errno = NO_RECOVERY;
+- BIGUNLOCK;
+- return -1;
++
++ rv = -1;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
++ return rv;
+ }
+ #endif
+
+@@ -1044,7 +1032,7 @@ int __open_nameservers()
+
+ void __close_nameservers(void)
+ {
+- BIGLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ while (__nameservers > 0) {
+ free(__nameserver[--__nameservers]);
+ __nameserver[__nameservers] = NULL;
+@@ -1053,7 +1041,7 @@ void __close_nameservers(void)
+ free(__searchdomain[--__searchdomains]);
+ __searchdomain[__searchdomains] = NULL;
+ }
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+ }
+ #endif
+
+@@ -1063,8 +1051,8 @@ struct hostent *gethostbyname(const char
+ {
+ static struct hostent h;
+ static char buf[sizeof(struct in_addr) +
+- sizeof(struct in_addr *)*2 +
+- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
++ sizeof(struct in_addr *)*2 +
++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
+ struct hostent *hp;
+
+ gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);
+@@ -1082,8 +1070,8 @@ struct hostent *gethostbyname2(const cha
+ #else /* __UCLIBC_HAS_IPV6__ */
+ static struct hostent h;
+ static char buf[sizeof(struct in6_addr) +
+- sizeof(struct in6_addr *)*2 +
+- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
++ sizeof(struct in6_addr *)*2 +
++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
+ struct hostent *hp;
+
+ gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno);
+@@ -1119,7 +1107,7 @@ int res_init(void)
+ /** rp->rhook = NULL; **/
+ /** rp->_u._ext.nsinit = 0; **/
+
+- BIGLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ if(__searchdomains) {
+ int i;
+ for(i=0; i<__searchdomains; i++) {
+@@ -1139,7 +1127,7 @@ int res_init(void)
+ }
+ }
+ rp->nscount = __nameservers;
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+
+ return(0);
+ }
+@@ -1175,10 +1163,10 @@ int res_query(const char *dname, int cla
+
+ memset((char *) &a, '\0', sizeof(a));
+
+- BIGLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ __nameserversXX=__nameservers;
+ __nameserverXX=__nameserver;
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+ i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a);
+
+ if (i < 0) {
+@@ -1207,10 +1195,10 @@ int res_query(const char *dname, int cla
+ * is detected. Error code, if any, is left in h_errno.
+ */
+ int res_search(name, class, type, answer, anslen)
+- const char *name; /* domain name */
+- int class, type; /* class and type of query */
+- u_char *answer; /* buffer to put answer */
+- int anslen; /* size of answer */
++ const char *name; /* domain name */
++ int class, type; /* class and type of query */
++ u_char *answer; /* buffer to put answer */
++ int anslen; /* size of answer */
+ {
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *)(void *)answer;
+@@ -1256,11 +1244,11 @@ int res_search(name, class, type, answer
+ int done = 0;
+
+ for (domain = (const char * const *)_res.dnsrch;
+- *domain && !done;
+- domain++) {
++ *domain && !done;
++ domain++) {
+
+ ret = res_querydomain(name, *domain, class, type,
+- answer, anslen);
++ answer, anslen);
+ if (ret > 0)
+ return (ret);
+
+@@ -1283,22 +1271,22 @@ int res_search(name, class, type, answer
+ }
+
+ switch (h_errno) {
+- case NO_DATA:
+- got_nodata++;
+- /* FALLTHROUGH */
+- case HOST_NOT_FOUND:
+- /* keep trying */
+- break;
+- case TRY_AGAIN:
+- if (hp->rcode == SERVFAIL) {
+- /* try next search element, if any */
+- got_servfail++;
++ case NO_DATA:
++ got_nodata++;
++ /* FALLTHROUGH */
++ case HOST_NOT_FOUND:
++ /* keep trying */
+ break;
+- }
+- /* FALLTHROUGH */
+- default:
+- /* anything else implies that we're done */
+- done++;
++ case TRY_AGAIN:
++ if (hp->rcode == SERVFAIL) {
++ /* try next search element, if any */
++ got_servfail++;
++ break;
++ }
++ /* FALLTHROUGH */
++ default:
++ /* anything else implies that we're done */
++ done++;
+ }
+ /*
+ * if we got here for some reason other than DNSRCH,
+@@ -1342,10 +1330,10 @@ int res_search(name, class, type, answer
+ * removing a trailing dot from name if domain is NULL.
+ */
+ int res_querydomain(name, domain, class, type, answer, anslen)
+- const char *name, *domain;
+- int class, type; /* class and type of query */
+- u_char *answer; /* buffer to put answer */
+- int anslen; /* size of answer */
++ const char *name, *domain;
++ int class, type; /* class and type of query */
++ u_char *answer; /* buffer to put answer */
++ int anslen; /* size of answer */
+ {
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+@@ -1359,7 +1347,7 @@ int res_querydomain(name, domain, class,
+ #ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_querydomain(%s, %s, %d, %d)\n",
+- name, domain?domain:"<Nil>", class, type);
++ name, domain?domain:"<Nil>", class, type);
+ #endif
+ if (domain == NULL) {
+ /*
+@@ -1400,11 +1388,11 @@ struct hostent *gethostbyaddr (const voi
+ static struct hostent h;
+ static char buf[
+ #ifndef __UCLIBC_HAS_IPV6__
+- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
++ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
+ #else
+- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
++ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
+ struct hostent *hp;
+
+ gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno);
+@@ -1425,11 +1413,11 @@ void __open_etc_hosts(FILE **fp)
+ }
+
+ int __read_etc_hosts_r(FILE * fp, const char * name, int type,
+- enum etc_hosts_action action,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop)
++ enum etc_hosts_action action,
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop)
+ {
+ struct in_addr *in=NULL;
+ struct in_addr **addr_list=NULL;
+@@ -1576,56 +1564,49 @@ int __read_etc_hosts_r(FILE * fp, const
+
+ #ifdef L_gethostent
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ static int __stay_open;
+ static FILE * __gethostent_fp;
+
+ void endhostent (void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ __stay_open = 0;
+ if (__gethostent_fp) {
+- fclose(__gethostent_fp);
++ fclose(__gethostent_fp);
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ void sethostent (int stay_open)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ __stay_open = stay_open;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen,
+- struct hostent **result, int *h_errnop)
++ struct hostent **result, int *h_errnop)
+ {
+- int ret;
++ int ret = 0;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (__gethostent_fp == NULL) {
+- __open_etc_hosts(&__gethostent_fp);
+- if (__gethostent_fp == NULL) {
+- UNLOCK;
+- *result=NULL;
+- return 0;
+- }
++ __open_etc_hosts(&__gethostent_fp);
++ if (__gethostent_fp == NULL) {
++ *result=NULL;
++ goto DONE;
++ }
+ }
+
+ ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT,
+- result_buf, buf, buflen, result, h_errnop);
++ result_buf, buf, buflen, result, h_errnop);
+ if (__stay_open==0) {
+- fclose(__gethostent_fp);
++ fclose(__gethostent_fp);
+ }
+- UNLOCK;
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return(ret);
+ }
+
+@@ -1634,17 +1615,17 @@ struct hostent *gethostent (void)
+ static struct hostent h;
+ static char buf[
+ #ifndef __UCLIBC_HAS_IPV6__
+- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
++ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
+ #else
+- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
++ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- sizeof(char *)*(ALIAS_DIM) +
+- 80/*namebuffer*/ + 2/* margin */];
++ sizeof(char *)*(ALIAS_DIM) +
++ 80/*namebuffer*/ + 2/* margin */];
+ struct hostent *host;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ gethostent_r(&h, buf, sizeof(buf), &host, &h_errno);
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return(host);
+ }
+ #endif
+@@ -1652,23 +1633,23 @@ struct hostent *gethostent (void)
+ #ifdef L_get_hosts_byname_r
+
+ int __get_hosts_byname_r(const char * name, int type,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop)
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop)
+ {
+ return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME,
+- result_buf, buf, buflen, result, h_errnop));
++ result_buf, buf, buflen, result, h_errnop));
+ }
+ #endif
+
+ #ifdef L_get_hosts_byaddr_r
+
+ int __get_hosts_byaddr_r(const char * addr, int len, int type,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop)
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop)
+ {
+ #ifndef __UCLIBC_HAS_IPV6__
+ char ipaddr[INET_ADDRSTRLEN];
+@@ -1677,24 +1658,24 @@ int __get_hosts_byaddr_r(const char * ad
+ #endif /* __UCLIBC_HAS_IPV6__ */
+
+ switch (type) {
+- case AF_INET:
+- if (len != sizeof(struct in_addr))
+- return 0;
+- break;
++ case AF_INET:
++ if (len != sizeof(struct in_addr))
++ return 0;
++ break;
+ #ifdef __UCLIBC_HAS_IPV6__
+- case AF_INET6:
+- if (len != sizeof(struct in6_addr))
+- return 0;
+- break;
++ case AF_INET6:
++ if (len != sizeof(struct in6_addr))
++ return 0;
++ break;
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- default:
+- return 0;
++ default:
++ return 0;
+ }
+
+ inet_ntop(type, addr, ipaddr, sizeof(ipaddr));
+
+ return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR,
+- result_buf, buf, buflen, result, h_errnop));
++ result_buf, buf, buflen, result, h_errnop));
+ }
+ #endif
+
+@@ -1705,8 +1686,8 @@ int __get_hosts_byaddr_r(const char * ad
+ #endif /* min */
+
+ int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
+- socklen_t hostlen, char *serv, socklen_t servlen,
+- unsigned int flags)
++ socklen_t hostlen, char *serv, socklen_t servlen,
++ unsigned int flags)
+ {
+ int serrno = errno;
+ int ok = 0;
+@@ -1720,167 +1701,167 @@ int getnameinfo (const struct sockaddr *
+ return EAI_FAMILY;
+
+ switch (sa->sa_family) {
+- case AF_LOCAL:
+- break;
+- case AF_INET:
+- if (addrlen < sizeof (struct sockaddr_in))
+- return EAI_FAMILY;
+- break;
++ case AF_LOCAL:
++ break;
++ case AF_INET:
++ if (addrlen < sizeof (struct sockaddr_in))
++ return EAI_FAMILY;
++ break;
+ #ifdef __UCLIBC_HAS_IPV6__
+- case AF_INET6:
+- if (addrlen < sizeof (struct sockaddr_in6))
+- return EAI_FAMILY;
+- break;
++ case AF_INET6:
++ if (addrlen < sizeof (struct sockaddr_in6))
++ return EAI_FAMILY;
++ break;
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- default:
+- return EAI_FAMILY;
++ default:
++ return EAI_FAMILY;
+ }
+
+ if (host != NULL && hostlen > 0)
+ switch (sa->sa_family) {
+- case AF_INET:
++ case AF_INET:
+ #ifdef __UCLIBC_HAS_IPV6__
+- case AF_INET6:
++ case AF_INET6:
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- if (!(flags & NI_NUMERICHOST)) {
++ if (!(flags & NI_NUMERICHOST)) {
+ #ifdef __UCLIBC_HAS_IPV6__
+- if (sa->sa_family == AF_INET6)
+- h = gethostbyaddr ((const void *)
+- &(((const struct sockaddr_in6 *) sa)->sin6_addr),
+- sizeof(struct in6_addr), AF_INET6);
+- else
+-#endif /* __UCLIBC_HAS_IPV6__ */
+- h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
+- sizeof(struct in_addr), AF_INET);
+-
+- if (h) {
+- char *c;
+- if ((flags & NI_NOFQDN)
+- && (getdomainname (domain, sizeof(domain)) == 0)
+- && (c = strstr (h->h_name, domain))
+- && (c != h->h_name) && (*(--c) == '.')) {
+- strncpy (host, h->h_name,
+- min(hostlen, (size_t) (c - h->h_name)));
+- host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
+- ok = 1;
+- } else {
+- strncpy (host, h->h_name, hostlen);
+- ok = 1;
++ if (sa->sa_family == AF_INET6)
++ h = gethostbyaddr ((const void *)
++ &(((const struct sockaddr_in6 *) sa)->sin6_addr),
++ sizeof(struct in6_addr), AF_INET6);
++ else
++#endif /* __UCLIBC_HAS_IPV6__ */
++ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
++ sizeof(struct in_addr), AF_INET);
++
++ if (h) {
++ char *c;
++ if ((flags & NI_NOFQDN)
++ && (getdomainname (domain, sizeof(domain)) == 0)
++ && (c = strstr (h->h_name, domain))
++ && (c != h->h_name) && (*(--c) == '.')) {
++ strncpy (host, h->h_name,
++ min(hostlen, (size_t) (c - h->h_name)));
++ host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
++ ok = 1;
++ } else {
++ strncpy (host, h->h_name, hostlen);
++ ok = 1;
++ }
+ }
+- }
+- }
++ }
+
+- if (!ok) {
+- if (flags & NI_NAMEREQD) {
+- errno = serrno;
+- return EAI_NONAME;
+- } else {
+- const char *c;
++ if (!ok) {
++ if (flags & NI_NAMEREQD) {
++ errno = serrno;
++ return EAI_NONAME;
++ } else {
++ const char *c;
+ #ifdef __UCLIBC_HAS_IPV6__
+- if (sa->sa_family == AF_INET6) {
+- const struct sockaddr_in6 *sin6p;
++ if (sa->sa_family == AF_INET6) {
++ const struct sockaddr_in6 *sin6p;
+
+- sin6p = (const struct sockaddr_in6 *) sa;
++ sin6p = (const struct sockaddr_in6 *) sa;
+
+- c = inet_ntop (AF_INET6,
+- (const void *) &sin6p->sin6_addr, host, hostlen);
++ c = inet_ntop (AF_INET6,
++ (const void *) &sin6p->sin6_addr, host, hostlen);
+ #if 0
+- /* Does scope id need to be supported? */
+- uint32_t scopeid;
+- scopeid = sin6p->sin6_scope_id;
+- if (scopeid != 0) {
+- /* Buffer is >= IFNAMSIZ+1. */
+- char scopebuf[IFNAMSIZ + 1];
+- char *scopeptr;
+- int ni_numericscope = 0;
+- size_t real_hostlen = __strnlen (host, hostlen);
+- size_t scopelen = 0;
+-
+- scopebuf[0] = SCOPE_DELIMITER;
+- scopebuf[1] = '\0';
+- scopeptr = &scopebuf[1];
+-
+- if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
+- || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
+- if (if_indextoname (scopeid, scopeptr) == NULL)
++ /* Does scope id need to be supported? */
++ uint32_t scopeid;
++ scopeid = sin6p->sin6_scope_id;
++ if (scopeid != 0) {
++ /* Buffer is >= IFNAMSIZ+1. */
++ char scopebuf[IFNAMSIZ + 1];
++ char *scopeptr;
++ int ni_numericscope = 0;
++ size_t real_hostlen = __strnlen (host, hostlen);
++ size_t scopelen = 0;
++
++ scopebuf[0] = SCOPE_DELIMITER;
++ scopebuf[1] = '\0';
++ scopeptr = &scopebuf[1];
++
++ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
++ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
++ if (if_indextoname (scopeid, scopeptr) == NULL)
++ ++ni_numericscope;
++ else
++ scopelen = strlen (scopebuf);
++ } else {
+ ++ni_numericscope;
+- else
+- scopelen = strlen (scopebuf);
+- } else {
+- ++ni_numericscope;
+- }
++ }
+
+- if (ni_numericscope)
+- scopelen = 1 + snprintf (scopeptr,
+- (scopebuf
+- + sizeof scopebuf
+- - scopeptr),
+- "%u", scopeid);
+-
+- if (real_hostlen + scopelen + 1 > hostlen)
+- return EAI_SYSTEM;
+- memcpy (host + real_hostlen, scopebuf, scopelen + 1);
+- }
++ if (ni_numericscope)
++ scopelen = 1 + snprintf (scopeptr,
++ (scopebuf
++ + sizeof scopebuf
++ - scopeptr),
++ "%u", scopeid);
++
++ if (real_hostlen + scopelen + 1 > hostlen)
++ return EAI_SYSTEM;
++ memcpy (host + real_hostlen, scopebuf, scopelen + 1);
++ }
+ #endif
+- } else
++ } else
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- c = inet_ntop (AF_INET, (const void *)
+- &(((const struct sockaddr_in *) sa)->sin_addr),
+- host, hostlen);
+-
+- if (c == NULL) {
+- errno = serrno;
+- return EAI_SYSTEM;
++ c = inet_ntop (AF_INET, (const void *)
++ &(((const struct sockaddr_in *) sa)->sin_addr),
++ host, hostlen);
++
++ if (c == NULL) {
++ errno = serrno;
++ return EAI_SYSTEM;
++ }
+ }
++ ok = 1;
+ }
+- ok = 1;
+- }
+- break;
+-
+- case AF_LOCAL:
+- if (!(flags & NI_NUMERICHOST)) {
+- struct utsname utsname;
++ break;
+
+- if (!uname (&utsname)) {
+- strncpy (host, utsname.nodename, hostlen);
+- break;
++ case AF_LOCAL:
++ if (!(flags & NI_NUMERICHOST)) {
++ struct utsname utsname;
++
++ if (!uname (&utsname)) {
++ strncpy (host, utsname.nodename, hostlen);
++ break;
++ };
+ };
+- };
+
+- if (flags & NI_NAMEREQD) {
+- errno = serrno;
+- return EAI_NONAME;
+- }
++ if (flags & NI_NAMEREQD) {
++ errno = serrno;
++ return EAI_NONAME;
++ }
+
+- strncpy (host, "localhost", hostlen);
+- break;
++ strncpy (host, "localhost", hostlen);
++ break;
+
+- default:
+- return EAI_FAMILY;
+- }
++ default:
++ return EAI_FAMILY;
++ }
+
+ if (serv && (servlen > 0)) {
+ switch (sa->sa_family) {
+- case AF_INET:
++ case AF_INET:
+ #ifdef __UCLIBC_HAS_IPV6__
+- case AF_INET6:
++ case AF_INET6:
+ #endif /* __UCLIBC_HAS_IPV6__ */
+- if (!(flags & NI_NUMERICSERV)) {
+- struct servent *s;
+- s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
+- ((flags & NI_DGRAM) ? "udp" : "tcp"));
+- if (s) {
+- strncpy (serv, s->s_name, servlen);
+- break;
++ if (!(flags & NI_NUMERICSERV)) {
++ struct servent *s;
++ s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
++ ((flags & NI_DGRAM) ? "udp" : "tcp"));
++ if (s) {
++ strncpy (serv, s->s_name, servlen);
++ break;
++ }
+ }
+- }
+- snprintf (serv, servlen, "%d",
+- ntohs (((const struct sockaddr_in *) sa)->sin_port));
+- break;
++ snprintf (serv, servlen, "%d",
++ ntohs (((const struct sockaddr_in *) sa)->sin_port));
++ break;
+
+- case AF_LOCAL:
+- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
+- break;
++ case AF_LOCAL:
++ strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
++ break;
+ }
+ }
+ if (host && (hostlen > 0))
+@@ -1896,10 +1877,10 @@ int getnameinfo (const struct sockaddr *
+ #ifdef L_gethostbyname_r
+
+ int gethostbyname_r(const char * name,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop)
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop)
+ {
+ struct in_addr *in;
+ struct in_addr **addr_list;
+@@ -1921,7 +1902,7 @@ int gethostbyname_r(const char * name,
+ __set_errno(0); /* to check for missing /etc/hosts. */
+
+ if ((i=__get_hosts_byname_r(name, AF_INET, result_buf,
+- buf, buflen, result, h_errnop))==0)
++ buf, buflen, result, h_errnop))==0)
+ return i;
+ switch (*h_errnop) {
+ case HOST_NOT_FOUND:
+@@ -1983,60 +1964,60 @@ int gethostbyname_r(const char * name,
+
+ for (;;) {
+
+- BIGLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ __nameserversXX=__nameservers;
+ __nameserverXX=__nameserver;
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+ a.buf = buf;
+ a.buflen = buflen;
+ a.add_count = 0;
+ i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a);
+
+ if (i < 0) {
+- *h_errnop = HOST_NOT_FOUND;
+- DPRINTF("__dns_lookup\n");
+- return TRY_AGAIN;
++ *h_errnop = HOST_NOT_FOUND;
++ DPRINTF("__dns_lookup\n");
++ return TRY_AGAIN;
+ }
+
+ if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen)
+- {
+- free(a.dotted);
+- free(packet);
+- *h_errnop = NETDB_INTERNAL;
+- DPRINTF("buffer too small for all addresses\n");
+- return ERANGE;
+- }
++ {
++ free(a.dotted);
++ free(packet);
++ *h_errnop = NETDB_INTERNAL;
++ DPRINTF("buffer too small for all addresses\n");
++ return ERANGE;
++ }
+ else if(a.add_count > 0)
+- {
+- memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength);
+- addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength);
+- addr_list[0] = in;
+- for (i = a.add_count-1; i>=0; --i)
+- addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i);
+- addr_list[a.add_count + 1] = 0;
+- buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf);
+- buf = (char*)&addr_list[a.add_count + 2];
+- }
++ {
++ memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength);
++ addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength);
++ addr_list[0] = in;
++ for (i = a.add_count-1; i>=0; --i)
++ addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i);
++ addr_list[a.add_count + 1] = 0;
++ buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf);
++ buf = (char*)&addr_list[a.add_count + 2];
++ }
+
+ strncpy(buf, a.dotted, buflen);
+ free(a.dotted);
+
+ if (a.atype == T_A) { /* ADDRESS */
+- memcpy(in, a.rdata, sizeof(*in));
+- result_buf->h_name = buf;
+- result_buf->h_addrtype = AF_INET;
+- result_buf->h_length = sizeof(*in);
+- result_buf->h_addr_list = (char **) addr_list;
++ memcpy(in, a.rdata, sizeof(*in));
++ result_buf->h_name = buf;
++ result_buf->h_addrtype = AF_INET;
++ result_buf->h_length = sizeof(*in);
++ result_buf->h_addr_list = (char **) addr_list;
+ #ifdef __UCLIBC_MJN3_ONLY__
+ #warning TODO -- generate the full list
+ #endif
+- result_buf->h_aliases = alias; /* TODO: generate the full list */
+- free(packet);
+- break;
++ result_buf->h_aliases = alias; /* TODO: generate the full list */
++ free(packet);
++ break;
+ } else {
+- free(packet);
+- *h_errnop=HOST_NOT_FOUND;
+- return TRY_AGAIN;
++ free(packet);
++ *h_errnop=HOST_NOT_FOUND;
++ return TRY_AGAIN;
+ }
+ }
+
+@@ -2049,14 +2030,14 @@ int gethostbyname_r(const char * name,
+ #ifdef L_gethostbyname2_r
+
+ int gethostbyname2_r(const char *name, int family,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop)
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop)
+ {
+ #ifndef __UCLIBC_HAS_IPV6__
+ return family == (AF_INET)? gethostbyname_r(name, result_buf,
+- buf, buflen, result, h_errnop) : HOST_NOT_FOUND;
++ buf, buflen, result, h_errnop) : HOST_NOT_FOUND;
+ #else /* __UCLIBC_HAS_IPV6__ */
+ struct in6_addr *in;
+ struct in6_addr **addr_list;
+@@ -2084,7 +2065,7 @@ int gethostbyname2_r(const char *name, i
+ __set_errno(0); /* to check for missing /etc/hosts. */
+
+ if ((i=__get_hosts_byname_r(name, AF_INET, result_buf,
+- buf, buflen, result, h_errnop))==0)
++ buf, buflen, result, h_errnop))==0)
+ return i;
+ switch (*h_errnop) {
+ case HOST_NOT_FOUND:
+@@ -2137,10 +2118,10 @@ int gethostbyname2_r(const char *name, i
+ memset((char *) &a, '\0', sizeof(a));
+
+ for (;;) {
+- BIGLOCK;
+- __nameserversXX=__nameservers;
+- __nameserverXX=__nameserver;
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
++ __nameserversXX=__nameservers;
++ __nameserverXX=__nameserver;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+
+ i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a);
+
+@@ -2190,10 +2171,10 @@ int gethostbyname2_r(const char *name, i
+
+ #ifdef L_gethostbyaddr_r
+ int gethostbyaddr_r (const void *addr, socklen_t len, int type,
+- struct hostent * result_buf,
+- char * buf, size_t buflen,
+- struct hostent ** result,
+- int * h_errnop)
++ struct hostent * result_buf,
++ char * buf, size_t buflen,
++ struct hostent ** result,
++ int * h_errnop)
+
+ {
+ struct in_addr *in;
+@@ -2234,7 +2215,7 @@ int gethostbyaddr_r (const void *addr, s
+
+ /* do /etc/hosts first */
+ if ((i=__get_hosts_byaddr_r(addr, len, type, result_buf,
+- buf, buflen, result, h_errnop))==0)
++ buf, buflen, result, h_errnop))==0)
+ return i;
+ switch (*h_errnop) {
+ case HOST_NOT_FOUND:
+@@ -2294,7 +2275,7 @@ int gethostbyaddr_r (const void *addr, s
+ addr_list[0] = in;
+
+ sprintf(buf, "%u.%u.%u.%u.in-addr.arpa",
+- tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
++ tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
+ #ifdef __UCLIBC_HAS_IPV6__
+ } else {
+ memcpy(in6->s6_addr, addr, len);
+@@ -2304,7 +2285,7 @@ int gethostbyaddr_r (const void *addr, s
+
+ for (i = len - 1; i >= 0; i--) {
+ qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf,
+- (in6->s6_addr[i] >> 4) & 0xf);
++ (in6->s6_addr[i] >> 4) & 0xf);
+ }
+ strcpy(qp, "ip6.int");
+ #endif /* __UCLIBC_HAS_IPV6__ */
+@@ -2314,10 +2295,10 @@ int gethostbyaddr_r (const void *addr, s
+
+ for (;;) {
+
+- BIGLOCK;
+- __nameserversXX=__nameservers;
+- __nameserverXX=__nameserver;
+- BIGUNLOCK;
++ __UCLIBC_MUTEX_LOCK(__resolv_lock);
++ __nameserversXX=__nameservers;
++ __nameserverXX=__nameserver;
++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+ i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a);
+
+ if (i < 0) {
+@@ -2381,7 +2362,7 @@ int gethostbyaddr_r (const void *addr, s
+ * Return size of compressed name or -1 if there was an error.
+ */
+ int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+- char *dst, int dstsiz)
++ char *dst, int dstsiz)
+ {
+ int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
+
+@@ -2401,7 +2382,7 @@ int __dn_expand(const u_char *msg, const
+ */
+ static int printable(int ch)
+ {
+- return (ch > 0x20 && ch < 0x7f);
++ return (ch > 0x20 && ch < 0x7f);
+ }
+
+ /*
+@@ -2413,18 +2394,18 @@ static int printable(int ch)
+ */
+ static int special(int ch)
+ {
+- switch (ch) {
++ switch (ch) {
+ case 0x22: /* '"' */
+ case 0x2E: /* '.' */
+ case 0x3B: /* ';' */
+ case 0x5C: /* '\\' */
+- /* Special modifiers in zone files. */
++ /* Special modifiers in zone files. */
+ case 0x40: /* '@' */
+ case 0x24: /* '$' */
+- return (1);
++ return (1);
+ default:
+- return (0);
+- }
++ return (0);
++ }
+ }
+
+ /*
+@@ -2436,7 +2417,7 @@ static int special(int ch)
+ * Root domain returns as "." not "".
+ */
+ int __ns_name_uncompress(const u_char *msg, const u_char *eom,
+- const u_char *src, char *dst, size_t dstsiz)
++ const u_char *src, char *dst, size_t dstsiz)
+ {
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+@@ -2525,7 +2506,7 @@ int __ns_name_ntop(const u_char *src, ch
+ return (-1);
+ }
+ *dn++ = '\0';
+- return (dn - dst);
++ return (dn - dst);
+ }
+
+ /*
+@@ -2535,7 +2516,7 @@ int __ns_name_ntop(const u_char *src, ch
+ * -1 if it fails, or consumed octets if it succeeds.
+ */
+ int __ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+- u_char *dst, size_t dstsiz)
++ u_char *dst, size_t dstsiz)
+ {
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+@@ -2554,46 +2535,46 @@ int __ns_name_unpack(const u_char *msg,
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+- case 0:
+- /* Limit checks. */
+- if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
+- __set_errno (EMSGSIZE);
+- return (-1);
+- }
+- checked += n + 1;
+- *dstp++ = n;
+- memcpy(dstp, srcp, n);
+- dstp += n;
+- srcp += n;
+- break;
++ case 0:
++ /* Limit checks. */
++ if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
++ __set_errno (EMSGSIZE);
++ return (-1);
++ }
++ checked += n + 1;
++ *dstp++ = n;
++ memcpy(dstp, srcp, n);
++ dstp += n;
++ srcp += n;
++ break;
+
+- case NS_CMPRSFLGS:
+- if (srcp >= eom) {
+- __set_errno (EMSGSIZE);
+- return (-1);
+- }
+- if (len < 0)
+- len = srcp - src + 1;
+- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+- if (srcp < msg || srcp >= eom) { /* Out of range. */
+- __set_errno (EMSGSIZE);
+- return (-1);
+- }
+- checked += 2;
+- /*
+- * Check for loops in the compressed name;
+- * if we've looked at the whole message,
+- * there must be a loop.
+- */
+- if (checked >= eom - msg) {
+- __set_errno (EMSGSIZE);
+- return (-1);
+- }
+- break;
++ case NS_CMPRSFLGS:
++ if (srcp >= eom) {
++ __set_errno (EMSGSIZE);
++ return (-1);
++ }
++ if (len < 0)
++ len = srcp - src + 1;
++ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
++ if (srcp < msg || srcp >= eom) { /* Out of range. */
++ __set_errno (EMSGSIZE);
++ return (-1);
++ }
++ checked += 2;
++ /*
++ * Check for loops in the compressed name;
++ * if we've looked at the whole message,
++ * there must be a loop.
++ */
++ if (checked >= eom - msg) {
++ __set_errno (EMSGSIZE);
++ return (-1);
++ }
++ break;
+
+- default:
+- __set_errno (EMSGSIZE);
+- return (-1); /* flag error */
++ default:
++ __set_errno (EMSGSIZE);
++ return (-1); /* flag error */
+ }
+ }
+ *dstp = '\0';
+diff --git a/libc/inet/rpc/create_xid.c b/libc/inet/rpc/create_xid.c
+index cbb961e..c86cbb4 100644
+--- a/libc/inet/rpc/create_xid.c
++++ b/libc/inet/rpc/create_xid.c
+@@ -27,15 +27,7 @@
+
+ /* The RPC code is not threadsafe, but new code should be threadsafe. */
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t createxid_lock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&createxid_lock)
+-# define UNLOCK __pthread_mutex_unlock(&createxid_lock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ static int is_initialized;
+ static struct drand48_data __rpc_lrand48_data;
+@@ -43,22 +35,22 @@ static struct drand48_data __rpc_lrand48
+ unsigned long
+ _create_xid (void)
+ {
+- unsigned long res;
++ unsigned long res;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+- if (!is_initialized)
+- {
+- struct timeval now;
++ if (!is_initialized)
++ {
++ struct timeval now;
+
+- gettimeofday (&now, (struct timezone *) 0);
+- srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
+- is_initialized = 1;
+- }
++ gettimeofday (&now, (struct timezone *) 0);
++ srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
++ is_initialized = 1;
++ }
+
+- lrand48_r (&__rpc_lrand48_data, &res);
++ lrand48_r (&__rpc_lrand48_data, &res);
+
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+- return res;
++ return res;
+ }
+diff --git a/libc/misc/dirent/closedir.c b/libc/misc/dirent/closedir.c
+index 068e2d3..56adb23 100644
+--- a/libc/misc/dirent/closedir.c
++++ b/libc/misc/dirent/closedir.c
+@@ -4,7 +4,6 @@
+ #include <unistd.h>
+ #include "dirstream.h"
+
+-
+ int closedir(DIR * dir)
+ {
+ int fd;
+@@ -19,14 +18,10 @@ int closedir(DIR * dir)
+ __set_errno(EBADF);
+ return -1;
+ }
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+ fd = dir->dd_fd;
+ dir->dd_fd = -1;
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+ free(dir->dd_buf);
+ free(dir);
+ return close(fd);
+diff --git a/libc/misc/dirent/dirstream.h b/libc/misc/dirent/dirstream.h
+index 2dd0264..bd721c5 100644
+--- a/libc/misc/dirent/dirstream.h
++++ b/libc/misc/dirent/dirstream.h
+@@ -26,9 +26,8 @@ Cambridge, MA 02139, USA. */
+
+ #include <features.h>
+ #include <sys/types.h>
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-#endif
++
++#include <bits/uClibc_mutex.h>
+
+ /* For now, syscall readdir () only supports one entry at a time. It
+ * will be changed in the future.
+@@ -63,11 +62,7 @@ struct __dirstream {
+ size_t dd_max;
+
+ /* lock */
+-#ifdef __UCLIBC_HAS_THREADS__
+- pthread_mutex_t dd_lock;
+-#else
+- void *dd_lock;
+-#endif
++ __UCLIBC_MUTEX(dd_lock);
+ }; /* stream data from opendir() */
+
+
+diff --git a/libc/misc/dirent/readdir.c b/libc/misc/dirent/readdir.c
+index 1f196e1..c55317a 100644
+--- a/libc/misc/dirent/readdir.c
++++ b/libc/misc/dirent/readdir.c
+@@ -5,7 +5,6 @@
+ #include <dirent.h>
+ #include "dirstream.h"
+
+-
+ struct dirent *readdir(DIR * dir)
+ {
+ ssize_t bytes;
+@@ -16,9 +15,7 @@ struct dirent *readdir(DIR * dir)
+ return NULL;
+ }
+
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+ do {
+ if (dir->dd_size <= dir->dd_nextloc) {
+@@ -44,8 +41,6 @@ struct dirent *readdir(DIR * dir)
+ } while (de->d_ino == 0);
+
+ all_done:
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+ return de;
+ }
+diff --git a/libc/misc/dirent/readdir64.c b/libc/misc/dirent/readdir64.c
+index f798c6f..6da3b0d 100644
+--- a/libc/misc/dirent/readdir64.c
++++ b/libc/misc/dirent/readdir64.c
+@@ -20,7 +20,6 @@
+ #include <dirent.h>
+ #include "dirstream.h"
+
+-
+ struct dirent64 *readdir64(DIR * dir)
+ {
+ ssize_t bytes;
+@@ -31,9 +30,7 @@ struct dirent64 *readdir64(DIR * dir)
+ return NULL;
+ }
+
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+ do {
+ if (dir->dd_size <= dir->dd_nextloc) {
+@@ -59,9 +56,7 @@ struct dirent64 *readdir64(DIR * dir)
+ } while (de->d_ino == 0);
+
+ all_done:
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+
+ return de;
+ }
+diff --git a/libc/misc/dirent/readdir64_r.c b/libc/misc/dirent/readdir64_r.c
+index da3564e..cc96eff 100644
+--- a/libc/misc/dirent/readdir64_r.c
++++ b/libc/misc/dirent/readdir64_r.c
+@@ -19,7 +19,6 @@
+ #include <dirent.h>
+ #include "dirstream.h"
+
+-
+ int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result)
+ {
+ int ret;
+@@ -32,21 +31,19 @@ int readdir64_r(DIR *dir, struct dirent6
+ }
+ de = NULL;
+
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+ do {
+ if (dir->dd_size <= dir->dd_nextloc) {
+- /* read dir->dd_max bytes of directory entries. */
+- bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
+- if (bytes <= 0) {
+- *result = NULL;
+- ret = errno;
+- goto all_done;
+- }
+- dir->dd_size = bytes;
+- dir->dd_nextloc = 0;
++ /* read dir->dd_max bytes of directory entries. */
++ bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
++ if (bytes <= 0) {
++ *result = NULL;
++ ret = errno;
++ goto all_done;
++ }
++ dir->dd_size = bytes;
++ dir->dd_nextloc = 0;
+ }
+
+ de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+@@ -66,12 +63,10 @@ int readdir64_r(DIR *dir, struct dirent6
+ }
+ ret = 0;
+
+-all_done:
++ all_done:
+
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
+- return((de != NULL)? 0 : ret);
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
++ return((de != NULL)? 0 : ret);
+ }
+ #endif /* __UCLIBC_HAS_LFS__ */
+
+diff --git a/libc/misc/dirent/readdir_r.c b/libc/misc/dirent/readdir_r.c
+index 245dcbd..aeccdd8 100644
+--- a/libc/misc/dirent/readdir_r.c
++++ b/libc/misc/dirent/readdir_r.c
+@@ -5,7 +5,6 @@
+ #include <dirent.h>
+ #include "dirstream.h"
+
+-
+ int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
+ {
+ int ret;
+@@ -18,21 +17,19 @@ int readdir_r(DIR *dir, struct dirent *e
+ }
+ de = NULL;
+
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+
+ do {
+ if (dir->dd_size <= dir->dd_nextloc) {
+- /* read dir->dd_max bytes of directory entries. */
+- bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
+- if (bytes <= 0) {
+- *result = NULL;
+- ret = errno;
+- goto all_done;
+- }
+- dir->dd_size = bytes;
+- dir->dd_nextloc = 0;
++ /* read dir->dd_max bytes of directory entries. */
++ bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
++ if (bytes <= 0) {
++ *result = NULL;
++ ret = errno;
++ goto all_done;
++ }
++ dir->dd_size = bytes;
++ dir->dd_nextloc = 0;
+ }
+
+ de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+@@ -52,10 +49,8 @@ int readdir_r(DIR *dir, struct dirent *e
+ }
+ ret = 0;
+
+-all_done:
++ all_done:
+
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
+- return((de != NULL)? 0 : ret);
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
++ return((de != NULL)? 0 : ret);
+ }
+diff --git a/libc/misc/dirent/rewinddir.c b/libc/misc/dirent/rewinddir.c
+index 60ef71d..fe8fc2a 100644
+--- a/libc/misc/dirent/rewinddir.c
++++ b/libc/misc/dirent/rewinddir.c
+@@ -3,7 +3,6 @@
+ #include <unistd.h>
+ #include "dirstream.h"
+
+-
+ /* rewinddir() just does an lseek(fd,0,0) - see close for comments */
+ void rewinddir(DIR * dir)
+ {
+@@ -11,12 +10,8 @@ void rewinddir(DIR * dir)
+ __set_errno(EBADF);
+ return;
+ }
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+ lseek(dir->dd_fd, 0, SEEK_SET);
+ dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0;
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+ }
+diff --git a/libc/misc/dirent/seekdir.c b/libc/misc/dirent/seekdir.c
+index 139f1e1..6d6f5f0 100644
+--- a/libc/misc/dirent/seekdir.c
++++ b/libc/misc/dirent/seekdir.c
+@@ -3,19 +3,14 @@
+ #include <unistd.h>
+ #include "dirstream.h"
+
+-
+ void seekdir(DIR * dir, long int offset)
+ {
+ if (!dir) {
+ __set_errno(EBADF);
+ return;
+ }
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_lock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
+ dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET);
+ dir->dd_size = dir->dd_nextloc = 0;
+-#ifdef __UCLIBC_HAS_THREADS__
+- __pthread_mutex_unlock(&(dir->dd_lock));
+-#endif
++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
+ }
+diff --git a/libc/misc/mntent/mntent.c b/libc/misc/mntent/mntent.c
+index d98a687..af6d848 100644
+--- a/libc/misc/mntent/mntent.c
++++ b/libc/misc/mntent/mntent.c
+@@ -3,15 +3,9 @@
+ #include <string.h>
+ #include <mntent.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++#include <bits/uClibc_mutex.h>
++
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ /* Reentrant version of getmntent. */
+ struct mntent *getmntent_r (FILE *filep,
+@@ -67,7 +61,7 @@ struct mntent *getmntent(FILE * filep)
+ struct mntent *tmp;
+ static char *buff = NULL;
+ static struct mntent mnt;
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ if (!buff) {
+ buff = malloc(BUFSIZ);
+@@ -76,7 +70,7 @@ struct mntent *getmntent(FILE * filep)
+ }
+
+ tmp = getmntent_r(filep, &mnt, buff, BUFSIZ);
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return(tmp);
+ }
+
+diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c
+index 89c2611..c27bd10 100644
+--- a/libc/misc/pthread/weaks.c
++++ b/libc/misc/pthread/weaks.c
+@@ -21,6 +21,7 @@
+ #include <limits.h>
+ #include <stdlib.h>
+
++static void __pthread_return_void __P ((void));
+ static int __pthread_return_0 __P ((void));
+ static int __pthread_return_1 __P ((void));
+
+@@ -104,8 +105,17 @@ weak_alias (__pthread_return_0, __pthrea
+ weak_alias (__pthread_return_0, __pthread_mutex_trylock)
+ weak_alias (__pthread_return_0, __pthread_mutex_unlock)
+
++weak_alias (__pthread_return_void, _pthread_cleanup_push_defer)
++weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore)
++
+ /**********************************************************************/
+
++static void
++__pthread_return_void (void)
++{
++ return;
++}
++
+ static int
+ __pthread_return_0 (void)
+ {
+diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c
+index 2b478e1..9e9ddbf 100644
+--- a/libc/misc/syslog/syslog.c
++++ b/libc/misc/syslog/syslog.c
+@@ -80,17 +80,9 @@
+ #include <ctype.h>
+ #include <signal.h>
+
++#include <bits/uClibc_mutex.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
+-
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ static int LogFile = -1; /* fd for log */
+ static int connected; /* have done connect */
+@@ -110,26 +102,26 @@ int setlogmask(int pmask);
+ static void
+ closelog_intern(int to_default)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (LogFile != -1) {
+ (void) close(LogFile);
+ }
+ LogFile = -1;
+ connected = 0;
+ if (to_default)
+- {
+- LogStat = 0;
+- LogTag = "syslog";
+- LogFacility = LOG_USER;
+- LogMask = 0xff;
+- }
+- UNLOCK;
++ {
++ LogStat = 0;
++ LogTag = "syslog";
++ LogFacility = LOG_USER;
++ LogMask = 0xff;
++ }
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ static void
+ sigpipe_handler (int sig)
+ {
+- closelog_intern (0);
++ closelog_intern (0);
+ }
+
+ /*
+@@ -165,7 +157,7 @@ vsyslog( int pri, const char *fmt, va_li
+
+ saved_errno = errno;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ /* See if we should just throw out this message. */
+ if (!(LogMask & LOG_MASK(LOG_PRI(pri))) || (pri &~ (LOG_PRIMASK|LOG_FACMASK)))
+@@ -208,7 +200,7 @@ vsyslog( int pri, const char *fmt, va_li
+ if (p >= end || p < head_end) { /* Returned -1 in case of error... */
+ static const char truncate_msg[12] = "[truncated] ";
+ memmove(head_end + sizeof(truncate_msg), head_end,
+- end - head_end - sizeof(truncate_msg));
++ end - head_end - sizeof(truncate_msg));
+ memcpy(head_end, truncate_msg, sizeof(truncate_msg));
+ if (p < head_end) {
+ while (p < end && *p) {
+@@ -261,11 +253,11 @@ vsyslog( int pri, const char *fmt, va_li
+ (void)close(fd);
+ }
+
+-getout:
+- UNLOCK;
++ getout:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ if (sigpipe == 0)
+ sigaction (SIGPIPE, &oldaction,
+- (struct sigaction *) NULL);
++ (struct sigaction *) NULL);
+ }
+
+ /*
+@@ -276,48 +268,48 @@ openlog( const char *ident, int logstat,
+ {
+ int logType = SOCK_DGRAM;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ if (ident != NULL)
+- LogTag = ident;
++ LogTag = ident;
+ LogStat = logstat;
+ if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+- LogFacility = logfac;
++ LogFacility = logfac;
+ if (LogFile == -1) {
+- SyslogAddr.sa_family = AF_UNIX;
+- (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
+- sizeof(SyslogAddr.sa_data));
+-retry:
+- if (LogStat & LOG_NDELAY) {
+- if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){
+- UNLOCK;
+- return;
+- }
+- /* fcntl(LogFile, F_SETFD, 1); */
+- }
++ SyslogAddr.sa_family = AF_UNIX;
++ (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
++ sizeof(SyslogAddr.sa_data));
++ retry:
++ if (LogStat & LOG_NDELAY) {
++ if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){
++ goto DONE;
++ }
++ /* fcntl(LogFile, F_SETFD, 1); */
++ }
+ }
+
+ if (LogFile != -1 && !connected) {
+- if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) -
+- sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1)
+- {
+- connected = 1;
+- } else if (logType == SOCK_DGRAM) {
+- logType = SOCK_STREAM;
+- if (LogFile != -1) {
+- close(LogFile);
+- LogFile = -1;
+- }
+- goto retry;
+- } else {
+- if (LogFile != -1) {
+- close(LogFile);
+- LogFile = -1;
+- }
+- }
++ if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) -
++ sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1)
++ {
++ connected = 1;
++ } else if (logType == SOCK_DGRAM) {
++ logType = SOCK_STREAM;
++ if (LogFile != -1) {
++ close(LogFile);
++ LogFile = -1;
++ }
++ goto retry;
++ } else {
++ if (LogFile != -1) {
++ close(LogFile);
++ LogFile = -1;
++ }
++ }
+ }
+
+- UNLOCK;
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ /*
+@@ -335,10 +327,10 @@ int setlogmask(int pmask)
+ int omask;
+
+ omask = LogMask;
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (pmask != 0)
+- LogMask = pmask;
+- UNLOCK;
++ LogMask = pmask;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return (omask);
+ }
+
+diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
+index f43bb8a..6165a52 100644
+--- a/libc/misc/time/time.c
++++ b/libc/misc/time/time.c
+@@ -143,6 +143,8 @@
+ #include <locale.h>
+ #include <bits/uClibc_uintmaxtostr.h>
+
++#include <bits/uClibc_mutex.h>
++
+ #ifdef __UCLIBC_HAS_XLOCALE__
+ #include <xlocale.h>
+ #endif
+@@ -191,21 +193,7 @@ typedef struct {
+ char tzname[TZNAME_MAX+1];
+ } rule_struct;
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-
+-#include <pthread.h>
+-
+-extern pthread_mutex_t _time_tzlock;
+-
+-#define TZLOCK __pthread_mutex_lock(&_time_tzlock)
+-#define TZUNLOCK __pthread_mutex_unlock(&_time_tzlock)
+-
+-#else
+-
+-#define TZLOCK ((void) 0)
+-#define TZUNLOCK ((void) 0)
+-
+-#endif
++__UCLIBC_MUTEX_EXTERN(_time_tzlock);
+
+ extern rule_struct _time_tzinfo[2];
+
+@@ -542,13 +530,13 @@ struct tm *localtime(const time_t *timer
+ struct tm *localtime_r(register const time_t *__restrict timer,
+ register struct tm *__restrict result)
+ {
+- TZLOCK;
++ __UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+ tzset();
+
+ __time_localtime_tzi(timer, result, _time_tzinfo);
+
+- TZUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+
+ return result;
+ }
+@@ -1037,7 +1025,7 @@ size_t __XL(strftime)(char *__restrict s
+ goto LOOP;
+ }
+
+- o = spec + 26; /* set to "????" */
++ o = ((const char *) spec) + 26; /* set to "????" */
+ if ((code & MASK_SPEC) == CALC_SPEC) {
+
+ if (*p == 's') {
+@@ -1073,17 +1061,15 @@ size_t __XL(strftime)(char *__restrict s
+
+ #ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+
+-#define RSP_TZUNLOCK ((void) 0)
+ #define RSP_TZNAME timeptr->tm_zone
+ #define RSP_GMT_OFFSET (-timeptr->tm_gmtoff)
+
+ #else
+
+-#define RSP_TZUNLOCK TZUNLOCK
+ #define RSP_TZNAME rsp->tzname
+ #define RSP_GMT_OFFSET rsp->gmt_offset
+
+- TZLOCK;
++ __UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+ rsp = _time_tzinfo;
+ if (timeptr->tm_isdst > 0) {
+@@ -1114,15 +1100,17 @@ size_t __XL(strftime)(char *__restrict s
+ }
+ #endif
+ o_count = SIZE_MAX;
+- RSP_TZUNLOCK;
++/* RSP_TZUNLOCK; */
++#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
+ goto OUTPUT;
++#endif
+ } else { /* z */
+ *s = '+';
+ if ((tzo = -RSP_GMT_OFFSET) < 0) {
+ tzo = -tzo;
+ *s = '-';
+ }
+- RSP_TZUNLOCK;
++/* RSP_TZUNLOCK; */
+ ++s;
+ --count;
+
+@@ -1131,7 +1119,13 @@ size_t __XL(strftime)(char *__restrict s
+
+ i = 16 + 6; /* 0-fill, width = 4 */
+ }
+-
++#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
++#else
++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
++ if (*p == 'Z') {
++ goto OUTPUT;
++ }
++#endif
+ } else {
+ /* TODO: don't need year for U, W */
+ for (i=0 ; i < 3 ; i++) {
+@@ -1664,9 +1658,7 @@ int daylight = 0;
+ long timezone = 0;
+ char *tzname[2] = { (char *) UTC, (char *) (UTC-1) };
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-pthread_mutex_t _time_tzlock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-#endif
++__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ rule_struct _time_tzinfo[2];
+
+@@ -1796,7 +1788,7 @@ void tzset(void)
+ static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */
+ #endif /* __UCLIBC_HAS_TZ_CACHING__ */
+
+- TZLOCK;
++ __UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+ e = getenv(TZ); /* TZ env var always takes precedence. */
+
+@@ -1962,10 +1954,10 @@ void tzset(void)
+ daylight = !!_time_tzinfo[1].tzname[0];
+ timezone = _time_tzinfo[0].gmt_offset;
+
+-#if defined(__UCLIBC_HAS_TZ_FILE__)
++#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__)
+ FAST_DONE:
+ #endif
+- TZUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+ }
+
+ #endif
+@@ -2167,13 +2159,13 @@ time_t _time_mktime(struct tm *timeptr,
+ {
+ time_t t;
+
+- TZLOCK;
++ __UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+ tzset();
+
+ t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo);
+
+- TZUNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
+
+ return t;
+ }
+diff --git a/libc/misc/ttyent/getttyent.c b/libc/misc/ttyent/getttyent.c
+index 6e2fbd2..c85c73a 100644
+--- a/libc/misc/ttyent/getttyent.c
++++ b/libc/misc/ttyent/getttyent.c
+@@ -35,9 +35,6 @@
+ #include <ctype.h>
+ #include <string.h>
+ #include <stdlib.h>
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-#endif
+
+ static char zapchar;
+ static FILE *tf;
+@@ -50,8 +47,8 @@ struct ttyent * getttynam(const char *tt
+
+ setttyent();
+ while ((t = getttyent()))
+- if (!strcmp(tty, t->ty_name))
+- break;
++ if (!strcmp(tty, t->ty_name))
++ break;
+ endttyent();
+ return (t);
+ }
+@@ -67,27 +64,27 @@ static char * skip(register char *p)
+ register int c, q;
+
+ for (q = 0, t = p; (c = *p) != '\0'; p++) {
+- if (c == '"') {
+- q ^= QUOTED; /* obscure, but nice */
+- continue;
+- }
+- if (q == QUOTED && *p == '\\' && *(p+1) == '"')
+- p++;
+- *t++ = *p;
+- if (q == QUOTED)
+- continue;
+- if (c == '#') {
+- zapchar = c;
+- *p = 0;
+- break;
+- }
+- if (c == '\t' || c == ' ' || c == '\n') {
+- zapchar = c;
+- *p++ = 0;
+- while ((c = *p) == '\t' || c == ' ' || c == '\n')
+- p++;
+- break;
+- }
++ if (c == '"') {
++ q ^= QUOTED; /* obscure, but nice */
++ continue;
++ }
++ if (q == QUOTED && *p == '\\' && *(p+1) == '"')
++ p++;
++ *t++ = *p;
++ if (q == QUOTED)
++ continue;
++ if (c == '#') {
++ zapchar = c;
++ *p = 0;
++ break;
++ }
++ if (c == '\t' || c == ' ' || c == '\n') {
++ zapchar = c;
++ *p++ = 0;
++ while ((c = *p) == '\t' || c == ' ' || c == '\n')
++ p++;
++ break;
++ }
+ }
+ *--t = '\0';
+ return (p);
+@@ -104,46 +101,46 @@ struct ttyent * getttyent(void)
+ register int c;
+ register char *p;
+ static char *line = NULL;
++ struct ttyent *retval = NULL;
+
+ if (!tf && !setttyent())
+- return (NULL);
++ return (NULL);
+
+ if (!line) {
+- line = malloc(BUFSIZ);
++ line = malloc(BUFSIZ);
+ if (!line)
+ abort();
+ }
+
+- __STDIO_ALWAYS_THREADLOCK(tf);
++ __STDIO_ALWAYS_THREADLOCK(tf);
+
+ for (;;) {
+- if (!fgets_unlocked(p = line, BUFSIZ, tf)) {
+- __STDIO_ALWAYS_THREADUNLOCK(tf);
+- return (NULL);
+- }
+- /* skip lines that are too big */
+- if (!index(p, '\n')) {
+- while ((c = getc_unlocked(tf)) != '\n' && c != EOF)
+- ;
+- continue;
+- }
+- while (isspace(*p))
+- ++p;
+- if (*p && *p != '#')
+- break;
++ if (!fgets_unlocked(p = line, BUFSIZ, tf)) {
++ goto DONE;
++ }
++ /* skip lines that are too big */
++ if (!index(p, '\n')) {
++ while ((c = getc_unlocked(tf)) != '\n' && c != EOF)
++ ;
++ continue;
++ }
++ while (isspace(*p))
++ ++p;
++ if (*p && *p != '#')
++ break;
+ }
+
+ zapchar = 0;
+ tty.ty_name = p;
+ p = skip(p);
+ if (!*(tty.ty_getty = p))
+- tty.ty_getty = tty.ty_type = NULL;
++ tty.ty_getty = tty.ty_type = NULL;
+ else {
+- p = skip(p);
+- if (!*(tty.ty_type = p))
+- tty.ty_type = NULL;
+- else
+- p = skip(p);
++ p = skip(p);
++ if (!*(tty.ty_type = p))
++ tty.ty_type = NULL;
++ else
++ p = skip(p);
+ }
+ tty.ty_status = 0;
+ tty.ty_window = NULL;
+@@ -151,43 +148,45 @@ struct ttyent * getttyent(void)
+ #define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1])
+ #define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
+ for (; *p; p = skip(p)) {
+- if (scmp(_TTYS_OFF))
+- tty.ty_status &= ~TTY_ON;
+- else if (scmp(_TTYS_ON))
+- tty.ty_status |= TTY_ON;
+- else if (scmp(_TTYS_SECURE))
+- tty.ty_status |= TTY_SECURE;
+- else if (vcmp(_TTYS_WINDOW))
+- tty.ty_window = value(p);
+- else
+- break;
++ if (scmp(_TTYS_OFF))
++ tty.ty_status &= ~TTY_ON;
++ else if (scmp(_TTYS_ON))
++ tty.ty_status |= TTY_ON;
++ else if (scmp(_TTYS_SECURE))
++ tty.ty_status |= TTY_SECURE;
++ else if (vcmp(_TTYS_WINDOW))
++ tty.ty_window = value(p);
++ else
++ break;
+ }
+- /* We can release the lock only here since `zapchar' is global. */
+- __STDIO_ALWAYS_THREADUNLOCK(tf);
+
+ if (zapchar == '#' || *p == '#')
+- while ((c = *++p) == ' ' || c == '\t')
+- ;
++ while ((c = *++p) == ' ' || c == '\t')
++ ;
+ tty.ty_comment = p;
+ if (*p == 0)
+- tty.ty_comment = 0;
++ tty.ty_comment = 0;
+ if ((p = index(p, '\n')))
+- *p = '\0';
+- return (&tty);
++ *p = '\0';
++ retval = &tty;
++
++ DONE:
++ __STDIO_ALWAYS_THREADUNLOCK(tf);
++ return retval;
+ }
+
+ int setttyent(void)
+ {
+
+ if (tf) {
+- rewind(tf);
+- return (1);
++ rewind(tf);
++ return (1);
+ } else if ((tf = fopen(_PATH_TTYS, "r"))) {
+- /* We do the locking ourselves. */
++ /* We do the locking ourselves. */
+ #ifdef __UCLIBC_HAS_THREADS__
+- __fsetlocking (tf, FSETLOCKING_BYCALLER);
++ __fsetlocking (tf, FSETLOCKING_BYCALLER);
+ #endif
+- return (1);
++ return (1);
+ }
+ return (0);
+ }
+@@ -197,9 +196,9 @@ int endttyent(void)
+ int rval;
+
+ if (tf) {
+- rval = !(fclose(tf) == EOF);
+- tf = NULL;
+- return (rval);
++ rval = !(fclose(tf) == EOF);
++ tf = NULL;
++ return (rval);
+ }
+ return (1);
+ }
+diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c
+index c1d8d6f..0fc6df4 100644
+--- a/libc/misc/utmp/utent.c
++++ b/libc/misc/utmp/utent.c
+@@ -20,19 +20,9 @@
+ #include <string.h>
+ #include <utmp.h>
+
++#include <bits/uClibc_mutex.h>
+
+-
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t utmplock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&utmplock)
+-# define UNLOCK __pthread_mutex_unlock(&utmplock)
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
+-
+-
++__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER);
+
+ /* Some global crap */
+ static int static_fd = -1;
+@@ -46,19 +36,19 @@ static struct utmp *__getutent(int utmp_
+
+ {
+ if (utmp_fd == -1) {
+- setutent();
++ setutent();
+ }
+ if (utmp_fd == -1) {
+- return NULL;
++ return NULL;
+ }
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(utmplock);
+ if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) != sizeof(struct utmp))
+- {
+- return NULL;
+- }
++ {
++ return NULL;
++ }
+
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(utmplock);
+ return &static_utmp;
+ }
+
+@@ -66,39 +56,39 @@ void setutent(void)
+ {
+ int ret;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(utmplock);
+ if (static_fd == -1) {
+- if ((static_fd = open(static_ut_name, O_RDWR)) < 0) {
+- if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) {
+- goto bummer;
+- }
+- }
+- /* Make sure the file will be closed on exec() */
+- ret = fcntl(static_fd, F_GETFD, 0);
+- if (ret >= 0) {
+- ret = fcntl(static_fd, F_GETFD, 0);
+- }
+- if (ret < 0) {
+-bummer:
+- UNLOCK;
+- static_fd = -1;
+- close(static_fd);
+- return;
+- }
++ if ((static_fd = open(static_ut_name, O_RDWR)) < 0) {
++ if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) {
++ goto bummer;
++ }
++ }
++ /* Make sure the file will be closed on exec() */
++ ret = fcntl(static_fd, F_GETFD, 0);
++ if (ret >= 0) {
++ ret = fcntl(static_fd, F_GETFD, 0);
++ }
++ if (ret < 0) {
++ bummer:
++ close(static_fd);
++ static_fd = -1;
++ goto DONE;
++ }
+ }
+ lseek(static_fd, 0, SEEK_SET);
+- UNLOCK;
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(utmplock);
+ return;
+ }
+
+ void endutent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(utmplock);
+ if (static_fd != -1) {
+- close(static_fd);
++ close(static_fd);
+ }
+ static_fd = -1;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(utmplock);
+ }
+
+ /* Locking is done in __getutent */
+@@ -113,22 +103,22 @@ struct utmp *getutid (const struct utmp
+ struct utmp *lutmp;
+
+ while ((lutmp = __getutent(static_fd)) != NULL) {
+- if ( (utmp_entry->ut_type == RUN_LVL ||
+- utmp_entry->ut_type == BOOT_TIME ||
+- utmp_entry->ut_type == NEW_TIME ||
+- utmp_entry->ut_type == OLD_TIME) &&
+- lutmp->ut_type == utmp_entry->ut_type)
+- {
+- return lutmp;
+- }
+- if ( (utmp_entry->ut_type == INIT_PROCESS ||
+- utmp_entry->ut_type == DEAD_PROCESS ||
+- utmp_entry->ut_type == LOGIN_PROCESS ||
+- utmp_entry->ut_type == USER_PROCESS) &&
+- !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)))
+- {
+- return lutmp;
+- }
++ if ( (utmp_entry->ut_type == RUN_LVL ||
++ utmp_entry->ut_type == BOOT_TIME ||
++ utmp_entry->ut_type == NEW_TIME ||
++ utmp_entry->ut_type == OLD_TIME) &&
++ lutmp->ut_type == utmp_entry->ut_type)
++ {
++ return lutmp;
++ }
++ if ( (utmp_entry->ut_type == INIT_PROCESS ||
++ utmp_entry->ut_type == DEAD_PROCESS ||
++ utmp_entry->ut_type == LOGIN_PROCESS ||
++ utmp_entry->ut_type == USER_PROCESS) &&
++ !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)))
++ {
++ return lutmp;
++ }
+ }
+
+ return NULL;
+@@ -140,11 +130,11 @@ struct utmp *getutline(const struct utmp
+ struct utmp *lutmp;
+
+ while ((lutmp = __getutent(static_fd)) != NULL) {
+- if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) &&
+- !strcmp(lutmp->ut_line, utmp_entry->ut_line))
+- {
+- return lutmp;
+- }
++ if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) &&
++ !strcmp(lutmp->ut_line, utmp_entry->ut_line))
++ {
++ return lutmp;
++ }
+ }
+
+ return NULL;
+@@ -152,42 +142,42 @@ struct utmp *getutline(const struct utmp
+
+ struct utmp *pututline (const struct utmp *utmp_entry)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(utmplock);
+ /* Ignore the return value. That way, if they've already positioned
+ the file pointer where they want it, everything will work out. */
+ lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
+
+ if (getutid(utmp_entry) != NULL) {
+- lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
+- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
+- return NULL;
++ lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
++ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
++ return NULL;
+ } else {
+- lseek(static_fd, (off_t) 0, SEEK_END);
+- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
+- return NULL;
++ lseek(static_fd, (off_t) 0, SEEK_END);
++ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
++ return NULL;
+ }
+
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(utmplock);
+ return (struct utmp *)utmp_entry;
+ }
+
+ int utmpname (const char *new_ut_name)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(utmplock);
+ if (new_ut_name != NULL) {
+- if (static_ut_name != default_file_name)
+- free((char *)static_ut_name);
+- static_ut_name = strdup(new_ut_name);
+- if (static_ut_name == NULL) {
+- /* We should probably whine about out-of-memory
+- * errors here... Instead just reset to the default */
+- static_ut_name = default_file_name;
+- }
++ if (static_ut_name != default_file_name)
++ free((char *)static_ut_name);
++ static_ut_name = strdup(new_ut_name);
++ if (static_ut_name == NULL) {
++ /* We should probably whine about out-of-memory
++ * errors here... Instead just reset to the default */
++ static_ut_name = default_file_name;
++ }
+ }
+
+ if (static_fd != -1)
+- close(static_fd);
+- UNLOCK;
++ close(static_fd);
++ __UCLIBC_MUTEX_UNLOCK(utmplock);
+ return 0;
+ }
+
+diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c
+index b49494f..408c57a 100644
+--- a/libc/misc/wchar/wstdio.c
++++ b/libc/misc/wchar/wstdio.c
+@@ -82,9 +82,6 @@ strong_alias(NAME,NAME##_unlocked) \
+ void NAME PARAMS
+ #endif
+
+-#define __STDIO_THREADLOCK_OPENLIST
+-#define __STDIO_THREADUNLOCK_OPENLIST
+-
+ #else /* __UCLIBC_HAS_THREADS__ */
+
+ #include <pthread.h>
+@@ -112,15 +109,6 @@ void NAME PARAMS \
+ } \
+ void NAME##_unlocked PARAMS
+
+-#define __STDIO_THREADLOCK_OPENLIST \
+- __pthread_mutex_lock(&_stdio_openlist_lock)
+-
+-#define __STDIO_THREADUNLOCK_OPENLIST \
+- __pthread_mutex_unlock(&_stdio_openlist_lock)
+-
+-#define __STDIO_THREADTRYLOCK_OPENLIST \
+- __pthread_mutex_trylock(&_stdio_openlist_lock)
+-
+ #endif /* __UCLIBC_HAS_THREADS__ */
+
+ #ifndef __STDIO_BUFFERS
+diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c
+index 6b9c251..063fed4 100644
+--- a/libc/pwd_grp/lckpwdf.c
++++ b/libc/pwd_grp/lckpwdf.c
+@@ -27,15 +27,9 @@
+ #include <sys/file.h>
+ #include <paths.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++#include <bits/uClibc_mutex.h>
++
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ /* How long to wait for getting the lock before returning with an
+ error. */
+@@ -57,18 +51,18 @@ int lckpwdf (void)
+ struct sigaction new_act; /* New signal action. */
+ struct flock fl; /* Information struct for locking. */
+ int result;
++ int rv = -1;
+
+ if (lock_fd != -1)
+ /* Still locked by own process. */
+ return -1;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ lock_fd = open (_PATH_PASSWD, O_WRONLY);
+ if (lock_fd == -1) {
+ /* Cannot create lock file. */
+- UNLOCK;
+- return -1;
++ goto DONE;
+ }
+
+ /* Make sure file gets correctly closed when process finished. */
+@@ -77,16 +71,14 @@ int lckpwdf (void)
+ /* Cannot get file flags. */
+ close(lock_fd);
+ lock_fd = -1;
+- UNLOCK;
+- return -1;
++ goto DONE;
+ }
+ flags |= FD_CLOEXEC; /* Close on exit. */
+ if (fcntl (lock_fd, F_SETFD, flags) < 0) {
+ /* Cannot set new flags. */
+ close(lock_fd);
+ lock_fd = -1;
+- UNLOCK;
+- return -1;
++ goto DONE;
+ }
+
+ /* Now we have to get exclusive write access. Since multiple
+@@ -107,8 +99,7 @@ int lckpwdf (void)
+ /* Cannot install signal handler. */
+ close(lock_fd);
+ lock_fd = -1;
+- UNLOCK;
+- return -1;
++ goto DONE;
+ }
+
+ /* Now make sure the alarm signal is not blocked. */
+@@ -118,8 +109,7 @@ int lckpwdf (void)
+ sigaction (SIGALRM, &saved_act, NULL);
+ close(lock_fd);
+ lock_fd = -1;
+- UNLOCK;
+- return -1;
++ goto DONE;
+ }
+
+ /* Start timer. If we cannot get the lock in the specified time we
+@@ -146,12 +136,14 @@ int lckpwdf (void)
+ if (result < 0) {
+ close(lock_fd);
+ lock_fd = -1;
+- UNLOCK;
+- return -1;
++ goto DONE;
+ }
+
+- UNLOCK;
+- return 0;
++ rv = 0;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
++ return rv;
+ }
+
+
+@@ -164,11 +156,11 @@ int ulckpwdf (void)
+ result = -1;
+ }
+ else {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ result = close (lock_fd);
+ /* Mark descriptor as unused. */
+ lock_fd = -1;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ return result;
+diff --git a/libc/pwd_grp/pwd_grp.c b/libc/pwd_grp/pwd_grp.c
+index 91c0d83..a302c7c 100644
+--- a/libc/pwd_grp/pwd_grp.c
++++ b/libc/pwd_grp/pwd_grp.c
+@@ -42,9 +42,8 @@
+ #include <pwd.h>
+ #include <grp.h>
+ #include <shadow.h>
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-#endif
++
++#include <bits/uClibc_mutex.h>
+
+ /**********************************************************************/
+ /* Sizes for staticly allocated buffers. */
+@@ -445,34 +444,27 @@ int getpw(uid_t uid, char *buf)
+ /**********************************************************************/
+ #ifdef L_getpwent_r
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK ((void) 0)
+-# define UNLOCK ((void) 0)
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ static FILE *pwf /*= NULL*/;
+
+ void setpwent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (pwf) {
+ rewind(pwf);
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ void endpwent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (pwf) {
+ fclose(pwf);
+ pwf = NULL;
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+
+@@ -482,7 +474,7 @@ int getpwent_r(struct passwd *__restrict
+ {
+ int rv;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ *result = NULL; /* In case of error... */
+
+@@ -500,7 +492,7 @@ int getpwent_r(struct passwd *__restrict
+ }
+
+ ERR:
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ return rv;
+ }
+@@ -509,34 +501,27 @@ int getpwent_r(struct passwd *__restrict
+ /**********************************************************************/
+ #ifdef L_getgrent_r
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK ((void) 0)
+-# define UNLOCK ((void) 0)
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ static FILE *grf /*= NULL*/;
+
+ void setgrent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (grf) {
+ rewind(grf);
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ void endgrent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (grf) {
+ fclose(grf);
+ grf = NULL;
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ int getgrent_r(struct group *__restrict resultbuf,
+@@ -545,7 +530,7 @@ int getgrent_r(struct group *__restrict
+ {
+ int rv;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ *result = NULL; /* In case of error... */
+
+@@ -563,7 +548,7 @@ int getgrent_r(struct group *__restrict
+ }
+
+ ERR:
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ return rv;
+ }
+@@ -572,34 +557,27 @@ int getgrent_r(struct group *__restrict
+ /**********************************************************************/
+ #ifdef L_getspent_r
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK ((void) 0)
+-# define UNLOCK ((void) 0)
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ static FILE *spf /*= NULL*/;
+
+ void setspent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (spf) {
+ rewind(spf);
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ void endspent(void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (spf) {
+ fclose(spf);
+ spf = NULL;
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+
+ int getspent_r(struct spwd *resultbuf, char *buffer,
+@@ -607,7 +585,7 @@ int getspent_r(struct spwd *resultbuf, c
+ {
+ int rv;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ *result = NULL; /* In case of error... */
+
+@@ -625,7 +603,7 @@ int getspent_r(struct spwd *resultbuf, c
+ }
+
+ ERR:
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ return rv;
+ }
+diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c
+index 7d3c38c..fe1bc91 100644
+--- a/libc/stdio/_READ.c
++++ b/libc/stdio/_READ.c
+@@ -41,7 +41,7 @@ size_t __stdio_READ(register FILE *strea
+ #warning EINTR?
+ #endif
+ /* RETRY: */
+- if ((rv = __READ(stream, buf, bufsize)) <= 0) {
++ if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) {
+ if (rv == 0) {
+ __STDIO_STREAM_SET_EOF(stream);
+ } else {
+diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c
+index d300d39..4131eb7 100644
+--- a/libc/stdio/_WRITE.c
++++ b/libc/stdio/_WRITE.c
+@@ -47,7 +47,7 @@ size_t __stdio_WRITE(register FILE *stre
+ return bufsize;
+ }
+ stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
+- if ((rv = __WRITE(stream, buf, stodo)) >= 0) {
++ if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) {
+ #ifdef __UCLIBC_MJN3_ONLY__
+ #warning TODO: Make custom stream write return check optional.
+ #endif
+diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c
+index f7f5bb6..4984f11 100644
+--- a/libc/stdio/_fopen.c
++++ b/libc/stdio/_fopen.c
+@@ -194,10 +194,23 @@ FILE *_stdio_fopen(intptr_t fname_or_mod
+ #endif
+
+ #ifdef __STDIO_HAS_OPENLIST
+- __STDIO_THREADLOCK_OPENLIST;
+- stream->__nextopen = _stdio_openlist; /* New files are inserted at */
+- _stdio_openlist = stream; /* the head of the list. */
+- __STDIO_THREADUNLOCK_OPENLIST;
++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
++ if (!(stream->__modeflags & __FLAG_FREEFILE))
++ {
++ /* An freopen call so the file was never removed from the list. */
++ }
++ else
++#endif
++ {
++ /* We have to lock the del mutex in case another thread wants to fclose()
++ * the last file. */
++ __STDIO_THREADLOCK_OPENLIST_DEL;
++ __STDIO_THREADLOCK_OPENLIST_ADD;
++ stream->__nextopen = _stdio_openlist; /* New files are inserted at */
++ _stdio_openlist = stream; /* the head of the list. */
++ __STDIO_THREADUNLOCK_OPENLIST_ADD;
++ __STDIO_THREADUNLOCK_OPENLIST_DEL;
++ }
+ #endif
+
+ __STDIO_STREAM_VALIDATE(stream);
+diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c
+index 4aae3c4..9cfe02c 100644
+--- a/libc/stdio/_stdio.c
++++ b/libc/stdio/_stdio.c
+@@ -151,8 +151,12 @@ FILE *__stdout = _stdio_streams + 1; /*
+ FILE *_stdio_openlist = _stdio_streams;
+
+ # ifdef __UCLIBC_HAS_THREADS__
+-pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-int _stdio_openlist_delflag = 0;
++__UCLIBC_MUTEX_INIT(_stdio_openlist_add_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
++#ifdef __STDIO_BUFFERS
++__UCLIBC_MUTEX_INIT(_stdio_openlist_del_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
++volatile int _stdio_openlist_use_count = 0;
++int _stdio_openlist_del_count = 0;
++#endif
+ # endif
+
+ #endif
+@@ -162,10 +166,10 @@ int _stdio_openlist_delflag = 0;
+ /* 2 if threading not initialized and 0 otherwise; */
+ int _stdio_user_locking = 2;
+
+-void __stdio_init_mutex(pthread_mutex_t *m)
++void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m)
+ {
+- static const pthread_mutex_t __stdio_mutex_initializer
+- = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
++ const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer));
+ }
+@@ -184,7 +188,11 @@ void _stdio_term(void)
+ * locked, then I suppose there is a chance that a pointer in the
+ * chain might be corrupt due to a partial store.
+ */
+- __stdio_init_mutex(&_stdio_openlist_lock);
++ __stdio_init_mutex(&_stdio_openlist_add_lock);
++#warning check
++#ifdef __STDIO_BUFFERS
++ __stdio_init_mutex(&_stdio_openlist_del_lock);
++#endif
+
+ /* Next we need to worry about the streams themselves. If a stream
+ * is currently locked, then it may be in an invalid state. So we
+@@ -192,7 +200,7 @@ void _stdio_term(void)
+ * Then we reinitialize the locks.
+ */
+ for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) {
+- if (__STDIO_ALWAYS_THREADTRYLOCK(ptr)) {
++ if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) {
+ /* The stream is already locked, so we don't want to touch it.
+ * However, if we have custom streams, we can't just close it
+ * or leave it locked since a custom stream may be stacked
+@@ -258,10 +266,6 @@ void _stdio_init(void)
+ #error Assumption violated about __MASK_READING and __FLAG_UNGOT
+ #endif
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-#endif
+-
+ #ifndef NDEBUG
+
+ void _stdio_validate_FILE(const FILE *stream)
+diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h
+index e3c2c58..decf57d 100644
+--- a/libc/stdio/_stdio.h
++++ b/libc/stdio/_stdio.h
+@@ -22,23 +22,57 @@
+ #include <wchar.h>
+ #endif
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
++#include <bits/uClibc_mutex.h>
+
+-#define __STDIO_THREADLOCK_OPENLIST \
+- __pthread_mutex_lock(&_stdio_openlist_lock)
++#define __STDIO_THREADLOCK_OPENLIST_ADD \
++ __UCLIBC_MUTEX_LOCK(_stdio_openlist_add_lock)
+
+-#define __STDIO_THREADUNLOCK_OPENLIST \
+- __pthread_mutex_unlock(&_stdio_openlist_lock)
++#define __STDIO_THREADUNLOCK_OPENLIST_ADD \
++ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_add_lock)
+
+-#define __STDIO_THREADTRYLOCK_OPENLIST \
+- __pthread_mutex_trylock(&_stdio_openlist_lock)
++#ifdef __STDIO_BUFFERS
+
+-#else
++#define __STDIO_THREADLOCK_OPENLIST_DEL \
++ __UCLIBC_MUTEX_LOCK(_stdio_openlist_del_lock)
++
++#define __STDIO_THREADUNLOCK_OPENLIST_DEL \
++ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_del_lock)
+
+-#define __STDIO_THREADLOCK_OPENLIST ((void)0)
+-#define __STDIO_THREADUNLOCK_OPENLIST ((void)0)
++#define __STDIO_OPENLIST_INC_USE \
++do { \
++ __STDIO_THREADLOCK_OPENLIST_DEL; \
++ ++_stdio_openlist_use_count; \
++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \
++} while (0)
++
++extern void _stdio_openlist_dec_use(void);
++
++#define __STDIO_OPENLIST_DEC_USE \
++ _stdio_openlist_dec_use()
++
++#define __STDIO_OPENLIST_INC_DEL_CNT \
++do { \
++ __STDIO_THREADLOCK_OPENLIST_DEL; \
++ ++_stdio_openlist_del_count; \
++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \
++} while (0)
++
++#define __STDIO_OPENLIST_DEC_DEL_CNT \
++do { \
++ __STDIO_THREADLOCK_OPENLIST_DEL; \
++ --_stdio_openlist_del_count; \
++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \
++} while (0)
++
++#endif /* __STDIO_BUFFERS */
+
++#ifndef __STDIO_THREADLOCK_OPENLIST_DEL
++#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0)
++#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0)
++#define __STDIO_OPENLIST_INC_USE ((void)0)
++#define __STDIO_OPENLIST_DEC_USE ((void)0)
++#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0)
++#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0)
+ #endif
+
+ #define __UNDEFINED_OR_NONPORTABLE ((void)0)
+diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c
+index 4df2e42..dfababc 100644
+--- a/libc/stdio/fclose.c
++++ b/libc/stdio/fclose.c
+@@ -12,30 +12,34 @@ int fclose(register FILE *stream)
+ int rv = 0;
+ __STDIO_AUTO_THREADLOCK_VAR;
+
+- /* First, remove the file from the open file list. */
+-#ifdef __STDIO_HAS_OPENLIST
+- {
+- register FILE *ptr;
+-
+- __STDIO_THREADLOCK_OPENLIST;
+- if ((ptr = _stdio_openlist) == stream) {
+- _stdio_openlist = stream->__nextopen;
+- } else {
+- while (ptr) {
+- if (ptr->__nextopen == stream) {
+- ptr->__nextopen = stream->__nextopen;
+- break;
+- }
+- ptr = ptr->__nextopen;
+- }
+- }
+- __STDIO_THREADUNLOCK_OPENLIST;
+-
+- if (!ptr) { /* Did not find stream in the open file list! */
+- return EOF;
+- }
+- }
+-#endif
++#warning dead code... but may want to simply check and not remove
++/* #ifdef __STDIO_HAS_OPENLIST */
++/* #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) */
++/* /\* First, remove the file from the open file list. *\/ */
++/* { */
++/* register FILE *ptr; */
++
++/* __STDIO_THREADLOCK_OPENLIST; */
++/* if ((ptr = _stdio_openlist) == stream) { */
++/* #warning does a mod!!! */
++/* _stdio_openlist = stream->__nextopen; */
++/* } else { */
++/* while (ptr) { */
++/* if (ptr->__nextopen == stream) { */
++/* ptr->__nextopen = stream->__nextopen; */
++/* break; */
++/* } */
++/* ptr = ptr->__nextopen; */
++/* } */
++/* } */
++/* __STDIO_THREADUNLOCK_OPENLIST; */
++
++/* if (!ptr) { /\* Did not find stream in the open file list! *\/ */
++/* return EOF; */
++/* } */
++/* } */
++/* #endif */
++/* #endif */
+
+ __STDIO_AUTO_THREADLOCK(stream);
+
+@@ -80,7 +84,15 @@ int fclose(register FILE *stream)
+ __STDIO_AUTO_THREADUNLOCK(stream);
+
+ __STDIO_STREAM_FREE_BUFFER(stream);
++#warning... inefficient - locks and unlocks twice and walks whole list
++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
++ /* inefficient - locks/unlocks twice and walks whole list */
++ __STDIO_OPENLIST_INC_USE;
++ __STDIO_OPENLIST_INC_DEL_CNT;
++ __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */
++#else
+ __STDIO_STREAM_FREE_FILE(stream);
++#endif
+
+ return rv;
+ }
+diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c
+index dbb6000..f62281a 100644
+--- a/libc/stdio/fcloseall.c
++++ b/libc/stdio/fcloseall.c
+@@ -19,14 +19,34 @@ int fcloseall (void)
+ #ifdef __STDIO_HAS_OPENLIST
+
+ int retval = 0;
++ FILE *f;
+
+- __STDIO_THREADLOCK_OPENLIST;
+- while (_stdio_openlist) {
+- if (fclose(_stdio_openlist)) {
++#warning remove dead code
++/* __STDIO_THREADLOCK_OPENLIST; */
++/* while (_stdio_openlist) { */
++/* if (fclose(_stdio_openlist)) { */
++/* retval = EOF; */
++/* } */
++/* } */
++/* __STDIO_THREADUNLOCK_OPENLIST; */
++
++ __STDIO_OPENLIST_INC_USE;
++
++#warning should probably have a get_head() operation
++ __STDIO_THREADLOCK_OPENLIST_ADD;
++ f = _stdio_openlist;
++ __STDIO_THREADUNLOCK_OPENLIST_ADD;
++
++ while (f) {
++#warning should probably have a get_next() operation
++ FILE *n = f->__nextopen;
++ if (fclose(f)) {
+ retval = EOF;
+ }
++ f = n;
+ }
+- __STDIO_THREADUNLOCK_OPENLIST;
++
++ __STDIO_OPENLIST_DEC_USE;
+
+ return retval;
+
+diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c
+index 6baa0ec..66b65cd 100644
+--- a/libc/stdio/fflush.c
++++ b/libc/stdio/fflush.c
+@@ -20,23 +20,50 @@ weak_alias(__fflush_unlocked,fflush_unlo
+ weak_alias(__fflush_unlocked,fflush);
+ #endif
+
+-#ifdef __UCLIBC_HAS_THREADS__
+ /* Even if the stream is set to user-locking, we still need to lock
+ * when all (lbf) writing streams are flushed. */
+-#define MY_STDIO_THREADLOCK(STREAM) \
+- if (_stdio_user_locking != 2) { \
+- __STDIO_ALWAYS_THREADLOCK(STREAM); \
+- }
+
+-#define MY_STDIO_THREADUNLOCK(STREAM) \
+- if (_stdio_user_locking != 2) { \
+- __STDIO_ALWAYS_THREADUNLOCK(STREAM); \
+- }
+-#else
+-#define MY_STDIO_THREADLOCK(STREAM) ((void)0)
+-#define MY_STDIO_THREADUNLOCK(STREAM) ((void)0)
+-#endif
++#define __MY_STDIO_THREADLOCK(__stream) \
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \
++ (_stdio_user_locking != 2))
++
++#define __MY_STDIO_THREADUNLOCK(__stream) \
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \
++ (_stdio_user_locking != 2))
+
++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
++void _stdio_openlist_dec_use(void)
++{
++ __STDIO_THREADLOCK_OPENLIST_DEL;
++ if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) {
++ FILE *p = NULL;
++ FILE *n;
++ FILE *stream;
++
++ __STDIO_THREADLOCK_OPENLIST_ADD;
++ for (stream = _stdio_openlist; stream; stream = n) {
++#warning walk the list and clear out all fclosed()d files
++ n = stream->__nextopen;
++#warning fix for nonatomic
++ if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
++ == (__FLAG_READONLY|__FLAG_WRITEONLY)
++ ) { /* The file was closed so remove from the list. */
++ if (!p) {
++ _stdio_openlist = n;
++ } else {
++ p->__nextopen = n;
++ }
++ __STDIO_STREAM_FREE_FILE(stream);
++ } else {
++ p = stream;
++ }
++ }
++ __STDIO_THREADUNLOCK_OPENLIST_DEL;
++ }
++ --_stdio_openlist_use_count;
++ __STDIO_THREADUNLOCK_OPENLIST_DEL;
++}
++#endif
+
+ int __fflush_unlocked(register FILE *stream)
+ {
+@@ -60,23 +87,39 @@ int __fflush_unlocked(register FILE *str
+ }
+
+ if (!stream) { /* Flush all (lbf) writing streams. */
+- __STDIO_THREADLOCK_OPENLIST;
+- for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) {
+- MY_STDIO_THREADLOCK(stream);
+- if (!(((stream->__modeflags | bufmask)
+- ^ (__FLAG_WRITING|__FLAG_LBF)
+- ) & (__FLAG_WRITING|__MASK_BUFMODE))
+- ) {
+- if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
+- __STDIO_STREAM_DISABLE_PUTC(stream);
+- __STDIO_STREAM_CLEAR_WRITING(stream);
+- } else {
+- retval = EOF;
++
++ __STDIO_OPENLIST_INC_USE;
++
++ __STDIO_THREADLOCK_OPENLIST_ADD;
++ stream = _stdio_openlist;
++ __STDIO_THREADUNLOCK_OPENLIST_ADD;
++
++ while(stream) {
++ /* We only care about currently writing streams and do not want to
++ * block trying to obtain mutexes on non-writing streams. */
++#warning fix for nonatomic
++#warning unnecessary check if no threads
++ if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */
++ __MY_STDIO_THREADLOCK(stream);
++ /* Need to check again once we have the lock. */
++ if (!(((stream->__modeflags | bufmask)
++ ^ (__FLAG_WRITING|__FLAG_LBF)
++ ) & (__FLAG_WRITING|__MASK_BUFMODE))
++ ) {
++ if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
++ __STDIO_STREAM_DISABLE_PUTC(stream);
++ __STDIO_STREAM_CLEAR_WRITING(stream);
++ } else {
++ retval = EOF;
++ }
+ }
++ __MY_STDIO_THREADUNLOCK(stream);
+ }
+- MY_STDIO_THREADUNLOCK(stream);
++ stream = stream->__nextopen;
+ }
+- __STDIO_THREADUNLOCK_OPENLIST;
++
++ __STDIO_OPENLIST_DEC_USE;
++
+ } else if (__STDIO_STREAM_IS_WRITING(stream)) {
+ if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
+ __STDIO_STREAM_DISABLE_PUTC(stream);
+diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c
+index 0dcc7c2..3fad711 100644
+--- a/libc/stdio/flockfile.c
++++ b/libc/stdio/flockfile.c
+@@ -11,6 +11,6 @@ void flockfile(FILE *stream)
+ {
+ __STDIO_STREAM_VALIDATE(stream);
+
+- __STDIO_ALWAYS_THREADLOCK(stream);
++ __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream);
+ }
+
+diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c
+index 0eccaac..36b8488 100644
+--- a/libc/stdio/freopen.c
++++ b/libc/stdio/freopen.c
+@@ -42,6 +42,8 @@ FILE *freopen(const char * __restrict fi
+
+ __STDIO_STREAM_VALIDATE(stream);
+
++ __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */
++
+ /* First, flush and close, but don't deallocate, the stream. */
+ /* This also removes the stream for the open file list. */
+ dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
+@@ -57,9 +59,16 @@ FILE *freopen(const char * __restrict fi
+
+ fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG);
+
++#warning if fp is NULL, then we do not free file (but beware stdin,stdout,stderr)
++ if (fp) {
++ __STDIO_OPENLIST_DEC_DEL_CNT;
++ }
++
+ /* Reset the allocation flags. */
+ stream->__modeflags |= dynmode;
+
++ __STDIO_OPENLIST_DEC_USE;
++
+ __STDIO_AUTO_THREADUNLOCK(stream);
+
+ return fp;
+diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c
+index 7092f34..69385ce 100644
+--- a/libc/stdio/ftello.c
++++ b/libc/stdio/ftello.c
+@@ -48,7 +48,10 @@ OFFSET_TYPE FTELL(register FILE *stream)
+
+ __STDIO_STREAM_VALIDATE(stream);
+
+- if ((__SEEK(stream, &pos, SEEK_CUR) < 0)
++ if ((__SEEK(stream, &pos,
++ ((__STDIO_STREAM_IS_WRITING(stream)
++ && (stream->__modeflags & __FLAG_APPEND))
++ ? SEEK_END : SEEK_CUR)) < 0)
+ || (__stdio_adjust_position(stream, &pos) < 0)) {
+ pos = -1;
+ }
+diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c
+index d85b8ff..0d2e156 100644
+--- a/libc/stdio/ftrylockfile.c
++++ b/libc/stdio/ftrylockfile.c
+@@ -15,5 +15,5 @@ int ftrylockfile(FILE *stream)
+ {
+ __STDIO_STREAM_VALIDATE(stream);
+
+- return __STDIO_ALWAYS_THREADTRYLOCK(stream);
++ return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream);
+ }
+diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c
+index 048c093..2ddf097 100644
+--- a/libc/stdio/funlockfile.c
++++ b/libc/stdio/funlockfile.c
+@@ -11,5 +11,5 @@ void funlockfile(FILE *stream)
+ {
+ __STDIO_STREAM_VALIDATE(stream);
+
+- __STDIO_ALWAYS_THREADUNLOCK(stream);
++ __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream);
+ }
+diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c
+index c7887ad..ab8d296 100644
+--- a/libc/stdio/popen.c
++++ b/libc/stdio/popen.c
+@@ -14,6 +14,7 @@
+ * Fix failure exit code for failed execve().
+ */
+
++#warning hmm... susv3 says "Pipe streams are byte-oriented."
+
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -21,6 +22,8 @@
+ #include <unistd.h>
+ #include <sys/wait.h>
+
++#include <bits/uClibc_mutex.h>
++
+ /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */
+ #include <sys/syscall.h>
+ #if ! defined __NR_vfork
+@@ -29,19 +32,11 @@
+ # define VFORK_UNLOCK ((void) 0)
+ #endif
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK ((void) 0)
+-# define UNLOCK ((void) 0)
+-#endif
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ #ifndef VFORK_LOCK
+-# define VFORK_LOCK LOCK
+-# define VFORK_UNLOCK UNLOCK
++# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock)
++# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock)
+ #endif
+
+ struct popen_list_item {
+@@ -118,10 +113,10 @@ FILE *popen(const char *command, const c
+ if (pid > 0) { /* Parent of vfork... */
+ pi->pid = pid;
+ pi->f = fp;
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ pi->next = popen_list;
+ popen_list = pi;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ return fp;
+ }
+@@ -136,6 +131,8 @@ FILE *popen(const char *command, const c
+ return NULL;
+ }
+
++#warning is pclose correct wrt the new mutex semantics?
++
+ int pclose(FILE *stream)
+ {
+ struct popen_list_item *p;
+@@ -144,7 +141,7 @@ int pclose(FILE *stream)
+
+ /* First, find the list entry corresponding to stream and remove it
+ * from the list. Set p to the list item (NULL if not found). */
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if ((p = popen_list) != NULL) {
+ if (p->f == stream) {
+ popen_list = p->next;
+@@ -163,7 +160,7 @@ int pclose(FILE *stream)
+ } while (1);
+ }
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+
+ if (p) {
+ pid = p->pid; /* Save the pid we need */
+diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c
+index 3fe62c6..6d53ab1 100644
+--- a/libc/stdio/setvbuf.c
++++ b/libc/stdio/setvbuf.c
+@@ -75,8 +75,8 @@ int setvbuf(register FILE * __restrict s
+ }
+
+ stream->__modeflags |= alloc_flag;
+- stream->__bufstart = buf;
+- stream->__bufend = buf + size;
++ stream->__bufstart = (unsigned char *) buf;
++ stream->__bufend = (unsigned char *) buf + size;
+ __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
+ __STDIO_STREAM_DISABLE_GETC(stream);
+ __STDIO_STREAM_DISABLE_PUTC(stream);
+diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c
+index 688ab7c..6d7664d 100644
+--- a/libc/stdio/vasprintf.c
++++ b/libc/stdio/vasprintf.c
+@@ -63,6 +63,8 @@ int vasprintf(char **__restrict buf, con
+ free(*buf);
+ *buf = NULL;
+ }
++ } else {
++ rv = -1;
+ }
+ }
+
+diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c
+index de8362c..7cb707f 100644
+--- a/libc/stdio/vdprintf.c
++++ b/libc/stdio/vdprintf.c
+@@ -15,8 +15,8 @@ int vdprintf(int filedes, const char * _
+ #ifdef __STDIO_BUFFERS
+ char buf[64]; /* TODO: provide _optional_ buffering? */
+
+- f.__bufend = buf + sizeof(buf);
+- f.__bufstart = buf;
++ f.__bufend = (unsigned char *) buf + sizeof(buf);
++ f.__bufstart = (unsigned char *) buf;
+ __STDIO_STREAM_DISABLE_GETC(&f);
+ __STDIO_STREAM_DISABLE_PUTC(&f);
+ __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f);
+diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
+index 10114f0..9214e3b 100644
+--- a/libc/stdio/vfprintf.c
++++ b/libc/stdio/vfprintf.c
+@@ -569,7 +569,7 @@ int _ppfs_init(register ppfs_t *ppfs, co
+ ppfs->fmtpos = fmt0; /* rewind */
+ }
+
+-#ifdef NL_MAX_ARG
++#ifdef NL_ARGMAX
+ /* If we have positional args, make sure we know all the types. */
+ {
+ register int *p = ppfs->argtype;
+@@ -581,7 +581,7 @@ int _ppfs_init(register ppfs_t *ppfs, co
+ ++p;
+ }
+ }
+-#endif /* NL_MAX_ARG */
++#endif /* NL_ARGMAX */
+
+ return 0;
+ }
+@@ -1214,7 +1214,7 @@ static size_t _fp_out_narrow(FILE *fp, i
+ }
+ len = buflen;
+ }
+- return r + OUTNSTR(fp, (const char *) buf, len);
++ return r + OUTNSTR(fp, (const unsigned char *) buf, len);
+ }
+
+ #endif /* __STDIO_PRINTF_FLOAT */
+diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c
+index 77c2cdc..9f69918 100644
+--- a/libc/stdlib/abort.c
++++ b/libc/stdlib/abort.c
+@@ -70,16 +70,9 @@ extern void _exit __P((int __status)) __
+ static int been_there_done_that = 0;
+
+ /* Be prepared in case multiple threads try to abort() */
+-#ifdef __UCLIBC_HAS_THREADS__
+-# include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock)
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++#include <bits/uClibc_mutex.h>
+
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ /* Cause an abnormal program termination with core-dump */
+ void abort(void)
+@@ -87,7 +80,7 @@ void abort(void)
+ sigset_t sigset;
+
+ /* Make sure we acquire the lock before proceeding */
+- LOCK;
++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock);
+
+ /* Unmask SIGABRT to be sure we can get it */
+ if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) {
+@@ -110,9 +103,9 @@ void abort(void)
+ #endif
+
+ abort_it:
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(mylock);
+ raise(SIGABRT);
+- LOCK;
++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock);
+ }
+
+ /* Still here? Try to remove any signal handlers */
+diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
+index 280f42c..b028068 100644
+--- a/libc/stdlib/atexit.c
++++ b/libc/stdlib/atexit.c
+@@ -40,17 +40,9 @@
+ #include <stdlib.h>
+ #include <errno.h>
+
++#include <bits/uClibc_mutex.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-extern pthread_mutex_t mylock;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
+-
++__UCLIBC_MUTEX_EXTERN(__atexit_lock);
+
+ typedef void (*aefuncp) (void); /* atexit function pointer */
+ typedef void (*oefuncp) (int, void *); /* on_exit function pointer */
+@@ -90,8 +82,9 @@ extern struct exit_function __exit_funct
+ int atexit(aefuncp func)
+ {
+ struct exit_function *efp;
++ int rv = -1;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(__atexit_lock);
+ if (func) {
+ #ifdef __UCLIBC_DYNAMIC_ATEXIT__
+ /* If we are out of function table slots, make some more */
+@@ -99,18 +92,16 @@ int atexit(aefuncp func)
+ efp=realloc(__exit_function_table,
+ (__exit_slots+20)*sizeof(struct exit_function));
+ if (efp==NULL) {
+- UNLOCK;
+ __set_errno(ENOMEM);
+- return -1;
++ goto DONE;
+ }
+ __exit_function_table = efp;
+ __exit_slots+=20;
+ }
+ #else
+ if (__exit_count >= __UCLIBC_MAX_ATEXIT) {
+- UNLOCK;
+ __set_errno(ENOMEM);
+- return -1;
++ goto DONE;
+ }
+ #endif
+ __exit_cleanup = __exit_handler; /* enable cleanup */
+@@ -118,8 +109,12 @@ int atexit(aefuncp func)
+ efp->type = ef_atexit;
+ efp->funcs.atexit = func;
+ }
+- UNLOCK;
+- return 0;
++
++ rv = 0;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock);
++ return rv;
+ }
+ #endif
+
+@@ -133,8 +128,9 @@ int atexit(aefuncp func)
+ int on_exit(oefuncp func, void *arg)
+ {
+ struct exit_function *efp;
++ int rv = -1;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(__atexit_lock);
+ if (func) {
+ #ifdef __UCLIBC_DYNAMIC_ATEXIT__
+ /* If we are out of function table slots, make some more */
+@@ -142,18 +138,16 @@ int on_exit(oefuncp func, void *arg)
+ efp=realloc(__exit_function_table,
+ (__exit_slots+20)*sizeof(struct exit_function));
+ if (efp==NULL) {
+- UNLOCK;
+ __set_errno(ENOMEM);
+- return -1;
++ goto DONE;
+ }
+ __exit_function_table=efp;
+ __exit_slots+=20;
+ }
+ #else
+ if (__exit_count >= __UCLIBC_MAX_ATEXIT) {
+- UNLOCK;
+ __set_errno(ENOMEM);
+- return -1;
++ goto DONE;
+ }
+ #endif
+
+@@ -163,8 +157,12 @@ int on_exit(oefuncp func, void *arg)
+ efp->funcs.on_exit.func = func;
+ efp->funcs.on_exit.arg = arg;
+ }
+- UNLOCK;
+- return 0;
++
++ rv = 0;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock);
++ return rv;
+ }
+ #endif
+
+@@ -214,9 +212,8 @@ void __exit_handler(int status)
+ #ifdef L_exit
+ extern void weak_function _stdio_term(void);
+ void (*__exit_cleanup) (int) = 0;
+-#ifdef __UCLIBC_HAS_THREADS__
+-pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-#endif
++
++__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ #ifdef __UCLIBC_CTOR_DTOR__
+ extern void (*__app_fini)(void);
+@@ -229,11 +226,11 @@ extern void (*__rtld_fini)(void);
+ void exit(int rv)
+ {
+ /* Perform exit-specific cleanup (atexit and on_exit) */
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(__atexit_lock);
+ if (__exit_cleanup) {
+ __exit_cleanup(rv);
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock);
+
+ #ifdef __UCLIBC_CTOR_DTOR__
+ if (__app_fini != NULL)
+diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c
+index ed14c37..519a875 100644
+--- a/libc/stdlib/malloc-simple/alloc.c
++++ b/libc/stdlib/malloc-simple/alloc.c
+@@ -108,15 +108,14 @@ void free(void *ptr)
+ #endif
+
+ #ifdef L_memalign
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-# define LOCK __pthread_mutex_lock(&__malloc_lock)
+-# define UNLOCK __pthread_mutex_unlock(&__malloc_lock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++
++#include <bits/uClibc_mutex.h>
++
++__UCLIBC_MUTEX_EXTERN(__malloc_lock);
++
++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
++
+
+ /* List of blocks allocated with memalign or valloc */
+ struct alignlist
+@@ -135,7 +134,7 @@ int __libc_free_aligned(void *ptr)
+ if (ptr == NULL)
+ return 0;
+
+- LOCK;
++ __MALLOC_LOCK;
+ for (l = _aligned_blocks; l != NULL; l = l->next) {
+ if (l->aligned == ptr) {
+ /* Mark the block as free */
+@@ -146,7 +145,7 @@ int __libc_free_aligned(void *ptr)
+ return 1;
+ }
+ }
+- UNLOCK;
++ __MALLOC_UNLOCK;
+ return 0;
+ }
+ void * memalign (size_t alignment, size_t size)
+@@ -159,10 +158,10 @@ void * memalign (size_t alignment, size_
+ return NULL;
+
+ adj = (unsigned long int) ((unsigned long int) ((char *) result -
+- (char *) NULL)) % alignment;
++ (char *) NULL)) % alignment;
+ if (adj != 0) {
+ struct alignlist *l;
+- LOCK;
++ __MALLOC_LOCK;
+ for (l = _aligned_blocks; l != NULL; l = l->next)
+ if (l->aligned == NULL)
+ /* This slot is free. Use it. */
+@@ -171,15 +170,16 @@ void * memalign (size_t alignment, size_
+ l = (struct alignlist *) malloc (sizeof (struct alignlist));
+ if (l == NULL) {
+ free(result);
+- UNLOCK;
+- return NULL;
++ result = NULL;
++ goto DONE;
+ }
+ l->next = _aligned_blocks;
+ _aligned_blocks = l;
+ }
+ l->exact = result;
+ result = l->aligned = (char *) result + alignment - adj;
+- UNLOCK;
++ DONE:
++ __MALLOC_UNLOCK;
+ }
+
+ return result;
+diff --git a/libc/stdlib/malloc-standard/calloc.c b/libc/stdlib/malloc-standard/calloc.c
+index a67dad7..4277954 100644
+--- a/libc/stdlib/malloc-standard/calloc.c
++++ b/libc/stdlib/malloc-standard/calloc.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -31,63 +31,63 @@ void* calloc(size_t n_elements, size_t e
+ * to fall through and call malloc(0) */
+ size = n_elements * elem_size;
+ if (n_elements && elem_size != (size / n_elements)) {
+- __set_errno(ENOMEM);
+- return NULL;
++ __set_errno(ENOMEM);
++ return NULL;
+ }
+
+- LOCK;
++ __MALLOC_LOCK;
+ mem = malloc(size);
+ if (mem != 0) {
+- p = mem2chunk(mem);
++ p = mem2chunk(mem);
+
+- if (!chunk_is_mmapped(p))
+- {
+- /*
+- Unroll clear of <= 36 bytes (72 if 8byte sizes)
+- We know that contents have an odd number of
+- size_t-sized words; minimally 3.
+- */
+-
+- d = (size_t*)mem;
+- clearsize = chunksize(p) - (sizeof(size_t));
+- nclears = clearsize / sizeof(size_t);
+- assert(nclears >= 3);
+-
+- if (nclears > 9)
+- memset(d, 0, clearsize);
+-
+- else {
+- *(d+0) = 0;
+- *(d+1) = 0;
+- *(d+2) = 0;
+- if (nclears > 4) {
+- *(d+3) = 0;
+- *(d+4) = 0;
+- if (nclears > 6) {
+- *(d+5) = 0;
+- *(d+6) = 0;
+- if (nclears > 8) {
+- *(d+7) = 0;
+- *(d+8) = 0;
++ if (!chunk_is_mmapped(p))
++ {
++ /*
++ Unroll clear of <= 36 bytes (72 if 8byte sizes)
++ We know that contents have an odd number of
++ size_t-sized words; minimally 3.
++ */
++
++ d = (size_t*)mem;
++ clearsize = chunksize(p) - (sizeof(size_t));
++ nclears = clearsize / sizeof(size_t);
++ assert(nclears >= 3);
++
++ if (nclears > 9)
++ memset(d, 0, clearsize);
++
++ else {
++ *(d+0) = 0;
++ *(d+1) = 0;
++ *(d+2) = 0;
++ if (nclears > 4) {
++ *(d+3) = 0;
++ *(d+4) = 0;
++ if (nclears > 6) {
++ *(d+5) = 0;
++ *(d+6) = 0;
++ if (nclears > 8) {
++ *(d+7) = 0;
++ *(d+8) = 0;
++ }
++ }
++ }
++ }
+ }
+- }
+- }
+- }
+- }
+ #if 0
+- else
+- {
+- /* Standard unix mmap using /dev/zero clears memory so calloc
+- * doesn't need to actually zero anything....
+- */
+- d = (size_t*)mem;
+- /* Note the additional (sizeof(size_t)) */
+- clearsize = chunksize(p) - 2*(sizeof(size_t));
+- memset(d, 0, clearsize);
+- }
++ else
++ {
++ /* Standard unix mmap using /dev/zero clears memory so calloc
++ * doesn't need to actually zero anything....
++ */
++ d = (size_t*)mem;
++ /* Note the additional (sizeof(size_t)) */
++ clearsize = chunksize(p) - 2*(sizeof(size_t));
++ memset(d, 0, clearsize);
++ }
+ #endif
+ }
+- UNLOCK;
++ __MALLOC_UNLOCK;
+ return mem;
+ }
+
+diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c
+index 94e1d65..4e08ef7 100644
+--- a/libc/stdlib/malloc-standard/free.c
++++ b/libc/stdlib/malloc-standard/free.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -42,71 +42,71 @@ static int __malloc_trim(size_t pad, mst
+
+ if (extra > 0) {
+
+- /*
+- Only proceed if end of memory is where we last set it.
+- This avoids problems if there were foreign sbrk calls.
+- */
+- current_brk = (char*)(MORECORE(0));
+- if (current_brk == (char*)(av->top) + top_size) {
+-
+- /*
+- Attempt to release memory. We ignore MORECORE return value,
+- and instead call again to find out where new end of memory is.
+- This avoids problems if first call releases less than we asked,
+- of if failure somehow altered brk value. (We could still
+- encounter problems if it altered brk in some very bad way,
+- but the only thing we can do is adjust anyway, which will cause
+- some downstream failure.)
+- */
+-
+- MORECORE(-extra);
+- new_brk = (char*)(MORECORE(0));
+-
+- if (new_brk != (char*)MORECORE_FAILURE) {
+- released = (long)(current_brk - new_brk);
+-
+- if (released != 0) {
+- /* Success. Adjust top. */
+- av->sbrked_mem -= released;
+- set_head(av->top, (top_size - released) | PREV_INUSE);
+- check_malloc_state();
+- return 1;
++ /*
++ Only proceed if end of memory is where we last set it.
++ This avoids problems if there were foreign sbrk calls.
++ */
++ current_brk = (char*)(MORECORE(0));
++ if (current_brk == (char*)(av->top) + top_size) {
++
++ /*
++ Attempt to release memory. We ignore MORECORE return value,
++ and instead call again to find out where new end of memory is.
++ This avoids problems if first call releases less than we asked,
++ of if failure somehow altered brk value. (We could still
++ encounter problems if it altered brk in some very bad way,
++ but the only thing we can do is adjust anyway, which will cause
++ some downstream failure.)
++ */
++
++ MORECORE(-extra);
++ new_brk = (char*)(MORECORE(0));
++
++ if (new_brk != (char*)MORECORE_FAILURE) {
++ released = (long)(current_brk - new_brk);
++
++ if (released != 0) {
++ /* Success. Adjust top. */
++ av->sbrked_mem -= released;
++ set_head(av->top, (top_size - released) | PREV_INUSE);
++ check_malloc_state();
++ return 1;
++ }
++ }
+ }
+- }
+- }
+ }
+ return 0;
+ }
+
+ /* ------------------------- malloc_trim -------------------------
+- malloc_trim(size_t pad);
++ malloc_trim(size_t pad);
+
+- If possible, gives memory back to the system (via negative
+- arguments to sbrk) if there is unused memory at the `high' end of
+- the malloc pool. You can call this after freeing large blocks of
+- memory to potentially reduce the system-level memory requirements
+- of a program. However, it cannot guarantee to reduce memory. Under
+- some allocation patterns, some large free blocks of memory will be
+- locked between two used chunks, so they cannot be given back to
+- the system.
+-
+- The `pad' argument to malloc_trim represents the amount of free
+- trailing space to leave untrimmed. If this argument is zero,
+- only the minimum amount of memory to maintain internal data
+- structures will be left (one page or less). Non-zero arguments
+- can be supplied to maintain enough trailing space to service
+- future expected allocations without having to re-obtain memory
+- from the system.
+-
+- Malloc_trim returns 1 if it actually released any memory, else 0.
+- On systems that do not support "negative sbrks", it will always
+- return 0.
++ If possible, gives memory back to the system (via negative
++ arguments to sbrk) if there is unused memory at the `high' end of
++ the malloc pool. You can call this after freeing large blocks of
++ memory to potentially reduce the system-level memory requirements
++ of a program. However, it cannot guarantee to reduce memory. Under
++ some allocation patterns, some large free blocks of memory will be
++ locked between two used chunks, so they cannot be given back to
++ the system.
++
++ The `pad' argument to malloc_trim represents the amount of free
++ trailing space to leave untrimmed. If this argument is zero,
++ only the minimum amount of memory to maintain internal data
++ structures will be left (one page or less). Non-zero arguments
++ can be supplied to maintain enough trailing space to service
++ future expected allocations without having to re-obtain memory
++ from the system.
++
++ Malloc_trim returns 1 if it actually released any memory, else 0.
++ On systems that do not support "negative sbrks", it will always
++ return 0.
+ */
+ int malloc_trim(size_t pad)
+ {
+- mstate av = get_malloc_state();
+- __malloc_consolidate(av);
+- return __malloc_trim(pad, av);
++ mstate av = get_malloc_state();
++ __malloc_consolidate(av);
++ return __malloc_trim(pad, av);
+ }
+
+ /*
+@@ -125,8 +125,8 @@ static void malloc_init_state(mstate av)
+
+ /* Establish circular links for normal bins */
+ for (i = 1; i < NBINS; ++i) {
+- bin = bin_at(av,i);
+- bin->fd = bin->bk = bin;
++ bin = bin_at(av,i);
++ bin->fd = bin->bk = bin;
+ }
+
+ av->top_pad = DEFAULT_TOP_PAD;
+@@ -157,15 +157,15 @@ static void malloc_init_state(mstate av)
+
+ /* ------------------------- __malloc_consolidate -------------------------
+
+- __malloc_consolidate is a specialized version of free() that tears
+- down chunks held in fastbins. Free itself cannot be used for this
+- purpose since, among other things, it might place chunks back onto
+- fastbins. So, instead, we need to use a minor variant of the same
+- code.
+-
+- Also, because this routine needs to be called the first time through
+- malloc anyway, it turns out to be the perfect place to trigger
+- initialization code.
++__malloc_consolidate is a specialized version of free() that tears
++down chunks held in fastbins. Free itself cannot be used for this
++purpose since, among other things, it might place chunks back onto
++fastbins. So, instead, we need to use a minor variant of the same
++code.
++
++Also, because this routine needs to be called the first time through
++malloc anyway, it turns out to be the perfect place to trigger
++initialization code.
+ */
+ void __malloc_consolidate(mstate av)
+ {
+@@ -186,78 +186,78 @@ void __malloc_consolidate(mstate av)
+ mchunkptr fwd;
+
+ /*
+- If max_fast is 0, we know that av hasn't
+- yet been initialized, in which case do so below
+- */
++ If max_fast is 0, we know that av hasn't
++ yet been initialized, in which case do so below
++ */
+
+ if (av->max_fast != 0) {
+- clear_fastchunks(av);
++ clear_fastchunks(av);
+
+- unsorted_bin = unsorted_chunks(av);
++ unsorted_bin = unsorted_chunks(av);
+
+- /*
+- Remove each chunk from fast bin and consolidate it, placing it
+- then in unsorted bin. Among other reasons for doing this,
+- placing in unsorted bin avoids needing to calculate actual bins
+- until malloc is sure that chunks aren't immediately going to be
+- reused anyway.
+- */
+-
+- maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
+- fb = &(av->fastbins[0]);
+- do {
+- if ( (p = *fb) != 0) {
+- *fb = 0;
++ /*
++ Remove each chunk from fast bin and consolidate it, placing it
++ then in unsorted bin. Among other reasons for doing this,
++ placing in unsorted bin avoids needing to calculate actual bins
++ until malloc is sure that chunks aren't immediately going to be
++ reused anyway.
++ */
+
++ maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
++ fb = &(av->fastbins[0]);
+ do {
+- check_inuse_chunk(p);
+- nextp = p->fd;
++ if ( (p = *fb) != 0) {
++ *fb = 0;
+
+- /* Slightly streamlined version of consolidation code in free() */
+- size = p->size & ~PREV_INUSE;
+- nextchunk = chunk_at_offset(p, size);
+- nextsize = chunksize(nextchunk);
++ do {
++ check_inuse_chunk(p);
++ nextp = p->fd;
++
++ /* Slightly streamlined version of consolidation code in free() */
++ size = p->size & ~PREV_INUSE;
++ nextchunk = chunk_at_offset(p, size);
++ nextsize = chunksize(nextchunk);
++
++ if (!prev_inuse(p)) {
++ prevsize = p->prev_size;
++ size += prevsize;
++ p = chunk_at_offset(p, -((long) prevsize));
++ unlink(p, bck, fwd);
++ }
++
++ if (nextchunk != av->top) {
++ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
++ set_head(nextchunk, nextsize);
++
++ if (!nextinuse) {
++ size += nextsize;
++ unlink(nextchunk, bck, fwd);
++ }
++
++ first_unsorted = unsorted_bin->fd;
++ unsorted_bin->fd = p;
++ first_unsorted->bk = p;
++
++ set_head(p, size | PREV_INUSE);
++ p->bk = unsorted_bin;
++ p->fd = first_unsorted;
++ set_foot(p, size);
++ }
++
++ else {
++ size += nextsize;
++ set_head(p, size | PREV_INUSE);
++ av->top = p;
++ }
+
+- if (!prev_inuse(p)) {
+- prevsize = p->prev_size;
+- size += prevsize;
+- p = chunk_at_offset(p, -((long) prevsize));
+- unlink(p, bck, fwd);
+- }
++ } while ( (p = nextp) != 0);
+
+- if (nextchunk != av->top) {
+- nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+- set_head(nextchunk, nextsize);
+-
+- if (!nextinuse) {
+- size += nextsize;
+- unlink(nextchunk, bck, fwd);
+ }
+-
+- first_unsorted = unsorted_bin->fd;
+- unsorted_bin->fd = p;
+- first_unsorted->bk = p;
+-
+- set_head(p, size | PREV_INUSE);
+- p->bk = unsorted_bin;
+- p->fd = first_unsorted;
+- set_foot(p, size);
+- }
+-
+- else {
+- size += nextsize;
+- set_head(p, size | PREV_INUSE);
+- av->top = p;
+- }
+-
+- } while ( (p = nextp) != 0);
+-
+- }
+- } while (fb++ != maxfb);
++ } while (fb++ != maxfb);
+ }
+ else {
+- malloc_init_state(av);
+- check_malloc_state();
++ malloc_init_state(av);
++ check_malloc_state();
+ }
+ }
+
+@@ -279,9 +279,9 @@ void free(void* mem)
+
+ /* free(0) has no effect */
+ if (mem == NULL)
+- return;
++ return;
+
+- LOCK;
++ __MALLOC_LOCK;
+ av = get_malloc_state();
+ p = mem2chunk(mem);
+ size = chunksize(p);
+@@ -289,9 +289,9 @@ void free(void* mem)
+ check_inuse_chunk(p);
+
+ /*
+- If eligible, place chunk on a fastbin so it can be found
+- and used quickly in malloc.
+- */
++ If eligible, place chunk on a fastbin so it can be found
++ and used quickly in malloc.
++ */
+
+ if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
+
+@@ -300,114 +300,114 @@ void free(void* mem)
+ bordering top into fastbins */
+ && (chunk_at_offset(p, size) != av->top)
+ #endif
+- ) {
++ ) {
+
+- set_fastchunks(av);
+- fb = &(av->fastbins[fastbin_index(size)]);
+- p->fd = *fb;
+- *fb = p;
++ set_fastchunks(av);
++ fb = &(av->fastbins[fastbin_index(size)]);
++ p->fd = *fb;
++ *fb = p;
+ }
+
+ /*
+- Consolidate other non-mmapped chunks as they arrive.
+- */
++ Consolidate other non-mmapped chunks as they arrive.
++ */
+
+ else if (!chunk_is_mmapped(p)) {
+- set_anychunks(av);
++ set_anychunks(av);
++
++ nextchunk = chunk_at_offset(p, size);
++ nextsize = chunksize(nextchunk);
++
++ /* consolidate backward */
++ if (!prev_inuse(p)) {
++ prevsize = p->prev_size;
++ size += prevsize;
++ p = chunk_at_offset(p, -((long) prevsize));
++ unlink(p, bck, fwd);
++ }
++
++ if (nextchunk != av->top) {
++ /* get and clear inuse bit */
++ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
++ set_head(nextchunk, nextsize);
++
++ /* consolidate forward */
++ if (!nextinuse) {
++ unlink(nextchunk, bck, fwd);
++ size += nextsize;
++ }
++
++ /*
++ Place the chunk in unsorted chunk list. Chunks are
++ not placed into regular bins until after they have
++ been given one chance to be used in malloc.
++ */
++
++ bck = unsorted_chunks(av);
++ fwd = bck->fd;
++ p->bk = bck;
++ p->fd = fwd;
++ bck->fd = p;
++ fwd->bk = p;
+
+- nextchunk = chunk_at_offset(p, size);
+- nextsize = chunksize(nextchunk);
++ set_head(p, size | PREV_INUSE);
++ set_foot(p, size);
++
++ check_free_chunk(p);
++ }
++
++ /*
++ If the chunk borders the current high end of memory,
++ consolidate into top
++ */
+
+- /* consolidate backward */
+- if (!prev_inuse(p)) {
+- prevsize = p->prev_size;
+- size += prevsize;
+- p = chunk_at_offset(p, -((long) prevsize));
+- unlink(p, bck, fwd);
+- }
+-
+- if (nextchunk != av->top) {
+- /* get and clear inuse bit */
+- nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+- set_head(nextchunk, nextsize);
+-
+- /* consolidate forward */
+- if (!nextinuse) {
+- unlink(nextchunk, bck, fwd);
+- size += nextsize;
+- }
+-
+- /*
+- Place the chunk in unsorted chunk list. Chunks are
+- not placed into regular bins until after they have
+- been given one chance to be used in malloc.
+- */
+-
+- bck = unsorted_chunks(av);
+- fwd = bck->fd;
+- p->bk = bck;
+- p->fd = fwd;
+- bck->fd = p;
+- fwd->bk = p;
+-
+- set_head(p, size | PREV_INUSE);
+- set_foot(p, size);
+-
+- check_free_chunk(p);
+- }
+-
+- /*
+- If the chunk borders the current high end of memory,
+- consolidate into top
+- */
+-
+- else {
+- size += nextsize;
+- set_head(p, size | PREV_INUSE);
+- av->top = p;
+- check_chunk(p);
+- }
+-
+- /*
+- If freeing a large space, consolidate possibly-surrounding
+- chunks. Then, if the total unused topmost memory exceeds trim
+- threshold, ask malloc_trim to reduce top.
+-
+- Unless max_fast is 0, we don't know if there are fastbins
+- bordering top, so we cannot tell for sure whether threshold
+- has been reached unless fastbins are consolidated. But we
+- don't want to consolidate on each free. As a compromise,
+- consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
+- is reached.
+- */
+-
+- if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
+- if (have_fastchunks(av))
+- __malloc_consolidate(av);
+-
+- if ((unsigned long)(chunksize(av->top)) >=
+- (unsigned long)(av->trim_threshold))
+- __malloc_trim(av->top_pad, av);
+- }
++ else {
++ size += nextsize;
++ set_head(p, size | PREV_INUSE);
++ av->top = p;
++ check_chunk(p);
++ }
++
++ /*
++ If freeing a large space, consolidate possibly-surrounding
++ chunks. Then, if the total unused topmost memory exceeds trim
++ threshold, ask malloc_trim to reduce top.
++
++ Unless max_fast is 0, we don't know if there are fastbins
++ bordering top, so we cannot tell for sure whether threshold
++ has been reached unless fastbins are consolidated. But we
++ don't want to consolidate on each free. As a compromise,
++ consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
++ is reached.
++ */
++
++ if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
++ if (have_fastchunks(av))
++ __malloc_consolidate(av);
++
++ if ((unsigned long)(chunksize(av->top)) >=
++ (unsigned long)(av->trim_threshold))
++ __malloc_trim(av->top_pad, av);
++ }
+
+ }
+ /*
+- If the chunk was allocated via mmap, release via munmap()
+- Note that if HAVE_MMAP is false but chunk_is_mmapped is
+- true, then user must have overwritten memory. There's nothing
+- we can do to catch this error unless DEBUG is set, in which case
+- check_inuse_chunk (above) will have triggered error.
+- */
++ If the chunk was allocated via mmap, release via munmap()
++ Note that if HAVE_MMAP is false but chunk_is_mmapped is
++ true, then user must have overwritten memory. There's nothing
++ we can do to catch this error unless DEBUG is set, in which case
++ check_inuse_chunk (above) will have triggered error.
++ */
+
+ else {
+- int ret;
+- size_t offset = p->prev_size;
+- av->n_mmaps--;
+- av->mmapped_mem -= (size + offset);
+- ret = munmap((char*)p - offset, size + offset);
+- /* munmap returns non-zero on failure */
+- assert(ret == 0);
++ int ret;
++ size_t offset = p->prev_size;
++ av->n_mmaps--;
++ av->mmapped_mem -= (size + offset);
++ ret = munmap((char*)p - offset, size + offset);
++ /* munmap returns non-zero on failure */
++ assert(ret == 0);
+ }
+- UNLOCK;
++ __MALLOC_UNLOCK;
+ }
+
+diff --git a/libc/stdlib/malloc-standard/mallinfo.c b/libc/stdlib/malloc-standard/mallinfo.c
+index 51ac423..1e0875c 100644
+--- a/libc/stdlib/malloc-standard/mallinfo.c
++++ b/libc/stdlib/malloc-standard/mallinfo.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -30,11 +30,11 @@ struct mallinfo mallinfo(void)
+ int nblocks;
+ int nfastblocks;
+
+- LOCK;
++ __MALLOC_LOCK;
+ av = get_malloc_state();
+ /* Ensure initialization */
+ if (av->top == 0) {
+- __malloc_consolidate(av);
++ __malloc_consolidate(av);
+ }
+
+ check_malloc_state();
+@@ -48,21 +48,21 @@ struct mallinfo mallinfo(void)
+ fastavail = 0;
+
+ for (i = 0; i < NFASTBINS; ++i) {
+- for (p = av->fastbins[i]; p != 0; p = p->fd) {
+- ++nfastblocks;
+- fastavail += chunksize(p);
+- }
++ for (p = av->fastbins[i]; p != 0; p = p->fd) {
++ ++nfastblocks;
++ fastavail += chunksize(p);
++ }
+ }
+
+ avail += fastavail;
+
+ /* traverse regular bins */
+ for (i = 1; i < NBINS; ++i) {
+- b = bin_at(av, i);
+- for (p = last(b); p != b; p = p->bk) {
+- ++nblocks;
+- avail += chunksize(p);
+- }
++ b = bin_at(av, i);
++ for (p = last(b); p != b; p = p->bk) {
++ ++nblocks;
++ avail += chunksize(p);
++ }
+ }
+
+ mi.smblks = nfastblocks;
+@@ -75,7 +75,7 @@ struct mallinfo mallinfo(void)
+ mi.fsmblks = fastavail;
+ mi.keepcost = chunksize(av->top);
+ mi.usmblks = av->max_total_mem;
+- UNLOCK;
++ __MALLOC_UNLOCK;
+ return mi;
+ }
+
+@@ -84,23 +84,40 @@ void malloc_stats(FILE *file)
+ struct mallinfo mi;
+
+ if (file==NULL) {
+- file = stderr;
++ file = stderr;
+ }
+
+ mi = mallinfo();
+- fprintf(file, "total bytes allocated = %10u\n", (unsigned int)(mi.arena + mi.hblkhd));
+- fprintf(file, "total bytes in use bytes = %10u\n", (unsigned int)(mi.uordblks + mi.hblkhd));
+- fprintf(file, "total non-mmapped bytes allocated = %10d\n", mi.arena);
+- fprintf(file, "number of mmapped regions = %10d\n", mi.hblks);
+- fprintf(file, "total allocated mmap space = %10d\n", mi.hblkhd);
+- fprintf(file, "total allocated sbrk space = %10d\n", mi.uordblks);
++ fprintf(file,
++ "total bytes allocated = %10u\n"
++ "total bytes in use bytes = %10u\n"
++ "total non-mmapped bytes allocated = %10d\n"
++ "number of mmapped regions = %10d\n"
++ "total allocated mmap space = %10d\n"
++ "total allocated sbrk space = %10d\n"
+ #if 0
+- fprintf(file, "number of free chunks = %10d\n", mi.ordblks);
+- fprintf(file, "number of fastbin blocks = %10d\n", mi.smblks);
+- fprintf(file, "space in freed fastbin blocks = %10d\n", mi.fsmblks);
++ "number of free chunks = %10d\n"
++ "number of fastbin blocks = %10d\n"
++ "space in freed fastbin blocks = %10d\n"
+ #endif
+- fprintf(file, "maximum total allocated space = %10d\n", mi.usmblks);
+- fprintf(file, "total free space = %10d\n", mi.fordblks);
+- fprintf(file, "memory releasable via malloc_trim = %10d\n", mi.keepcost);
++ "maximum total allocated space = %10d\n"
++ "total free space = %10d\n"
++ "memory releasable via malloc_trim = %10d\n",
++
++ (unsigned int)(mi.arena + mi.hblkhd),
++ (unsigned int)(mi.uordblks + mi.hblkhd),
++ mi.arena,
++ mi.hblks,
++ mi.hblkhd,
++ mi.uordblks,
++#if 0
++ mi.ordblks,
++ mi.smblks,
++ mi.fsmblks,
++#endif
++ mi.usmblks,
++ mi.fordblks,
++ mi.keepcost
++ );
+ }
+
+diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c
+index 7025e83..60494a0 100644
+--- a/libc/stdlib/malloc-standard/malloc.c
++++ b/libc/stdlib/malloc-standard/malloc.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -17,17 +17,14 @@
+ #define _GNU_SOURCE
+ #include "malloc.h"
+
+-
+-#ifdef __UCLIBC_HAS_THREADS__
+-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-#endif
++__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ /*
+- There is exactly one instance of this struct in this malloc.
+- If you are adapting this malloc in a way that does NOT use a static
+- malloc_state, you MUST explicitly zero-fill it before using. This
+- malloc relies on the property that malloc_state is initialized to
+- all zeroes (as is true of C statics).
++ There is exactly one instance of this struct in this malloc.
++ If you are adapting this malloc in a way that does NOT use a static
++ malloc_state, you MUST explicitly zero-fill it before using. This
++ malloc relies on the property that malloc_state is initialized to
++ all zeroes (as is true of C statics).
+ */
+ struct malloc_state __malloc_state; /* never directly referenced */
+
+@@ -77,30 +74,30 @@ void __do_check_chunk(mchunkptr p)
+
+ if (!chunk_is_mmapped(p)) {
+
+- /* Has legal address ... */
+- if (p != av->top) {
+- if (contiguous(av)) {
+- assert(((char*)p) >= min_address);
+- assert(((char*)p + sz) <= ((char*)(av->top)));
+- }
+- }
+- else {
+- /* top size is always at least MINSIZE */
+- assert((unsigned long)(sz) >= MINSIZE);
+- /* top predecessor always marked inuse */
+- assert(prev_inuse(p));
+- }
++ /* Has legal address ... */
++ if (p != av->top) {
++ if (contiguous(av)) {
++ assert(((char*)p) >= min_address);
++ assert(((char*)p + sz) <= ((char*)(av->top)));
++ }
++ }
++ else {
++ /* top size is always at least MINSIZE */
++ assert((unsigned long)(sz) >= MINSIZE);
++ /* top predecessor always marked inuse */
++ assert(prev_inuse(p));
++ }
+
+ }
+ else {
+- /* address is outside main heap */
+- if (contiguous(av) && av->top != initial_top(av)) {
+- assert(((char*)p) < min_address || ((char*)p) > max_address);
+- }
+- /* chunk is page-aligned */
+- assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);
+- /* mem is aligned */
+- assert(aligned_OK(chunk2mem(p)));
++ /* address is outside main heap */
++ if (contiguous(av) && av->top != initial_top(av)) {
++ assert(((char*)p) < min_address || ((char*)p) > max_address);
++ }
++ /* chunk is page-aligned */
++ assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);
++ /* mem is aligned */
++ assert(aligned_OK(chunk2mem(p)));
+ }
+ }
+
+@@ -121,21 +118,21 @@ void __do_check_free_chunk(mchunkptr p)
+
+ /* Unless a special marker, must have OK fields */
+ if ((unsigned long)(sz) >= MINSIZE)
+- {
+- assert((sz & MALLOC_ALIGN_MASK) == 0);
+- assert(aligned_OK(chunk2mem(p)));
+- /* ... matching footer field */
+- assert(next->prev_size == sz);
+- /* ... and is fully consolidated */
+- assert(prev_inuse(p));
+- assert (next == av->top || inuse(next));
+-
+- /* ... and has minimally sane links */
+- assert(p->fd->bk == p);
+- assert(p->bk->fd == p);
+- }
++ {
++ assert((sz & MALLOC_ALIGN_MASK) == 0);
++ assert(aligned_OK(chunk2mem(p)));
++ /* ... matching footer field */
++ assert(next->prev_size == sz);
++ /* ... and is fully consolidated */
++ assert(prev_inuse(p));
++ assert (next == av->top || inuse(next));
++
++ /* ... and has minimally sane links */
++ assert(p->fd->bk == p);
++ assert(p->bk->fd == p);
++ }
+ else /* markers are always of size (sizeof(size_t)) */
+- assert(sz == (sizeof(size_t)));
++ assert(sz == (sizeof(size_t)));
+ }
+
+ /* Properties of inuse chunks */
+@@ -146,7 +143,7 @@ void __do_check_inuse_chunk(mchunkptr p)
+ __do_check_chunk(p);
+
+ if (chunk_is_mmapped(p))
+- return; /* mmapped chunks have no next/prev */
++ return; /* mmapped chunks have no next/prev */
+
+ /* Check whether it claims to be in use ... */
+ assert(inuse(p));
+@@ -156,20 +153,20 @@ void __do_check_inuse_chunk(mchunkptr p)
+ /* ... and is surrounded by OK chunks.
+ Since more things can be checked with free chunks than inuse ones,
+ if an inuse chunk borders them and debug is on, it's worth doing them.
+- */
++ */
+ if (!prev_inuse(p)) {
+- /* Note that we cannot even look at prev unless it is not inuse */
+- mchunkptr prv = prev_chunk(p);
+- assert(next_chunk(prv) == p);
+- __do_check_free_chunk(prv);
++ /* Note that we cannot even look at prev unless it is not inuse */
++ mchunkptr prv = prev_chunk(p);
++ assert(next_chunk(prv) == p);
++ __do_check_free_chunk(prv);
+ }
+
+ if (next == av->top) {
+- assert(prev_inuse(next));
+- assert(chunksize(next) >= MINSIZE);
++ assert(prev_inuse(next));
++ assert(chunksize(next) >= MINSIZE);
+ }
+ else if (!inuse(next))
+- __do_check_free_chunk(next);
++ __do_check_free_chunk(next);
+ }
+
+ /* Properties of chunks recycled from fastbins */
+@@ -198,14 +195,14 @@ void __do_check_malloced_chunk(mchunkptr
+ __do_check_remalloced_chunk(p, s);
+
+ /*
+- ... plus, must obey implementation invariant that prev_inuse is
+- always true of any allocated chunk; i.e., that each allocated
+- chunk borders either a previously allocated and still in-use
+- chunk, or the base of its memory arena. This is ensured
+- by making all allocations from the the `lowest' part of any found
+- chunk. This does not necessarily hold however for chunks
+- recycled via fastbins.
+- */
++ ... plus, must obey implementation invariant that prev_inuse is
++ always true of any allocated chunk; i.e., that each allocated
++ chunk borders either a previously allocated and still in-use
++ chunk, or the base of its memory arena. This is ensured
++ by making all allocations from the the `lowest' part of any found
++ chunk. This does not necessarily hold however for chunks
++ recycled via fastbins.
++ */
+
+ assert(prev_inuse(p));
+ }
+@@ -243,7 +240,7 @@ void __do_check_malloc_state(void)
+
+ /* cannot run remaining checks until fully initialized */
+ if (av->top == 0 || av->top == initial_top(av))
+- return;
++ return;
+
+ /* pagesize is a power of 2 */
+ assert((av->pagesize & (av->pagesize-1)) == 0);
+@@ -256,64 +253,64 @@ void __do_check_malloc_state(void)
+ max_fast_bin = fastbin_index(av->max_fast);
+
+ for (i = 0; i < NFASTBINS; ++i) {
+- p = av->fastbins[i];
++ p = av->fastbins[i];
+
+- /* all bins past max_fast are empty */
+- if (i > max_fast_bin)
+- assert(p == 0);
+-
+- while (p != 0) {
+- /* each chunk claims to be inuse */
+- __do_check_inuse_chunk(p);
+- total += chunksize(p);
+- /* chunk belongs in this bin */
+- assert(fastbin_index(chunksize(p)) == i);
+- p = p->fd;
+- }
++ /* all bins past max_fast are empty */
++ if (i > max_fast_bin)
++ assert(p == 0);
++
++ while (p != 0) {
++ /* each chunk claims to be inuse */
++ __do_check_inuse_chunk(p);
++ total += chunksize(p);
++ /* chunk belongs in this bin */
++ assert(fastbin_index(chunksize(p)) == i);
++ p = p->fd;
++ }
+ }
+
+ if (total != 0)
+- assert(have_fastchunks(av));
++ assert(have_fastchunks(av));
+ else if (!have_fastchunks(av))
+- assert(total == 0);
++ assert(total == 0);
+
+ /* check normal bins */
+ for (i = 1; i < NBINS; ++i) {
+- b = bin_at(av,i);
++ b = bin_at(av,i);
+
+- /* binmap is accurate (except for bin 1 == unsorted_chunks) */
+- if (i >= 2) {
+- binbit = get_binmap(av,i);
+- empty = last(b) == b;
+- if (!binbit)
+- assert(empty);
+- else if (!empty)
+- assert(binbit);
+- }
+-
+- for (p = last(b); p != b; p = p->bk) {
+- /* each chunk claims to be free */
+- __do_check_free_chunk(p);
+- size = chunksize(p);
+- total += size;
+- if (i >= 2) {
+- /* chunk belongs in bin */
+- idx = bin_index(size);
+- assert(idx == i);
+- /* lists are sorted */
+- if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
+- assert(p->bk == b ||
+- (unsigned long)chunksize(p->bk) >=
+- (unsigned long)chunksize(p));
+- }
+- }
+- /* chunk is followed by a legal chain of inuse chunks */
+- for (q = next_chunk(p);
+- (q != av->top && inuse(q) &&
+- (unsigned long)(chunksize(q)) >= MINSIZE);
+- q = next_chunk(q))
+- __do_check_inuse_chunk(q);
+- }
++ /* binmap is accurate (except for bin 1 == unsorted_chunks) */
++ if (i >= 2) {
++ binbit = get_binmap(av,i);
++ empty = last(b) == b;
++ if (!binbit)
++ assert(empty);
++ else if (!empty)
++ assert(binbit);
++ }
++
++ for (p = last(b); p != b; p = p->bk) {
++ /* each chunk claims to be free */
++ __do_check_free_chunk(p);
++ size = chunksize(p);
++ total += size;
++ if (i >= 2) {
++ /* chunk belongs in bin */
++ idx = bin_index(size);
++ assert(idx == i);
++ /* lists are sorted */
++ if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
++ assert(p->bk == b ||
++ (unsigned long)chunksize(p->bk) >=
++ (unsigned long)chunksize(p));
++ }
++ }
++ /* chunk is followed by a legal chain of inuse chunks */
++ for (q = next_chunk(p);
++ (q != av->top && inuse(q) &&
++ (unsigned long)(chunksize(q)) >= MINSIZE);
++ q = next_chunk(q))
++ __do_check_inuse_chunk(q);
++ }
+ }
+
+ /* top chunk is OK */
+@@ -326,13 +323,13 @@ void __do_check_malloc_state(void)
+ assert(av->n_mmaps <= av->max_n_mmaps);
+
+ assert((unsigned long)(av->sbrked_mem) <=
+- (unsigned long)(av->max_sbrked_mem));
++ (unsigned long)(av->max_sbrked_mem));
+
+ assert((unsigned long)(av->mmapped_mem) <=
+- (unsigned long)(av->max_mmapped_mem));
++ (unsigned long)(av->max_mmapped_mem));
+
+ assert((unsigned long)(av->max_total_mem) >=
+- (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem));
++ (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem));
+ }
+ #endif
+
+@@ -370,84 +367,84 @@ static void* __malloc_alloc(size_t nb, m
+ size_t pagemask = av->pagesize - 1;
+
+ /*
+- If there is space available in fastbins, consolidate and retry
+- malloc from scratch rather than getting memory from system. This
+- can occur only if nb is in smallbin range so we didn't consolidate
+- upon entry to malloc. It is much easier to handle this case here
+- than in malloc proper.
+- */
++ If there is space available in fastbins, consolidate and retry
++ malloc from scratch rather than getting memory from system. This
++ can occur only if nb is in smallbin range so we didn't consolidate
++ upon entry to malloc. It is much easier to handle this case here
++ than in malloc proper.
++ */
+
+ if (have_fastchunks(av)) {
+- assert(in_smallbin_range(nb));
+- __malloc_consolidate(av);
+- return malloc(nb - MALLOC_ALIGN_MASK);
++ assert(in_smallbin_range(nb));
++ __malloc_consolidate(av);
++ return malloc(nb - MALLOC_ALIGN_MASK);
+ }
+
+
+ /*
+- If have mmap, and the request size meets the mmap threshold, and
+- the system supports mmap, and there are few enough currently
+- allocated mmapped regions, try to directly map this request
+- rather than expanding top.
+- */
++ If have mmap, and the request size meets the mmap threshold, and
++ the system supports mmap, and there are few enough currently
++ allocated mmapped regions, try to directly map this request
++ rather than expanding top.
++ */
+
+ if ((unsigned long)(nb) >= (unsigned long)(av->mmap_threshold) &&
+ (av->n_mmaps < av->n_mmaps_max)) {
+
+- char* mm; /* return value from mmap call*/
+-
+- /*
+- Round up size to nearest page. For mmapped chunks, the overhead
+- is one (sizeof(size_t)) unit larger than for normal chunks, because there
+- is no following chunk whose prev_size field could be used.
+- */
+- size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
+-
+- /* Don't try if size wraps around 0 */
+- if ((unsigned long)(size) > (unsigned long)(nb)) {
+-
+- mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
+-
+- if (mm != (char*)(MORECORE_FAILURE)) {
++ char* mm; /* return value from mmap call*/
+
+ /*
+- The offset to the start of the mmapped region is stored
+- in the prev_size field of the chunk. This allows us to adjust
+- returned start address to meet alignment requirements here
+- and in memalign(), and still be able to compute proper
+- address argument for later munmap in free() and realloc().
+- */
+-
+- front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK;
+- if (front_misalign > 0) {
+- correction = MALLOC_ALIGNMENT - front_misalign;
+- p = (mchunkptr)(mm + correction);
+- p->prev_size = correction;
+- set_head(p, (size - correction) |IS_MMAPPED);
+- }
+- else {
+- p = (mchunkptr)mm;
+- p->prev_size = 0;
+- set_head(p, size|IS_MMAPPED);
+- }
++ Round up size to nearest page. For mmapped chunks, the overhead
++ is one (sizeof(size_t)) unit larger than for normal chunks, because there
++ is no following chunk whose prev_size field could be used.
++ */
++ size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
++
++ /* Don't try if size wraps around 0 */
++ if ((unsigned long)(size) > (unsigned long)(nb)) {
++
++ mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
++
++ if (mm != (char*)(MORECORE_FAILURE)) {
++
++ /*
++ The offset to the start of the mmapped region is stored
++ in the prev_size field of the chunk. This allows us to adjust
++ returned start address to meet alignment requirements here
++ and in memalign(), and still be able to compute proper
++ address argument for later munmap in free() and realloc().
++ */
++
++ front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK;
++ if (front_misalign > 0) {
++ correction = MALLOC_ALIGNMENT - front_misalign;
++ p = (mchunkptr)(mm + correction);
++ p->prev_size = correction;
++ set_head(p, (size - correction) |IS_MMAPPED);
++ }
++ else {
++ p = (mchunkptr)mm;
++ p->prev_size = 0;
++ set_head(p, size|IS_MMAPPED);
++ }
++
++ /* update statistics */
++
++ if (++av->n_mmaps > av->max_n_mmaps)
++ av->max_n_mmaps = av->n_mmaps;
++
++ sum = av->mmapped_mem += size;
++ if (sum > (unsigned long)(av->max_mmapped_mem))
++ av->max_mmapped_mem = sum;
++ sum += av->sbrked_mem;
++ if (sum > (unsigned long)(av->max_total_mem))
++ av->max_total_mem = sum;
+
+- /* update statistics */
++ check_chunk(p);
+
+- if (++av->n_mmaps > av->max_n_mmaps)
+- av->max_n_mmaps = av->n_mmaps;
+-
+- sum = av->mmapped_mem += size;
+- if (sum > (unsigned long)(av->max_mmapped_mem))
+- av->max_mmapped_mem = sum;
+- sum += av->sbrked_mem;
+- if (sum > (unsigned long)(av->max_total_mem))
+- av->max_total_mem = sum;
+-
+- check_chunk(p);
+-
+- return chunk2mem(p);
+- }
+- }
++ return chunk2mem(p);
++ }
++ }
+ }
+
+ /* Record incoming configuration of top */
+@@ -462,8 +459,8 @@ static void* __malloc_alloc(size_t nb, m
+ * be at least MINSIZE and to have prev_inuse set. */
+
+ assert((old_top == initial_top(av) && old_size == 0) ||
+- ((unsigned long) (old_size) >= MINSIZE &&
+- prev_inuse(old_top)));
++ ((unsigned long) (old_size) >= MINSIZE &&
++ prev_inuse(old_top)));
+
+ /* Precondition: not enough current space to satisfy nb request */
+ assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE));
+@@ -477,272 +474,272 @@ static void* __malloc_alloc(size_t nb, m
+ size = nb + av->top_pad + MINSIZE;
+
+ /*
+- If contiguous, we can subtract out existing space that we hope to
+- combine with new space. We add it back later only if
+- we don't actually get contiguous space.
+- */
++ If contiguous, we can subtract out existing space that we hope to
++ combine with new space. We add it back later only if
++ we don't actually get contiguous space.
++ */
+
+ if (contiguous(av))
+- size -= old_size;
++ size -= old_size;
+
+ /*
+- Round to a multiple of page size.
+- If MORECORE is not contiguous, this ensures that we only call it
+- with whole-page arguments. And if MORECORE is contiguous and
+- this is not first time through, this preserves page-alignment of
+- previous calls. Otherwise, we correct to page-align below.
+- */
++ Round to a multiple of page size.
++ If MORECORE is not contiguous, this ensures that we only call it
++ with whole-page arguments. And if MORECORE is contiguous and
++ this is not first time through, this preserves page-alignment of
++ previous calls. Otherwise, we correct to page-align below.
++ */
+
+ size = (size + pagemask) & ~pagemask;
+
+ /*
+- Don't try to call MORECORE if argument is so big as to appear
+- negative. Note that since mmap takes size_t arg, it may succeed
+- below even if we cannot call MORECORE.
+- */
++ Don't try to call MORECORE if argument is so big as to appear
++ negative. Note that since mmap takes size_t arg, it may succeed
++ below even if we cannot call MORECORE.
++ */
+
+ if (size > 0)
+- brk = (char*)(MORECORE(size));
++ brk = (char*)(MORECORE(size));
+
+ /*
+- If have mmap, try using it as a backup when MORECORE fails or
+- cannot be used. This is worth doing on systems that have "holes" in
+- address space, so sbrk cannot extend to give contiguous space, but
+- space is available elsewhere. Note that we ignore mmap max count
+- and threshold limits, since the space will not be used as a
+- segregated mmap region.
+- */
++ If have mmap, try using it as a backup when MORECORE fails or
++ cannot be used. This is worth doing on systems that have "holes" in
++ address space, so sbrk cannot extend to give contiguous space, but
++ space is available elsewhere. Note that we ignore mmap max count
++ and threshold limits, since the space will not be used as a
++ segregated mmap region.
++ */
+
+ if (brk == (char*)(MORECORE_FAILURE)) {
+
+- /* Cannot merge with old top, so add its size back in */
+- if (contiguous(av))
+- size = (size + old_size + pagemask) & ~pagemask;
+-
+- /* If we are relying on mmap as backup, then use larger units */
+- if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE))
+- size = MMAP_AS_MORECORE_SIZE;
+-
+- /* Don't try if size wraps around 0 */
+- if ((unsigned long)(size) > (unsigned long)(nb)) {
+-
+- brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
+-
+- if (brk != (char*)(MORECORE_FAILURE)) {
+-
+- /* We do not need, and cannot use, another sbrk call to find end */
+- snd_brk = brk + size;
+-
+- /* Record that we no longer have a contiguous sbrk region.
+- After the first time mmap is used as backup, we do not
+- ever rely on contiguous space since this could incorrectly
+- bridge regions.
+- */
+- set_noncontiguous(av);
+- }
+- }
++ /* Cannot merge with old top, so add its size back in */
++ if (contiguous(av))
++ size = (size + old_size + pagemask) & ~pagemask;
++
++ /* If we are relying on mmap as backup, then use larger units */
++ if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE))
++ size = MMAP_AS_MORECORE_SIZE;
++
++ /* Don't try if size wraps around 0 */
++ if ((unsigned long)(size) > (unsigned long)(nb)) {
++
++ brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
++
++ if (brk != (char*)(MORECORE_FAILURE)) {
++
++ /* We do not need, and cannot use, another sbrk call to find end */
++ snd_brk = brk + size;
++
++ /* Record that we no longer have a contiguous sbrk region.
++ After the first time mmap is used as backup, we do not
++ ever rely on contiguous space since this could incorrectly
++ bridge regions.
++ */
++ set_noncontiguous(av);
++ }
++ }
+ }
+
+ if (brk != (char*)(MORECORE_FAILURE)) {
+- av->sbrked_mem += size;
++ av->sbrked_mem += size;
+
+- /*
+- If MORECORE extends previous space, we can likewise extend top size.
+- */
+-
+- if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
+- set_head(old_top, (size + old_size) | PREV_INUSE);
+- }
+-
+- /*
+- Otherwise, make adjustments:
+-
+- * If the first time through or noncontiguous, we need to call sbrk
+- just to find out where the end of memory lies.
+-
+- * We need to ensure that all returned chunks from malloc will meet
+- MALLOC_ALIGNMENT
+-
+- * If there was an intervening foreign sbrk, we need to adjust sbrk
+- request size to account for fact that we will not be able to
+- combine new space with existing space in old_top.
+-
+- * Almost all systems internally allocate whole pages at a time, in
+- which case we might as well use the whole last page of request.
+- So we allocate enough more memory to hit a page boundary now,
+- which in turn causes future contiguous calls to page-align.
+- */
+-
+- else {
+- front_misalign = 0;
+- end_misalign = 0;
+- correction = 0;
+- aligned_brk = brk;
+-
+- /*
+- If MORECORE returns an address lower than we have seen before,
+- we know it isn't really contiguous. This and some subsequent
+- checks help cope with non-conforming MORECORE functions and
+- the presence of "foreign" calls to MORECORE from outside of
+- malloc or by other threads. We cannot guarantee to detect
+- these in all cases, but cope with the ones we do detect.
+- */
+- if (contiguous(av) && old_size != 0 && brk < old_end) {
+- set_noncontiguous(av);
+- }
+-
+- /* handle contiguous cases */
+- if (contiguous(av)) {
+-
+- /* We can tolerate forward non-contiguities here (usually due
+- to foreign calls) but treat them as part of our space for
+- stats reporting. */
+- if (old_size != 0)
+- av->sbrked_mem += brk - old_end;
+-
+- /* Guarantee alignment of first new chunk made from this space */
+-
+- front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK;
+- if (front_misalign > 0) {
+-
+- /*
+- Skip over some bytes to arrive at an aligned position.
+- We don't need to specially mark these wasted front bytes.
+- They will never be accessed anyway because
+- prev_inuse of av->top (and any chunk created from its start)
+- is always true after initialization.
+- */
++ /*
++ If MORECORE extends previous space, we can likewise extend top size.
++ */
+
+- correction = MALLOC_ALIGNMENT - front_misalign;
+- aligned_brk += correction;
++ if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
++ set_head(old_top, (size + old_size) | PREV_INUSE);
+ }
+
+ /*
+- If this isn't adjacent to existing space, then we will not
+- be able to merge with old_top space, so must add to 2nd request.
+- */
+-
+- correction += old_size;
+-
+- /* Extend the end address to hit a page boundary */
+- end_misalign = (size_t)(brk + size + correction);
+- correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
+-
+- assert(correction >= 0);
+- snd_brk = (char*)(MORECORE(correction));
+-
+- if (snd_brk == (char*)(MORECORE_FAILURE)) {
+- /*
+- If can't allocate correction, try to at least find out current
+- brk. It might be enough to proceed without failing.
+- */
+- correction = 0;
+- snd_brk = (char*)(MORECORE(0));
+- }
+- else if (snd_brk < brk) {
+- /*
+- If the second call gives noncontiguous space even though
+- it says it won't, the only course of action is to ignore
+- results of second call, and conservatively estimate where
+- the first call left us. Also set noncontiguous, so this
+- won't happen again, leaving at most one hole.
+-
+- Note that this check is intrinsically incomplete. Because
+- MORECORE is allowed to give more space than we ask for,
+- there is no reliable way to detect a noncontiguity
+- producing a forward gap for the second call.
+- */
+- snd_brk = brk + size;
+- correction = 0;
+- set_noncontiguous(av);
+- }
+-
+- }
+-
+- /* handle non-contiguous cases */
+- else {
+- /* MORECORE/mmap must correctly align */
+- assert(aligned_OK(chunk2mem(brk)));
+-
+- /* Find out current end of memory */
+- if (snd_brk == (char*)(MORECORE_FAILURE)) {
+- snd_brk = (char*)(MORECORE(0));
+- av->sbrked_mem += snd_brk - brk - size;
+- }
+- }
+-
+- /* Adjust top based on results of second sbrk */
+- if (snd_brk != (char*)(MORECORE_FAILURE)) {
+- av->top = (mchunkptr)aligned_brk;
+- set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
+- av->sbrked_mem += correction;
++ Otherwise, make adjustments:
+
+- /*
+- If not the first time through, we either have a
+- gap due to foreign sbrk or a non-contiguous region. Insert a
+- double fencepost at old_top to prevent consolidation with space
+- we don't own. These fenceposts are artificial chunks that are
+- marked as inuse and are in any case too small to use. We need
+- two to make sizes and alignments work out.
+- */
+-
+- if (old_size != 0) {
+- /* Shrink old_top to insert fenceposts, keeping size a
+- multiple of MALLOC_ALIGNMENT. We know there is at least
+- enough space in old_top to do this.
+- */
+- old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK;
+- set_head(old_top, old_size | PREV_INUSE);
+-
+- /*
+- Note that the following assignments completely overwrite
+- old_top when old_size was previously MINSIZE. This is
+- intentional. We need the fencepost, even if old_top otherwise gets
+- lost.
+- */
+- chunk_at_offset(old_top, old_size )->size =
+- (sizeof(size_t))|PREV_INUSE;
+-
+- chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size =
+- (sizeof(size_t))|PREV_INUSE;
+-
+- /* If possible, release the rest, suppressing trimming. */
+- if (old_size >= MINSIZE) {
+- size_t tt = av->trim_threshold;
+- av->trim_threshold = (size_t)(-1);
+- free(chunk2mem(old_top));
+- av->trim_threshold = tt;
+- }
+- }
+- }
+- }
+-
+- /* Update statistics */
+- sum = av->sbrked_mem;
+- if (sum > (unsigned long)(av->max_sbrked_mem))
+- av->max_sbrked_mem = sum;
+-
+- sum += av->mmapped_mem;
+- if (sum > (unsigned long)(av->max_total_mem))
+- av->max_total_mem = sum;
+-
+- check_malloc_state();
+-
+- /* finally, do the allocation */
+-
+- p = av->top;
+- size = chunksize(p);
+-
+- /* check that one of the above allocation paths succeeded */
+- if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
+- remainder_size = size - nb;
+- remainder = chunk_at_offset(p, nb);
+- av->top = remainder;
+- set_head(p, nb | PREV_INUSE);
+- set_head(remainder, remainder_size | PREV_INUSE);
+- check_malloced_chunk(p, nb);
+- return chunk2mem(p);
+- }
++ * If the first time through or noncontiguous, we need to call sbrk
++ just to find out where the end of memory lies.
++
++ * We need to ensure that all returned chunks from malloc will meet
++ MALLOC_ALIGNMENT
++
++ * If there was an intervening foreign sbrk, we need to adjust sbrk
++ request size to account for fact that we will not be able to
++ combine new space with existing space in old_top.
++
++ * Almost all systems internally allocate whole pages at a time, in
++ which case we might as well use the whole last page of request.
++ So we allocate enough more memory to hit a page boundary now,
++ which in turn causes future contiguous calls to page-align.
++ */
++
++ else {
++ front_misalign = 0;
++ end_misalign = 0;
++ correction = 0;
++ aligned_brk = brk;
++
++ /*
++ If MORECORE returns an address lower than we have seen before,
++ we know it isn't really contiguous. This and some subsequent
++ checks help cope with non-conforming MORECORE functions and
++ the presence of "foreign" calls to MORECORE from outside of
++ malloc or by other threads. We cannot guarantee to detect
++ these in all cases, but cope with the ones we do detect.
++ */
++ if (contiguous(av) && old_size != 0 && brk < old_end) {
++ set_noncontiguous(av);
++ }
++
++ /* handle contiguous cases */
++ if (contiguous(av)) {
++
++ /* We can tolerate forward non-contiguities here (usually due
++ to foreign calls) but treat them as part of our space for
++ stats reporting. */
++ if (old_size != 0)
++ av->sbrked_mem += brk - old_end;
++
++ /* Guarantee alignment of first new chunk made from this space */
++
++ front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK;
++ if (front_misalign > 0) {
++
++ /*
++ Skip over some bytes to arrive at an aligned position.
++ We don't need to specially mark these wasted front bytes.
++ They will never be accessed anyway because
++ prev_inuse of av->top (and any chunk created from its start)
++ is always true after initialization.
++ */
++
++ correction = MALLOC_ALIGNMENT - front_misalign;
++ aligned_brk += correction;
++ }
++
++ /*
++ If this isn't adjacent to existing space, then we will not
++ be able to merge with old_top space, so must add to 2nd request.
++ */
++
++ correction += old_size;
++
++ /* Extend the end address to hit a page boundary */
++ end_misalign = (size_t)(brk + size + correction);
++ correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
++
++ assert(correction >= 0);
++ snd_brk = (char*)(MORECORE(correction));
++
++ if (snd_brk == (char*)(MORECORE_FAILURE)) {
++ /*
++ If can't allocate correction, try to at least find out current
++ brk. It might be enough to proceed without failing.
++ */
++ correction = 0;
++ snd_brk = (char*)(MORECORE(0));
++ }
++ else if (snd_brk < brk) {
++ /*
++ If the second call gives noncontiguous space even though
++ it says it won't, the only course of action is to ignore
++ results of second call, and conservatively estimate where
++ the first call left us. Also set noncontiguous, so this
++ won't happen again, leaving at most one hole.
++
++ Note that this check is intrinsically incomplete. Because
++ MORECORE is allowed to give more space than we ask for,
++ there is no reliable way to detect a noncontiguity
++ producing a forward gap for the second call.
++ */
++ snd_brk = brk + size;
++ correction = 0;
++ set_noncontiguous(av);
++ }
++
++ }
++
++ /* handle non-contiguous cases */
++ else {
++ /* MORECORE/mmap must correctly align */
++ assert(aligned_OK(chunk2mem(brk)));
++
++ /* Find out current end of memory */
++ if (snd_brk == (char*)(MORECORE_FAILURE)) {
++ snd_brk = (char*)(MORECORE(0));
++ av->sbrked_mem += snd_brk - brk - size;
++ }
++ }
++
++ /* Adjust top based on results of second sbrk */
++ if (snd_brk != (char*)(MORECORE_FAILURE)) {
++ av->top = (mchunkptr)aligned_brk;
++ set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
++ av->sbrked_mem += correction;
++
++ /*
++ If not the first time through, we either have a
++ gap due to foreign sbrk or a non-contiguous region. Insert a
++ double fencepost at old_top to prevent consolidation with space
++ we don't own. These fenceposts are artificial chunks that are
++ marked as inuse and are in any case too small to use. We need
++ two to make sizes and alignments work out.
++ */
++
++ if (old_size != 0) {
++ /* Shrink old_top to insert fenceposts, keeping size a
++ multiple of MALLOC_ALIGNMENT. We know there is at least
++ enough space in old_top to do this.
++ */
++ old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK;
++ set_head(old_top, old_size | PREV_INUSE);
++
++ /*
++ Note that the following assignments completely overwrite
++ old_top when old_size was previously MINSIZE. This is
++ intentional. We need the fencepost, even if old_top otherwise gets
++ lost.
++ */
++ chunk_at_offset(old_top, old_size )->size =
++ (sizeof(size_t))|PREV_INUSE;
++
++ chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size =
++ (sizeof(size_t))|PREV_INUSE;
++
++ /* If possible, release the rest, suppressing trimming. */
++ if (old_size >= MINSIZE) {
++ size_t tt = av->trim_threshold;
++ av->trim_threshold = (size_t)(-1);
++ free(chunk2mem(old_top));
++ av->trim_threshold = tt;
++ }
++ }
++ }
++ }
++
++ /* Update statistics */
++ sum = av->sbrked_mem;
++ if (sum > (unsigned long)(av->max_sbrked_mem))
++ av->max_sbrked_mem = sum;
++
++ sum += av->mmapped_mem;
++ if (sum > (unsigned long)(av->max_total_mem))
++ av->max_total_mem = sum;
++
++ check_malloc_state();
++
++ /* finally, do the allocation */
++
++ p = av->top;
++ size = chunksize(p);
++
++ /* check that one of the above allocation paths succeeded */
++ if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
++ remainder_size = size - nb;
++ remainder = chunk_at_offset(p, nb);
++ av->top = remainder;
++ set_head(p, nb | PREV_INUSE);
++ set_head(remainder, remainder_size | PREV_INUSE);
++ check_malloced_chunk(p, nb);
++ return chunk2mem(p);
++ }
+
+ }
+
+@@ -767,25 +764,25 @@ static int __malloc_largebin_index(unsig
+ #if defined(__GNUC__) && defined(i386)
+
+ __asm__("bsrl %1,%0\n\t"
+- : "=r" (m)
+- : "g" (x));
++ : "=r" (m)
++ : "g" (x));
+
+ #else
+ {
+- /*
+- Based on branch-free nlz algorithm in chapter 5 of Henry
+- S. Warren Jr's book "Hacker's Delight".
+- */
+-
+- unsigned int n = ((x - 0x100) >> 16) & 8;
+- x <<= n;
+- m = ((x - 0x1000) >> 16) & 4;
+- n += m;
+- x <<= m;
+- m = ((x - 0x4000) >> 16) & 2;
+- n += m;
+- x = (x << m) >> 14;
+- m = 13 - n + (x & ~(x>>1));
++ /*
++ Based on branch-free nlz algorithm in chapter 5 of Henry
++ S. Warren Jr's book "Hacker's Delight".
++ */
++
++ unsigned int n = ((x - 0x100) >> 16) & 8;
++ x <<= n;
++ m = ((x - 0x1000) >> 16) & 4;
++ n += m;
++ x <<= m;
++ m = ((x - 0x4000) >> 16) & 2;
++ n += m;
++ x = (x << m) >> 14;
++ m = 13 - n + (x & ~(x>>1));
+ }
+ #endif
+
+@@ -826,69 +823,70 @@ void* malloc(size_t bytes)
+ mchunkptr fwd; /* misc temp for linking */
+ mchunkptr bck; /* misc temp for linking */
+ void * sysmem;
++ void * retval;
+
+ #if !defined(__MALLOC_GLIBC_COMPAT__)
+ if (!bytes) return NULL;
+ #endif
+
+- LOCK;
++ __MALLOC_LOCK;
+ av = get_malloc_state();
+ /*
+- Convert request size to internal form by adding (sizeof(size_t)) bytes
+- overhead plus possibly more to obtain necessary alignment and/or
+- to obtain a size of at least MINSIZE, the smallest allocatable
+- size. Also, checked_request2size traps (returning 0) request sizes
+- that are so large that they wrap around zero when padded and
+- aligned.
+- */
++ Convert request size to internal form by adding (sizeof(size_t)) bytes
++ overhead plus possibly more to obtain necessary alignment and/or
++ to obtain a size of at least MINSIZE, the smallest allocatable
++ size. Also, checked_request2size traps (returning 0) request sizes
++ that are so large that they wrap around zero when padded and
++ aligned.
++ */
+
+ checked_request2size(bytes, nb);
+
+ /*
+- Bypass search if no frees yet
+- */
++ Bypass search if no frees yet
++ */
+ if (!have_anychunks(av)) {
+- if (av->max_fast == 0) /* initialization check */
+- __malloc_consolidate(av);
+- goto use_top;
++ if (av->max_fast == 0) /* initialization check */
++ __malloc_consolidate(av);
++ goto use_top;
+ }
+
+ /*
+- If the size qualifies as a fastbin, first check corresponding bin.
+- */
++ If the size qualifies as a fastbin, first check corresponding bin.
++ */
+
+ if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) {
+- fb = &(av->fastbins[(fastbin_index(nb))]);
+- if ( (victim = *fb) != 0) {
+- *fb = victim->fd;
+- check_remalloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
++ fb = &(av->fastbins[(fastbin_index(nb))]);
++ if ( (victim = *fb) != 0) {
++ *fb = victim->fd;
++ check_remalloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
+ }
+
+ /*
+- If a small request, check regular bin. Since these "smallbins"
+- hold one size each, no searching within bins is necessary.
+- (For a large request, we need to wait until unsorted chunks are
+- processed to find best fit. But for small ones, fits are exact
+- anyway, so we can check now, which is faster.)
+- */
++ If a small request, check regular bin. Since these "smallbins"
++ hold one size each, no searching within bins is necessary.
++ (For a large request, we need to wait until unsorted chunks are
++ processed to find best fit. But for small ones, fits are exact
++ anyway, so we can check now, which is faster.)
++ */
+
+ if (in_smallbin_range(nb)) {
+- idx = smallbin_index(nb);
+- bin = bin_at(av,idx);
++ idx = smallbin_index(nb);
++ bin = bin_at(av,idx);
+
+- if ( (victim = last(bin)) != bin) {
+- bck = victim->bk;
+- set_inuse_bit_at_offset(victim, nb);
+- bin->bk = bck;
+- bck->fd = bin;
+-
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
++ if ( (victim = last(bin)) != bin) {
++ bck = victim->bk;
++ set_inuse_bit_at_offset(victim, nb);
++ bin->bk = bck;
++ bck->fd = bin;
++
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
+ }
+
+ /* If this is a large request, consolidate fastbins before continuing.
+@@ -899,154 +897,154 @@ void* malloc(size_t bytes)
+ large requests, but less often mixtures, so consolidation is not
+ invoked all that often in most programs. And the programs that
+ it is called frequently in otherwise tend to fragment.
+- */
++ */
+
+ else {
+- idx = __malloc_largebin_index(nb);
+- if (have_fastchunks(av))
+- __malloc_consolidate(av);
++ idx = __malloc_largebin_index(nb);
++ if (have_fastchunks(av))
++ __malloc_consolidate(av);
+ }
+
+ /*
+- Process recently freed or remaindered chunks, taking one only if
+- it is exact fit, or, if this a small request, the chunk is remainder from
+- the most recent non-exact fit. Place other traversed chunks in
+- bins. Note that this step is the only place in any routine where
+- chunks are placed in bins.
+- */
++ Process recently freed or remaindered chunks, taking one only if
++ it is exact fit, or, if this a small request, the chunk is remainder from
++ the most recent non-exact fit. Place other traversed chunks in
++ bins. Note that this step is the only place in any routine where
++ chunks are placed in bins.
++ */
+
+ while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
+- bck = victim->bk;
+- size = chunksize(victim);
++ bck = victim->bk;
++ size = chunksize(victim);
++
++ /* If a small request, try to use last remainder if it is the
++ only chunk in unsorted bin. This helps promote locality for
++ runs of consecutive small requests. This is the only
++ exception to best-fit, and applies only when there is
++ no exact fit for a small chunk.
++ */
++
++ if (in_smallbin_range(nb) &&
++ bck == unsorted_chunks(av) &&
++ victim == av->last_remainder &&
++ (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
++
++ /* split and reattach remainder */
++ remainder_size = size - nb;
++ remainder = chunk_at_offset(victim, nb);
++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
++ av->last_remainder = remainder;
++ remainder->bk = remainder->fd = unsorted_chunks(av);
++
++ set_head(victim, nb | PREV_INUSE);
++ set_head(remainder, remainder_size | PREV_INUSE);
++ set_foot(remainder, remainder_size);
++
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
++
++ /* remove from unsorted list */
++ unsorted_chunks(av)->bk = bck;
++ bck->fd = unsorted_chunks(av);
++
++ /* Take now instead of binning if exact fit */
++
++ if (size == nb) {
++ set_inuse_bit_at_offset(victim, size);
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
++
++ /* place chunk in bin */
+
+- /* If a small request, try to use last remainder if it is the
+- only chunk in unsorted bin. This helps promote locality for
+- runs of consecutive small requests. This is the only
+- exception to best-fit, and applies only when there is
+- no exact fit for a small chunk.
+- */
+-
+- if (in_smallbin_range(nb) &&
+- bck == unsorted_chunks(av) &&
+- victim == av->last_remainder &&
+- (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
+-
+- /* split and reattach remainder */
+- remainder_size = size - nb;
+- remainder = chunk_at_offset(victim, nb);
+- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+- av->last_remainder = remainder;
+- remainder->bk = remainder->fd = unsorted_chunks(av);
+-
+- set_head(victim, nb | PREV_INUSE);
+- set_head(remainder, remainder_size | PREV_INUSE);
+- set_foot(remainder, remainder_size);
+-
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
+-
+- /* remove from unsorted list */
+- unsorted_chunks(av)->bk = bck;
+- bck->fd = unsorted_chunks(av);
+-
+- /* Take now instead of binning if exact fit */
+-
+- if (size == nb) {
+- set_inuse_bit_at_offset(victim, size);
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
+-
+- /* place chunk in bin */
+-
+- if (in_smallbin_range(size)) {
+- victim_index = smallbin_index(size);
+- bck = bin_at(av, victim_index);
+- fwd = bck->fd;
+- }
+- else {
+- victim_index = __malloc_largebin_index(size);
+- bck = bin_at(av, victim_index);
+- fwd = bck->fd;
+-
+- if (fwd != bck) {
+- /* if smaller than smallest, place first */
+- if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) {
+- fwd = bck;
+- bck = bck->bk;
+- }
+- else if ((unsigned long)(size) >=
+- (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
+-
+- /* maintain large bins in sorted order */
+- size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */
+- while ((unsigned long)(size) < (unsigned long)(fwd->size))
+- fwd = fwd->fd;
+- bck = fwd->bk;
+- }
+- }
+- }
+-
+- mark_bin(av, victim_index);
+- victim->bk = bck;
+- victim->fd = fwd;
+- fwd->bk = victim;
+- bck->fd = victim;
++ if (in_smallbin_range(size)) {
++ victim_index = smallbin_index(size);
++ bck = bin_at(av, victim_index);
++ fwd = bck->fd;
++ }
++ else {
++ victim_index = __malloc_largebin_index(size);
++ bck = bin_at(av, victim_index);
++ fwd = bck->fd;
++
++ if (fwd != bck) {
++ /* if smaller than smallest, place first */
++ if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) {
++ fwd = bck;
++ bck = bck->bk;
++ }
++ else if ((unsigned long)(size) >=
++ (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
++
++ /* maintain large bins in sorted order */
++ size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */
++ while ((unsigned long)(size) < (unsigned long)(fwd->size))
++ fwd = fwd->fd;
++ bck = fwd->bk;
++ }
++ }
++ }
++
++ mark_bin(av, victim_index);
++ victim->bk = bck;
++ victim->fd = fwd;
++ fwd->bk = victim;
++ bck->fd = victim;
+ }
+
+ /*
+- If a large request, scan through the chunks of current bin to
+- find one that fits. (This will be the smallest that fits unless
+- FIRST_SORTED_BIN_SIZE has been changed from default.) This is
+- the only step where an unbounded number of chunks might be
+- scanned without doing anything useful with them. However the
+- lists tend to be short.
+- */
++ If a large request, scan through the chunks of current bin to
++ find one that fits. (This will be the smallest that fits unless
++ FIRST_SORTED_BIN_SIZE has been changed from default.) This is
++ the only step where an unbounded number of chunks might be
++ scanned without doing anything useful with them. However the
++ lists tend to be short.
++ */
+
+ if (!in_smallbin_range(nb)) {
+- bin = bin_at(av, idx);
+-
+- for (victim = last(bin); victim != bin; victim = victim->bk) {
+- size = chunksize(victim);
++ bin = bin_at(av, idx);
+
+- if ((unsigned long)(size) >= (unsigned long)(nb)) {
+- remainder_size = size - nb;
+- unlink(victim, bck, fwd);
++ for (victim = last(bin); victim != bin; victim = victim->bk) {
++ size = chunksize(victim);
+
+- /* Exhaust */
+- if (remainder_size < MINSIZE) {
+- set_inuse_bit_at_offset(victim, size);
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
+- /* Split */
+- else {
+- remainder = chunk_at_offset(victim, nb);
+- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+- remainder->bk = remainder->fd = unsorted_chunks(av);
+- set_head(victim, nb | PREV_INUSE);
+- set_head(remainder, remainder_size | PREV_INUSE);
+- set_foot(remainder, remainder_size);
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
++ if ((unsigned long)(size) >= (unsigned long)(nb)) {
++ remainder_size = size - nb;
++ unlink(victim, bck, fwd);
++
++ /* Exhaust */
++ if (remainder_size < MINSIZE) {
++ set_inuse_bit_at_offset(victim, size);
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
++ /* Split */
++ else {
++ remainder = chunk_at_offset(victim, nb);
++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
++ remainder->bk = remainder->fd = unsorted_chunks(av);
++ set_head(victim, nb | PREV_INUSE);
++ set_head(remainder, remainder_size | PREV_INUSE);
++ set_foot(remainder, remainder_size);
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
++ }
+ }
+- }
+- }
+ }
+
+ /*
+- Search for a chunk by scanning bins, starting with next largest
+- bin. This search is strictly by best-fit; i.e., the smallest
+- (with ties going to approximately the least recently used) chunk
+- that fits is selected.
++ Search for a chunk by scanning bins, starting with next largest
++ bin. This search is strictly by best-fit; i.e., the smallest
++ (with ties going to approximately the least recently used) chunk
++ that fits is selected.
+
+- The bitmap avoids needing to check that most blocks are nonempty.
+- */
++ The bitmap avoids needing to check that most blocks are nonempty.
++ */
+
+ ++idx;
+ bin = bin_at(av,idx);
+@@ -1056,109 +1054,111 @@ void* malloc(size_t bytes)
+
+ for (;;) {
+
+- /* Skip rest of block if there are no more set bits in this block. */
+- if (bit > map || bit == 0) {
+- do {
+- if (++block >= BINMAPSIZE) /* out of bins */
+- goto use_top;
+- } while ( (map = av->binmap[block]) == 0);
+-
+- bin = bin_at(av, (block << BINMAPSHIFT));
+- bit = 1;
+- }
+-
+- /* Advance to bin with set bit. There must be one. */
+- while ((bit & map) == 0) {
+- bin = next_bin(bin);
+- bit <<= 1;
+- assert(bit != 0);
+- }
+-
+- /* Inspect the bin. It is likely to be non-empty */
+- victim = last(bin);
+-
+- /* If a false alarm (empty bin), clear the bit. */
+- if (victim == bin) {
+- av->binmap[block] = map &= ~bit; /* Write through */
+- bin = next_bin(bin);
+- bit <<= 1;
+- }
+-
+- else {
+- size = chunksize(victim);
+-
+- /* We know the first chunk in this bin is big enough to use. */
+- assert((unsigned long)(size) >= (unsigned long)(nb));
+-
+- remainder_size = size - nb;
+-
+- /* unlink */
+- bck = victim->bk;
+- bin->bk = bck;
+- bck->fd = bin;
+-
+- /* Exhaust */
+- if (remainder_size < MINSIZE) {
+- set_inuse_bit_at_offset(victim, size);
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
++ /* Skip rest of block if there are no more set bits in this block. */
++ if (bit > map || bit == 0) {
++ do {
++ if (++block >= BINMAPSIZE) /* out of bins */
++ goto use_top;
++ } while ( (map = av->binmap[block]) == 0);
+
+- /* Split */
+- else {
+- remainder = chunk_at_offset(victim, nb);
++ bin = bin_at(av, (block << BINMAPSHIFT));
++ bit = 1;
++ }
+
+- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+- remainder->bk = remainder->fd = unsorted_chunks(av);
+- /* advertise as last remainder */
+- if (in_smallbin_range(nb))
+- av->last_remainder = remainder;
++ /* Advance to bin with set bit. There must be one. */
++ while ((bit & map) == 0) {
++ bin = next_bin(bin);
++ bit <<= 1;
++ assert(bit != 0);
++ }
+
+- set_head(victim, nb | PREV_INUSE);
+- set_head(remainder, remainder_size | PREV_INUSE);
+- set_foot(remainder, remainder_size);
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
+- }
+- }
++ /* Inspect the bin. It is likely to be non-empty */
++ victim = last(bin);
++
++ /* If a false alarm (empty bin), clear the bit. */
++ if (victim == bin) {
++ av->binmap[block] = map &= ~bit; /* Write through */
++ bin = next_bin(bin);
++ bit <<= 1;
++ }
++
++ else {
++ size = chunksize(victim);
++
++ /* We know the first chunk in this bin is big enough to use. */
++ assert((unsigned long)(size) >= (unsigned long)(nb));
++
++ remainder_size = size - nb;
++
++ /* unlink */
++ bck = victim->bk;
++ bin->bk = bck;
++ bck->fd = bin;
++
++ /* Exhaust */
++ if (remainder_size < MINSIZE) {
++ set_inuse_bit_at_offset(victim, size);
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
++
++ /* Split */
++ else {
++ remainder = chunk_at_offset(victim, nb);
++
++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
++ remainder->bk = remainder->fd = unsorted_chunks(av);
++ /* advertise as last remainder */
++ if (in_smallbin_range(nb))
++ av->last_remainder = remainder;
++
++ set_head(victim, nb | PREV_INUSE);
++ set_head(remainder, remainder_size | PREV_INUSE);
++ set_foot(remainder, remainder_size);
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
++ }
++ }
+ }
+
+-use_top:
++ use_top:
+ /*
+- If large enough, split off the chunk bordering the end of memory
+- (held in av->top). Note that this is in accord with the best-fit
+- search rule. In effect, av->top is treated as larger (and thus
+- less well fitting) than any other available chunk since it can
+- be extended to be as large as necessary (up to system
+- limitations).
+-
+- We require that av->top always exists (i.e., has size >=
+- MINSIZE) after initialization, so if it would otherwise be
+- exhuasted by current request, it is replenished. (The main
+- reason for ensuring it exists is that we may need MINSIZE space
+- to put in fenceposts in sysmalloc.)
+- */
++ If large enough, split off the chunk bordering the end of memory
++ (held in av->top). Note that this is in accord with the best-fit
++ search rule. In effect, av->top is treated as larger (and thus
++ less well fitting) than any other available chunk since it can
++ be extended to be as large as necessary (up to system
++ limitations).
++
++ We require that av->top always exists (i.e., has size >=
++ MINSIZE) after initialization, so if it would otherwise be
++ exhuasted by current request, it is replenished. (The main
++ reason for ensuring it exists is that we may need MINSIZE space
++ to put in fenceposts in sysmalloc.)
++ */
+
+ victim = av->top;
+ size = chunksize(victim);
+
+ if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
+- remainder_size = size - nb;
+- remainder = chunk_at_offset(victim, nb);
+- av->top = remainder;
+- set_head(victim, nb | PREV_INUSE);
+- set_head(remainder, remainder_size | PREV_INUSE);
+-
+- check_malloced_chunk(victim, nb);
+- UNLOCK;
+- return chunk2mem(victim);
++ remainder_size = size - nb;
++ remainder = chunk_at_offset(victim, nb);
++ av->top = remainder;
++ set_head(victim, nb | PREV_INUSE);
++ set_head(remainder, remainder_size | PREV_INUSE);
++
++ check_malloced_chunk(victim, nb);
++ retval = chunk2mem(victim);
++ goto DONE;
+ }
+
+ /* If no space in top, relay to handle system-dependent cases */
+ sysmem = __malloc_alloc(nb, av);
+- UNLOCK;
+- return sysmem;
++ retval = sysmem;
++ DONE:
++ __MALLOC_UNLOCK;
++ return retval;
+ }
+
+diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h
+index fbc1492..14a0dd9 100644
+--- a/libc/stdlib/malloc-standard/malloc.h
++++ b/libc/stdlib/malloc-standard/malloc.h
+@@ -22,16 +22,12 @@
+ #include <malloc.h>
+ #include <stdlib.h>
+
++#include <bits/uClibc_mutex.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-extern pthread_mutex_t __malloc_lock;
+-# define LOCK __pthread_mutex_lock(&__malloc_lock)
+-# define UNLOCK __pthread_mutex_unlock(&__malloc_lock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++__UCLIBC_MUTEX_EXTERN(__malloc_lock);
++
++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
+
+
+
+diff --git a/libc/stdlib/malloc-standard/mallopt.c b/libc/stdlib/malloc-standard/mallopt.c
+index e287920..41aa614 100644
+--- a/libc/stdlib/malloc-standard/mallopt.c
++++ b/libc/stdlib/malloc-standard/mallopt.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -25,40 +25,40 @@ int mallopt(int param_number, int value)
+
+ ret = 0;
+
+- LOCK;
++ __MALLOC_LOCK;
+ av = get_malloc_state();
+ /* Ensure initialization/consolidation */
+ __malloc_consolidate(av);
+
+ switch(param_number) {
+- case M_MXFAST:
+- if (value >= 0 && value <= MAX_FAST_SIZE) {
+- set_max_fast(av, value);
+- ret = 1;
+- }
+- break;
+-
+- case M_TRIM_THRESHOLD:
+- av->trim_threshold = value;
+- ret = 1;
+- break;
+-
+- case M_TOP_PAD:
+- av->top_pad = value;
+- ret = 1;
+- break;
+-
+- case M_MMAP_THRESHOLD:
+- av->mmap_threshold = value;
+- ret = 1;
+- break;
+-
+- case M_MMAP_MAX:
+- av->n_mmaps_max = value;
+- ret = 1;
+- break;
++ case M_MXFAST:
++ if (value >= 0 && value <= MAX_FAST_SIZE) {
++ set_max_fast(av, value);
++ ret = 1;
++ }
++ break;
++
++ case M_TRIM_THRESHOLD:
++ av->trim_threshold = value;
++ ret = 1;
++ break;
++
++ case M_TOP_PAD:
++ av->top_pad = value;
++ ret = 1;
++ break;
++
++ case M_MMAP_THRESHOLD:
++ av->mmap_threshold = value;
++ ret = 1;
++ break;
++
++ case M_MMAP_MAX:
++ av->n_mmaps_max = value;
++ ret = 1;
++ break;
+ }
+- UNLOCK;
++ __MALLOC_UNLOCK;
+ return ret;
+ }
+
+diff --git a/libc/stdlib/malloc-standard/memalign.c b/libc/stdlib/malloc-standard/memalign.c
+index bd95362..e78d752 100644
+--- a/libc/stdlib/malloc-standard/memalign.c
++++ b/libc/stdlib/malloc-standard/memalign.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -35,6 +35,7 @@ void* memalign(size_t alignment, size_t
+ mchunkptr remainder; /* spare room at end to split off */
+ unsigned long remainder_size; /* its size */
+ size_t size;
++ void *retval;
+
+ /* If need less alignment than we give anyway, just relay to malloc */
+
+@@ -46,12 +47,12 @@ void* memalign(size_t alignment, size_t
+
+ /* Make sure alignment is power of 2 (in case MINSIZE is not). */
+ if ((alignment & (alignment - 1)) != 0) {
+- size_t a = MALLOC_ALIGNMENT * 2;
+- while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
+- alignment = a;
++ size_t a = MALLOC_ALIGNMENT * 2;
++ while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
++ alignment = a;
+ }
+
+- LOCK;
++ __MALLOC_LOCK;
+ checked_request2size(bytes, nb);
+
+ /* Strategy: find a spot within that chunk that meets the alignment
+@@ -63,64 +64,67 @@ void* memalign(size_t alignment, size_t
+ m = (char*)(malloc(nb + alignment + MINSIZE));
+
+ if (m == 0) {
+- UNLOCK;
+- return 0; /* propagate failure */
++ retval = 0; /* propagate failure */
++ goto DONE;
+ }
+
+ p = mem2chunk(m);
+
+ if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */
+
+- /*
+- Find an aligned spot inside chunk. Since we need to give back
+- leading space in a chunk of at least MINSIZE, if the first
+- calculation places us at a spot with less than MINSIZE leader,
+- we can move to the next aligned spot -- we've allocated enough
+- total room so that this is always possible.
+- */
+-
+- brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) &
+- -((signed long) alignment)));
+- if ((unsigned long)(brk - (char*)(p)) < MINSIZE)
+- brk += alignment;
+-
+- newp = (mchunkptr)brk;
+- leadsize = brk - (char*)(p);
+- newsize = chunksize(p) - leadsize;
+-
+- /* For mmapped chunks, just adjust offset */
+- if (chunk_is_mmapped(p)) {
+- newp->prev_size = p->prev_size + leadsize;
+- set_head(newp, newsize|IS_MMAPPED);
+- UNLOCK;
+- return chunk2mem(newp);
+- }
+-
+- /* Otherwise, give back leader, use the rest */
+- set_head(newp, newsize | PREV_INUSE);
+- set_inuse_bit_at_offset(newp, newsize);
+- set_head_size(p, leadsize);
+- free(chunk2mem(p));
+- p = newp;
++ /*
++ Find an aligned spot inside chunk. Since we need to give back
++ leading space in a chunk of at least MINSIZE, if the first
++ calculation places us at a spot with less than MINSIZE leader,
++ we can move to the next aligned spot -- we've allocated enough
++ total room so that this is always possible.
++ */
++
++ brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) &
++ -((signed long) alignment)));
++ if ((unsigned long)(brk - (char*)(p)) < MINSIZE)
++ brk += alignment;
++
++ newp = (mchunkptr)brk;
++ leadsize = brk - (char*)(p);
++ newsize = chunksize(p) - leadsize;
++
++ /* For mmapped chunks, just adjust offset */
++ if (chunk_is_mmapped(p)) {
++ newp->prev_size = p->prev_size + leadsize;
++ set_head(newp, newsize|IS_MMAPPED);
++ retval = chunk2mem(newp);
++ goto DONE;
++ }
++
++ /* Otherwise, give back leader, use the rest */
++ set_head(newp, newsize | PREV_INUSE);
++ set_inuse_bit_at_offset(newp, newsize);
++ set_head_size(p, leadsize);
++ free(chunk2mem(p));
++ p = newp;
+
+- assert (newsize >= nb &&
+- (((unsigned long)(chunk2mem(p))) % alignment) == 0);
++ assert (newsize >= nb &&
++ (((unsigned long)(chunk2mem(p))) % alignment) == 0);
+ }
+
+ /* Also give back spare room at the end */
+ if (!chunk_is_mmapped(p)) {
+- size = chunksize(p);
+- if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
+- remainder_size = size - nb;
+- remainder = chunk_at_offset(p, nb);
+- set_head(remainder, remainder_size | PREV_INUSE);
+- set_head_size(p, nb);
+- free(chunk2mem(remainder));
+- }
++ size = chunksize(p);
++ if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
++ remainder_size = size - nb;
++ remainder = chunk_at_offset(p, nb);
++ set_head(remainder, remainder_size | PREV_INUSE);
++ set_head_size(p, nb);
++ free(chunk2mem(remainder));
++ }
+ }
+
+ check_inuse_chunk(p);
+- UNLOCK;
+- return chunk2mem(p);
++ retval = chunk2mem(p);
++
++ DONE:
++ __MALLOC_UNLOCK;
++ return retval;
+ }
+
+diff --git a/libc/stdlib/malloc-standard/realloc.c b/libc/stdlib/malloc-standard/realloc.c
+index 1950130..9ca4b26 100644
+--- a/libc/stdlib/malloc-standard/realloc.c
++++ b/libc/stdlib/malloc-standard/realloc.c
+@@ -8,7 +8,7 @@
+ VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+ Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
+@@ -23,14 +23,14 @@ void* realloc(void* oldmem, size_t bytes
+ {
+ mstate av;
+
+- size_t nb; /* padded request size */
++ size_t nb; /* padded request size */
+
+ mchunkptr oldp; /* chunk corresponding to oldmem */
+- size_t oldsize; /* its size */
++ size_t oldsize; /* its size */
+
+ mchunkptr newp; /* chunk to return */
+- size_t newsize; /* its size */
+- void* newmem; /* corresponding user mem */
++ size_t newsize; /* its size */
++ void* newmem; /* corresponding user mem */
+
+ mchunkptr next; /* next contiguous chunk after oldp */
+
+@@ -40,21 +40,23 @@ void* realloc(void* oldmem, size_t bytes
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+
+- unsigned long copysize; /* bytes to copy */
++ unsigned long copysize; /* bytes to copy */
+ unsigned int ncopies; /* size_t words to copy */
+- size_t* s; /* copy source */
+- size_t* d; /* copy destination */
++ size_t* s; /* copy source */
++ size_t* d; /* copy destination */
++
++ void *retval;
+
+
+ /* Check for special cases. */
+ if (! oldmem)
+- return malloc(bytes);
++ return malloc(bytes);
+ if (! bytes) {
+- free (oldmem);
+- return malloc(bytes);
++ free (oldmem);
++ return malloc(bytes);
+ }
+
+- LOCK;
++ __MALLOC_LOCK;
+ av = get_malloc_state();
+ checked_request2size(bytes, nb);
+
+@@ -65,173 +67,176 @@ void* realloc(void* oldmem, size_t bytes
+
+ if (!chunk_is_mmapped(oldp)) {
+
+- if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
+- /* already big enough; split below */
+- newp = oldp;
+- newsize = oldsize;
+- }
+-
+- else {
+- next = chunk_at_offset(oldp, oldsize);
+-
+- /* Try to expand forward into top */
+- if (next == av->top &&
+- (unsigned long)(newsize = oldsize + chunksize(next)) >=
+- (unsigned long)(nb + MINSIZE)) {
+- set_head_size(oldp, nb);
+- av->top = chunk_at_offset(oldp, nb);
+- set_head(av->top, (newsize - nb) | PREV_INUSE);
+- UNLOCK;
+- return chunk2mem(oldp);
+- }
+-
+- /* Try to expand forward into next chunk; split off remainder below */
+- else if (next != av->top &&
+- !inuse(next) &&
+- (unsigned long)(newsize = oldsize + chunksize(next)) >=
+- (unsigned long)(nb)) {
+- newp = oldp;
+- unlink(next, bck, fwd);
+- }
+-
+- /* allocate, copy, free */
+- else {
+- newmem = malloc(nb - MALLOC_ALIGN_MASK);
+- if (newmem == 0) {
+- UNLOCK;
+- return 0; /* propagate failure */
+- }
+-
+- newp = mem2chunk(newmem);
+- newsize = chunksize(newp);
+-
+- /*
+- Avoid copy if newp is next chunk after oldp.
+- */
+- if (newp == next) {
+- newsize += oldsize;
+- newp = oldp;
++ if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
++ /* already big enough; split below */
++ newp = oldp;
++ newsize = oldsize;
+ }
++
+ else {
+- /*
+- Unroll copy of <= 36 bytes (72 if 8byte sizes)
+- We know that contents have an odd number of
+- size_t-sized words; minimally 3.
+- */
+-
+- copysize = oldsize - (sizeof(size_t));
+- s = (size_t*)(oldmem);
+- d = (size_t*)(newmem);
+- ncopies = copysize / sizeof(size_t);
+- assert(ncopies >= 3);
+-
+- if (ncopies > 9)
+- memcpy(d, s, copysize);
+-
+- else {
+- *(d+0) = *(s+0);
+- *(d+1) = *(s+1);
+- *(d+2) = *(s+2);
+- if (ncopies > 4) {
+- *(d+3) = *(s+3);
+- *(d+4) = *(s+4);
+- if (ncopies > 6) {
+- *(d+5) = *(s+5);
+- *(d+6) = *(s+6);
+- if (ncopies > 8) {
+- *(d+7) = *(s+7);
+- *(d+8) = *(s+8);
++ next = chunk_at_offset(oldp, oldsize);
++
++ /* Try to expand forward into top */
++ if (next == av->top &&
++ (unsigned long)(newsize = oldsize + chunksize(next)) >=
++ (unsigned long)(nb + MINSIZE)) {
++ set_head_size(oldp, nb);
++ av->top = chunk_at_offset(oldp, nb);
++ set_head(av->top, (newsize - nb) | PREV_INUSE);
++ retval = chunk2mem(oldp);
++ goto DONE;
++ }
++
++ /* Try to expand forward into next chunk; split off remainder below */
++ else if (next != av->top &&
++ !inuse(next) &&
++ (unsigned long)(newsize = oldsize + chunksize(next)) >=
++ (unsigned long)(nb)) {
++ newp = oldp;
++ unlink(next, bck, fwd);
++ }
++
++ /* allocate, copy, free */
++ else {
++ newmem = malloc(nb - MALLOC_ALIGN_MASK);
++ if (newmem == 0) {
++ retval = 0; /* propagate failure */
++ goto DONE;
++ }
++
++ newp = mem2chunk(newmem);
++ newsize = chunksize(newp);
++
++ /*
++ Avoid copy if newp is next chunk after oldp.
++ */
++ if (newp == next) {
++ newsize += oldsize;
++ newp = oldp;
++ }
++ else {
++ /*
++ Unroll copy of <= 36 bytes (72 if 8byte sizes)
++ We know that contents have an odd number of
++ size_t-sized words; minimally 3.
++ */
++
++ copysize = oldsize - (sizeof(size_t));
++ s = (size_t*)(oldmem);
++ d = (size_t*)(newmem);
++ ncopies = copysize / sizeof(size_t);
++ assert(ncopies >= 3);
++
++ if (ncopies > 9)
++ memcpy(d, s, copysize);
++
++ else {
++ *(d+0) = *(s+0);
++ *(d+1) = *(s+1);
++ *(d+2) = *(s+2);
++ if (ncopies > 4) {
++ *(d+3) = *(s+3);
++ *(d+4) = *(s+4);
++ if (ncopies > 6) {
++ *(d+5) = *(s+5);
++ *(d+6) = *(s+6);
++ if (ncopies > 8) {
++ *(d+7) = *(s+7);
++ *(d+8) = *(s+8);
++ }
++ }
++ }
++ }
++
++ free(oldmem);
++ check_inuse_chunk(newp);
++ retval = chunk2mem(newp);
++ goto DONE;
+ }
+- }
+ }
+- }
++ }
++
++ /* If possible, free extra space in old or extended chunk */
++
++ assert((unsigned long)(newsize) >= (unsigned long)(nb));
++
++ remainder_size = newsize - nb;
+
+- free(oldmem);
+- check_inuse_chunk(newp);
+- UNLOCK;
+- return chunk2mem(newp);
+- }
+- }
+- }
+-
+- /* If possible, free extra space in old or extended chunk */
+-
+- assert((unsigned long)(newsize) >= (unsigned long)(nb));
+-
+- remainder_size = newsize - nb;
+-
+- if (remainder_size < MINSIZE) { /* not enough extra to split off */
+- set_head_size(newp, newsize);
+- set_inuse_bit_at_offset(newp, newsize);
+- }
+- else { /* split remainder */
+- remainder = chunk_at_offset(newp, nb);
+- set_head_size(newp, nb);
+- set_head(remainder, remainder_size | PREV_INUSE);
+- /* Mark remainder as inuse so free() won't complain */
+- set_inuse_bit_at_offset(remainder, remainder_size);
+- free(chunk2mem(remainder));
+- }
+-
+- check_inuse_chunk(newp);
+- UNLOCK;
+- return chunk2mem(newp);
++ if (remainder_size < MINSIZE) { /* not enough extra to split off */
++ set_head_size(newp, newsize);
++ set_inuse_bit_at_offset(newp, newsize);
++ }
++ else { /* split remainder */
++ remainder = chunk_at_offset(newp, nb);
++ set_head_size(newp, nb);
++ set_head(remainder, remainder_size | PREV_INUSE);
++ /* Mark remainder as inuse so free() won't complain */
++ set_inuse_bit_at_offset(remainder, remainder_size);
++ free(chunk2mem(remainder));
++ }
++
++ check_inuse_chunk(newp);
++ retval = chunk2mem(newp);
++ goto DONE;
+ }
+
+ /*
+- Handle mmap cases
+- */
++ Handle mmap cases
++ */
+
+ else {
+- size_t offset = oldp->prev_size;
+- size_t pagemask = av->pagesize - 1;
+- char *cp;
+- unsigned long sum;
+-
+- /* Note the extra (sizeof(size_t)) overhead */
+- newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask;
+-
+- /* don't need to remap if still within same page */
+- if (oldsize == newsize - offset) {
+- UNLOCK;
+- return oldmem;
+- }
+-
+- cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
+-
+- if (cp != (char*)MORECORE_FAILURE) {
+-
+- newp = (mchunkptr)(cp + offset);
+- set_head(newp, (newsize - offset)|IS_MMAPPED);
+-
+- assert(aligned_OK(chunk2mem(newp)));
+- assert((newp->prev_size == offset));
+-
+- /* update statistics */
+- sum = av->mmapped_mem += newsize - oldsize;
+- if (sum > (unsigned long)(av->max_mmapped_mem))
+- av->max_mmapped_mem = sum;
+- sum += av->sbrked_mem;
+- if (sum > (unsigned long)(av->max_total_mem))
+- av->max_total_mem = sum;
+-
+- UNLOCK;
+- return chunk2mem(newp);
+- }
+-
+- /* Note the extra (sizeof(size_t)) overhead. */
+- if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t))))
+- newmem = oldmem; /* do nothing */
+- else {
+- /* Must alloc, copy, free. */
+- newmem = malloc(nb - MALLOC_ALIGN_MASK);
+- if (newmem != 0) {
+- memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t)));
+- free(oldmem);
+- }
+- }
+- UNLOCK;
+- return newmem;
++ size_t offset = oldp->prev_size;
++ size_t pagemask = av->pagesize - 1;
++ char *cp;
++ unsigned long sum;
++
++ /* Note the extra (sizeof(size_t)) overhead */
++ newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask;
++
++ /* don't need to remap if still within same page */
++ if (oldsize == newsize - offset) {
++ retval = oldmem;
++ goto DONE;
++ }
++
++ cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
++
++ if (cp != (char*)MORECORE_FAILURE) {
++
++ newp = (mchunkptr)(cp + offset);
++ set_head(newp, (newsize - offset)|IS_MMAPPED);
++
++ assert(aligned_OK(chunk2mem(newp)));
++ assert((newp->prev_size == offset));
++
++ /* update statistics */
++ sum = av->mmapped_mem += newsize - oldsize;
++ if (sum > (unsigned long)(av->max_mmapped_mem))
++ av->max_mmapped_mem = sum;
++ sum += av->sbrked_mem;
++ if (sum > (unsigned long)(av->max_total_mem))
++ av->max_total_mem = sum;
++
++ retval = chunk2mem(newp);
++ goto DONE;
++ }
++
++ /* Note the extra (sizeof(size_t)) overhead. */
++ if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t))))
++ newmem = oldmem; /* do nothing */
++ else {
++ /* Must alloc, copy, free. */
++ newmem = malloc(nb - MALLOC_ALIGN_MASK);
++ if (newmem != 0) {
++ memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t)));
++ free(oldmem);
++ }
++ }
++ retval = newmem;
+ }
++
++ DONE:
++ __MALLOC_UNLOCK;
++ return retval;
+ }
+
+diff --git a/libc/stdlib/random.c b/libc/stdlib/random.c
+index b0a00e1..1bd63bc 100644
+--- a/libc/stdlib/random.c
++++ b/libc/stdlib/random.c
+@@ -27,16 +27,14 @@
+ #include <limits.h>
+ #include <stddef.h>
+ #include <stdlib.h>
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
++
+ /* POSIX.1c requires that there is mutual exclusion for the `rand' and
+ `srand' functions to prevent concurrent calls from modifying common
+ data. */
+-static pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+-#else
+-#define __pthread_mutex_lock(x)
+-#define __pthread_mutex_unlock(x)
+-#endif
++
++#include <bits/uClibc_mutex.h>
++
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+
+ /* An improved random number generation package. In addition to the standard
+ rand()/srand() like interface, this package also has a special state info
+@@ -184,9 +182,9 @@ static struct random_data unsafe_state =
+ for default usage relies on values produced by this routine. */
+ void srandom (unsigned int x)
+ {
+- __pthread_mutex_lock(&lock);
++ __UCLIBC_MUTEX_LOCK(mylock);
+ srandom_r (x, &unsafe_state);
+- __pthread_mutex_unlock(&lock);
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ }
+ weak_alias (srandom, srand)
+
+@@ -205,10 +203,10 @@ char * initstate (unsigned int seed, cha
+ {
+ int32_t *ostate;
+
+- __pthread_mutex_lock(&lock);
++ __UCLIBC_MUTEX_LOCK(mylock);
+ ostate = &unsafe_state.state[-1];
+ initstate_r (seed, arg_state, n, &unsafe_state);
+- __pthread_mutex_unlock(&lock);
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return (char *) ostate;
+ }
+
+@@ -224,11 +222,11 @@ char * setstate (char *arg_state)
+ {
+ int32_t *ostate;
+
+- __pthread_mutex_lock(&lock);
++ __UCLIBC_MUTEX_LOCK(mylock);
+ ostate = &unsafe_state.state[-1];
+ if (setstate_r (arg_state, &unsafe_state) < 0)
+ ostate = NULL;
+- __pthread_mutex_unlock(&lock);
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return (char *) ostate;
+ }
+
+@@ -247,9 +245,9 @@ long int random ()
+ {
+ int32_t retval;
+
+- __pthread_mutex_lock(&lock);
++ __UCLIBC_MUTEX_LOCK(mylock);
+ random_r (&unsafe_state, &retval);
+- __pthread_mutex_unlock(&lock);
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return retval;
+ }
+
+diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c
+index d0cfe52..2d899cc 100644
+--- a/libc/stdlib/setenv.c
++++ b/libc/stdlib/setenv.c
+@@ -17,7 +17,7 @@
+ 02111-1307 USA.
+
+ modified for uClibc by Erik Andersen <andersen@codepoet.org>
+- */
++*/
+
+ #define _GNU_SOURCE
+ #include <features.h>
+@@ -26,16 +26,9 @@
+ #include <string.h>
+ #include <unistd.h>
+
+-#ifdef __UCLIBC_HAS_THREADS__
+-#include <pthread.h>
+-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+-# define LOCK __pthread_mutex_lock(&mylock)
+-# define UNLOCK __pthread_mutex_unlock(&mylock);
+-#else
+-# define LOCK
+-# define UNLOCK
+-#endif
++#include <bits/uClibc_mutex.h>
+
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ /* If this variable is not a null pointer we allocated the current
+ environment. */
+@@ -49,14 +42,15 @@ static char **last_environ;
+ to reuse values once generated for a `setenv' call since we can never
+ free the strings. */
+ int __add_to_environ (const char *name, const char *value,
+- const char *combined, int replace)
++ const char *combined, int replace)
+ {
+ register char **ep;
+ register size_t size;
+ const size_t namelen = strlen (name);
+ const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
++ int rv = -1;
+
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+
+ /* We have to get the pointer now that we have the lock and not earlier
+ since another thread might have created a new environment. */
+@@ -64,72 +58,72 @@ int __add_to_environ (const char *name,
+
+ size = 0;
+ if (ep != NULL) {
+- for (; *ep != NULL; ++ep) {
+- if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
+- break;
+- else
+- ++size;
+- }
++ for (; *ep != NULL; ++ep) {
++ if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
++ break;
++ else
++ ++size;
++ }
+ }
+
+ if (ep == NULL || *ep == NULL) {
+- char **new_environ;
++ char **new_environ;
+
+- /* We allocated this space; we can extend it. */
+- new_environ = (char **) realloc (last_environ,
+- (size + 2) * sizeof (char *));
+- if (new_environ == NULL) {
+- UNLOCK;
+- return -1;
+- }
+-
+- /* If the whole entry is given add it. */
+- if (combined != NULL) {
+- /* We must not add the string to the search tree since it belongs
+- to the user. */
+- new_environ[size] = (char *) combined;
+- } else {
+- /* See whether the value is already known. */
+- new_environ[size] = (char *) malloc (namelen + 1 + vallen);
+- if (new_environ[size] == NULL) {
+- __set_errno (ENOMEM);
+- UNLOCK;
+- return -1;
+- }
+-
+- memcpy (new_environ[size], name, namelen);
+- new_environ[size][namelen] = '=';
+- memcpy (&new_environ[size][namelen + 1], value, vallen);
+- }
+-
+- if (__environ != last_environ) {
+- memcpy ((char *) new_environ, (char *) __environ,
+- size * sizeof (char *));
+- }
++ /* We allocated this space; we can extend it. */
++ new_environ = (char **) realloc (last_environ,
++ (size + 2) * sizeof (char *));
++ if (new_environ == NULL) {
++ goto DONE;
++ }
++
++ /* If the whole entry is given add it. */
++ if (combined != NULL) {
++ /* We must not add the string to the search tree since it belongs
++ to the user. */
++ new_environ[size] = (char *) combined;
++ } else {
++ /* See whether the value is already known. */
++ new_environ[size] = (char *) malloc (namelen + 1 + vallen);
++ if (new_environ[size] == NULL) {
++ __set_errno (ENOMEM);
++ goto DONE;
++ }
++
++ memcpy (new_environ[size], name, namelen);
++ new_environ[size][namelen] = '=';
++ memcpy (&new_environ[size][namelen + 1], value, vallen);
++ }
++
++ if (__environ != last_environ) {
++ memcpy ((char *) new_environ, (char *) __environ,
++ size * sizeof (char *));
++ }
+
+- new_environ[size + 1] = NULL;
+- last_environ = __environ = new_environ;
++ new_environ[size + 1] = NULL;
++ last_environ = __environ = new_environ;
+ } else if (replace) {
+- char *np;
++ char *np;
+
+- /* Use the user string if given. */
+- if (combined != NULL) {
+- np = (char *) combined;
+- } else {
+- np = malloc (namelen + 1 + vallen);
+- if (np == NULL) {
+- UNLOCK;
+- return -1;
+- }
+- memcpy (np, name, namelen);
+- np[namelen] = '=';
+- memcpy (&np[namelen + 1], value, vallen);
+- }
+- *ep = np;
+- }
+-
+- UNLOCK;
+- return 0;
++ /* Use the user string if given. */
++ if (combined != NULL) {
++ np = (char *) combined;
++ } else {
++ np = malloc (namelen + 1 + vallen);
++ if (np == NULL) {
++ goto DONE;
++ }
++ memcpy (np, name, namelen);
++ np[namelen] = '=';
++ memcpy (&np[namelen + 1], value, vallen);
++ }
++ *ep = np;
++ }
++
++ rv = 0;
++
++ DONE:
++ __UCLIBC_MUTEX_UNLOCK(mylock);
++ return rv;
+ }
+
+ int setenv (const char *name, const char *value, int replace)
+@@ -143,26 +137,26 @@ int unsetenv (const char *name)
+ char **ep;
+
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) {
+- __set_errno (EINVAL);
+- return -1;
++ __set_errno (EINVAL);
++ return -1;
+ }
+
+ len = strlen (name);
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ ep = __environ;
+ while (*ep != NULL) {
+- if (!strncmp (*ep, name, len) && (*ep)[len] == '=') {
+- /* Found it. Remove this pointer by moving later ones back. */
+- char **dp = ep;
+- do {
+- dp[0] = dp[1];
+- } while (*dp++);
+- /* Continue the loop in case NAME appears again. */
+- } else {
+- ++ep;
+- }
++ if (!strncmp (*ep, name, len) && (*ep)[len] == '=') {
++ /* Found it. Remove this pointer by moving later ones back. */
++ char **dp = ep;
++ do {
++ dp[0] = dp[1];
++ } while (*dp++);
++ /* Continue the loop in case NAME appears again. */
++ } else {
++ ++ep;
++ }
+ }
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return 0;
+ }
+
+@@ -171,15 +165,15 @@ int unsetenv (const char *name)
+ for Fortran 77) requires this function. */
+ int clearenv (void)
+ {
+- LOCK;
++ __UCLIBC_MUTEX_LOCK(mylock);
+ if (__environ == last_environ && __environ != NULL) {
+- /* We allocated this environment so we can free it. */
+- free (__environ);
+- last_environ = NULL;
++ /* We allocated this environment so we can free it. */
++ free (__environ);
++ last_environ = NULL;
+ }
+ /* Clear the environment pointer removes the whole environment. */
+ __environ = NULL;
+- UNLOCK;
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return 0;
+ }
+
+@@ -190,10 +184,10 @@ int putenv (char *string)
+ const char *const name_end = strchr (string, '=');
+
+ if (name_end != NULL) {
+- char *name = strndup(string, name_end - string);
+- result = __add_to_environ (name, NULL, string, 1);
+- free(name);
+- return(result);
++ char *name = strndup(string, name_end - string);
++ result = __add_to_environ (name, NULL, string, 1);
++ free(name);
++ return(result);
+ }
+ unsetenv (string);
+ return 0;
+diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h
+index 40cd5fe..3c6911e 100644
+--- a/libc/sysdeps/linux/common/bits/uClibc_stdio.h
++++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h
+@@ -116,9 +116,7 @@
+ #endif
+
+ /**********************************************************************/
+-#ifdef __UCLIBC_HAS_THREADS__
+-/* Need this for pthread_mutex_t. */
+-#include <bits/pthreadtypes.h>
++#include <bits/uClibc_mutex.h>
+
+ /* user_locking
+ * 0 : do auto locking/unlocking
+@@ -132,43 +130,37 @@
+ * This way, we avoid calling the weak lock/unlock functions.
+ */
+
+-#define __STDIO_AUTO_THREADLOCK_VAR int __infunc_user_locking
+-
+-#define __STDIO_AUTO_THREADLOCK(__stream) \
+- if ((__infunc_user_locking = (__stream)->__user_locking) == 0) { \
+- __pthread_mutex_lock(&(__stream)->__lock); \
+- }
+-
+-#define __STDIO_AUTO_THREADUNLOCK(__stream) \
+- if (__infunc_user_locking == 0) { \
+- __pthread_mutex_unlock(&(__stream)->__lock); \
+- }
++#define __STDIO_AUTO_THREADLOCK_VAR \
++ __UCLIBC_MUTEX_AUTO_LOCK_VAR(__infunc_user_locking)
+
+-#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1)
++#define __STDIO_AUTO_THREADLOCK(__stream) \
++ __UCLIBC_MUTEX_AUTO_LOCK((__stream)->__lock, __infunc_user_locking, \
++ (__stream)->__user_locking)
+
+-#define __STDIO_ALWAYS_THREADLOCK(__stream) \
+- __pthread_mutex_lock(&(__stream)->__lock)
++#define __STDIO_AUTO_THREADUNLOCK(__stream) \
++ __UCLIBC_MUTEX_AUTO_UNLOCK((__stream)->__lock, __infunc_user_locking)
+
+-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) \
+- __pthread_mutex_trylock(&(__stream)->__lock)
++#define __STDIO_ALWAYS_THREADLOCK(__stream) \
++ __UCLIBC_MUTEX_LOCK((__stream)->__lock)
+
+-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \
+- __pthread_mutex_unlock(&(__stream)->__lock)
++#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \
++ __UCLIBC_MUTEX_UNLOCK((__stream)->__lock)
+
+-#else /* __UCLIBC_HAS_THREADS__ */
++#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream) \
++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE((__stream)->__lock)
+
+-#define __STDIO_AUTO_THREADLOCK_VAR ((void)0)
++#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream) \
++ __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE((__stream)->__lock)
+
+-#define __STDIO_AUTO_THREADLOCK(__stream) ((void)0)
+-#define __STDIO_AUTO_THREADUNLOCK(__stream) ((void)0)
++#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) \
++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE((__stream)->__lock)
+
++#ifdef __UCLIBC_HAS_THREADS__
++#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1)
++#else
+ #define __STDIO_SET_USER_LOCKING(__stream) ((void)0)
++#endif
+
+-#define __STDIO_ALWAYS_THREADLOCK(__stream) ((void)0)
+-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) (0) /* Always succeed. */
+-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) ((void)0)
+-
+-#endif /* __UCLIBC_HAS_THREADS__ */
+ /**********************************************************************/
+
+ #define __STDIO_IOFBF 0 /* Fully buffered. */
+@@ -283,7 +275,7 @@ struct __STDIO_FILE_STRUCT {
+ #endif
+ #ifdef __UCLIBC_HAS_THREADS__
+ int __user_locking;
+- pthread_mutex_t __lock;
++ __UCLIBC_MUTEX(__lock);
+ #endif
+ /* Everything after this is unimplemented... and may be trashed. */
+ #if __STDIO_BUILTIN_BUF_SIZE > 0
+@@ -358,10 +350,14 @@ extern void _stdio_term(void);
+ extern struct __STDIO_FILE_STRUCT *_stdio_openlist;
+
+ #ifdef __UCLIBC_HAS_THREADS__
+-extern pthread_mutex_t _stdio_openlist_lock;
+-extern int _stdio_openlist_delflag;
++__UCLIBC_MUTEX_EXTERN(_stdio_openlist_add_lock);
++#ifdef __STDIO_BUFFERS
++__UCLIBC_MUTEX_EXTERN(_stdio_openlist_del_lock);
++extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */
++extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */
++#endif
+ extern int _stdio_user_locking;
+-extern void __stdio_init_mutex(pthread_mutex_t *m);
++extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m);
+ #endif
+
+ #endif
+diff --git a/libc/sysdeps/linux/common/getdents.c b/libc/sysdeps/linux/common/getdents.c
+index ab6a276..23463e5 100644
+--- a/libc/sysdeps/linux/common/getdents.c
++++ b/libc/sysdeps/linux/common/getdents.c
+@@ -30,8 +30,6 @@
+ #include <sys/syscall.h>
+
+
+-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+-
+ struct kernel_dirent
+ {
+ long d_ino;
+diff --git a/libc/sysdeps/linux/common/sigprocmask.c b/libc/sysdeps/linux/common/sigprocmask.c
+index 70ff366..565318d 100644
+--- a/libc/sysdeps/linux/common/sigprocmask.c
++++ b/libc/sysdeps/linux/common/sigprocmask.c
+@@ -23,6 +23,8 @@ int sigprocmask(int how, const sigset_t
+ if (set &&
+ #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2)
+ (((unsigned int) how) > 2)
++#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3)
++ (((unsigned int)(how-1)) > 2)
+ #else
+ #warning "compile time assumption violated.. slow path..."
+ ((how != SIG_BLOCK) && (how != SIG_UNBLOCK)
+@@ -48,6 +50,8 @@ int sigprocmask(int how, const sigset_t
+ if (set &&
+ #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2)
+ (((unsigned int) how) > 2)
++#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3)
++ (((unsigned int)(how-1)) > 2)
+ #else
+ #warning "compile time assumption violated.. slow path..."
+ ((how != SIG_BLOCK) && (how != SIG_UNBLOCK)
+diff --git a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h
+index b6f52cc..317e5b3 100644
+--- a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h
++++ b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h
+@@ -38,3 +38,6 @@ struct kernel_sigaction {
+ void (*sa_restorer)(void);
+ int s_resv[1]; /* reserved */
+ };
++
++extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded,
++ struct kernel_sigaction *__unbounded, size_t);
+diff --git a/libc/sysdeps/linux/mips/pipe.S b/libc/sysdeps/linux/mips/pipe.S
+index c3afae5..cd88074 100644
+--- a/libc/sysdeps/linux/mips/pipe.S
++++ b/libc/sysdeps/linux/mips/pipe.S
+@@ -7,25 +7,36 @@
+ #include <asm/unistd.h>
+ #include <asm/regdef.h>
+
+- .globl pipe
+- .ent pipe, 0
++ .globl pipe
++ .ent pipe, 0
+ pipe:
+- addiu sp,sp,-24
+- sw a0,16(sp)
+- li v0,__NR_pipe
+- syscall
+- beqz a3, 1f
+- la t3, errno
+- sw v0, (t3)
+- li v0, -1
+- b 2f
++ .frame sp, 24, sp
++#ifdef __PIC__
++ .set noreorder
++ .cpload $25
++ .set reorder
++ addiu sp,sp,-24
++ .cprestore 16
++#else
++ addiu sp,sp,-24
++#endif
++ sw a0,16(sp)
++ li v0,__NR_pipe
++ syscall
++ beqz a3, 1f
++#ifdef __PIC__
++ la t0, __syscall_error
++ jr t9
++#else
++ j __syscall_error
++#endif
+ 1:
+- lw a0, 16(sp)
+- sw v0, 0(a0)
+- sw v1, 4(a0)
+- li v0, 0
++ lw a0, 16(sp)
++ sw v0, 0(a0)
++ sw v1, 4(a0)
++ li v0, 0
+ 2:
+- addiu sp,sp,24
+- j ra
+- .end pipe
+- .size pipe,.-pipe
++ addiu sp,sp,24
++ j ra
++ .end pipe
++ .size pipe,.-pipe
+diff --git a/libcrypt/des.c b/libcrypt/des.c
+index 3b49a7a..f7a6be1 100644
+--- a/libcrypt/des.c
++++ b/libcrypt/des.c
+@@ -504,7 +504,7 @@ do_des( u_int32_t l_in, u_int32_t r_in,
+ kl = kl1;
+ kr = kr1;
+ round = 16;
+- while (round--) {
++ do {
+ /*
+ * Expand R to 48 bits (simulate the E-box).
+ */
+@@ -540,7 +540,7 @@ do_des( u_int32_t l_in, u_int32_t r_in,
+ f ^= l;
+ l = r;
+ r = f;
+- }
++ } while (--round);
+ r = l;
+ l = f;
+ }
+diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c
+index eb544f3..cfec2b7 100644
+--- a/libpthread/linuxthreads/ptfork.c
++++ b/libpthread/linuxthreads/ptfork.c
+@@ -26,6 +26,15 @@
+ #include "pthread.h"
+ #include "internals.h"
+
++#warning hack alert... should be sufficent for system(), but what about other libc mutexes?
++#include <bits/uClibc_mutex.h>
++
++__UCLIBC_MUTEX_EXTERN(__malloc_lock);
++
++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
++#warning hack alert block end
++
+ struct handler_list {
+ void (*handler)(void);
+ struct handler_list * next;
+@@ -91,9 +100,18 @@ pid_t __fork(void)
+ parent = pthread_atfork_parent;
+ pthread_mutex_unlock(&pthread_atfork_lock);
+ pthread_call_handlers(prepare);
++
++#warning hack alert
++ __MALLOC_LOCK;
++
+ pid = __libc_fork();
++
++#warning hack alert
++ __MALLOC_UNLOCK;
++
+ if (pid == 0) {
+ __pthread_reset_main_thread();
++#warning need to reconsider __fresetlockfiles!
+ __fresetlockfiles();
+ pthread_call_handlers(child);
+ } else {
+diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h
+--- uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h 1969-12-31 17:00:00.000000000 -0700
++++ uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h 2006-03-08 11:21:58.000000000 -0700
+@@ -0,0 +1,87 @@
++/* Copyright (C) 2006 Manuel Novoa III <mjn3@codepoet.org>
++ *
++ * GNU Library General Public License (LGPL) version 2 or later.
++ *
++ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
++ */
++
++#ifndef _UCLIBC_MUTEX_H
++#define _UCLIBC_MUTEX_H
++
++#include <features.h>
++
++#ifdef __UCLIBC_HAS_THREADS__
++
++#include <pthread.h>
++
++#define __UCLIBC_MUTEX_TYPE pthread_mutex_t
++
++#define __UCLIBC_MUTEX(M) pthread_mutex_t M
++#define __UCLIBC_MUTEX_INIT(M,I) pthread_mutex_t M = I
++#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I
++#define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M
++
++#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \
++ __pthread_mutex_lock(&(M))
++
++#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \
++ __pthread_mutex_unlock(&(M))
++
++#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \
++ __pthread_mutex_trylock(&(M))
++
++#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \
++ do { \
++ struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \
++ if (C) { \
++ _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \
++ __pthread_mutex_unlock, \
++ &(M)); \
++ __pthread_mutex_lock(&(M)); \
++ } \
++ ((void)0)
++
++#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) \
++ if (C) { \
++ _pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);\
++ } \
++ } while (0)
++
++#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) int A
++
++#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) \
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,((A=(V)) == 0))
++
++#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) \
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,(A == 0))
++
++#define __UCLIBC_MUTEX_LOCK(M) \
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1)
++
++#define __UCLIBC_MUTEX_UNLOCK(M) \
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1)
++
++#else
++
++#define __UCLIBC_MUTEX(M) void *__UCLIBC_MUTEX_DUMMY_ ## M
++#define __UCLIBC_MUTEX_INIT(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M
++#define __UCLIBC_MUTEX_STATIC(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M
++#define __UCLIBC_MUTEX_EXTERN(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M
++
++#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) ((void)0)
++#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) ((void)0)
++#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) (0) /* Always succeed? */
++
++#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) ((void)0)
++#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) ((void)0)
++
++#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) ((void)0)
++#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) ((void)0)
++#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) ((void)0)
++
++#define __UCLIBC_MUTEX_LOCK(M) ((void)0)
++#define __UCLIBC_MUTEX_UNLOCK(M) ((void)0)
++
++#endif
++
++#endif /* _UCLIBC_MUTEX_H */
+diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c
+--- uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c 2005-08-17 16:49:44.000000000 -0600
++++ uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c 1969-12-31 17:00:00.000000000 -0700
+@@ -1,23 +0,0 @@
+-/* pipe system call for Linux/MIPS */
+-
+-/*see uClibc's sh/pipe.c and glibc-2.2.4's mips/pipe.S */
+-
+-#include <errno.h>
+-#include <unistd.h>
+-#include <syscall.h>
+-
+-int pipe(int *fd)
+-{
+- register long int res __asm__ ("$2"); // v0
+- register long int res2 __asm__ ("$3"); // v1
+-
+- asm ("move\t$4,%2\n\t" // $4 = a0
+- "syscall" /* Perform the system call. */
+- : "=r" (res)
+- : "0" (__NR_pipe), "r" (fd)
+- : "$4", "$7");
+-
+- fd[0] = res;
+- fd[1] = res2;
+- return(0);
+-}
--- /dev/null
+--- uClibc/libc/misc/time/time.c (revision 16488)
++++ uClibc/libc/misc/time/time.c (working copy)
+@@ -157,6 +157,22 @@
+ #define TZNAME_MAX _POSIX_TZNAME_MAX
+ #endif
+
++#if defined (L_tzset) || defined (L_localtime_r) || defined(L_strftime) || \
++ defined(L__time_mktime) || defined(L__time_mktime_tzi) || \
++ ((defined(L_strftime) || defined(L_strftime_l)) && \
++ defined(__UCLIBC_HAS_XLOCALE__))
++
++void _time_tzset (int);
++
++#ifndef L__time_mktime
++
++ /* Jan 1, 2007 Z - tm = 0,0,0,1,0,107,1,0,0 */
++
++const static time_t new_rule_starts = 1167609600;
++
++#endif
++#endif
++
+ /**********************************************************************/
+ /* The era code is currently unfinished. */
+ /* #define ENABLE_ERA_CODE */
+@@ -532,7 +548,7 @@
+ {
+ __UCLIBC_MUTEX_LOCK(_time_tzlock);
+
+- tzset();
++ _time_tzset(*timer < new_rule_starts);
+
+ __time_localtime_tzi(timer, result, _time_tzinfo);
+
+@@ -956,7 +972,8 @@
+ unsigned char mod;
+ unsigned char code;
+
+- tzset(); /* We'll, let's get this out of the way. */
++ /* We'll, let's get this out of the way. */
++ _time_tzset(_time_mktime((struct tm *) timeptr, 0) < new_rule_starts);
+
+ lvl = 0;
+ p = format;
+@@ -1644,7 +1661,9 @@
+ 6, 0, 0, /* Note: overloaded for non-M non-J case... */
+ 0, 1, 0, /* J */
+ ',', 'M', '4', '.', '1', '.', '0',
+- ',', 'M', '1', '0', '.', '5', '.', '0', 0
++ ',', 'M', '1', '0', '.', '5', '.', '0', 0,
++ ',', 'M', '3', '.', '2', '.', '0',
++ ',', 'M', '1', '1', '.', '1', '.', '0', 0
+ };
+
+ #define TZ vals
+@@ -1652,6 +1671,7 @@
+ #define RANGE (vals + 7)
+ #define RULE (vals + 11 - 1)
+ #define DEFAULT_RULES (vals + 22)
++#define DEFAULT_2007_RULES (vals + 38)
+
+ /* Initialize to UTC. */
+ int daylight = 0;
+@@ -1774,6 +1794,11 @@
+
+ void tzset(void)
+ {
++ _time_tzset((time(NULL)) < new_rule_starts);
++}
++
++void _time_tzset(int use_old_rules)
++{
+ register const char *e;
+ register char *s;
+ long off;
+@@ -1896,7 +1921,15 @@
+ } else { /* OK, we have dst, so get some rules. */
+ count = 0;
+ if (!*e) { /* No rules so default to US rules. */
+- e = DEFAULT_RULES;
++ e = use_old_rules ? DEFAULT_RULES : DEFAULT_2007_RULES;
++#ifdef DEBUG_TZSET
++ if (e == DEFAULT_RULES)
++ printf("tzset: Using old rules.\n");
++ else if (e == DEFAULT_2007_RULES)
++ printf("tzset: Using new rules\n");
++ else
++ printf("tzset: Using undefined rules\n");
++#endif /* DEBUG_TZSET */
+ }
+
+ do {
+@@ -2230,6 +2263,8 @@
+ --d;
+ }
+
++ _time_tzset (x.tm_year < 2007); /* tm_year was expanded above */
++
+ #ifdef __BCC__
+ d = p[5] - 1;
+ days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]);
--- /dev/null
+diff -urN uClibc-0.9.29-0rig/include/assert.h uClibc-0.9.29/include/assert.h
+--- uClibc-0.9.29-0rig/include/assert.h 2005-11-03 23:42:46.000000000 +0100
++++ uClibc-0.9.29/include/assert.h 2007-08-13 19:10:57.000000000 +0200
+@@ -31,7 +31,7 @@
+ #define _ASSERT_H 1
+ #include <features.h>
+
+-#if defined __cplusplus && __GNUC_PREREQ (2,95)
++#if defined __cplusplus && __GNUC_PREREQ(2,95)
+ # define __ASSERT_VOID_CAST static_cast<void>
+ #else
+ # define __ASSERT_VOID_CAST (void)
+@@ -59,13 +59,17 @@
+ (__ASSERT_VOID_CAST ((expr) ? 0 : \
+ (__assert (__STRING(expr), __FILE__, __LINE__, \
+ __ASSERT_FUNCTION), 0)))
+-
++
++/* Define some temporaries to workaround tinyx makedepend bug */
++#define __GNUC_PREREQ_2_6 __GNUC_PREREQ(2, 6)
++#define __GNUC_PREREQ_2_4 __GNUC_PREREQ(2, 4)
+ /* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__'
+ which contains the name of the function currently being defined.
+ This is broken in G++ before version 2.6.
+ C9x has a similar variable called __func__, but prefer the GCC one since
+ it demangles C++ function names. */
+-# if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4)
++
++# if defined __cplusplus ? __GNUC_PREREQ_2_6 : __GNUC_PREREQ_2_4
+ # define __ASSERT_FUNCTION __PRETTY_FUNCTION__
+ # else
+ # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+diff -urN uClibc-0.9.29-0rig/include/complex.h uClibc-0.9.29/include/complex.h
+--- uClibc-0.9.29-0rig/include/complex.h 2002-05-09 10:15:21.000000000 +0200
++++ uClibc-0.9.29/include/complex.h 2007-08-13 17:55:29.000000000 +0200
+@@ -33,7 +33,7 @@
+ /* We might need to add support for more compilers here. But since ISO
+ C99 is out hopefully all maintained compilers will soon provide the data
+ types `float complex' and `double complex'. */
+-#if __GNUC_PREREQ (2, 7) && !__GNUC_PREREQ (2, 97)
++#if __GNUC_PREREQ(2, 7) && !__GNUC_PREREQ(2, 97)
+ # define _Complex __complex__
+ #endif
+
+diff -urN uClibc-0.9.29-0rig/include/features.h uClibc-0.9.29/include/features.h
+--- uClibc-0.9.29-0rig/include/features.h 2006-11-29 22:10:04.000000000 +0100
++++ uClibc-0.9.29/include/features.h 2007-08-13 17:55:51.000000000 +0200
+@@ -143,7 +143,7 @@
+
+ /* Convenience macros to test the versions of glibc and gcc.
+ Use them like this:
+- #if __GNUC_PREREQ (2,8)
++ #if __GNUC_PREREQ(2,8)
+ ... code requiring gcc 2.8 or later ...
+ #endif
+ Note - they won't work for gcc1 or glibc1, since the _MINOR macros
+@@ -297,7 +297,7 @@
+ /* uClibc does not support _FORTIFY_SOURCE */
+ #undef _FORTIFY_SOURCE
+ #if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 \
+- && __GNUC_PREREQ (4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0
++ && __GNUC_PREREQ(4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+ # if _FORTIFY_SOURCE > 1
+ # define __USE_FORTIFY_LEVEL 2
+ # else
+@@ -366,7 +366,7 @@
+ #endif /* !ASSEMBLER */
+
+ /* Decide whether we can define 'extern inline' functions in headers. */
+-#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \
++#if __GNUC_PREREQ(2, 7) && defined __OPTIMIZE__ \
+ && !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__
+ # define __USE_EXTERN_INLINES 1
+ #endif
+diff -urN uClibc-0.9.29-0rig/include/tgmath.h uClibc-0.9.29/include/tgmath.h
+--- uClibc-0.9.29-0rig/include/tgmath.h 2002-05-09 10:15:21.000000000 +0200
++++ uClibc-0.9.29/include/tgmath.h 2007-08-13 17:56:17.000000000 +0200
+@@ -34,7 +34,7 @@
+ do not try this for now and instead concentrate only on GNU CC. Once
+ we have more information support for other compilers might follow. */
+
+-#if __GNUC_PREREQ (2, 7)
++#if __GNUC_PREREQ(2, 7)
+
+ # ifdef __NO_LONG_DOUBLE_MATH
+ # define __tgml(fct) fct
--- /dev/null
+Index: uclibc/Makefile
+===================================================================
+RCS file: /disk1/ic_group/design/I9980/REPOSITORY/I7413/source/uclibc/Makefile,v
+retrieving revision 1.1.1.3
+diff -u -r1.1.1.3 Makefile
+--- uclibc/Makefile 31 Aug 2005 13:08:25 -0000 1.1.1.3
++++ uclibc/Makefile 7 Dec 2005 06:38:39 -0000
+@@ -163,7 +163,7 @@
+ else \
+ extra_exclude="" ; \
+ fi ; \
+- tar -chf - include --exclude .svn --exclude CVS $$extra_exclude \
++ tar -chf - --exclude .svn --exclude CVS $$extra_exclude include \
+ | tar -xf - -C $(PREFIX)$(DEVEL_PREFIX)
+ ifneq ($(strip $(UCLIBC_HAS_FLOATS)),y)
+ # Remove floating point related headers since float support is disabled.
+--- a/extra/scripts/fix_includes.sh 2005-08-18 00:49:41.000000000 +0200
++++ b/extra/scripts/fix_includes.sh 2006-09-27 13:23:12.000000000 +0200
+@@ -78,36 +78,6 @@ if [ ! -d "$KERNEL_SOURCE" ]; then
+ exit 1;
+ fi;
+
+-if [ -f "$KERNEL_SOURCE/Makefile" ] ; then
+-# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
+-eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $KERNEL_SOURCE/Makefile`
+-else
+-ver=`grep UTS_RELEASE $KERNEL_SOURCE/include/linux/version.h | cut -d '"' -f 2`
+-VERSION=`echo "$ver" | cut -d '.' -f 1`
+-PATCHLEVEL=`echo "$ver" | cut -d '.' -f 2`
+-if echo "$ver" | grep -q '-' ; then
+-SUBLEVEL=`echo "$ver" | sed "s/${VERSION}.${PATCHLEVEL}.//" | cut -d '-' -f 1`
+-EXTRAVERSION=`echo "$ver" | sed "s/${VERSION}.${PATCHLEVEL}.${SUBLEVEL}-//"`
+-else
+-SUBLEVEL=`echo "$ver" | cut -d '.' -f 3`
+-#EXTRAVERSION=
+-fi
+-fi
+-if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
+-then
+- echo "Unable to determine version for kernel headers"
+- echo -e "\tprovided in directory $KERNEL_SOURCE"
+- exit 1
+-fi
+-
+-if [ "$MAKE_IS_SILENT" != "y" ]; then
+-echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
+-echo -e "\n"
+-echo "Using kernel headers from $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} for architecture '$TARGET_ARCH'"
+-echo -e "\tprovided in directory $KERNEL_SOURCE"
+-echo -e "\n"
+-fi
+-
+ # Create a symlink to include/asm
+
+ rm -f include/asm*
+@@ -172,7 +142,7 @@ fi;
+
+
+ # Annoyingly, 2.6.x kernel headers also need an include/asm-generic/ directory
+-if [ $VERSION -eq 2 ] && [ $PATCHLEVEL -ge 6 ] ; then
++if [ -d $KERNEL_SOURCE/include/asm-generic ] ; then
+ ln -fs $KERNEL_SOURCE/include/asm-generic include/asm-generic
+ fi;
+
+From 7b2f125425cf777e7937b533217588e27952b87d Mon Sep 17 00:00:00 2001
+From: Haavard Skinnemoen <hskinnemoen@atmel.com>
+Date: Mon, 7 Aug 2006 11:12:50 +0200
+Subject: [PATCH] Let optimized stringops override default ones
+
+The default, slow stringops must be archived _before_ the optimized
+stringops if there is to be any point doing the optimizations in the
+first place.
+---
+ libc/Makefile | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/libc/Makefile b/libc/Makefile
+index 31e4bab..687eac5 100644
+--- a/libc/Makefile
++++ b/libc/Makefile
+@@ -59,7 +59,7 @@ # will evaluate to no files :(.
+ $(AR) dN 2 $(LIBNAME) $$objs && \
+ $(AR) dN 2 $(LIBNAME) $$objs
+ @for objfile in obj.signal \
+- obj.string.generic obj.string.$(TARGET_ARCH) obj.string \
++ obj.string obj.string.generic obj.string.$(TARGET_ARCH) \
+ obj.sysdeps.common obj.sysdeps.$(TARGET_ARCH) ; do \
+ if [ -e $$objfile ] ; then \
+ if [ "$(MAKE_IS_SILENT)" = "n" ] ; then \
+--
+1.4.1.1
+
+Subject: [PATCH] Fix getrusage argument type
+
+The first argument to getrusage is of type __rusage_who_t, not int.
+This patch fixes that.
+---
+
+ libc/sysdeps/linux/common/getrusage.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: uClibc-0.9.28/libc/sysdeps/linux/common/getrusage.c
+===================================================================
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/common/getrusage.c 2006-02-07 17:18:22.000000000 +0100
++++ uClibc-0.9.28/libc/sysdeps/linux/common/getrusage.c 2006-02-07 17:18:31.000000000 +0100
+@@ -10,4 +10,4 @@
+ #include "syscalls.h"
+ #include <unistd.h>
+ #include <wait.h>
+-_syscall2(int, getrusage, int, who, struct rusage *, usage);
++_syscall2(int, getrusage, __rusage_who_t, who, struct rusage *, usage);
+Subject: [PATCH] Fix __libc_fcntl64 prototype in __syscall_fcntl.c
+
+__libc_fcntl64 is a varargs function and should be declared as such.
+Otherwise, the gcc compiler for AVR32, and perhaps other architectures,
+will use the wrong calling convention.
+
+---
+
+ libc/sysdeps/linux/common/__syscall_fcntl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: uClibc-0.9.28/libc/sysdeps/linux/common/__syscall_fcntl.c
+===================================================================
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/common/__syscall_fcntl.c 2006-02-07 16:48:32.000000000 +0100
++++ uClibc-0.9.28/libc/sysdeps/linux/common/__syscall_fcntl.c 2006-02-07 17:19:09.000000000 +0100
+@@ -12,7 +12,7 @@
+ #include <fcntl.h>
+
+ #if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64
+-extern int __libc_fcntl64(int fd, int cmd, long arg);
++extern int __libc_fcntl64(int fd, int cmd, ...);
+ #endif
+
+ #define __NR___syscall_fcntl __NR_fcntl
+From nobody Mon Sep 17 00:00:00 2001
+From: HÃ¥vard Skinnemoen <hskinnemoen@atmel.com>
+Date: Fri Apr 7 17:10:32 2006 +0200
+Subject: [PATCH] Fix broken __libc_open declaration in open64.c
+
+__libc_open is a vararg function and should therefore be declared as
+such. Fixes bug #4190.
+
+---
+
+ libc/sysdeps/linux/common/open64.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+70f2c81903327a8a346e370830932b80045ab04e
+diff --git a/libc/sysdeps/linux/common/open64.c b/libc/sysdeps/linux/common/open64.c
+index 543aa13..d9a27a7 100644
+--- a/libc/sysdeps/linux/common/open64.c
++++ b/libc/sysdeps/linux/common/open64.c
+@@ -26,7 +26,7 @@
+ #endif
+
+ #ifdef __UCLIBC_HAS_LFS__
+-extern int __libc_open (__const char *file, int oflag, mode_t mode);
++extern int __libc_open (__const char *file, int oflag, ...);
+
+ /* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
+ a third argument is the file protection. */
+--
+1.2.4
+
+Subject: [PATCH] AVR32 Architecture support
+
+Add support for the AVR32 architecture in the core libc and build system.
+This also adds AVR32-ELF definitions to elf.h
+
+---
+
+ Rules.mak | 4
+ extra/Configs/Config.avr32 | 38 +++++
+ extra/Configs/Config.in | 7 +
+ include/elf.h | 51 +++++++
+ libc/sysdeps/linux/avr32/Makefile | 93 +++++++++++++
+ libc/sysdeps/linux/avr32/__longjmp.S | 17 ++
+ libc/sysdeps/linux/avr32/_mmap.c | 33 ++++
+ libc/sysdeps/linux/avr32/bits/atomicity.h | 86 ++++++++++++
+ libc/sysdeps/linux/avr32/bits/byteswap.h | 80 +++++++++++
+ libc/sysdeps/linux/avr32/bits/endian.h | 7 +
+ libc/sysdeps/linux/avr32/bits/fcntl.h | 167 +++++++++++++++++++++++++
+ libc/sysdeps/linux/avr32/bits/kernel_stat.h | 63 +++++++++
+ libc/sysdeps/linux/avr32/bits/kernel_types.h | 56 ++++++++
+ libc/sysdeps/linux/avr32/bits/machine-gmon.h | 69 ++++++++++
+ libc/sysdeps/linux/avr32/bits/mman.h | 95 ++++++++++++++
+ libc/sysdeps/linux/avr32/bits/profil-counter.h | 26 +++
+ libc/sysdeps/linux/avr32/bits/setjmp.h | 21 +++
+ libc/sysdeps/linux/avr32/bits/syscalls.h | 143 +++++++++++++++++++++
+ libc/sysdeps/linux/avr32/bits/wordsize.h | 1
+ libc/sysdeps/linux/avr32/brk.c | 23 +++
+ libc/sysdeps/linux/avr32/bsd-_setjmp.S | 12 +
+ libc/sysdeps/linux/avr32/bsd-setjmp.S | 12 +
+ libc/sysdeps/linux/avr32/clone.c | 37 +++++
+ libc/sysdeps/linux/avr32/crt1.S | 93 +++++++++++++
+ libc/sysdeps/linux/avr32/crti.S | 17 ++
+ libc/sysdeps/linux/avr32/crtn.S | 14 ++
+ libc/sysdeps/linux/avr32/mmap.c | 31 ++++
+ libc/sysdeps/linux/avr32/setjmp.S | 43 ++++++
+ libc/sysdeps/linux/avr32/sigaction.c | 49 +++++++
+ libc/sysdeps/linux/avr32/sigrestorer.S | 11 +
+ libc/sysdeps/linux/avr32/sys/elf.h | 26 +++
+ libc/sysdeps/linux/avr32/sys/io.h | 48 +++++++
+ libc/sysdeps/linux/avr32/sys/procfs.h | 123 ++++++++++++++++++
+ libc/sysdeps/linux/avr32/sys/ucontext.h | 94 ++++++++++++++
+ libc/sysdeps/linux/avr32/sys/user.h | 46 ++++++
+ libc/sysdeps/linux/avr32/syscall.S | 81 ++++++++++++
+ libc/sysdeps/linux/avr32/vfork.S | 55 ++++++++
+ 37 files changed, 1872 insertions(+)
+
+Index: uClibc-0.9.28/extra/Configs/Config.avr32
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/extra/Configs/Config.avr32 2006-05-05 09:27:17.000000000 +0200
+@@ -0,0 +1,38 @@
++#
++# For a description of the syntax of this configuration file,
++# see extra/config/Kconfig-language.txt
++#
++
++config HAVE_ELF
++ bool
++ default y
++
++config TARGET_ARCH
++ default "avr32"
++
++config ARCH_CFLAGS
++ string
++
++config ARCH_LDFLAGS
++ string
++
++config LIBGCC_CFLAGS
++ string
++
++config ARCH_SUPPORTS_BIG_ENDIAN
++ bool
++ default y
++
++config UCLIBC_COMPLETELY_PIC
++ select FORCE_SHAREABLE_TEXT_SEGMENTS
++ bool
++ default y
++
++choice
++ prompt "Target CPU Type"
++ default CONFIG_AP7000
++
++config CONFIG_AP7000
++ bool "AP7000"
++
++endchoice
+Index: uClibc-0.9.28/extra/Configs/Config.in
+===================================================================
+--- uClibc-0.9.28.orig/extra/Configs/Config.in 2006-04-19 12:47:48.000000000 +0200
++++ uClibc-0.9.28/extra/Configs/Config.in 2006-04-19 12:48:33.000000000 +0200
+@@ -16,6 +16,9 @@ config TARGET_alpha
+ config TARGET_arm
+ bool "arm"
+
++config TARGET_avr32
++ bool "avr32"
++
+ config TARGET_bfin
+ bool "bfin"
+
+@@ -83,6 +86,10 @@ if TARGET_arm
+ source "extra/Configs/Config.arm"
+ endif
+
++if TARGET_avr32
++source "extra/Configs/Config.avr32"
++endif
++
+ if TARGET_bfin
+ source "extra/Configs/Config.bfin"
+ endif
+Index: uClibc-0.9.28/include/elf.h
+===================================================================
+--- uClibc-0.9.28.orig/include/elf.h 2006-04-19 12:47:48.000000000 +0200
++++ uClibc-0.9.28/include/elf.h 2006-05-05 09:28:38.000000000 +0200
+@@ -261,6 +261,8 @@ typedef struct
+ #define EM_NIOS32 0xfebb /* Altera Nios 32 */
+ #define EM_ALTERA_NIOS2 0x9ee5 /* Altera Nios II */
+
++#define EM_AVR32 0x18ad
++
+ /* V850 backend magic number. Written in the absense of an ABI. */
+ #define EM_CYGNUS_V850 0x9080
+
+@@ -2687,6 +2689,55 @@ typedef Elf32_Addr Elf32_Conflict;
+ /* Keep this the last entry. */
+ #define R_V850_NUM 25
+
++/* Atmel AVR32 relocations. */
++#define R_AVR32_NONE 0
++#define R_AVR32_32 1
++#define R_AVR32_16 2
++#define R_AVR32_8 3
++#define R_AVR32_32_PCREL 4
++#define R_AVR32_16_PCREL 5
++#define R_AVR32_8_PCREL 6
++#define R_AVR32_DIFF32 7
++#define R_AVR32_DIFF16 8
++#define R_AVR32_DIFF8 9
++#define R_AVR32_GOT32 10
++#define R_AVR32_GOT16 11
++#define R_AVR32_GOT8 12
++#define R_AVR32_21S 13
++#define R_AVR32_16U 14
++#define R_AVR32_16S 15
++#define R_AVR32_8S 16
++#define R_AVR32_8S_EXT 17
++#define R_AVR32_22H_PCREL 18
++#define R_AVR32_18W_PCREL 19
++#define R_AVR32_16B_PCREL 20
++#define R_AVR32_16N_PCREL 21
++#define R_AVR32_14UW_PCREL 22
++#define R_AVR32_11H_PCREL 23
++#define R_AVR32_10UW_PCREL 24
++#define R_AVR32_9H_PCREL 25
++#define R_AVR32_9UW_PCREL 26
++#define R_AVR32_HI16 27
++#define R_AVR32_LO16 28
++#define R_AVR32_GOTPC 29
++#define R_AVR32_GOTCALL 30
++#define R_AVR32_LDA_GOT 31
++#define R_AVR32_GOT21S 32
++#define R_AVR32_GOT18SW 33
++#define R_AVR32_GOT16S 34
++#define R_AVR32_GOT7UW 35
++#define R_AVR32_32_CPENT 36
++#define R_AVR32_CPCALL 37
++#define R_AVR32_16_CP 38
++#define R_AVR32_9W_CP 39
++#define R_AVR32_RELATIVE 40
++#define R_AVR32_GLOB_DAT 41
++#define R_AVR32_JMP_SLOT 42
++#define R_AVR32_ALIGN 43
++#define R_AVR32_NUM 44
++
++/* AVR32 dynamic tags */
++#define DT_AVR32_GOTSZ 0x70000001 /* Total size of GOT in bytes */
+
+ #define R_H8_NONE 0
+ #define R_H8_DIR32 1
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/Makefile
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/Makefile 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,93 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++TOPDIR=../../../../
++include $(TOPDIR)Rules.mak
++ASFLAGS=$(CFLAGS)
++
++CRT_SRC = crt1.S
++CRT_OBJ = crt1.o
++SCRT_OBJ = $(patsubst %,S%, $(CRT_OBJ))
++CTOR_TARGETS=$(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o
++
++SSRC=__longjmp.S setjmp.S bsd-setjmp.S vfork.S \
++ bsd-_setjmp.S sigrestorer.S syscall.S
++SOBJS=$(patsubst %.S,%.o, $(SSRC))
++
++CSRC=clone.c brk.c sigaction.c mmap.c
++COBJS=$(patsubst %.c,%.o, $(CSRC))
++
++OBJS=$(SOBJS) $(COBJS)
++
++OBJ_LIST=../../../obj.sysdeps.$(TARGET_ARCH)
++
++all: $(OBJ_LIST)
++
++$(OBJ_LIST): $(OBJS) $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS)
++ echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $(OBJ_LIST)
++ $(INSTALL) -d $(TOPDIR)lib/
++ cp $(CRT_OBJ) $(SCRT_OBJ) $(TOPDIR)lib/
++
++$(CRT_OBJ): $(CRT_SRC)
++ $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++$(SCRT_OBJ): $(CRT_SRC)
++ $(CC) $(ASFLAGS) $(PIEFLAG) -DL_$* $< -c -o $*.o
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++$(SOBJS): %.o : %.S
++ $(CC) $(ASFLAGS) -c $< -o $@
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++$(COBJS): %.o : %.c
++ $(CC) $(CFLAGS) -c $< -o $@
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y)
++crti.o: crti.S
++ $(CC) $(ASFLAGS) -c crti.S -o crti.o
++
++$(TOPDIR)lib/crti.o: crti.o
++ $(INSTALL) -d $(TOPDIR)lib/
++ cp crti.o $(TOPDIR)lib/
++
++crtn.o: crtn.S
++ $(CC) $(ASFLAGS) -c crtn.S -o crtn.o
++
++$(TOPDIR)lib/crtn.o: crtn.o
++ $(INSTALL) -d $(TOPDIR)lib/
++ cp crtn.o $(TOPDIR)lib/
++else
++$(TOPDIR)lib/crti.o:
++ $(INSTALL) -d $(TOPDIR)lib/
++ $(AR) $(ARFLAGS) $(TOPDIR)lib/crti.o
++$(TOPDIR)lib/crtn.o:
++ $(INSTALL) -d $(TOPDIR)lib/
++ $(AR) $(ARFLAGS) $(TOPDIR)lib/crtn.o
++endif
++
++
++headers:
++# $(LN) -fs ../libc/sysdeps/linux/avr32/fpu_control.h $(TOPDIR)/include/
++
++clean:
++ $(RM) *.[oa] *~ core
++ $(RM) bits/sysnum.h
++ $(RM) gmon-start.S
++
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/__longjmp.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/__longjmp.S 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,17 @@
++/* longjmp for AVR32
++ *
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++
++ .global __longjmp
++ .type __longjmp,"function"
++ .align 1
++__longjmp:
++ ldm r12++, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr
++ mov r12, r11 /* get the return value right */
++ mustr r8 /* restore status register (lower half) */
++ cp r12, 0 /* can't return zero */
++ frs
++ moveq r12, 1
++ mov pc,lr
++ .size __longjmp, . - __longjmp
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/_mmap.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/_mmap.c 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,33 @@
++/* Copyright (C) 2005 Atmel Norway
++
++ This program is free software; you can redistribute it and/or modify it under
++ the terms of the GNU Library General Public License as published by the Free
++ Software Foundation; either version 2 of the License, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++ details.
++
++ You should have received a copy of the GNU Library General Public License
++ along with this program; if not, write to the Free Software Foundation, Inc.,
++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ 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.
++ */
++
++#include <errno.h>
++#include <sys/mman.h>
++#include <sys/syscall.h>
++
++#define __NR_mmap2 __NR_mmap
++
++static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, __off_t, pgoff);
++
++__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
++{
++ return mmap2(addr, len, prot, flags, fd, offset >> 12);
++}
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/atomicity.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/atomicity.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,86 @@
++/* Low-level functions for atomic operations. AVR32 version.
++ Copyright (C) 1997, 1998, 1999, 2000 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _ATOMICITY_H
++#define _ATOMICITY_H 1
++
++#include <inttypes.h>
++
++static inline int
++__attribute__((unused))
++exchange_and_add (volatile uint32_t *mem, int val)
++{
++ int tmp, result;
++
++ __asm__ __volatile__(
++ "/* Inline exchange and add */\n"
++ "1: ssrf 5\n"
++ " ld.w %0, %3\n"
++ " add %1, %0, %4\n"
++ " stcond %2, %1\n"
++ " brne 1b"
++ : "=&r"(result), "=&r"(tmp), "=m"(*mem)
++ : "m"(*mem), "r"(val)
++ : "cc", "memory");
++
++ return result;
++}
++
++static inline void
++__attribute__((unused))
++atomic_add (volatile uin32_t *mem, int val)
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline atomic add */\n"
++ "1: ssrf 5\n"
++ " ld.w %0, %2\n"
++ " add %0, %3\n"
++ " stcond %2, %0\n"
++ " brne 1b"
++ : "=&r"(result), "=m"(*mem)
++ : "m"(*mem), "r"(val)
++ : "cc", "memory");
++}
++
++static inline int
++__attribute__((unused))
++compare_and_swap(volatile long int *p, long int oldval, long int newval)
++{
++ long int result, tmp;
++
++ __asm__ __volatile__(
++ "/* Inline compare and swap */\n"
++ "1: ssrf 5\n"
++ " ld.w %1, %3\n"
++ " cp.w %1, %5\n"
++ " sreq %0\n"
++ " brne 2f\n"
++ " stcond %2, %4\n"
++ " brne 1b\n"
++ "2:"
++ : "=&r"(result), "=&r"(tmp), "=m"(*p)
++ : "m"(*p), "r"(newval), "r"(oldval)
++ : "cc", "memory");
++
++ return result;
++}
++
++#endif /* atomicity.h */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/byteswap.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/byteswap.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,80 @@
++/* Macros to swap the order of bytes in integer values.
++ Copyright (C) 2005 Atmel Norway.
++
++ 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. */
++
++#if !defined _BYTESWAP_H && !defined _NETINET_IN_H
++# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
++#endif
++
++#ifndef _BITS_BYTESWAP_H
++#define _BITS_BYTESWAP_H 1
++
++/* Swap bytes in 16 bit value. */
++#if defined __GNUC__
++# define __bswap_16(x) (__extension__ __builtin_bswap_16(x))
++#else
++/* This is better than nothing. */
++static __inline unsigned short int
++__bswap_16 (unsigned short int __bsx)
++{
++ return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
++}
++#endif
++
++/* Swap bytes in 32 bit value. */
++#if defined __GNUC__
++# define __bswap_32(x) (__extension__ __builtin_bswap_32(x))
++#else
++static __inline unsigned int
++__bswap_32 (unsigned int __bsx)
++{
++ return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
++ (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));
++}
++#endif
++
++#if defined __GNUC__
++/* Swap bytes in 64 bit value. */
++# define __bswap_constant_64(x) \
++ ((((x) & 0xff00000000000000ull) >> 56) \
++ | (((x) & 0x00ff000000000000ull) >> 40) \
++ | (((x) & 0x0000ff0000000000ull) >> 24) \
++ | (((x) & 0x000000ff00000000ull) >> 8) \
++ | (((x) & 0x00000000ff000000ull) << 8) \
++ | (((x) & 0x0000000000ff0000ull) << 24) \
++ | (((x) & 0x000000000000ff00ull) << 40) \
++ | (((x) & 0x00000000000000ffull) << 56))
++
++# define __bswap_64(x) \
++ (__extension__ \
++ ({ \
++ union { \
++ __extension__ unsigned long long int __ll; \
++ unsigned int __l[2]; \
++ } __w, __r; \
++ if (__builtin_constant_p(x)) \
++ __r.__ll = __bswap_constant_64(x); \
++ else { \
++ __w.__ll = (x); \
++ __r.__l[0] = __bswap_32(__w.__l[1]); \
++ __r.__l[1] = __bswap_32(__w.__l[0]); \
++ } \
++ __r.__ll; \
++ }))
++#endif
++
++#endif /* _BITS_BYTESWAP_H */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/endian.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/endian.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,7 @@
++/* AVR32 is big-endian */
++
++#ifndef _ENDIAN_H
++# error "Never use <bits/endian.h> directly; include <endian.h> instead."
++#endif
++
++#define __BYTE_ORDER __BIG_ENDIAN
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/fcntl.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/fcntl.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,167 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ *
++ * This file is part of the Linux kernel
++ */
++#ifndef _FCNTL_H
++# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
++#endif
++
++#include <sys/types.h>
++
++/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
++ located on an ext2 file system */
++#define O_ACCMODE 0003
++#define O_RDONLY 00
++#define O_WRONLY 01
++#define O_RDWR 02
++#define O_CREAT 0100 /* not fcntl */
++#define O_EXCL 0200 /* not fcntl */
++#define O_NOCTTY 0400 /* not fcntl */
++#define O_TRUNC 01000 /* not fcntl */
++#define O_APPEND 02000
++#define O_NONBLOCK 04000
++#define O_NDELAY O_NONBLOCK
++#define O_SYNC 010000
++#define O_ASYNC 020000
++
++#ifdef __USE_GNU
++# define O_DIRECTORY 040000 /* must be a directory */
++# define O_NOFOLLOW 0100000 /* don't follow links */
++# define O_DIRECT 0200000 /* direct disk access */
++#endif
++
++#ifdef __USE_LARGEFILE64
++# define O_LARGEFILE 0400000
++#endif
++
++/* For now Linux has synchronisity options for data and read operations.
++ We define the symbols here but let them do the same as O_SYNC since
++ this is a superset. */
++#if defined __USE_POSIX199309 || defined __USE_UNIX98
++# define O_DSYNC O_SYNC /* Synchronize data. */
++# define O_RSYNC O_SYNC /* Synchronize read operations. */
++#endif
++
++#define F_DUPFD 0 /* dup */
++#define F_GETFD 1 /* get close_on_exec */
++#define F_SETFD 2 /* set/clear close_on_exec */
++#define F_GETFL 3 /* get file->f_flags */
++#define F_SETFL 4 /* set file->f_flags */
++
++#ifndef __USE_FILE_OFFSET64
++# define F_GETLK 5
++# define F_SETLK 6
++# define F_SETLKW 7
++#else
++# define F_GETLK F_GETLK64
++# define F_SETLK F_SETLK64
++# define F_SETLKW F_SETLKW64
++#endif
++#define F_GETLK64 12 /* using 'struct flock64' */
++#define F_SETLK64 13
++#define F_SETLKW64 14
++
++#if defined __USE_BSD || defined __USE_XOPEN2K
++# define F_SETOWN 8 /* for sockets. */
++# define F_GETOWN 9 /* for sockets. */
++#endif
++
++#ifdef __USE_GNU
++# define F_SETSIG 10 /* for sockets. */
++# define F_GETSIG 11 /* for sockets. */
++#endif
++
++#ifdef __USE_GNU
++# define F_SETLEASE 1024 /* Set a lease. */
++# define F_GETLEASE 1025 /* Enquire what lease is active. */
++# define F_NOTIFY 1026 /* Request notfications on a directory. */
++#endif
++
++/* for F_[GET|SET]FL */
++#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
++
++/* for posix fcntl() and lockf() */
++#define F_RDLCK 0
++#define F_WRLCK 1
++#define F_UNLCK 2
++
++/* for old implementation of bsd flock () */
++#define F_EXLCK 4 /* or 3 */
++#define F_SHLCK 8 /* or 4 */
++
++/* for leases */
++#define F_INPROGRESS 16
++
++#ifdef __USE_BSD
++/* operations for bsd flock(), also used by the kernel implementation */
++# define LOCK_SH 1 /* shared lock */
++# define LOCK_EX 2 /* exclusive lock */
++# define LOCK_NB 4 /* or'd with one of the above to prevent
++ blocking */
++# define LOCK_UN 8 /* remove lock */
++#endif
++
++#ifdef __USE_GNU
++# define LOCK_MAND 32 /* This is a mandatory flock */
++# define LOCK_READ 64 /* ... Which allows concurrent
++ read operations */
++# define LOCK_WRITE 128 /* ... Which allows concurrent
++ write operations */
++# define LOCK_RW 192 /* ... Which allows concurrent
++ read & write ops */
++#endif
++
++#ifdef __USE_GNU
++/* Types of directory notifications that may be requested with F_NOTIFY. */
++# define DN_ACCESS 0x00000001 /* File accessed. */
++# define DN_MODIFY 0x00000002 /* File modified. */
++# define DN_CREATE 0x00000004 /* File created. */
++# define DN_DELETE 0x00000008 /* File removed. */
++# define DN_RENAME 0x00000010 /* File renamed. */
++# define DN_ATTRIB 0x00000020 /* File changed attibutes. */
++# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */
++#endif
++
++struct flock {
++ short l_type;
++ short l_whence;
++#ifndef __USE_FILE_OFFSET64
++ __off_t l_start;
++ __off_t l_len;
++#else
++ __off64_t l_start;
++ __off64_t l_len;
++#endif
++ __pid_t l_pid;
++};
++
++#ifdef __USE_LARGEFILE64
++struct flock64 {
++ short l_type;
++ short l_whence;
++ __off64_t l_start;
++ __off64_t l_len;
++ __pid_t l_pid;
++};
++#endif
++
++/* Define some more compatibility macros to be backward compatible with
++ * BSD systems which did not managed to hide these kernel macros. */
++#ifdef __USE_BSD
++# define FAPPEND O_APPEND
++# define FFSYNC O_FSYNC
++# define FASYNC O_ASYNC
++# define FNONBLOCK O_NONBLOCK
++# define FNDELAY O_NDELAY
++#endif /* Use BSD. */
++
++/* Advise to `posix_fadvise'. */
++#ifdef __USE_XOPEN2K
++# define POSIX_FADV_NORMAL 0 /* No further special treatment. */
++# define POSIX_FADV_RANDOM 1 /* Expect random page references. */
++# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */
++# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
++# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
++#endif
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/kernel_stat.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/kernel_stat.h 2006-05-05 09:28:32.000000000 +0200
+@@ -0,0 +1,63 @@
++#ifndef _BITS_STAT_STRUCT_H
++#define _BITS_STAT_STRUCT_H
++
++/*
++ * This file provides struct stat, taken from kernel 2.6.4
++ * (include/asm-avr32/stat.h revision 1.1).
++ */
++
++struct kernel_stat {
++ unsigned long st_dev;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned long st_rdev;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#define STAT_HAVE_NSEC 1
++
++struct kernel_stat64 {
++ unsigned long long st_dev;
++
++ unsigned long long st_ino;
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++
++ long long st_size;
++ unsigned long __pad1;
++ unsigned long st_blksize;
++
++ unsigned long long st_blocks;
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* _BITS_STAT_STRUCT_H */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/kernel_types.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/kernel_types.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,56 @@
++/* Note that we use the exact same include guard #define names
++ * as asm/posix_types.h. This will avoid gratuitous conflicts
++ * with the posix_types.h kernel header, and will ensure that
++ * our private content, and not the kernel header, will win.
++ * -Erik
++ */
++#ifndef __ASM_AVR32_POSIX_TYPES_H
++#define __ASM_AVR32_POSIX_TYPES_H
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_dev_t;
++typedef unsigned long __kernel_ino_t;
++typedef unsigned short __kernel_mode_t;
++typedef unsigned short __kernel_nlink_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned short __kernel_ipc_pid_t;
++typedef unsigned int __kernel_uid_t;
++typedef unsigned int __kernel_gid_t;
++typedef unsigned long __kernel_size_t;
++typedef int __kernel_ssize_t;
++typedef int __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_suseconds_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++
++typedef unsigned short __kernel_old_uid_t;
++typedef unsigned short __kernel_old_gid_t;
++typedef unsigned short __kernel_old_dev_t;
++
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++
++typedef struct {
++#if defined(__USE_ALL)
++ int val[2];
++#else
++ int __val[2];
++#endif
++} __kernel_fsid_t;
++
++#endif /* __ASM_AVR32_POSIX_TYPES_H */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/machine-gmon.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/machine-gmon.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,69 @@
++/* Machine-dependent definitions for profiling support. AVR32 version.
++ Copyright (C) 1996, 1997, 1998 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#define mcount_internal __mcount_internal
++
++#define _MCOUNT_DECL(frompc, selfpc) \
++static void __attribute((used)) mcount_internal(unsigned long frompc, unsigned long selfpc)
++
++/*
++ * This mcount implementation expects to get called after the prologue
++ * has been run. It also expects that r7 contains a valid frame
++ * pointer.
++ *
++ * When profiling, the compiler should generate something like this at
++ * each function entry:
++ *
++ * pushm r0-r7,lr // lr mandatory, others optional
++ * mov r7, sp
++ * // rest of prologue goes here
++ * mcall pc[.LC1 - .]
++ * // rest of function goes here
++ * .LC1:
++ * .long mcount
++ *
++ * or for PIC:
++ *
++ * pushm r0-r7,lr
++ * mov r7, sp
++ * // rest of prologue goes here
++ * lddpc r0, .LC1
++ * .L1: rsub r0, pc
++ * mcall r0[mcount@GOT]
++ * // rest of function goes here
++ * .LC1:
++ * .long .L1 - _GLOBAL_OFFSET_TABLE_
++ *
++ * This way, when mcount() is called, r7 points to the calling
++ * function's return address. It is guaranteed that calling mcount
++ * will clobber no registers except LR, which is unavoidable.
++ */
++#define MCOUNT asm( \
++ " .align 4\n" \
++ " .global _mcount\n" \
++ " .type _mcount,@function\n" \
++ "_mcount:\n" \
++ " pushm r8-r12,lr\n" \
++ " mov r11, lr\n" \
++ " ld.w r12, r7[0]\n" \
++ " rcall __mcount_internal\n" \
++ " popm r8-r12,pc\n" \
++ " .size _mcount, . - _mcount\n" \
++ " .weak mcount\n" \
++ " mcount = _mcount");
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/mman.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/mman.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,95 @@
++/* Definitions for POSIX memory map interface. Linux/AVR32 version.
++ Copyright (C) 1997, 2000 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_MMAN_H
++# error "Never include this file directly. Use <sys/mman.h> instead"
++#endif
++
++/* The following definitions basically come from the kernel headers.
++ But the kernel header is not namespace clean. */
++
++
++/* Protections are chosen from these bits, OR'd together. The
++ implementation does not necessarily support PROT_EXEC or PROT_WRITE
++ without PROT_READ. The only guarantees are that no writing will be
++ allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
++
++#define PROT_READ 0x1 /* Page can be read. */
++#define PROT_WRITE 0x2 /* Page can be written. */
++#define PROT_EXEC 0x4 /* Page can be executed. */
++#define PROT_NONE 0x0 /* Page can not be accessed. */
++
++/* Sharing types (must choose one and only one of these). */
++#define MAP_SHARED 0x01 /* Share changes. */
++#define MAP_PRIVATE 0x02 /* Changes are private. */
++#ifdef __USE_MISC
++# define MAP_TYPE 0x0f /* Mask for type of mapping. */
++#endif
++
++/* Other flags. */
++#define MAP_FIXED 0x10 /* Interpret addr exactly. */
++#ifdef __USE_MISC
++# define MAP_FILE 0
++# define MAP_ANONYMOUS 0x20 /* Don't use a file. */
++# define MAP_ANON MAP_ANONYMOUS
++#endif
++
++/* These are Linux-specific. */
++#ifdef __USE_MISC
++# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */
++# define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */
++# define MAP_LOCKED 0x2000 /* Lock the mapping. */
++# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */
++# define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
++# define MAP_NONBLOCK 0x10000 /* do not block on IO */
++#endif
++
++/* Flags to `msync'. */
++#define MS_ASYNC 1 /* Sync memory asynchronously. */
++#define MS_SYNC 4 /* Synchronous memory sync. */
++#define MS_INVALIDATE 2 /* Invalidate the caches. */
++
++/* Flags for `mlockall'. */
++#define MCL_CURRENT 1 /* Lock all currently mapped pages. */
++#define MCL_FUTURE 2 /* Lock all additions to address
++ space. */
++
++/* Flags for `mremap'. */
++#ifdef __USE_GNU
++# define MREMAP_MAYMOVE 1
++#endif
++
++/* Advise to `madvise'. */
++#ifdef __USE_BSD
++# define MADV_NORMAL 0 /* No further special treatment. */
++# define MADV_RANDOM 1 /* Expect random page references. */
++# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define MADV_WILLNEED 3 /* Will need these pages. */
++# define MADV_DONTNEED 4 /* Don't need these pages. */
++#endif
++
++/* The POSIX people had to invent similar names for the same things. */
++#ifdef __USE_XOPEN2K
++# define POSIX_MADV_NORMAL 0 /* No further special treatment. */
++# define POSIX_MADV_RANDOM 1 /* Expect random page references. */
++# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */
++# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */
++#endif
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/profil-counter.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/profil-counter.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,26 @@
++/* Low-level statistical profiling support function. Linux/AVR32 version.
++ Copyright (C) 1996, 1997, 1998, 2002 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <signal.h>
++
++void
++profil_counter(int signo, siginfo_t *si, struct sigcontext *sc)
++{
++ profil_count((void *)sc->pc);
++}
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/setjmp.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/setjmp.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,21 @@
++/*
++ * Copyright (C) 2004-2005 Atmel Norway
++ */
++#ifndef _SETJMP_H
++# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
++#endif
++
++#ifndef _ASM
++/*
++ * The jump buffer contains r0-r7, sr, sp and lr. Other registers are
++ * not saved.
++ */
++typedef int __jmp_buf[11];
++#endif
++
++#define __JMP_BUF_SP 4
++
++/* Test if longjmp to JMPBUF would unwind the frame containing a local
++ variable at ADDRESS. */
++#define _JMPBUF_UNWINDS(jmpbuf, address) \
++ ((void *)(address) < (void *)(jmpbuf[__JMP_BUF_SP]))
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/syscalls.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/syscalls.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,143 @@
++#ifndef _SYSCALL_H
++# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
++#endif
++
++/*
++ * This includes the `__NR_<name>' syscall numbers taken from the
++ * Linux kernel header files. It also defines the traditional
++ * `SYS_<name>' macros for older programs.
++ */
++#include <bits/sysnum.h>
++
++#ifndef __set_errno
++# define __set_errno(val) (*__errno_location()) = (val)
++#endif
++#ifndef SYS_ify
++# define SYS_ify(syscall_name) (__NR_##syscall_name)
++#endif
++
++#ifndef __ASSEMBLER__
++
++#undef _syscall0
++#define _syscall0(type,name) \
++ type name(void) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 0)); \
++ }
++
++#undef _syscall1
++#define _syscall1(type,name,type1,arg1) \
++ type name(type1 arg1) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 1, arg1)); \
++ }
++
++#undef _syscall2
++#define _syscall2(type,name,type1,arg1,type2,arg2) \
++ type name(type1 arg1, type2 arg2) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 2, arg1, arg2)); \
++ }
++
++#undef _syscall3
++#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
++ type name(type1 arg1, type2 arg2, type3 arg3) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 3, arg1, \
++ arg2, arg3)); \
++ }
++
++#undef _syscall4
++#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 4, arg1, arg2, \
++ arg3, arg4)); \
++ }
++
++#undef _syscall5
++#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4,type5,arg5) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
++ type5 arg5) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 5, arg1, arg2, \
++ arg3, arg4, arg5)); \
++ }
++
++#undef _syscall6
++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4,type5,arg5,type6,arg6) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
++ type5 arg5, type6 arg6) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 6, arg1, arg2, arg3, \
++ arg4, arg5, arg6)); \
++ }
++
++#undef unlikely
++#define unlikely(x) __builtin_expect((x), 0)
++
++#undef INLINE_SYSCALL
++#define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ unsigned _sys_result = INTERNAL_SYSCALL(name, , nr, args); \
++ if (unlikely(INTERNAL_SYSCALL_ERROR_P(_sys_result, ))) { \
++ __set_errno(INTERNAL_SYSCALL_ERRNO(_sys_result, )); \
++ _sys_result = (unsigned int) -1; \
++ } \
++ (int) _sys_result; \
++ })
++
++#undef INTERNAL_SYSCALL_DECL
++#define INTERNAL_SYSCALL_DECL(err) do { } while(0)
++
++#undef INTERNAL_SYSCALL
++#define INTERNAL_SYSCALL(name, err, nr, args...) \
++ ({ \
++ register int _a1 asm ("r12"); \
++ register int _scno asm("r8") = SYS_ify(name); \
++ LOAD_ARGS_##nr (args); \
++ asm volatile ("scall /* syscall " #name " */" \
++ : "=r" (_a1) \
++ : "r"(_scno) ASM_ARGS_##nr \
++ : "lr", "cc", "memory"); \
++ _a1; \
++ })
++
++#undef INTERNAL_SYSCALL_ERROR_P
++#define INTERNAL_SYSCALL_ERROR_P(val, err) \
++ ((unsigned int)(val) >= 0xfffff001U)
++
++#undef INTERNAL_SYSCALL_ERRNO
++#define INTERNAL_SYSCALL_ERRNO(val, errr) (-(val))
++
++#define LOAD_ARGS_0() do { } while(0)
++#define ASM_ARGS_0
++#define LOAD_ARGS_1(a1) \
++ _a1 = (int) (a1); \
++ LOAD_ARGS_0()
++#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a1)
++#define LOAD_ARGS_2(a1, a2) \
++ register int _a2 asm("r11") = (int)(a2); \
++ LOAD_ARGS_1(a1)
++#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a2)
++#define LOAD_ARGS_3(a1, a2, a3) \
++ register int _a3 asm("r10") = (int)(a3); \
++ LOAD_ARGS_2(a1, a2)
++#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a3)
++#define LOAD_ARGS_4(a1, a2, a3, a4) \
++ register int _a4 asm("r9") = (int)(a4); \
++ LOAD_ARGS_3(a1, a2, a3)
++#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a4)
++#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
++ register int _a5 asm("r5") = (int)(a5); \
++ LOAD_ARGS_4(a1, a2, a3, a4)
++#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a5)
++#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
++ register int _a6 asm("r3") = (int)(a6); \
++ LOAD_ARGS_5(a1, a2, a3, a4, a5)
++#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a6)
++
++#endif /* __ASSEMBLER__ */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/wordsize.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bits/wordsize.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1 @@
++#define __WORDSIZE 32
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/brk.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/brk.c 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,23 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <errno.h>
++#include <sys/syscall.h>
++
++void *__curbrk = 0;
++
++int brk (void *addr)
++{
++ void *newbrk;
++
++ newbrk = INLINE_SYSCALL(brk, 1, addr);
++
++ __curbrk = newbrk;
++
++ if (newbrk < addr) {
++ __set_errno (ENOMEM);
++ return -1;
++ }
++
++ return 0;
++}
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bsd-_setjmp.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bsd-_setjmp.S 2006-05-05 09:26:42.000000000 +0200
+@@ -0,0 +1,12 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++
++ /* This just does a tail-call to __sigsetjmp(env, 0) */
++ .global _setjmp
++ .type _setjmp,"function"
++ .align 1
++_setjmp:
++ mov r11, 0
++ bral __sigsetjmp_internal
++ .size _setjmp, . - _setjmp
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/bsd-setjmp.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/bsd-setjmp.S 2006-05-05 09:26:42.000000000 +0200
+@@ -0,0 +1,12 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++
++ /* This just does a tail-call to __sigsetjmp(env, 1) */
++ .global setjmp
++ .type setjmp,"function"
++ .align 1
++setjmp:
++ mov r11, 1
++ bral __sigsetjmp_internal
++ .size setjmp, . - setjmp
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/clone.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/clone.c 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <errno.h>
++#include <sys/syscall.h>
++#include <unistd.h>
++
++/*
++ * I don't know if we can be absolutely certain that the fn and arg
++ * parameters are preserved when returning as the child. If the
++ * compiler stores them in registers (r0-r7), they should be.
++ */
++int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg)
++{
++ register int (*_fn)(void *arg) = fn;
++ register void *_arg = arg;
++ int err;
++
++ /* Sanity check the arguments */
++ err = -EINVAL;
++ if (!fn)
++ goto syscall_error;
++ if (!child_stack)
++ goto syscall_error;
++
++ err = INLINE_SYSCALL(clone, 2, flags, child_stack);
++ if (err < 0)
++ goto syscall_error;
++ else if (err != 0)
++ return err;
++
++ _exit(_fn(_arg));
++
++syscall_error:
++ __set_errno (-err);
++ return -1;
++}
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/crt1.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/crt1.S 2006-05-05 09:28:23.000000000 +0200
+@@ -0,0 +1,93 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ *
++ * When we enter _start, the stack looks like this:
++ * argc argument counter
++ * argv[0] pointer to program name
++ * argv[1..argc-1] pointers to program args
++ * NULL
++ * env[0..N] pointers to environment variables
++ * NULL
++ *
++ * r12 contains a function pointer to be registered with `atexit'.
++ * This is how the dynamic linker arranges to have DT_FINI functions
++ * called for shared libraries that have been loaded before this
++ * code runs.
++ *
++ * We're going to call the following function:
++ * __uClibc_main(int (*main)(int, char **, char **), int argc,
++ * char **argv, void (*app_init)(void), void (*app_fini)(void),
++ * void (*rtld_fini)(void), void *stack_end)
++ *
++ * So we need to set up things as follows:
++ * r12 = address of main
++ * r11 = argc
++ * r10 = &argv[0]
++ * r9 = address of _init
++ * r8 = address of _fini
++ * sp[0] = whatever we got passed in r12
++ */
++
++#include <features.h>
++
++ .text
++ .global _start
++ .type _start, @function
++_start:
++ /* Clear the frame pointer and link register since this is the outermost frame. */
++ mov r7, 0
++ mov lr, 0
++
++ ld.w r11, sp++ /* argc */
++ mov r10, sp /* &argv[0] */
++
++ st.w --sp, r10 /* stack_end */
++ st.w --sp, r12 /* rtld_fini */
++
++#ifdef __PIC__
++ lddpc r6, .L_GOT
++.L_RGOT:
++ rsub r6, pc
++ lda.w r9, _init
++ lda.w r8, _fini
++ lda.w r12, main
++
++ /* Ok, now run uClibc's main() -- should not return */
++ call __uClibc_main
++
++ .align 2
++.L_GOT:
++ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
++#else
++ lddpc r9, __init_addr /* app_init */
++ lddpc r8, __fini_addr /* app_fini */
++ lddpc r12, __main_addr /* main */
++
++ /* Ok, now run uClibc's main() -- should not return */
++ lddpc pc, ___uClibc_main_addr
++
++ .align 2
++__init_addr:
++ .long _init
++__fini_addr:
++ .long _fini
++__main_addr:
++ .long main
++___uClibc_main_addr:
++ .long __uClibc_main
++#endif
++ .size _start, . - _start
++
++ /*
++ * The LSB says we need this.
++ */
++ .section ".note.ABI-tag", "a"
++ .align 4
++ .long 2f - 1f /* namesz */
++ .long 4f - 3f /* descsz */
++ .long 1 /* type */
++1: .asciz "GNU" /* name */
++2: .align 4
++3: .long 0 /* Linux executable */
++ .long 2,6,0 /* Earliest compatible kernel */
++4: .align 4
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/crti.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/crti.S 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,17 @@
++
++ .section .init
++ .align 2
++ .global _init
++ .type _init, @function
++_init:
++ /* Use a four-byte instruction to avoid NOPs */
++ stm --sp, r0-r7,lr
++ .align 2
++
++ .section .fini
++ .align 2
++ .global _fini
++ .type _fini, @function
++_fini:
++ stm --sp, r0-r7,lr
++ .align 2
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/crtn.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/crtn.S 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,14 @@
++
++ .section .init
++ .align 2
++ .global _init
++ .type _init, @function
++ ldm sp++, r0-r7,pc
++ .size _init, . - _init
++
++ .section .fini
++ .align 2
++ .global _fini
++ .type _fini, @function
++ ldm sp++, r0-r7,pc
++ .size _fini, . - _fini
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/mmap.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/mmap.c 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,31 @@
++/* Copyright (C) 2005 Atmel Norway
++
++ This program is free software; you can redistribute it and/or modify it under
++ the terms of the GNU Library General Public License as published by the Free
++ Software Foundation; either version 2 of the License, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++ details.
++
++ You should have received a copy of the GNU Library General Public License
++ along with this program; if not, write to the Free Software Foundation, Inc.,
++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ 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.
++ */
++
++#include <errno.h>
++#include <sys/mman.h>
++#include <sys/syscall.h>
++
++static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, __off_t, pgoff);
++
++__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
++{
++ return mmap2(addr, len, prot, flags, fd, offset >> 12);
++}
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/setjmp.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/setjmp.S 2006-05-05 09:28:28.000000000 +0200
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#define _SETJMP_H
++#define _ASM
++#include <bits/setjmp.h>
++
++ .text
++
++ .global __sigsetjmp
++ .type __sigsetjmp,"function"
++
++ /* Create a global, hidden symbol for use by setjmp() and _setjmp().
++ If it's not hidden, the linker will complain about a relative
++ jump to a dynamic symbol when building a shared library.
++
++ Also, if a user overrides the __sigsetjmp function, he might not
++ expect the setjmp() and _setjmp() function to effectively be
++ overridden as well. */
++ .global __sigsetjmp_internal
++ .hidden __sigsetjmp_internal
++ .type __sigsetjmp_internal,"function"
++ .align 1
++__sigsetjmp:
++__sigsetjmp_internal:
++ mustr r8
++ stm r12, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr
++
++ /* Make a tail call to __sigjmp_save; it takes the same args. */
++#ifdef __PIC__
++ mov r9, r6
++ lddpc r6, .LG
++.L1: rsub r6, pc
++ ld.w r8, r6[__sigjmp_save@got]
++ mov r6, r9
++ mov pc, r8
++
++ .align 2
++.LG: .long .L1 - _GLOBAL_OFFSET_TABLE_
++#else
++ rjmp __sigjmp_save
++#endif
++ .size __sigsetjmp, . - __sigsetjmp
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sigaction.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sigaction.c 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <errno.h>
++#include <signal.h>
++#include <string.h>
++#include <sys/syscall.h>
++#include <bits/kernel_sigaction.h>
++
++#define SA_RESTORER 0x04000000
++extern void __default_rt_sa_restorer(void);
++
++/*
++ * If act is not NULL, change the action for sig to *act.
++ * If oact is not NULL, put the old action for sig in *oact.
++ */
++int __libc_sigaction(int signum, const struct sigaction *act,
++ struct sigaction *oldact)
++{
++ struct kernel_sigaction kact, koact;
++ int result;
++
++ if (act) {
++ kact.k_sa_handler = act->sa_handler;
++ memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
++ kact.sa_flags = act->sa_flags;
++ if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK))
++ kact.sa_restorer = act->sa_restorer;
++ else
++ kact.sa_restorer = __default_rt_sa_restorer;
++ kact.sa_flags |= SA_RESTORER;
++ }
++
++ result = __syscall_rt_sigaction(signum, act ? __ptrvalue(&kact) : NULL,
++ oldact ? __ptrvalue(&koact) : NULL,
++ _NSIG / 8);
++
++ if (oldact && result >= 0) {
++ oldact->sa_handler = koact.k_sa_handler;
++ memcpy(&oldact->sa_mask, &koact.sa_mask,
++ sizeof(oldact->sa_mask));
++ oldact->sa_flags = koact.sa_flags;
++ oldact->sa_restorer = koact.sa_restorer;
++ }
++
++ return result;
++}
++
++weak_alias(__libc_sigaction, sigaction)
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sigrestorer.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sigrestorer.S 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,11 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <sys/syscall.h>
++
++ .global __default_rt_sa_restorer
++ .type __default_rt_sa_restorer,"function"
++ .align 1
++__default_rt_sa_restorer:
++ mov r8, __NR_rt_sigreturn
++ scall
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/elf.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/elf.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,26 @@
++/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_ELF_H
++#define _SYS_ELF_H 1
++
++#warning "This header is obsolete; use <sys/procfs.h> instead."
++
++#include <sys/procfs.h>
++
++#endif /* sys/elf.h */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/io.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/io.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,48 @@
++/* Copyright (C) 1996, 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_IO_H
++
++#define _SYS_IO_H 1
++#include <features.h>
++
++__BEGIN_DECLS
++
++/* If TURN_ON is TRUE, request for permission to do direct i/o on the
++ port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O
++ permission off for that range. This call requires root privileges. */
++extern int ioperm (unsigned long int __from, unsigned long int __num,
++ int __turn_on) __THROW;
++
++/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero,
++ permission to access any I/O port is granted. This call requires
++ root privileges. */
++extern int iopl (int __level) __THROW;
++
++/* The functions that actually perform reads and writes. */
++extern unsigned char inb (unsigned long int port) __THROW;
++extern unsigned short int inw (unsigned long int port) __THROW;
++extern unsigned long int inl (unsigned long int port) __THROW;
++
++extern void outb (unsigned char value, unsigned long int port) __THROW;
++extern void outw (unsigned short value, unsigned long int port) __THROW;
++extern void outl (unsigned long value, unsigned long int port) __THROW;
++
++__END_DECLS
++
++#endif /* _SYS_IO_H */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/procfs.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/procfs.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,123 @@
++/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_PROCFS_H
++#define _SYS_PROCFS_H 1
++
++/* This is somewhat modelled after the file of the same name on SVR4
++ systems. It provides a definition of the core file format for ELF
++ used on Linux. It doesn't have anything to do with the /proc file
++ system, even though Linux has one.
++
++ Anyway, the whole purpose of this file is for GDB and GDB only.
++ Don't read too much into it. Don't use it for anything other than
++ GDB unless you know what you are doing. */
++
++#include <features.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/user.h>
++
++__BEGIN_DECLS
++
++/* Type for a general-purpose register. */
++typedef unsigned long elf_greg_t;
++
++/* And the whole bunch of them. We could have used `struct
++ user_regs' directly in the typedef, but tradition says that
++ the register set is an array, which does have some peculiar
++ semantics, so leave it that way. */
++#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++/* Register set for the floating-point registers. */
++typedef struct user_fpregs elf_fpregset_t;
++
++/* Signal info. */
++struct elf_siginfo
++ {
++ int si_signo; /* Signal number. */
++ int si_code; /* Extra code. */
++ int si_errno; /* Errno. */
++ };
++
++/* Definitions to generate Intel SVR4-like core files. These mostly
++ have the same names as the SVR4 types with "elf_" tacked on the
++ front to prevent clashes with Linux definitions, and the typedef
++ forms have been avoided. This is mostly like the SVR4 structure,
++ but more Linuxy, with things that Linux does not support and which
++ GDB doesn't really use excluded. */
++
++struct elf_prstatus
++ {
++ struct elf_siginfo pr_info; /* Info associated with signal. */
++ short int pr_cursig; /* Current signal. */
++ unsigned long int pr_sigpend; /* Set of pending signals. */
++ unsigned long int pr_sighold; /* Set of held signals. */
++ __pid_t pr_pid;
++ __pid_t pr_ppid;
++ __pid_t pr_pgrp;
++ __pid_t pr_sid;
++ struct timeval pr_utime; /* User time. */
++ struct timeval pr_stime; /* System time. */
++ struct timeval pr_cutime; /* Cumulative user time. */
++ struct timeval pr_cstime; /* Cumulative system time. */
++ elf_gregset_t pr_reg; /* GP registers. */
++ int pr_fpvalid; /* True if math copro being used. */
++ };
++
++
++#define ELF_PRARGSZ (80) /* Number of chars for args. */
++
++struct elf_prpsinfo
++ {
++ char pr_state; /* Numeric process state. */
++ char pr_sname; /* Char for pr_state. */
++ char pr_zomb; /* Zombie. */
++ char pr_nice; /* Nice val. */
++ unsigned long int pr_flag; /* Flags. */
++ unsigned short int pr_uid;
++ unsigned short int pr_gid;
++ int pr_pid, pr_ppid, pr_pgrp, pr_sid;
++ /* Lots missing */
++ char pr_fname[16]; /* Filename of executable. */
++ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
++ };
++
++/* The rest of this file provides the types for emulation of the
++ Solaris <proc_service.h> interfaces that should be implemented by
++ users of libthread_db. */
++
++/* Addresses. */
++typedef void *psaddr_t;
++
++/* Register sets. Linux has different names. */
++typedef elf_gregset_t prgregset_t;
++typedef elf_fpregset_t prfpregset_t;
++
++/* We don't have any differences between processes and threads,
++ therefore have only one PID type. */
++typedef __pid_t lwpid_t;
++
++/* Process status and info. In the end we do provide typedefs for them. */
++typedef struct elf_prstatus prstatus_t;
++typedef struct elf_prpsinfo prpsinfo_t;
++
++__END_DECLS
++
++#endif /* sys/procfs.h */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/ucontext.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/ucontext.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,94 @@
++/* Copyright (C) 1998, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++/* Linux/AVR32 ABI compliant context switching support. */
++
++#ifndef _SYS_UCONTEXT_H
++#define _SYS_UCONTEXT_H 1
++
++#include <features.h>
++#include <signal.h>
++#include <sys/procfs.h>
++#include <bits/sigcontext.h>
++
++typedef int greg_t;
++
++/* Number of general registers. */
++#define NGREG 16
++
++/* Container for all general registers. */
++typedef elf_gregset_t gregset_t;
++
++/* Number of each register is the `gregset_t' array. */
++enum
++{
++ R0 = 0,
++#define R0 R0
++ R1 = 1,
++#define R1 R1
++ R2 = 2,
++#define R2 R2
++ R3 = 3,
++#define R3 R3
++ R4 = 4,
++#define R4 R4
++ R5 = 5,
++#define R5 R5
++ R6 = 6,
++#define R6 R6
++ R7 = 7,
++#define R7 R7
++ R8 = 8,
++#define R8 R8
++ R9 = 9,
++#define R9 R9
++ R10 = 10,
++#define R10 R10
++ R11 = 11,
++#define R11 R11
++ R12 = 12,
++#define R12 R12
++ R13 = 13,
++#define R13 R13
++ R14 = 14,
++#define R14 R14
++ R15 = 15
++#define R15 R15
++};
++
++/* Structure to describe FPU registers. */
++typedef elf_fpregset_t fpregset_t;
++
++/* Context to describe whole processor state. */
++typedef struct
++ {
++ gregset_t gregs;
++ fpregset_t fpregs;
++ } mcontext_t;
++
++/* Userlevel context. */
++typedef struct ucontext
++{
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ struct sigcontext uc_mcontext;
++ sigset_t uc_sigmask; /* mask last for extensibility */
++} ucontext_t;
++
++#endif /* sys/ucontext.h */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/user.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/sys/user.h 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,46 @@
++#ifndef _SYS_USER_H
++#define _SYS_USER_H
++
++struct user_fpregs
++{
++
++};
++
++struct user_regs
++{
++ unsigned long sr;
++ unsigned long pc;
++ unsigned long lr;
++ unsigned long sp;
++ unsigned long r12;
++ unsigned long r11;
++ unsigned long r10;
++ unsigned long r9;
++ unsigned long r8;
++ unsigned long r7;
++ unsigned long r6;
++ unsigned long r5;
++ unsigned long r4;
++ unsigned long r3;
++ unsigned long r2;
++ unsigned long r1;
++ unsigned long r0;
++ unsigned long r12_orig;
++};
++
++struct user
++{
++ struct user_regs regs; /* general registers */
++ size_t u_tsize; /* text size (pages) */
++ size_t u_dsize; /* data size (pages) */
++ size_t u_ssize; /* stack size (pages) */
++ unsigned long start_code; /* text starting address */
++ unsigned long start_data; /* data starting address */
++ unsigned long start_stack; /* stack starting address */
++ long int signal; /* signal causing core dump */
++ struct user_regs * u_ar0; /* help gdb find registers */
++ unsigned long magic; /* identifies a core file */
++ char u_comm[32]; /* user command name */
++};
++
++#endif /* _SYS_USER_H */
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/syscall.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/syscall.S 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,81 @@
++/*
++ * syscall for AVR32/uClibc
++ *
++ * Copyright (C) 2004 Atmel Norway
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <features.h>
++
++ .text
++
++ /*
++ * long int syscall(long int sysno, ...)
++ */
++ .global syscall
++ .type syscall, @function
++ .align 2
++syscall:
++ stm --sp, r3,r5,lr
++ sub lr, sp, -12
++ mov r8, r12
++ ldm lr, r3,r5,r9-r12
++ scall
++ cp.w r12, -4095
++ brlo .Ldone
++
++#ifdef __PIC__
++ lddpc r5, .Lgot
++.Lgotcalc:
++ rsub r5, pc
++# ifdef __UCLIBC_HAS_THREADS__
++ mov r3, r12
++ mcall r5[__errno_location@got]
++ st.w r12[0], r3
++# else
++ ld.w r3, r5[errno@got]
++ st.w r3[0], r12
++# endif
++#else
++# ifdef __UCLIBC_HAS_THREADS__
++ mov r3, r12
++ mcall .Lerrno_location
++ st.w r12[0], r3
++# else
++ lddpc r3, .Lerrno
++ st.w r3[0], r12
++# endif
++#endif
++ mov r12, -1
++
++.Ldone:
++ ldm sp++, r3,r5,pc
++
++ .align 2
++#ifdef __PIC__
++.Lgot:
++ .long .Lgotcalc - _GLOBAL_OFFSET_TABLE_
++#else
++# ifdef __UCLIBC_HAS_THREADS__
++.Lerrno_location:
++ .long __errno_location
++# else
++.Lerrno:
++ .long errno
++# endif
++#endif
++
++
++ .size syscall, . - syscall
+Index: uClibc-0.9.28/libc/sysdeps/linux/avr32/vfork.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libc/sysdeps/linux/avr32/vfork.S 2006-04-19 12:48:33.000000000 +0200
+@@ -0,0 +1,55 @@
++ /*
++ * vfork for uClibc
++ *
++ * Copyright (C) 2005 Atmel Norway
++ */
++
++ /*
++ * Clone the process without copying the address space. The
++ * calling process is suspended until the child either exits
++ * or calls execve.
++ *
++ * This all means that we cannot rely on the stack to store
++ * away registers, since they will be overwritten by the child
++ * as soon as it makes another function call (e.g. execve()).
++ * Fortunately, the Linux kernel preserves LR across system calls.
++ */
++#include <features.h>
++#include <sys/syscall.h>
++
++ .global __vfork
++ .type __vfork,@function
++ .align 1
++__vfork:
++ mov r8, __NR_vfork
++ scall
++ cp.w r12, -4096
++ retls r12
++
++ /* vfork failed, so we may use the stack freely */
++ pushm r4-r7,lr
++#ifdef __PIC__
++ lddpc r6, .L_GOT
++ rsub r4, r12, 0
++.L_RGOT:
++ rsub r6, pc
++ mcall r6[__errno_location@got]
++#else
++ rsub r4, r12, 0
++ mcall .L__errno_location
++#endif
++ st.w r12[0], r4
++ popm r4-r7,pc,r12=-1
++
++ .align 2
++#ifdef __PIC__
++.L_GOT:
++ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
++#else
++.L__errno_location:
++ .long __errno_location
++#endif
++ .size __vfork, . - __vfork
++
++ .weak vfork
++ vfork = __vfork
+Index: uClibc-0.9.28/Rules.mak
+===================================================================
+--- uClibc-0.9.28.orig/Rules.mak 2006-05-05 09:26:01.000000000 +0200
++++ uClibc-0.9.28/Rules.mak 2006-05-05 09:27:17.000000000 +0200
+@@ -231,6 +231,10 @@ ifeq ($(strip $(TARGET_ARCH)),frv)
+ UCLIBC_LDSO=ld.so.1
+ endif
+
++ifeq ($(strip $(TARGET_ARCH)),avr32)
++ CPU_CFLAGS-$(CONFIG_AP7000) += -mcpu=ap7000
++endif
++
+ # Keep the check_gcc from being needlessly executed
+ ifndef PIEFLAG
+ ifneq ($(UCLIBC_BUILD_PIE),y)
+From nobody Mon Sep 17 00:00:00 2001
+Subject: [PATCH] Make linkrelax configurable
+From: HÃ¥vard Skinnemoen <hskinnemoen@atmel.com>
+Date: 1133951618 +0100
+
+Add a linkrelax option to the configure system which will give
+appropriate options to the compiler, assembler and linker to enable
+link-time optimizations.
+
+---
+
+ Rules.mak | 2 ++
+ extra/Configs/Config.avr32 | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+Index: uClibc-0.9.28/Rules.mak
+===================================================================
+--- uClibc-0.9.28.orig/Rules.mak 2006-02-08 17:58:53.000000000 +0100
++++ uClibc-0.9.28/Rules.mak 2006-02-08 17:59:07.000000000 +0100
+@@ -233,6 +233,8 @@ endif
+
+ ifeq ($(strip $(TARGET_ARCH)),avr32)
+ CPU_CFLAGS-$(CONFIG_AP7000) += -mcpu=ap7000
++ CPU_CFLAGS-$(LINKRELAX) += -masm-addr-pseudos -Wa,--pic,--linkrelax
++ CPU_LDFLAGS-$(LINKRELAX) += --relax
+ endif
+
+ # Keep the check_gcc from being needlessly executed
+Index: uClibc-0.9.28/extra/Configs/Config.avr32
+===================================================================
+--- uClibc-0.9.28.orig/extra/Configs/Config.avr32 2006-02-08 17:58:53.000000000 +0100
++++ uClibc-0.9.28/extra/Configs/Config.avr32 2006-02-08 17:59:07.000000000 +0100
+@@ -36,3 +36,7 @@ config CONFIG_AP7000
+ bool "AP7000"
+
+ endchoice
++
++config LINKRELAX
++ bool "Enable linker optimizations"
++ default n
+Subject: [PATCH] AVR32-optimized string operations
+
+Add hand-optimized AVR32-specific string operations. Some of them
+need a bit more testing, though.
+
+---
+
+ libc/string/avr32/Makefile | 40 +++++++++++
+ libc/string/avr32/bcopy.S | 15 ++++
+ libc/string/avr32/bzero.S | 12 +++
+ libc/string/avr32/memchr.S | 62 +++++++++++++++++
+ libc/string/avr32/memcmp.S | 50 +++++++++++++
+ libc/string/avr32/memcpy.S | 110 ++++++++++++++++++++++++++++++
+ libc/string/avr32/memmove.S | 114 +++++++++++++++++++++++++++++++
+ libc/string/avr32/memset.S | 60 ++++++++++++++++
+ libc/string/avr32/strcat.S | 95 ++++++++++++++++++++++++++
+ libc/string/avr32/strcmp.S | 80 ++++++++++++++++++++++
+ libc/string/avr32/strcpy.S | 63 +++++++++++++++++
+ libc/string/avr32/stringtest.c | 144 ++++++++++++++++++++++++++++++++++++++++
+ libc/string/avr32/strlen.S | 52 ++++++++++++++
+ libc/string/avr32/strncpy.S | 77 +++++++++++++++++++++
+ libc/string/avr32/test_memcpy.c | 66 ++++++++++++++++++
+ 15 files changed, 1040 insertions(+)
+
+Index: uClibc-0.9.28-avr32/libc/string/avr32/bcopy.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/bcopy.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,15 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++ .text
++ .global bcopy
++ .type bcopy, @function
++ .align 1
++bcopy:
++ /* Swap the first two arguments */
++ eor r11, r12
++ eor r12, r11
++ eor r11, r12
++ rjmp __memmove
++ .size bcopy, . - bcopy
+Index: uClibc-0.9.28-avr32/libc/string/avr32/bzero.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/bzero.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,12 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++ .text
++ .global bzero
++ .type bzero, @function
++ .align 1
++bzero:
++ mov r10, r11
++ mov r11, 0
++ rjmp __memset
+Index: uClibc-0.9.28-avr32/libc/string/avr32/Makefile
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/Makefile 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,40 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++TOPDIR=../../../
++include $(TOPDIR)Rules.mak
++
++SSRC := bcopy.S bzero.S memcmp.S memcpy.S memmove.S
++SSRC += memset.S strcmp.S strlen.S
++# memchr.S, strcat.S, strcpy.S, strncpy.S is broken
++SOBJS := $(patsubst %.S,%.o, $(SSRC))
++OBJS := $(SOBJS)
++
++OBJ_LIST:= ../../obj.string.$(TARGET_ARCH)
++
++all: $(OBJ_LIST)
++
++$(OBJ_LIST): $(OBJS)
++ echo $(addprefix string/$(TARGET_ARCH)/, $(OBJS)) > $@
++
++$(SOBJS): %.o: %.S
++ $(CC) $(ASFLAGS) -c $< -o $@
++ $(STRIPTOOL) -x -R .note -R .comment $@
++
++clean:
++ $(RM) *.[oa] *~ core
+Index: uClibc-0.9.28-avr32/libc/string/avr32/memchr.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/memchr.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,62 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define str r12
++#define chr r11
++#define len r10
++
++ .text
++ .global memchr
++ .type memchr, @function
++memchr:
++ or chr, chr, chr << 8
++ or chr, chr, chr << 16
++
++ mov r9, str
++ andl r9, 3, COH
++ brne .Lunaligned_str
++
++1: sub len, 4
++ brlt 2f
++ ld.w r8, str++
++ psub.b r9, r8, r11
++ tnbz r9
++ brne 1b
++
++ sub str, 4
++ bfextu r9, r8, 24, 8
++ cp.b r9, r11
++ reteq str
++ sub str, -1
++ bfextu r9, r8, 16, 8
++ cp.b r9, r11
++ reteq str
++ sub str, -1
++ bfextu r9, r8, 8, 8
++ cp.b r9, r11
++ reteq str
++ sub str, -1
++ retal str
++
++2: sub len, -4
++ reteq 0
++
++3: ld.ub r8, str++
++ cp.w r8, 0
++ reteq str
++ sub len, 1
++ brne 3b
++
++ retal 0
++
++.Lunaligned_str:
++1: sub len, 1
++ retlt 0
++ ld.ub r8, str++
++ cp.b r8, r11
++ reteq str
++ sub r9, 1
++ brge 1b
++
++ rjmp .Laligned_search
+Index: uClibc-0.9.28-avr32/libc/string/avr32/memcmp.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/memcmp.S 2006-10-20 10:42:09.000000000 +0200
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2004 Atmel Norway.
++ */
++
++#define s1 r12
++#define s2 r11
++#define len r10
++
++ .text
++ .global memcmp
++ .type memcmp, @function
++ .align 1
++memcmp:
++ sub len, 4
++ brlt .Lless_than_4
++
++1: ld.w r8, s1++
++ ld.w r9, s2++
++ cp.w r8, r9
++ brne .Lfound_word
++ sub len, 4
++ brge 1b
++
++.Lless_than_4:
++ sub len, -4
++ reteq 0
++
++1: ld.ub r8, s1++
++ ld.ub r9, s2++
++ sub r8, r9
++ retne r8
++ sub len, 1
++ brgt 1b
++
++ retal 0
++
++.Lfound_word:
++ psub.b r9, r8, r9
++ bfextu r8, r9, 24, 8
++ retne r8
++ bfextu r8, r9, 16, 8
++ retne r8
++ bfextu r8, r9, 8, 8
++ retne r8
++ retal r9
++
++ .size memcmp, . - memcmp
++
++ .weak bcmp
++ bcmp = memcmp
+Index: uClibc-0.9.28-avr32/libc/string/avr32/memcpy.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/memcpy.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,110 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++/* Don't use r12 as dst since we must return it unmodified */
++#define dst r9
++#define src r11
++#define len r10
++
++ .text
++ .global memcpy
++ .type memcpy, @function
++
++ .global __memcpy
++ .hidden __memcpy
++ .type __memcpy, @function
++memcpy:
++__memcpy:
++ pref src[0]
++ mov dst, r12
++
++ /* If we have less than 32 bytes, don't do anything fancy */
++ cp.w len, 32
++ brge .Lmore_than_31
++
++ sub len, 1
++ retlt r12
++1: ld.ub r8, src++
++ st.b dst++, r8
++ sub len, 1
++ brge 1b
++ retal r12
++
++.Lmore_than_31:
++ pushm r0-r7, lr
++
++ /* Check alignment */
++ mov r8, src
++ andl r8, 31, COH
++ brne .Lunaligned_src
++ mov r8, dst
++ andl r8, 3, COH
++ brne .Lunaligned_dst
++
++.Laligned_copy:
++ sub len, 32
++ brlt .Lless_than_32
++
++1: /* Copy 32 bytes at a time */
++ ldm src, r0-r7
++ sub src, -32
++ stm dst, r0-r7
++ sub dst, -32
++ sub len, 32
++ brge 1b
++
++.Lless_than_32:
++ /* Copy 16 more bytes if possible */
++ sub len, -16
++ brlt .Lless_than_16
++ ldm src, r0-r3
++ sub src, -16
++ sub len, 16
++ stm dst, r0-r3
++ sub dst, -16
++
++.Lless_than_16:
++ /* Do the remaining as byte copies */
++ neg len
++ add pc, pc, len << 2
++ .rept 15
++ ld.ub r0, src++
++ st.b dst++, r0
++ .endr
++
++ popm r0-r7, pc
++
++.Lunaligned_src:
++ /* Make src cacheline-aligned. r8 = (src & 31) */
++ rsub r8, r8, 32
++ sub len, r8
++1: ld.ub r0, src++
++ st.b dst++, r0
++ sub r8, 1
++ brne 1b
++
++ /* If dst is word-aligned, we're ready to go */
++ pref src[0]
++ mov r8, 3
++ tst dst, r8
++ breq .Laligned_copy
++
++.Lunaligned_dst:
++ /* src is aligned, but dst is not. Expect bad performance */
++ sub len, 4
++ brlt 2f
++1: ld.w r0, src++
++ st.w dst++, r0
++ sub len, 4
++ brge 1b
++
++2: neg len
++ add pc, pc, len << 2
++ .rept 3
++ ld.ub r0, src++
++ st.b dst++, r0
++ .endr
++
++ popm r0-r7, pc
++ .size memcpy, . - memcpy
+Index: uClibc-0.9.28-avr32/libc/string/avr32/memmove.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/memmove.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,114 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define dst r12
++#define src r11
++#define len r10
++
++ .text
++ .global memmove
++ .type memmove, @function
++
++ .global __memmove
++ .hidden __memmove
++ .type __memmove, @function
++memmove:
++__memmove:
++ cp.w src, dst
++ brge __memcpy
++
++ add dst, len
++ add src, len
++ pref src[-1]
++
++ /*
++ * The rest is basically the same as in memcpy.S except that
++ * the direction is reversed.
++ */
++ cp.w len, 32
++ brge .Lmore_than_31
++
++ sub len, 1
++ retlt r12
++1: ld.ub r8, --src
++ st.b --dst, r8
++ sub len, 1
++ brge 1b
++ retal r12
++
++.Lmore_than_31:
++ pushm r0-r7, lr
++
++ /* Check alignment */
++ mov r8, src
++ andl r8, 31, COH
++ brne .Lunaligned_src
++ mov r8, r12
++ andl r8, 3, COH
++ brne .Lunaligned_dst
++
++.Laligned_copy:
++ sub len, 32
++ brlt .Lless_than_32
++
++1: /* Copy 32 bytes at a time */
++ sub src, 32
++ ldm src, r0-r7
++ sub dst, 32
++ sub len, 32
++ stm dst, r0-r7
++ brge 1b
++
++.Lless_than_32:
++ /* Copy 16 more bytes if possible */
++ sub len, -16
++ brlt .Lless_than_16
++ sub src, 16
++ ldm src, r0-r3
++ sub dst, 16
++ sub len, 16
++ stm dst, r0-r3
++
++.Lless_than_16:
++ /* Do the remaining as byte copies */
++ sub len, -16
++ breq 2f
++1: ld.ub r0, --src
++ st.b --dst, r0
++ sub len, 1
++ brne 1b
++
++2: popm r0-r7, pc
++
++.Lunaligned_src:
++ /* Make src cacheline-aligned. r8 = (src & 31) */
++ sub len, r8
++1: ld.ub r0, --src
++ st.b --dst, r0
++ sub r8, 1
++ brne 1b
++
++ /* If dst is word-aligned, we're ready to go */
++ pref src[-4]
++ mov r8, 3
++ tst dst, r8
++ breq .Laligned_copy
++
++.Lunaligned_dst:
++ /* src is aligned, but dst is not. Expect bad performance */
++ sub len, 4
++ brlt 2f
++1: ld.w r0, --src
++ st.w --dst, r0
++ sub len, 4
++ brge 1b
++
++2: neg len
++ add pc, pc, len << 2
++ .rept 3
++ ld.ub r0, --src
++ st.b --dst, r0
++ .endr
++
++ popm r0-r7, pc
+Index: uClibc-0.9.28-avr32/libc/string/avr32/memset.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/memset.S 2006-10-20 10:42:15.000000000 +0200
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2004 Atmel Norway.
++ */
++
++#define s r12
++#define c r11
++#define n r10
++
++ .text
++ .global memset
++ .type memset, @function
++
++ .global __memset
++ .hidden __memset
++ .type __memset, @function
++
++ .align 1
++memset:
++__memset:
++ cp.w n, 32
++ mov r9, s
++ brge .Llarge_memset
++
++ sub n, 1
++ retlt s
++1: st.b s++, c
++ sub n, 1
++ brge 1b
++
++ retal r9
++
++.Llarge_memset:
++ mov r8, r11
++ mov r11, 3
++ bfins r8, r8, 8, 8
++ bfins r8, r8, 16, 16
++ tst s, r11
++ breq 2f
++
++1: st.b s++, r8
++ sub n, 1
++ tst s, r11
++ brne 1b
++
++2: mov r11, r9
++ mov r9, r8
++ sub n, 8
++
++3: st.d s++, r8
++ sub n, 8
++ brge 3b
++
++ /* If we are done, n == -8 and we'll skip all st.b insns below */
++ neg n
++ lsl n, 1
++ add pc, n
++ .rept 7
++ st.b s++, r8
++ .endr
++ retal r11
+Index: uClibc-0.9.28-avr32/libc/string/avr32/strcat.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/strcat.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,95 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define s1 r9
++#define s2 r11
++
++ .text
++ .global strcat
++ .type strcat, @function
++ .align 1
++strcat:
++ mov s1, r12
++
++ /* Make sure s1 is word-aligned */
++ mov r10, s1
++ andl r10, 3, COH
++ breq 2f
++
++ add pc, pc, r10 << 3
++ sub r0, r0, 0 /* 4-byte nop */
++ ld.ub r8, s1++
++ sub r8, r8, 0
++ breq 2f
++ ld.ub r8, s1++
++ sub r8, r8, 0
++ breq 3f
++ ld.ub r8, s1++
++ sub r8, r8, 0
++ breq 4f
++
++ /* Find the end of the first string */
++5: ld.w r8, s1++
++ tnbz r8
++ brne 5b
++
++ sub s1, 4
++
++ bfextu r10, r8, 24, 8
++ cp.w r10, 0
++ breq 1f
++ sub s1, -1
++ bfextu r10, r8, 16, 8
++ cp.w r10, 0
++ breq 2f
++ sub s1, -1
++ bfextu r10, r8, 8, 8
++ cp.w r10, 0
++ breq 3f
++ sub s1, -1
++ rjmp 4f
++
++ /* Now, append s2 */
++1: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++2: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++3: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++4: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++
++ /* Copy one word at a time */
++ ld.w r8, s2++
++ tnbz r8
++ breq 2f
++1: st.w r8, s2++
++ ld.w r8, s2++
++ tnbz r8
++ brne 1b
++
++ /* Copy the remaining bytes */
++ bfextu r10, r8, 24, 8
++ st.b s1++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 16, 8
++ st.b s1++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 8, 8
++ st.b s1++, r10
++ cp.w r10, 0
++ reteq r12
++ st.b s1++, r8
++ retal r12
++ .size strcat, . - strcat
+Index: uClibc-0.9.28-avr32/libc/string/avr32/strcmp.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/strcmp.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,80 @@
++/*
++ * Copyright (C) 2004 Atmel Norway.
++ */
++
++#define s1 r12
++#define s2 r11
++#define len r10
++
++ .text
++ .global strcmp
++ .type strcmp, @function
++ .align 1
++strcmp:
++ mov r8, 3
++ tst s1, r8
++ brne .Lunaligned_s1
++ tst s2, r8
++ brne .Lunaligned_s2
++
++1: ld.w r8, s1++
++ ld.w r9, s2++
++ cp.w r8, r9
++ brne 2f
++ tnbz r8
++ brne 1b
++ retal 0
++
++2: bfextu r12, r8, 24, 8
++ bfextu r11, r9, 24, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 16, 8
++ bfextu r11, r9, 16, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 8, 8
++ bfextu r11, r9, 8, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 0, 8
++ bfextu r11, r9, 0, 8
++ sub r12, r11
++ retal r12
++
++.Lunaligned_s1:
++3: tst s1, r8
++ breq 4f
++ ld.ub r10, s1++
++ ld.ub r9, s2++
++ sub r10, r9
++ retne r10
++ cp.w r9, 0
++ brne 3b
++ retal r10
++
++4: tst s2, r8
++ breq 1b
++
++.Lunaligned_s2:
++ /*
++ * s1 and s2 can't both be aligned, and unaligned word loads
++ * can trigger spurious exceptions if we cross a page boundary.
++ * Do it the slow way...
++ */
++1: ld.ub r8, s1++
++ ld.ub r9, s2++
++ sub r8, r9
++ retne r8
++ cp.w r9, 0
++ brne 1b
++ retal 0
++
++ .weak strcoll
++ strcoll = strcmp
+Index: uClibc-0.9.28-avr32/libc/string/avr32/strcpy.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/strcpy.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ *
++ * To reduce the size, this one might simply call strncpy with len = -1.
++ */
++
++#define dst r9
++#define src r11
++
++ .text
++ .global strcpy
++ .type strcpy, @function
++strcpy:
++ mov dst, r12
++
++ pref src[0]
++
++ /*
++ * Check alignment. If src is aligned but dst isn't, we can't
++ * do much about it...
++ */
++ mov r8, src
++ andl r8, 3 COH
++ brne .Lunaligned_src
++
++.Laligned_copy:
++1: ld.w r8, src++
++ tnbz r8
++ breq 2f
++ st.w dst++, r8
++ rjmp 1b
++
++2: /*
++ * Ok, r8 now contains the terminating '\0'. Copy the
++ * remaining bytes individually.
++ */
++ bfextu r10, r8, 24, 8
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 16, 8
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 8, 8
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++ st.b dst++, r8
++ retal r12
++
++.Lunaligned_src:
++ /* Copy bytes until we're aligned */
++ rsub r8, r8, 4
++ add pc, pc, r8 << 3
++ nop
++ nop
++ ld.ub r10, src++
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++
++ rjmp .Laligned_copy
+Index: uClibc-0.9.28-avr32/libc/string/avr32/stringtest.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/stringtest.c 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,144 @@
++
++#include <stdio.h>
++#include <string.h>
++#include <time.h>
++#include <sys/mman.h>
++
++#define BUF_SIZE (8 * 1024)
++
++static char *buf1;
++static char *buf1_ref;
++static char *buf2;
++
++extern void *optimized_memcpy(void *dest, void *src, size_t len);
++extern void *optimized_memmove(void *dest, void *src, size_t len);
++extern char *optimized_strcpy(char *dest, char *src);
++extern char *optimized_strncpy(char *dest, char *src, size_t len);
++
++void dump_mismatch(char *buf, char *ref, size_t len)
++{
++ int i, j;
++
++ for (i = 0; i < len; i += 16) {
++ if (memcmp(buf + i, ref + i, 16) == 0)
++ continue;
++
++ printf("%4x buf:", i);
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", buf[j]);
++ printf("\n ref:");
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", ref[j]);
++ printf("\n");
++ }
++}
++
++static void test_memcpy(int src_offset, int dst_offset, int len)
++{
++ clock_t start, old, new;
++ int i;
++
++ memset(buf1, 0x55, BUF_SIZE);
++ memset(buf1_ref, 0x55, BUF_SIZE);
++ memset(buf2, 0xaa, BUF_SIZE);
++
++ printf("Testing memcpy with offsets %d => %d and len %d...",
++ src_offset, dst_offset, len);
++
++ start = clock();
++ for (i = 0; i < 8192; i++)
++ optimized_memcpy(buf1 + dst_offset, buf2 + src_offset, len);
++ new = clock() - start;
++ start = clock();
++ for ( i = 0; i < 8192; i++)
++ memcpy(buf1_ref + dst_offset, buf2 + src_offset, len);
++ old = clock() - start;
++
++ if (memcmp(buf1, buf1_ref, BUF_SIZE) == 0)
++ printf("OK\n");
++ else {
++ printf("FAILED\n");
++ dump_mismatch(buf1, buf1_ref, BUF_SIZE);
++ }
++ printf("CPU time used: %d vs. %d\n", new, old);
++}
++
++static void test_memmove(int src_offset, int dst_offset, int len)
++{
++ clock_t start, old, new;
++
++ memset(buf1, 0x55, BUF_SIZE);
++ memset(buf1_ref, 0x55, BUF_SIZE);
++ memset(buf2, 0xaa, BUF_SIZE);
++
++ printf("Testing memmove with offsets %d => %d and len %d...",
++ src_offset, dst_offset, len);
++
++ start = clock();
++ optimized_memmove(buf1 + dst_offset, buf2 + src_offset, len);
++ new = clock() - start;
++ start = clock();
++ memmove(buf1_ref + dst_offset, buf2 + src_offset, len);
++ old = clock() - start;
++
++ if (memcmp(buf1, buf1_ref, BUF_SIZE) == 0)
++ printf("OK\n");
++ else {
++ printf("FAILED\n");
++ dump_mismatch(buf1, buf1_ref, BUF_SIZE);
++ }
++ printf("CPU time used: %d vs. %d\n", new, old);
++}
++
++int main(int argc, char *argv[])
++{
++ buf2 = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf2 == MAP_FAILED) {
++ perror("Failed to allocate memory for buf2");
++ return 1;
++ }
++ buf1 = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf1 == MAP_FAILED) {
++ perror("Failed to allocate memory for buf1");
++ return 1;
++ }
++ buf1_ref = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf1_ref == MAP_FAILED) {
++ perror("Failed to allocate memory for buf1_ref");
++ return 1;
++ }
++ printf("\n === MEMCPY ===\n\n");
++
++ test_memcpy(0, 0, BUF_SIZE - 32);
++ test_memcpy(0, 0, 1);
++ test_memcpy(0, 0, 31);
++ test_memcpy(0, 0, 32);
++ test_memcpy(0, 0, 127);
++ test_memcpy(0, 0, 128);
++ test_memcpy(4, 4, BUF_SIZE - 32 - 4);
++ test_memcpy(1, 1, BUF_SIZE - 32 - 1);
++ test_memcpy(1, 1, 126);
++ test_memcpy(0, 3, 128);
++ test_memcpy(1, 4, 128);
++ test_memcpy(0, 0, 0);
++
++ printf("\n === MEMMOVE ===\n\n");
++
++ test_memmove(0, 0, BUF_SIZE - 32);
++ test_memmove(0, 0, 1);
++ test_memmove(0, 0, 31);
++ test_memmove(0, 0, 32);
++ test_memmove(0, 0, BUF_SIZE - 33);
++ test_memmove(0, 0, 128);
++ test_memmove(4, 4, BUF_SIZE - 32 - 4);
++ test_memmove(1, 1, BUF_SIZE - 32 - 1);
++ test_memmove(1, 1, BUF_SIZE - 130);
++ test_memmove(0, 3, BUF_SIZE - 128);
++ test_memmove(1, 4, BUF_SIZE - 128);
++ test_memmove(0, 0, 0);
++
++ return 0;
++}
+Index: uClibc-0.9.28-avr32/libc/string/avr32/strlen.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/strlen.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,52 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define str r12
++
++ .text
++ .global strlen
++ .type strlen, @function
++strlen:
++ mov r11, r12
++
++ mov r9, str
++ andl r9, 3, COH
++ brne .Lunaligned_str
++
++1: ld.w r8, str++
++ tnbz r8
++ brne 1b
++
++ sub r12, r11
++ bfextu r9, r8, 24, 8
++ cp.w r9, 0
++ subeq r12, 4
++ reteq r12
++ bfextu r9, r8, 16, 8
++ cp.w r9, 0
++ subeq r12, 3
++ reteq r12
++ bfextu r9, r8, 8, 8
++ cp.w r9, 0
++ subeq r12, 2
++ reteq r12
++ sub r12, 1
++ retal r12
++
++.Lunaligned_str:
++ add pc, pc, r9 << 3
++ sub r0, r0, 0 /* 4-byte nop */
++ ld.ub r8, str++
++ sub r8, r8, 0
++ breq 1f
++ ld.ub r8, str++
++ sub r8, r8, 0
++ breq 1f
++ ld.ub r8, str++
++ sub r8, r8, 0
++ brne 1b
++
++1: sub r12, 1
++ sub r12, r11
++ retal r12
+Index: uClibc-0.9.28-avr32/libc/string/avr32/strncpy.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/strncpy.S 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,77 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define dst r9
++#define src r11
++
++ .text
++ .global strcpy
++ .type strncpy, @function
++strncpy:
++ mov dst, r12
++
++ pref src[0]
++ mov dst, r12
++
++ /*
++ * Check alignment. If src is aligned but dst isn't, we can't
++ * do much about it...
++ */
++ mov r8, src
++ andl r8, 3 COH
++ brne .Lunaligned_src
++
++.Laligned_copy:
++ sub r10, 4
++ brlt 3f
++1: ld.w r8, src++
++ tnbz r8
++ breq 2f
++ st.w dst++, r8
++ sub r10, 4
++ brne 1b
++
++3: sub r10, -4
++ reteq r12
++
++ /* This is safe as long as src is word-aligned and r10 > 0 */
++ ld.w r8, src++
++
++2: /*
++ * Ok, r8 now contains the terminating '\0'. Copy the
++ * remaining bytes individually.
++ */
++ bfextu r11, r8, 24, 8
++ st.b dst++, r11
++ cp.w r11, 0
++ reteq r12
++ sub r10, 1
++ reteq r12
++ bfextu r11, r8, 16, 8
++ st.b dst++, r11
++ cp.w r11, 0
++ reteq r12
++ sub r10, 1
++ reteq r12
++ bfextu r11, r8, 8, 8
++ st.b dst++, r11
++ cp.w r11, 0
++ reteq r12
++ sub r10, 1
++ reteq r12
++ st.b dst++, r8
++ retal r12
++
++.Lunaligned_src:
++ /* Copy bytes until we're aligned */
++ min r8, r8, r10
++ sub r10, r8
++ sub r8, 1
++ retlt r12
++1: ld.ub r10, src++
++ st.b dst++, r10
++ sub r8, 1
++ brge 1b
++
++ rjmp .Laligned_copy
+Index: uClibc-0.9.28-avr32/libc/string/avr32/test_memcpy.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28-avr32/libc/string/avr32/test_memcpy.c 2006-10-19 15:05:52.000000000 +0200
+@@ -0,0 +1,66 @@
++
++#include <stdio.h>
++#include <string.h>
++
++#define BUF_SIZE 32768
++
++static char buf1[BUF_SIZE] __attribute__((aligned(32)));
++static char buf1_ref[BUF_SIZE] __attribute__((aligned(32)));
++static char buf2[BUF_SIZE] __attribute__((aligned(32)));
++
++extern void *new_memcpy(void *dest, void *src, size_t len);
++
++void dump_mismatch(char *buf, char *ref, size_t len)
++{
++ int i, j;
++
++ for (i = 0; i < len; i += 16) {
++ if (memcmp(buf + i, ref + i, 16) == 0)
++ continue;
++
++ printf("% 4x buf:", i);
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", buf[j]);
++ printf("\n ref:");
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", ref[j]);
++ printf("\n");
++ }
++}
++
++void test(int src_offset, int dst_offset, int len)
++{
++ memset(buf1, 0x55, sizeof(buf1));
++ memset(buf1_ref, 0x55, sizeof(buf1_ref));
++ memset(buf2, 0xaa, sizeof(buf2));
++
++ printf("Testing with offsets %d => %d and len %d...",
++ src_offset, dst_offset, len);
++
++ new_memcpy(buf1 + dst_offset, buf2 + src_offset, len);
++ memcpy(buf1_ref + dst_offset, buf2 + src_offset, len);
++
++ if (memcmp(buf1, buf1_ref, sizeof(buf1)) == 0)
++ printf("OK\n");
++ else {
++ printf("FAILED\n");
++ dump_mismatch(buf1, buf1_ref, sizeof(buf1));
++ }
++}
++
++int main(int argc, char *argv[])
++{
++ test(0, 0, BUF_SIZE);
++ test(0, 0, 1);
++ test(0, 0, 31);
++ test(0, 0, 32);
++ test(0, 0, 127);
++ test(0, 0, 128);
++ test(4, 4, BUF_SIZE - 4);
++ test(1, 1, BUF_SIZE - 1);
++ test(1, 1, 126);
++ test(0, 3, 128);
++ test(1, 4, 128);
++
++ return 0;
++}
+Subject: [PATCH] Don't include create_module() for AVR32
+
+The create_module() system call is obsolete in Linux 2.6, so the
+AVR32 kernel doesn't even have it.
+
+Come to think about it, this should be completely unnecessary as the
+create_module function is only a stub when __NR_create_module is
+undefined.
+---
+
+ libc/sysdeps/linux/common/create_module.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: uClibc-0.9.28/libc/sysdeps/linux/common/create_module.c
+===================================================================
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/common/create_module.c 2006-02-07 16:48:38.000000000 +0100
++++ uClibc-0.9.28/libc/sysdeps/linux/common/create_module.c 2006-02-07 17:17:14.000000000 +0100
+@@ -61,7 +61,8 @@ unsigned long create_module(const char *
+ {
+ return __create_module(name, size, 0, 0);
+ }
+-#else
++/* create_module is obsolete in Linux 2.6, so AVR32 doesn't have it */
++#elif !defined(__avr32__)
+ /* Sparc, MIPS, etc don't mistake return values for errors. */
+ _syscall2(unsigned long, create_module, const char *, name, size_t, size);
+ #endif
+Subject: [PATCH] ldso: Always inline _dl_memcpy()
+
+On some gcc versions, inline is merely a hint. AVR32 depends on this
+function actually getting inlined, so we need to use __always_inline
+instead of just inline.
+
+---
+
+ ldso/include/dl-string.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: uClibc-0.9.28/ldso/include/dl-string.h
+===================================================================
+--- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-02-07 17:01:28.000000000 +0100
++++ uClibc-0.9.28/ldso/include/dl-string.h 2006-02-07 17:03:02.000000000 +0100
+@@ -134,7 +134,7 @@ static inline char * _dl_strstr(const ch
+ } while (1);
+ }
+
+-static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
++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;
+Subject: [PATCH] ldso: Define MAP_FAILED for _dl_mmap()
+
+When using mmap2() to emulate mmap(), _dl_mmap() uses MAP_FAILED to
+indicate failure. MAP_FAILED is not defined anywhere, so this patch
+defines it.
+
+---
+
+ ldso/include/dl-syscall.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+Index: uClibc-0.9.28/ldso/include/dl-syscall.h
+===================================================================
+--- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-02-07 16:49:27.000000000 +0100
++++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-02-07 17:07:06.000000000 +0100
+@@ -132,6 +132,7 @@ static inline _syscall6(__ptr_t, __sysca
+ size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+ /*always 12, even on architectures where PAGE_SHIFT != 12 */
+ #define MMAP2_PAGE_SHIFT 12
++#define MAP_FAILED ((void *) -1)
+ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+Subject: [PATCH] ldso: Always inline system calls
+
+Some versions of gcc consider inline merely a hint. AVR32 depends on
+the system calls actually being inlined, so we need to use
+__always_inline instead of just inline.
+
+---
+
+ ldso/include/dl-syscall.h | 38 +++++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+Index: uClibc-0.9.28/ldso/include/dl-syscall.h
+===================================================================
+--- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-02-07 17:07:06.000000000 +0100
++++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-02-07 17:08:47.000000000 +0100
+@@ -60,59 +60,59 @@
+ 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 inline _syscall1(void, _dl_exit, int, status);
++static __always_inline _syscall1(void, _dl_exit, int, status);
+
+ #define __NR__dl_close __NR_close
+-static inline _syscall1(int, _dl_close, int, fd);
++static __always_inline _syscall1(int, _dl_close, int, fd);
+
+ #define __NR__dl_open __NR_open
+-static inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode);
++static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode);
+
+ #define __NR__dl_write __NR_write
+-static inline _syscall3(unsigned long, _dl_write, int, fd,
++static __always_inline _syscall3(unsigned long, _dl_write, int, fd,
+ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_read __NR_read
+-static inline _syscall3(unsigned long, _dl_read, int, fd,
++static __always_inline _syscall3(unsigned long, _dl_read, int, fd,
+ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_mprotect __NR_mprotect
+-static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot);
++static __always_inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot);
+
+ #define __NR__dl_stat __NR_stat
+-static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);
++static __always_inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);
+
+ #define __NR__dl_munmap __NR_munmap
+-static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
++static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
+
+ #define __NR__dl_getuid __NR_getuid
+-static inline _syscall0(uid_t, _dl_getuid);
++static __always_inline _syscall0(uid_t, _dl_getuid);
+
+ #define __NR__dl_geteuid __NR_geteuid
+-static inline _syscall0(uid_t, _dl_geteuid);
++static __always_inline _syscall0(uid_t, _dl_geteuid);
+
+ #define __NR__dl_getgid __NR_getgid
+-static inline _syscall0(gid_t, _dl_getgid);
++static __always_inline _syscall0(gid_t, _dl_getgid);
+
+ #define __NR__dl_getegid __NR_getegid
+-static inline _syscall0(gid_t, _dl_getegid);
++static __always_inline _syscall0(gid_t, _dl_getegid);
+
+ #define __NR__dl_getpid __NR_getpid
+-static inline _syscall0(gid_t, _dl_getpid);
++static __always_inline _syscall0(gid_t, _dl_getpid);
+
+ #define __NR__dl_readlink __NR_readlink
+-static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
++static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
+
+ #ifdef __NR_mmap
+ #ifdef MMAP_HAS_6_ARGS
+ #define __NR__dl_mmap __NR_mmap
+-static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
++static __always_inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
+ int, prot, int, flags, int, fd, off_t, offset);
+ #else
+ #define __NR__dl_mmap_real __NR_mmap
+-static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++static __always_inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
+
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+ unsigned long buffer[6];
+@@ -128,12 +128,12 @@ static inline void * _dl_mmap(void * add
+ #endif
+ #elif defined __NR_mmap2
+ #define __NR___syscall_mmap2 __NR_mmap2
+-static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
++static __always_inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
+ size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+ /*always 12, even on architectures where PAGE_SHIFT != 12 */
+ #define MMAP2_PAGE_SHIFT 12
+ #define MAP_FAILED ((void *) -1)
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
+Subject: [PATCH] ldso: AVR32 support
+
+This implements the AVR32-specific parts of the dynamic linker.
+
+---
+
+ ldso/ldso/avr32/dl-debug.h | 45 +++++++++
+ ldso/ldso/avr32/dl-startup.h | 110 ++++++++++++++++++++++++
+ ldso/ldso/avr32/dl-syscalls.h | 5 +
+ ldso/ldso/avr32/dl-sysdep.h | 103 ++++++++++++++++++++++
+ ldso/ldso/avr32/elfinterp.c | 191 ++++++++++++++++++++++++++++++++++++++++++
+ ldso/ldso/avr32/resolve.S | 28 ++++++
+ 6 files changed, 482 insertions(+)
+
+Index: uClibc-0.9.28/ldso/ldso/avr32/dl-debug.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/ldso/ldso/avr32/dl-debug.h 2006-05-05 09:30:43.000000000 +0200
+@@ -0,0 +1,45 @@
++/*
++ * AVR32 ELF shared libary loader support
++ *
++ * Copyright (C) 2005 Atmel Norway
++ * 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 *_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",
++};
+Index: uClibc-0.9.28/ldso/ldso/avr32/dl-startup.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/ldso/ldso/avr32/dl-startup.h 2006-05-05 09:29:45.000000000 +0200
+@@ -0,0 +1,110 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Architecture specific code used by dl-startup.c
++ * Copyright (C) 2005 Atmel Norway
++ */
++
++/* 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 if 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(ELF32_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(ELF32_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);
++ }
++}
++
++/* Transfer control to the user's application, once the dynamic loader
++ * is done. This routine has to exit the current function, then call
++ * the _dl_elf_main function.
++ *
++ * Since our _dl_boot will simply call whatever is returned by
++ * _dl_boot2, we can just return the address we're supposed to
++ * call. */
++#define START() return _dl_elf_main;
+Index: uClibc-0.9.28/ldso/ldso/avr32/dl-syscalls.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/ldso/ldso/avr32/dl-syscalls.h 2006-05-05 09:29:25.000000000 +0200
+@@ -0,0 +1,5 @@
++/* We can't use the real errno in ldso, since it has not yet
++ * been dynamicly linked in yet. */
++extern int _dl_errno;
++#define __set_errno(X) {(_dl_errno) = (X);}
++#include "sys/syscall.h"
+Index: uClibc-0.9.28/ldso/ldso/avr32/dl-sysdep.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/ldso/ldso/avr32/dl-sysdep.h 2006-05-05 09:30:43.000000000 +0200
+@@ -0,0 +1,103 @@
++/* 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) 2004-2005 Atmel Norway
++ */
++
++/* 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"
++
++unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
++
++/* 4096 bytes alignment */
++#define PAGE_ALIGN 0xfffff000
++#define ADDR_ALIGN 0xfff
++#define OFFS_ALIGN 0x7ffff000
++
++#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 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 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 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);
++}
+Index: uClibc-0.9.28/ldso/ldso/avr32/elfinterp.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/ldso/ldso/avr32/elfinterp.c 2006-05-05 09:30:43.000000000 +0200
+@@ -0,0 +1,191 @@
++/*
++ * 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)
++{
++ struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
++ Elf32_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;
++
++#if 0
++ local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
++ gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
++
++ sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
++ + sym_index;
++ strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
++ symname = strtab + sym->st_name;
++
++#if 0
++ new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
++ tpnt->symbol_scope, tpnt,
++ resolver);
++#endif
++
++ entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
++ *entry = 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_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
++{
++ Elf32_Sym *symtab;
++ Elf32_Rela *rpnt;
++ char *strtab;
++ int i;
++
++ rpnt = (Elf32_Rela *)rel_addr;
++ rel_size /= sizeof(Elf32_Rela);
++ symtab = (Elf32_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 = ELF32_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 = ELF32_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 dyn_elf *scope,
++ Elf32_Rela *rpnt, Elf32_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
++
++ reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
++ reloc_type = ELF32_R_TYPE(rpnt->r_info);
++ symtab_index = ELF32_R_SYM(rpnt->r_info);
++ symbol_addr = 0;
++ symname = strtab + symtab[symtab_index].st_name;
++
++ if (symtab_index) {
++ symbol_addr = (unsigned long)
++ _dl_find_hash(strtab + symtab[symtab_index].st_name,
++ tpnt->symbol_scope, tpnt,
++ elf_machine_type_class(reloc_type));
++
++ /* Allow undefined references to weak symbols */
++ if (!symbol_addr &&
++ ELF32_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 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,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
++ _dl_do_reloc);
++}
+Index: uClibc-0.9.28/ldso/ldso/avr32/resolve.S
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/ldso/ldso/avr32/resolve.S 2006-05-05 09:29:25.000000000 +0200
+@@ -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 Atmel Norway
++ */
++
++#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
+Subject: [PATCH] ldso: AVR32 needs CONSTANT_STRING_GOT_FIXUP
+
+Add AVR32 to the list of architectures needing CONSTANT_STRING_GOT_FIXUP.
+
+---
+
+ ldso/include/dl-string.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: uClibc-0.9.28/ldso/include/dl-string.h
+===================================================================
+--- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-02-07 16:58:58.000000000 +0100
++++ uClibc-0.9.28/ldso/include/dl-string.h 2006-02-07 16:59:28.000000000 +0100
+@@ -271,7 +271,8 @@ static __always_inline char * _dl_simple
+ /* 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(__mips__) \
+- || defined(__sh__) || defined(__powerpc__)
++ || defined(__sh__) || defined(__powerpc__) \
++ || defined(__avr32__)
+ # define CONSTANT_STRING_GOT_FIXUP(X) \
+ if ((X) < (const char *) load_addr) (X) += load_addr
+ # define NO_EARLY_SEND_STDERR
+Subject: [PATCH] ldso: AVR32 startup hack
+
+AVR32 needs to do both PERFORM_BOOTSTRAP_GOT and a full relocation of
+the GOT. I don't quite remember why, but I think it's because some GOT
+entries just need the load address added to them, while the rest need
+the full relocation code.
+
+This patch should be revisited to figure out whether we're processing
+relocations against undefined symbols and whether that's something we
+should be doing...
+
+---
+
+ ldso/ldso/dl-startup.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+Index: uClibc-0.9.28/ldso/ldso/dl-startup.c
+===================================================================
+--- uClibc-0.9.28.orig/ldso/ldso/dl-startup.c 2006-02-07 16:49:27.000000000 +0100
++++ uClibc-0.9.28/ldso/ldso/dl-startup.c 2006-02-07 17:12:09.000000000 +0100
+@@ -217,7 +217,9 @@ static void * __attribute_used__ _dl_sta
+ /* some arches (like MIPS) we have to tweak the GOT before relocations */
+ PERFORM_BOOTSTRAP_GOT(tpnt);
+
+-#else
++#endif
++
++#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__)
+
+ /* OK, now do the relocations. We do not do a lazy binding here, so
+ that once we are done, we have considerably more flexibility. */
+@@ -259,7 +261,7 @@ static void * __attribute_used__ _dl_sta
+ rel_addr += relative_count * sizeof(ELF_RELOC);;
+ }
+
+- rpnt = (ELF_RELOC *) (rel_addr + load_addr);
++ rpnt = (ELF_RELOC *) (rel_addr /* + load_addr */);
+ for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+ reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+Subject: [PATCH] ldd: AVR32 support
+
+Add AVR32-specific definitions to ldd.
+
+---
+
+ utils/ldd.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+Index: uClibc-0.9.28/utils/ldd.c
+===================================================================
+--- uClibc-0.9.28.orig/utils/ldd.c 2006-02-07 16:48:02.000000000 +0100
++++ uClibc-0.9.28/utils/ldd.c 2006-02-07 17:13:00.000000000 +0100
+@@ -56,6 +56,11 @@
+ #define ELFCLASSM ELFCLASS32
+ #endif
+
++#if defined(__avr32__)
++#define MATCH_MACHINE(x) (x == EM_AVR32)
++#define ELFCLASSM ELFCLASS32
++#endif
++
+ #if defined(__s390__)
+ #define MATCH_MACHINE(x) (x == EM_S390)
+ #define ELFCLASSM ELFCLASS32
+Subject: [PATCH] libpthread: AVR32 support
+
+Implement pt-machine.h for AVR32.
+---
+
+ libpthread/linuxthreads/sysdeps/avr32/pt-machine.h | 92 +++++++++++++++++++++
+ 1 file changed, 92 insertions(+)
+
+Index: uClibc-0.9.28/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ uClibc-0.9.28/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h 2006-02-07 17:14:47.000000000 +0100
+@@ -0,0 +1,92 @@
++/* Machine-dependent pthreads configuration and inline functions.
++
++ Copyright (C) 2005 Atmel Norway
++ 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; see the file COPYING.LIB. If not,
++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#ifndef _PT_MACHINE_H
++#define _PT_MACHINE_H 1
++
++#include <features.h>
++
++static inline int
++_test_and_set (int *p, int v) __THROW
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline test and set */\n"
++ "1: ssrf 5\n"
++ " ld.w %0, %2\n"
++ " tst %0, %3\n"
++ " breq 2f\n"
++ " stcond %1, %3\n"
++ " brne 1b\n"
++ "2:"
++ : "=&r"(result), "=m"(*p)
++ : "m"(*p), "r"(v)
++ : "memory", "cc");
++
++ return result;
++}
++
++#ifndef PT_EI
++# define PT_EI extern inline
++#endif
++
++extern long int testandset (int *spinlock);
++extern int __compare_and_swap (long int *p, long int oldval, long int newval);
++
++/* Spinlock implementation; required. */
++PT_EI long int
++testandset (int *spinlock)
++{
++ return _test_and_set(spinlock, 1);
++}
++
++
++/* Get some notion of the current stack. Need not be exactly the top
++ of the stack, just something somewhere in the current frame. */
++#define CURRENT_STACK_FRAME stack_pointer
++register char * stack_pointer __asm__ ("sp");
++
++/* Compare-and-swap for semaphores. */
++
++#define HAS_COMPARE_AND_SWAP
++PT_EI int
++__compare_and_swap(long int *p, long int oldval, long int newval)
++{
++ long int result, tmp;
++
++ __asm__ __volatile__(
++ "/* Inline compare and swap */\n"
++ "1: ssrf 5\n"
++ " ld.w %1, %3\n"
++ " cp.w %1, %5\n"
++ " sreq %0\n"
++ " brne 2f\n"
++ " stcond %2, %4\n"
++ " brne 1b\n"
++ "2:"
++ : "=&r"(result), "=&r"(tmp), "=m"(*p)
++ : "m"(*p), "r"(newval), "r"(oldval)
++ : "cc", "memory");
++
++ return result;
++}
++
++#endif /* pt-machine.h */
+---
+ libc/sysdeps/linux/avr32/bits/fcntl.h | 33 +++++++++++++++++----------------
+ 1 file changed, 17 insertions(+), 16 deletions(-)
+
+Index: uClibc-0.9.28-avr32/libc/sysdeps/linux/avr32/bits/fcntl.h
+===================================================================
+--- uClibc-0.9.28-avr32.orig/libc/sysdeps/linux/avr32/bits/fcntl.h 2006-11-23 17:38:30.000000000 +0100
++++ uClibc-0.9.28-avr32/libc/sysdeps/linux/avr32/bits/fcntl.h 2006-11-23 17:52:15.000000000 +0100
+@@ -11,28 +11,29 @@
+
+ /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+ located on an ext2 file system */
+-#define O_ACCMODE 0003
+-#define O_RDONLY 00
+-#define O_WRONLY 01
+-#define O_RDWR 02
+-#define O_CREAT 0100 /* not fcntl */
+-#define O_EXCL 0200 /* not fcntl */
+-#define O_NOCTTY 0400 /* not fcntl */
+-#define O_TRUNC 01000 /* not fcntl */
+-#define O_APPEND 02000
+-#define O_NONBLOCK 04000
++#define O_ACCMODE 00000003
++#define O_RDONLY 00000000
++#define O_WRONLY 00000001
++#define O_RDWR 00000002
++#define O_CREAT 00000100 /* not fcntl */
++#define O_EXCL 00000200 /* not fcntl */
++#define O_NOCTTY 00000400 /* not fcntl */
++#define O_TRUNC 00001000 /* not fcntl */
++#define O_APPEND 00002000
++#define O_NONBLOCK 00004000
+ #define O_NDELAY O_NONBLOCK
+-#define O_SYNC 010000
+-#define O_ASYNC 020000
++#define O_SYNC 00010000
++#define O_ASYNC 00020000
+
+ #ifdef __USE_GNU
+-# define O_DIRECTORY 040000 /* must be a directory */
+-# define O_NOFOLLOW 0100000 /* don't follow links */
+-# define O_DIRECT 0200000 /* direct disk access */
++# define O_DIRECT 00040000 /* must be a directory */
++# define O_DIRECTORY 00200000 /* direct disk access */
++# define O_NOFOLLOW 00400000 /* don't follow links */
++# define O_NOATIME 01000000 /* don't set atime */
+ #endif
+
+ #ifdef __USE_LARGEFILE64
+-# define O_LARGEFILE 0400000
++# define O_LARGEFILE 00100000
+ #endif
+
+ /* For now Linux has synchronisity options for data and read operations.
+++ /dev/null
---- uClibc-0.9.28/Makefile.orig 2006-12-11 21:06:42.000000000 -0700
-+++ uClibc-0.9.28/Makefile 2006-12-11 21:06:53.000000000 -0700
-@@ -158,7 +158,7 @@
- $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)lib
- $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)include
- -$(INSTALL) -m 644 lib/*.[ao] $(PREFIX)$(DEVEL_PREFIX)lib/
-- if [ "$(KERNEL_SOURCE)" == "$(DEVEL_PREFIX)" ] ; then \
-+ if [ "$(KERNEL_SOURCE)" = "$(DEVEL_PREFIX)" ] ; then \
- extra_exclude="--exclude include/linux --exclude include/asm'*'" ; \
- else \
- extra_exclude="" ; \
---- uClibc-0.9.28/extra/scripts/fix_includes.sh.orig 2006-12-13 05:44:21.000000000 -0700
-+++ uClibc-0.9.28/extra/scripts/fix_includes.sh 2006-12-13 05:44:35.000000000 -0700
-@@ -1,183 +1,155 @@
- #!/bin/sh
--# Copyright (C) 2003 Erik Andersen <andersen@uclibc.org>
- #
--# This program is free software; you can redistribute it and/or
--# modify it under the terms of the GNU Library General Public
--# License as published by the Free Software Foundation; either
--# version 2 of the License, or (at your option) any later
--# version.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU Library General Public License for more details.
--#
--# You should have received a copy of the GNU Library General
--# Public License along with this program; if not, write to the
--# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
--# Boston, MA 02111-1307 USA
--
--usage () {
-- echo ""
-- echo "usage: "`basename $0`" -k KERNEL_SOURCE_DIRECTORY -t TARGET_ARCH"
-- echo ""
-- echo "This utility scans the KERNEL_SOURCE_DIRECTORY directory and"
-- echo "checks that it contains well formed kernel headers suitable"
-- echo "for inclusion as the include/linux/ directory provided by"
-- echo "uClibc."
-- echo ""
-- echo "If the specified kernel headers are present and already"
-- echo "configured for the architecture specified by TARGET_ARCH,"
-- echo "they will be used as-is."
-- echo ""
-- echo "If the specified kernel headers are missing entirely, this"
-- echo "script will return an error."
-- echo ""
-- echo "If the specified kernel headers are present, but are either"
-- echo "not yet configured or are configured for an architecture"
-- echo "different than that specified by TARGET_ARCH, this script"
-- echo "will attempt to 'fix' the kernel headers and make them"
-- echo "suitable for use by uClibc. This fixing process may fail."
-- echo "It is therefore best to always provide kernel headers that"
-- echo "are already configured for the selected architecture."
-- echo ""
-- echo "Most Linux distributions provide 'kernel-headers' packages"
-- echo "that are suitable for use by uClibc."
-- echo ""
-- echo ""
-- exit 1;
-+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
-+#
-+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-+#
-+
-+usage() {
-+ echo ""
-+ echo "usage: "`basename $0`" -k KERNEL_SOURCE_DIRECTORY -t TARGET_ARCH"
-+ echo ""
-+ echo "This utility scans the KERNEL_SOURCE_DIRECTORY directory and"
-+ echo "checks that it contains well formed kernel headers suitable"
-+ echo "for inclusion as the include/linux/ directory provided by"
-+ echo "uClibc."
-+ echo ""
-+ echo "If the specified kernel headers are present and already"
-+ echo "configured for the architecture specified by TARGET_ARCH,"
-+ echo "they will be used as-is."
-+ echo ""
-+ echo "If the specified kernel headers are missing entirely, this"
-+ echo "script will return an error."
-+ echo ""
-+ echo "If the specified kernel headers are present, but are either"
-+ echo "not yet configured or are configured for an architecture"
-+ echo "different than that specified by TARGET_ARCH, this script"
-+ echo "will attempt to 'fix' the kernel headers and make them"
-+ echo "suitable for use by uClibc. This fixing process may fail."
-+ echo "It is therefore best to always provide kernel headers that"
-+ echo "are already configured for the selected architecture."
-+ echo ""
-+ echo "Most Linux distributions provide 'kernel-headers' packages"
-+ echo "that are suitable for use by uClibc."
-+ echo ""
-+ echo ""
-+ exit 1
- }
-
--HAS_MMU="y";
-+
-+#
-+# Parse our arguments
-+#
-+HAS_MMU="y"
- while [ -n "$1" ]; do
-- case $1 in
-- -k ) shift; if [ -n "$1" ]; then KERNEL_SOURCE=$1; shift; else usage; fi; ;;
-- -t ) shift; if [ -n "$1" ]; then TARGET_ARCH=$1; shift; else usage; fi; ;;
-- -n ) shift; HAS_MMU="n"; ;;
-- -* ) usage; ;;
-- * ) usage; ;;
-- esac;
--done;
-+ case $1 in
-+ -k ) shift; if [ -n "$1" ]; then KERNEL_SOURCE=$1; shift; else usage; fi; ;;
-+ -t ) shift; if [ -n "$1" ]; then TARGET_ARCH=$1; shift; else usage; fi; ;;
-+ -n ) shift; HAS_MMU="n"; ;;
-+ -* ) usage; ;;
-+ * ) usage; ;;
-+ esac
-+done
-
--if [ ! -f "$KERNEL_SOURCE/Makefile" -a ! -f "$KERNEL_SOURCE/include/linux/version.h" ]; then
-- echo "";
-- echo "";
-- echo "The file $KERNEL_SOURCE/Makefile or $KERNEL_SOURCE/include/linux/version.h is missing!";
-- echo "Perhaps your kernel source is broken?"
-- echo "";
-- echo "";
-- exit 1;
--fi;
-
--if [ ! -d "$KERNEL_SOURCE" ]; then
-- echo "";
-- echo "";
-- echo "$KERNEL_SOURCE is not a directory";
-- echo "";
-- echo "";
-- exit 1;
--fi;
--
--if [ -f "$KERNEL_SOURCE/Makefile" ] ; then
--# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
--eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $KERNEL_SOURCE/Makefile`
--else
--ver=`grep UTS_RELEASE $KERNEL_SOURCE/include/linux/version.h | cut -d '"' -f 2`
--VERSION=`echo "$ver" | cut -d '.' -f 1`
--PATCHLEVEL=`echo "$ver" | cut -d '.' -f 2`
--if echo "$ver" | grep -q '-' ; then
--SUBLEVEL=`echo "$ver" | sed "s/${VERSION}.${PATCHLEVEL}.//" | cut -d '-' -f 1`
--EXTRAVERSION=`echo "$ver" | sed "s/${VERSION}.${PATCHLEVEL}.${SUBLEVEL}-//"`
--else
--SUBLEVEL=`echo "$ver" | cut -d '.' -f 3`
--#EXTRAVERSION=
--fi
-+#
-+# Perform some sanity checks on our kernel sources
-+#
-+if [ ! -f "$KERNEL_SOURCE/Makefile" -a ! -f "$KERNEL_SOURCE/include/linux/version.h" ]; then
-+ echo ""
-+ echo ""
-+ echo "The file $KERNEL_SOURCE/Makefile or $KERNEL_SOURCE/include/linux/version.h is missing!"
-+ echo "Perhaps your kernel source is broken?"
-+ echo ""
-+ echo ""
-+ exit 1
- fi
--if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
--then
-- echo "Unable to determine version for kernel headers"
-- echo -e "\tprovided in directory $KERNEL_SOURCE"
-- exit 1
-+if [ ! -d "$KERNEL_SOURCE" ]; then
-+ echo ""
-+ echo ""
-+ echo "$KERNEL_SOURCE is not a directory"
-+ echo ""
-+ echo ""
-+ exit 1
- fi
-
--if [ "$MAKE_IS_SILENT" != "y" ]; then
--echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
--echo -e "\n"
--echo "Using kernel headers from $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} for architecture '$TARGET_ARCH'"
--echo -e "\tprovided in directory $KERNEL_SOURCE"
--echo -e "\n"
--fi
-
-+#
- # Create a symlink to include/asm
--
-+#
- rm -f include/asm*
- if [ ! -d "$KERNEL_SOURCE/include/asm" ]; then
-- echo "";
-- echo "";
-- echo "The symlink $KERNEL_SOURCE/include/asm is missing\!";
-- echo "Perhaps you forgot to configure your kernel source?";
-- echo "You really should configure your kernel source tree so I";
-- echo "do not have to try and guess about this sort of thing.";
-- echo ""
-- echo "Attempting to guess a usable value....";
-- echo ""
-- echo "";
-- sleep 1;
--
-- if [ "$TARGET_ARCH" = "powerpc" ];then
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-ppc include/asm;
-- set +x;
-- elif [ "$TARGET_ARCH" = "mips" ];then
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-mips include/asm;
-- set +x;
-- elif [ "$TARGET_ARCH" = "arm" ];then
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-arm include/asm;
-- set +x;
-- if [ ! -L $KERNEL_SOURCE/include/asm-arm/proc ] ; then
-- if [ ! -L proc ] ; then
-- (cd include/asm;
-- ln -fs proc-armv proc;
-- ln -fs arch-ebsa285 arch);
-- fi
-+ echo ""
-+ echo ""
-+ echo "The symlink $KERNEL_SOURCE/include/asm is missing\!"
-+ echo "Perhaps you forgot to configure your kernel source?"
-+ echo "You really should configure your kernel source tree so I"
-+ echo "do not have to try and guess about this sort of thing."
-+ echo ""
-+ echo "Attempting to guess a usable value...."
-+ echo ""
-+ echo ""
-+ sleep 1
-+
-+ if [ "$TARGET_ARCH" = "powerpc" ]; then
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-ppc include/asm
-+ set +x
-+ elif [ "$TARGET_ARCH" = "mips" ]; then
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-mips include/asm
-+ set +x
-+ elif [ "$TARGET_ARCH" = "arm" ]; then
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-arm include/asm
-+ set +x
-+ if [ ! -L $KERNEL_SOURCE/include/asm-arm/proc ]; then
-+ if [ ! -L proc ]; then
-+ (
-+ cd include/asm
-+ ln -fs proc-armv proc
-+ ln -fs arch-ebsa285 arch
-+ )
-+ fi
-+ fi
-+ elif [ "$TARGET_ARCH" = "cris" ]; then
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-cris include/asm
-+ set +x
-+ elif [ "$HAS_MMU" != "y" ]; then
-+ if [ -d $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu ]; then
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu include/asm
-+ set +x
-+ else
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm
-+ set +x
-+ fi
-+ else
-+ set -x
-+ ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm
-+ set +x
- fi;
-- elif [ "$TARGET_ARCH" = "cris" ]; then
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-cris include/asm;
-- set +x;
-- elif [ "$HAS_MMU" != "y" ]; then
-- if [ -d $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu ] ; then
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-${TARGET_ARCH}nommu include/asm;
-- set +x;
-- else
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm;
-- set +x;
-- fi;
-- else
-- set -x;
-- ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm;
-- set +x;
-- fi;
- else
--# No guessing required.....
--ln -fs $KERNEL_SOURCE/include/asm include/asm
--if [ -e $KERNEL_SOURCE/include/asm-$TARGET_ARCH ] ; then
--ln -fs $KERNEL_SOURCE/include/asm-$TARGET_ARCH include/asm-$TARGET_ARCH
-+ # No guessing required.....
-+ for x in $KERNEL_SOURCE/include/asm* ; do
-+ ln -fs ${x} include/
-+ done
- fi
--fi;
-
-
-+#
- # Annoyingly, 2.6.x kernel headers also need an include/asm-generic/ directory
--if [ $VERSION -eq 2 ] && [ $PATCHLEVEL -ge 6 ] ; then
-- ln -fs $KERNEL_SOURCE/include/asm-generic include/asm-generic
--fi;
-+#
-+if [ -e $KERNEL_SOURCE/include/asm-generic ]; then
-+ rm -f include/asm-generic
-+ ln -fs $KERNEL_SOURCE/include/asm-generic include/asm-generic
-+fi
-
-
-+#
- # Create the include/linux symlink.
-+#
- rm -f include/linux
- ln -fs $KERNEL_SOURCE/include/linux include/linux
--
+++ /dev/null
-This patch supports cross-development for embedded systems by allowing the
-host version of ldconfig (ldconfig.host) to build ld.so.cache for the target.
-Changes include:
- 1) LDSO_CACHE_SUPPORT is defined for the host build.
- 2) A little-endian host can create a big-endian ld.so.cache, and vice versa.
- 3) Can use -r option without chroot(), so no need to run as superuser.
-
-Dan Howell <dahowell@directv.com>
-
-diff -urN uClibc-orig/utils/chroot_realpath.c uClibc-20050502/utils/chroot_realpath.c
---- uClibc-orig/utils/chroot_realpath.c 1969-12-31 16:00:00.000000000 -0800
-+++ uClibc-20050502/utils/chroot_realpath.c 2005-09-12 18:30:29.000000000 -0700
-@@ -0,0 +1,163 @@
-+/*
-+ * chroot_realpath.c -- reslove pathname as if inside chroot
-+ * Based on realpath.c Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU Library Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU Library Public License for more details.
-+ *
-+ * 2005/09/12: Dan Howell (modified from realpath.c to emulate chroot)
-+ */
-+
-+#ifdef HAVE_CONFIG_H
-+#include <config.h>
-+#endif
-+
-+#include <sys/types.h>
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <strings.h>
-+#include <limits.h> /* for PATH_MAX */
-+#include <sys/param.h> /* for MAXPATHLEN */
-+#include <errno.h>
-+#ifndef __set_errno
-+#define __set_errno(val) ((errno) = (val))
-+#endif
-+
-+#include <sys/stat.h> /* for S_IFLNK */
-+
-+#ifndef PATH_MAX
-+#define PATH_MAX _POSIX_PATH_MAX
-+#endif
-+
-+#define MAX_READLINKS 32
-+
-+char *chroot_realpath(const char *chroot, const char *path, char resolved_path[])
-+{
-+ char copy_path[PATH_MAX];
-+ char link_path[PATH_MAX];
-+ char got_path[PATH_MAX];
-+ char *got_path_root = got_path;
-+ char *new_path = got_path;
-+ char *max_path;
-+ int readlinks = 0;
-+ int n;
-+ int chroot_len;
-+
-+ /* Trivial case. */
-+ if (chroot == NULL || *chroot == '\0' ||
-+ (*chroot == '/' && chroot[1] == '\0')) {
-+ strcpy(resolved_path, path);
-+ return resolved_path;
-+ }
-+
-+ chroot_len = strlen(chroot);
-+
-+ if (chroot_len + strlen(path) >= PATH_MAX - 3) {
-+ __set_errno(ENAMETOOLONG);
-+ return NULL;
-+ }
-+
-+ /* Make a copy of the source path since we may need to modify it. */
-+ strcpy(copy_path, path);
-+ path = copy_path;
-+ max_path = copy_path + PATH_MAX - chroot_len - 3;
-+
-+ /* Start with the chroot path. */
-+ strcpy(new_path, chroot);
-+ new_path += chroot_len;
-+ while (*new_path == '/' && new_path > got_path)
-+ new_path--;
-+ got_path_root = new_path;
-+ *new_path++ = '/';
-+
-+ /* Expand each slash-separated pathname component. */
-+ while (*path != '\0') {
-+ /* Ignore stray "/". */
-+ if (*path == '/') {
-+ path++;
-+ continue;
-+ }
-+ if (*path == '.') {
-+ /* Ignore ".". */
-+ if (path[1] == '\0' || path[1] == '/') {
-+ path++;
-+ continue;
-+ }
-+ if (path[1] == '.') {
-+ if (path[2] == '\0' || path[2] == '/') {
-+ path += 2;
-+ /* Ignore ".." at root. */
-+ if (new_path == got_path_root + 1)
-+ continue;
-+ /* Handle ".." by backing up. */
-+ while ((--new_path)[-1] != '/');
-+ continue;
-+ }
-+ }
-+ }
-+ /* Safely copy the next pathname component. */
-+ while (*path != '\0' && *path != '/') {
-+ if (path > max_path) {
-+ __set_errno(ENAMETOOLONG);
-+ return NULL;
-+ }
-+ *new_path++ = *path++;
-+ }
-+ if (*path == '\0')
-+ /* Don't follow symlink for last pathname component. */
-+ break;
-+#ifdef S_IFLNK
-+ /* Protect against infinite loops. */
-+ if (readlinks++ > MAX_READLINKS) {
-+ __set_errno(ELOOP);
-+ return NULL;
-+ }
-+ /* See if latest pathname component is a symlink. */
-+ *new_path = '\0';
-+ n = readlink(got_path, link_path, PATH_MAX - 1);
-+ if (n < 0) {
-+ /* EINVAL means the file exists but isn't a symlink. */
-+ if (errno != EINVAL) {
-+ /* Make sure it's null terminated. */
-+ *new_path = '\0';
-+ strcpy(resolved_path, got_path);
-+ return NULL;
-+ }
-+ } else {
-+ /* Note: readlink doesn't add the null byte. */
-+ link_path[n] = '\0';
-+ if (*link_path == '/')
-+ /* Start over for an absolute symlink. */
-+ new_path = got_path_root;
-+ else
-+ /* Otherwise back up over this component. */
-+ while (*(--new_path) != '/');
-+ /* Safe sex check. */
-+ if (strlen(path) + n >= PATH_MAX - 2) {
-+ __set_errno(ENAMETOOLONG);
-+ return NULL;
-+ }
-+ /* Insert symlink contents into path. */
-+ strcat(link_path, path);
-+ strcpy(copy_path, link_path);
-+ path = copy_path;
-+ }
-+#endif /* S_IFLNK */
-+ *new_path++ = '/';
-+ }
-+ /* Delete trailing slash but don't whomp a lone slash. */
-+ if (new_path != got_path + 1 && new_path[-1] == '/')
-+ new_path--;
-+ /* Make sure it's null terminated. */
-+ *new_path = '\0';
-+ strcpy(resolved_path, got_path);
-+ return resolved_path;
-+}
-diff -urN uClibc-orig/utils/ldconfig.c uClibc-20050502/utils/ldconfig.c
---- uClibc-orig/utils/ldconfig.c 2005-05-01 23:10:12.000000000 -0700
-+++ uClibc-20050502/utils/ldconfig.c 2005-09-16 19:26:33.000000000 -0700
-@@ -22,6 +22,8 @@
- *
- * This program may be used for any purpose as long as this
- * copyright notice is kept.
-+ *
-+ * 2005/09/16: Dan Howell (modified for cross-development)
- */
-
- #include <stdio.h>
-@@ -37,6 +39,7 @@
- #include <errno.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
-+#include "bswap.h"
- #include "dl-defs.h"
-
- #define BUFFER_SIZE 4096
-@@ -56,6 +59,7 @@
- #if !defined (N_MAGIC)
- #define N_MAGIC(exec) ((exec).a_info & 0xffff)
- #endif
-+#define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff)
- /* Code indicating object file or impure executable. */
- #define OMAGIC 0407
- /* Code indicating pure executable. */
-@@ -97,6 +101,8 @@
- char *conffile = LDSO_CONF; /* default conf file */
- char *cachefile = LDSO_CACHE; /* default cache file */
- #endif
-+char *chroot_dir = NULL;
-+int byteswap = 0;
-
- struct needed_tab
- {
-@@ -117,6 +123,8 @@
- { NULL, LIB_ELF }
- };
-
-+extern char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]);
-+
-
- /* These two are used internally -- you shouldn't need to use them */
- static void verror_msg(const char *s, va_list p)
-@@ -242,6 +250,8 @@
- ElfW(Ehdr) *elf_hdr;
- struct stat statbuf;
- char buff[BUFFER_SIZE];
-+ char real[BUFFER_SIZE];
-+ static int byteswapflag = -1; /* start with byte-order unknown */
-
- /* see if name is of the form *.so* */
- if (name[strlen(name)-1] != '~' && (cp = strstr(name, ".so")))
-@@ -256,8 +266,12 @@
- sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ?
- "/" : "", name);
-
-+ /* get real path in case of chroot */
-+ if (!chroot_realpath(chroot_dir, buff, real))
-+ warn("can't resolve %s in chroot %s", buff, chroot_dir);
-+
- /* first, make sure it's a regular file */
-- if (lstat(buff, &statbuf))
-+ if (lstat(real, &statbuf))
- warn("skipping %s", buff);
- else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
- warnx("%s is not a regular file or symlink, skipping", buff);
-@@ -267,14 +281,15 @@
- *islink = S_ISLNK(statbuf.st_mode);
-
- /* then try opening it */
-- if (!(file = fopen(buff, "rb")))
-+ if (!(file = fopen(real, "rb")))
- warn("skipping %s", buff);
- else
- {
- /* now make sure it's a shared library */
- if (fread(&exec, sizeof exec, 1, file) < 1)
- warnx("can't read header from %s, skipping", buff);
-- else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC)
-+ else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC &&
-+ N_MAGIC_SWAP(exec) != ZMAGIC && N_MAGIC_SWAP(exec) != QMAGIC)
- {
- elf_hdr = (ElfW(Ehdr) *) &exec;
- if (elf_hdr->e_ident[0] != 0x7f ||
-@@ -294,6 +309,9 @@
- *type = LIB_ELF;
- good = readsoname(buff, file, expected_type, type,
- elf_hdr->e_ident[EI_CLASS]);
-+ if (byteswapflag == -1)
-+ /* byte-order detected */
-+ byteswapflag = byteswap;
- if (good == NULL || *islink)
- {
- if (good != NULL)
-@@ -313,6 +331,12 @@
- }
- else
- {
-+ /* Determine byte-order */
-+ byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1;
-+ if (byteswapflag == -1)
-+ /* byte-order detected */
-+ byteswapflag = byteswap;
-+
- if (*islink)
- good = xstrdup(name);
- else
-@@ -330,6 +354,14 @@
- *type = LIB_DLL;
- }
- fclose(file);
-+
-+ if (byteswapflag >= 0 && byteswap != byteswapflag)
-+ {
-+ byteswapflag = -2;
-+ warnx("mixed byte-order detected, using host byte-order...");
-+ }
-+ if (byteswapflag == -2)
-+ byteswap = 0;
- }
- }
- }
-@@ -343,18 +375,24 @@
- int change = 1;
- char libname[BUFFER_SIZE];
- char linkname[BUFFER_SIZE];
-+ char reallibname[BUFFER_SIZE];
-+ char reallinkname[BUFFER_SIZE];
- struct stat libstat;
- struct stat linkstat;
-
- /* construct the full path names */
- sprintf(libname, "%s/%s", dir, file);
- sprintf(linkname, "%s/%s", dir, so);
-+ if (!chroot_realpath(chroot_dir, libname, reallibname))
-+ warn("can't resolve %s in chroot %s", libname, chroot_dir);
-+ if (!chroot_realpath(chroot_dir, linkname, reallinkname))
-+ warn("can't resolve %s in chroot %s", linkname, chroot_dir);
-
- /* see if a link already exists */
-- if (!stat(linkname, &linkstat))
-+ if (!stat(reallinkname, &linkstat))
- {
- /* now see if it's the one we want */
-- if (stat(libname, &libstat))
-+ if (stat(reallibname, &libstat))
- warn("can't stat %s", libname);
- else if (libstat.st_dev == linkstat.st_dev &&
- libstat.st_ino == linkstat.st_ino)
-@@ -364,14 +402,14 @@
- /* then update the link, if required */
- if (change > 0 && !nolinks)
- {
-- if (!lstat(linkname, &linkstat))
-+ if (!lstat(reallinkname, &linkstat))
- {
- if (!S_ISLNK(linkstat.st_mode))
- {
- warnx("%s is not a symlink", linkname);
- change = -1;
- }
-- else if (remove(linkname))
-+ else if (remove(reallinkname))
- {
- warn("can't unlink %s", linkname);
- change = -1;
-@@ -379,7 +417,7 @@
- }
- if (change > 0)
- {
-- if (symlink(file, linkname))
-+ if (symlink(file, reallinkname))
- {
- warn("can't link %s to %s", linkname, file);
- change = -1;
-@@ -441,6 +479,7 @@
- char *so, *path, *path_n;
- struct lib *lp, *libs = NULL;
- int i, libtype, islink, expected_type = LIB_ANY;
-+ char realname[BUFFER_SIZE];
-
- /* We need a writable copy of this string */
- path = strdup(rawname);
-@@ -500,8 +539,12 @@
- if (verbose > 0)
- printf("%s:\n", name);
-
-+ /* get real path in case of chroot */
-+ if (!chroot_realpath(chroot_dir, name, realname))
-+ warn("can't resolve %s in chroot %s", name, chroot_dir);
-+
- /* if we can't open it, we can't do anything */
-- if ((dir = opendir(name)) == NULL)
-+ if ((dir = opendir(realname)) == NULL)
- {
- warn("skipping %s", name);
- free(path);
-@@ -596,8 +639,12 @@
- char *res = NULL, *cp;
- FILE *file;
- struct stat stat;
-+ char realconffile[BUFFER_SIZE];
-+
-+ if (!chroot_realpath(chroot_dir, conffile, realconffile))
-+ return NULL;
-
-- if ((file = fopen(conffile, "r")) != NULL)
-+ if ((file = fopen(realconffile, "r")) != NULL)
- {
- fstat(fileno(file), &stat);
- res = xmalloc(stat.st_size + 1);
-@@ -678,22 +725,38 @@
- {
- int cachefd;
- int stroffset = 0;
-+ char realcachefile[BUFFER_SIZE];
- char tempfile[BUFFER_SIZE];
-+ header_t swap_magic;
-+ header_t *magic_ptr;
-+ libentry_t swap_lib;
-+ libentry_t *lib_ptr;
- liblist_t *cur_lib;
-
- if (!magic.nlibs)
- return;
-
-- sprintf(tempfile, "%s~", cachefile);
-+ if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
-+ err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)",
-+ cachefile, chroot_dir, strerror(errno));
-+
-+ sprintf(tempfile, "%s~", realcachefile);
-
- if (unlink(tempfile) && errno != ENOENT)
-- err(EXIT_FATAL,"can't unlink %s (%s)", tempfile, strerror(errno));
-+ err(EXIT_FATAL,"can't unlink %s~ (%s)", cachefile, strerror(errno));
-
- if ((cachefd = creat(tempfile, 0644)) < 0)
-- err(EXIT_FATAL,"can't create %s (%s)", tempfile, strerror(errno));
-+ err(EXIT_FATAL,"can't create %s~ (%s)", cachefile, strerror(errno));
-
-- if (write(cachefd, &magic, sizeof (header_t)) != sizeof (header_t))
-- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
-+ if (byteswap) {
-+ swap_magic = magic;
-+ swap_magic.nlibs = bswap_32(swap_magic.nlibs);
-+ magic_ptr = &swap_magic;
-+ } else {
-+ magic_ptr = &magic;
-+ }
-+ if (write(cachefd, magic_ptr, sizeof (header_t)) != sizeof (header_t))
-+ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
-
- for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next)
- {
-@@ -701,29 +764,37 @@
- stroffset += strlen(cur_lib->soname) + 1;
- cur_lib->liboffset = stroffset;
- stroffset += strlen(cur_lib->libname) + 1;
-- if (write(cachefd, cur_lib, sizeof (libentry_t)) !=
-- sizeof (libentry_t))
-- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
-+ if (byteswap) {
-+ swap_lib.flags = bswap_32(cur_lib->flags);
-+ swap_lib.sooffset = bswap_32(cur_lib->sooffset);
-+ swap_lib.liboffset = bswap_32(cur_lib->liboffset);
-+ lib_ptr = &swap_lib;
-+ } else {
-+ lib_ptr = (libentry_t *)cur_lib;
-+ }
-+ if (write(cachefd, lib_ptr, sizeof (libentry_t)) !=
-+ sizeof (libentry_t))
-+ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
- }
-
- for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next)
- {
- if (write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1)
- != strlen(cur_lib->soname) + 1)
-- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
-+ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
- if (write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1)
- != strlen(cur_lib->libname) + 1)
-- err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
-+ err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
- }
-
- if (close(cachefd))
-- err(EXIT_FATAL,"can't close %s (%s)", tempfile, strerror(errno));
-+ err(EXIT_FATAL,"can't close %s~ (%s)", cachefile, strerror(errno));
-
- if (chmod(tempfile, 0644))
-- err(EXIT_FATAL,"can't chmod %s (%s)", tempfile, strerror(errno));
-+ err(EXIT_FATAL,"can't chmod %s~ (%s)", cachefile, strerror(errno));
-
-- if (rename(tempfile, cachefile))
-- err(EXIT_FATAL,"can't rename %s (%s)", tempfile, strerror(errno));
-+ if (rename(tempfile, realcachefile))
-+ err(EXIT_FATAL,"can't rename %s~ (%s)", cachefile, strerror(errno));
- }
-
- void cache_print(void)
-@@ -734,8 +805,13 @@
- char *strs;
- header_t *header;
- libentry_t *libent;
-+ char realcachefile[BUFFER_SIZE];
-+
-+ if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
-+ err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)",
-+ cachefile, chroot_dir, strerror(errno));
-
-- if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY))<0)
-+ if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY))<0)
- err(EXIT_FATAL,"can't read %s (%s)", cachefile, strerror(errno));
- if ((c = mmap(0,st.st_size, PROT_READ, MAP_SHARED ,fd, 0)) == (caddr_t)-1)
- err(EXIT_FATAL,"can't map %s (%s)", cachefile, strerror(errno));
-@@ -828,7 +904,6 @@
- int nodefault = 0;
- char *cp, *dir, *so;
- int libtype, islink;
-- char *chroot_dir = NULL;
- int printcache = 0;
- #ifdef __LDSO_CACHE_SUPPORT__
- char *extpath;
-@@ -891,10 +966,16 @@
- }
-
- if (chroot_dir && *chroot_dir) {
-- if (chroot(chroot_dir) < 0)
-- err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
-- if (chdir("/") < 0)
-- err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno));
-+ if (chroot(chroot_dir) < 0) {
-+ if (chdir(chroot_dir) < 0)
-+ err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
-+ }
-+ else
-+ {
-+ if (chdir("/") < 0)
-+ err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno));
-+ chroot_dir = NULL;
-+ }
- }
-
- /* allow me to introduce myself, hi, my name is ... */
-diff -urN uClibc-orig/utils/Makefile uClibc-20050502/utils/Makefile
---- uClibc-orig/utils/Makefile 2005-05-01 23:10:12.000000000 -0700
-+++ uClibc-20050502/utils/Makefile 2005-09-16 19:28:55.000000000 -0700
-@@ -29,6 +29,12 @@
- TARGET_ICONV =
- endif
-
-+ifeq ($(strip $(LDSO_CACHE_SUPPORT)),y)
-+HOST_LDSO_CACHE_FLAG = -D__LDSO_CACHE_SUPPORT__=1
-+else
-+HOST_LDSO_CACHE_FLAG =
-+endif
-+
- # NOTE: We build the utils AFTER we have a uClibc-targeted toolchain.
-
- ifeq ($(strip $(HAVE_SHARED)),y)
-@@ -51,7 +57,7 @@
- else
- LDCONFIG_CFLAGS := $(PIEFLAG) $(LDPIEFLAG)
- endif
--ldconfig: ldconfig.c
-+ldconfig: ldconfig.c chroot_realpath.c
- $(CC) $(CFLAGS) $(LDCONFIG_CFLAGS) \
- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
- -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
-@@ -79,13 +85,13 @@
-
- ldd.host: ldd.c
- $(HOSTCC) $(HOSTCFLAGS) -Wl,-s \
-- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
-+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \
- -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
- $^ -o $@
-
--ldconfig.host: ldconfig.c
-+ldconfig.host: ldconfig.c chroot_realpath.c
- $(HOSTCC) $(HOSTCFLAGS) -Wl,-s \
-- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
-+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \
- -DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
- $^ -o $@
-
-diff -urN uClibc-orig/utils/readsoname2.c uClibc-20050502/utils/readsoname2.c
---- uClibc-orig/utils/readsoname2.c 2005-05-01 23:10:12.000000000 -0700
-+++ uClibc-20050502/utils/readsoname2.c 2005-09-16 17:48:59.000000000 -0700
-@@ -26,7 +26,7 @@
-
- if (fstat(fileno(infile), &st))
- return NULL;
-- header = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(infile), 0);
-+ header = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(infile), 0);
- if (header == (caddr_t)-1)
- return NULL;
-
-@@ -34,6 +34,19 @@
- if ((char *)(epnt+1) > (char *)(header + st.st_size))
- goto skip;
-
-+#if __BYTE_ORDER == __LITTLE_ENDIAN
-+ byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0;
-+#elif __BYTE_ORDER == __BIG_ENDIAN
-+ byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0;
-+#else
-+#error Unknown host byte order!
-+#endif
-+ /* Be very lazy, and only byteswap the stuff we use */
-+ if (byteswap==1) {
-+ epnt->e_phoff=bswap_32(epnt->e_phoff);
-+ epnt->e_phnum=bswap_16(epnt->e_phnum);
-+ }
-+
- ppnt = (ElfW(Phdr) *)&header[epnt->e_phoff];
- if ((char *)ppnt < (char *)header ||
- (char *)(ppnt+epnt->e_phnum) > (char *)(header + st.st_size))
-@@ -41,6 +54,14 @@
-
- for(i = 0; i < epnt->e_phnum; i++)
- {
-+ /* Be very lazy, and only byteswap the stuff we use */
-+ if (byteswap==1) {
-+ ppnt->p_type=bswap_32(ppnt->p_type);
-+ ppnt->p_vaddr=bswap_32(ppnt->p_vaddr);
-+ ppnt->p_offset=bswap_32(ppnt->p_offset);
-+ ppnt->p_filesz=bswap_32(ppnt->p_filesz);
-+ }
-+
- if (loadaddr == -1 && ppnt->p_type == PT_LOAD)
- loadaddr = (ppnt->p_vaddr & ~(page_size-1)) -
- (ppnt->p_offset & ~(page_size-1));
-@@ -58,11 +79,20 @@
- (char *)(dpnt+dynamic_size) > (char *)(header + st.st_size))
- goto skip;
-
-+ if (byteswap==1) {
-+ dpnt->d_tag=bswap_32(dpnt->d_tag);
-+ dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val);
-+ }
-+
- while (dpnt->d_tag != DT_NULL)
- {
- if (dpnt->d_tag == DT_STRTAB)
- strtab_val = dpnt->d_un.d_val;
- dpnt++;
-+ if (byteswap==1) {
-+ dpnt->d_tag=bswap_32(dpnt->d_tag);
-+ dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val);
-+ }
- };
-
- if (!strtab_val)
+++ /dev/null
-diff -urN uClibc-0.9.28.orig/include/elf.h uClibc-0.9.28/include/elf.h
---- uClibc-0.9.28.orig/include/elf.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/include/elf.h 2006-04-28 00:14:35.000000000 -0600
-@@ -142,6 +142,7 @@
- #define ELFOSABI_HPUX 1 /* HP-UX */
- #define ELFOSABI_NETBSD 2 /* NetBSD. */
- #define ELFOSABI_LINUX 3 /* Linux. */
-+#define ELFOSABI_HURD 4 /* GNU/Hurd */
- #define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
- #define ELFOSABI_AIX 7 /* IBM AIX. */
- #define ELFOSABI_IRIX 8 /* SGI Irix. */
-@@ -149,6 +150,9 @@
- #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
- #define ELFOSABI_MODESTO 11 /* Novell Modesto. */
- #define ELFOSABI_OPENBSD 12 /* OpenBSD. */
-+#define ELFOSABI_OPENVMS 13 /* OpenVMS */
-+#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */
-+#define ELFOSABI_AROS 15 /* Amiga Research OS */
- #define ELFOSABI_ARM 97 /* ARM */
- #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
-
-@@ -177,6 +181,7 @@
- #define EM_386 3 /* Intel 80386 */
- #define EM_68K 4 /* Motorola m68k family */
- #define EM_88K 5 /* Motorola m88k family */
-+#define EM_486 6 /* Intel 80486 *//* Reserved for future use */
- #define EM_860 7 /* Intel 80860 */
- #define EM_MIPS 8 /* MIPS R3000 big-endian */
- #define EM_S370 9 /* IBM System/370 */
-@@ -193,7 +198,8 @@
- #define EM_V800 36 /* NEC V800 series */
- #define EM_FR20 37 /* Fujitsu FR20 */
- #define EM_RH32 38 /* TRW RH-32 */
--#define EM_RCE 39 /* Motorola RCE */
-+#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */
-+#define EM_RCE 39 /* Old name for MCore */
- #define EM_ARM 40 /* ARM */
- #define EM_FAKE_ALPHA 41 /* Digital Alpha */
- #define EM_SH 42 /* Renesas SH */
-@@ -248,18 +254,105 @@
- #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
- #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
- #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
-+#define EM_IP2K 101 /* Ubicom IP2022 micro controller */
-+#define EM_CR 103 /* National Semiconductor CompactRISC */
-+#define EM_MSP430 105 /* TI msp430 micro controller */
-+#define EM_BLACKFIN 106 /* Analog Devices Blackfin */
-+#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
-+#define EM_CRX 114 /* National Semiconductor CRX */
- #define EM_NUM 95
-
--/* If it is necessary to assign new unofficial EM_* values, please
-- pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
-- chances of collision with official or non-GNU unofficial values. */
-+/* If it is necessary to assign new unofficial EM_* values, please pick large
-+ random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
-+ with official or non-GNU unofficial values.
-
--/* Fujitsu FR-V. */
-+ NOTE: Do not just increment the most recent number by one.
-+ Somebody else somewhere will do exactly the same thing, and you
-+ will have a collision. Instead, pick a random number.
-+
-+ Normally, each entity or maintainer responsible for a machine with an
-+ unofficial e_machine number should eventually ask registry@caldera.com for
-+ an officially blessed number to be added to the list above. */
-+
-+/* picoJava */
-+#define EM_PJ_OLD 99
-+
-+/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */
-+#define EM_CYGNUS_POWERPC 0x9025
-+
-+/* Old version of Sparc v9, from before the ABI; this should be
-+ removed shortly. */
-+#define EM_OLD_SPARCV9 11
-+
-+/* Old version of PowerPC, this should be removed shortly. */
-+#define EM_PPC_OLD 17
-+
-+/* (Deprecated) Temporary number for the OpenRISC processor. */
-+#define EM_OR32 0x8472
-+
-+/* Renesas M32C and M16C. */
-+#define EM_M32C 0xFEB0
-+
-+/* Cygnus M32R ELF backend. Written in the absence of an ABI. */
-+#define EM_CYGNUS_M32R 0x9041
-+
-+/* old S/390 backend magic number. Written in the absence of an ABI. */
-+#define EM_S390_OLD 0xa390
-+
-+/* D10V backend magic number. Written in the absence of an ABI. */
-+#define EM_CYGNUS_D10V 0x7650
-+
-+/* D30V backend magic number. Written in the absence of an ABI. */
-+#define EM_CYGNUS_D30V 0x7676
-+
-+/* V850 backend magic number. Written in the absense of an ABI. */
-+#define EM_CYGNUS_V850 0x9080
-+
-+/* mn10200 and mn10300 backend magic numbers.
-+ Written in the absense of an ABI. */
-+#define EM_CYGNUS_MN10200 0xdead
-+#define EM_CYGNUS_MN10300 0xbeef
-+
-+/* FR30 magic number - no EABI available. */
-+#define EM_CYGNUS_FR30 0x3330
-+
-+/* AVR magic number
-+ Written in the absense of an ABI. */
-+#define EM_AVR_OLD 0x1057
-+
-+/* OpenRISC magic number
-+ Written in the absense of an ABI. */
-+#define EM_OPENRISC_OLD 0x3426
-+
-+/* DLX magic number
-+ Written in the absense of an ABI. */
-+#define EM_DLX 0x5aa5
-+
-+#define EM_XSTORMY16 0xad45
-+
-+/* FRV magic number - no EABI available??. */
- #define EM_CYGNUS_FRV 0x5441
-
-+/* Ubicom IP2xxx; no ABI */
-+#define EM_IP2K_OLD 0x8217
-+
-+#define EM_MT 0x2530 /* Morpho MT; no ABI */
-+
-+/* MSP430 magic number
-+ Written in the absense everything. */
-+#define EM_MSP430_OLD 0x1059
-+
-+/* Vitesse IQ2000. */
-+#define EM_IQ2000 0xFEBA
-+
-+/* Old, unofficial value for Xtensa. */
-+#define EM_XTENSA_OLD 0xabc7
-+
-+/* Alpha backend magic number. Written in the absence of an ABI. */
- #define EM_ALPHA 0x9026
--#define EM_NIOS32 0xfebb /* Altera Nios 32 */
--#define EM_ALTERA_NIOS2 0x9ee5 /* Altera Nios II */
-+
-+/* NIOS magic number - no EABI available. */
-+#define EM_NIOS32 0xFEBB
-
- /* V850 backend magic number. Written in the absense of an ABI. */
- #define EM_CYGNUS_V850 0x9080
-@@ -2498,6 +2591,12 @@
- #define R_390_NUM 61
-
-
-+/* CRIS flags. */
-+#define EF_CRIS_VARIANT_MASK 0x0000000e
-+#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000
-+#define EF_CRIS_VARIANT_V32 0x00000002
-+#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004
-+
- /* CRIS relocations. */
- #define R_CRIS_NONE 0
- #define R_CRIS_8 1
-@@ -2688,6 +2787,7 @@
- #define R_V850_NUM 25
-
-
-+/* Renesas H8/300 Relocations */
- #define R_H8_NONE 0
- #define R_H8_DIR32 1
- #define R_H8_DIR32_28 2
-@@ -2731,8 +2831,7 @@
- #define R_H8_DIR32A16 63
- #define R_H8_ABS32 65
- #define R_H8_ABS32A16 127
--
--/* Altera NIOS specific definitions. */
-+#define R_H8_NUM 128
-
- /* NIOS relocations. */
- #define R_NIOS_NONE 0
-diff -urN uClibc-0.9.28.orig/include/errno.h uClibc-0.9.28/include/errno.h
---- uClibc-0.9.28.orig/include/errno.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/include/errno.h 2006-04-28 00:14:35.000000000 -0600
-@@ -43,9 +43,11 @@
- variable. This redeclaration using the macro still works, but it
- will be a function declaration without a prototype and may trigger
- a -Wstrict-prototypes warning. */
-+#ifndef __ASSEMBLER__
- #ifndef errno
- extern int errno;
- #endif
-+#endif
-
- #if 0 /*def __USE_GNU uClibc note: not supported */
-
-diff -urN uClibc-0.9.28.orig/ldso/Makefile uClibc-0.9.28/ldso/Makefile
---- uClibc-0.9.28.orig/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600
-@@ -37,15 +37,12 @@
-
- LN_HEADERS := $(patsubst %, include/%, elf.h)
- LN_ARCH_HEADERS := $(patsubst %, include/%, dl-startup.h dl-syscalls.h dl-sysdep.h dl-debug.h)
--HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS) include/dl-progname.h
-+HEADERS := $(LN_HEADERS) $(LN_ARCH_HEADERS)
- headers: $(HEADERS)
- $(LN_HEADERS):
- $(LN) -fs $(TOPDIR)../$@ $@
- $(LN_ARCH_HEADERS):
- $(LN) -fs ../ldso/$(TARGET_ARCH)/$(patsubst include/%,%,$@) $@
--include/dl-progname.h:
-- echo '#include "$(TARGET_ARCH)/elfinterp.c"' \
-- > include/dl-progname.h
-
- clean:
- set -e ; for d in $(DIRS) ; do $(MAKE) -C $$d $@ ; done
-diff -urN uClibc-0.9.28.orig/ldso/include/dl-defs.h uClibc-0.9.28/ldso/include/dl-defs.h
---- uClibc-0.9.28.orig/ldso/include/dl-defs.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/dl-defs.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,6 +1,29 @@
-+/* 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_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
-diff -urN uClibc-0.9.28.orig/ldso/include/dl-elf.h uClibc-0.9.28/ldso/include/dl-elf.h
---- uClibc-0.9.28.orig/ldso/include/dl-elf.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/dl-elf.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,3 +1,10 @@
-+/* 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
-
-diff -urN uClibc-0.9.28.orig/ldso/include/dl-hash.h uClibc-0.9.28/ldso/include/dl-hash.h
---- uClibc-0.9.28.orig/ldso/include/dl-hash.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/dl-hash.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,3 +1,10 @@
-+/* 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_HASH_H_
- #define _LD_HASH_H_
-
-@@ -32,15 +39,15 @@
- unsigned short usage_count;
- unsigned short int init_flag;
- unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
-- Elf32_Word nbucket;
-- Elf32_Word *elf_buckets;
-+ Elf_Symndx nbucket;
-+ Elf_Symndx *elf_buckets;
- 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
- */
-- Elf32_Word nchain;
-- Elf32_Word *chains;
-+ Elf_Symndx nchain;
-+ Elf_Symndx *chains;
- unsigned long dynamic_info[DYNAMIC_SIZE];
-
- unsigned long n_phent;
-@@ -49,6 +56,9 @@
- 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 */
-@@ -66,7 +76,6 @@
- extern struct elf_resolve * _dl_loaded_modules;
- extern struct dyn_elf * _dl_handles;
-
--extern struct elf_resolve * _dl_check_hashed_files(const char * libname);
- extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
- char * loadaddr, unsigned long * dynamic_info,
- unsigned long dynamic_addr, unsigned long dynamic_size);
-diff -urN uClibc-0.9.28.orig/ldso/include/dl-string.h uClibc-0.9.28/ldso/include/dl-string.h
---- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/dl-string.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,9 +1,24 @@
-+/* 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 <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);
-@@ -26,8 +41,8 @@
- static __always_inline size_t _dl_strlen(const char * str)
- {
- register const char *ptr = (char *) str-1;
--
-- while (*++ptr);
-+ while (*++ptr)
-+ ;/* empty */
- return (ptr - str);
- }
-
-@@ -49,7 +64,8 @@
- register char *ptr = dst;
-
- dst--;src--;
-- while ((*++dst = *++src) != 0);
-+ while ((*++dst = *++src) != 0)
-+ ;/* empty */
-
- return ptr;
- }
-@@ -63,8 +79,7 @@
- c2 = (unsigned char) *++s2;
- if (c1 == '\0')
- return c1 - c2;
-- }
-- while (c1 == c2);
-+ } while (c1 == c2);
-
- return c1 - c2;
- }
-@@ -98,43 +113,41 @@
- return 0;
- }
-
--static inline char * _dl_strrchr(const char *str, int c)
-+static __always_inline char * _dl_strrchr(const char *str, int c)
- {
-- register char *prev = 0;
-- register char *ptr = (char *) str-1;
-+ 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);
-+ while (*++ptr != '\0') {
-+ if (*ptr == c)
-+ prev = ptr;
-+ }
-+ if (c == '\0')
-+ return(ptr);
-+ return(prev);
- }
-
--static inline char * _dl_strstr(const char *s1, const char *s2)
-+static __always_inline char * _dl_strstr(const char *s1, const char *s2)
- {
-- register const char *s = s1;
-- register const char *p = 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);
-+ do {
-+ if (!*p)
-+ return (char *) s1;;
-+ if (*p == *s) {
-+ ++p;
-+ ++s;
-+ } else {
-+ p = s2;
-+ if (!*s)
-+ return NULL;
-+ s = ++s1;
-+ }
-+ } while (1);
- }
-
--static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
-+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;
-@@ -163,27 +176,28 @@
- /* 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 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;
-+ 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)
-@@ -225,10 +239,10 @@
- char *p = &local[22];
- *--p = '\0';
- do {
-- char temp;
-- do_rem(temp, i, 10);
-- *--p = '0' + temp;
-- i /= 10;
-+ char temp;
-+ do_rem(temp, i, 10);
-+ *--p = '0' + temp;
-+ do_div_10(i, temp);
- } while (i > 0);
- return p;
- }
-@@ -242,9 +256,9 @@
- do {
- char temp = i & 0xf;
- if (temp <= 0x09)
-- *--p = '0' + temp;
-+ *--p = '0' + temp;
- else
-- *--p = 'a' - 0x0a + temp;
-+ *--p = 'a' - 0x0a + temp;
- i >>= 4;
- } while (i > 0);
- *--p = 'x';
-@@ -270,8 +284,8 @@
-
- /* 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(__mips__) \
-- || defined(__sh__) || defined(__powerpc__)
-+#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \
-+ defined(__mips__) || defined(__sh__) || defined(__powerpc__)
- # define CONSTANT_STRING_GOT_FIXUP(X) \
- if ((X) < (const char *) load_addr) (X) += load_addr
- # define NO_EARLY_SEND_STDERR
-@@ -318,7 +332,7 @@
- do { \
- do_rem(v, (X), 10); \
- *--tmp2 = '0' + v; \
-- (X) /= 10; \
-+ do_div_10((X), v); \
- } while ((X) > 0); \
- _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
- }
-diff -urN uClibc-0.9.28.orig/ldso/include/dl-syscall.h uClibc-0.9.28/ldso/include/dl-syscall.h
---- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,3 +1,10 @@
-+/* 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_
-
-@@ -12,9 +19,8 @@
- #include <bits/kernel_stat.h>
- #include <bits/kernel_types.h>
-
--
- /* _dl_open() parameters */
--#define O_RDONLY 0x0000
-+#define O_RDONLY 00
- #define O_WRONLY 01
- #define O_RDWR 02
- #define O_CREAT 0100
-@@ -39,18 +45,6 @@
- #define S_IWRITE 0200 /* Write by owner. */
- #define S_IEXEC 0100 /* Execute by owner. */
-
--/* Stuff for _dl_mmap */
--#if 0
--#define MAP_FAILED ((void *) -1)
--#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
--#else
--#ifndef _dl_MAX_ERRNO
--#define _dl_MAX_ERRNO 4096
--#endif
--#define _dl_mmap_check_error(__res) \
-- (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
--#endif
--
-
-
- /* Here are the definitions for some syscalls that are used
-@@ -66,54 +60,125 @@
- static inline _syscall1(int, _dl_close, int, fd);
-
- #define __NR__dl_open __NR_open
--static inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode);
-+static inline _syscall3(int, _dl_open, const char *, fn, int, flags,
-+ __kernel_mode_t, mode);
-
- #define __NR__dl_write __NR_write
- static inline _syscall3(unsigned long, _dl_write, int, fd,
-- const void *, buf, unsigned long, count);
-+ const void *, buf, unsigned long, count);
-
- #define __NR__dl_read __NR_read
- static inline _syscall3(unsigned long, _dl_read, int, fd,
-- const void *, buf, unsigned long, count);
-+ const void *, buf, unsigned long, count);
-
- #define __NR__dl_mprotect __NR_mprotect
--static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot);
-+static inline _syscall3(int, _dl_mprotect, const void *, addr,
-+ unsigned long, len, int, prot);
-
- #define __NR__dl_stat __NR_stat
--static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);
-+static inline _syscall2(int, _dl_stat, const char *, file_name,
-+ struct stat *, buf);
-+
-+#define __NR__dl_fstat __NR_fstat
-+static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
-
- #define __NR__dl_munmap __NR_munmap
- static 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 inline _syscall0(uid_t, _dl_getuid);
-
-+#ifndef __NR_geteuid
-+# define __NR_geteuid __NR_getuid
-+#endif
- #define __NR__dl_geteuid __NR_geteuid
- static inline _syscall0(uid_t, _dl_geteuid);
-
-+#ifdef __NR_getxgid
-+# define __NR_getgid __NR_getxgid
-+#endif
- #define __NR__dl_getgid __NR_getgid
- static inline _syscall0(gid_t, _dl_getgid);
-
-+#ifndef __NR_getegid
-+# define __NR_getegid __NR_getgid
-+#endif
- #define __NR__dl_getegid __NR_getegid
- static inline _syscall0(gid_t, _dl_getegid);
-
-+#ifdef __NR_getxpid
-+# define __NR_getpid __NR_getxpid
-+#endif
- #define __NR__dl_getpid __NR_getpid
- static inline _syscall0(gid_t, _dl_getpid);
-
- #define __NR__dl_readlink __NR_readlink
--static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
-+static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
-+ size_t, bufsiz);
-
--#ifdef __NR_mmap
--#ifdef MMAP_HAS_6_ARGS
--#define __NR__dl_mmap __NR_mmap
--static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
-- int, prot, int, flags, int, fd, off_t, offset);
-+#ifdef __UCLIBC_HAS_SSP__
-+# include <sys/time.h>
-+# define __NR__dl_gettimeofday __NR_gettimeofday
-+static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
-+# ifdef __USE_BSD
-+ struct timezone *, tz);
-+# else
-+ void *, tz);
-+# endif
-+#endif
-+
-+
-+/* handle all the fun mmap intricacies */
-+#if (defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)) || !defined(__NR_mmap2)
-+# define _dl_MAX_ERRNO 4096
-+# define _dl_mmap_check_error(__res) \
-+ (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
- #else
--#define __NR__dl_mmap_real __NR_mmap
--static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
-+# define MAP_FAILED ((void *) -1)
-+# define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
-+#endif
-+
-+/* first try mmap(), syscall6() style */
-+#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
-+
-+# define __NR__dl_mmap __NR_mmap
-+static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
-+ int, prot, int, flags, int, fd, off_t, offset);
-+
-+/* then try mmap2() */
-+#elif defined(__NR_mmap2)
-+
-+# define __NR___syscall_mmap2 __NR_mmap2
-+static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
-+ int, prot, int, flags, int, fd, off_t, offset);
-+
-+/* 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
-
- static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
-- int flags, int fd, unsigned long offset)
-+ int flags, int fd, unsigned long offset)
-+{
-+ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
-+ return MAP_FAILED;
-+ return __syscall_mmap2(addr, size, prot, flags,
-+ fd, (off_t) (offset >> MMAP2_PAGE_SHIFT));
-+}
-+
-+/* finally, fall back to mmap(), syscall1() style */
-+#elif defined(__NR_mmap)
-+
-+# define __NR__dl_mmap_real __NR_mmap
-+static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
-+static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
-+ int flags, int fd, unsigned long offset)
- {
- unsigned long buffer[6];
-
-@@ -125,24 +190,9 @@
- buffer[5] = (unsigned long) offset;
- return (void *) _dl_mmap_real(buffer);
- }
--#endif
--#elif defined __NR_mmap2
--#define __NR___syscall_mmap2 __NR_mmap2
--static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
-- size_t, len, int, prot, int, flags, int, fd, off_t, offset);
--/*always 12, even on architectures where PAGE_SHIFT != 12 */
--#define MMAP2_PAGE_SHIFT 12
--static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
-- int flags, int fd, unsigned long offset)
--{
-- if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
-- return MAP_FAILED;
-- return(__syscall_mmap2(addr, size, prot, flags,
-- fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
--}
-+
- #else
--#error "Your architecture doesn't seem to provide mmap() !?"
-+# error "Your architecture doesn't seem to provide mmap() !?"
- #endif
-
- #endif /* _LD_SYSCALL_H_ */
--
-diff -urN uClibc-0.9.28.orig/ldso/include/dlfcn.h uClibc-0.9.28/ldso/include/dlfcn.h
---- uClibc-0.9.28.orig/ldso/include/dlfcn.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/dlfcn.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,3 +1,10 @@
-+/* 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
-diff -urN uClibc-0.9.28.orig/ldso/include/ldso.h uClibc-0.9.28/ldso/include/ldso.h
---- uClibc-0.9.28.orig/ldso/include/ldso.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/ldso.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,3 +1,10 @@
-+/* 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_
-
-@@ -20,13 +27,15 @@
- /* Pull in compiler and arch stuff */
- #include <stdlib.h>
- #include <stdarg.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>
-+#define attribute_unused __attribute__ ((unused))
- /* Pull in the ldso syscalls and string functions */
- #include <dl-syscall.h>
- #include <dl-string.h>
--/* Pull in the arch specific page size */
--#include <bits/uClibc_page.h>
- /* Now the ldso specific headers */
- #include <dl-elf.h>
- #include <dl-hash.h>
-diff -urN uClibc-0.9.28.orig/ldso/include/unsecvars.h uClibc-0.9.28/ldso/include/unsecvars.h
---- uClibc-0.9.28.orig/ldso/include/unsecvars.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/include/unsecvars.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,3 +1,10 @@
-+/* 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
-@@ -5,22 +12,21 @@
- */
-
- #define UNSECURE_ENVVARS \
-- "LD_AOUT_PRELOAD\0" \
-- "LD_AOUT_LIBRARY_PATH\0" \
- "LD_PRELOAD\0" \
- "LD_LIBRARY_PATH\0" \
- "LD_DEBUG\0" \
- "LD_DEBUG_OUTPUT\0" \
- "LD_TRACE_LOADED_OBJECTS\0" \
-- "HOSTALIASES\0" \
-- "LOCALDOMAIN\0" \
-- "RES_OPTIONS\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.
- *
-- * MALLOC_TRACE, RESOLV_HOST_CONF, TZDIR, GCONV_PATH, LD_USE_LOAD_BIAS,
-- * LD_PROFILE, LD_ORIGIN_PATH, LOCPATH, NLSPATH
-+ * 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 -urN uClibc-0.9.28.orig/ldso/ldso/Makefile uClibc-0.9.28/ldso/ldso/Makefile
---- uClibc-0.9.28.orig/ldso/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600
-@@ -42,7 +42,9 @@
- endif
- XXFLAGS+= -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \
- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
-- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include
-+ -fno-builtin -nostdinc -D_LIBC \
-+ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \
-+ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include
-
- # BEWARE!!! At least mips* will die if -O0 is used!!!
- XXFLAGS:=$(XXFLAGS:-O0=-O1)
-diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h uClibc-0.9.28/ldso/ldso/arm/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,10 +1,15 @@
- /* vi: set sw=4 ts=4: */
- /*
- * Architecture specific code used by dl-startup.c
-- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
-+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
-+ *
-+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
--asm(
-+#include <features.h>
-+
-+#if !defined(__thumb__)
-+__asm__(
- " .text\n"
- " .globl _start\n"
- " .type _start,%function\n"
-@@ -40,7 +45,78 @@
- " 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"
-@@ -51,6 +127,7 @@
- " .size _start,.-_start\n"
- ".previous\n"
- );
-+#endif
-
-
- /* Get a pointer to the argv array. On many platforms this can be just
-@@ -115,9 +192,3 @@
- _dl_exit(1);
- }
- }
--
--
--/* Transfer control to the user's application, once the dynamic loader is
-- * done. This routine has to exit the current function, then call the
-- * _dl_elf_main function. */
--#define START() return _dl_elf_main;
-diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,6 +1,7 @@
- /* 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);}
--#include "sys/syscall.h"
-
-diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -43,6 +43,7 @@
- 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
-@@ -85,7 +86,25 @@
- extern void __dl_start asm ("_dl_start");
- Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
- Elf32_Addr pcrel_addr;
-+#if !defined __thumb__
- asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
-+#else
-+ int tmp;
-+ /* The above adr will not work on thumb because it
-+ * is negative. The only safe way is to temporarily
-+ * swap to arm.
-+ */
-+ asm( ".align 2\n"
-+ " bx pc\n"
-+ " nop \n"
-+ " .arm \n"
-+ " adr %0, _dl_start\n"
-+ " .align 2\n"
-+ " orr %1, pc, #1\n"
-+ " bx %1\n"
-+ " .force_thumb\n"
-+ : "=r" (pcrel_addr), "=&r" (tmp));
-+#endif
- return pcrel_addr - got_addr;
- }
-
-diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c uClibc-0.9.28/ldso/ldso/arm/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -38,6 +38,8 @@
- 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)
-@@ -63,7 +65,6 @@
- strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
- symname = strtab + symtab[symtab_index].st_name;
-
--
- if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) {
- _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
- _dl_progname);
-diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h uClibc-0.9.28/ldso/ldso/cris/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/cris/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -4,22 +4,43 @@
-
- /* 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" \
-+" 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 if the first argument, on other platforms we need to
-@@ -58,8 +79,3 @@
- break;
- }
- }
--
--/* Transfer control to the user's application, once the dynamic loader is
-- * done. This routine has to exit the current function, then call the
-- * _dl_elf_main function. */
--#define START() return _dl_elf_main
-diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,5 +1,6 @@
- /* 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);}
--#include "sys/syscall.h"
-diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -18,8 +18,6 @@
- struct elf_resolve;
- extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
-
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 8192 bytes alignment */
- #define PAGE_ALIGN 0xffffe000
- #define ADDR_ALIGN 0x1fff
-@@ -68,8 +66,32 @@
- {
- 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;
- }
-
-diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S uClibc-0.9.28/ldso/ldso/cris/resolve.S
---- uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/cris/resolve.S 2006-04-28 00:14:35.000000000 -0600
-@@ -17,33 +17,73 @@
- .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
-+ 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
-+ 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
-+ 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+]
-+ 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 -urN uClibc-0.9.28.orig/ldso/ldso/dl-elf.c uClibc-0.9.28/ldso/ldso/dl-elf.c
---- uClibc-0.9.28.orig/ldso/ldso/dl-elf.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/dl-elf.c 2006-05-02 13:50:58.000000000 -0600
-@@ -3,7 +3,7 @@
- * 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-2004 by Erik Andersen <andersen@codepoet.org>
-+ * 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
- *
-@@ -60,8 +60,8 @@
- _dl_cache_addr = (caddr_t) _dl_mmap(0, _dl_cache_size, PROT_READ, MAP_SHARED, fd, 0);
- _dl_close(fd);
- if (_dl_mmap_check_error(_dl_cache_addr)) {
-- _dl_dprintf(2, "%s: can't map cache '%s'\n",
-- _dl_progname, LDSO_CACHE);
-+ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
-+ _dl_progname, __LINE__, LDSO_CACHE);
- return -1;
- }
-
-@@ -115,7 +115,7 @@
- #endif
-
-
--void
-+void
- _dl_protect_relro (struct elf_resolve *l)
- {
- ElfW(Addr) start = ((l->loadaddr + l->relro_addr)
-@@ -136,27 +136,41 @@
- search_for_named_library(const char *name, int secure, const char *path_list,
- struct dyn_elf **rpnt)
- {
-- char *path, *path_n;
-- char mylibname[2050];
-+ char *path, *path_n, *mylibname;
- struct elf_resolve *tpnt;
-- int done = 0;
-+ int done;
-
- if (path_list==NULL)
- return NULL;
-
-- /* We need a writable copy of this string */
-- path = _dl_strdup(path_list);
-- if (!path) {
-+ /* 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);
-+
-+ /* gcc inlines alloca using a single instruction adjusting
-+ * the stack pointer and no stack overflow check and thus
-+ * no NULL error return. No point leaving in dead code... */
-+#if 0
-+ if (!path || !mylibname) {
- _dl_dprintf(2, "Out of memory!\n");
- _dl_exit(0);
- }
-+#endif
-+
-+ _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 */
-+ /* "" maps to CWD */
-+ done = 0;
- path_n = path;
- do {
- if (*path == 0) {
-@@ -180,71 +194,6 @@
- return NULL;
- }
-
--/* Check if the named library is already loaded... */
--struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
-- int trace_loaded_objects)
--{
-- const char *pnt, *pnt1;
-- struct elf_resolve *tpnt1;
-- const char *libname, *libname2;
-- static const char libc[] = "libc.so.";
-- static const char aborted_wrong_lib[] = "%s: aborted attempt to load %s!\n";
--
-- pnt = libname = full_libname;
--
-- _dl_if_debug_dprint("Checking if '%s' is already loaded\n", 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)
-- return NULL;
--
-- /* Skip over any initial initial './' and '/' stuff to
-- * get the short form libname with no path garbage */
-- pnt1 = _dl_strrchr(pnt, '/');
-- if (pnt1) {
-- libname = pnt1 + 1;
-- }
--
-- /* Make sure they are not trying to load the wrong C library!
-- * This sometimes happens esp with shared libraries when the
-- * library path is somehow wrong! */
--#define isdigit(c) (c >= '0' && c <= '9')
-- if ((_dl_strncmp(libname, libc, 8) == 0) && _dl_strlen(libname) >=8 &&
-- isdigit(libname[8]))
-- {
-- /* Abort attempts to load glibc, libc5, etc */
-- if ( libname[8]!='0') {
-- if (!trace_loaded_objects) {
-- _dl_dprintf(2, aborted_wrong_lib, libname, _dl_progname);
-- _dl_exit(1);
-- }
-- return NULL;
-- }
-- }
--
-- /* Critical step! Weed out duplicates early to avoid
-- * function aliasing, which wastes memory, and causes
-- * really bad things to happen with weaks and globals. */
-- for (tpnt1 = _dl_loaded_modules; tpnt1; tpnt1 = tpnt1->next) {
--
-- /* Skip over any initial initial './' and '/' stuff to
-- * get the short form libname with no path garbage */
-- libname2 = tpnt1->libname;
-- pnt1 = _dl_strrchr(libname2, '/');
-- if (pnt1) {
-- libname2 = pnt1 + 1;
-- }
--
-- if (_dl_strcmp(libname2, libname) == 0) {
-- /* Well, that was certainly easy */
-- return tpnt1;
-- }
-- }
--
-- return NULL;
--}
--
--
- /* Used to return error codes back to dlopen et. al. */
- unsigned long _dl_error_number;
- unsigned long _dl_internal_error_number;
-@@ -271,14 +220,6 @@
- libname = pnt + 1;
- }
-
-- /* Critical step! Weed out duplicates early to avoid
-- * function aliasing, which wastes memory, and causes
-- * really bad things to happen with weaks and globals. */
-- if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) {
-- tpnt1->usage_count++;
-- return tpnt1;
-- }
--
- _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
-@@ -290,7 +231,6 @@
- if (tpnt1) {
- return tpnt1;
- }
-- //goto goof;
- }
-
- /*
-@@ -411,56 +351,45 @@
- int i, flags, piclib, infile;
- ElfW(Addr) relro_addr = 0;
- size_t relro_size = 0;
--
-- /* If this file is already loaded, skip this step */
-- tpnt = _dl_check_hashed_files(libname);
-- if (tpnt) {
-- if (*rpnt) {
-- (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
-- _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
-- (*rpnt)->next->prev = (*rpnt);
-- *rpnt = (*rpnt)->next;
-- (*rpnt)->dyn = tpnt;
-- tpnt->symbol_scope = _dl_symbol_tables;
-- }
-- tpnt->usage_count++;
-- tpnt->libtype = elf_lib;
-- _dl_if_debug_dprint("file='%s'; already loaded\n", libname);
-- return tpnt;
-- }
--
-- /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
-- we don't load the library if it isn't setuid. */
--
-- if (secure) {
-- struct stat st;
--
-- if (_dl_stat(libname, &st) || !(st.st_mode & S_ISUID))
-- return NULL;
-- }
-+ struct stat st;
-
- libaddr = 0;
- infile = _dl_open(libname, O_RDONLY, 0);
- if (infile < 0) {
--#if 0
-- /*
-- * NO! When we open shared libraries we may search several paths.
-- * it is inappropriate to generate an error here.
-- */
-- _dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
--#endif
- _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 setu/gid binary using LD_PRELOAD),
-+ we don't load the library if it isn't setuid. */
-+ if (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;
-+ }
-+ }
- header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (_dl_mmap_check_error(header)) {
-- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
-+ _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;
-@@ -475,7 +404,7 @@
- _dl_close(infile);
- _dl_munmap(header, _dl_pagesize);
- return NULL;
-- };
-+ }
-
- if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1
- #ifdef MAGIC2
-@@ -490,7 +419,7 @@
- _dl_close(infile);
- _dl_munmap(header, _dl_pagesize);
- return NULL;
-- };
-+ }
-
- ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
-
-@@ -502,7 +431,7 @@
- _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. */
-@@ -518,7 +447,7 @@
- }
- }
- ppnt++;
-- };
-+ }
-
- maxvma = (maxvma + ADDR_ALIGN) & ~ADDR_ALIGN;
- minvma = minvma & ~0xffffU;
-@@ -530,12 +459,12 @@
- status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
- maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
- if (_dl_mmap_check_error(status)) {
-- _dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
-+ _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;
-
-@@ -567,14 +496,14 @@
- ppnt->p_offset & OFFS_ALIGN);
-
- if (_dl_mmap_check_error(status)) {
-- _dl_dprintf(2, "%s: can't map '%s'\n",
-- _dl_progname, libname);
-+ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
-+ _dl_progname, __LINE__, libname);
- _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
- _dl_munmap((char *) libaddr, maxvma - minvma);
- _dl_close(infile);
- _dl_munmap(header, _dl_pagesize);
- return NULL;
-- };
-+ }
-
- /* Pad the last page with zeroes. */
- cpnt = (char *) (status + (ppnt->p_vaddr & ADDR_ALIGN) +
-@@ -601,21 +530,21 @@
- ppnt->p_filesz, LXFLAGS(ppnt->p_flags), flags,
- infile, ppnt->p_offset & OFFS_ALIGN);
- if (_dl_mmap_check_error(status)) {
-- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
-+ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
- _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
- _dl_munmap((char *) libaddr, maxvma - minvma);
- _dl_close(infile);
- _dl_munmap(header, _dl_pagesize);
- return NULL;
-- };
-+ }
-
- /* if(libaddr == 0 && piclib) {
- libaddr = (unsigned long) status;
- flags |= MAP_FIXED;
-- }; */
-- };
-+ } */
-+ }
- ppnt++;
-- };
-+ }
- _dl_close(infile);
-
- /* For a non-PIC library, the addresses are all absolute */
-@@ -665,6 +594,8 @@
- dynamic_addr, 0);
- 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) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
- tpnt->n_phent = epnt->e_phnum;
-
-@@ -693,7 +624,7 @@
- if (lpnt) {
- lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
- INIT_GOT(lpnt, tpnt);
-- };
-+ }
-
- _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
- _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, libaddr);
-@@ -714,10 +645,12 @@
- ElfW(Addr) reloc_addr;
-
- if (rpnt->next)
-- goof += _dl_fixup(rpnt->next, now_flag);
-+ goof = _dl_fixup(rpnt->next, now_flag);
-+ if (goof)
-+ return goof;
- tpnt = rpnt->dyn;
-
-- if(!(tpnt->init_flag & RELOCS_DONE))
-+ if(!(tpnt->init_flag & RELOCS_DONE))
- _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
-
- if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
-@@ -735,7 +668,6 @@
- #endif
- if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
- !(tpnt->init_flag & RELOCS_DONE)) {
-- 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 */
-@@ -746,14 +678,14 @@
- goof += _dl_parse_relocation_information(rpnt,
- 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;
-- tpnt->init_flag |= JMP_RELOCS_DONE;
-+ tpnt->rtld_flags |= now_flag;
- if (!(tpnt->rtld_flags & RTLD_NOW)) {
- _dl_parse_lazy_relocation_information(rpnt,
- tpnt->dynamic_info[DT_JMPREL],
-@@ -763,6 +695,7 @@
- tpnt->dynamic_info[DT_JMPREL],
- tpnt->dynamic_info[DT_PLTRELSZ]);
- }
-+ tpnt->init_flag |= JMP_RELOCS_DONE;
- }
- return goof;
- }
-@@ -770,11 +703,18 @@
- /* Minimal printf which handles only %s, %d, and %x */
- void _dl_dprintf(int fd, const char *fmt, ...)
- {
-- long num;
-+#if __WORDSIZE > 32
-+ long int num;
-+#else
-+ int num;
-+#endif
- va_list args;
- char *start, *ptr, *string;
- static 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)) {
-@@ -784,9 +724,6 @@
-
- start = ptr = buf;
-
-- if (!fmt)
-- return;
--
- if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
- _dl_write(fd, "overflow\n", 11);
- _dl_exit(20);
-@@ -818,8 +755,11 @@
- case 'd':
- {
- char tmp[22];
-- num = va_arg(args, long);
--
-+#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;
-@@ -828,8 +768,11 @@
- case 'X':
- {
- char tmp[22];
-- num = va_arg(args, long);
--
-+#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;
-@@ -864,8 +807,10 @@
- {
- __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
- }
-+
-+/* we want this in ldso.so and libdl.a but nowhere else */
- #ifdef __USE_GNU
--#if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
-+#if ! defined SHARED || (! defined PIC && ! defined __PIC__)
- int
- __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data)
- {
-@@ -884,6 +829,6 @@
- }
- return ret;
- }
--strong_alias(__dl_iterate_phdr, dl_iterate_phdr);
-+strong_alias(__dl_iterate_phdr, dl_iterate_phdr)
- #endif
- #endif
-diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-hash.c uClibc-0.9.28/ldso/ldso/dl-hash.c
---- uClibc-0.9.28.orig/ldso/ldso/dl-hash.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2006-04-28 00:14:35.000000000 -0600
-@@ -57,7 +57,7 @@
- /* 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 Elf32_Word _dl_elf_hash(const char *name)
-+static inline Elf_Symndx _dl_elf_hash(const char *name)
- {
- unsigned long hash=0;
- unsigned long tmp;
-@@ -77,21 +77,6 @@
- return hash;
- }
-
--/* Check to see if a library has already been added to the hash chain. */
--struct elf_resolve *_dl_check_hashed_files(const char *libname)
--{
-- struct elf_resolve *tpnt;
-- int len = _dl_strlen(libname);
--
-- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
-- if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
-- (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
-- return tpnt;
-- }
--
-- return NULL;
--}
--
- /*
- * 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
-@@ -99,9 +84,10 @@
- */
- struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
- char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
-+ //attribute_unused
- unsigned long dynamic_size)
- {
-- Elf32_Word *hash_addr;
-+ Elf_Symndx *hash_addr;
- struct elf_resolve *tpnt;
- int i;
-
-@@ -125,7 +111,7 @@
- tpnt->libtype = loaded_file;
-
- if (dynamic_info[DT_HASH] != 0) {
-- hash_addr = (Elf32_Word*)dynamic_info[DT_HASH];
-+ hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH];
- tpnt->nbucket = *hash_addr++;
- tpnt->nchain = *hash_addr++;
- tpnt->elf_buckets = hash_addr;
-diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-startup.c uClibc-0.9.28/ldso/ldso/dl-startup.c
---- uClibc-0.9.28.orig/ldso/ldso/dl-startup.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/dl-startup.c 2006-04-28 00:14:35.000000000 -0600
-@@ -98,7 +98,7 @@
- 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 */
-+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)
-@@ -307,5 +307,11 @@
- SEND_STDERR_DEBUG("transfering control to application @ ");
- _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val;
- SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1);
-+
-+#ifndef START
-+ return _dl_elf_main;
-+#else
-+#warning You need to update your arch ldso code
- START();
-+#endif
- }
-diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -20,9 +20,10 @@
-
- /* 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);}
--#include "sys/syscall.h"
- #include <sys/mman.h>
-
- /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
-diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -65,8 +65,6 @@
-
- extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
-
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 16KiB page alignment. Should perhaps be made dynamic using
- getpagesize(), based on AT_PAGESZ from auxvt? */
- #define PAGE_ALIGN 0xffffc000
-diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c uClibc-0.9.28/ldso/ldso/frv/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/frv/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -24,7 +24,7 @@
- the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- USA. */
-
--#include <sys/cdefs.h> /* __attribute_used__ */
-+#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
-@@ -37,7 +37,7 @@
- a more than adequate job of explaining everything required to get this
- working. */
-
--struct funcdesc_value volatile *__attribute__((__visibility__("hidden")))
-+struct funcdesc_value volatile attribute_hidden *
- _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
- {
- int reloc_type;
-diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h uClibc-0.9.28/ldso/ldso/i386/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/i386/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -3,7 +3,7 @@
- * Architecture specific code used by dl-startup.c
- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
- */
--asm(
-+__asm__ (
- " .text\n"
- " .align 16\n"
- " .globl _start\n"
-@@ -41,9 +41,9 @@
- #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1)
-
- /* Handle relocation of the symbols in the dynamic loader. */
--static inline
-+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)
-+ unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
- {
- switch (ELF32_R_TYPE(rpnt->r_info))
- {
-@@ -64,8 +64,3 @@
- _dl_exit(1);
- }
- }
--
--/* Transfer control to the user's application, once the dynamic loader is
-- * done. This routine has to exit the current function, then call the
-- * _dl_elf_main function. */
--#define START() return _dl_elf_main
-diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,5 +1,6 @@
- /* 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);}
--#include "sys/syscall.h"
-diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -25,8 +25,6 @@
- struct elf_resolve;
- extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
-
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 4096 bytes alignment */
- #define PAGE_ALIGN 0xfffff000
- #define ADDR_ALIGN 0xfff
-@@ -44,16 +42,18 @@
- /* 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 __attribute__ ((unused))
-+static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused;
-+static inline Elf32_Addr
- elf_machine_dynamic (void)
- {
-- register Elf32_Addr *got asm ("%ebx");
-+ register Elf32_Addr *got __asm__ ("%ebx");
- return *got;
- }
-
-
- /* Return the run-time load address of the shared object. */
--static inline Elf32_Addr __attribute__ ((unused))
-+static inline Elf32_Addr elf_machine_load_address (void) attribute_unused;
-+static inline Elf32_Addr
- elf_machine_load_address (void)
- {
- /* It doesn't matter what variable this is, the reference never makes
-@@ -61,7 +61,7 @@
- via the GOT to make sure the compiler initialized %ebx in time. */
- extern int _dl_errno;
- Elf32_Addr addr;
-- asm ("leal _dl_start@GOTOFF(%%ebx), %0\n"
-+ __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n"
- "subl _dl_start@GOT(%%ebx), %0"
- : "=r" (addr) : "m" (_dl_errno) : "cc");
- return addr;
-diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c uClibc-0.9.28/ldso/ldso/i386/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/i386/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -67,12 +67,6 @@
- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
- symname = strtab + symtab[symtab_index].st_name;
-
-- if (unlikely(reloc_type != R_386_JMP_SLOT)) {
-- _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
-- _dl_progname);
-- _dl_exit(1);
-- }
--
- /* Address of the jump instruction to fix up. */
- instr_addr = ((unsigned long)this_reloc->r_offset +
- (unsigned long)tpnt->loadaddr);
-@@ -81,7 +75,7 @@
- /* Get the address of the GOT entry. */
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
- if (unlikely(!new_addr)) {
-- _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
-+ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
- _dl_exit(1);
- }
-
-@@ -147,15 +141,15 @@
- int reloc_type = ELF32_R_TYPE(rpnt->r_info);
-
- #if defined (__SUPPORT_LD_DEBUG__)
-- _dl_dprintf(2, "can't handle reloc type %s\n",
-- _dl_reltypes(reloc_type));
-+ _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\n",
-- reloc_type);
-+ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n",
-+ reloc_type, tpnt->libname);
- #endif
-- _dl_exit(-res);
-+ return res;
- } else if (unlikely(res > 0)) {
-- _dl_dprintf(2, "can't resolve symbol\n");
-+ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
- return res;
- }
- }
-@@ -191,10 +185,8 @@
- * might have been intentional. We should not be linking local
- * symbols here, so all bases should be covered.
- */
-- if (unlikely(!symbol_addr && ELF32_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 (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
-+ return 1;
- }
-
- #if defined (__SUPPORT_LD_DEBUG__)
-@@ -233,7 +225,7 @@
- }
- break;
- default:
-- return -1; /* Calls _dl_exit(1). */
-+ return -1;
- }
-
- #if defined (__SUPPORT_LD_DEBUG__)
-@@ -273,7 +265,7 @@
- *reloc_addr += (unsigned long)tpnt->loadaddr;
- break;
- default:
-- return -1; /* Calls _dl_exit(1). */
-+ return -1;
- }
-
- #if defined (__SUPPORT_LD_DEBUG__)
-diff -urN uClibc-0.9.28.orig/ldso/ldso/ldso.c uClibc-0.9.28/ldso/ldso/ldso.c
---- uClibc-0.9.28.orig/ldso/ldso/ldso.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/ldso.c 2006-05-02 13:55:54.000000000 -0600
-@@ -39,7 +39,7 @@
- #define ALLOW_ZERO_PLTGOT
-
- /* Pull in the value of _dl_progname */
--#include "dl-progname.h"
-+#include LDSO_ELFINTERP
-
- /* Global variables used within the shared library loader */
- char *_dl_library_path = 0; /* Where we look for libraries */
-@@ -74,7 +74,8 @@
- * 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)
-+void _dl_debug_state(void);
-+void _dl_debug_state()
- {
- }
-
-@@ -82,9 +83,78 @@
- static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */
-
- static struct elf_resolve **init_fini_list;
--static int nlist; /* # items in init_fini_list */
-+static unsigned int nlist; /* # items in init_fini_list */
- extern void _start(void);
-
-+#ifdef __UCLIBC_HAS_SSP__
-+#ifndef __UCLIBC_HAS_SSP_COMPAT__
-+#define __UCLIBC_HAS_SSP_COMPAT__ 1
-+#endif
-+# include <dl-osinfo.h>
-+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;
-+# ifdef __UCLIBC_HAS_SSP_COMPAT__
-+strong_alias(__stack_chk_guard,__guard)
-+# endif
-+# elif __UCLIBC_HAS_SSP_COMPAT__
-+uintptr_t __guard attribute_relro;
-+# endif
-+#endif
-+
-+static void _dl_run_array_forward(unsigned long array, unsigned long size,
-+ ElfW(Addr) loadaddr)
-+{
-+ if (array != 0) {
-+ unsigned int j;
-+ unsigned int jm;
-+ ElfW(Addr) *addrs;
-+ jm = size / sizeof (ElfW(Addr));
-+ addrs = (ElfW(Addr) *) (array + loadaddr);
-+ for (j = 0; j < jm; ++j) {
-+ void (*dl_elf_func) (void);
-+ dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
-+ (*dl_elf_func) ();
-+ }
-+ }
-+}
-+
-+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) *) (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_elf_func) ();
-+ }
-+ }
-+}
-+
-+void _dl_app_fini_array(void);
-+void _dl_app_fini_array(void)
-+{
-+ _dl_run_fini_array(_dl_loaded_modules);
-+}
-+
- static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
- {
- int i;
-@@ -95,6 +165,7 @@
- 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);
-
-@@ -112,7 +183,8 @@
- ElfW(Phdr) *ppnt;
- ElfW(Dyn) *dpnt;
- char *lpntstr;
-- int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
-+ unsigned int i;
-+ int unlazy = 0, trace_loaded_objects = 0;
- struct dyn_elf *rpnt;
- struct elf_resolve *tcurr;
- struct elf_resolve *tpnt1;
-@@ -128,6 +200,7 @@
- * 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, 0x00, 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;
-@@ -168,8 +241,8 @@
- * Note that for SUID programs we ignore the settings in
- * LD_LIBRARY_PATH.
- */
-- if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
-- (auxvt[AT_UID].a_un.a_val != -1 &&
-+ 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;
-@@ -196,6 +269,20 @@
- unlazy = RTLD_NOW;
- }
-
-+ /* sjhill: your TLS init should go before this */
-+#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);
-+# ifdef __UCLIBC_HAS_SSP_COMPAT__
-+ __guard = stack_chk_guard;
-+# endif
-+# else
-+ __stack_chk_guard = stack_chk_guard;
-+# endif
-+#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
-@@ -206,12 +293,12 @@
- * different from what the ELF header says for ET_DYN/PIE executables.
- */
- {
-- int i;
-- ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
-+ unsigned int idx;
-+ ElfW(Phdr) *phdr = (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_PHDR) {
-- app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
-+ for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
-+ if (phdr->p_type == PT_PHDR) {
-+ app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
- break;
- }
-
-@@ -459,8 +546,8 @@
- PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- _dl_close(fd);
- if (preload == (caddr_t) -1) {
-- _dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n",
-- _dl_progname, LDSO_PRELOAD);
-+ _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
-+ _dl_progname, __LINE__, LDSO_PRELOAD);
- break;
- }
-
-@@ -528,15 +615,15 @@
-
- nlist = 0;
- for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
-- ElfW(Dyn) *dpnt;
-+ ElfW(Dyn) *this_dpnt;
-
- nlist++;
-- for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
-- if (dpnt->d_tag == DT_NEEDED) {
-+ 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] + dpnt->d_un.d_val);
-+ lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
- name = _dl_get_last_path_component(lpntstr);
- if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
- continue;
-@@ -633,7 +720,7 @@
- ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
- ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
- int j;
--
-+
- tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
- tpnt->dynamic_info,
- (unsigned long)tpnt->dynamic_addr,
-@@ -703,16 +790,14 @@
- * order so that COPY directives work correctly.
- */
- if (_dl_symbol_tables)
-- goof += _dl_fixup(_dl_symbol_tables, unlazy);
-+ if (_dl_fixup(_dl_symbol_tables, unlazy))
-+ _dl_exit(-1);
-
- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
- if (tpnt->relro_size)
- _dl_protect_relro (tpnt);
- }
-
--
--
--
- /* 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
-@@ -746,6 +831,14 @@
- /* 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 */
-@@ -762,17 +855,9 @@
-
- (*dl_elf_func) ();
- }
-- }
--#ifdef _DL_FINI_CRT_COMPAT
-- /* arches that have moved their ldso FINI handling should skip this part */
-- {
-- int (*_dl_atexit) (void *) = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit",
-- _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
-
-- if (_dl_atexit)
-- (*_dl_atexit) (_dl_fini);
-+ _dl_run_init_array(tpnt);
- }
--#endif
-
- /* 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("malloc",
-diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -4,23 +4,48 @@
- * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
- */
-
--asm(
-- " .text\n"
-- " .globl _start\n"
-- " .type _start,@function\n"
-- "_start:\n"
-- " .set _start,_dl_start\n"
-- " .size _start,.-_start\n"
-- " .previous\n"
--);
-+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\
-+ move.l _dl_skip_args(%pc), %d0\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\
-+ lea _dl_fini(%pc), %a1\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 if the first argument, on other platforms we need to
- * do something a little more subtle here. */
--#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned int *) & ARGS)
-+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
-
- /* Handle relocation of the symbols in the dynamic loader. */
--static inline
-+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)
- {
-@@ -59,12 +84,3 @@
- _dl_exit (1);
- }
- }
--
--/* Transfer control to the user's application, once the dynamic loader is
-- * done. This routine has to exit the current function, then call the
-- * _dl_elf_main function. */
--#define START() \
-- __asm__ volatile ( \
-- "unlk %%a6\n\t" \
-- "jmp %0@" \
-- : : "a" (_dl_elf_main));
-diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,5 +1,6 @@
- /* 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);}
--#include "sys/syscall.h"
-diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -25,10 +25,6 @@
- struct elf_resolve;
- extern unsigned int _dl_linux_resolver (struct elf_resolve *, int);
-
--/* Define this because we do not want to call .udiv in the library.
-- Not needed for m68k. */
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 4096 bytes alignment */
- #define PAGE_ALIGN 0xfffff000
- #define ADDR_ALIGN 0xfff
-diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -40,6 +40,8 @@
- a more than adequate job of explaining everything required to get this
- working. */
-
-+#include "ldso.h"
-+
- extern int _dl_linux_resolve(void);
-
- unsigned int
-@@ -48,20 +50,20 @@
- int reloc_type;
- ELF_RELOC *this_reloc;
- char *strtab;
-- Elf32_Sym *symtab;
-+ ElfW(Sym) *symtab;
- int symtab_index;
-- ELF_RELOC *rel_addr;
-+ char *rel_addr;
- char *new_addr;
- char **got_addr;
-- unsigned int instr_addr;
-+ ElfW(Addr) instr_addr;
- char *symname;
-
-- rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL];
-- this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
-- reloc_type = ELF32_R_TYPE(this_reloc->r_info);
-- symtab_index = ELF32_R_SYM(this_reloc->r_info);
-+ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
-+ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
-+ reloc_type = ELF_R_TYPE(this_reloc->r_info);
-+ symtab_index = ELF_R_SYM(this_reloc->r_info);
-
-- symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
-+ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
- symname = strtab + symtab[symtab_index].st_name;
-
-@@ -72,7 +74,7 @@
- }
-
- /* Address of the jump instruction to fix up. */
-- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
-+ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
- got_addr = (char **)instr_addr;
-
- /* Get the address of the GOT entry. */
-@@ -88,159 +90,237 @@
- _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
- if (_dl_debug_detail)
- _dl_dprintf(_dl_debug_file,
-- "\n\tpatched: %x ==> %x @ %x",
-+ "\tpatched: %x ==> %x @ %x\n",
- *got_addr, new_addr, got_addr);
- }
- }
-- if (!_dl_debug_nofixups) {
-- *got_addr = new_addr;
-- }
--#else
-- *got_addr = new_addr;
-+ if (!_dl_debug_nofixups)
- #endif
-+ *got_addr = new_addr;
-
-- return (unsigned int)new_addr;
-+ return (unsigned int)new_addr;
- }
-
--void
--_dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt,
-- unsigned long rel_addr, unsigned long rel_size)
-+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))
- {
-- int i;
-+ unsigned int i;
- char *strtab;
-- int reloc_type;
-+ ElfW(Sym) *symtab;
-+ ELF_RELOC *rpnt;
- int symtab_index;
-- Elf32_Sym *symtab;
-- Elf32_Rela *rpnt;
-- unsigned int *reloc_addr;
-- struct elf_resolve *tpnt = arg_rpnt->dyn;
--
-- /* Now parse the relocation information. */
-- rpnt = (Elf32_Rela *)rel_addr;
-- rel_size = rel_size / sizeof (Elf32_Rela);
-
-- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
-+ /* 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++) {
-- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
-- reloc_type = ELF32_R_TYPE (rpnt->r_info);
-- symtab_index = ELF32_R_SYM (rpnt->r_info);
-+ int res;
-
-- switch (reloc_type)
-- {
-- case R_68K_NONE:
-- break;
-- case R_68K_JMP_SLOT:
-- *reloc_addr += (unsigned int) tpnt->loadaddr;
-- break;
-- default:
-- _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
-+ 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__)
-- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]);
-+ "%s\n", _dl_reltypes(reloc_type));
-+#else
-+ "%x\n", reloc_type);
- #endif
-- if (symtab_index)
-- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
-- _dl_dprintf (2, "\n");
-- _dl_exit (1);
-+ _dl_exit(-res);
-+ } else if (unlikely(res > 0)) {
-+ _dl_dprintf(2, "can't resolve symbol\n");
-+ return res;
- }
- }
-+
-+ return 0;
- }
-
--int
--_dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
-- unsigned long rel_addr, unsigned long rel_size)
-+static int
-+_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
-+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
- {
-- int i;
-- char *strtab;
- int reloc_type;
-- int goof = 0;
-- Elf32_Sym *symtab;
-- Elf32_Rela *rpnt;
-- unsigned int *reloc_addr;
-- unsigned int symbol_addr;
- int symtab_index;
-- struct elf_resolve *tpnt = arg_rpnt->dyn;
-- /* Now parse the relocation information */
-+ char *symname;
-+ ElfW(Sym) *sym;
-+ ElfW(Addr) *reloc_addr;
-+ ElfW(Addr) symbol_addr;
-+#if defined (__SUPPORT_LD_DEBUG__)
-+ ElfW(Addr) old_val;
-+#endif
-
-- rpnt = (Elf32_Rela *)rel_addr;
-- rel_size = rel_size / sizeof (Elf32_Rela);
-+ 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 = &symtab[symtab_index];
-+ symbol_addr = 0;
-+ symname = strtab + sym->st_name;
-+
-+ if (symtab_index) {
-+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
-+ elf_machine_type_class(reloc_type));
-+ /*
-+ * 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->st_info) != STB_WEAK)) {
-+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
-+ _dl_exit(1);
-+ };
-+ }
-
-- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
-- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
-+#if defined (__SUPPORT_LD_DEBUG__)
-+ old_val = *reloc_addr;
-+#endif
-
-- for (i = 0; i < rel_size; i++, rpnt++) {
-- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
-- reloc_type = ELF32_R_TYPE (rpnt->r_info);
-- symtab_index = ELF32_R_SYM (rpnt->r_info);
-- symbol_addr = 0;
-- if (symtab_index) {
-- symbol_addr = (unsigned int)
-- _dl_find_hash (strtab + symtab[symtab_index].st_name,
-- tpnt->symbol_scope, tpnt,
-- elf_machine_type_class(reloc_type));
--
-- /* 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
-- && ELF32_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);
-- }
-- }
-- 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;
-- break;
-- case R_68K_RELATIVE:
-- *reloc_addr = ((unsigned int) tpnt->loadaddr
-- /* Compatibility kludge. */
-- + (rpnt->r_addend ? : *reloc_addr));
-- break;
-- case R_68K_COPY:
-+ 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->st_size,
-+ symbol_addr, reloc_addr);
-+#endif
- _dl_memcpy ((void *) reloc_addr,
- (void *) symbol_addr,
-- symtab[symtab_index].st_size);
-- break;
-- default:
-- _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
--#if defined (__SUPPORT_LD_DEBUG__)
-- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]);
--#endif
-- if (symtab_index)
-- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
-- _dl_dprintf (2, "\n");
-- _dl_exit (1);
-- }
-+ 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 dyn_elf *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);
- }
-- return goof;
-+
-+#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, rel_addr, rel_size);
-+#endif
-+}
-+
-+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);
- }
-diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S uClibc-0.9.28/ldso/ldso/m68k/resolve.S
---- uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/m68k/resolve.S 2006-04-28 00:14:35.000000000 -0600
-@@ -8,14 +8,16 @@
- .globl _dl_linux_resolve
- .type _dl_linux_resolve,@function
- _dl_linux_resolve:
-- moveml %a0/%a1,%sp@-
--#ifdef __PIC__
-- bsrl _dl_linux_resolver@PLTPC
--#else
-- jbsr _dl_linux_resolver
--#endif
-- moveml %sp@+,%a0/%a1
-- addql #8,%sp
-- jmp @(%d0)
--.LFE2:
-- .size _dl_linux_resolve,.LFE2-_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.
-+ jmp (%d0)
-+.size _dl_linux_resolve,.-_dl_linux_resolve
-diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h uClibc-0.9.28/ldso/ldso/mips/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/mips/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -136,13 +136,3 @@
- SEND_STDERR("Aiieeee!"); \
- _dl_exit(1); \
- }
--
--
--/*
-- * Transfer control to the user's application, once the dynamic loader
-- * is done. This routine has to exit the current function, then
-- * call the _dl_elf_main function. For MIPS, we do it in assembly
-- * because the stack doesn't get properly restored otherwise. Got look
-- * at boot1_arch.h
-- */
--#define START() return _dl_elf_main
-diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h 2006-05-02 13:39:25.000000000 -0600
-@@ -1,7 +1,8 @@
- /* We can't use the real errno in ldso, since it has not yet
- * been dynamicly linked in yet. */
-+#define __UCLIBC_MMAP_HAS_6_ARGS__
-+
-+#include "sys/syscall.h"
- extern int _dl_errno;
-+#undef __set_errno
- #define __set_errno(X) {(_dl_errno) = (X);}
--#include "sys/syscall.h"
--
--#define MMAP_HAS_6_ARGS
-diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -30,7 +30,7 @@
- /* Initialization sequence for the application/library GOT. */
- #define INIT_GOT(GOT_BASE,MODULE) \
- do { \
-- unsigned long i; \
-+ unsigned long idx; \
- \
- /* Check if this is the dynamic linker itself */ \
- if (MODULE->libtype == program_interpreter) \
-@@ -41,9 +41,9 @@
- GOT_BASE[1] = (unsigned long) MODULE; \
- \
- /* Add load address displacement to all local GOT entries */ \
-- i = 2; \
-- while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
-- GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
-+ idx = 2; \
-+ while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
-+ GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \
- \
- } while (0)
-
-@@ -63,8 +63,6 @@
- struct elf_resolve;
- void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
-
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 4096 bytes alignment */
- #define PAGE_ALIGN 0xfffff000
- #define ADDR_ALIGN 0xfff
-diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c uClibc-0.9.28/ldso/ldso/mips/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/mips/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -27,6 +27,8 @@
- * SUCH DAMAGE.
- */
-
-+#include "ldso.h"
-+
- extern int _dl_runtime_resolve(void);
-
- #define OFFSET_GP_GOT 0x7ff0
-@@ -146,7 +148,6 @@
- break;
- default:
- {
-- int reloc_type = ELF32_R_TYPE(rpnt->r_info);
- _dl_dprintf(2, "\n%s: ",_dl_progname);
-
- if (symtab_index)
-diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -42,8 +42,10 @@
- " bne 2b\n"
- " addi 6,6,4\n"
- #endif
-- /* Pass a termination function pointer (in this case _dl_fini) in r7. */
-- " lwz 7,_dl_fini@got(31)\n"
-+ /* 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"
-@@ -78,9 +80,3 @@
- _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\
- } \
- }
--/*
-- * Transfer control to the user's application, once the dynamic loader
-- * is done. This routine has to exit the current function, then
-- * call the _dl_elf_main function.
-- */
--#define START() return _dl_elf_main
-diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 13:39:14.000000000 -0600
-@@ -1,251 +1,8 @@
--/*
-- * This file contains the system call macros and syscall
-- * numbers used by the shared library loader.
-- */
--
--#define MMAP_HAS_6_ARGS
--
--#define __NR_exit 1
--#define __NR_read 3
--#define __NR_write 4
--#define __NR_open 5
--#define __NR_close 6
--#define __NR_getpid 20
--#define __NR_getuid 24
--#define __NR_geteuid 49
--#define __NR_getgid 47
--#define __NR_getegid 50
--#define __NR_readlink 85
--#define __NR_mmap 90
--#define __NR_munmap 91
--#define __NR_stat 106
--#define __NR_mprotect 125
--
--
- /* We can't use the real errno in ldso, since it has not yet
- * been dynamicly linked in yet. */
--extern int _dl_errno;
--
--/* Here are the macros which define how this platform makes
-- * system calls. This particular variant does _not_ set
-- * errno (note how it is disabled in __syscall_return) since
-- * these will get called before the errno symbol is dynamicly
-- * linked. */
--
--#undef __syscall_return
--#define __syscall_return(type) \
-- return (__sc_err & 0x10000000 ? _dl_errno = __sc_ret, __sc_ret = -1 : 0), \
-- (type) __sc_ret
--
--#undef __syscall_clobbers
--#define __syscall_clobbers \
-- "r9", "r10", "r11", "r12"
-- //"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
--
--#undef _syscall0
--#define _syscall0(type,name) \
--type name(void) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0) \
-- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
--#undef _syscall1
--#define _syscall1(type,name,type1,arg1) \
--type name(type1 arg1) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- \
-- __sc_3 = (unsigned long) (arg1); \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0) \
-- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
--#undef _syscall2
--#define _syscall2(type,name,type1,arg1,type2,arg2) \
--type name(type1 arg1, type2 arg2) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- register unsigned long __sc_4 __asm__ ("r4"); \
-- \
-- __sc_3 = (unsigned long) (arg1); \
-- __sc_4 = (unsigned long) (arg2); \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0), \
-- "r" (__sc_4) \
-- : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
--#undef _syscall3
--#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
--type name(type1 arg1, type2 arg2, type3 arg3) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- register unsigned long __sc_4 __asm__ ("r4"); \
-- register unsigned long __sc_5 __asm__ ("r5"); \
-- \
-- __sc_3 = (unsigned long) (arg1); \
-- __sc_4 = (unsigned long) (arg2); \
-- __sc_5 = (unsigned long) (arg3); \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0), \
-- "r" (__sc_4), \
-- "r" (__sc_5) \
-- : "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
--#undef _syscall4
--#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
--type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- register unsigned long __sc_4 __asm__ ("r4"); \
-- register unsigned long __sc_5 __asm__ ("r5"); \
-- register unsigned long __sc_6 __asm__ ("r6"); \
-- \
-- __sc_3 = (unsigned long) (arg1); \
-- __sc_4 = (unsigned long) (arg2); \
-- __sc_5 = (unsigned long) (arg3); \
-- __sc_6 = (unsigned long) (arg4); \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0), \
-- "r" (__sc_4), \
-- "r" (__sc_5), \
-- "r" (__sc_6) \
-- : "r7", "r8", "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
--#undef _syscall5
--#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
--type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- register unsigned long __sc_4 __asm__ ("r4"); \
-- register unsigned long __sc_5 __asm__ ("r5"); \
-- register unsigned long __sc_6 __asm__ ("r6"); \
-- register unsigned long __sc_7 __asm__ ("r7"); \
-- \
-- __sc_3 = (unsigned long) (arg1); \
-- __sc_4 = (unsigned long) (arg2); \
-- __sc_5 = (unsigned long) (arg3); \
-- __sc_6 = (unsigned long) (arg4); \
-- __sc_7 = (unsigned long) (arg5); \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0), \
-- "r" (__sc_4), \
-- "r" (__sc_5), \
-- "r" (__sc_6), \
-- "r" (__sc_7) \
-- : "r8", "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
--
--#undef _syscall6
--#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
--type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
--{ \
-- unsigned long __sc_ret, __sc_err; \
-- { \
-- register unsigned long __sc_0 __asm__ ("r0"); \
-- register unsigned long __sc_3 __asm__ ("r3"); \
-- register unsigned long __sc_4 __asm__ ("r4"); \
-- register unsigned long __sc_5 __asm__ ("r5"); \
-- register unsigned long __sc_6 __asm__ ("r6"); \
-- register unsigned long __sc_7 __asm__ ("r7"); \
-- register unsigned long __sc_8 __asm__ ("r8"); \
-- \
-- __sc_3 = (unsigned long) (arg1); \
-- __sc_4 = (unsigned long) (arg2); \
-- __sc_5 = (unsigned long) (arg3); \
-- __sc_6 = (unsigned long) (arg4); \
-- __sc_7 = (unsigned long) (arg5); \
-- __sc_8 = (unsigned long) (arg6); \
-- __sc_0 = __NR_##name; \
-- __asm__ __volatile__ \
-- ("sc \n\t" \
-- "mfcr %1 " \
-- : "=&r" (__sc_3), "=&r" (__sc_0) \
-- : "0" (__sc_3), "1" (__sc_0), \
-- "r" (__sc_4), \
-- "r" (__sc_5), \
-- "r" (__sc_6), \
-- "r" (__sc_7), \
-- "r" (__sc_8) \
-- : "r9", "r10", "r11", "r12" ); \
-- __sc_ret = __sc_3; \
-- __sc_err = __sc_0; \
-- } \
-- __syscall_return (type); \
--}
--
-+#define __UCLIBC_MMAP_HAS_6_ARGS__
-
-+#include "sys/syscall.h"
-+extern int _dl_errno;
-+#undef __set_errno
-+#define __set_errno(X) {(_dl_errno) = (X);}
-diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -67,9 +67,6 @@
- extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
- void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt);
-
--
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 4096 bytes alignment */
- #define PAGE_ALIGN 0xfffff000
- #define ADDR_ALIGN 0xfff
-diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -29,6 +29,8 @@
- * SUCH DAMAGE.
- */
-
-+#include "ldso.h"
-+
- extern int _dl_linux_resolve(void);
-
- void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
-@@ -138,7 +140,7 @@
- finaladdr = (Elf32_Addr) _dl_find_hash(symname,
- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
- if (unlikely(!finaladdr)) {
-- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
-+ _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;
-@@ -379,15 +381,15 @@
- {
- int reloc_type = ELF32_R_TYPE(rpnt->r_info);
- #if defined (__SUPPORT_LD_DEBUG__)
-- _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
-+ _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\n", reloc_type);
-+ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname);
- #endif
-- _dl_exit(-res);
-+ return res;
- }
- if (unlikely(res >0))
- {
-- _dl_dprintf(2, "can't resolve symbol\n");
-+ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
- return res;
- }
- }
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h uClibc-0.9.28/ldso/ldso/sh/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -55,11 +55,3 @@
- default: \
- _dl_exit(1); \
- }
--
--
--/*
-- * Transfer control to the user's application, once the dynamic loader
-- * is done. This routine has to exit the current function, then
-- * call the _dl_elf_main function.
-- */
--#define START() return _dl_elf_main;
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h 2006-05-02 13:39:28.000000000 -0600
-@@ -1,7 +1,8 @@
- /* We can't use the real errno in ldso, since it has not yet
- * been dynamicly linked in yet. */
-+#define __UCLIBC_MMAP_HAS_6_ARGS__
-+
-+#include "sys/syscall.h"
- extern int _dl_errno;
-+#undef __set_errno
- #define __set_errno(X) {(_dl_errno) = (X);}
--#include "sys/syscall.h"
--
--#define MMAP_HAS_6_ARGS
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -25,7 +25,7 @@
- struct elf_resolve;
- extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
-
--static __inline__ unsigned int
-+static inline unsigned int
- _dl_urem(unsigned int n, unsigned int base)
- {
- int res;
-@@ -104,7 +104,7 @@
- elf_machine_dynamic (void)
- {
- register Elf32_Addr *got;
-- asm ("mov r12,%0" :"=r" (got));
-+ __asm__ ("mov r12,%0" :"=r" (got));
- return *got;
- }
-
-@@ -113,7 +113,7 @@
- elf_machine_load_address (void)
- {
- Elf32_Addr addr;
-- asm ("mov.l 1f,r0\n\
-+ __asm__ ("mov.l 1f,r0\n\
- mov.l 3f,r2\n\
- add r12,r2\n\
- mov.l @(r0,r12),r0\n\
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c uClibc-0.9.28/ldso/ldso/sh/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -39,6 +39,8 @@
- 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)
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -115,12 +115,3 @@
- default: \
- _dl_exit(1); \
- }
--
--/*
-- * Transfer control to the user's application, once the dynamic loader
-- * is done. This routine has to exit the current function, then
-- * call the _dl_elf_main function.
-- */
--
--#define START() return _dl_elf_main;
--
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,8 +1,9 @@
- /* 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);}
--#include "sys/syscall.h"
-
- #undef __syscall_return
- #define __syscall_return(type, res) \
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -25,8 +25,6 @@
- struct elf_resolve;
- extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
-
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 4096 bytes alignment */
- #define PAGE_ALIGN 0xfffff000
- #define ADDR_ALIGN 0xfff
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -41,6 +41,8 @@
- 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)
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -3,15 +3,46 @@
- * 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"
-- "_start:\n"
-- " .set _start,_dl_start\n"
-- " .size _start,.-_start\n"
-- " .previous\n"
--);
-+
-+asm ("\
-+ .text\n\
-+ .global _start\n\
-+ .type _start,%function\n\
-+ .align 32\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
-@@ -19,17 +50,15 @@
- * 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) __asm__("\tadd %%fp,68,%0\n" : "=r" (ARGVP));
-+#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(ELF32_R_TYPE((RELP)->r_info)) { \
-+switch(ELF_R_TYPE((RELP)->r_info)) { \
- case R_SPARC_32: \
-- *REL = SYMBOL + (RELP)->r_addend; \
-- break; \
- case R_SPARC_GLOB_DAT: \
- *REL = SYMBOL + (RELP)->r_addend; \
- break; \
-@@ -38,7 +67,6 @@
- REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \
- break; \
- case R_SPARC_NONE: \
-- break; \
- case R_SPARC_WDISP30: \
- break; \
- case R_SPARC_RELATIVE: \
-@@ -46,18 +74,4 @@
- break; \
- default: \
- _dl_exit(1); \
-- }
--
--/*
-- * Transfer control to the user's application, once the dynamic loader
-- * is done. The crt calls atexit with $g1 if not null, so we need to
-- * ensure that it contains NULL.
-- */
--
--#define START() \
-- __asm__ volatile ( \
-- "add %%g0,%%g0,%%g1\n\t" \
-- "jmpl %0, %%o7\n\t" \
-- "restore %%g0,%%g0,%%g0\n\t" \
-- : /*"=r" (status) */ : \
-- "r" (_dl_elf_main): "g1", "o0", "o1")
-+}
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 13:39:21.000000000 -0600
-@@ -1,187 +1,8 @@
--/*
-- * This file contains the system call macros and syscall
-- * numbers used by the shared library loader.
-- *
-- * NOTE: This should be integrated/moved to
-- * sysdeps/linux/sparc/bits/syscalls.h at some point ...
-- */
--
--#define MMAP_HAS_6_ARGS
--
--#define __NR_exit 1
--#define __NR_read 3
--#define __NR_write 4
--#define __NR_open 5
--#define __NR_close 6
--#define __NR_getpid 20
--#define __NR_getuid 24
--#define __NR_getgid 47
--#define __NR_geteuid 49
--#define __NR_getegid 50
--#define __NR_readlink 58
--#define __NR_mmap 71
--#define __NR_munmap 73
--#define __NR_stat 38
--#define __NR_mprotect 74
--
- /* We can't use the real errno in ldso, since it has not yet
- * been dynamicly linked in yet. */
-+#define __UCLIBC_MMAP_HAS_6_ARGS__
-+
-+#include "sys/syscall.h"
- extern int _dl_errno;
-+#undef __set_errno
- #define __set_errno(X) {(_dl_errno) = (X);}
--
--/* Here are the macros which define how this platform makes
-- * system calls. This particular variant does _not_ set
-- * errno (note how _dl_errno is used in __syscall_return) since
-- * these will get called before the errno symbol is dynamicly
-- * linked. */
--
--#define __syscall_return(type, res) \
--do { \
-- if (res < -255 || res >= 0) \
-- return (type) res; \
-- __set_errno(-res); \
-- res = -1; \
-- return (type) res; \
--} while (0)
--
--#define _syscall0(type,name) \
--type name(void) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res)\
-- : "r" (__g1) \
-- : "o0", "cc"); \
-- __syscall_return(type, __res); \
--}
--
--#define _syscall1(type,name,type1,arg1) \
--type name(type1 arg1) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- register long __o0 __asm__ ("o0") = (long)(arg1); \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res), "=&r" (__o0) \
-- : "1" (__o0), "r" (__g1) \
-- : "cc"); \
-- __syscall_return(type, __res); \
--}
--
--#define _syscall2(type,name,type1,arg1,type2,arg2) \
--type name(type1 arg1,type2 arg2) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- register long __o0 __asm__ ("o0") = (long)(arg1); \
-- register long __o1 __asm__ ("o1") = (long)(arg2); \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res), "=&r" (__o0) \
-- : "1" (__o0), "r" (__o1), "r" (__g1) \
-- : "cc"); \
-- __syscall_return(type, __res); \
--}
--
--#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
--type name(type1 arg1,type2 arg2,type3 arg3) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- register long __o0 __asm__ ("o0") = (long)(arg1); \
-- register long __o1 __asm__ ("o1") = (long)(arg2); \
-- register long __o2 __asm__ ("o2") = (long)(arg3); \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res), "=&r" (__o0) \
-- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
-- : "cc"); \
-- __syscall_return(type, __res); \
--}
--
--#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
--type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- register long __o0 __asm__ ("o0") = (long)(arg1); \
-- register long __o1 __asm__ ("o1") = (long)(arg2); \
-- register long __o2 __asm__ ("o2") = (long)(arg3); \
-- register long __o3 __asm__ ("o3") = (long)(arg4); \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res), "=&r" (__o0) \
-- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
-- : "cc"); \
-- __syscall_return(type, __res); \
--}
--
--#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-- type5,arg5) \
--type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- register long __o0 __asm__ ("o0") = (long)(arg1); \
-- register long __o1 __asm__ ("o1") = (long)(arg2); \
-- register long __o2 __asm__ ("o2") = (long)(arg3); \
-- register long __o3 __asm__ ("o3") = (long)(arg4); \
-- register long __o4 __asm__ ("o4") = (long)(arg5); \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res), "=&r" (__o0) \
-- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
-- : "cc"); \
-- __syscall_return(type, __res); \
--}
--
--#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-- type5,arg5,type6,arg6) \
--type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
--{ \
-- long __res; \
-- register long __g1 __asm__ ("g1") = __NR_##name; \
-- register long __o0 __asm__ ("o0") = (long)(arg1); \
-- register long __o1 __asm__ ("o1") = (long)(arg2); \
-- register long __o2 __asm__ ("o2") = (long)(arg3); \
-- register long __o3 __asm__ ("o3") = (long)(arg4); \
-- register long __o4 __asm__ ("o4") = (long)(arg5); \
-- register long __o5 __asm__ ("o5") = (long)(arg6); \
-- __asm__ __volatile__ ( \
-- "t 0x10\n\t" \
-- "bcc 1f\n\t" \
-- "mov %%o0, %0\n\t" \
-- "sub %%g0, %%o0, %0\n\t" \
-- "1:\n\t" \
-- : "=r" (__res), "=&r" (__o0) \
-- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \
-- : "cc"); \
-- __syscall_return(type, __res); \
--}
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -1,9 +1,9 @@
--
-+/* vi: set sw=4 ts=4: */
- /*
- * Various assmbly 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 LINUXBIN
-
- /* Define this if the system uses RELOCA. */
- #define ELF_USES_RELOCA
-@@ -31,19 +31,14 @@
- #undef MAGIC2
-
- /* Used for error messages */
--#define ELF_TARGET "Sparc"
-+#define ELF_TARGET "sparc"
-
--#ifndef COMPILE_ASM
--extern unsigned int _dl_linux_resolver(unsigned int reloc_entry,
-- unsigned int * i);
--#endif
-+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 __linux__
--#define SOLARIS_COMPATIBLE
--#endif
-
- #ifndef COMPILE_ASM
- /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */
-@@ -87,13 +82,6 @@
- #define do_rem(result, n, base) ((result) = sparc_mod(n, base))
- #endif
-
--/*
-- * dbx wants the binder to have a specific name. Mustn't disappoint it.
-- */
--#ifdef SOLARIS_COMPATIBLE
--#define _dl_linux_resolve _elf_rtbndr
--#endif
--
- /* 4096 bytes alignment */
- /* ...but 8192 is required for mmap() on sparc64 kernel */
- #define PAGE_ALIGN 0xffffe000
-@@ -160,7 +148,7 @@
- elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
- Elf32_Word relative_count)
- {
-- Elf32_Rela * rpnt = (void *)rel_addr;
-+ Elf32_Rela * rpnt = (void *)rel_addr;
- --rpnt;
- do {
- Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
-diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -33,236 +33,340 @@
- 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. */
-+ 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 int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
-+unsigned long
-+_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
- {
-- int reloc_type;
-- Elf32_Rela * this_reloc;
-- char * strtab;
-- Elf32_Sym * symtab;
-- Elf32_Rela * rel_addr;
-- struct elf_resolve * tpnt;
-- int symtab_index;
-- char * new_addr;
-- char ** got_addr;
-- unsigned int instr_addr;
-- tpnt = (struct elf_resolve *) plt[2];
--
-- rel_addr = (Elf32_Rela *)tpnt->dynamic_info[DT_JMPREL];
--
-- /*
-- * Generate the correct relocation index into the .rela.plt section.
-- */
-- reloc_entry = (reloc_entry >> 10) - 0xc;
--
-- this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
--
-- reloc_type = ELF32_R_TYPE(this_reloc->r_info);
-- symtab_index = ELF32_R_SYM(this_reloc->r_info);
--
-- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
-- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
--
--#ifdef __SUPPORT_LD_DEBUG__
-- if (_dl_debug_symbols) {
-- _dl_dprintf(2, "tpnt = %x\n", tpnt);
-- _dl_dprintf(2, "reloc = %x\n", this_reloc);
-- _dl_dprintf(2, "symtab = %x\n", symtab);
-- _dl_dprintf(2, "strtab = %x\n", strtab);
-- }
--#endif
--
--
-- if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
-- _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
-- _dl_progname, reloc_type);
-- _dl_exit(30);
-- };
--
-- /* Address of jump instruction to fix up */
-- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
-- got_addr = (char **) instr_addr;
--
--#ifdef __SUPPORT_LD_DEBUG__
-- if (_dl_debug_symbols) {
-- _dl_dprintf(2, "symtab_index %x\n", symtab_index);
--
-- _dl_dprintf(2, "Resolving symbol %s\n",
-- strtab + symtab[symtab_index].st_name);
-- }
--#endif
--
-- /* Get the address of the GOT entry */
-- new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
-- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
-- if(unlikely(!new_addr)) {
-- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
-- _dl_progname, strtab + symtab[symtab_index].st_name);
-- _dl_exit(31);
-- };
-+ int reloc_type;
-+ 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);
-+ reloc_type = ELF_R_TYPE(this_reloc->r_info);
-+ 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;
-+
-+ if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
-+ _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
-+ _dl_progname);
-+ _dl_exit(1);
-+ }
-+
-+ /* 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, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
-+ 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",
-- strtab + symtab[symtab_index].st_name);
-- if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
-- "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
-+ 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) {
-+ if (!_dl_debug_nofixups)
-+#endif
-+ {
- got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
- got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
- }
-+
-+ return (unsigned long)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;
-+
-+ /* 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
-- got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
-- got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
-+ "%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;
-+}
-
-- _dl_dprintf(2, "Address = %x\n",new_addr);
-- _dl_exit(32);
-+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;
-+ ElfW(Sym) *sym;
-+ 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 = &symtab[symtab_index];
-+ symbol_addr = 0;
-+ symname = strtab + sym->st_name;
-+
-+ if (symtab_index) {
-+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
-+ elf_machine_type_class(reloc_type));
-+ /*
-+ * 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->st_info) != STB_WEAK)) {
-+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
-+ _dl_exit(1);
-+ }
-+ }
-+
-+#if defined (__SUPPORT_LD_DEBUG__)
-+ old_val = *reloc_addr;
-+#endif
-
-- return (unsigned int) new_addr;
-+ symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */
-+
-+ switch (reloc_type) {
-+ case R_SPARC_NONE:
-+ break;
-+
-+#if 0 /* these dont really seem to be useful */
-+ case R_SPARC_8:
-+ *(char *) reloc_addr = symbol_addr;
-+ break;
-+ case R_SPARC_16:
-+ *(short *) reloc_addr = symbol_addr;
-+ break;
-+ case R_SPARC_DISP8:
-+ *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr;
-+ break;
-+ case R_SPARC_DISP16:
-+ *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr;
-+ break;
-+#endif
-+
-+ 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:
-+/*
-+value = symbol_addr;
-+value += reloc->r_addend;
-+disp = value - reloc_addr;
-+reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff);
-+reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10);
-+ reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff);
-+ reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10);
-+*/
-+ reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
-+ reloc_addr[2] = 0x81c06000 | (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->st_size,
-+ symbol_addr, reloc_addr);
-+#endif
-+
-+ _dl_memcpy((char *)reloc_addr,
-+ (char *)symbol_addr,
-+ 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 __SPARC_LAZY_RELOC_WORKS
-+#ifdef __SPARC_LAZY_RELOC_WORKS
-+static int
-+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *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 *arg_rpnt,
-- unsigned long rel_addr, unsigned long rel_size)
--{
-- int i;
-- char * strtab;
-- int reloc_type;
-- int symtab_index;
-- Elf32_Sym * symtab;
-- Elf32_Rela * rpnt;
-- unsigned int * reloc_addr;
-- struct elf_resolve * tpnt = arg_rpnt->dyn;
--
-- /* Now parse the relocation information */
-- rpnt = (Elf32_Rela *)rel_addr;
--
-- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
-- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
--
-- for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
-- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
-- reloc_type = ELF32_R_TYPE(rpnt->r_info);
-- symtab_index = ELF32_R_SYM(rpnt->r_info);
--
-- switch(reloc_type){
-- case R_SPARC_NONE:
-- break;
-- case R_SPARC_JMP_SLOT:
-- break;
-- default:
-- _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
--#if defined (__SUPPORT_LD_DEBUG__)
-- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]);
--#endif
-- if(symtab_index) _dl_dprintf(2, "'%s'\n",
-- strtab + symtab[symtab_index].st_name);
-- _dl_exit(33);
-- };
-- };
--}
--
--int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
-- unsigned long rel_addr, unsigned long rel_size)
--{
-- int i;
-- char * strtab;
-- int reloc_type;
-- int goof = 0;
-- Elf32_Sym * symtab;
-- Elf32_Rela * rpnt;
-- unsigned int * reloc_addr;
-- unsigned int symbol_addr;
-- int symtab_index;
-- struct elf_resolve * tpnt = arg_rpnt->dyn;
-- /* Now parse the relocation information */
--
-- rpnt = (Elf32_Rela *)rel_addr;
--
-- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
-- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
--
-- for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
-- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
-- reloc_type = ELF32_R_TYPE(rpnt->r_info);
-- symtab_index = ELF32_R_SYM(rpnt->r_info);
-- symbol_addr = 0;
--
-- if(symtab_index) {
--
-- symbol_addr = (unsigned int)
-- _dl_find_hash(strtab + symtab[symtab_index].st_name,
-- tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type));
--
-- if(!symbol_addr &&
-- ELF32_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);
-- };
-- };
-- switch(reloc_type){
-- case R_SPARC_NONE:
-- break;
-- case R_SPARC_32:
-- *reloc_addr = symbol_addr + rpnt->r_addend;
-- break;
-- case R_SPARC_DISP32:
-- *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
-- break;
-- case R_SPARC_GLOB_DAT:
-- *reloc_addr = symbol_addr + rpnt->r_addend;
-- break;
-- case R_SPARC_JMP_SLOT:
-- reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
-- reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
-- break;
-- case R_SPARC_RELATIVE:
-- *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
-- 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_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_WDISP30:
-- *reloc_addr = (*reloc_addr & 0xc0000000)|
-- ((symbol_addr - (unsigned int) reloc_addr) >> 2);
-- break;
-- case R_SPARC_COPY:
-- _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size);
-- break;
-- default:
-- _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
--#if defined (__SUPPORT_LD_DEBUG__)
-- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]);
--#endif
-- if (symtab_index)
-- _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-- _dl_exit(34);
-- };
-+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, rel_addr, rel_size);
-+#endif
-+}
-
-- };
-- return goof;
-+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);
- }
-diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h
---- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h 2006-04-28 00:14:35.000000000 -0600
-@@ -30,7 +30,10 @@
- */
-
- static const char *_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"
-+ [ 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 -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h
---- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
-@@ -6,7 +6,7 @@
- *
- * Parts taken from glibc/sysdeps/x86_64/dl-machine.h
- */
--asm(
-+__asm__ (
- " .text\n"
- " .align 16\n"
- " .global _start\n"
-@@ -42,10 +42,10 @@
-
- /* 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, Elf64_Sym *sym)
-+void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr,
-+ ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym)
- {
-- switch (ELF64_R_TYPE(rpnt->r_info)) {
-+ 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;
-@@ -63,8 +63,3 @@
- _dl_exit(1);
- }
- }
--
--/* Transfer control to the user's application, once the dynamic loader is
-- * done. This routine has to exit the current function, then call the
-- * _dl_elf_main function. */
--#define START() return _dl_elf_main
-diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h
---- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 13:39:17.000000000 -0600
-@@ -1,7 +1,8 @@
- /* We can't use the real errno in ldso, since it has not yet
- * been dynamicly linked in yet. */
-+#define __UCLIBC_MMAP_HAS_6_ARGS__
-+
-+#include "sys/syscall.h"
- extern int _dl_errno;
-+#undef __set_errno
- #define __set_errno(X) {(_dl_errno) = (X);}
--#include "sys/syscall.h"
--
--#define MMAP_HAS_6_ARGS
-diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h
---- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
-@@ -41,8 +41,6 @@
- struct elf_resolve;
- extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
-
--#define do_rem(result, n, base) ((result) = (n) % (base))
--
- /* 4096 bytes alignment */
- #define PAGE_ALIGN 0xfffff000
- #define ADDR_ALIGN 0xfff
-@@ -90,7 +88,7 @@
- and compare it with the current value that we can get via
- an RIP relative addressing mode. */
-
-- asm ("movq 1f(%%rip), %1\n"
-+ __asm__ ("movq 1f(%%rip), %1\n"
- "0:\tleaq _dl_start(%%rip), %0\n\t"
- "subq %1, %0\n\t"
- ".section\t.data\n"
-diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c
---- uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
-@@ -165,6 +165,7 @@
- int reloc_type;
- int symtab_index;
- char *symname;
-+ ElfW(Sym) *sym;
- ElfW(Addr) *reloc_addr;
- ElfW(Addr) symbol_addr;
- #if defined (__SUPPORT_LD_DEBUG__)
-@@ -174,8 +175,9 @@
- 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 = &symtab[symtab_index];
- symbol_addr = 0;
-- symname = strtab + symtab[symtab_index].st_name;
-+ symname = strtab + sym->st_name;
-
- if (symtab_index) {
- symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
-@@ -185,7 +187,7 @@
- * 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(symtab[symtab_index].st_info) != STB_WEAK)) {
-+ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
- _dl_exit(1);
- };
-@@ -209,7 +211,7 @@
-
- case R_X86_64_GLOB_DAT:
- case R_X86_64_JUMP_SLOT:
-- *reloc_addr = symbol_addr;
-+ *reloc_addr = symbol_addr + rpnt->r_addend;
- break;
-
- /* handled by elf_machine_relative()
-@@ -217,33 +219,33 @@
- *reloc_addr = map->l_addr + rpnt->r_addend;
- break;
- */
--#if 0
- case R_X86_64_DTPMOD64:
-+ *reloc_addr = 1;
- break;
- case R_X86_64_DTPOFF64:
-- *reloc_addr = symbol_addr + rpnt->r_addend;
-+ *reloc_addr = sym->st_value + rpnt->r_addend;
- break;
- case R_X86_64_TPOFF64:
-- *reloc_addr = symbol_addr + rpnt->r_addend;
-+ *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr;
- break;
- case R_X86_64_32:
-- *reloc_addr = symbol_addr + rpnt->r_addend;
-+ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;
-+ /* XXX: should check for overflow eh ? */
- break;
-
--#endif
- 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, symtab[symtab_index].st_size,
-+ symname, sym->st_size,
- symbol_addr, reloc_addr);
- #endif
-
- _dl_memcpy((char *)reloc_addr,
- (char *)symbol_addr,
-- symtab[symtab_index].st_size);
-+ sym->st_size);
- } else
- _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
- break;
-@@ -261,7 +263,6 @@
- return 0;
- }
-
--#if 0
- static int
- _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
- ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
-@@ -288,7 +289,7 @@
- case R_X86_64_NONE:
- break;
- case R_X86_64_JUMP_SLOT:
-- *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value;
-+ *reloc_addr += (unsigned long)tpnt->loadaddr;
- break;
- default:
- _dl_exit(1);
-@@ -302,17 +303,13 @@
-
- return 0;
- }
--#endif
-
- void
- _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
- unsigned long rel_addr,
- unsigned long rel_size)
- {
-- _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
--/* jump slot isnt working
- (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
--*/
- }
-
- int
-diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S uClibc-0.9.28/ldso/ldso/x86_64/resolve.S
---- uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S 1969-12-31 17:00:00.000000000 -0700
-+++ uClibc-0.9.28/ldso/ldso/x86_64/resolve.S 2006-04-28 00:14:35.000000000 -0600
-@@ -0,0 +1,63 @@
-+/*
-+ * 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
-+.align 16
-+
-+_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 -urN uClibc-0.9.28.orig/ldso/libdl/Makefile uClibc-0.9.28/ldso/libdl/Makefile
---- uClibc-0.9.28.orig/ldso/libdl/Makefile 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/libdl/Makefile 2006-04-28 00:14:35.000000000 -0600
-@@ -29,12 +29,14 @@
- endif
- XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) \
- -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
-- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I. -I$(TOPDIR)include
-+ -fno-builtin -nostdinc -D_LIBC \
-+ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \
-+ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include
-
- XXFLAGS+=-isystem $(shell $(CC) -print-file-name=include)
- XXFLAGS_NOPIC:=$(XXFLAGS)
- ifeq ($(DOPIC),y)
-- XXFLAGS += $(PICFLAG) -D__LIBDL_SHARED__
-+ XXFLAGS += $(PICFLAG) -DSHARED
- endif
- ifeq ($(strip $(SUPPORT_LD_DEBUG)),y)
- XXFLAGS+=-D__SUPPORT_LD_DEBUG__
-diff -urN uClibc-0.9.28.orig/ldso/libdl/libdl.c uClibc-0.9.28/ldso/libdl/libdl.c
---- uClibc-0.9.28.orig/ldso/libdl/libdl.c 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/ldso/libdl/libdl.c 2006-04-28 00:14:35.000000000 -0600
-@@ -3,7 +3,7 @@
- * Program to load an ELF binary on a linux system, and run it
- * after resolving ELF shared library symbols
- *
-- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
-+ * 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
- *
-@@ -30,12 +30,12 @@
- */
-
-
--#define _GNU_SOURCE
-+#define _GNU_SOURCE
- #include <ldso.h>
- #include <stdio.h>
-
-
--#if defined (__LIBDL_SHARED__)
-+#ifdef SHARED
-
- /* When libdl is loaded as a shared library, we need to load in
- * and use a pile of symbols from ldso... */
-@@ -52,6 +51,8 @@
- extern struct r_debug *_dl_debug_addr;
- extern unsigned long _dl_error_number;
- extern void *(*_dl_malloc_function)(size_t);
-+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);
-@@ -64,7 +65,7 @@
- #endif
-
-
--#else /* __LIBDL_SHARED__ */
-+#else /* SHARED */
-
- /* When libdl is linked as a static library, we need to replace all
- * the symbols that otherwise would have been loaded in from ldso... */
-@@ -81,11 +82,11 @@
- struct r_debug *_dl_debug_addr = NULL;
- #define _dl_malloc malloc
- #include "../ldso/dl-debug.c"
--#include "dl-progname.h"
-+#include LDSO_ELFINTERP
- #include "../ldso/dl-hash.c"
- #define _dl_trace_loaded_objects 0
- #include "../ldso/dl-elf.c"
--#endif /* __LIBDL_SHARED__ */
-+#endif /* SHARED */
-
- #ifdef __SUPPORT_LD_DEBUG__
- # define _dl_if_debug_print(fmt, args...) \
-@@ -126,7 +127,8 @@
- "Unable to resolve symbol"
- };
-
--void __attribute__ ((destructor)) dl_cleanup(void)
-+void dl_cleanup(void) __attribute__ ((destructor));
-+void dl_cleanup(void)
- {
- struct dyn_elf *d;
- for (d = _dl_handles; d; d = d->next_handle) {
-@@ -138,13 +140,12 @@
- {
- struct elf_resolve *tpnt, *tfrom;
- struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
-- struct dyn_elf *dpnt;
- ElfW(Addr) from;
- struct elf_resolve *tpnt1;
- void (*dl_brk) (void);
- int now_flag;
- struct init_fini_list *tmp, *runp, *runp2, *dep_list;
-- int nlist, i;
-+ unsigned int nlist, i;
- struct elf_resolve **init_fini_list;
-
- /* A bit of sanity checking... */
-@@ -169,12 +170,15 @@
- * the application. Thus this may go away at some time
- * in the future.
- */
-- tfrom = NULL;
-- for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
-- tpnt = dpnt->dyn;
-- if (tpnt->loadaddr < from
-- && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
-- tfrom = tpnt;
-+ {
-+ struct dyn_elf *dpnt;
-+ tfrom = NULL;
-+ for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
-+ tpnt = dpnt->dyn;
-+ if (tpnt->loadaddr < from
-+ && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
-+ tfrom = tpnt;
-+ }
- }
- for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next);
-
-@@ -233,11 +237,8 @@
- 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) {
-- char *name;
--
- lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
- dpnt->d_un.d_val);
-- name = _dl_get_last_path_component(lpntstr);
- _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);
-@@ -297,14 +298,14 @@
- }
- /* Sort the INIT/FINI list in dependency order. */
- for (runp2 = dep_list; runp2; runp2 = runp2->next) {
-- int j, k;
-+ 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 *runp = init_fini_list[k]->init_fini;
-+ struct init_fini_list *ele = init_fini_list[k]->init_fini;
-
-- for (; runp; runp = runp->next) {
-- if (runp->tpnt == runp2->tpnt) {
-+ 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)
-@@ -367,7 +368,7 @@
- }
- }
-
--#if defined (__LIBDL_SHARED__)
-+#ifdef SHARED
- /* Run the ctors and setup the dtors */
- for (i = nlist; i; --i) {
- tpnt = init_fini_list[i-1];
-@@ -384,8 +385,11 @@
- (*dl_elf_func) ();
- }
- }
-+
-+ _dl_run_init_array(tpnt);
- }
--#endif
-+#endif /* SHARED */
-+
- _dl_unmap_cache();
- return (void *) dyn_chain;
-
-@@ -450,9 +454,16 @@
- 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;
-+ struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
- struct init_fini_list *runp, *tmp;
- ElfW(Phdr) *ppnt;
- struct elf_resolve *tpnt, *run_tpnt;
-@@ -460,7 +471,7 @@
- void (*dl_brk) (void);
- struct dyn_elf *handle;
- unsigned int end;
-- int i = 0, j;
-+ unsigned int i, j;
-
- handle = (struct dyn_elf *) vhandle;
- if (handle == _dl_symbol_tables)
-@@ -491,13 +502,21 @@
- for (j = 0; j < handle->init_fini.nlist; ++j) {
- tpnt = handle->init_fini.init_fini[j];
- if (--tpnt->usage_count == 0) {
-- if (tpnt->dynamic_info[DT_FINI] && need_fini &&
-+ 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_elf_fini = (int (*)(void)) (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_elf_fini) ();
-+#ifdef SHARED
-+ _dl_run_fini_array(tpnt);
-+#endif
-+
-+ if (tpnt->dynamic_info[DT_FINI]) {
-+ dl_elf_fini = (int (*)(void)) (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_elf_fini) ();
-+ }
- }
-
- _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
-@@ -541,8 +560,9 @@
- 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->next->next;
-+ rpnt1->next = rpnt1_tmp;
- if (rpnt1->next)
- rpnt1->next->prev = rpnt1;
- break;
-@@ -588,8 +608,9 @@
- }
-
- /*
-- * Dump information to stderrr about the current loaded modules
-+ * Dump information to stderr about the current loaded modules
- */
-+#if 1
- static char *type[] = { "Lib", "Exe", "Int", "Mod" };
-
- int dlinfo(void)
-@@ -660,16 +681,14 @@
- {
- char *strtab;
- ElfW(Sym) *symtab;
-- int hn, si;
-- int sf;
-- int sn = 0;
-+ unsigned int hn, si, sn, sf;
- ElfW(Addr) sa;
-
- sa = 0;
- symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
- strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
-
-- sf = 0;
-+ sf = sn = 0;
- for (hn = 0; hn < pelf->nbucket; hn++) {
- for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
- ElfW(Addr) symbol_addr;
-@@ -696,3 +715,4 @@
- return 1;
- }
- }
-+#endif
-diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h
---- uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -4,17 +4,15 @@
- # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
- #endif
-
-+#include <errno.h>
-+
- /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
- * header files. It also defines the traditional `SYS_<name>' macros for older
- * programs. */
- #include <bits/sysnum.h>
-
--#ifndef __set_errno
--# define __set_errno(val) (*__errno_location ()) = (val)
--#endif
--
- /*
-- Some of the sneaky macros in the code were taken from
-+ Some of the sneaky macros in the code were taken from
- glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h
- */
-
-@@ -22,7 +20,8 @@
-
- /* We need some help from the assembler to generate optimal code. We
- define some macros here which later will be used. */
--asm (".L__X'%ebx = 1\n\t"
-+
-+__asm__ (".L__X'%ebx = 1\n\t"
- ".L__X'%ecx = 2\n\t"
- ".L__X'%edx = 2\n\t"
- ".L__X'%eax = 3\n\t"
-@@ -56,7 +55,6 @@
- ".endif\n\t"
- ".endm\n\t");
-
--
- #undef _syscall0
- #define _syscall0(type,name) \
- type name(void) \
-@@ -90,7 +88,7 @@
- type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
- { \
- return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \
--}
-+}
-
- #undef _syscall5
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-@@ -100,10 +98,18 @@
- return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \
- }
-
-+#undef _syscall6
-+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
-+ type5,arg5,type6,arg6) \
-+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \
-+{ \
-+return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \
-+}
-+
- #define INLINE_SYSCALL(name, nr, args...) \
- ({ \
- unsigned int resultvar; \
-- asm volatile ( \
-+ __asm__ __volatile__ ( \
- LOADARGS_##nr \
- "movl %1, %%eax\n\t" \
- "int $0x80\n\t" \
-@@ -125,6 +131,7 @@
- #define LOADARGS_3 LOADARGS_1
- #define LOADARGS_4 LOADARGS_1
- #define LOADARGS_5 LOADARGS_1
-+#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t"
-
- #define RESTOREARGS_0
- #define RESTOREARGS_1 \
-@@ -133,6 +140,7 @@
- #define RESTOREARGS_3 RESTOREARGS_1
- #define RESTOREARGS_4 RESTOREARGS_1
- #define RESTOREARGS_5 RESTOREARGS_1
-+#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1
-
- #define ASMFMT_0()
- #define ASMFMT_1(arg1) \
-@@ -145,7 +153,8 @@
- , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
- #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
- , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
--
-+#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \
-+ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6)
-
- #endif /* __ASSEMBLER__ */
- #endif /* _BITS_SYSCALLS_H */
-diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h
---- uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600
-+++ uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600
-@@ -5,67 +5,164 @@
- # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
- #endif
-
-+#include <errno.h>
-+
- /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
- * header files. It also defines the traditional `SYS_<name>' macros for older
- * programs. */
- #include <bits/sysnum.h>
-
--
--#define __STRINGIFY(s) __STRINGIFY2 (s)
--#define __STRINGIFY2(s) #s
--
--#undef JUMPTARGET
--#ifdef __PIC__
--#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall@plt)
-+/* Define a macro which expands inline into the wrapper code for a system
-+ call. This use is for internal calls that do not need to handle errors
-+ normally. It will never touch errno.
-+ On powerpc a system call basically clobbers the same registers like a
-+ function call, with the exception of LR (which is needed for the
-+ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
-+ an error return status). */
-+
-+# undef INLINE_SYSCALL
-+#if 1
-+# define INLINE_SYSCALL(name, nr, args...) \
-+ ({ \
-+ INTERNAL_SYSCALL_DECL (sc_err); \
-+ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
-+ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
-+ { \
-+ __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
-+ sc_ret = -1L; \
-+ } \
-+ sc_ret; \
-+ })
- #else
--#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall)
-+# define INLINE_SYSCALL(name, nr, args...) \
-+ ({ \
-+ INTERNAL_SYSCALL_DECL (sc_err); \
-+ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
-+ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
-+ { \
-+ sc_ret = __syscall_error(INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));\
-+ } \
-+ sc_ret; \
-+ })
- #endif
-
--#define unified_syscall_body(name) \
-- __asm__ ( \
-- ".section \".text\"\n\t" \
-- ".align 2\n\t" \
-- ".globl " __STRINGIFY(name) "\n\t" \
-- ".type " __STRINGIFY(name) ",@function\n\t" \
-- #name":\tli 0," __STRINGIFY(__NR_##name) "\n\t" \
-- "b " __MAKE_SYSCALL "\n\t" \
-- ".size\t" __STRINGIFY(name) ",.""-" __STRINGIFY(name) "\n" \
-- )
-+/* Define a macro which expands inline into the wrapper code for a system
-+ call. This use is for internal calls that do not need to handle errors
-+ normally. It will never touch errno.
-+ On powerpc a system call basically clobbers the same registers like a
-+ function call, with the exception of LR (which is needed for the
-+ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
-+ an error return status). */
-+
-+# undef INTERNAL_SYSCALL_DECL
-+# define INTERNAL_SYSCALL_DECL(err) long int err
-+
-+# undef INTERNAL_SYSCALL
-+# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
-+ ({ \
-+ register long int r0 __asm__ ("r0"); \
-+ register long int r3 __asm__ ("r3"); \
-+ register long int r4 __asm__ ("r4"); \
-+ register long int r5 __asm__ ("r5"); \
-+ register long int r6 __asm__ ("r6"); \
-+ register long int r7 __asm__ ("r7"); \
-+ register long int r8 __asm__ ("r8"); \
-+ register long int r9 __asm__ ("r9"); \
-+ register long int r10 __asm__ ("r10"); \
-+ register long int r11 __asm__ ("r11"); \
-+ register long int r12 __asm__ ("r12"); \
-+ LOADARGS_##nr(name, args); \
-+ __asm__ __volatile__ \
-+ ("sc \n\t" \
-+ "mfcr %0" \
-+ : "=&r" (r0), \
-+ "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
-+ "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
-+ : ASM_INPUT_##nr \
-+ : "cr0", "ctr", "memory"); \
-+ err = r0; \
-+ (int) r3; \
-+ })
-+# define INTERNAL_SYSCALL(name, err, nr, args...) \
-+ INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
-+
-+# undef INTERNAL_SYSCALL_ERROR_P
-+# define INTERNAL_SYSCALL_ERROR_P(val, err) \
-+ ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
-+
-+# undef INTERNAL_SYSCALL_ERRNO
-+# define INTERNAL_SYSCALL_ERRNO(val, err) (val)
-+
-+# define LOADARGS_0(name, dummy) \
-+ r0 = (long int)name
-+# define LOADARGS_1(name, __arg1) \
-+ LOADARGS_0(name, 0); \
-+ r3 = (long int)__arg1
-+# define LOADARGS_2(name, __arg1, __arg2) \
-+ LOADARGS_1(name, __arg1); \
-+ r4 = (long int)__arg2
-+# define LOADARGS_3(name, __arg1, __arg2, __arg3) \
-+ LOADARGS_2(name, __arg1, __arg2); \
-+ r5 = (long int)__arg3
-+# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
-+ LOADARGS_3(name, __arg1, __arg2, __arg3); \
-+ r6 = (long int)__arg4
-+# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
-+ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
-+ r7 = (long int)__arg5
-+# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
-+ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
-+ r8 = (long int)__arg6
-+
-+# define ASM_INPUT_0 "0" (r0)
-+# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
-+# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
-+# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
-+# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
-+# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
-+# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
-
- #undef _syscall0
--#define _syscall0(type,name) \
--type name(void); \
--unified_syscall_body(name)
-+#define _syscall0(type,name) \
-+type name(void){ \
-+ return (type) INLINE_SYSCALL(name, 0); \
-+}
-
- #undef _syscall1
- #define _syscall1(type,name,type1,arg1) \
--type name(type1 arg1); \
--unified_syscall_body(name)
-+type name(type1 arg1){ \
-+ return (type) INLINE_SYSCALL(name, 1, arg1); \
-+}
-
- #undef _syscall2
- #define _syscall2(type,name,type1,arg1,type2,arg2) \
--type name(type1 arg1, type2 arg2); \
--unified_syscall_body(name)
-+type name(type1 arg1, type2 arg2){ \
-+ return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \
-+}
-
- #undef _syscall3
- #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
--type name(type1 arg1, type2 arg2, type3 arg3); \
--unified_syscall_body(name)
-+type name(type1 arg1, type2 arg2, type3 arg3){ \
-+ return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \
-+}
-
- #undef _syscall4
- #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
--type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \
--unified_syscall_body(name)
-+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \
-+ return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \
-+}
-
- #undef _syscall5
- #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
--type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \
--unified_syscall_body(name)
-+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \
-+ return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \
-+}
-
- #undef _syscall6
- #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
--type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6); \
--unified_syscall_body(name)
-+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \
-+ return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \
-+}
-
- #endif /* _BITS_SYSCALLS_H */
-
+++ /dev/null
-Index: uclibc/libm/fp_private.h
-===================================================================
---- uclibc/libm/fp_private.h (revision 12879)
-+++ uclibc/libm/fp_private.h (working copy)
-@@ -70,10 +70,11 @@
- *******************************************************************************/
-
- #include <stdint.h>
-+#include <endian.h>
-
- typedef struct /* Hex representation of a double. */
- {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- uint32_t high;
- uint32_t low;
- #else
-Index: uclibc/libm/powerpc/s_ceil.c
-===================================================================
---- uclibc/libm/powerpc/s_ceil.c (revision 12879)
-+++ uclibc/libm/powerpc/s_ceil.c (working copy)
-@@ -21,13 +21,15 @@
- * *
- *******************************************************************************/
-
-+#include <endian.h>
-+
- static const double twoTo52 = 4503599627370496.0;
- static const unsigned long signMask = 0x80000000ul;
-
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/s_ldexp.c
-===================================================================
---- uclibc/libm/powerpc/s_ldexp.c (revision 12879)
-+++ uclibc/libm/powerpc/s_ldexp.c (working copy)
-@@ -21,11 +21,12 @@
-
- #include <limits.h>
- #include <math.h>
-+#include <endian.h>
-
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/s_rint.c
-===================================================================
---- uclibc/libm/powerpc/s_rint.c (revision 12879)
-+++ uclibc/libm/powerpc/s_rint.c (working copy)
-@@ -46,13 +46,14 @@
-
- #include <limits.h>
- #include <math.h>
-+#include <endian.h>
-
- #define SET_INVALID 0x01000000UL
-
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/s_floor.c
-===================================================================
---- uclibc/libm/powerpc/s_floor.c (revision 12879)
-+++ uclibc/libm/powerpc/s_floor.c (working copy)
-@@ -21,13 +21,15 @@
- * *
- *******************************************************************************/
-
-+#include <endian.h>
-+
- static const double twoTo52 = 4503599627370496.0;
- static const unsigned long signMask = 0x80000000ul;
-
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/s_logb.c
-===================================================================
---- uclibc/libm/powerpc/s_logb.c (revision 12879)
-+++ uclibc/libm/powerpc/s_logb.c (working copy)
-@@ -32,10 +32,12 @@
- * Standard 754. *
- *******************************************************************************/
-
-+#include <endian.h>
-+
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/s_frexp.c
-===================================================================
---- uclibc/libm/powerpc/s_frexp.c (revision 12879)
-+++ uclibc/libm/powerpc/s_frexp.c (working copy)
-@@ -21,13 +21,14 @@
-
- #include <limits.h>
- #include <math.h>
-+#include <endian.h>
-
- static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
-
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/s_modf.c
-===================================================================
---- uclibc/libm/powerpc/s_modf.c (revision 12879)
-+++ uclibc/libm/powerpc/s_modf.c (working copy)
-@@ -45,13 +45,14 @@
-
- #include <limits.h>
- #include <math.h>
-+#include <endian.h>
-
- #define SET_INVALID 0x01000000UL
-
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libm/powerpc/w_scalb.c
-===================================================================
---- uclibc/libm/powerpc/w_scalb.c (revision 12879)
-+++ uclibc/libm/powerpc/w_scalb.c (working copy)
-@@ -19,10 +19,12 @@
- **
- ***********************************************************************/
-
-+#include <endian.h>
-+
- typedef union
- {
- struct {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long int hi;
- unsigned long int lo;
- #else
-Index: uclibc/libc/string/sh64/strcpy.S
-===================================================================
---- uclibc/libc/string/sh64/strcpy.S (revision 12879)
-+++ uclibc/libc/string/sh64/strcpy.S (working copy)
-@@ -6,7 +6,9 @@
- !
- ! SH5 code Copyright 2002 SuperH Ltd.
-
--#ifdef __LITTLE_ENDIAN__
-+#include <endian.h>
-+
-+#if __BYTE_ORDER == __LITTLE_ENDIAN
- #define SHHI shlld
- #define SHLO shlrd
- #else
-@@ -67,7 +69,7 @@
- add r5, r63, r4
- addi r0, 8, r0
- shortstring:
--#ifndef __LITTLE_ENDIAN__
-+#if __BYTE_ORDER != __LITTLE_ENDIAN
- pta/l shortstring2,tr1
- byterev r4,r4
- #endif
-Index: uclibc/libc/string/sh64/memset.S
-===================================================================
---- uclibc/libc/string/sh64/memset.S (revision 12879)
-+++ uclibc/libc/string/sh64/memset.S (working copy)
-@@ -9,7 +9,9 @@
- ! Copyright 2002 SuperH Ltd.
- !
-
--#ifdef __LITTLE_ENDIAN__
-+#include <endian.h>
-+
-+#if __BYTE_ORDER == __LITTLE_ENDIAN
- #define SHHI shlld
- #define SHLO shlrd
- #else
-Index: uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h
-===================================================================
---- uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h (revision 12879)
-+++ uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h (working copy)
-@@ -30,10 +30,10 @@
- };
-
- struct kernel_stat64 {
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned char __pad0b[6];
- unsigned short st_dev;
--#elif defined(__LITTLE_ENDIAN__)
-+#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
- unsigned short st_dev;
- unsigned char __pad0b[6];
- #else
-@@ -48,7 +48,7 @@
- unsigned long st_uid;
- unsigned long st_gid;
-
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned char __pad3b[6];
- unsigned short st_rdev;
- #else /* Must be little */
-@@ -60,7 +60,7 @@
- long long st_size;
- unsigned long st_blksize;
-
--#if defined(__BIG_ENDIAN__)
-+#if (__BYTE_ORDER == __BIG_ENDIAN)
- unsigned long __pad4; /* Future possible st_blocks hi bits */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- #else /* Must be little */
+++ /dev/null
-diff --git a/include/printf.h b/include/printf.h
-index 340b6cb..2dea58f 100644
---- a/include/printf.h
-+++ b/include/printf.h
-@@ -75,6 +75,7 @@ struct printf_info
- unsigned int is_short:1; /* h flag. */
- unsigned int is_long:1; /* l flag. */
- unsigned int is_long_double:1;/* L flag. */
-+ unsigned int __padding:20;/* non-gnu -- total of 32 bits on 32bit arch */
-
- #elif __BYTE_ORDER == __BIG_ENDIAN
-
-diff --git a/include/pthread.h b/include/pthread.h
-index 8c01172..cee112b 100644
---- a/include/pthread.h
-+++ b/include/pthread.h
-@@ -644,7 +644,8 @@ extern void _pthread_cleanup_pop (struct
- /* Install a cleanup handler as pthread_cleanup_push does, but also
- saves the current cancellation type and set it to deferred cancellation. */
-
--#ifdef __USE_GNU
-+/* #ifdef __USE_GNU */
-+#if defined(__USE_GNU) || defined(_LIBC)
- # define pthread_cleanup_push_defer_np(routine,arg) \
- { struct _pthread_cleanup_buffer _buffer; \
- _pthread_cleanup_push_defer (&_buffer, (routine), (arg));
-diff --git a/libc/inet/getnetent.c b/libc/inet/getnetent.c
-index 181c5ad..659bf5d 100644
---- a/libc/inet/getnetent.c
-+++ b/libc/inet/getnetent.c
-@@ -22,18 +22,9 @@
- #include <netdb.h>
- #include <arpa/inet.h>
-
-+#include <bits/uClibc_mutex.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
--
--
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- #define MAXALIASES 35
- static const char NETDB[] = _PATH_NETWORKS;
-@@ -46,25 +37,25 @@ int _net_stayopen;
-
- void setnetent(int f)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (netf == NULL)
-- netf = fopen(NETDB, "r" );
-+ netf = fopen(NETDB, "r" );
- else
-- rewind(netf);
-+ rewind(netf);
- _net_stayopen |= f;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return;
- }
-
- void endnetent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (netf) {
-- fclose(netf);
-- netf = NULL;
-+ fclose(netf);
-+ netf = NULL;
- }
- _net_stayopen = 0;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- static char * any(register char *cp, char *match)
-@@ -72,10 +63,10 @@ static char * any(register char *cp, cha
- register char *mp, c;
-
- while ((c = *cp)) {
-- for (mp = match; *mp; mp++)
-- if (*mp == c)
-- return (cp);
-- cp++;
-+ for (mp = match; *mp; mp++)
-+ if (*mp == c)
-+ return (cp);
-+ cp++;
- }
- return ((char *)0);
- }
-@@ -84,59 +75,62 @@ struct netent * getnetent(void)
- {
- char *p;
- register char *cp, **q;
-+ struct netent *rv = NULL;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) {
-- UNLOCK;
-- return (NULL);
-+ goto DONE;
- }
--again:
-+ again:
-
- if (!line) {
-- line = malloc(BUFSIZ + 1);
-- if (!line)
-- abort();
-+ line = malloc(BUFSIZ + 1);
-+ if (!line)
-+ abort();
- }
-
- p = fgets(line, BUFSIZ, netf);
- if (p == NULL) {
-- UNLOCK;
-- return (NULL);
-+ goto DONE;
- }
- if (*p == '#')
-- goto again;
-+ goto again;
- cp = any(p, "#\n");
- if (cp == NULL)
-- goto again;
-+ goto again;
- *cp = '\0';
- net.n_name = p;
- cp = any(p, " \t");
- if (cp == NULL)
-- goto again;
-+ goto again;
- *cp++ = '\0';
- while (*cp == ' ' || *cp == '\t')
-- cp++;
-+ cp++;
- p = any(cp, " \t");
- if (p != NULL)
-- *p++ = '\0';
-+ *p++ = '\0';
- net.n_net = inet_network(cp);
- net.n_addrtype = AF_INET;
- q = net.n_aliases = net_aliases;
- if (p != NULL)
-- cp = p;
-+ cp = p;
- while (cp && *cp) {
-- if (*cp == ' ' || *cp == '\t') {
-- cp++;
-- continue;
-- }
-- if (q < &net_aliases[MAXALIASES - 1])
-- *q++ = cp;
-- cp = any(cp, " \t");
-- if (cp != NULL)
-- *cp++ = '\0';
-+ if (*cp == ' ' || *cp == '\t') {
-+ cp++;
-+ continue;
-+ }
-+ if (q < &net_aliases[MAXALIASES - 1])
-+ *q++ = cp;
-+ cp = any(cp, " \t");
-+ if (cp != NULL)
-+ *cp++ = '\0';
- }
- *q = NULL;
-- UNLOCK;
-- return (&net);
-+
-+ rv = &net;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-+ return rv;
- }
-
-diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c
-index c9f35f1..3665d89 100644
---- a/libc/inet/getproto.c
-+++ b/libc/inet/getproto.c
-@@ -62,17 +62,9 @@
- #include <string.h>
- #include <errno.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
--
-+#include <bits/uClibc_mutex.h>
-
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- #define MAXALIASES 35
- #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES))
-@@ -85,109 +77,114 @@ static int proto_stayopen;
- static void __initbuf(void)
- {
- if (!static_aliases) {
-- static_aliases = malloc(SBUFSIZE);
-- if (!static_aliases)
-- abort();
-+ static_aliases = malloc(SBUFSIZE);
-+ if (!static_aliases)
-+ abort();
- }
- }
-
- void setprotoent(int f)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (protof == NULL)
-- protof = fopen(_PATH_PROTOCOLS, "r" );
-+ protof = fopen(_PATH_PROTOCOLS, "r" );
- else
-- rewind(protof);
-+ rewind(protof);
- proto_stayopen |= f;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- void endprotoent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (protof) {
-- fclose(protof);
-- protof = NULL;
-+ fclose(protof);
-+ protof = NULL;
- }
- proto_stayopen = 0;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- int getprotoent_r(struct protoent *result_buf,
-- char *buf, size_t buflen,
-- struct protoent **result)
-+ char *buf, size_t buflen,
-+ struct protoent **result)
- {
- char *p;
- register char *cp, **q;
- char **proto_aliases;
- char *line;
-+ int rv;
-
- *result = NULL;
-
- if (buflen < sizeof(*proto_aliases)*MAXALIASES) {
-- errno=ERANGE;
-- return errno;
-+ errno=ERANGE;
-+ return errno;
- }
-- LOCK;
-+
-+ __UCLIBC_MUTEX_LOCK(mylock);
- proto_aliases=(char **)buf;
- buf+=sizeof(*proto_aliases)*MAXALIASES;
- buflen-=sizeof(*proto_aliases)*MAXALIASES;
-
- if (buflen < BUFSIZ+1) {
-- UNLOCK;
-- errno=ERANGE;
-- return errno;
-+ errno=rv=ERANGE;
-+ goto DONE;
- }
- line=buf;
- buf+=BUFSIZ+1;
- buflen-=BUFSIZ+1;
-
- if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) {
-- UNLOCK;
-- return errno;
-+ rv=errno;
-+ goto DONE;
- }
--again:
-+ again:
- if ((p = fgets(line, BUFSIZ, protof)) == NULL) {
-- UNLOCK;
-- return TRY_AGAIN;
-+ rv=TRY_AGAIN;
-+ goto DONE;
- }
-
- if (*p == '#')
-- goto again;
-+ goto again;
- cp = strpbrk(p, "#\n");
- if (cp == NULL)
-- goto again;
-+ goto again;
- *cp = '\0';
- result_buf->p_name = p;
- cp = strpbrk(p, " \t");
- if (cp == NULL)
-- goto again;
-+ goto again;
- *cp++ = '\0';
- while (*cp == ' ' || *cp == '\t')
-- cp++;
-+ cp++;
- p = strpbrk(cp, " \t");
- if (p != NULL)
-- *p++ = '\0';
-+ *p++ = '\0';
- result_buf->p_proto = atoi(cp);
- q = result_buf->p_aliases = proto_aliases;
- if (p != NULL) {
-- cp = p;
-- while (cp && *cp) {
-- if (*cp == ' ' || *cp == '\t') {
-- cp++;
-- continue;
-- }
-- if (q < &proto_aliases[MAXALIASES - 1])
-- *q++ = cp;
-- cp = strpbrk(cp, " \t");
-- if (cp != NULL)
-- *cp++ = '\0';
-- }
-+ cp = p;
-+ while (cp && *cp) {
-+ if (*cp == ' ' || *cp == '\t') {
-+ cp++;
-+ continue;
-+ }
-+ if (q < &proto_aliases[MAXALIASES - 1])
-+ *q++ = cp;
-+ cp = strpbrk(cp, " \t");
-+ if (cp != NULL)
-+ *cp++ = '\0';
-+ }
- }
- *q = NULL;
- *result=result_buf;
-- UNLOCK;
-- return 0;
-+
-+ rv = 0;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-+ return rv;
- }
-
- struct protoent * getprotoent(void)
-@@ -201,26 +198,26 @@ struct protoent * getprotoent(void)
-
-
- int getprotobyname_r(const char *name,
-- struct protoent *result_buf,
-- char *buf, size_t buflen,
-- struct protoent **result)
-+ struct protoent *result_buf,
-+ char *buf, size_t buflen,
-+ struct protoent **result)
- {
- register char **cp;
- int ret;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- setprotoent(proto_stayopen);
- while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) {
-- if (strcmp(result_buf->p_name, name) == 0)
-- break;
-- for (cp = result_buf->p_aliases; *cp != 0; cp++)
-- if (strcmp(*cp, name) == 0)
-- goto found;
-+ if (strcmp(result_buf->p_name, name) == 0)
-+ break;
-+ for (cp = result_buf->p_aliases; *cp != 0; cp++)
-+ if (strcmp(*cp, name) == 0)
-+ goto found;
- }
--found:
-+ found:
- if (!proto_stayopen)
-- endprotoent();
-- UNLOCK;
-+ endprotoent();
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return *result?0:ret;
- }
-
-@@ -236,20 +233,20 @@ struct protoent * getprotobyname(const c
-
-
- int getprotobynumber_r (int proto_num,
-- struct protoent *result_buf,
-- char *buf, size_t buflen,
-- struct protoent **result)
-+ struct protoent *result_buf,
-+ char *buf, size_t buflen,
-+ struct protoent **result)
- {
- int ret;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- setprotoent(proto_stayopen);
- while (!(ret=getprotoent_r(result_buf, buf, buflen, result)))
-- if (result_buf->p_proto == proto_num)
-- break;
-+ if (result_buf->p_proto == proto_num)
-+ break;
- if (!proto_stayopen)
-- endprotoent();
-- UNLOCK;
-+ endprotoent();
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return *result?0:ret;
- }
-
-diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c
-index cbe5c50..b666057 100644
---- a/libc/inet/getservice.c
-+++ b/libc/inet/getservice.c
-@@ -65,20 +65,9 @@
- #include <arpa/inet.h>
- #include <errno.h>
-
-+#include <bits/uClibc_mutex.h>
-
--
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
--
--
--
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- #define MAXALIASES 35
- #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES))
-@@ -91,32 +80,32 @@ static int serv_stayopen;
- static void __initbuf(void)
- {
- if (!servbuf) {
-- servbuf = malloc(SBUFSIZE);
-- if (!servbuf)
-- abort();
-+ servbuf = malloc(SBUFSIZE);
-+ if (!servbuf)
-+ abort();
- }
- }
-
- void setservent(int f)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (servf == NULL)
-- servf = fopen(_PATH_SERVICES, "r" );
-+ servf = fopen(_PATH_SERVICES, "r" );
- else
-- rewind(servf);
-+ rewind(servf);
- serv_stayopen |= f;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- void endservent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (servf) {
-- fclose(servf);
-- servf = NULL;
-+ fclose(servf);
-+ servf = NULL;
- }
- serv_stayopen = 0;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- struct servent * getservent(void)
-@@ -149,127 +138,129 @@ struct servent * getservbyport(int port,
- }
-
- int getservent_r(struct servent * result_buf,
-- char * buf, size_t buflen,
-- struct servent ** result)
-+ char * buf, size_t buflen,
-+ struct servent ** result)
- {
- char *p;
- register char *cp, **q;
- char **serv_aliases;
- char *line;
-+ int rv;
-
- *result=NULL;
-
- if (buflen < sizeof(*serv_aliases)*MAXALIASES) {
-- errno=ERANGE;
-- return errno;
-+ errno=ERANGE;
-+ return errno;
- }
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- serv_aliases=(char **)buf;
- buf+=sizeof(*serv_aliases)*MAXALIASES;
- buflen-=sizeof(*serv_aliases)*MAXALIASES;
-
- if (buflen < BUFSIZ+1) {
-- UNLOCK;
-- errno=ERANGE;
-- return errno;
-+ errno=rv=ERANGE;
-+ goto DONE;
- }
- line=buf;
- buf+=BUFSIZ+1;
- buflen-=BUFSIZ+1;
-
- if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) {
-- UNLOCK;
-- errno=EIO;
-- return errno;
-+ errno=rv=EIO;
-+ goto DONE;
- }
--again:
-+ again:
- if ((p = fgets(line, BUFSIZ, servf)) == NULL) {
-- UNLOCK;
-- errno=EIO;
-- return errno;
-+ errno=rv=EIO;
-+ goto DONE;
- }
- if (*p == '#')
-- goto again;
-+ goto again;
- cp = strpbrk(p, "#\n");
- if (cp == NULL)
-- goto again;
-+ goto again;
- *cp = '\0';
- result_buf->s_name = p;
- p = strpbrk(p, " \t");
- if (p == NULL)
-- goto again;
-+ goto again;
- *p++ = '\0';
- while (*p == ' ' || *p == '\t')
-- p++;
-+ p++;
- cp = strpbrk(p, ",/");
- if (cp == NULL)
-- goto again;
-+ goto again;
- *cp++ = '\0';
- result_buf->s_port = htons((u_short)atoi(p));
- result_buf->s_proto = cp;
- q = result_buf->s_aliases = serv_aliases;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
-- *cp++ = '\0';
-+ *cp++ = '\0';
- while (cp && *cp) {
-- if (*cp == ' ' || *cp == '\t') {
-- cp++;
-- continue;
-- }
-- if (q < &serv_aliases[MAXALIASES - 1])
-- *q++ = cp;
-- cp = strpbrk(cp, " \t");
-- if (cp != NULL)
-- *cp++ = '\0';
-+ if (*cp == ' ' || *cp == '\t') {
-+ cp++;
-+ continue;
-+ }
-+ if (q < &serv_aliases[MAXALIASES - 1])
-+ *q++ = cp;
-+ cp = strpbrk(cp, " \t");
-+ if (cp != NULL)
-+ *cp++ = '\0';
- }
- *q = NULL;
- *result=result_buf;
-- UNLOCK;
-- return 0;
-+
-+ rv = 0;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-+ return rv;
- }
-
- int getservbyname_r(const char *name, const char *proto,
-- struct servent * result_buf, char * buf, size_t buflen,
-- struct servent ** result)
-+ struct servent * result_buf, char * buf, size_t buflen,
-+ struct servent ** result)
- {
- register char **cp;
- int ret;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- setservent(serv_stayopen);
- while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
-- if (strcmp(name, result_buf->s_name) == 0)
-- goto gotname;
-- for (cp = result_buf->s_aliases; *cp; cp++)
-- if (strcmp(name, *cp) == 0)
-- goto gotname;
-- continue;
--gotname:
-- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
-- break;
-+ if (strcmp(name, result_buf->s_name) == 0)
-+ goto gotname;
-+ for (cp = result_buf->s_aliases; *cp; cp++)
-+ if (strcmp(name, *cp) == 0)
-+ goto gotname;
-+ continue;
-+ gotname:
-+ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
-+ break;
- }
- if (!serv_stayopen)
-- endservent();
-- UNLOCK;
-+ endservent();
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return *result?0:ret;
- }
-
- int getservbyport_r(int port, const char *proto,
-- struct servent * result_buf, char * buf,
-- size_t buflen, struct servent ** result)
-+ struct servent * result_buf, char * buf,
-+ size_t buflen, struct servent ** result)
- {
- int ret;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- setservent(serv_stayopen);
- while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
-- if (result_buf->s_port != port)
-- continue;
-- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
-- break;
-+ if (result_buf->s_port != port)
-+ continue;
-+ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
-+ break;
- }
- if (!serv_stayopen)
-- endservent();
-- UNLOCK;
-+ endservent();
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return *result?0:ret;
- }
-diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
-index 27b60ef..0f583ab 100644
---- a/libc/inet/resolv.c
-+++ b/libc/inet/resolv.c
-@@ -7,7 +7,7 @@
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
--*/
-+ */
-
- /*
- * Portions Copyright (c) 1985, 1993
-@@ -153,6 +153,11 @@
- #include <sys/utsname.h>
- #include <sys/un.h>
-
-+#include <bits/uClibc_mutex.h>
-+
-+__UCLIBC_MUTEX_EXTERN(__resolv_lock);
-+
-+
- #define MAX_RECURSE 5
- #define REPLY_TIMEOUT 10
- #define MAX_RETRIES 3
-@@ -180,18 +185,6 @@ extern char * __nameserver[MAX_SERVERS];
- extern int __searchdomains;
- extern char * __searchdomain[MAX_SEARCH];
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--extern pthread_mutex_t __resolv_lock;
--# define BIGLOCK __pthread_mutex_lock(&__resolv_lock)
--# define BIGUNLOCK __pthread_mutex_unlock(&__resolv_lock);
--#else
--# define BIGLOCK
--# define BIGUNLOCK
--#endif
--
--
--
- /* Structs */
- struct resolv_header {
- int id;
-@@ -229,49 +222,49 @@ enum etc_hosts_action {
-
- /* function prototypes */
- extern int __get_hosts_byname_r(const char * name, int type,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop);
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop);
- extern int __get_hosts_byaddr_r(const char * addr, int len, int type,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop);
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop);
- extern void __open_etc_hosts(FILE **fp);
- extern int __read_etc_hosts_r(FILE *fp, const char * name, int type,
-- enum etc_hosts_action action,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop);
-+ enum etc_hosts_action action,
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop);
- extern int __dns_lookup(const char * name, int type, int nscount,
-- char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
-+ char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);
-
- extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen);
- extern int __decode_dotted(const unsigned char * message, int offset,
-- char * dest, int maxlen);
-+ char * dest, int maxlen);
- extern int __length_dotted(const unsigned char * message, int offset);
- extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);
- extern int __decode_header(unsigned char * data, struct resolv_header * h);
- extern int __encode_question(struct resolv_question * q,
-- unsigned char * dest, int maxlen);
-+ unsigned char * dest, int maxlen);
- extern int __decode_question(unsigned char * message, int offset,
-- struct resolv_question * q);
-+ struct resolv_question * q);
- extern int __encode_answer(struct resolv_answer * a,
-- unsigned char * dest, int maxlen);
-+ unsigned char * dest, int maxlen);
- extern int __decode_answer(unsigned char * message, int offset,
-- struct resolv_answer * a);
-+ struct resolv_answer * a);
- extern int __length_question(unsigned char * message, int offset);
- extern int __open_nameservers(void);
- extern void __close_nameservers(void);
- extern int __dn_expand(const u_char *, const u_char *, const u_char *,
-- char *, int);
-+ char *, int);
- extern int __ns_name_uncompress(const u_char *, const u_char *,
-- const u_char *, char *, size_t);
-+ const u_char *, char *, size_t);
- extern int __ns_name_ntop(const u_char *, char *, size_t);
- extern int __ns_name_unpack(const u_char *, const u_char *, const u_char *,
-- u_char *, size_t);
-+ u_char *, size_t);
-
-
- #ifdef L_encodeh
-@@ -361,7 +354,7 @@ int __encode_dotted(const char *dotted,
- This routine understands compressed data. */
-
- int __decode_dotted(const unsigned char *data, int offset,
-- char *dest, int maxlen)
-+ char *dest, int maxlen)
- {
- int l;
- int measure = 1;
-@@ -435,7 +428,7 @@ int __length_dotted(const unsigned char
-
- #ifdef L_encodeq
- int __encode_question(struct resolv_question *q,
-- unsigned char *dest, int maxlen)
-+ unsigned char *dest, int maxlen)
- {
- int i;
-
-@@ -460,7 +453,7 @@ int __encode_question(struct resolv_ques
-
- #ifdef L_decodeq
- int __decode_question(unsigned char *message, int offset,
-- struct resolv_question *q)
-+ struct resolv_question *q)
- {
- char temp[256];
- int i;
-@@ -525,7 +518,7 @@ int __encode_answer(struct resolv_answer
-
- #ifdef L_decodea
- int __decode_answer(unsigned char *message, int offset,
-- struct resolv_answer *a)
-+ struct resolv_answer *a)
- {
- char temp[256];
- int i;
-@@ -557,11 +550,11 @@ int __decode_answer(unsigned char *messa
-
- #ifdef L_encodep
- int __encode_packet(struct resolv_header *h,
-- struct resolv_question **q,
-- struct resolv_answer **an,
-- struct resolv_answer **ns,
-- struct resolv_answer **ar,
-- unsigned char *dest, int maxlen)
-+ struct resolv_question **q,
-+ struct resolv_answer **an,
-+ struct resolv_answer **ns,
-+ struct resolv_answer **ar,
-+ unsigned char *dest, int maxlen)
- {
- int i, total = 0;
- int j;
-@@ -621,7 +614,7 @@ int __decode_packet(unsigned char *data,
-
- #ifdef L_formquery
- int __form_query(int id, const char *name, int type, unsigned char *packet,
-- int maxlen)
-+ int maxlen)
- {
- struct resolv_header h;
- struct resolv_question q;
-@@ -649,14 +642,7 @@ int __form_query(int id, const char *nam
-
- #ifdef L_dnslookup
-
--#ifdef __UCLIBC_HAS_THREADS__
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- /* Just for the record, having to lock __dns_lookup() just for these two globals
- * is pretty lame. I think these two variables can probably be de-global-ized,
-@@ -665,7 +651,7 @@ static pthread_mutex_t mylock = PTHREAD_
- static int ns=0, id=1;
-
- int __dns_lookup(const char *name, int type, int nscount, char **nsip,
-- unsigned char **outpacket, struct resolv_answer *a)
-+ unsigned char **outpacket, struct resolv_answer *a)
- {
- int i, j, len, fd, pos, rc;
- struct timeval tv;
-@@ -693,10 +679,10 @@ int __dns_lookup(const char *name, int t
- DPRINTF("Looking up type %d answer for '%s'\n", type, name);
-
- /* Mess with globals while under lock */
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- local_ns = ns % nscount;
- local_id = id;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- while (retries < MAX_RETRIES) {
- if (fd != -1)
-@@ -722,13 +708,13 @@ int __dns_lookup(const char *name, int t
-
- strncpy(lookup,name,MAXDNAME);
- if (variant >= 0) {
-- BIGLOCK;
-- if (variant < __searchdomains) {
-- strncat(lookup,".", MAXDNAME);
-- strncat(lookup,__searchdomain[variant], MAXDNAME);
-- }
-- BIGUNLOCK;
-- }
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
-+ if (variant < __searchdomains) {
-+ strncat(lookup,".", MAXDNAME);
-+ strncat(lookup,__searchdomain[variant], MAXDNAME);
-+ }
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-+ }
- DPRINTF("lookup name: %s\n", lookup);
- q.dotted = (char *)lookup;
- q.qtype = type;
-@@ -750,7 +736,7 @@ int __dns_lookup(const char *name, int t
- fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- #endif
- if (fd < 0) {
-- retries++;
-+ retries++;
- continue;
- }
-
-@@ -772,11 +758,11 @@ int __dns_lookup(const char *name, int t
- #endif
- if (rc < 0) {
- if (errno == ENETUNREACH) {
-- /* routing error, presume not transient */
-- goto tryall;
-+ /* routing error, presume not transient */
-+ goto tryall;
- } else
-- /* retry */
-- retries++;
-+ /* retry */
-+ retries++;
- continue;
- }
-
-@@ -838,55 +824,55 @@ int __dns_lookup(const char *name, int t
-
- first_answer = 1;
- for (j=0;j<h.ancount;j++,pos += i)
-- {
-- i = __decode_answer(packet, pos, &ma);
-+ {
-+ i = __decode_answer(packet, pos, &ma);
-
-- if (i<0) {
-- DPRINTF("failed decode %d\n", i);
-- goto again;
-- }
-+ if (i<0) {
-+ DPRINTF("failed decode %d\n", i);
-+ goto again;
-+ }
-
-- if ( first_answer )
-- {
-- ma.buf = a->buf;
-- ma.buflen = a->buflen;
-- ma.add_count = a->add_count;
-- memcpy(a, &ma, sizeof(ma));
-- if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA)))
-- {
-- break;
-- }
-- if (a->atype != type)
-- {
-- free(a->dotted);
-- continue;
-- }
-- a->add_count = h.ancount - j - 1;
-- if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen)
-- {
-- break;
-- }
-- a->add_count = 0;
-- first_answer = 0;
-- }
-- else
-- {
-- free(ma.dotted);
-- if (ma.atype != type)
-- {
-- continue;
-- }
-- if (a->rdlength != ma.rdlength)
-- {
-- free(a->dotted);
-- DPRINTF("Answer address len(%u) differs from original(%u)\n",
-- ma.rdlength, a->rdlength);
-- goto again;
-+ if ( first_answer )
-+ {
-+ ma.buf = a->buf;
-+ ma.buflen = a->buflen;
-+ ma.add_count = a->add_count;
-+ memcpy(a, &ma, sizeof(ma));
-+ if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA)))
-+ {
-+ break;
-+ }
-+ if (a->atype != type)
-+ {
-+ free(a->dotted);
-+ continue;
-+ }
-+ a->add_count = h.ancount - j - 1;
-+ if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen)
-+ {
-+ break;
-+ }
-+ a->add_count = 0;
-+ first_answer = 0;
-+ }
-+ else
-+ {
-+ free(ma.dotted);
-+ if (ma.atype != type)
-+ {
-+ continue;
-+ }
-+ if (a->rdlength != ma.rdlength)
-+ {
-+ free(a->dotted);
-+ DPRINTF("Answer address len(%u) differs from original(%u)\n",
-+ ma.rdlength, a->rdlength);
-+ goto again;
-+ }
-+ memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength);
-+ ++a->add_count;
-+ }
- }
-- memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength);
-- ++a->add_count;
-- }
-- }
-
- DPRINTF("Answer name = |%s|\n", a->dotted);
- DPRINTF("Answer type = |%d|\n", a->atype);
-@@ -900,48 +886,48 @@ int __dns_lookup(const char *name, int t
- free(lookup);
-
- /* Mess with globals while under lock */
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- ns = local_ns;
- id = local_id;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- return (len); /* success! */
-
-- tryall:
-+ tryall:
- /* if there are other nameservers, give them a go,
- otherwise return with error */
- {
- variant = -1;
-- local_ns = (local_ns + 1) % nscount;
-- if (local_ns == 0)
-- retries++;
-+ local_ns = (local_ns + 1) % nscount;
-+ if (local_ns == 0)
-+ retries++;
-
-- continue;
-+ continue;
- }
-
-- again:
-+ again:
- /* if there are searchdomains, try them or fallback as passed */
- {
- int sdomains;
-- BIGLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
- sdomains=__searchdomains;
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-
- if (variant < sdomains - 1) {
-- /* next search */
-- variant++;
-+ /* next search */
-+ variant++;
- } else {
-- /* next server, first search */
-- local_ns = (local_ns + 1) % nscount;
-- if (local_ns == 0)
-- retries++;
-+ /* next server, first search */
-+ local_ns = (local_ns + 1) % nscount;
-+ if (local_ns == 0)
-+ retries++;
-
-- variant = -1;
-+ variant = -1;
- }
- }
- }
-
--fail:
-+ fail:
- if (fd != -1)
- close(fd);
- if (lookup)
-@@ -951,10 +937,10 @@ fail:
- h_errno = NETDB_INTERNAL;
- /* Mess with globals while under lock */
- if (local_ns != -1) {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- ns = local_ns;
- id = local_id;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
- return -1;
- }
-@@ -966,9 +952,8 @@ int __nameservers;
- char * __nameserver[MAX_SERVERS];
- int __searchdomains;
- char * __searchdomain[MAX_SEARCH];
--#ifdef __UCLIBC_HAS_THREADS__
--pthread_mutex_t __resolv_lock = PTHREAD_MUTEX_INITIALIZER;
--#endif
-+
-+__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER);
-
- /*
- * we currently read formats not quite the same as that on normal
-@@ -982,60 +967,63 @@ int __open_nameservers()
- #define RESOLV_ARGS 5
- char szBuffer[128], *p, *argv[RESOLV_ARGS];
- int argc;
-+ int rv = 0;
-
-- BIGLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
- if (__nameservers > 0) {
-- BIGUNLOCK;
-- return 0;
-+ goto DONE;
- }
-
- if ((fp = fopen("/etc/resolv.conf", "r")) ||
-- (fp = fopen("/etc/config/resolv.conf", "r")))
-- {
--
-- while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
-+ (fp = fopen("/etc/config/resolv.conf", "r")))
-+ {
-
-- for (p = szBuffer; *p && isspace(*p); p++)
-- /* skip white space */;
-- if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
-- continue;
-- argc = 0;
-- while (*p && argc < RESOLV_ARGS) {
-- argv[argc++] = p;
-- while (*p && !isspace(*p) && *p != '\n')
-- p++;
-- while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
-- *p++ = '\0';
-- }
-+ while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
-
-- if (strcmp(argv[0], "nameserver") == 0) {
-- for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {
-- __nameserver[__nameservers++] = strdup(argv[i]);
-- DPRINTF("adding nameserver %s\n", argv[i]);
-+ for (p = szBuffer; *p && isspace(*p); p++)
-+ /* skip white space */;
-+ if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
-+ continue;
-+ argc = 0;
-+ while (*p && argc < RESOLV_ARGS) {
-+ argv[argc++] = p;
-+ while (*p && !isspace(*p) && *p != '\n')
-+ p++;
-+ while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
-+ *p++ = '\0';
- }
-- }
-
-- /* domain and search are mutually exclusive, the last one wins */
-- if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
-- while (__searchdomains > 0) {
-- free(__searchdomain[--__searchdomains]);
-- __searchdomain[__searchdomains] = NULL;
-+ if (strcmp(argv[0], "nameserver") == 0) {
-+ for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {
-+ __nameserver[__nameservers++] = strdup(argv[i]);
-+ DPRINTF("adding nameserver %s\n", argv[i]);
-+ }
- }
-- for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {
-- __searchdomain[__searchdomains++] = strdup(argv[i]);
-- DPRINTF("adding search %s\n", argv[i]);
-+
-+ /* domain and search are mutually exclusive, the last one wins */
-+ if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
-+ while (__searchdomains > 0) {
-+ free(__searchdomain[--__searchdomains]);
-+ __searchdomain[__searchdomains] = NULL;
-+ }
-+ for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {
-+ __searchdomain[__searchdomains++] = strdup(argv[i]);
-+ DPRINTF("adding search %s\n", argv[i]);
-+ }
- }
- }
-+ fclose(fp);
-+ DPRINTF("nameservers = %d\n", __nameservers);
-+ goto DONE;
- }
-- fclose(fp);
-- DPRINTF("nameservers = %d\n", __nameservers);
-- BIGUNLOCK;
-- return 0;
-- }
- DPRINTF("failed to open %s\n", "resolv.conf");
- h_errno = NO_RECOVERY;
-- BIGUNLOCK;
-- return -1;
-+
-+ rv = -1;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-+ return rv;
- }
- #endif
-
-@@ -1044,7 +1032,7 @@ int __open_nameservers()
-
- void __close_nameservers(void)
- {
-- BIGLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
- while (__nameservers > 0) {
- free(__nameserver[--__nameservers]);
- __nameserver[__nameservers] = NULL;
-@@ -1053,7 +1041,7 @@ void __close_nameservers(void)
- free(__searchdomain[--__searchdomains]);
- __searchdomain[__searchdomains] = NULL;
- }
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
- }
- #endif
-
-@@ -1063,8 +1051,8 @@ struct hostent *gethostbyname(const char
- {
- static struct hostent h;
- static char buf[sizeof(struct in_addr) +
-- sizeof(struct in_addr *)*2 +
-- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
-+ sizeof(struct in_addr *)*2 +
-+ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
- struct hostent *hp;
-
- gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);
-@@ -1082,8 +1070,8 @@ struct hostent *gethostbyname2(const cha
- #else /* __UCLIBC_HAS_IPV6__ */
- static struct hostent h;
- static char buf[sizeof(struct in6_addr) +
-- sizeof(struct in6_addr *)*2 +
-- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
-+ sizeof(struct in6_addr *)*2 +
-+ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
- struct hostent *hp;
-
- gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno);
-@@ -1119,7 +1107,7 @@ int res_init(void)
- /** rp->rhook = NULL; **/
- /** rp->_u._ext.nsinit = 0; **/
-
-- BIGLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
- if(__searchdomains) {
- int i;
- for(i=0; i<__searchdomains; i++) {
-@@ -1139,7 +1127,7 @@ int res_init(void)
- }
- }
- rp->nscount = __nameservers;
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-
- return(0);
- }
-@@ -1175,10 +1163,10 @@ int res_query(const char *dname, int cla
-
- memset((char *) &a, '\0', sizeof(a));
-
-- BIGLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
- __nameserversXX=__nameservers;
- __nameserverXX=__nameserver;
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
- i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a);
-
- if (i < 0) {
-@@ -1207,10 +1195,10 @@ int res_query(const char *dname, int cla
- * is detected. Error code, if any, is left in h_errno.
- */
- int res_search(name, class, type, answer, anslen)
-- const char *name; /* domain name */
-- int class, type; /* class and type of query */
-- u_char *answer; /* buffer to put answer */
-- int anslen; /* size of answer */
-+ const char *name; /* domain name */
-+ int class, type; /* class and type of query */
-+ u_char *answer; /* buffer to put answer */
-+ int anslen; /* size of answer */
- {
- const char *cp, * const *domain;
- HEADER *hp = (HEADER *)(void *)answer;
-@@ -1256,11 +1244,11 @@ int res_search(name, class, type, answer
- int done = 0;
-
- for (domain = (const char * const *)_res.dnsrch;
-- *domain && !done;
-- domain++) {
-+ *domain && !done;
-+ domain++) {
-
- ret = res_querydomain(name, *domain, class, type,
-- answer, anslen);
-+ answer, anslen);
- if (ret > 0)
- return (ret);
-
-@@ -1283,22 +1271,22 @@ int res_search(name, class, type, answer
- }
-
- switch (h_errno) {
-- case NO_DATA:
-- got_nodata++;
-- /* FALLTHROUGH */
-- case HOST_NOT_FOUND:
-- /* keep trying */
-- break;
-- case TRY_AGAIN:
-- if (hp->rcode == SERVFAIL) {
-- /* try next search element, if any */
-- got_servfail++;
-+ case NO_DATA:
-+ got_nodata++;
-+ /* FALLTHROUGH */
-+ case HOST_NOT_FOUND:
-+ /* keep trying */
- break;
-- }
-- /* FALLTHROUGH */
-- default:
-- /* anything else implies that we're done */
-- done++;
-+ case TRY_AGAIN:
-+ if (hp->rcode == SERVFAIL) {
-+ /* try next search element, if any */
-+ got_servfail++;
-+ break;
-+ }
-+ /* FALLTHROUGH */
-+ default:
-+ /* anything else implies that we're done */
-+ done++;
- }
- /*
- * if we got here for some reason other than DNSRCH,
-@@ -1342,10 +1330,10 @@ int res_search(name, class, type, answer
- * removing a trailing dot from name if domain is NULL.
- */
- int res_querydomain(name, domain, class, type, answer, anslen)
-- const char *name, *domain;
-- int class, type; /* class and type of query */
-- u_char *answer; /* buffer to put answer */
-- int anslen; /* size of answer */
-+ const char *name, *domain;
-+ int class, type; /* class and type of query */
-+ u_char *answer; /* buffer to put answer */
-+ int anslen; /* size of answer */
- {
- char nbuf[MAXDNAME];
- const char *longname = nbuf;
-@@ -1359,7 +1347,7 @@ int res_querydomain(name, domain, class,
- #ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";; res_querydomain(%s, %s, %d, %d)\n",
-- name, domain?domain:"<Nil>", class, type);
-+ name, domain?domain:"<Nil>", class, type);
- #endif
- if (domain == NULL) {
- /*
-@@ -1400,11 +1388,11 @@ struct hostent *gethostbyaddr (const voi
- static struct hostent h;
- static char buf[
- #ifndef __UCLIBC_HAS_IPV6__
-- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
-+ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
- #else
-- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
-+ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
- #endif /* __UCLIBC_HAS_IPV6__ */
-- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
-+ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */];
- struct hostent *hp;
-
- gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno);
-@@ -1425,11 +1413,11 @@ void __open_etc_hosts(FILE **fp)
- }
-
- int __read_etc_hosts_r(FILE * fp, const char * name, int type,
-- enum etc_hosts_action action,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop)
-+ enum etc_hosts_action action,
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop)
- {
- struct in_addr *in=NULL;
- struct in_addr **addr_list=NULL;
-@@ -1576,56 +1564,49 @@ int __read_etc_hosts_r(FILE * fp, const
-
- #ifdef L_gethostent
-
--#ifdef __UCLIBC_HAS_THREADS__
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- static int __stay_open;
- static FILE * __gethostent_fp;
-
- void endhostent (void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- __stay_open = 0;
- if (__gethostent_fp) {
-- fclose(__gethostent_fp);
-+ fclose(__gethostent_fp);
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- void sethostent (int stay_open)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- __stay_open = stay_open;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen,
-- struct hostent **result, int *h_errnop)
-+ struct hostent **result, int *h_errnop)
- {
-- int ret;
-+ int ret = 0;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (__gethostent_fp == NULL) {
-- __open_etc_hosts(&__gethostent_fp);
-- if (__gethostent_fp == NULL) {
-- UNLOCK;
-- *result=NULL;
-- return 0;
-- }
-+ __open_etc_hosts(&__gethostent_fp);
-+ if (__gethostent_fp == NULL) {
-+ *result=NULL;
-+ goto DONE;
-+ }
- }
-
- ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT,
-- result_buf, buf, buflen, result, h_errnop);
-+ result_buf, buf, buflen, result, h_errnop);
- if (__stay_open==0) {
-- fclose(__gethostent_fp);
-+ fclose(__gethostent_fp);
- }
-- UNLOCK;
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return(ret);
- }
-
-@@ -1634,17 +1615,17 @@ struct hostent *gethostent (void)
- static struct hostent h;
- static char buf[
- #ifndef __UCLIBC_HAS_IPV6__
-- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
-+ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
- #else
-- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
-+ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
- #endif /* __UCLIBC_HAS_IPV6__ */
-- sizeof(char *)*(ALIAS_DIM) +
-- 80/*namebuffer*/ + 2/* margin */];
-+ sizeof(char *)*(ALIAS_DIM) +
-+ 80/*namebuffer*/ + 2/* margin */];
- struct hostent *host;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- gethostent_r(&h, buf, sizeof(buf), &host, &h_errno);
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return(host);
- }
- #endif
-@@ -1652,23 +1633,23 @@ struct hostent *gethostent (void)
- #ifdef L_get_hosts_byname_r
-
- int __get_hosts_byname_r(const char * name, int type,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop)
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop)
- {
- return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME,
-- result_buf, buf, buflen, result, h_errnop));
-+ result_buf, buf, buflen, result, h_errnop));
- }
- #endif
-
- #ifdef L_get_hosts_byaddr_r
-
- int __get_hosts_byaddr_r(const char * addr, int len, int type,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop)
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop)
- {
- #ifndef __UCLIBC_HAS_IPV6__
- char ipaddr[INET_ADDRSTRLEN];
-@@ -1677,24 +1658,24 @@ int __get_hosts_byaddr_r(const char * ad
- #endif /* __UCLIBC_HAS_IPV6__ */
-
- switch (type) {
-- case AF_INET:
-- if (len != sizeof(struct in_addr))
-- return 0;
-- break;
-+ case AF_INET:
-+ if (len != sizeof(struct in_addr))
-+ return 0;
-+ break;
- #ifdef __UCLIBC_HAS_IPV6__
-- case AF_INET6:
-- if (len != sizeof(struct in6_addr))
-- return 0;
-- break;
-+ case AF_INET6:
-+ if (len != sizeof(struct in6_addr))
-+ return 0;
-+ break;
- #endif /* __UCLIBC_HAS_IPV6__ */
-- default:
-- return 0;
-+ default:
-+ return 0;
- }
-
- inet_ntop(type, addr, ipaddr, sizeof(ipaddr));
-
- return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR,
-- result_buf, buf, buflen, result, h_errnop));
-+ result_buf, buf, buflen, result, h_errnop));
- }
- #endif
-
-@@ -1705,8 +1686,8 @@ int __get_hosts_byaddr_r(const char * ad
- #endif /* min */
-
- int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
-- socklen_t hostlen, char *serv, socklen_t servlen,
-- unsigned int flags)
-+ socklen_t hostlen, char *serv, socklen_t servlen,
-+ unsigned int flags)
- {
- int serrno = errno;
- int ok = 0;
-@@ -1720,167 +1701,167 @@ int getnameinfo (const struct sockaddr *
- return EAI_FAMILY;
-
- switch (sa->sa_family) {
-- case AF_LOCAL:
-- break;
-- case AF_INET:
-- if (addrlen < sizeof (struct sockaddr_in))
-- return EAI_FAMILY;
-- break;
-+ case AF_LOCAL:
-+ break;
-+ case AF_INET:
-+ if (addrlen < sizeof (struct sockaddr_in))
-+ return EAI_FAMILY;
-+ break;
- #ifdef __UCLIBC_HAS_IPV6__
-- case AF_INET6:
-- if (addrlen < sizeof (struct sockaddr_in6))
-- return EAI_FAMILY;
-- break;
-+ case AF_INET6:
-+ if (addrlen < sizeof (struct sockaddr_in6))
-+ return EAI_FAMILY;
-+ break;
- #endif /* __UCLIBC_HAS_IPV6__ */
-- default:
-- return EAI_FAMILY;
-+ default:
-+ return EAI_FAMILY;
- }
-
- if (host != NULL && hostlen > 0)
- switch (sa->sa_family) {
-- case AF_INET:
-+ case AF_INET:
- #ifdef __UCLIBC_HAS_IPV6__
-- case AF_INET6:
-+ case AF_INET6:
- #endif /* __UCLIBC_HAS_IPV6__ */
-- if (!(flags & NI_NUMERICHOST)) {
-+ if (!(flags & NI_NUMERICHOST)) {
- #ifdef __UCLIBC_HAS_IPV6__
-- if (sa->sa_family == AF_INET6)
-- h = gethostbyaddr ((const void *)
-- &(((const struct sockaddr_in6 *) sa)->sin6_addr),
-- sizeof(struct in6_addr), AF_INET6);
-- else
--#endif /* __UCLIBC_HAS_IPV6__ */
-- h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
-- sizeof(struct in_addr), AF_INET);
--
-- if (h) {
-- char *c;
-- if ((flags & NI_NOFQDN)
-- && (getdomainname (domain, sizeof(domain)) == 0)
-- && (c = strstr (h->h_name, domain))
-- && (c != h->h_name) && (*(--c) == '.')) {
-- strncpy (host, h->h_name,
-- min(hostlen, (size_t) (c - h->h_name)));
-- host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
-- ok = 1;
-- } else {
-- strncpy (host, h->h_name, hostlen);
-- ok = 1;
-+ if (sa->sa_family == AF_INET6)
-+ h = gethostbyaddr ((const void *)
-+ &(((const struct sockaddr_in6 *) sa)->sin6_addr),
-+ sizeof(struct in6_addr), AF_INET6);
-+ else
-+#endif /* __UCLIBC_HAS_IPV6__ */
-+ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
-+ sizeof(struct in_addr), AF_INET);
-+
-+ if (h) {
-+ char *c;
-+ if ((flags & NI_NOFQDN)
-+ && (getdomainname (domain, sizeof(domain)) == 0)
-+ && (c = strstr (h->h_name, domain))
-+ && (c != h->h_name) && (*(--c) == '.')) {
-+ strncpy (host, h->h_name,
-+ min(hostlen, (size_t) (c - h->h_name)));
-+ host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0';
-+ ok = 1;
-+ } else {
-+ strncpy (host, h->h_name, hostlen);
-+ ok = 1;
-+ }
- }
-- }
-- }
-+ }
-
-- if (!ok) {
-- if (flags & NI_NAMEREQD) {
-- errno = serrno;
-- return EAI_NONAME;
-- } else {
-- const char *c;
-+ if (!ok) {
-+ if (flags & NI_NAMEREQD) {
-+ errno = serrno;
-+ return EAI_NONAME;
-+ } else {
-+ const char *c;
- #ifdef __UCLIBC_HAS_IPV6__
-- if (sa->sa_family == AF_INET6) {
-- const struct sockaddr_in6 *sin6p;
-+ if (sa->sa_family == AF_INET6) {
-+ const struct sockaddr_in6 *sin6p;
-
-- sin6p = (const struct sockaddr_in6 *) sa;
-+ sin6p = (const struct sockaddr_in6 *) sa;
-
-- c = inet_ntop (AF_INET6,
-- (const void *) &sin6p->sin6_addr, host, hostlen);
-+ c = inet_ntop (AF_INET6,
-+ (const void *) &sin6p->sin6_addr, host, hostlen);
- #if 0
-- /* Does scope id need to be supported? */
-- uint32_t scopeid;
-- scopeid = sin6p->sin6_scope_id;
-- if (scopeid != 0) {
-- /* Buffer is >= IFNAMSIZ+1. */
-- char scopebuf[IFNAMSIZ + 1];
-- char *scopeptr;
-- int ni_numericscope = 0;
-- size_t real_hostlen = __strnlen (host, hostlen);
-- size_t scopelen = 0;
--
-- scopebuf[0] = SCOPE_DELIMITER;
-- scopebuf[1] = '\0';
-- scopeptr = &scopebuf[1];
--
-- if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
-- || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
-- if (if_indextoname (scopeid, scopeptr) == NULL)
-+ /* Does scope id need to be supported? */
-+ uint32_t scopeid;
-+ scopeid = sin6p->sin6_scope_id;
-+ if (scopeid != 0) {
-+ /* Buffer is >= IFNAMSIZ+1. */
-+ char scopebuf[IFNAMSIZ + 1];
-+ char *scopeptr;
-+ int ni_numericscope = 0;
-+ size_t real_hostlen = __strnlen (host, hostlen);
-+ size_t scopelen = 0;
-+
-+ scopebuf[0] = SCOPE_DELIMITER;
-+ scopebuf[1] = '\0';
-+ scopeptr = &scopebuf[1];
-+
-+ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
-+ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) {
-+ if (if_indextoname (scopeid, scopeptr) == NULL)
-+ ++ni_numericscope;
-+ else
-+ scopelen = strlen (scopebuf);
-+ } else {
- ++ni_numericscope;
-- else
-- scopelen = strlen (scopebuf);
-- } else {
-- ++ni_numericscope;
-- }
-+ }
-
-- if (ni_numericscope)
-- scopelen = 1 + snprintf (scopeptr,
-- (scopebuf
-- + sizeof scopebuf
-- - scopeptr),
-- "%u", scopeid);
--
-- if (real_hostlen + scopelen + 1 > hostlen)
-- return EAI_SYSTEM;
-- memcpy (host + real_hostlen, scopebuf, scopelen + 1);
-- }
-+ if (ni_numericscope)
-+ scopelen = 1 + snprintf (scopeptr,
-+ (scopebuf
-+ + sizeof scopebuf
-+ - scopeptr),
-+ "%u", scopeid);
-+
-+ if (real_hostlen + scopelen + 1 > hostlen)
-+ return EAI_SYSTEM;
-+ memcpy (host + real_hostlen, scopebuf, scopelen + 1);
-+ }
- #endif
-- } else
-+ } else
- #endif /* __UCLIBC_HAS_IPV6__ */
-- c = inet_ntop (AF_INET, (const void *)
-- &(((const struct sockaddr_in *) sa)->sin_addr),
-- host, hostlen);
--
-- if (c == NULL) {
-- errno = serrno;
-- return EAI_SYSTEM;
-+ c = inet_ntop (AF_INET, (const void *)
-+ &(((const struct sockaddr_in *) sa)->sin_addr),
-+ host, hostlen);
-+
-+ if (c == NULL) {
-+ errno = serrno;
-+ return EAI_SYSTEM;
-+ }
- }
-+ ok = 1;
- }
-- ok = 1;
-- }
-- break;
--
-- case AF_LOCAL:
-- if (!(flags & NI_NUMERICHOST)) {
-- struct utsname utsname;
-+ break;
-
-- if (!uname (&utsname)) {
-- strncpy (host, utsname.nodename, hostlen);
-- break;
-+ case AF_LOCAL:
-+ if (!(flags & NI_NUMERICHOST)) {
-+ struct utsname utsname;
-+
-+ if (!uname (&utsname)) {
-+ strncpy (host, utsname.nodename, hostlen);
-+ break;
-+ };
- };
-- };
-
-- if (flags & NI_NAMEREQD) {
-- errno = serrno;
-- return EAI_NONAME;
-- }
-+ if (flags & NI_NAMEREQD) {
-+ errno = serrno;
-+ return EAI_NONAME;
-+ }
-
-- strncpy (host, "localhost", hostlen);
-- break;
-+ strncpy (host, "localhost", hostlen);
-+ break;
-
-- default:
-- return EAI_FAMILY;
-- }
-+ default:
-+ return EAI_FAMILY;
-+ }
-
- if (serv && (servlen > 0)) {
- switch (sa->sa_family) {
-- case AF_INET:
-+ case AF_INET:
- #ifdef __UCLIBC_HAS_IPV6__
-- case AF_INET6:
-+ case AF_INET6:
- #endif /* __UCLIBC_HAS_IPV6__ */
-- if (!(flags & NI_NUMERICSERV)) {
-- struct servent *s;
-- s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
-- ((flags & NI_DGRAM) ? "udp" : "tcp"));
-- if (s) {
-- strncpy (serv, s->s_name, servlen);
-- break;
-+ if (!(flags & NI_NUMERICSERV)) {
-+ struct servent *s;
-+ s = getservbyport (((const struct sockaddr_in *) sa)->sin_port,
-+ ((flags & NI_DGRAM) ? "udp" : "tcp"));
-+ if (s) {
-+ strncpy (serv, s->s_name, servlen);
-+ break;
-+ }
- }
-- }
-- snprintf (serv, servlen, "%d",
-- ntohs (((const struct sockaddr_in *) sa)->sin_port));
-- break;
-+ snprintf (serv, servlen, "%d",
-+ ntohs (((const struct sockaddr_in *) sa)->sin_port));
-+ break;
-
-- case AF_LOCAL:
-- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
-- break;
-+ case AF_LOCAL:
-+ strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
-+ break;
- }
- }
- if (host && (hostlen > 0))
-@@ -1896,10 +1877,10 @@ int getnameinfo (const struct sockaddr *
- #ifdef L_gethostbyname_r
-
- int gethostbyname_r(const char * name,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop)
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop)
- {
- struct in_addr *in;
- struct in_addr **addr_list;
-@@ -1921,7 +1902,7 @@ int gethostbyname_r(const char * name,
- __set_errno(0); /* to check for missing /etc/hosts. */
-
- if ((i=__get_hosts_byname_r(name, AF_INET, result_buf,
-- buf, buflen, result, h_errnop))==0)
-+ buf, buflen, result, h_errnop))==0)
- return i;
- switch (*h_errnop) {
- case HOST_NOT_FOUND:
-@@ -1983,60 +1964,60 @@ int gethostbyname_r(const char * name,
-
- for (;;) {
-
-- BIGLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
- __nameserversXX=__nameservers;
- __nameserverXX=__nameserver;
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
- a.buf = buf;
- a.buflen = buflen;
- a.add_count = 0;
- i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a);
-
- if (i < 0) {
-- *h_errnop = HOST_NOT_FOUND;
-- DPRINTF("__dns_lookup\n");
-- return TRY_AGAIN;
-+ *h_errnop = HOST_NOT_FOUND;
-+ DPRINTF("__dns_lookup\n");
-+ return TRY_AGAIN;
- }
-
- if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen)
-- {
-- free(a.dotted);
-- free(packet);
-- *h_errnop = NETDB_INTERNAL;
-- DPRINTF("buffer too small for all addresses\n");
-- return ERANGE;
-- }
-+ {
-+ free(a.dotted);
-+ free(packet);
-+ *h_errnop = NETDB_INTERNAL;
-+ DPRINTF("buffer too small for all addresses\n");
-+ return ERANGE;
-+ }
- else if(a.add_count > 0)
-- {
-- memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength);
-- addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength);
-- addr_list[0] = in;
-- for (i = a.add_count-1; i>=0; --i)
-- addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i);
-- addr_list[a.add_count + 1] = 0;
-- buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf);
-- buf = (char*)&addr_list[a.add_count + 2];
-- }
-+ {
-+ memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength);
-+ addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength);
-+ addr_list[0] = in;
-+ for (i = a.add_count-1; i>=0; --i)
-+ addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i);
-+ addr_list[a.add_count + 1] = 0;
-+ buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf);
-+ buf = (char*)&addr_list[a.add_count + 2];
-+ }
-
- strncpy(buf, a.dotted, buflen);
- free(a.dotted);
-
- if (a.atype == T_A) { /* ADDRESS */
-- memcpy(in, a.rdata, sizeof(*in));
-- result_buf->h_name = buf;
-- result_buf->h_addrtype = AF_INET;
-- result_buf->h_length = sizeof(*in);
-- result_buf->h_addr_list = (char **) addr_list;
-+ memcpy(in, a.rdata, sizeof(*in));
-+ result_buf->h_name = buf;
-+ result_buf->h_addrtype = AF_INET;
-+ result_buf->h_length = sizeof(*in);
-+ result_buf->h_addr_list = (char **) addr_list;
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning TODO -- generate the full list
- #endif
-- result_buf->h_aliases = alias; /* TODO: generate the full list */
-- free(packet);
-- break;
-+ result_buf->h_aliases = alias; /* TODO: generate the full list */
-+ free(packet);
-+ break;
- } else {
-- free(packet);
-- *h_errnop=HOST_NOT_FOUND;
-- return TRY_AGAIN;
-+ free(packet);
-+ *h_errnop=HOST_NOT_FOUND;
-+ return TRY_AGAIN;
- }
- }
-
-@@ -2049,14 +2030,14 @@ int gethostbyname_r(const char * name,
- #ifdef L_gethostbyname2_r
-
- int gethostbyname2_r(const char *name, int family,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop)
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop)
- {
- #ifndef __UCLIBC_HAS_IPV6__
- return family == (AF_INET)? gethostbyname_r(name, result_buf,
-- buf, buflen, result, h_errnop) : HOST_NOT_FOUND;
-+ buf, buflen, result, h_errnop) : HOST_NOT_FOUND;
- #else /* __UCLIBC_HAS_IPV6__ */
- struct in6_addr *in;
- struct in6_addr **addr_list;
-@@ -2084,7 +2065,7 @@ int gethostbyname2_r(const char *name, i
- __set_errno(0); /* to check for missing /etc/hosts. */
-
- if ((i=__get_hosts_byname_r(name, AF_INET, result_buf,
-- buf, buflen, result, h_errnop))==0)
-+ buf, buflen, result, h_errnop))==0)
- return i;
- switch (*h_errnop) {
- case HOST_NOT_FOUND:
-@@ -2137,10 +2118,10 @@ int gethostbyname2_r(const char *name, i
- memset((char *) &a, '\0', sizeof(a));
-
- for (;;) {
-- BIGLOCK;
-- __nameserversXX=__nameservers;
-- __nameserverXX=__nameserver;
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
-+ __nameserversXX=__nameservers;
-+ __nameserverXX=__nameserver;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
-
- i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a);
-
-@@ -2190,10 +2171,10 @@ int gethostbyname2_r(const char *name, i
-
- #ifdef L_gethostbyaddr_r
- int gethostbyaddr_r (const void *addr, socklen_t len, int type,
-- struct hostent * result_buf,
-- char * buf, size_t buflen,
-- struct hostent ** result,
-- int * h_errnop)
-+ struct hostent * result_buf,
-+ char * buf, size_t buflen,
-+ struct hostent ** result,
-+ int * h_errnop)
-
- {
- struct in_addr *in;
-@@ -2234,7 +2215,7 @@ int gethostbyaddr_r (const void *addr, s
-
- /* do /etc/hosts first */
- if ((i=__get_hosts_byaddr_r(addr, len, type, result_buf,
-- buf, buflen, result, h_errnop))==0)
-+ buf, buflen, result, h_errnop))==0)
- return i;
- switch (*h_errnop) {
- case HOST_NOT_FOUND:
-@@ -2294,7 +2275,7 @@ int gethostbyaddr_r (const void *addr, s
- addr_list[0] = in;
-
- sprintf(buf, "%u.%u.%u.%u.in-addr.arpa",
-- tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
-+ tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
- #ifdef __UCLIBC_HAS_IPV6__
- } else {
- memcpy(in6->s6_addr, addr, len);
-@@ -2304,7 +2285,7 @@ int gethostbyaddr_r (const void *addr, s
-
- for (i = len - 1; i >= 0; i--) {
- qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf,
-- (in6->s6_addr[i] >> 4) & 0xf);
-+ (in6->s6_addr[i] >> 4) & 0xf);
- }
- strcpy(qp, "ip6.int");
- #endif /* __UCLIBC_HAS_IPV6__ */
-@@ -2314,10 +2295,10 @@ int gethostbyaddr_r (const void *addr, s
-
- for (;;) {
-
-- BIGLOCK;
-- __nameserversXX=__nameservers;
-- __nameserverXX=__nameserver;
-- BIGUNLOCK;
-+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
-+ __nameserversXX=__nameservers;
-+ __nameserverXX=__nameserver;
-+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
- i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a);
-
- if (i < 0) {
-@@ -2381,7 +2362,7 @@ int gethostbyaddr_r (const void *addr, s
- * Return size of compressed name or -1 if there was an error.
- */
- int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
-- char *dst, int dstsiz)
-+ char *dst, int dstsiz)
- {
- int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
-
-@@ -2401,7 +2382,7 @@ int __dn_expand(const u_char *msg, const
- */
- static int printable(int ch)
- {
-- return (ch > 0x20 && ch < 0x7f);
-+ return (ch > 0x20 && ch < 0x7f);
- }
-
- /*
-@@ -2413,18 +2394,18 @@ static int printable(int ch)
- */
- static int special(int ch)
- {
-- switch (ch) {
-+ switch (ch) {
- case 0x22: /* '"' */
- case 0x2E: /* '.' */
- case 0x3B: /* ';' */
- case 0x5C: /* '\\' */
-- /* Special modifiers in zone files. */
-+ /* Special modifiers in zone files. */
- case 0x40: /* '@' */
- case 0x24: /* '$' */
-- return (1);
-+ return (1);
- default:
-- return (0);
-- }
-+ return (0);
-+ }
- }
-
- /*
-@@ -2436,7 +2417,7 @@ static int special(int ch)
- * Root domain returns as "." not "".
- */
- int __ns_name_uncompress(const u_char *msg, const u_char *eom,
-- const u_char *src, char *dst, size_t dstsiz)
-+ const u_char *src, char *dst, size_t dstsiz)
- {
- u_char tmp[NS_MAXCDNAME];
- int n;
-@@ -2525,7 +2506,7 @@ int __ns_name_ntop(const u_char *src, ch
- return (-1);
- }
- *dn++ = '\0';
-- return (dn - dst);
-+ return (dn - dst);
- }
-
- /*
-@@ -2535,7 +2516,7 @@ int __ns_name_ntop(const u_char *src, ch
- * -1 if it fails, or consumed octets if it succeeds.
- */
- int __ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
-- u_char *dst, size_t dstsiz)
-+ u_char *dst, size_t dstsiz)
- {
- const u_char *srcp, *dstlim;
- u_char *dstp;
-@@ -2554,46 +2535,46 @@ int __ns_name_unpack(const u_char *msg,
- while ((n = *srcp++) != 0) {
- /* Check for indirection. */
- switch (n & NS_CMPRSFLGS) {
-- case 0:
-- /* Limit checks. */
-- if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
-- __set_errno (EMSGSIZE);
-- return (-1);
-- }
-- checked += n + 1;
-- *dstp++ = n;
-- memcpy(dstp, srcp, n);
-- dstp += n;
-- srcp += n;
-- break;
-+ case 0:
-+ /* Limit checks. */
-+ if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
-+ __set_errno (EMSGSIZE);
-+ return (-1);
-+ }
-+ checked += n + 1;
-+ *dstp++ = n;
-+ memcpy(dstp, srcp, n);
-+ dstp += n;
-+ srcp += n;
-+ break;
-
-- case NS_CMPRSFLGS:
-- if (srcp >= eom) {
-- __set_errno (EMSGSIZE);
-- return (-1);
-- }
-- if (len < 0)
-- len = srcp - src + 1;
-- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
-- if (srcp < msg || srcp >= eom) { /* Out of range. */
-- __set_errno (EMSGSIZE);
-- return (-1);
-- }
-- checked += 2;
-- /*
-- * Check for loops in the compressed name;
-- * if we've looked at the whole message,
-- * there must be a loop.
-- */
-- if (checked >= eom - msg) {
-- __set_errno (EMSGSIZE);
-- return (-1);
-- }
-- break;
-+ case NS_CMPRSFLGS:
-+ if (srcp >= eom) {
-+ __set_errno (EMSGSIZE);
-+ return (-1);
-+ }
-+ if (len < 0)
-+ len = srcp - src + 1;
-+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
-+ if (srcp < msg || srcp >= eom) { /* Out of range. */
-+ __set_errno (EMSGSIZE);
-+ return (-1);
-+ }
-+ checked += 2;
-+ /*
-+ * Check for loops in the compressed name;
-+ * if we've looked at the whole message,
-+ * there must be a loop.
-+ */
-+ if (checked >= eom - msg) {
-+ __set_errno (EMSGSIZE);
-+ return (-1);
-+ }
-+ break;
-
-- default:
-- __set_errno (EMSGSIZE);
-- return (-1); /* flag error */
-+ default:
-+ __set_errno (EMSGSIZE);
-+ return (-1); /* flag error */
- }
- }
- *dstp = '\0';
-diff --git a/libc/inet/rpc/create_xid.c b/libc/inet/rpc/create_xid.c
-index cbb961e..c86cbb4 100644
---- a/libc/inet/rpc/create_xid.c
-+++ b/libc/inet/rpc/create_xid.c
-@@ -27,15 +27,7 @@
-
- /* The RPC code is not threadsafe, but new code should be threadsafe. */
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t createxid_lock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&createxid_lock)
--# define UNLOCK __pthread_mutex_unlock(&createxid_lock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- static int is_initialized;
- static struct drand48_data __rpc_lrand48_data;
-@@ -43,22 +35,22 @@ static struct drand48_data __rpc_lrand48
- unsigned long
- _create_xid (void)
- {
-- unsigned long res;
-+ unsigned long res;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
-- if (!is_initialized)
-- {
-- struct timeval now;
-+ if (!is_initialized)
-+ {
-+ struct timeval now;
-
-- gettimeofday (&now, (struct timezone *) 0);
-- srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
-- is_initialized = 1;
-- }
-+ gettimeofday (&now, (struct timezone *) 0);
-+ srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data);
-+ is_initialized = 1;
-+ }
-
-- lrand48_r (&__rpc_lrand48_data, &res);
-+ lrand48_r (&__rpc_lrand48_data, &res);
-
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
-- return res;
-+ return res;
- }
-diff --git a/libc/misc/dirent/closedir.c b/libc/misc/dirent/closedir.c
-index 068e2d3..56adb23 100644
---- a/libc/misc/dirent/closedir.c
-+++ b/libc/misc/dirent/closedir.c
-@@ -4,7 +4,6 @@
- #include <unistd.h>
- #include "dirstream.h"
-
--
- int closedir(DIR * dir)
- {
- int fd;
-@@ -19,14 +18,10 @@ int closedir(DIR * dir)
- __set_errno(EBADF);
- return -1;
- }
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
- fd = dir->dd_fd;
- dir->dd_fd = -1;
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
- free(dir->dd_buf);
- free(dir);
- return close(fd);
-diff --git a/libc/misc/dirent/dirstream.h b/libc/misc/dirent/dirstream.h
-index 2dd0264..bd721c5 100644
---- a/libc/misc/dirent/dirstream.h
-+++ b/libc/misc/dirent/dirstream.h
-@@ -26,9 +26,8 @@ Cambridge, MA 02139, USA. */
-
- #include <features.h>
- #include <sys/types.h>
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--#endif
-+
-+#include <bits/uClibc_mutex.h>
-
- /* For now, syscall readdir () only supports one entry at a time. It
- * will be changed in the future.
-@@ -63,11 +62,7 @@ struct __dirstream {
- size_t dd_max;
-
- /* lock */
--#ifdef __UCLIBC_HAS_THREADS__
-- pthread_mutex_t dd_lock;
--#else
-- void *dd_lock;
--#endif
-+ __UCLIBC_MUTEX(dd_lock);
- }; /* stream data from opendir() */
-
-
-diff --git a/libc/misc/dirent/readdir.c b/libc/misc/dirent/readdir.c
-index 1f196e1..c55317a 100644
---- a/libc/misc/dirent/readdir.c
-+++ b/libc/misc/dirent/readdir.c
-@@ -5,7 +5,6 @@
- #include <dirent.h>
- #include "dirstream.h"
-
--
- struct dirent *readdir(DIR * dir)
- {
- ssize_t bytes;
-@@ -16,9 +15,7 @@ struct dirent *readdir(DIR * dir)
- return NULL;
- }
-
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
-
- do {
- if (dir->dd_size <= dir->dd_nextloc) {
-@@ -44,8 +41,6 @@ struct dirent *readdir(DIR * dir)
- } while (de->d_ino == 0);
-
- all_done:
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
- return de;
- }
-diff --git a/libc/misc/dirent/readdir64.c b/libc/misc/dirent/readdir64.c
-index f798c6f..6da3b0d 100644
---- a/libc/misc/dirent/readdir64.c
-+++ b/libc/misc/dirent/readdir64.c
-@@ -20,7 +20,6 @@
- #include <dirent.h>
- #include "dirstream.h"
-
--
- struct dirent64 *readdir64(DIR * dir)
- {
- ssize_t bytes;
-@@ -31,9 +30,7 @@ struct dirent64 *readdir64(DIR * dir)
- return NULL;
- }
-
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
-
- do {
- if (dir->dd_size <= dir->dd_nextloc) {
-@@ -59,9 +56,7 @@ struct dirent64 *readdir64(DIR * dir)
- } while (de->d_ino == 0);
-
- all_done:
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
-
- return de;
- }
-diff --git a/libc/misc/dirent/readdir64_r.c b/libc/misc/dirent/readdir64_r.c
-index da3564e..cc96eff 100644
---- a/libc/misc/dirent/readdir64_r.c
-+++ b/libc/misc/dirent/readdir64_r.c
-@@ -19,7 +19,6 @@
- #include <dirent.h>
- #include "dirstream.h"
-
--
- int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result)
- {
- int ret;
-@@ -32,21 +31,19 @@ int readdir64_r(DIR *dir, struct dirent6
- }
- de = NULL;
-
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
-
- do {
- if (dir->dd_size <= dir->dd_nextloc) {
-- /* read dir->dd_max bytes of directory entries. */
-- bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
-- if (bytes <= 0) {
-- *result = NULL;
-- ret = errno;
-- goto all_done;
-- }
-- dir->dd_size = bytes;
-- dir->dd_nextloc = 0;
-+ /* read dir->dd_max bytes of directory entries. */
-+ bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
-+ if (bytes <= 0) {
-+ *result = NULL;
-+ ret = errno;
-+ goto all_done;
-+ }
-+ dir->dd_size = bytes;
-+ dir->dd_nextloc = 0;
- }
-
- de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc);
-@@ -66,12 +63,10 @@ int readdir64_r(DIR *dir, struct dirent6
- }
- ret = 0;
-
--all_done:
-+ all_done:
-
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-- return((de != NULL)? 0 : ret);
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
-+ return((de != NULL)? 0 : ret);
- }
- #endif /* __UCLIBC_HAS_LFS__ */
-
-diff --git a/libc/misc/dirent/readdir_r.c b/libc/misc/dirent/readdir_r.c
-index 245dcbd..aeccdd8 100644
---- a/libc/misc/dirent/readdir_r.c
-+++ b/libc/misc/dirent/readdir_r.c
-@@ -5,7 +5,6 @@
- #include <dirent.h>
- #include "dirstream.h"
-
--
- int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
- {
- int ret;
-@@ -18,21 +17,19 @@ int readdir_r(DIR *dir, struct dirent *e
- }
- de = NULL;
-
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
-
- do {
- if (dir->dd_size <= dir->dd_nextloc) {
-- /* read dir->dd_max bytes of directory entries. */
-- bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
-- if (bytes <= 0) {
-- *result = NULL;
-- ret = errno;
-- goto all_done;
-- }
-- dir->dd_size = bytes;
-- dir->dd_nextloc = 0;
-+ /* read dir->dd_max bytes of directory entries. */
-+ bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
-+ if (bytes <= 0) {
-+ *result = NULL;
-+ ret = errno;
-+ goto all_done;
-+ }
-+ dir->dd_size = bytes;
-+ dir->dd_nextloc = 0;
- }
-
- de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
-@@ -52,10 +49,8 @@ int readdir_r(DIR *dir, struct dirent *e
- }
- ret = 0;
-
--all_done:
-+ all_done:
-
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-- return((de != NULL)? 0 : ret);
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
-+ return((de != NULL)? 0 : ret);
- }
-diff --git a/libc/misc/dirent/rewinddir.c b/libc/misc/dirent/rewinddir.c
-index 60ef71d..fe8fc2a 100644
---- a/libc/misc/dirent/rewinddir.c
-+++ b/libc/misc/dirent/rewinddir.c
-@@ -3,7 +3,6 @@
- #include <unistd.h>
- #include "dirstream.h"
-
--
- /* rewinddir() just does an lseek(fd,0,0) - see close for comments */
- void rewinddir(DIR * dir)
- {
-@@ -11,12 +10,8 @@ void rewinddir(DIR * dir)
- __set_errno(EBADF);
- return;
- }
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
- lseek(dir->dd_fd, 0, SEEK_SET);
- dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0;
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
- }
-diff --git a/libc/misc/dirent/seekdir.c b/libc/misc/dirent/seekdir.c
-index 139f1e1..6d6f5f0 100644
---- a/libc/misc/dirent/seekdir.c
-+++ b/libc/misc/dirent/seekdir.c
-@@ -3,19 +3,14 @@
- #include <unistd.h>
- #include "dirstream.h"
-
--
- void seekdir(DIR * dir, long int offset)
- {
- if (!dir) {
- __set_errno(EBADF);
- return;
- }
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_lock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_LOCK(dir->dd_lock);
- dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET);
- dir->dd_size = dir->dd_nextloc = 0;
--#ifdef __UCLIBC_HAS_THREADS__
-- __pthread_mutex_unlock(&(dir->dd_lock));
--#endif
-+ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
- }
-diff --git a/libc/misc/mntent/mntent.c b/libc/misc/mntent/mntent.c
-index d98a687..af6d848 100644
---- a/libc/misc/mntent/mntent.c
-+++ b/libc/misc/mntent/mntent.c
-@@ -3,15 +3,9 @@
- #include <string.h>
- #include <mntent.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+#include <bits/uClibc_mutex.h>
-+
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- /* Reentrant version of getmntent. */
- struct mntent *getmntent_r (FILE *filep,
-@@ -67,7 +61,7 @@ struct mntent *getmntent(FILE * filep)
- struct mntent *tmp;
- static char *buff = NULL;
- static struct mntent mnt;
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- if (!buff) {
- buff = malloc(BUFSIZ);
-@@ -76,7 +70,7 @@ struct mntent *getmntent(FILE * filep)
- }
-
- tmp = getmntent_r(filep, &mnt, buff, BUFSIZ);
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return(tmp);
- }
-
-diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c
-index 89c2611..c27bd10 100644
---- a/libc/misc/pthread/weaks.c
-+++ b/libc/misc/pthread/weaks.c
-@@ -21,6 +21,7 @@
- #include <limits.h>
- #include <stdlib.h>
-
-+static void __pthread_return_void __P ((void));
- static int __pthread_return_0 __P ((void));
- static int __pthread_return_1 __P ((void));
-
-@@ -104,8 +105,17 @@ weak_alias (__pthread_return_0, __pthrea
- weak_alias (__pthread_return_0, __pthread_mutex_trylock)
- weak_alias (__pthread_return_0, __pthread_mutex_unlock)
-
-+weak_alias (__pthread_return_void, _pthread_cleanup_push_defer)
-+weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore)
-+
- /**********************************************************************/
-
-+static void
-+__pthread_return_void (void)
-+{
-+ return;
-+}
-+
- static int
- __pthread_return_0 (void)
- {
-diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c
-index 2b478e1..9e9ddbf 100644
---- a/libc/misc/syslog/syslog.c
-+++ b/libc/misc/syslog/syslog.c
-@@ -80,17 +80,9 @@
- #include <ctype.h>
- #include <signal.h>
-
-+#include <bits/uClibc_mutex.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
--
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- static int LogFile = -1; /* fd for log */
- static int connected; /* have done connect */
-@@ -110,26 +102,26 @@ int setlogmask(int pmask);
- static void
- closelog_intern(int to_default)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (LogFile != -1) {
- (void) close(LogFile);
- }
- LogFile = -1;
- connected = 0;
- if (to_default)
-- {
-- LogStat = 0;
-- LogTag = "syslog";
-- LogFacility = LOG_USER;
-- LogMask = 0xff;
-- }
-- UNLOCK;
-+ {
-+ LogStat = 0;
-+ LogTag = "syslog";
-+ LogFacility = LOG_USER;
-+ LogMask = 0xff;
-+ }
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- static void
- sigpipe_handler (int sig)
- {
-- closelog_intern (0);
-+ closelog_intern (0);
- }
-
- /*
-@@ -165,7 +157,7 @@ vsyslog( int pri, const char *fmt, va_li
-
- saved_errno = errno;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- /* See if we should just throw out this message. */
- if (!(LogMask & LOG_MASK(LOG_PRI(pri))) || (pri &~ (LOG_PRIMASK|LOG_FACMASK)))
-@@ -208,7 +200,7 @@ vsyslog( int pri, const char *fmt, va_li
- if (p >= end || p < head_end) { /* Returned -1 in case of error... */
- static const char truncate_msg[12] = "[truncated] ";
- memmove(head_end + sizeof(truncate_msg), head_end,
-- end - head_end - sizeof(truncate_msg));
-+ end - head_end - sizeof(truncate_msg));
- memcpy(head_end, truncate_msg, sizeof(truncate_msg));
- if (p < head_end) {
- while (p < end && *p) {
-@@ -261,11 +253,11 @@ vsyslog( int pri, const char *fmt, va_li
- (void)close(fd);
- }
-
--getout:
-- UNLOCK;
-+ getout:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- if (sigpipe == 0)
- sigaction (SIGPIPE, &oldaction,
-- (struct sigaction *) NULL);
-+ (struct sigaction *) NULL);
- }
-
- /*
-@@ -276,48 +268,48 @@ openlog( const char *ident, int logstat,
- {
- int logType = SOCK_DGRAM;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- if (ident != NULL)
-- LogTag = ident;
-+ LogTag = ident;
- LogStat = logstat;
- if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
-- LogFacility = logfac;
-+ LogFacility = logfac;
- if (LogFile == -1) {
-- SyslogAddr.sa_family = AF_UNIX;
-- (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
-- sizeof(SyslogAddr.sa_data));
--retry:
-- if (LogStat & LOG_NDELAY) {
-- if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){
-- UNLOCK;
-- return;
-- }
-- /* fcntl(LogFile, F_SETFD, 1); */
-- }
-+ SyslogAddr.sa_family = AF_UNIX;
-+ (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
-+ sizeof(SyslogAddr.sa_data));
-+ retry:
-+ if (LogStat & LOG_NDELAY) {
-+ if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){
-+ goto DONE;
-+ }
-+ /* fcntl(LogFile, F_SETFD, 1); */
-+ }
- }
-
- if (LogFile != -1 && !connected) {
-- if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) -
-- sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1)
-- {
-- connected = 1;
-- } else if (logType == SOCK_DGRAM) {
-- logType = SOCK_STREAM;
-- if (LogFile != -1) {
-- close(LogFile);
-- LogFile = -1;
-- }
-- goto retry;
-- } else {
-- if (LogFile != -1) {
-- close(LogFile);
-- LogFile = -1;
-- }
-- }
-+ if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) -
-+ sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1)
-+ {
-+ connected = 1;
-+ } else if (logType == SOCK_DGRAM) {
-+ logType = SOCK_STREAM;
-+ if (LogFile != -1) {
-+ close(LogFile);
-+ LogFile = -1;
-+ }
-+ goto retry;
-+ } else {
-+ if (LogFile != -1) {
-+ close(LogFile);
-+ LogFile = -1;
-+ }
-+ }
- }
-
-- UNLOCK;
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- /*
-@@ -335,10 +327,10 @@ int setlogmask(int pmask)
- int omask;
-
- omask = LogMask;
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (pmask != 0)
-- LogMask = pmask;
-- UNLOCK;
-+ LogMask = pmask;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return (omask);
- }
-
-diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
-index f43bb8a..6165a52 100644
---- a/libc/misc/time/time.c
-+++ b/libc/misc/time/time.c
-@@ -143,6 +143,8 @@
- #include <locale.h>
- #include <bits/uClibc_uintmaxtostr.h>
-
-+#include <bits/uClibc_mutex.h>
-+
- #ifdef __UCLIBC_HAS_XLOCALE__
- #include <xlocale.h>
- #endif
-@@ -191,21 +193,7 @@ typedef struct {
- char tzname[TZNAME_MAX+1];
- } rule_struct;
-
--#ifdef __UCLIBC_HAS_THREADS__
--
--#include <pthread.h>
--
--extern pthread_mutex_t _time_tzlock;
--
--#define TZLOCK __pthread_mutex_lock(&_time_tzlock)
--#define TZUNLOCK __pthread_mutex_unlock(&_time_tzlock)
--
--#else
--
--#define TZLOCK ((void) 0)
--#define TZUNLOCK ((void) 0)
--
--#endif
-+__UCLIBC_MUTEX_EXTERN(_time_tzlock);
-
- extern rule_struct _time_tzinfo[2];
-
-@@ -542,13 +530,13 @@ struct tm *localtime(const time_t *timer
- struct tm *localtime_r(register const time_t *__restrict timer,
- register struct tm *__restrict result)
- {
-- TZLOCK;
-+ __UCLIBC_MUTEX_LOCK(_time_tzlock);
-
- tzset();
-
- __time_localtime_tzi(timer, result, _time_tzinfo);
-
-- TZUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
-
- return result;
- }
-@@ -1037,7 +1025,7 @@ size_t __XL(strftime)(char *__restrict s
- goto LOOP;
- }
-
-- o = spec + 26; /* set to "????" */
-+ o = ((const char *) spec) + 26; /* set to "????" */
- if ((code & MASK_SPEC) == CALC_SPEC) {
-
- if (*p == 's') {
-@@ -1073,17 +1061,15 @@ size_t __XL(strftime)(char *__restrict s
-
- #ifdef __UCLIBC_HAS_TM_EXTENSIONS__
-
--#define RSP_TZUNLOCK ((void) 0)
- #define RSP_TZNAME timeptr->tm_zone
- #define RSP_GMT_OFFSET (-timeptr->tm_gmtoff)
-
- #else
-
--#define RSP_TZUNLOCK TZUNLOCK
- #define RSP_TZNAME rsp->tzname
- #define RSP_GMT_OFFSET rsp->gmt_offset
-
-- TZLOCK;
-+ __UCLIBC_MUTEX_LOCK(_time_tzlock);
-
- rsp = _time_tzinfo;
- if (timeptr->tm_isdst > 0) {
-@@ -1114,15 +1100,17 @@ size_t __XL(strftime)(char *__restrict s
- }
- #endif
- o_count = SIZE_MAX;
-- RSP_TZUNLOCK;
-+/* RSP_TZUNLOCK; */
-+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
- goto OUTPUT;
-+#endif
- } else { /* z */
- *s = '+';
- if ((tzo = -RSP_GMT_OFFSET) < 0) {
- tzo = -tzo;
- *s = '-';
- }
-- RSP_TZUNLOCK;
-+/* RSP_TZUNLOCK; */
- ++s;
- --count;
-
-@@ -1131,7 +1119,13 @@ size_t __XL(strftime)(char *__restrict s
-
- i = 16 + 6; /* 0-fill, width = 4 */
- }
--
-+#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
-+#else
-+ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
-+ if (*p == 'Z') {
-+ goto OUTPUT;
-+ }
-+#endif
- } else {
- /* TODO: don't need year for U, W */
- for (i=0 ; i < 3 ; i++) {
-@@ -1664,9 +1658,7 @@ int daylight = 0;
- long timezone = 0;
- char *tzname[2] = { (char *) UTC, (char *) (UTC-1) };
-
--#ifdef __UCLIBC_HAS_THREADS__
--pthread_mutex_t _time_tzlock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--#endif
-+__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- rule_struct _time_tzinfo[2];
-
-@@ -1796,7 +1788,7 @@ void tzset(void)
- static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */
- #endif /* __UCLIBC_HAS_TZ_CACHING__ */
-
-- TZLOCK;
-+ __UCLIBC_MUTEX_LOCK(_time_tzlock);
-
- e = getenv(TZ); /* TZ env var always takes precedence. */
-
-@@ -1962,10 +1954,10 @@ void tzset(void)
- daylight = !!_time_tzinfo[1].tzname[0];
- timezone = _time_tzinfo[0].gmt_offset;
-
--#if defined(__UCLIBC_HAS_TZ_FILE__)
-+#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__)
- FAST_DONE:
- #endif
-- TZUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
- }
-
- #endif
-@@ -2167,13 +2159,13 @@ time_t _time_mktime(struct tm *timeptr,
- {
- time_t t;
-
-- TZLOCK;
-+ __UCLIBC_MUTEX_LOCK(_time_tzlock);
-
- tzset();
-
- t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo);
-
-- TZUNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(_time_tzlock);
-
- return t;
- }
-diff --git a/libc/misc/ttyent/getttyent.c b/libc/misc/ttyent/getttyent.c
-index 6e2fbd2..c85c73a 100644
---- a/libc/misc/ttyent/getttyent.c
-+++ b/libc/misc/ttyent/getttyent.c
-@@ -35,9 +35,6 @@
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--#endif
-
- static char zapchar;
- static FILE *tf;
-@@ -50,8 +47,8 @@ struct ttyent * getttynam(const char *tt
-
- setttyent();
- while ((t = getttyent()))
-- if (!strcmp(tty, t->ty_name))
-- break;
-+ if (!strcmp(tty, t->ty_name))
-+ break;
- endttyent();
- return (t);
- }
-@@ -67,27 +64,27 @@ static char * skip(register char *p)
- register int c, q;
-
- for (q = 0, t = p; (c = *p) != '\0'; p++) {
-- if (c == '"') {
-- q ^= QUOTED; /* obscure, but nice */
-- continue;
-- }
-- if (q == QUOTED && *p == '\\' && *(p+1) == '"')
-- p++;
-- *t++ = *p;
-- if (q == QUOTED)
-- continue;
-- if (c == '#') {
-- zapchar = c;
-- *p = 0;
-- break;
-- }
-- if (c == '\t' || c == ' ' || c == '\n') {
-- zapchar = c;
-- *p++ = 0;
-- while ((c = *p) == '\t' || c == ' ' || c == '\n')
-- p++;
-- break;
-- }
-+ if (c == '"') {
-+ q ^= QUOTED; /* obscure, but nice */
-+ continue;
-+ }
-+ if (q == QUOTED && *p == '\\' && *(p+1) == '"')
-+ p++;
-+ *t++ = *p;
-+ if (q == QUOTED)
-+ continue;
-+ if (c == '#') {
-+ zapchar = c;
-+ *p = 0;
-+ break;
-+ }
-+ if (c == '\t' || c == ' ' || c == '\n') {
-+ zapchar = c;
-+ *p++ = 0;
-+ while ((c = *p) == '\t' || c == ' ' || c == '\n')
-+ p++;
-+ break;
-+ }
- }
- *--t = '\0';
- return (p);
-@@ -104,46 +101,46 @@ struct ttyent * getttyent(void)
- register int c;
- register char *p;
- static char *line = NULL;
-+ struct ttyent *retval = NULL;
-
- if (!tf && !setttyent())
-- return (NULL);
-+ return (NULL);
-
- if (!line) {
-- line = malloc(BUFSIZ);
-+ line = malloc(BUFSIZ);
- if (!line)
- abort();
- }
-
-- __STDIO_ALWAYS_THREADLOCK(tf);
-+ __STDIO_ALWAYS_THREADLOCK(tf);
-
- for (;;) {
-- if (!fgets_unlocked(p = line, BUFSIZ, tf)) {
-- __STDIO_ALWAYS_THREADUNLOCK(tf);
-- return (NULL);
-- }
-- /* skip lines that are too big */
-- if (!index(p, '\n')) {
-- while ((c = getc_unlocked(tf)) != '\n' && c != EOF)
-- ;
-- continue;
-- }
-- while (isspace(*p))
-- ++p;
-- if (*p && *p != '#')
-- break;
-+ if (!fgets_unlocked(p = line, BUFSIZ, tf)) {
-+ goto DONE;
-+ }
-+ /* skip lines that are too big */
-+ if (!index(p, '\n')) {
-+ while ((c = getc_unlocked(tf)) != '\n' && c != EOF)
-+ ;
-+ continue;
-+ }
-+ while (isspace(*p))
-+ ++p;
-+ if (*p && *p != '#')
-+ break;
- }
-
- zapchar = 0;
- tty.ty_name = p;
- p = skip(p);
- if (!*(tty.ty_getty = p))
-- tty.ty_getty = tty.ty_type = NULL;
-+ tty.ty_getty = tty.ty_type = NULL;
- else {
-- p = skip(p);
-- if (!*(tty.ty_type = p))
-- tty.ty_type = NULL;
-- else
-- p = skip(p);
-+ p = skip(p);
-+ if (!*(tty.ty_type = p))
-+ tty.ty_type = NULL;
-+ else
-+ p = skip(p);
- }
- tty.ty_status = 0;
- tty.ty_window = NULL;
-@@ -151,43 +148,45 @@ struct ttyent * getttyent(void)
- #define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1])
- #define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
- for (; *p; p = skip(p)) {
-- if (scmp(_TTYS_OFF))
-- tty.ty_status &= ~TTY_ON;
-- else if (scmp(_TTYS_ON))
-- tty.ty_status |= TTY_ON;
-- else if (scmp(_TTYS_SECURE))
-- tty.ty_status |= TTY_SECURE;
-- else if (vcmp(_TTYS_WINDOW))
-- tty.ty_window = value(p);
-- else
-- break;
-+ if (scmp(_TTYS_OFF))
-+ tty.ty_status &= ~TTY_ON;
-+ else if (scmp(_TTYS_ON))
-+ tty.ty_status |= TTY_ON;
-+ else if (scmp(_TTYS_SECURE))
-+ tty.ty_status |= TTY_SECURE;
-+ else if (vcmp(_TTYS_WINDOW))
-+ tty.ty_window = value(p);
-+ else
-+ break;
- }
-- /* We can release the lock only here since `zapchar' is global. */
-- __STDIO_ALWAYS_THREADUNLOCK(tf);
-
- if (zapchar == '#' || *p == '#')
-- while ((c = *++p) == ' ' || c == '\t')
-- ;
-+ while ((c = *++p) == ' ' || c == '\t')
-+ ;
- tty.ty_comment = p;
- if (*p == 0)
-- tty.ty_comment = 0;
-+ tty.ty_comment = 0;
- if ((p = index(p, '\n')))
-- *p = '\0';
-- return (&tty);
-+ *p = '\0';
-+ retval = &tty;
-+
-+ DONE:
-+ __STDIO_ALWAYS_THREADUNLOCK(tf);
-+ return retval;
- }
-
- int setttyent(void)
- {
-
- if (tf) {
-- rewind(tf);
-- return (1);
-+ rewind(tf);
-+ return (1);
- } else if ((tf = fopen(_PATH_TTYS, "r"))) {
-- /* We do the locking ourselves. */
-+ /* We do the locking ourselves. */
- #ifdef __UCLIBC_HAS_THREADS__
-- __fsetlocking (tf, FSETLOCKING_BYCALLER);
-+ __fsetlocking (tf, FSETLOCKING_BYCALLER);
- #endif
-- return (1);
-+ return (1);
- }
- return (0);
- }
-@@ -197,9 +196,9 @@ int endttyent(void)
- int rval;
-
- if (tf) {
-- rval = !(fclose(tf) == EOF);
-- tf = NULL;
-- return (rval);
-+ rval = !(fclose(tf) == EOF);
-+ tf = NULL;
-+ return (rval);
- }
- return (1);
- }
-diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c
-index c1d8d6f..0fc6df4 100644
---- a/libc/misc/utmp/utent.c
-+++ b/libc/misc/utmp/utent.c
-@@ -20,19 +20,9 @@
- #include <string.h>
- #include <utmp.h>
-
-+#include <bits/uClibc_mutex.h>
-
--
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t utmplock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&utmplock)
--# define UNLOCK __pthread_mutex_unlock(&utmplock)
--#else
--# define LOCK
--# define UNLOCK
--#endif
--
--
-+__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER);
-
- /* Some global crap */
- static int static_fd = -1;
-@@ -46,19 +36,19 @@ static struct utmp *__getutent(int utmp_
-
- {
- if (utmp_fd == -1) {
-- setutent();
-+ setutent();
- }
- if (utmp_fd == -1) {
-- return NULL;
-+ return NULL;
- }
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(utmplock);
- if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) != sizeof(struct utmp))
-- {
-- return NULL;
-- }
-+ {
-+ return NULL;
-+ }
-
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(utmplock);
- return &static_utmp;
- }
-
-@@ -66,39 +56,39 @@ void setutent(void)
- {
- int ret;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(utmplock);
- if (static_fd == -1) {
-- if ((static_fd = open(static_ut_name, O_RDWR)) < 0) {
-- if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) {
-- goto bummer;
-- }
-- }
-- /* Make sure the file will be closed on exec() */
-- ret = fcntl(static_fd, F_GETFD, 0);
-- if (ret >= 0) {
-- ret = fcntl(static_fd, F_GETFD, 0);
-- }
-- if (ret < 0) {
--bummer:
-- UNLOCK;
-- static_fd = -1;
-- close(static_fd);
-- return;
-- }
-+ if ((static_fd = open(static_ut_name, O_RDWR)) < 0) {
-+ if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) {
-+ goto bummer;
-+ }
-+ }
-+ /* Make sure the file will be closed on exec() */
-+ ret = fcntl(static_fd, F_GETFD, 0);
-+ if (ret >= 0) {
-+ ret = fcntl(static_fd, F_GETFD, 0);
-+ }
-+ if (ret < 0) {
-+ bummer:
-+ close(static_fd);
-+ static_fd = -1;
-+ goto DONE;
-+ }
- }
- lseek(static_fd, 0, SEEK_SET);
-- UNLOCK;
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(utmplock);
- return;
- }
-
- void endutent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(utmplock);
- if (static_fd != -1) {
-- close(static_fd);
-+ close(static_fd);
- }
- static_fd = -1;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(utmplock);
- }
-
- /* Locking is done in __getutent */
-@@ -113,22 +103,22 @@ struct utmp *getutid (const struct utmp
- struct utmp *lutmp;
-
- while ((lutmp = __getutent(static_fd)) != NULL) {
-- if ( (utmp_entry->ut_type == RUN_LVL ||
-- utmp_entry->ut_type == BOOT_TIME ||
-- utmp_entry->ut_type == NEW_TIME ||
-- utmp_entry->ut_type == OLD_TIME) &&
-- lutmp->ut_type == utmp_entry->ut_type)
-- {
-- return lutmp;
-- }
-- if ( (utmp_entry->ut_type == INIT_PROCESS ||
-- utmp_entry->ut_type == DEAD_PROCESS ||
-- utmp_entry->ut_type == LOGIN_PROCESS ||
-- utmp_entry->ut_type == USER_PROCESS) &&
-- !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)))
-- {
-- return lutmp;
-- }
-+ if ( (utmp_entry->ut_type == RUN_LVL ||
-+ utmp_entry->ut_type == BOOT_TIME ||
-+ utmp_entry->ut_type == NEW_TIME ||
-+ utmp_entry->ut_type == OLD_TIME) &&
-+ lutmp->ut_type == utmp_entry->ut_type)
-+ {
-+ return lutmp;
-+ }
-+ if ( (utmp_entry->ut_type == INIT_PROCESS ||
-+ utmp_entry->ut_type == DEAD_PROCESS ||
-+ utmp_entry->ut_type == LOGIN_PROCESS ||
-+ utmp_entry->ut_type == USER_PROCESS) &&
-+ !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)))
-+ {
-+ return lutmp;
-+ }
- }
-
- return NULL;
-@@ -140,11 +130,11 @@ struct utmp *getutline(const struct utmp
- struct utmp *lutmp;
-
- while ((lutmp = __getutent(static_fd)) != NULL) {
-- if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) &&
-- !strcmp(lutmp->ut_line, utmp_entry->ut_line))
-- {
-- return lutmp;
-- }
-+ if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) &&
-+ !strcmp(lutmp->ut_line, utmp_entry->ut_line))
-+ {
-+ return lutmp;
-+ }
- }
-
- return NULL;
-@@ -152,42 +142,42 @@ struct utmp *getutline(const struct utmp
-
- struct utmp *pututline (const struct utmp *utmp_entry)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(utmplock);
- /* Ignore the return value. That way, if they've already positioned
- the file pointer where they want it, everything will work out. */
- lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
-
- if (getutid(utmp_entry) != NULL) {
-- lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
-- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
-- return NULL;
-+ lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
-+ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
-+ return NULL;
- } else {
-- lseek(static_fd, (off_t) 0, SEEK_END);
-- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
-- return NULL;
-+ lseek(static_fd, (off_t) 0, SEEK_END);
-+ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
-+ return NULL;
- }
-
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(utmplock);
- return (struct utmp *)utmp_entry;
- }
-
- int utmpname (const char *new_ut_name)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(utmplock);
- if (new_ut_name != NULL) {
-- if (static_ut_name != default_file_name)
-- free((char *)static_ut_name);
-- static_ut_name = strdup(new_ut_name);
-- if (static_ut_name == NULL) {
-- /* We should probably whine about out-of-memory
-- * errors here... Instead just reset to the default */
-- static_ut_name = default_file_name;
-- }
-+ if (static_ut_name != default_file_name)
-+ free((char *)static_ut_name);
-+ static_ut_name = strdup(new_ut_name);
-+ if (static_ut_name == NULL) {
-+ /* We should probably whine about out-of-memory
-+ * errors here... Instead just reset to the default */
-+ static_ut_name = default_file_name;
-+ }
- }
-
- if (static_fd != -1)
-- close(static_fd);
-- UNLOCK;
-+ close(static_fd);
-+ __UCLIBC_MUTEX_UNLOCK(utmplock);
- return 0;
- }
-
-diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c
-index b49494f..408c57a 100644
---- a/libc/misc/wchar/wstdio.c
-+++ b/libc/misc/wchar/wstdio.c
-@@ -82,9 +82,6 @@ strong_alias(NAME,NAME##_unlocked) \
- void NAME PARAMS
- #endif
-
--#define __STDIO_THREADLOCK_OPENLIST
--#define __STDIO_THREADUNLOCK_OPENLIST
--
- #else /* __UCLIBC_HAS_THREADS__ */
-
- #include <pthread.h>
-@@ -112,15 +109,6 @@ void NAME PARAMS \
- } \
- void NAME##_unlocked PARAMS
-
--#define __STDIO_THREADLOCK_OPENLIST \
-- __pthread_mutex_lock(&_stdio_openlist_lock)
--
--#define __STDIO_THREADUNLOCK_OPENLIST \
-- __pthread_mutex_unlock(&_stdio_openlist_lock)
--
--#define __STDIO_THREADTRYLOCK_OPENLIST \
-- __pthread_mutex_trylock(&_stdio_openlist_lock)
--
- #endif /* __UCLIBC_HAS_THREADS__ */
-
- #ifndef __STDIO_BUFFERS
-diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c
-index 6b9c251..063fed4 100644
---- a/libc/pwd_grp/lckpwdf.c
-+++ b/libc/pwd_grp/lckpwdf.c
-@@ -27,15 +27,9 @@
- #include <sys/file.h>
- #include <paths.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+#include <bits/uClibc_mutex.h>
-+
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- /* How long to wait for getting the lock before returning with an
- error. */
-@@ -57,18 +51,18 @@ int lckpwdf (void)
- struct sigaction new_act; /* New signal action. */
- struct flock fl; /* Information struct for locking. */
- int result;
-+ int rv = -1;
-
- if (lock_fd != -1)
- /* Still locked by own process. */
- return -1;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- lock_fd = open (_PATH_PASSWD, O_WRONLY);
- if (lock_fd == -1) {
- /* Cannot create lock file. */
-- UNLOCK;
-- return -1;
-+ goto DONE;
- }
-
- /* Make sure file gets correctly closed when process finished. */
-@@ -77,16 +71,14 @@ int lckpwdf (void)
- /* Cannot get file flags. */
- close(lock_fd);
- lock_fd = -1;
-- UNLOCK;
-- return -1;
-+ goto DONE;
- }
- flags |= FD_CLOEXEC; /* Close on exit. */
- if (fcntl (lock_fd, F_SETFD, flags) < 0) {
- /* Cannot set new flags. */
- close(lock_fd);
- lock_fd = -1;
-- UNLOCK;
-- return -1;
-+ goto DONE;
- }
-
- /* Now we have to get exclusive write access. Since multiple
-@@ -107,8 +99,7 @@ int lckpwdf (void)
- /* Cannot install signal handler. */
- close(lock_fd);
- lock_fd = -1;
-- UNLOCK;
-- return -1;
-+ goto DONE;
- }
-
- /* Now make sure the alarm signal is not blocked. */
-@@ -118,8 +109,7 @@ int lckpwdf (void)
- sigaction (SIGALRM, &saved_act, NULL);
- close(lock_fd);
- lock_fd = -1;
-- UNLOCK;
-- return -1;
-+ goto DONE;
- }
-
- /* Start timer. If we cannot get the lock in the specified time we
-@@ -146,12 +136,14 @@ int lckpwdf (void)
- if (result < 0) {
- close(lock_fd);
- lock_fd = -1;
-- UNLOCK;
-- return -1;
-+ goto DONE;
- }
-
-- UNLOCK;
-- return 0;
-+ rv = 0;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-+ return rv;
- }
-
-
-@@ -164,11 +156,11 @@ int ulckpwdf (void)
- result = -1;
- }
- else {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- result = close (lock_fd);
- /* Mark descriptor as unused. */
- lock_fd = -1;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- return result;
-diff --git a/libc/pwd_grp/pwd_grp.c b/libc/pwd_grp/pwd_grp.c
-index 91c0d83..a302c7c 100644
---- a/libc/pwd_grp/pwd_grp.c
-+++ b/libc/pwd_grp/pwd_grp.c
-@@ -42,9 +42,8 @@
- #include <pwd.h>
- #include <grp.h>
- #include <shadow.h>
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--#endif
-+
-+#include <bits/uClibc_mutex.h>
-
- /**********************************************************************/
- /* Sizes for staticly allocated buffers. */
-@@ -445,34 +444,27 @@ int getpw(uid_t uid, char *buf)
- /**********************************************************************/
- #ifdef L_getpwent_r
-
--#ifdef __UCLIBC_HAS_THREADS__
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK ((void) 0)
--# define UNLOCK ((void) 0)
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- static FILE *pwf /*= NULL*/;
-
- void setpwent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (pwf) {
- rewind(pwf);
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- void endpwent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (pwf) {
- fclose(pwf);
- pwf = NULL;
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
-
-@@ -482,7 +474,7 @@ int getpwent_r(struct passwd *__restrict
- {
- int rv;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- *result = NULL; /* In case of error... */
-
-@@ -500,7 +492,7 @@ int getpwent_r(struct passwd *__restrict
- }
-
- ERR:
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- return rv;
- }
-@@ -509,34 +501,27 @@ int getpwent_r(struct passwd *__restrict
- /**********************************************************************/
- #ifdef L_getgrent_r
-
--#ifdef __UCLIBC_HAS_THREADS__
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK ((void) 0)
--# define UNLOCK ((void) 0)
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- static FILE *grf /*= NULL*/;
-
- void setgrent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (grf) {
- rewind(grf);
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- void endgrent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (grf) {
- fclose(grf);
- grf = NULL;
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- int getgrent_r(struct group *__restrict resultbuf,
-@@ -545,7 +530,7 @@ int getgrent_r(struct group *__restrict
- {
- int rv;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- *result = NULL; /* In case of error... */
-
-@@ -563,7 +548,7 @@ int getgrent_r(struct group *__restrict
- }
-
- ERR:
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- return rv;
- }
-@@ -572,34 +557,27 @@ int getgrent_r(struct group *__restrict
- /**********************************************************************/
- #ifdef L_getspent_r
-
--#ifdef __UCLIBC_HAS_THREADS__
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK ((void) 0)
--# define UNLOCK ((void) 0)
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- static FILE *spf /*= NULL*/;
-
- void setspent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (spf) {
- rewind(spf);
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- void endspent(void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (spf) {
- fclose(spf);
- spf = NULL;
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
-
- int getspent_r(struct spwd *resultbuf, char *buffer,
-@@ -607,7 +585,7 @@ int getspent_r(struct spwd *resultbuf, c
- {
- int rv;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- *result = NULL; /* In case of error... */
-
-@@ -625,7 +603,7 @@ int getspent_r(struct spwd *resultbuf, c
- }
-
- ERR:
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- return rv;
- }
-diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c
-index 7d3c38c..fe1bc91 100644
---- a/libc/stdio/_READ.c
-+++ b/libc/stdio/_READ.c
-@@ -41,7 +41,7 @@ size_t __stdio_READ(register FILE *strea
- #warning EINTR?
- #endif
- /* RETRY: */
-- if ((rv = __READ(stream, buf, bufsize)) <= 0) {
-+ if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) {
- if (rv == 0) {
- __STDIO_STREAM_SET_EOF(stream);
- } else {
-diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c
-index d300d39..4131eb7 100644
---- a/libc/stdio/_WRITE.c
-+++ b/libc/stdio/_WRITE.c
-@@ -47,7 +47,7 @@ size_t __stdio_WRITE(register FILE *stre
- return bufsize;
- }
- stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
-- if ((rv = __WRITE(stream, buf, stodo)) >= 0) {
-+ if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) {
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning TODO: Make custom stream write return check optional.
- #endif
-diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c
-index f7f5bb6..4984f11 100644
---- a/libc/stdio/_fopen.c
-+++ b/libc/stdio/_fopen.c
-@@ -194,10 +194,23 @@ FILE *_stdio_fopen(intptr_t fname_or_mod
- #endif
-
- #ifdef __STDIO_HAS_OPENLIST
-- __STDIO_THREADLOCK_OPENLIST;
-- stream->__nextopen = _stdio_openlist; /* New files are inserted at */
-- _stdio_openlist = stream; /* the head of the list. */
-- __STDIO_THREADUNLOCK_OPENLIST;
-+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
-+ if (!(stream->__modeflags & __FLAG_FREEFILE))
-+ {
-+ /* An freopen call so the file was never removed from the list. */
-+ }
-+ else
-+#endif
-+ {
-+ /* We have to lock the del mutex in case another thread wants to fclose()
-+ * the last file. */
-+ __STDIO_THREADLOCK_OPENLIST_DEL;
-+ __STDIO_THREADLOCK_OPENLIST_ADD;
-+ stream->__nextopen = _stdio_openlist; /* New files are inserted at */
-+ _stdio_openlist = stream; /* the head of the list. */
-+ __STDIO_THREADUNLOCK_OPENLIST_ADD;
-+ __STDIO_THREADUNLOCK_OPENLIST_DEL;
-+ }
- #endif
-
- __STDIO_STREAM_VALIDATE(stream);
-diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c
-index 4aae3c4..9cfe02c 100644
---- a/libc/stdio/_stdio.c
-+++ b/libc/stdio/_stdio.c
-@@ -151,8 +151,12 @@ FILE *__stdout = _stdio_streams + 1; /*
- FILE *_stdio_openlist = _stdio_streams;
-
- # ifdef __UCLIBC_HAS_THREADS__
--pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--int _stdio_openlist_delflag = 0;
-+__UCLIBC_MUTEX_INIT(_stdio_openlist_add_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-+#ifdef __STDIO_BUFFERS
-+__UCLIBC_MUTEX_INIT(_stdio_openlist_del_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-+volatile int _stdio_openlist_use_count = 0;
-+int _stdio_openlist_del_count = 0;
-+#endif
- # endif
-
- #endif
-@@ -162,10 +166,10 @@ int _stdio_openlist_delflag = 0;
- /* 2 if threading not initialized and 0 otherwise; */
- int _stdio_user_locking = 2;
-
--void __stdio_init_mutex(pthread_mutex_t *m)
-+void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m)
- {
-- static const pthread_mutex_t __stdio_mutex_initializer
-- = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-+ const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer,
-+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer));
- }
-@@ -184,7 +188,11 @@ void _stdio_term(void)
- * locked, then I suppose there is a chance that a pointer in the
- * chain might be corrupt due to a partial store.
- */
-- __stdio_init_mutex(&_stdio_openlist_lock);
-+ __stdio_init_mutex(&_stdio_openlist_add_lock);
-+#warning check
-+#ifdef __STDIO_BUFFERS
-+ __stdio_init_mutex(&_stdio_openlist_del_lock);
-+#endif
-
- /* Next we need to worry about the streams themselves. If a stream
- * is currently locked, then it may be in an invalid state. So we
-@@ -192,7 +200,7 @@ void _stdio_term(void)
- * Then we reinitialize the locks.
- */
- for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) {
-- if (__STDIO_ALWAYS_THREADTRYLOCK(ptr)) {
-+ if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) {
- /* The stream is already locked, so we don't want to touch it.
- * However, if we have custom streams, we can't just close it
- * or leave it locked since a custom stream may be stacked
-@@ -258,10 +266,6 @@ void _stdio_init(void)
- #error Assumption violated about __MASK_READING and __FLAG_UNGOT
- #endif
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--#endif
--
- #ifndef NDEBUG
-
- void _stdio_validate_FILE(const FILE *stream)
-diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h
-index e3c2c58..decf57d 100644
---- a/libc/stdio/_stdio.h
-+++ b/libc/stdio/_stdio.h
-@@ -22,23 +22,57 @@
- #include <wchar.h>
- #endif
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
-+#include <bits/uClibc_mutex.h>
-
--#define __STDIO_THREADLOCK_OPENLIST \
-- __pthread_mutex_lock(&_stdio_openlist_lock)
-+#define __STDIO_THREADLOCK_OPENLIST_ADD \
-+ __UCLIBC_MUTEX_LOCK(_stdio_openlist_add_lock)
-
--#define __STDIO_THREADUNLOCK_OPENLIST \
-- __pthread_mutex_unlock(&_stdio_openlist_lock)
-+#define __STDIO_THREADUNLOCK_OPENLIST_ADD \
-+ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_add_lock)
-
--#define __STDIO_THREADTRYLOCK_OPENLIST \
-- __pthread_mutex_trylock(&_stdio_openlist_lock)
-+#ifdef __STDIO_BUFFERS
-
--#else
-+#define __STDIO_THREADLOCK_OPENLIST_DEL \
-+ __UCLIBC_MUTEX_LOCK(_stdio_openlist_del_lock)
-+
-+#define __STDIO_THREADUNLOCK_OPENLIST_DEL \
-+ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_del_lock)
-
--#define __STDIO_THREADLOCK_OPENLIST ((void)0)
--#define __STDIO_THREADUNLOCK_OPENLIST ((void)0)
-+#define __STDIO_OPENLIST_INC_USE \
-+do { \
-+ __STDIO_THREADLOCK_OPENLIST_DEL; \
-+ ++_stdio_openlist_use_count; \
-+ __STDIO_THREADUNLOCK_OPENLIST_DEL; \
-+} while (0)
-+
-+extern void _stdio_openlist_dec_use(void);
-+
-+#define __STDIO_OPENLIST_DEC_USE \
-+ _stdio_openlist_dec_use()
-+
-+#define __STDIO_OPENLIST_INC_DEL_CNT \
-+do { \
-+ __STDIO_THREADLOCK_OPENLIST_DEL; \
-+ ++_stdio_openlist_del_count; \
-+ __STDIO_THREADUNLOCK_OPENLIST_DEL; \
-+} while (0)
-+
-+#define __STDIO_OPENLIST_DEC_DEL_CNT \
-+do { \
-+ __STDIO_THREADLOCK_OPENLIST_DEL; \
-+ --_stdio_openlist_del_count; \
-+ __STDIO_THREADUNLOCK_OPENLIST_DEL; \
-+} while (0)
-+
-+#endif /* __STDIO_BUFFERS */
-
-+#ifndef __STDIO_THREADLOCK_OPENLIST_DEL
-+#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0)
-+#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0)
-+#define __STDIO_OPENLIST_INC_USE ((void)0)
-+#define __STDIO_OPENLIST_DEC_USE ((void)0)
-+#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0)
-+#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0)
- #endif
-
- #define __UNDEFINED_OR_NONPORTABLE ((void)0)
-diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c
-index 4df2e42..dfababc 100644
---- a/libc/stdio/fclose.c
-+++ b/libc/stdio/fclose.c
-@@ -12,30 +12,34 @@ int fclose(register FILE *stream)
- int rv = 0;
- __STDIO_AUTO_THREADLOCK_VAR;
-
-- /* First, remove the file from the open file list. */
--#ifdef __STDIO_HAS_OPENLIST
-- {
-- register FILE *ptr;
--
-- __STDIO_THREADLOCK_OPENLIST;
-- if ((ptr = _stdio_openlist) == stream) {
-- _stdio_openlist = stream->__nextopen;
-- } else {
-- while (ptr) {
-- if (ptr->__nextopen == stream) {
-- ptr->__nextopen = stream->__nextopen;
-- break;
-- }
-- ptr = ptr->__nextopen;
-- }
-- }
-- __STDIO_THREADUNLOCK_OPENLIST;
--
-- if (!ptr) { /* Did not find stream in the open file list! */
-- return EOF;
-- }
-- }
--#endif
-+#warning dead code... but may want to simply check and not remove
-+/* #ifdef __STDIO_HAS_OPENLIST */
-+/* #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) */
-+/* /\* First, remove the file from the open file list. *\/ */
-+/* { */
-+/* register FILE *ptr; */
-+
-+/* __STDIO_THREADLOCK_OPENLIST; */
-+/* if ((ptr = _stdio_openlist) == stream) { */
-+/* #warning does a mod!!! */
-+/* _stdio_openlist = stream->__nextopen; */
-+/* } else { */
-+/* while (ptr) { */
-+/* if (ptr->__nextopen == stream) { */
-+/* ptr->__nextopen = stream->__nextopen; */
-+/* break; */
-+/* } */
-+/* ptr = ptr->__nextopen; */
-+/* } */
-+/* } */
-+/* __STDIO_THREADUNLOCK_OPENLIST; */
-+
-+/* if (!ptr) { /\* Did not find stream in the open file list! *\/ */
-+/* return EOF; */
-+/* } */
-+/* } */
-+/* #endif */
-+/* #endif */
-
- __STDIO_AUTO_THREADLOCK(stream);
-
-@@ -80,7 +84,15 @@ int fclose(register FILE *stream)
- __STDIO_AUTO_THREADUNLOCK(stream);
-
- __STDIO_STREAM_FREE_BUFFER(stream);
-+#warning... inefficient - locks and unlocks twice and walks whole list
-+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
-+ /* inefficient - locks/unlocks twice and walks whole list */
-+ __STDIO_OPENLIST_INC_USE;
-+ __STDIO_OPENLIST_INC_DEL_CNT;
-+ __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */
-+#else
- __STDIO_STREAM_FREE_FILE(stream);
-+#endif
-
- return rv;
- }
-diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c
-index dbb6000..f62281a 100644
---- a/libc/stdio/fcloseall.c
-+++ b/libc/stdio/fcloseall.c
-@@ -19,14 +19,34 @@ int fcloseall (void)
- #ifdef __STDIO_HAS_OPENLIST
-
- int retval = 0;
-+ FILE *f;
-
-- __STDIO_THREADLOCK_OPENLIST;
-- while (_stdio_openlist) {
-- if (fclose(_stdio_openlist)) {
-+#warning remove dead code
-+/* __STDIO_THREADLOCK_OPENLIST; */
-+/* while (_stdio_openlist) { */
-+/* if (fclose(_stdio_openlist)) { */
-+/* retval = EOF; */
-+/* } */
-+/* } */
-+/* __STDIO_THREADUNLOCK_OPENLIST; */
-+
-+ __STDIO_OPENLIST_INC_USE;
-+
-+#warning should probably have a get_head() operation
-+ __STDIO_THREADLOCK_OPENLIST_ADD;
-+ f = _stdio_openlist;
-+ __STDIO_THREADUNLOCK_OPENLIST_ADD;
-+
-+ while (f) {
-+#warning should probably have a get_next() operation
-+ FILE *n = f->__nextopen;
-+ if (fclose(f)) {
- retval = EOF;
- }
-+ f = n;
- }
-- __STDIO_THREADUNLOCK_OPENLIST;
-+
-+ __STDIO_OPENLIST_DEC_USE;
-
- return retval;
-
-diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c
-index 6baa0ec..66b65cd 100644
---- a/libc/stdio/fflush.c
-+++ b/libc/stdio/fflush.c
-@@ -20,23 +20,50 @@ weak_alias(__fflush_unlocked,fflush_unlo
- weak_alias(__fflush_unlocked,fflush);
- #endif
-
--#ifdef __UCLIBC_HAS_THREADS__
- /* Even if the stream is set to user-locking, we still need to lock
- * when all (lbf) writing streams are flushed. */
--#define MY_STDIO_THREADLOCK(STREAM) \
-- if (_stdio_user_locking != 2) { \
-- __STDIO_ALWAYS_THREADLOCK(STREAM); \
-- }
-
--#define MY_STDIO_THREADUNLOCK(STREAM) \
-- if (_stdio_user_locking != 2) { \
-- __STDIO_ALWAYS_THREADUNLOCK(STREAM); \
-- }
--#else
--#define MY_STDIO_THREADLOCK(STREAM) ((void)0)
--#define MY_STDIO_THREADUNLOCK(STREAM) ((void)0)
--#endif
-+#define __MY_STDIO_THREADLOCK(__stream) \
-+ __UCLIBC_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \
-+ (_stdio_user_locking != 2))
-+
-+#define __MY_STDIO_THREADUNLOCK(__stream) \
-+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \
-+ (_stdio_user_locking != 2))
-
-+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
-+void _stdio_openlist_dec_use(void)
-+{
-+ __STDIO_THREADLOCK_OPENLIST_DEL;
-+ if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) {
-+ FILE *p = NULL;
-+ FILE *n;
-+ FILE *stream;
-+
-+ __STDIO_THREADLOCK_OPENLIST_ADD;
-+ for (stream = _stdio_openlist; stream; stream = n) {
-+#warning walk the list and clear out all fclosed()d files
-+ n = stream->__nextopen;
-+#warning fix for nonatomic
-+ if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
-+ == (__FLAG_READONLY|__FLAG_WRITEONLY)
-+ ) { /* The file was closed so remove from the list. */
-+ if (!p) {
-+ _stdio_openlist = n;
-+ } else {
-+ p->__nextopen = n;
-+ }
-+ __STDIO_STREAM_FREE_FILE(stream);
-+ } else {
-+ p = stream;
-+ }
-+ }
-+ __STDIO_THREADUNLOCK_OPENLIST_DEL;
-+ }
-+ --_stdio_openlist_use_count;
-+ __STDIO_THREADUNLOCK_OPENLIST_DEL;
-+}
-+#endif
-
- int __fflush_unlocked(register FILE *stream)
- {
-@@ -60,23 +87,39 @@ int __fflush_unlocked(register FILE *str
- }
-
- if (!stream) { /* Flush all (lbf) writing streams. */
-- __STDIO_THREADLOCK_OPENLIST;
-- for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) {
-- MY_STDIO_THREADLOCK(stream);
-- if (!(((stream->__modeflags | bufmask)
-- ^ (__FLAG_WRITING|__FLAG_LBF)
-- ) & (__FLAG_WRITING|__MASK_BUFMODE))
-- ) {
-- if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
-- __STDIO_STREAM_DISABLE_PUTC(stream);
-- __STDIO_STREAM_CLEAR_WRITING(stream);
-- } else {
-- retval = EOF;
-+
-+ __STDIO_OPENLIST_INC_USE;
-+
-+ __STDIO_THREADLOCK_OPENLIST_ADD;
-+ stream = _stdio_openlist;
-+ __STDIO_THREADUNLOCK_OPENLIST_ADD;
-+
-+ while(stream) {
-+ /* We only care about currently writing streams and do not want to
-+ * block trying to obtain mutexes on non-writing streams. */
-+#warning fix for nonatomic
-+#warning unnecessary check if no threads
-+ if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */
-+ __MY_STDIO_THREADLOCK(stream);
-+ /* Need to check again once we have the lock. */
-+ if (!(((stream->__modeflags | bufmask)
-+ ^ (__FLAG_WRITING|__FLAG_LBF)
-+ ) & (__FLAG_WRITING|__MASK_BUFMODE))
-+ ) {
-+ if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
-+ __STDIO_STREAM_DISABLE_PUTC(stream);
-+ __STDIO_STREAM_CLEAR_WRITING(stream);
-+ } else {
-+ retval = EOF;
-+ }
- }
-+ __MY_STDIO_THREADUNLOCK(stream);
- }
-- MY_STDIO_THREADUNLOCK(stream);
-+ stream = stream->__nextopen;
- }
-- __STDIO_THREADUNLOCK_OPENLIST;
-+
-+ __STDIO_OPENLIST_DEC_USE;
-+
- } else if (__STDIO_STREAM_IS_WRITING(stream)) {
- if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
- __STDIO_STREAM_DISABLE_PUTC(stream);
-diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c
-index 0dcc7c2..3fad711 100644
---- a/libc/stdio/flockfile.c
-+++ b/libc/stdio/flockfile.c
-@@ -11,6 +11,6 @@ void flockfile(FILE *stream)
- {
- __STDIO_STREAM_VALIDATE(stream);
-
-- __STDIO_ALWAYS_THREADLOCK(stream);
-+ __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream);
- }
-
-diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c
-index 0eccaac..36b8488 100644
---- a/libc/stdio/freopen.c
-+++ b/libc/stdio/freopen.c
-@@ -42,6 +42,8 @@ FILE *freopen(const char * __restrict fi
-
- __STDIO_STREAM_VALIDATE(stream);
-
-+ __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */
-+
- /* First, flush and close, but don't deallocate, the stream. */
- /* This also removes the stream for the open file list. */
- dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
-@@ -57,9 +59,16 @@ FILE *freopen(const char * __restrict fi
-
- fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG);
-
-+#warning if fp is NULL, then we do not free file (but beware stdin,stdout,stderr)
-+ if (fp) {
-+ __STDIO_OPENLIST_DEC_DEL_CNT;
-+ }
-+
- /* Reset the allocation flags. */
- stream->__modeflags |= dynmode;
-
-+ __STDIO_OPENLIST_DEC_USE;
-+
- __STDIO_AUTO_THREADUNLOCK(stream);
-
- return fp;
-diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c
-index 7092f34..69385ce 100644
---- a/libc/stdio/ftello.c
-+++ b/libc/stdio/ftello.c
-@@ -48,7 +48,10 @@ OFFSET_TYPE FTELL(register FILE *stream)
-
- __STDIO_STREAM_VALIDATE(stream);
-
-- if ((__SEEK(stream, &pos, SEEK_CUR) < 0)
-+ if ((__SEEK(stream, &pos,
-+ ((__STDIO_STREAM_IS_WRITING(stream)
-+ && (stream->__modeflags & __FLAG_APPEND))
-+ ? SEEK_END : SEEK_CUR)) < 0)
- || (__stdio_adjust_position(stream, &pos) < 0)) {
- pos = -1;
- }
-diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c
-index d85b8ff..0d2e156 100644
---- a/libc/stdio/ftrylockfile.c
-+++ b/libc/stdio/ftrylockfile.c
-@@ -15,5 +15,5 @@ int ftrylockfile(FILE *stream)
- {
- __STDIO_STREAM_VALIDATE(stream);
-
-- return __STDIO_ALWAYS_THREADTRYLOCK(stream);
-+ return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream);
- }
-diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c
-index 048c093..2ddf097 100644
---- a/libc/stdio/funlockfile.c
-+++ b/libc/stdio/funlockfile.c
-@@ -11,5 +11,5 @@ void funlockfile(FILE *stream)
- {
- __STDIO_STREAM_VALIDATE(stream);
-
-- __STDIO_ALWAYS_THREADUNLOCK(stream);
-+ __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream);
- }
-diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c
-index c7887ad..ab8d296 100644
---- a/libc/stdio/popen.c
-+++ b/libc/stdio/popen.c
-@@ -14,6 +14,7 @@
- * Fix failure exit code for failed execve().
- */
-
-+#warning hmm... susv3 says "Pipe streams are byte-oriented."
-
- #include <stdio.h>
- #include <stdlib.h>
-@@ -21,6 +22,8 @@
- #include <unistd.h>
- #include <sys/wait.h>
-
-+#include <bits/uClibc_mutex.h>
-+
- /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */
- #include <sys/syscall.h>
- #if ! defined __NR_vfork
-@@ -29,19 +32,11 @@
- # define VFORK_UNLOCK ((void) 0)
- #endif
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK ((void) 0)
--# define UNLOCK ((void) 0)
--#endif
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- #ifndef VFORK_LOCK
--# define VFORK_LOCK LOCK
--# define VFORK_UNLOCK UNLOCK
-+# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock)
-+# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock)
- #endif
-
- struct popen_list_item {
-@@ -118,10 +113,10 @@ FILE *popen(const char *command, const c
- if (pid > 0) { /* Parent of vfork... */
- pi->pid = pid;
- pi->f = fp;
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- pi->next = popen_list;
- popen_list = pi;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- return fp;
- }
-@@ -136,6 +131,8 @@ FILE *popen(const char *command, const c
- return NULL;
- }
-
-+#warning is pclose correct wrt the new mutex semantics?
-+
- int pclose(FILE *stream)
- {
- struct popen_list_item *p;
-@@ -144,7 +141,7 @@ int pclose(FILE *stream)
-
- /* First, find the list entry corresponding to stream and remove it
- * from the list. Set p to the list item (NULL if not found). */
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if ((p = popen_list) != NULL) {
- if (p->f == stream) {
- popen_list = p->next;
-@@ -163,7 +160,7 @@ int pclose(FILE *stream)
- } while (1);
- }
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-
- if (p) {
- pid = p->pid; /* Save the pid we need */
-diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c
-index 3fe62c6..6d53ab1 100644
---- a/libc/stdio/setvbuf.c
-+++ b/libc/stdio/setvbuf.c
-@@ -75,8 +75,8 @@ int setvbuf(register FILE * __restrict s
- }
-
- stream->__modeflags |= alloc_flag;
-- stream->__bufstart = buf;
-- stream->__bufend = buf + size;
-+ stream->__bufstart = (unsigned char *) buf;
-+ stream->__bufend = (unsigned char *) buf + size;
- __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
- __STDIO_STREAM_DISABLE_GETC(stream);
- __STDIO_STREAM_DISABLE_PUTC(stream);
-diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c
-index 688ab7c..6d7664d 100644
---- a/libc/stdio/vasprintf.c
-+++ b/libc/stdio/vasprintf.c
-@@ -63,6 +63,8 @@ int vasprintf(char **__restrict buf, con
- free(*buf);
- *buf = NULL;
- }
-+ } else {
-+ rv = -1;
- }
- }
-
-diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c
-index de8362c..7cb707f 100644
---- a/libc/stdio/vdprintf.c
-+++ b/libc/stdio/vdprintf.c
-@@ -15,8 +15,8 @@ int vdprintf(int filedes, const char * _
- #ifdef __STDIO_BUFFERS
- char buf[64]; /* TODO: provide _optional_ buffering? */
-
-- f.__bufend = buf + sizeof(buf);
-- f.__bufstart = buf;
-+ f.__bufend = (unsigned char *) buf + sizeof(buf);
-+ f.__bufstart = (unsigned char *) buf;
- __STDIO_STREAM_DISABLE_GETC(&f);
- __STDIO_STREAM_DISABLE_PUTC(&f);
- __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f);
-diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
-index 10114f0..9214e3b 100644
---- a/libc/stdio/vfprintf.c
-+++ b/libc/stdio/vfprintf.c
-@@ -569,7 +569,7 @@ int _ppfs_init(register ppfs_t *ppfs, co
- ppfs->fmtpos = fmt0; /* rewind */
- }
-
--#ifdef NL_MAX_ARG
-+#ifdef NL_ARGMAX
- /* If we have positional args, make sure we know all the types. */
- {
- register int *p = ppfs->argtype;
-@@ -581,7 +581,7 @@ int _ppfs_init(register ppfs_t *ppfs, co
- ++p;
- }
- }
--#endif /* NL_MAX_ARG */
-+#endif /* NL_ARGMAX */
-
- return 0;
- }
-@@ -1214,7 +1214,7 @@ static size_t _fp_out_narrow(FILE *fp, i
- }
- len = buflen;
- }
-- return r + OUTNSTR(fp, (const char *) buf, len);
-+ return r + OUTNSTR(fp, (const unsigned char *) buf, len);
- }
-
- #endif /* __STDIO_PRINTF_FLOAT */
-diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c
-index 77c2cdc..9f69918 100644
---- a/libc/stdlib/abort.c
-+++ b/libc/stdlib/abort.c
-@@ -70,16 +70,9 @@ extern void _exit __P((int __status)) __
- static int been_there_done_that = 0;
-
- /* Be prepared in case multiple threads try to abort() */
--#ifdef __UCLIBC_HAS_THREADS__
--# include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock)
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+#include <bits/uClibc_mutex.h>
-
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- /* Cause an abnormal program termination with core-dump */
- void abort(void)
-@@ -87,7 +80,7 @@ void abort(void)
- sigset_t sigset;
-
- /* Make sure we acquire the lock before proceeding */
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock);
-
- /* Unmask SIGABRT to be sure we can get it */
- if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) {
-@@ -110,9 +103,9 @@ void abort(void)
- #endif
-
- abort_it:
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(mylock);
- raise(SIGABRT);
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock);
- }
-
- /* Still here? Try to remove any signal handlers */
-diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
-index 280f42c..b028068 100644
---- a/libc/stdlib/atexit.c
-+++ b/libc/stdlib/atexit.c
-@@ -40,17 +40,9 @@
- #include <stdlib.h>
- #include <errno.h>
-
-+#include <bits/uClibc_mutex.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--extern pthread_mutex_t mylock;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
--
-+__UCLIBC_MUTEX_EXTERN(__atexit_lock);
-
- typedef void (*aefuncp) (void); /* atexit function pointer */
- typedef void (*oefuncp) (int, void *); /* on_exit function pointer */
-@@ -90,8 +82,9 @@ extern struct exit_function __exit_funct
- int atexit(aefuncp func)
- {
- struct exit_function *efp;
-+ int rv = -1;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(__atexit_lock);
- if (func) {
- #ifdef __UCLIBC_DYNAMIC_ATEXIT__
- /* If we are out of function table slots, make some more */
-@@ -99,18 +92,16 @@ int atexit(aefuncp func)
- efp=realloc(__exit_function_table,
- (__exit_slots+20)*sizeof(struct exit_function));
- if (efp==NULL) {
-- UNLOCK;
- __set_errno(ENOMEM);
-- return -1;
-+ goto DONE;
- }
- __exit_function_table = efp;
- __exit_slots+=20;
- }
- #else
- if (__exit_count >= __UCLIBC_MAX_ATEXIT) {
-- UNLOCK;
- __set_errno(ENOMEM);
-- return -1;
-+ goto DONE;
- }
- #endif
- __exit_cleanup = __exit_handler; /* enable cleanup */
-@@ -118,8 +109,12 @@ int atexit(aefuncp func)
- efp->type = ef_atexit;
- efp->funcs.atexit = func;
- }
-- UNLOCK;
-- return 0;
-+
-+ rv = 0;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(__atexit_lock);
-+ return rv;
- }
- #endif
-
-@@ -133,8 +128,9 @@ int atexit(aefuncp func)
- int on_exit(oefuncp func, void *arg)
- {
- struct exit_function *efp;
-+ int rv = -1;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(__atexit_lock);
- if (func) {
- #ifdef __UCLIBC_DYNAMIC_ATEXIT__
- /* If we are out of function table slots, make some more */
-@@ -142,18 +138,16 @@ int on_exit(oefuncp func, void *arg)
- efp=realloc(__exit_function_table,
- (__exit_slots+20)*sizeof(struct exit_function));
- if (efp==NULL) {
-- UNLOCK;
- __set_errno(ENOMEM);
-- return -1;
-+ goto DONE;
- }
- __exit_function_table=efp;
- __exit_slots+=20;
- }
- #else
- if (__exit_count >= __UCLIBC_MAX_ATEXIT) {
-- UNLOCK;
- __set_errno(ENOMEM);
-- return -1;
-+ goto DONE;
- }
- #endif
-
-@@ -163,8 +157,12 @@ int on_exit(oefuncp func, void *arg)
- efp->funcs.on_exit.func = func;
- efp->funcs.on_exit.arg = arg;
- }
-- UNLOCK;
-- return 0;
-+
-+ rv = 0;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(__atexit_lock);
-+ return rv;
- }
- #endif
-
-@@ -214,9 +212,8 @@ void __exit_handler(int status)
- #ifdef L_exit
- extern void weak_function _stdio_term(void);
- void (*__exit_cleanup) (int) = 0;
--#ifdef __UCLIBC_HAS_THREADS__
--pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--#endif
-+
-+__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- #ifdef __UCLIBC_CTOR_DTOR__
- extern void (*__app_fini)(void);
-@@ -229,11 +226,11 @@ extern void (*__rtld_fini)(void);
- void exit(int rv)
- {
- /* Perform exit-specific cleanup (atexit and on_exit) */
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(__atexit_lock);
- if (__exit_cleanup) {
- __exit_cleanup(rv);
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(__atexit_lock);
-
- #ifdef __UCLIBC_CTOR_DTOR__
- if (__app_fini != NULL)
-diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c
-index ed14c37..519a875 100644
---- a/libc/stdlib/malloc-simple/alloc.c
-+++ b/libc/stdlib/malloc-simple/alloc.c
-@@ -108,15 +108,14 @@ void free(void *ptr)
- #endif
-
- #ifdef L_memalign
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--# define LOCK __pthread_mutex_lock(&__malloc_lock)
--# define UNLOCK __pthread_mutex_unlock(&__malloc_lock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+
-+#include <bits/uClibc_mutex.h>
-+
-+__UCLIBC_MUTEX_EXTERN(__malloc_lock);
-+
-+#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
-+#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
-+
-
- /* List of blocks allocated with memalign or valloc */
- struct alignlist
-@@ -135,7 +134,7 @@ int __libc_free_aligned(void *ptr)
- if (ptr == NULL)
- return 0;
-
-- LOCK;
-+ __MALLOC_LOCK;
- for (l = _aligned_blocks; l != NULL; l = l->next) {
- if (l->aligned == ptr) {
- /* Mark the block as free */
-@@ -146,7 +145,7 @@ int __libc_free_aligned(void *ptr)
- return 1;
- }
- }
-- UNLOCK;
-+ __MALLOC_UNLOCK;
- return 0;
- }
- void * memalign (size_t alignment, size_t size)
-@@ -159,10 +158,10 @@ void * memalign (size_t alignment, size_
- return NULL;
-
- adj = (unsigned long int) ((unsigned long int) ((char *) result -
-- (char *) NULL)) % alignment;
-+ (char *) NULL)) % alignment;
- if (adj != 0) {
- struct alignlist *l;
-- LOCK;
-+ __MALLOC_LOCK;
- for (l = _aligned_blocks; l != NULL; l = l->next)
- if (l->aligned == NULL)
- /* This slot is free. Use it. */
-@@ -171,15 +170,16 @@ void * memalign (size_t alignment, size_
- l = (struct alignlist *) malloc (sizeof (struct alignlist));
- if (l == NULL) {
- free(result);
-- UNLOCK;
-- return NULL;
-+ result = NULL;
-+ goto DONE;
- }
- l->next = _aligned_blocks;
- _aligned_blocks = l;
- }
- l->exact = result;
- result = l->aligned = (char *) result + alignment - adj;
-- UNLOCK;
-+ DONE:
-+ __MALLOC_UNLOCK;
- }
-
- return result;
-diff --git a/libc/stdlib/malloc-standard/calloc.c b/libc/stdlib/malloc-standard/calloc.c
-index a67dad7..4277954 100644
---- a/libc/stdlib/malloc-standard/calloc.c
-+++ b/libc/stdlib/malloc-standard/calloc.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -31,63 +31,63 @@ void* calloc(size_t n_elements, size_t e
- * to fall through and call malloc(0) */
- size = n_elements * elem_size;
- if (n_elements && elem_size != (size / n_elements)) {
-- __set_errno(ENOMEM);
-- return NULL;
-+ __set_errno(ENOMEM);
-+ return NULL;
- }
-
-- LOCK;
-+ __MALLOC_LOCK;
- mem = malloc(size);
- if (mem != 0) {
-- p = mem2chunk(mem);
-+ p = mem2chunk(mem);
-
-- if (!chunk_is_mmapped(p))
-- {
-- /*
-- Unroll clear of <= 36 bytes (72 if 8byte sizes)
-- We know that contents have an odd number of
-- size_t-sized words; minimally 3.
-- */
--
-- d = (size_t*)mem;
-- clearsize = chunksize(p) - (sizeof(size_t));
-- nclears = clearsize / sizeof(size_t);
-- assert(nclears >= 3);
--
-- if (nclears > 9)
-- memset(d, 0, clearsize);
--
-- else {
-- *(d+0) = 0;
-- *(d+1) = 0;
-- *(d+2) = 0;
-- if (nclears > 4) {
-- *(d+3) = 0;
-- *(d+4) = 0;
-- if (nclears > 6) {
-- *(d+5) = 0;
-- *(d+6) = 0;
-- if (nclears > 8) {
-- *(d+7) = 0;
-- *(d+8) = 0;
-+ if (!chunk_is_mmapped(p))
-+ {
-+ /*
-+ Unroll clear of <= 36 bytes (72 if 8byte sizes)
-+ We know that contents have an odd number of
-+ size_t-sized words; minimally 3.
-+ */
-+
-+ d = (size_t*)mem;
-+ clearsize = chunksize(p) - (sizeof(size_t));
-+ nclears = clearsize / sizeof(size_t);
-+ assert(nclears >= 3);
-+
-+ if (nclears > 9)
-+ memset(d, 0, clearsize);
-+
-+ else {
-+ *(d+0) = 0;
-+ *(d+1) = 0;
-+ *(d+2) = 0;
-+ if (nclears > 4) {
-+ *(d+3) = 0;
-+ *(d+4) = 0;
-+ if (nclears > 6) {
-+ *(d+5) = 0;
-+ *(d+6) = 0;
-+ if (nclears > 8) {
-+ *(d+7) = 0;
-+ *(d+8) = 0;
-+ }
-+ }
-+ }
-+ }
- }
-- }
-- }
-- }
-- }
- #if 0
-- else
-- {
-- /* Standard unix mmap using /dev/zero clears memory so calloc
-- * doesn't need to actually zero anything....
-- */
-- d = (size_t*)mem;
-- /* Note the additional (sizeof(size_t)) */
-- clearsize = chunksize(p) - 2*(sizeof(size_t));
-- memset(d, 0, clearsize);
-- }
-+ else
-+ {
-+ /* Standard unix mmap using /dev/zero clears memory so calloc
-+ * doesn't need to actually zero anything....
-+ */
-+ d = (size_t*)mem;
-+ /* Note the additional (sizeof(size_t)) */
-+ clearsize = chunksize(p) - 2*(sizeof(size_t));
-+ memset(d, 0, clearsize);
-+ }
- #endif
- }
-- UNLOCK;
-+ __MALLOC_UNLOCK;
- return mem;
- }
-
-diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c
-index 94e1d65..4e08ef7 100644
---- a/libc/stdlib/malloc-standard/free.c
-+++ b/libc/stdlib/malloc-standard/free.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -42,71 +42,71 @@ static int __malloc_trim(size_t pad, mst
-
- if (extra > 0) {
-
-- /*
-- Only proceed if end of memory is where we last set it.
-- This avoids problems if there were foreign sbrk calls.
-- */
-- current_brk = (char*)(MORECORE(0));
-- if (current_brk == (char*)(av->top) + top_size) {
--
-- /*
-- Attempt to release memory. We ignore MORECORE return value,
-- and instead call again to find out where new end of memory is.
-- This avoids problems if first call releases less than we asked,
-- of if failure somehow altered brk value. (We could still
-- encounter problems if it altered brk in some very bad way,
-- but the only thing we can do is adjust anyway, which will cause
-- some downstream failure.)
-- */
--
-- MORECORE(-extra);
-- new_brk = (char*)(MORECORE(0));
--
-- if (new_brk != (char*)MORECORE_FAILURE) {
-- released = (long)(current_brk - new_brk);
--
-- if (released != 0) {
-- /* Success. Adjust top. */
-- av->sbrked_mem -= released;
-- set_head(av->top, (top_size - released) | PREV_INUSE);
-- check_malloc_state();
-- return 1;
-+ /*
-+ Only proceed if end of memory is where we last set it.
-+ This avoids problems if there were foreign sbrk calls.
-+ */
-+ current_brk = (char*)(MORECORE(0));
-+ if (current_brk == (char*)(av->top) + top_size) {
-+
-+ /*
-+ Attempt to release memory. We ignore MORECORE return value,
-+ and instead call again to find out where new end of memory is.
-+ This avoids problems if first call releases less than we asked,
-+ of if failure somehow altered brk value. (We could still
-+ encounter problems if it altered brk in some very bad way,
-+ but the only thing we can do is adjust anyway, which will cause
-+ some downstream failure.)
-+ */
-+
-+ MORECORE(-extra);
-+ new_brk = (char*)(MORECORE(0));
-+
-+ if (new_brk != (char*)MORECORE_FAILURE) {
-+ released = (long)(current_brk - new_brk);
-+
-+ if (released != 0) {
-+ /* Success. Adjust top. */
-+ av->sbrked_mem -= released;
-+ set_head(av->top, (top_size - released) | PREV_INUSE);
-+ check_malloc_state();
-+ return 1;
-+ }
-+ }
- }
-- }
-- }
- }
- return 0;
- }
-
- /* ------------------------- malloc_trim -------------------------
-- malloc_trim(size_t pad);
-+ malloc_trim(size_t pad);
-
-- If possible, gives memory back to the system (via negative
-- arguments to sbrk) if there is unused memory at the `high' end of
-- the malloc pool. You can call this after freeing large blocks of
-- memory to potentially reduce the system-level memory requirements
-- of a program. However, it cannot guarantee to reduce memory. Under
-- some allocation patterns, some large free blocks of memory will be
-- locked between two used chunks, so they cannot be given back to
-- the system.
--
-- The `pad' argument to malloc_trim represents the amount of free
-- trailing space to leave untrimmed. If this argument is zero,
-- only the minimum amount of memory to maintain internal data
-- structures will be left (one page or less). Non-zero arguments
-- can be supplied to maintain enough trailing space to service
-- future expected allocations without having to re-obtain memory
-- from the system.
--
-- Malloc_trim returns 1 if it actually released any memory, else 0.
-- On systems that do not support "negative sbrks", it will always
-- return 0.
-+ If possible, gives memory back to the system (via negative
-+ arguments to sbrk) if there is unused memory at the `high' end of
-+ the malloc pool. You can call this after freeing large blocks of
-+ memory to potentially reduce the system-level memory requirements
-+ of a program. However, it cannot guarantee to reduce memory. Under
-+ some allocation patterns, some large free blocks of memory will be
-+ locked between two used chunks, so they cannot be given back to
-+ the system.
-+
-+ The `pad' argument to malloc_trim represents the amount of free
-+ trailing space to leave untrimmed. If this argument is zero,
-+ only the minimum amount of memory to maintain internal data
-+ structures will be left (one page or less). Non-zero arguments
-+ can be supplied to maintain enough trailing space to service
-+ future expected allocations without having to re-obtain memory
-+ from the system.
-+
-+ Malloc_trim returns 1 if it actually released any memory, else 0.
-+ On systems that do not support "negative sbrks", it will always
-+ return 0.
- */
- int malloc_trim(size_t pad)
- {
-- mstate av = get_malloc_state();
-- __malloc_consolidate(av);
-- return __malloc_trim(pad, av);
-+ mstate av = get_malloc_state();
-+ __malloc_consolidate(av);
-+ return __malloc_trim(pad, av);
- }
-
- /*
-@@ -125,8 +125,8 @@ static void malloc_init_state(mstate av)
-
- /* Establish circular links for normal bins */
- for (i = 1; i < NBINS; ++i) {
-- bin = bin_at(av,i);
-- bin->fd = bin->bk = bin;
-+ bin = bin_at(av,i);
-+ bin->fd = bin->bk = bin;
- }
-
- av->top_pad = DEFAULT_TOP_PAD;
-@@ -157,15 +157,15 @@ static void malloc_init_state(mstate av)
-
- /* ------------------------- __malloc_consolidate -------------------------
-
-- __malloc_consolidate is a specialized version of free() that tears
-- down chunks held in fastbins. Free itself cannot be used for this
-- purpose since, among other things, it might place chunks back onto
-- fastbins. So, instead, we need to use a minor variant of the same
-- code.
--
-- Also, because this routine needs to be called the first time through
-- malloc anyway, it turns out to be the perfect place to trigger
-- initialization code.
-+__malloc_consolidate is a specialized version of free() that tears
-+down chunks held in fastbins. Free itself cannot be used for this
-+purpose since, among other things, it might place chunks back onto
-+fastbins. So, instead, we need to use a minor variant of the same
-+code.
-+
-+Also, because this routine needs to be called the first time through
-+malloc anyway, it turns out to be the perfect place to trigger
-+initialization code.
- */
- void __malloc_consolidate(mstate av)
- {
-@@ -186,78 +186,78 @@ void __malloc_consolidate(mstate av)
- mchunkptr fwd;
-
- /*
-- If max_fast is 0, we know that av hasn't
-- yet been initialized, in which case do so below
-- */
-+ If max_fast is 0, we know that av hasn't
-+ yet been initialized, in which case do so below
-+ */
-
- if (av->max_fast != 0) {
-- clear_fastchunks(av);
-+ clear_fastchunks(av);
-
-- unsorted_bin = unsorted_chunks(av);
-+ unsorted_bin = unsorted_chunks(av);
-
-- /*
-- Remove each chunk from fast bin and consolidate it, placing it
-- then in unsorted bin. Among other reasons for doing this,
-- placing in unsorted bin avoids needing to calculate actual bins
-- until malloc is sure that chunks aren't immediately going to be
-- reused anyway.
-- */
--
-- maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
-- fb = &(av->fastbins[0]);
-- do {
-- if ( (p = *fb) != 0) {
-- *fb = 0;
-+ /*
-+ Remove each chunk from fast bin and consolidate it, placing it
-+ then in unsorted bin. Among other reasons for doing this,
-+ placing in unsorted bin avoids needing to calculate actual bins
-+ until malloc is sure that chunks aren't immediately going to be
-+ reused anyway.
-+ */
-
-+ maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
-+ fb = &(av->fastbins[0]);
- do {
-- check_inuse_chunk(p);
-- nextp = p->fd;
-+ if ( (p = *fb) != 0) {
-+ *fb = 0;
-
-- /* Slightly streamlined version of consolidation code in free() */
-- size = p->size & ~PREV_INUSE;
-- nextchunk = chunk_at_offset(p, size);
-- nextsize = chunksize(nextchunk);
-+ do {
-+ check_inuse_chunk(p);
-+ nextp = p->fd;
-+
-+ /* Slightly streamlined version of consolidation code in free() */
-+ size = p->size & ~PREV_INUSE;
-+ nextchunk = chunk_at_offset(p, size);
-+ nextsize = chunksize(nextchunk);
-+
-+ if (!prev_inuse(p)) {
-+ prevsize = p->prev_size;
-+ size += prevsize;
-+ p = chunk_at_offset(p, -((long) prevsize));
-+ unlink(p, bck, fwd);
-+ }
-+
-+ if (nextchunk != av->top) {
-+ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-+ set_head(nextchunk, nextsize);
-+
-+ if (!nextinuse) {
-+ size += nextsize;
-+ unlink(nextchunk, bck, fwd);
-+ }
-+
-+ first_unsorted = unsorted_bin->fd;
-+ unsorted_bin->fd = p;
-+ first_unsorted->bk = p;
-+
-+ set_head(p, size | PREV_INUSE);
-+ p->bk = unsorted_bin;
-+ p->fd = first_unsorted;
-+ set_foot(p, size);
-+ }
-+
-+ else {
-+ size += nextsize;
-+ set_head(p, size | PREV_INUSE);
-+ av->top = p;
-+ }
-
-- if (!prev_inuse(p)) {
-- prevsize = p->prev_size;
-- size += prevsize;
-- p = chunk_at_offset(p, -((long) prevsize));
-- unlink(p, bck, fwd);
-- }
-+ } while ( (p = nextp) != 0);
-
-- if (nextchunk != av->top) {
-- nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-- set_head(nextchunk, nextsize);
--
-- if (!nextinuse) {
-- size += nextsize;
-- unlink(nextchunk, bck, fwd);
- }
--
-- first_unsorted = unsorted_bin->fd;
-- unsorted_bin->fd = p;
-- first_unsorted->bk = p;
--
-- set_head(p, size | PREV_INUSE);
-- p->bk = unsorted_bin;
-- p->fd = first_unsorted;
-- set_foot(p, size);
-- }
--
-- else {
-- size += nextsize;
-- set_head(p, size | PREV_INUSE);
-- av->top = p;
-- }
--
-- } while ( (p = nextp) != 0);
--
-- }
-- } while (fb++ != maxfb);
-+ } while (fb++ != maxfb);
- }
- else {
-- malloc_init_state(av);
-- check_malloc_state();
-+ malloc_init_state(av);
-+ check_malloc_state();
- }
- }
-
-@@ -279,9 +279,9 @@ void free(void* mem)
-
- /* free(0) has no effect */
- if (mem == NULL)
-- return;
-+ return;
-
-- LOCK;
-+ __MALLOC_LOCK;
- av = get_malloc_state();
- p = mem2chunk(mem);
- size = chunksize(p);
-@@ -289,9 +289,9 @@ void free(void* mem)
- check_inuse_chunk(p);
-
- /*
-- If eligible, place chunk on a fastbin so it can be found
-- and used quickly in malloc.
-- */
-+ If eligible, place chunk on a fastbin so it can be found
-+ and used quickly in malloc.
-+ */
-
- if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
-
-@@ -300,114 +300,114 @@ void free(void* mem)
- bordering top into fastbins */
- && (chunk_at_offset(p, size) != av->top)
- #endif
-- ) {
-+ ) {
-
-- set_fastchunks(av);
-- fb = &(av->fastbins[fastbin_index(size)]);
-- p->fd = *fb;
-- *fb = p;
-+ set_fastchunks(av);
-+ fb = &(av->fastbins[fastbin_index(size)]);
-+ p->fd = *fb;
-+ *fb = p;
- }
-
- /*
-- Consolidate other non-mmapped chunks as they arrive.
-- */
-+ Consolidate other non-mmapped chunks as they arrive.
-+ */
-
- else if (!chunk_is_mmapped(p)) {
-- set_anychunks(av);
-+ set_anychunks(av);
-+
-+ nextchunk = chunk_at_offset(p, size);
-+ nextsize = chunksize(nextchunk);
-+
-+ /* consolidate backward */
-+ if (!prev_inuse(p)) {
-+ prevsize = p->prev_size;
-+ size += prevsize;
-+ p = chunk_at_offset(p, -((long) prevsize));
-+ unlink(p, bck, fwd);
-+ }
-+
-+ if (nextchunk != av->top) {
-+ /* get and clear inuse bit */
-+ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-+ set_head(nextchunk, nextsize);
-+
-+ /* consolidate forward */
-+ if (!nextinuse) {
-+ unlink(nextchunk, bck, fwd);
-+ size += nextsize;
-+ }
-+
-+ /*
-+ Place the chunk in unsorted chunk list. Chunks are
-+ not placed into regular bins until after they have
-+ been given one chance to be used in malloc.
-+ */
-+
-+ bck = unsorted_chunks(av);
-+ fwd = bck->fd;
-+ p->bk = bck;
-+ p->fd = fwd;
-+ bck->fd = p;
-+ fwd->bk = p;
-
-- nextchunk = chunk_at_offset(p, size);
-- nextsize = chunksize(nextchunk);
-+ set_head(p, size | PREV_INUSE);
-+ set_foot(p, size);
-+
-+ check_free_chunk(p);
-+ }
-+
-+ /*
-+ If the chunk borders the current high end of memory,
-+ consolidate into top
-+ */
-
-- /* consolidate backward */
-- if (!prev_inuse(p)) {
-- prevsize = p->prev_size;
-- size += prevsize;
-- p = chunk_at_offset(p, -((long) prevsize));
-- unlink(p, bck, fwd);
-- }
--
-- if (nextchunk != av->top) {
-- /* get and clear inuse bit */
-- nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-- set_head(nextchunk, nextsize);
--
-- /* consolidate forward */
-- if (!nextinuse) {
-- unlink(nextchunk, bck, fwd);
-- size += nextsize;
-- }
--
-- /*
-- Place the chunk in unsorted chunk list. Chunks are
-- not placed into regular bins until after they have
-- been given one chance to be used in malloc.
-- */
--
-- bck = unsorted_chunks(av);
-- fwd = bck->fd;
-- p->bk = bck;
-- p->fd = fwd;
-- bck->fd = p;
-- fwd->bk = p;
--
-- set_head(p, size | PREV_INUSE);
-- set_foot(p, size);
--
-- check_free_chunk(p);
-- }
--
-- /*
-- If the chunk borders the current high end of memory,
-- consolidate into top
-- */
--
-- else {
-- size += nextsize;
-- set_head(p, size | PREV_INUSE);
-- av->top = p;
-- check_chunk(p);
-- }
--
-- /*
-- If freeing a large space, consolidate possibly-surrounding
-- chunks. Then, if the total unused topmost memory exceeds trim
-- threshold, ask malloc_trim to reduce top.
--
-- Unless max_fast is 0, we don't know if there are fastbins
-- bordering top, so we cannot tell for sure whether threshold
-- has been reached unless fastbins are consolidated. But we
-- don't want to consolidate on each free. As a compromise,
-- consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
-- is reached.
-- */
--
-- if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
-- if (have_fastchunks(av))
-- __malloc_consolidate(av);
--
-- if ((unsigned long)(chunksize(av->top)) >=
-- (unsigned long)(av->trim_threshold))
-- __malloc_trim(av->top_pad, av);
-- }
-+ else {
-+ size += nextsize;
-+ set_head(p, size | PREV_INUSE);
-+ av->top = p;
-+ check_chunk(p);
-+ }
-+
-+ /*
-+ If freeing a large space, consolidate possibly-surrounding
-+ chunks. Then, if the total unused topmost memory exceeds trim
-+ threshold, ask malloc_trim to reduce top.
-+
-+ Unless max_fast is 0, we don't know if there are fastbins
-+ bordering top, so we cannot tell for sure whether threshold
-+ has been reached unless fastbins are consolidated. But we
-+ don't want to consolidate on each free. As a compromise,
-+ consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
-+ is reached.
-+ */
-+
-+ if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
-+ if (have_fastchunks(av))
-+ __malloc_consolidate(av);
-+
-+ if ((unsigned long)(chunksize(av->top)) >=
-+ (unsigned long)(av->trim_threshold))
-+ __malloc_trim(av->top_pad, av);
-+ }
-
- }
- /*
-- If the chunk was allocated via mmap, release via munmap()
-- Note that if HAVE_MMAP is false but chunk_is_mmapped is
-- true, then user must have overwritten memory. There's nothing
-- we can do to catch this error unless DEBUG is set, in which case
-- check_inuse_chunk (above) will have triggered error.
-- */
-+ If the chunk was allocated via mmap, release via munmap()
-+ Note that if HAVE_MMAP is false but chunk_is_mmapped is
-+ true, then user must have overwritten memory. There's nothing
-+ we can do to catch this error unless DEBUG is set, in which case
-+ check_inuse_chunk (above) will have triggered error.
-+ */
-
- else {
-- int ret;
-- size_t offset = p->prev_size;
-- av->n_mmaps--;
-- av->mmapped_mem -= (size + offset);
-- ret = munmap((char*)p - offset, size + offset);
-- /* munmap returns non-zero on failure */
-- assert(ret == 0);
-+ int ret;
-+ size_t offset = p->prev_size;
-+ av->n_mmaps--;
-+ av->mmapped_mem -= (size + offset);
-+ ret = munmap((char*)p - offset, size + offset);
-+ /* munmap returns non-zero on failure */
-+ assert(ret == 0);
- }
-- UNLOCK;
-+ __MALLOC_UNLOCK;
- }
-
-diff --git a/libc/stdlib/malloc-standard/mallinfo.c b/libc/stdlib/malloc-standard/mallinfo.c
-index 51ac423..1e0875c 100644
---- a/libc/stdlib/malloc-standard/mallinfo.c
-+++ b/libc/stdlib/malloc-standard/mallinfo.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -30,11 +30,11 @@ struct mallinfo mallinfo(void)
- int nblocks;
- int nfastblocks;
-
-- LOCK;
-+ __MALLOC_LOCK;
- av = get_malloc_state();
- /* Ensure initialization */
- if (av->top == 0) {
-- __malloc_consolidate(av);
-+ __malloc_consolidate(av);
- }
-
- check_malloc_state();
-@@ -48,21 +48,21 @@ struct mallinfo mallinfo(void)
- fastavail = 0;
-
- for (i = 0; i < NFASTBINS; ++i) {
-- for (p = av->fastbins[i]; p != 0; p = p->fd) {
-- ++nfastblocks;
-- fastavail += chunksize(p);
-- }
-+ for (p = av->fastbins[i]; p != 0; p = p->fd) {
-+ ++nfastblocks;
-+ fastavail += chunksize(p);
-+ }
- }
-
- avail += fastavail;
-
- /* traverse regular bins */
- for (i = 1; i < NBINS; ++i) {
-- b = bin_at(av, i);
-- for (p = last(b); p != b; p = p->bk) {
-- ++nblocks;
-- avail += chunksize(p);
-- }
-+ b = bin_at(av, i);
-+ for (p = last(b); p != b; p = p->bk) {
-+ ++nblocks;
-+ avail += chunksize(p);
-+ }
- }
-
- mi.smblks = nfastblocks;
-@@ -75,7 +75,7 @@ struct mallinfo mallinfo(void)
- mi.fsmblks = fastavail;
- mi.keepcost = chunksize(av->top);
- mi.usmblks = av->max_total_mem;
-- UNLOCK;
-+ __MALLOC_UNLOCK;
- return mi;
- }
-
-@@ -84,23 +84,40 @@ void malloc_stats(FILE *file)
- struct mallinfo mi;
-
- if (file==NULL) {
-- file = stderr;
-+ file = stderr;
- }
-
- mi = mallinfo();
-- fprintf(file, "total bytes allocated = %10u\n", (unsigned int)(mi.arena + mi.hblkhd));
-- fprintf(file, "total bytes in use bytes = %10u\n", (unsigned int)(mi.uordblks + mi.hblkhd));
-- fprintf(file, "total non-mmapped bytes allocated = %10d\n", mi.arena);
-- fprintf(file, "number of mmapped regions = %10d\n", mi.hblks);
-- fprintf(file, "total allocated mmap space = %10d\n", mi.hblkhd);
-- fprintf(file, "total allocated sbrk space = %10d\n", mi.uordblks);
-+ fprintf(file,
-+ "total bytes allocated = %10u\n"
-+ "total bytes in use bytes = %10u\n"
-+ "total non-mmapped bytes allocated = %10d\n"
-+ "number of mmapped regions = %10d\n"
-+ "total allocated mmap space = %10d\n"
-+ "total allocated sbrk space = %10d\n"
- #if 0
-- fprintf(file, "number of free chunks = %10d\n", mi.ordblks);
-- fprintf(file, "number of fastbin blocks = %10d\n", mi.smblks);
-- fprintf(file, "space in freed fastbin blocks = %10d\n", mi.fsmblks);
-+ "number of free chunks = %10d\n"
-+ "number of fastbin blocks = %10d\n"
-+ "space in freed fastbin blocks = %10d\n"
- #endif
-- fprintf(file, "maximum total allocated space = %10d\n", mi.usmblks);
-- fprintf(file, "total free space = %10d\n", mi.fordblks);
-- fprintf(file, "memory releasable via malloc_trim = %10d\n", mi.keepcost);
-+ "maximum total allocated space = %10d\n"
-+ "total free space = %10d\n"
-+ "memory releasable via malloc_trim = %10d\n",
-+
-+ (unsigned int)(mi.arena + mi.hblkhd),
-+ (unsigned int)(mi.uordblks + mi.hblkhd),
-+ mi.arena,
-+ mi.hblks,
-+ mi.hblkhd,
-+ mi.uordblks,
-+#if 0
-+ mi.ordblks,
-+ mi.smblks,
-+ mi.fsmblks,
-+#endif
-+ mi.usmblks,
-+ mi.fordblks,
-+ mi.keepcost
-+ );
- }
-
-diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c
-index 7025e83..60494a0 100644
---- a/libc/stdlib/malloc-standard/malloc.c
-+++ b/libc/stdlib/malloc-standard/malloc.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -17,17 +17,14 @@
- #define _GNU_SOURCE
- #include "malloc.h"
-
--
--#ifdef __UCLIBC_HAS_THREADS__
--pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--#endif
-+__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- /*
-- There is exactly one instance of this struct in this malloc.
-- If you are adapting this malloc in a way that does NOT use a static
-- malloc_state, you MUST explicitly zero-fill it before using. This
-- malloc relies on the property that malloc_state is initialized to
-- all zeroes (as is true of C statics).
-+ There is exactly one instance of this struct in this malloc.
-+ If you are adapting this malloc in a way that does NOT use a static
-+ malloc_state, you MUST explicitly zero-fill it before using. This
-+ malloc relies on the property that malloc_state is initialized to
-+ all zeroes (as is true of C statics).
- */
- struct malloc_state __malloc_state; /* never directly referenced */
-
-@@ -77,30 +74,30 @@ void __do_check_chunk(mchunkptr p)
-
- if (!chunk_is_mmapped(p)) {
-
-- /* Has legal address ... */
-- if (p != av->top) {
-- if (contiguous(av)) {
-- assert(((char*)p) >= min_address);
-- assert(((char*)p + sz) <= ((char*)(av->top)));
-- }
-- }
-- else {
-- /* top size is always at least MINSIZE */
-- assert((unsigned long)(sz) >= MINSIZE);
-- /* top predecessor always marked inuse */
-- assert(prev_inuse(p));
-- }
-+ /* Has legal address ... */
-+ if (p != av->top) {
-+ if (contiguous(av)) {
-+ assert(((char*)p) >= min_address);
-+ assert(((char*)p + sz) <= ((char*)(av->top)));
-+ }
-+ }
-+ else {
-+ /* top size is always at least MINSIZE */
-+ assert((unsigned long)(sz) >= MINSIZE);
-+ /* top predecessor always marked inuse */
-+ assert(prev_inuse(p));
-+ }
-
- }
- else {
-- /* address is outside main heap */
-- if (contiguous(av) && av->top != initial_top(av)) {
-- assert(((char*)p) < min_address || ((char*)p) > max_address);
-- }
-- /* chunk is page-aligned */
-- assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);
-- /* mem is aligned */
-- assert(aligned_OK(chunk2mem(p)));
-+ /* address is outside main heap */
-+ if (contiguous(av) && av->top != initial_top(av)) {
-+ assert(((char*)p) < min_address || ((char*)p) > max_address);
-+ }
-+ /* chunk is page-aligned */
-+ assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);
-+ /* mem is aligned */
-+ assert(aligned_OK(chunk2mem(p)));
- }
- }
-
-@@ -121,21 +118,21 @@ void __do_check_free_chunk(mchunkptr p)
-
- /* Unless a special marker, must have OK fields */
- if ((unsigned long)(sz) >= MINSIZE)
-- {
-- assert((sz & MALLOC_ALIGN_MASK) == 0);
-- assert(aligned_OK(chunk2mem(p)));
-- /* ... matching footer field */
-- assert(next->prev_size == sz);
-- /* ... and is fully consolidated */
-- assert(prev_inuse(p));
-- assert (next == av->top || inuse(next));
--
-- /* ... and has minimally sane links */
-- assert(p->fd->bk == p);
-- assert(p->bk->fd == p);
-- }
-+ {
-+ assert((sz & MALLOC_ALIGN_MASK) == 0);
-+ assert(aligned_OK(chunk2mem(p)));
-+ /* ... matching footer field */
-+ assert(next->prev_size == sz);
-+ /* ... and is fully consolidated */
-+ assert(prev_inuse(p));
-+ assert (next == av->top || inuse(next));
-+
-+ /* ... and has minimally sane links */
-+ assert(p->fd->bk == p);
-+ assert(p->bk->fd == p);
-+ }
- else /* markers are always of size (sizeof(size_t)) */
-- assert(sz == (sizeof(size_t)));
-+ assert(sz == (sizeof(size_t)));
- }
-
- /* Properties of inuse chunks */
-@@ -146,7 +143,7 @@ void __do_check_inuse_chunk(mchunkptr p)
- __do_check_chunk(p);
-
- if (chunk_is_mmapped(p))
-- return; /* mmapped chunks have no next/prev */
-+ return; /* mmapped chunks have no next/prev */
-
- /* Check whether it claims to be in use ... */
- assert(inuse(p));
-@@ -156,20 +153,20 @@ void __do_check_inuse_chunk(mchunkptr p)
- /* ... and is surrounded by OK chunks.
- Since more things can be checked with free chunks than inuse ones,
- if an inuse chunk borders them and debug is on, it's worth doing them.
-- */
-+ */
- if (!prev_inuse(p)) {
-- /* Note that we cannot even look at prev unless it is not inuse */
-- mchunkptr prv = prev_chunk(p);
-- assert(next_chunk(prv) == p);
-- __do_check_free_chunk(prv);
-+ /* Note that we cannot even look at prev unless it is not inuse */
-+ mchunkptr prv = prev_chunk(p);
-+ assert(next_chunk(prv) == p);
-+ __do_check_free_chunk(prv);
- }
-
- if (next == av->top) {
-- assert(prev_inuse(next));
-- assert(chunksize(next) >= MINSIZE);
-+ assert(prev_inuse(next));
-+ assert(chunksize(next) >= MINSIZE);
- }
- else if (!inuse(next))
-- __do_check_free_chunk(next);
-+ __do_check_free_chunk(next);
- }
-
- /* Properties of chunks recycled from fastbins */
-@@ -198,14 +195,14 @@ void __do_check_malloced_chunk(mchunkptr
- __do_check_remalloced_chunk(p, s);
-
- /*
-- ... plus, must obey implementation invariant that prev_inuse is
-- always true of any allocated chunk; i.e., that each allocated
-- chunk borders either a previously allocated and still in-use
-- chunk, or the base of its memory arena. This is ensured
-- by making all allocations from the the `lowest' part of any found
-- chunk. This does not necessarily hold however for chunks
-- recycled via fastbins.
-- */
-+ ... plus, must obey implementation invariant that prev_inuse is
-+ always true of any allocated chunk; i.e., that each allocated
-+ chunk borders either a previously allocated and still in-use
-+ chunk, or the base of its memory arena. This is ensured
-+ by making all allocations from the the `lowest' part of any found
-+ chunk. This does not necessarily hold however for chunks
-+ recycled via fastbins.
-+ */
-
- assert(prev_inuse(p));
- }
-@@ -243,7 +240,7 @@ void __do_check_malloc_state(void)
-
- /* cannot run remaining checks until fully initialized */
- if (av->top == 0 || av->top == initial_top(av))
-- return;
-+ return;
-
- /* pagesize is a power of 2 */
- assert((av->pagesize & (av->pagesize-1)) == 0);
-@@ -256,64 +253,64 @@ void __do_check_malloc_state(void)
- max_fast_bin = fastbin_index(av->max_fast);
-
- for (i = 0; i < NFASTBINS; ++i) {
-- p = av->fastbins[i];
-+ p = av->fastbins[i];
-
-- /* all bins past max_fast are empty */
-- if (i > max_fast_bin)
-- assert(p == 0);
--
-- while (p != 0) {
-- /* each chunk claims to be inuse */
-- __do_check_inuse_chunk(p);
-- total += chunksize(p);
-- /* chunk belongs in this bin */
-- assert(fastbin_index(chunksize(p)) == i);
-- p = p->fd;
-- }
-+ /* all bins past max_fast are empty */
-+ if (i > max_fast_bin)
-+ assert(p == 0);
-+
-+ while (p != 0) {
-+ /* each chunk claims to be inuse */
-+ __do_check_inuse_chunk(p);
-+ total += chunksize(p);
-+ /* chunk belongs in this bin */
-+ assert(fastbin_index(chunksize(p)) == i);
-+ p = p->fd;
-+ }
- }
-
- if (total != 0)
-- assert(have_fastchunks(av));
-+ assert(have_fastchunks(av));
- else if (!have_fastchunks(av))
-- assert(total == 0);
-+ assert(total == 0);
-
- /* check normal bins */
- for (i = 1; i < NBINS; ++i) {
-- b = bin_at(av,i);
-+ b = bin_at(av,i);
-
-- /* binmap is accurate (except for bin 1 == unsorted_chunks) */
-- if (i >= 2) {
-- binbit = get_binmap(av,i);
-- empty = last(b) == b;
-- if (!binbit)
-- assert(empty);
-- else if (!empty)
-- assert(binbit);
-- }
--
-- for (p = last(b); p != b; p = p->bk) {
-- /* each chunk claims to be free */
-- __do_check_free_chunk(p);
-- size = chunksize(p);
-- total += size;
-- if (i >= 2) {
-- /* chunk belongs in bin */
-- idx = bin_index(size);
-- assert(idx == i);
-- /* lists are sorted */
-- if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
-- assert(p->bk == b ||
-- (unsigned long)chunksize(p->bk) >=
-- (unsigned long)chunksize(p));
-- }
-- }
-- /* chunk is followed by a legal chain of inuse chunks */
-- for (q = next_chunk(p);
-- (q != av->top && inuse(q) &&
-- (unsigned long)(chunksize(q)) >= MINSIZE);
-- q = next_chunk(q))
-- __do_check_inuse_chunk(q);
-- }
-+ /* binmap is accurate (except for bin 1 == unsorted_chunks) */
-+ if (i >= 2) {
-+ binbit = get_binmap(av,i);
-+ empty = last(b) == b;
-+ if (!binbit)
-+ assert(empty);
-+ else if (!empty)
-+ assert(binbit);
-+ }
-+
-+ for (p = last(b); p != b; p = p->bk) {
-+ /* each chunk claims to be free */
-+ __do_check_free_chunk(p);
-+ size = chunksize(p);
-+ total += size;
-+ if (i >= 2) {
-+ /* chunk belongs in bin */
-+ idx = bin_index(size);
-+ assert(idx == i);
-+ /* lists are sorted */
-+ if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
-+ assert(p->bk == b ||
-+ (unsigned long)chunksize(p->bk) >=
-+ (unsigned long)chunksize(p));
-+ }
-+ }
-+ /* chunk is followed by a legal chain of inuse chunks */
-+ for (q = next_chunk(p);
-+ (q != av->top && inuse(q) &&
-+ (unsigned long)(chunksize(q)) >= MINSIZE);
-+ q = next_chunk(q))
-+ __do_check_inuse_chunk(q);
-+ }
- }
-
- /* top chunk is OK */
-@@ -326,13 +323,13 @@ void __do_check_malloc_state(void)
- assert(av->n_mmaps <= av->max_n_mmaps);
-
- assert((unsigned long)(av->sbrked_mem) <=
-- (unsigned long)(av->max_sbrked_mem));
-+ (unsigned long)(av->max_sbrked_mem));
-
- assert((unsigned long)(av->mmapped_mem) <=
-- (unsigned long)(av->max_mmapped_mem));
-+ (unsigned long)(av->max_mmapped_mem));
-
- assert((unsigned long)(av->max_total_mem) >=
-- (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem));
-+ (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem));
- }
- #endif
-
-@@ -370,84 +367,84 @@ static void* __malloc_alloc(size_t nb, m
- size_t pagemask = av->pagesize - 1;
-
- /*
-- If there is space available in fastbins, consolidate and retry
-- malloc from scratch rather than getting memory from system. This
-- can occur only if nb is in smallbin range so we didn't consolidate
-- upon entry to malloc. It is much easier to handle this case here
-- than in malloc proper.
-- */
-+ If there is space available in fastbins, consolidate and retry
-+ malloc from scratch rather than getting memory from system. This
-+ can occur only if nb is in smallbin range so we didn't consolidate
-+ upon entry to malloc. It is much easier to handle this case here
-+ than in malloc proper.
-+ */
-
- if (have_fastchunks(av)) {
-- assert(in_smallbin_range(nb));
-- __malloc_consolidate(av);
-- return malloc(nb - MALLOC_ALIGN_MASK);
-+ assert(in_smallbin_range(nb));
-+ __malloc_consolidate(av);
-+ return malloc(nb - MALLOC_ALIGN_MASK);
- }
-
-
- /*
-- If have mmap, and the request size meets the mmap threshold, and
-- the system supports mmap, and there are few enough currently
-- allocated mmapped regions, try to directly map this request
-- rather than expanding top.
-- */
-+ If have mmap, and the request size meets the mmap threshold, and
-+ the system supports mmap, and there are few enough currently
-+ allocated mmapped regions, try to directly map this request
-+ rather than expanding top.
-+ */
-
- if ((unsigned long)(nb) >= (unsigned long)(av->mmap_threshold) &&
- (av->n_mmaps < av->n_mmaps_max)) {
-
-- char* mm; /* return value from mmap call*/
--
-- /*
-- Round up size to nearest page. For mmapped chunks, the overhead
-- is one (sizeof(size_t)) unit larger than for normal chunks, because there
-- is no following chunk whose prev_size field could be used.
-- */
-- size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
--
-- /* Don't try if size wraps around 0 */
-- if ((unsigned long)(size) > (unsigned long)(nb)) {
--
-- mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
--
-- if (mm != (char*)(MORECORE_FAILURE)) {
-+ char* mm; /* return value from mmap call*/
-
- /*
-- The offset to the start of the mmapped region is stored
-- in the prev_size field of the chunk. This allows us to adjust
-- returned start address to meet alignment requirements here
-- and in memalign(), and still be able to compute proper
-- address argument for later munmap in free() and realloc().
-- */
--
-- front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK;
-- if (front_misalign > 0) {
-- correction = MALLOC_ALIGNMENT - front_misalign;
-- p = (mchunkptr)(mm + correction);
-- p->prev_size = correction;
-- set_head(p, (size - correction) |IS_MMAPPED);
-- }
-- else {
-- p = (mchunkptr)mm;
-- p->prev_size = 0;
-- set_head(p, size|IS_MMAPPED);
-- }
-+ Round up size to nearest page. For mmapped chunks, the overhead
-+ is one (sizeof(size_t)) unit larger than for normal chunks, because there
-+ is no following chunk whose prev_size field could be used.
-+ */
-+ size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
-+
-+ /* Don't try if size wraps around 0 */
-+ if ((unsigned long)(size) > (unsigned long)(nb)) {
-+
-+ mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
-+
-+ if (mm != (char*)(MORECORE_FAILURE)) {
-+
-+ /*
-+ The offset to the start of the mmapped region is stored
-+ in the prev_size field of the chunk. This allows us to adjust
-+ returned start address to meet alignment requirements here
-+ and in memalign(), and still be able to compute proper
-+ address argument for later munmap in free() and realloc().
-+ */
-+
-+ front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK;
-+ if (front_misalign > 0) {
-+ correction = MALLOC_ALIGNMENT - front_misalign;
-+ p = (mchunkptr)(mm + correction);
-+ p->prev_size = correction;
-+ set_head(p, (size - correction) |IS_MMAPPED);
-+ }
-+ else {
-+ p = (mchunkptr)mm;
-+ p->prev_size = 0;
-+ set_head(p, size|IS_MMAPPED);
-+ }
-+
-+ /* update statistics */
-+
-+ if (++av->n_mmaps > av->max_n_mmaps)
-+ av->max_n_mmaps = av->n_mmaps;
-+
-+ sum = av->mmapped_mem += size;
-+ if (sum > (unsigned long)(av->max_mmapped_mem))
-+ av->max_mmapped_mem = sum;
-+ sum += av->sbrked_mem;
-+ if (sum > (unsigned long)(av->max_total_mem))
-+ av->max_total_mem = sum;
-
-- /* update statistics */
-+ check_chunk(p);
-
-- if (++av->n_mmaps > av->max_n_mmaps)
-- av->max_n_mmaps = av->n_mmaps;
--
-- sum = av->mmapped_mem += size;
-- if (sum > (unsigned long)(av->max_mmapped_mem))
-- av->max_mmapped_mem = sum;
-- sum += av->sbrked_mem;
-- if (sum > (unsigned long)(av->max_total_mem))
-- av->max_total_mem = sum;
--
-- check_chunk(p);
--
-- return chunk2mem(p);
-- }
-- }
-+ return chunk2mem(p);
-+ }
-+ }
- }
-
- /* Record incoming configuration of top */
-@@ -462,8 +459,8 @@ static void* __malloc_alloc(size_t nb, m
- * be at least MINSIZE and to have prev_inuse set. */
-
- assert((old_top == initial_top(av) && old_size == 0) ||
-- ((unsigned long) (old_size) >= MINSIZE &&
-- prev_inuse(old_top)));
-+ ((unsigned long) (old_size) >= MINSIZE &&
-+ prev_inuse(old_top)));
-
- /* Precondition: not enough current space to satisfy nb request */
- assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE));
-@@ -477,272 +474,272 @@ static void* __malloc_alloc(size_t nb, m
- size = nb + av->top_pad + MINSIZE;
-
- /*
-- If contiguous, we can subtract out existing space that we hope to
-- combine with new space. We add it back later only if
-- we don't actually get contiguous space.
-- */
-+ If contiguous, we can subtract out existing space that we hope to
-+ combine with new space. We add it back later only if
-+ we don't actually get contiguous space.
-+ */
-
- if (contiguous(av))
-- size -= old_size;
-+ size -= old_size;
-
- /*
-- Round to a multiple of page size.
-- If MORECORE is not contiguous, this ensures that we only call it
-- with whole-page arguments. And if MORECORE is contiguous and
-- this is not first time through, this preserves page-alignment of
-- previous calls. Otherwise, we correct to page-align below.
-- */
-+ Round to a multiple of page size.
-+ If MORECORE is not contiguous, this ensures that we only call it
-+ with whole-page arguments. And if MORECORE is contiguous and
-+ this is not first time through, this preserves page-alignment of
-+ previous calls. Otherwise, we correct to page-align below.
-+ */
-
- size = (size + pagemask) & ~pagemask;
-
- /*
-- Don't try to call MORECORE if argument is so big as to appear
-- negative. Note that since mmap takes size_t arg, it may succeed
-- below even if we cannot call MORECORE.
-- */
-+ Don't try to call MORECORE if argument is so big as to appear
-+ negative. Note that since mmap takes size_t arg, it may succeed
-+ below even if we cannot call MORECORE.
-+ */
-
- if (size > 0)
-- brk = (char*)(MORECORE(size));
-+ brk = (char*)(MORECORE(size));
-
- /*
-- If have mmap, try using it as a backup when MORECORE fails or
-- cannot be used. This is worth doing on systems that have "holes" in
-- address space, so sbrk cannot extend to give contiguous space, but
-- space is available elsewhere. Note that we ignore mmap max count
-- and threshold limits, since the space will not be used as a
-- segregated mmap region.
-- */
-+ If have mmap, try using it as a backup when MORECORE fails or
-+ cannot be used. This is worth doing on systems that have "holes" in
-+ address space, so sbrk cannot extend to give contiguous space, but
-+ space is available elsewhere. Note that we ignore mmap max count
-+ and threshold limits, since the space will not be used as a
-+ segregated mmap region.
-+ */
-
- if (brk == (char*)(MORECORE_FAILURE)) {
-
-- /* Cannot merge with old top, so add its size back in */
-- if (contiguous(av))
-- size = (size + old_size + pagemask) & ~pagemask;
--
-- /* If we are relying on mmap as backup, then use larger units */
-- if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE))
-- size = MMAP_AS_MORECORE_SIZE;
--
-- /* Don't try if size wraps around 0 */
-- if ((unsigned long)(size) > (unsigned long)(nb)) {
--
-- brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
--
-- if (brk != (char*)(MORECORE_FAILURE)) {
--
-- /* We do not need, and cannot use, another sbrk call to find end */
-- snd_brk = brk + size;
--
-- /* Record that we no longer have a contiguous sbrk region.
-- After the first time mmap is used as backup, we do not
-- ever rely on contiguous space since this could incorrectly
-- bridge regions.
-- */
-- set_noncontiguous(av);
-- }
-- }
-+ /* Cannot merge with old top, so add its size back in */
-+ if (contiguous(av))
-+ size = (size + old_size + pagemask) & ~pagemask;
-+
-+ /* If we are relying on mmap as backup, then use larger units */
-+ if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE))
-+ size = MMAP_AS_MORECORE_SIZE;
-+
-+ /* Don't try if size wraps around 0 */
-+ if ((unsigned long)(size) > (unsigned long)(nb)) {
-+
-+ brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE));
-+
-+ if (brk != (char*)(MORECORE_FAILURE)) {
-+
-+ /* We do not need, and cannot use, another sbrk call to find end */
-+ snd_brk = brk + size;
-+
-+ /* Record that we no longer have a contiguous sbrk region.
-+ After the first time mmap is used as backup, we do not
-+ ever rely on contiguous space since this could incorrectly
-+ bridge regions.
-+ */
-+ set_noncontiguous(av);
-+ }
-+ }
- }
-
- if (brk != (char*)(MORECORE_FAILURE)) {
-- av->sbrked_mem += size;
-+ av->sbrked_mem += size;
-
-- /*
-- If MORECORE extends previous space, we can likewise extend top size.
-- */
--
-- if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
-- set_head(old_top, (size + old_size) | PREV_INUSE);
-- }
--
-- /*
-- Otherwise, make adjustments:
--
-- * If the first time through or noncontiguous, we need to call sbrk
-- just to find out where the end of memory lies.
--
-- * We need to ensure that all returned chunks from malloc will meet
-- MALLOC_ALIGNMENT
--
-- * If there was an intervening foreign sbrk, we need to adjust sbrk
-- request size to account for fact that we will not be able to
-- combine new space with existing space in old_top.
--
-- * Almost all systems internally allocate whole pages at a time, in
-- which case we might as well use the whole last page of request.
-- So we allocate enough more memory to hit a page boundary now,
-- which in turn causes future contiguous calls to page-align.
-- */
--
-- else {
-- front_misalign = 0;
-- end_misalign = 0;
-- correction = 0;
-- aligned_brk = brk;
--
-- /*
-- If MORECORE returns an address lower than we have seen before,
-- we know it isn't really contiguous. This and some subsequent
-- checks help cope with non-conforming MORECORE functions and
-- the presence of "foreign" calls to MORECORE from outside of
-- malloc or by other threads. We cannot guarantee to detect
-- these in all cases, but cope with the ones we do detect.
-- */
-- if (contiguous(av) && old_size != 0 && brk < old_end) {
-- set_noncontiguous(av);
-- }
--
-- /* handle contiguous cases */
-- if (contiguous(av)) {
--
-- /* We can tolerate forward non-contiguities here (usually due
-- to foreign calls) but treat them as part of our space for
-- stats reporting. */
-- if (old_size != 0)
-- av->sbrked_mem += brk - old_end;
--
-- /* Guarantee alignment of first new chunk made from this space */
--
-- front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK;
-- if (front_misalign > 0) {
--
-- /*
-- Skip over some bytes to arrive at an aligned position.
-- We don't need to specially mark these wasted front bytes.
-- They will never be accessed anyway because
-- prev_inuse of av->top (and any chunk created from its start)
-- is always true after initialization.
-- */
-+ /*
-+ If MORECORE extends previous space, we can likewise extend top size.
-+ */
-
-- correction = MALLOC_ALIGNMENT - front_misalign;
-- aligned_brk += correction;
-+ if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
-+ set_head(old_top, (size + old_size) | PREV_INUSE);
- }
-
- /*
-- If this isn't adjacent to existing space, then we will not
-- be able to merge with old_top space, so must add to 2nd request.
-- */
--
-- correction += old_size;
--
-- /* Extend the end address to hit a page boundary */
-- end_misalign = (size_t)(brk + size + correction);
-- correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
--
-- assert(correction >= 0);
-- snd_brk = (char*)(MORECORE(correction));
--
-- if (snd_brk == (char*)(MORECORE_FAILURE)) {
-- /*
-- If can't allocate correction, try to at least find out current
-- brk. It might be enough to proceed without failing.
-- */
-- correction = 0;
-- snd_brk = (char*)(MORECORE(0));
-- }
-- else if (snd_brk < brk) {
-- /*
-- If the second call gives noncontiguous space even though
-- it says it won't, the only course of action is to ignore
-- results of second call, and conservatively estimate where
-- the first call left us. Also set noncontiguous, so this
-- won't happen again, leaving at most one hole.
--
-- Note that this check is intrinsically incomplete. Because
-- MORECORE is allowed to give more space than we ask for,
-- there is no reliable way to detect a noncontiguity
-- producing a forward gap for the second call.
-- */
-- snd_brk = brk + size;
-- correction = 0;
-- set_noncontiguous(av);
-- }
--
-- }
--
-- /* handle non-contiguous cases */
-- else {
-- /* MORECORE/mmap must correctly align */
-- assert(aligned_OK(chunk2mem(brk)));
--
-- /* Find out current end of memory */
-- if (snd_brk == (char*)(MORECORE_FAILURE)) {
-- snd_brk = (char*)(MORECORE(0));
-- av->sbrked_mem += snd_brk - brk - size;
-- }
-- }
--
-- /* Adjust top based on results of second sbrk */
-- if (snd_brk != (char*)(MORECORE_FAILURE)) {
-- av->top = (mchunkptr)aligned_brk;
-- set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
-- av->sbrked_mem += correction;
-+ Otherwise, make adjustments:
-
-- /*
-- If not the first time through, we either have a
-- gap due to foreign sbrk or a non-contiguous region. Insert a
-- double fencepost at old_top to prevent consolidation with space
-- we don't own. These fenceposts are artificial chunks that are
-- marked as inuse and are in any case too small to use. We need
-- two to make sizes and alignments work out.
-- */
--
-- if (old_size != 0) {
-- /* Shrink old_top to insert fenceposts, keeping size a
-- multiple of MALLOC_ALIGNMENT. We know there is at least
-- enough space in old_top to do this.
-- */
-- old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK;
-- set_head(old_top, old_size | PREV_INUSE);
--
-- /*
-- Note that the following assignments completely overwrite
-- old_top when old_size was previously MINSIZE. This is
-- intentional. We need the fencepost, even if old_top otherwise gets
-- lost.
-- */
-- chunk_at_offset(old_top, old_size )->size =
-- (sizeof(size_t))|PREV_INUSE;
--
-- chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size =
-- (sizeof(size_t))|PREV_INUSE;
--
-- /* If possible, release the rest, suppressing trimming. */
-- if (old_size >= MINSIZE) {
-- size_t tt = av->trim_threshold;
-- av->trim_threshold = (size_t)(-1);
-- free(chunk2mem(old_top));
-- av->trim_threshold = tt;
-- }
-- }
-- }
-- }
--
-- /* Update statistics */
-- sum = av->sbrked_mem;
-- if (sum > (unsigned long)(av->max_sbrked_mem))
-- av->max_sbrked_mem = sum;
--
-- sum += av->mmapped_mem;
-- if (sum > (unsigned long)(av->max_total_mem))
-- av->max_total_mem = sum;
--
-- check_malloc_state();
--
-- /* finally, do the allocation */
--
-- p = av->top;
-- size = chunksize(p);
--
-- /* check that one of the above allocation paths succeeded */
-- if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
-- remainder_size = size - nb;
-- remainder = chunk_at_offset(p, nb);
-- av->top = remainder;
-- set_head(p, nb | PREV_INUSE);
-- set_head(remainder, remainder_size | PREV_INUSE);
-- check_malloced_chunk(p, nb);
-- return chunk2mem(p);
-- }
-+ * If the first time through or noncontiguous, we need to call sbrk
-+ just to find out where the end of memory lies.
-+
-+ * We need to ensure that all returned chunks from malloc will meet
-+ MALLOC_ALIGNMENT
-+
-+ * If there was an intervening foreign sbrk, we need to adjust sbrk
-+ request size to account for fact that we will not be able to
-+ combine new space with existing space in old_top.
-+
-+ * Almost all systems internally allocate whole pages at a time, in
-+ which case we might as well use the whole last page of request.
-+ So we allocate enough more memory to hit a page boundary now,
-+ which in turn causes future contiguous calls to page-align.
-+ */
-+
-+ else {
-+ front_misalign = 0;
-+ end_misalign = 0;
-+ correction = 0;
-+ aligned_brk = brk;
-+
-+ /*
-+ If MORECORE returns an address lower than we have seen before,
-+ we know it isn't really contiguous. This and some subsequent
-+ checks help cope with non-conforming MORECORE functions and
-+ the presence of "foreign" calls to MORECORE from outside of
-+ malloc or by other threads. We cannot guarantee to detect
-+ these in all cases, but cope with the ones we do detect.
-+ */
-+ if (contiguous(av) && old_size != 0 && brk < old_end) {
-+ set_noncontiguous(av);
-+ }
-+
-+ /* handle contiguous cases */
-+ if (contiguous(av)) {
-+
-+ /* We can tolerate forward non-contiguities here (usually due
-+ to foreign calls) but treat them as part of our space for
-+ stats reporting. */
-+ if (old_size != 0)
-+ av->sbrked_mem += brk - old_end;
-+
-+ /* Guarantee alignment of first new chunk made from this space */
-+
-+ front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK;
-+ if (front_misalign > 0) {
-+
-+ /*
-+ Skip over some bytes to arrive at an aligned position.
-+ We don't need to specially mark these wasted front bytes.
-+ They will never be accessed anyway because
-+ prev_inuse of av->top (and any chunk created from its start)
-+ is always true after initialization.
-+ */
-+
-+ correction = MALLOC_ALIGNMENT - front_misalign;
-+ aligned_brk += correction;
-+ }
-+
-+ /*
-+ If this isn't adjacent to existing space, then we will not
-+ be able to merge with old_top space, so must add to 2nd request.
-+ */
-+
-+ correction += old_size;
-+
-+ /* Extend the end address to hit a page boundary */
-+ end_misalign = (size_t)(brk + size + correction);
-+ correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
-+
-+ assert(correction >= 0);
-+ snd_brk = (char*)(MORECORE(correction));
-+
-+ if (snd_brk == (char*)(MORECORE_FAILURE)) {
-+ /*
-+ If can't allocate correction, try to at least find out current
-+ brk. It might be enough to proceed without failing.
-+ */
-+ correction = 0;
-+ snd_brk = (char*)(MORECORE(0));
-+ }
-+ else if (snd_brk < brk) {
-+ /*
-+ If the second call gives noncontiguous space even though
-+ it says it won't, the only course of action is to ignore
-+ results of second call, and conservatively estimate where
-+ the first call left us. Also set noncontiguous, so this
-+ won't happen again, leaving at most one hole.
-+
-+ Note that this check is intrinsically incomplete. Because
-+ MORECORE is allowed to give more space than we ask for,
-+ there is no reliable way to detect a noncontiguity
-+ producing a forward gap for the second call.
-+ */
-+ snd_brk = brk + size;
-+ correction = 0;
-+ set_noncontiguous(av);
-+ }
-+
-+ }
-+
-+ /* handle non-contiguous cases */
-+ else {
-+ /* MORECORE/mmap must correctly align */
-+ assert(aligned_OK(chunk2mem(brk)));
-+
-+ /* Find out current end of memory */
-+ if (snd_brk == (char*)(MORECORE_FAILURE)) {
-+ snd_brk = (char*)(MORECORE(0));
-+ av->sbrked_mem += snd_brk - brk - size;
-+ }
-+ }
-+
-+ /* Adjust top based on results of second sbrk */
-+ if (snd_brk != (char*)(MORECORE_FAILURE)) {
-+ av->top = (mchunkptr)aligned_brk;
-+ set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
-+ av->sbrked_mem += correction;
-+
-+ /*
-+ If not the first time through, we either have a
-+ gap due to foreign sbrk or a non-contiguous region. Insert a
-+ double fencepost at old_top to prevent consolidation with space
-+ we don't own. These fenceposts are artificial chunks that are
-+ marked as inuse and are in any case too small to use. We need
-+ two to make sizes and alignments work out.
-+ */
-+
-+ if (old_size != 0) {
-+ /* Shrink old_top to insert fenceposts, keeping size a
-+ multiple of MALLOC_ALIGNMENT. We know there is at least
-+ enough space in old_top to do this.
-+ */
-+ old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK;
-+ set_head(old_top, old_size | PREV_INUSE);
-+
-+ /*
-+ Note that the following assignments completely overwrite
-+ old_top when old_size was previously MINSIZE. This is
-+ intentional. We need the fencepost, even if old_top otherwise gets
-+ lost.
-+ */
-+ chunk_at_offset(old_top, old_size )->size =
-+ (sizeof(size_t))|PREV_INUSE;
-+
-+ chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size =
-+ (sizeof(size_t))|PREV_INUSE;
-+
-+ /* If possible, release the rest, suppressing trimming. */
-+ if (old_size >= MINSIZE) {
-+ size_t tt = av->trim_threshold;
-+ av->trim_threshold = (size_t)(-1);
-+ free(chunk2mem(old_top));
-+ av->trim_threshold = tt;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Update statistics */
-+ sum = av->sbrked_mem;
-+ if (sum > (unsigned long)(av->max_sbrked_mem))
-+ av->max_sbrked_mem = sum;
-+
-+ sum += av->mmapped_mem;
-+ if (sum > (unsigned long)(av->max_total_mem))
-+ av->max_total_mem = sum;
-+
-+ check_malloc_state();
-+
-+ /* finally, do the allocation */
-+
-+ p = av->top;
-+ size = chunksize(p);
-+
-+ /* check that one of the above allocation paths succeeded */
-+ if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
-+ remainder_size = size - nb;
-+ remainder = chunk_at_offset(p, nb);
-+ av->top = remainder;
-+ set_head(p, nb | PREV_INUSE);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+ check_malloced_chunk(p, nb);
-+ return chunk2mem(p);
-+ }
-
- }
-
-@@ -767,25 +764,25 @@ static int __malloc_largebin_index(unsig
- #if defined(__GNUC__) && defined(i386)
-
- __asm__("bsrl %1,%0\n\t"
-- : "=r" (m)
-- : "g" (x));
-+ : "=r" (m)
-+ : "g" (x));
-
- #else
- {
-- /*
-- Based on branch-free nlz algorithm in chapter 5 of Henry
-- S. Warren Jr's book "Hacker's Delight".
-- */
--
-- unsigned int n = ((x - 0x100) >> 16) & 8;
-- x <<= n;
-- m = ((x - 0x1000) >> 16) & 4;
-- n += m;
-- x <<= m;
-- m = ((x - 0x4000) >> 16) & 2;
-- n += m;
-- x = (x << m) >> 14;
-- m = 13 - n + (x & ~(x>>1));
-+ /*
-+ Based on branch-free nlz algorithm in chapter 5 of Henry
-+ S. Warren Jr's book "Hacker's Delight".
-+ */
-+
-+ unsigned int n = ((x - 0x100) >> 16) & 8;
-+ x <<= n;
-+ m = ((x - 0x1000) >> 16) & 4;
-+ n += m;
-+ x <<= m;
-+ m = ((x - 0x4000) >> 16) & 2;
-+ n += m;
-+ x = (x << m) >> 14;
-+ m = 13 - n + (x & ~(x>>1));
- }
- #endif
-
-@@ -826,69 +823,70 @@ void* malloc(size_t bytes)
- mchunkptr fwd; /* misc temp for linking */
- mchunkptr bck; /* misc temp for linking */
- void * sysmem;
-+ void * retval;
-
- #if !defined(__MALLOC_GLIBC_COMPAT__)
- if (!bytes) return NULL;
- #endif
-
-- LOCK;
-+ __MALLOC_LOCK;
- av = get_malloc_state();
- /*
-- Convert request size to internal form by adding (sizeof(size_t)) bytes
-- overhead plus possibly more to obtain necessary alignment and/or
-- to obtain a size of at least MINSIZE, the smallest allocatable
-- size. Also, checked_request2size traps (returning 0) request sizes
-- that are so large that they wrap around zero when padded and
-- aligned.
-- */
-+ Convert request size to internal form by adding (sizeof(size_t)) bytes
-+ overhead plus possibly more to obtain necessary alignment and/or
-+ to obtain a size of at least MINSIZE, the smallest allocatable
-+ size. Also, checked_request2size traps (returning 0) request sizes
-+ that are so large that they wrap around zero when padded and
-+ aligned.
-+ */
-
- checked_request2size(bytes, nb);
-
- /*
-- Bypass search if no frees yet
-- */
-+ Bypass search if no frees yet
-+ */
- if (!have_anychunks(av)) {
-- if (av->max_fast == 0) /* initialization check */
-- __malloc_consolidate(av);
-- goto use_top;
-+ if (av->max_fast == 0) /* initialization check */
-+ __malloc_consolidate(av);
-+ goto use_top;
- }
-
- /*
-- If the size qualifies as a fastbin, first check corresponding bin.
-- */
-+ If the size qualifies as a fastbin, first check corresponding bin.
-+ */
-
- if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) {
-- fb = &(av->fastbins[(fastbin_index(nb))]);
-- if ( (victim = *fb) != 0) {
-- *fb = victim->fd;
-- check_remalloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
-+ fb = &(av->fastbins[(fastbin_index(nb))]);
-+ if ( (victim = *fb) != 0) {
-+ *fb = victim->fd;
-+ check_remalloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
- }
-
- /*
-- If a small request, check regular bin. Since these "smallbins"
-- hold one size each, no searching within bins is necessary.
-- (For a large request, we need to wait until unsorted chunks are
-- processed to find best fit. But for small ones, fits are exact
-- anyway, so we can check now, which is faster.)
-- */
-+ If a small request, check regular bin. Since these "smallbins"
-+ hold one size each, no searching within bins is necessary.
-+ (For a large request, we need to wait until unsorted chunks are
-+ processed to find best fit. But for small ones, fits are exact
-+ anyway, so we can check now, which is faster.)
-+ */
-
- if (in_smallbin_range(nb)) {
-- idx = smallbin_index(nb);
-- bin = bin_at(av,idx);
-+ idx = smallbin_index(nb);
-+ bin = bin_at(av,idx);
-
-- if ( (victim = last(bin)) != bin) {
-- bck = victim->bk;
-- set_inuse_bit_at_offset(victim, nb);
-- bin->bk = bck;
-- bck->fd = bin;
--
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
-+ if ( (victim = last(bin)) != bin) {
-+ bck = victim->bk;
-+ set_inuse_bit_at_offset(victim, nb);
-+ bin->bk = bck;
-+ bck->fd = bin;
-+
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
- }
-
- /* If this is a large request, consolidate fastbins before continuing.
-@@ -899,154 +897,154 @@ void* malloc(size_t bytes)
- large requests, but less often mixtures, so consolidation is not
- invoked all that often in most programs. And the programs that
- it is called frequently in otherwise tend to fragment.
-- */
-+ */
-
- else {
-- idx = __malloc_largebin_index(nb);
-- if (have_fastchunks(av))
-- __malloc_consolidate(av);
-+ idx = __malloc_largebin_index(nb);
-+ if (have_fastchunks(av))
-+ __malloc_consolidate(av);
- }
-
- /*
-- Process recently freed or remaindered chunks, taking one only if
-- it is exact fit, or, if this a small request, the chunk is remainder from
-- the most recent non-exact fit. Place other traversed chunks in
-- bins. Note that this step is the only place in any routine where
-- chunks are placed in bins.
-- */
-+ Process recently freed or remaindered chunks, taking one only if
-+ it is exact fit, or, if this a small request, the chunk is remainder from
-+ the most recent non-exact fit. Place other traversed chunks in
-+ bins. Note that this step is the only place in any routine where
-+ chunks are placed in bins.
-+ */
-
- while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
-- bck = victim->bk;
-- size = chunksize(victim);
-+ bck = victim->bk;
-+ size = chunksize(victim);
-+
-+ /* If a small request, try to use last remainder if it is the
-+ only chunk in unsorted bin. This helps promote locality for
-+ runs of consecutive small requests. This is the only
-+ exception to best-fit, and applies only when there is
-+ no exact fit for a small chunk.
-+ */
-+
-+ if (in_smallbin_range(nb) &&
-+ bck == unsorted_chunks(av) &&
-+ victim == av->last_remainder &&
-+ (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
-+
-+ /* split and reattach remainder */
-+ remainder_size = size - nb;
-+ remainder = chunk_at_offset(victim, nb);
-+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
-+ av->last_remainder = remainder;
-+ remainder->bk = remainder->fd = unsorted_chunks(av);
-+
-+ set_head(victim, nb | PREV_INUSE);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+ set_foot(remainder, remainder_size);
-+
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
-+
-+ /* remove from unsorted list */
-+ unsorted_chunks(av)->bk = bck;
-+ bck->fd = unsorted_chunks(av);
-+
-+ /* Take now instead of binning if exact fit */
-+
-+ if (size == nb) {
-+ set_inuse_bit_at_offset(victim, size);
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
-+
-+ /* place chunk in bin */
-
-- /* If a small request, try to use last remainder if it is the
-- only chunk in unsorted bin. This helps promote locality for
-- runs of consecutive small requests. This is the only
-- exception to best-fit, and applies only when there is
-- no exact fit for a small chunk.
-- */
--
-- if (in_smallbin_range(nb) &&
-- bck == unsorted_chunks(av) &&
-- victim == av->last_remainder &&
-- (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
--
-- /* split and reattach remainder */
-- remainder_size = size - nb;
-- remainder = chunk_at_offset(victim, nb);
-- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
-- av->last_remainder = remainder;
-- remainder->bk = remainder->fd = unsorted_chunks(av);
--
-- set_head(victim, nb | PREV_INUSE);
-- set_head(remainder, remainder_size | PREV_INUSE);
-- set_foot(remainder, remainder_size);
--
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
--
-- /* remove from unsorted list */
-- unsorted_chunks(av)->bk = bck;
-- bck->fd = unsorted_chunks(av);
--
-- /* Take now instead of binning if exact fit */
--
-- if (size == nb) {
-- set_inuse_bit_at_offset(victim, size);
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
--
-- /* place chunk in bin */
--
-- if (in_smallbin_range(size)) {
-- victim_index = smallbin_index(size);
-- bck = bin_at(av, victim_index);
-- fwd = bck->fd;
-- }
-- else {
-- victim_index = __malloc_largebin_index(size);
-- bck = bin_at(av, victim_index);
-- fwd = bck->fd;
--
-- if (fwd != bck) {
-- /* if smaller than smallest, place first */
-- if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) {
-- fwd = bck;
-- bck = bck->bk;
-- }
-- else if ((unsigned long)(size) >=
-- (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
--
-- /* maintain large bins in sorted order */
-- size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */
-- while ((unsigned long)(size) < (unsigned long)(fwd->size))
-- fwd = fwd->fd;
-- bck = fwd->bk;
-- }
-- }
-- }
--
-- mark_bin(av, victim_index);
-- victim->bk = bck;
-- victim->fd = fwd;
-- fwd->bk = victim;
-- bck->fd = victim;
-+ if (in_smallbin_range(size)) {
-+ victim_index = smallbin_index(size);
-+ bck = bin_at(av, victim_index);
-+ fwd = bck->fd;
-+ }
-+ else {
-+ victim_index = __malloc_largebin_index(size);
-+ bck = bin_at(av, victim_index);
-+ fwd = bck->fd;
-+
-+ if (fwd != bck) {
-+ /* if smaller than smallest, place first */
-+ if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) {
-+ fwd = bck;
-+ bck = bck->bk;
-+ }
-+ else if ((unsigned long)(size) >=
-+ (unsigned long)(FIRST_SORTED_BIN_SIZE)) {
-+
-+ /* maintain large bins in sorted order */
-+ size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */
-+ while ((unsigned long)(size) < (unsigned long)(fwd->size))
-+ fwd = fwd->fd;
-+ bck = fwd->bk;
-+ }
-+ }
-+ }
-+
-+ mark_bin(av, victim_index);
-+ victim->bk = bck;
-+ victim->fd = fwd;
-+ fwd->bk = victim;
-+ bck->fd = victim;
- }
-
- /*
-- If a large request, scan through the chunks of current bin to
-- find one that fits. (This will be the smallest that fits unless
-- FIRST_SORTED_BIN_SIZE has been changed from default.) This is
-- the only step where an unbounded number of chunks might be
-- scanned without doing anything useful with them. However the
-- lists tend to be short.
-- */
-+ If a large request, scan through the chunks of current bin to
-+ find one that fits. (This will be the smallest that fits unless
-+ FIRST_SORTED_BIN_SIZE has been changed from default.) This is
-+ the only step where an unbounded number of chunks might be
-+ scanned without doing anything useful with them. However the
-+ lists tend to be short.
-+ */
-
- if (!in_smallbin_range(nb)) {
-- bin = bin_at(av, idx);
--
-- for (victim = last(bin); victim != bin; victim = victim->bk) {
-- size = chunksize(victim);
-+ bin = bin_at(av, idx);
-
-- if ((unsigned long)(size) >= (unsigned long)(nb)) {
-- remainder_size = size - nb;
-- unlink(victim, bck, fwd);
-+ for (victim = last(bin); victim != bin; victim = victim->bk) {
-+ size = chunksize(victim);
-
-- /* Exhaust */
-- if (remainder_size < MINSIZE) {
-- set_inuse_bit_at_offset(victim, size);
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
-- /* Split */
-- else {
-- remainder = chunk_at_offset(victim, nb);
-- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
-- remainder->bk = remainder->fd = unsorted_chunks(av);
-- set_head(victim, nb | PREV_INUSE);
-- set_head(remainder, remainder_size | PREV_INUSE);
-- set_foot(remainder, remainder_size);
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-+ if ((unsigned long)(size) >= (unsigned long)(nb)) {
-+ remainder_size = size - nb;
-+ unlink(victim, bck, fwd);
-+
-+ /* Exhaust */
-+ if (remainder_size < MINSIZE) {
-+ set_inuse_bit_at_offset(victim, size);
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
-+ /* Split */
-+ else {
-+ remainder = chunk_at_offset(victim, nb);
-+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
-+ remainder->bk = remainder->fd = unsorted_chunks(av);
-+ set_head(victim, nb | PREV_INUSE);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+ set_foot(remainder, remainder_size);
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
-+ }
- }
-- }
-- }
- }
-
- /*
-- Search for a chunk by scanning bins, starting with next largest
-- bin. This search is strictly by best-fit; i.e., the smallest
-- (with ties going to approximately the least recently used) chunk
-- that fits is selected.
-+ Search for a chunk by scanning bins, starting with next largest
-+ bin. This search is strictly by best-fit; i.e., the smallest
-+ (with ties going to approximately the least recently used) chunk
-+ that fits is selected.
-
-- The bitmap avoids needing to check that most blocks are nonempty.
-- */
-+ The bitmap avoids needing to check that most blocks are nonempty.
-+ */
-
- ++idx;
- bin = bin_at(av,idx);
-@@ -1056,109 +1054,111 @@ void* malloc(size_t bytes)
-
- for (;;) {
-
-- /* Skip rest of block if there are no more set bits in this block. */
-- if (bit > map || bit == 0) {
-- do {
-- if (++block >= BINMAPSIZE) /* out of bins */
-- goto use_top;
-- } while ( (map = av->binmap[block]) == 0);
--
-- bin = bin_at(av, (block << BINMAPSHIFT));
-- bit = 1;
-- }
--
-- /* Advance to bin with set bit. There must be one. */
-- while ((bit & map) == 0) {
-- bin = next_bin(bin);
-- bit <<= 1;
-- assert(bit != 0);
-- }
--
-- /* Inspect the bin. It is likely to be non-empty */
-- victim = last(bin);
--
-- /* If a false alarm (empty bin), clear the bit. */
-- if (victim == bin) {
-- av->binmap[block] = map &= ~bit; /* Write through */
-- bin = next_bin(bin);
-- bit <<= 1;
-- }
--
-- else {
-- size = chunksize(victim);
--
-- /* We know the first chunk in this bin is big enough to use. */
-- assert((unsigned long)(size) >= (unsigned long)(nb));
--
-- remainder_size = size - nb;
--
-- /* unlink */
-- bck = victim->bk;
-- bin->bk = bck;
-- bck->fd = bin;
--
-- /* Exhaust */
-- if (remainder_size < MINSIZE) {
-- set_inuse_bit_at_offset(victim, size);
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
-+ /* Skip rest of block if there are no more set bits in this block. */
-+ if (bit > map || bit == 0) {
-+ do {
-+ if (++block >= BINMAPSIZE) /* out of bins */
-+ goto use_top;
-+ } while ( (map = av->binmap[block]) == 0);
-
-- /* Split */
-- else {
-- remainder = chunk_at_offset(victim, nb);
-+ bin = bin_at(av, (block << BINMAPSHIFT));
-+ bit = 1;
-+ }
-
-- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
-- remainder->bk = remainder->fd = unsorted_chunks(av);
-- /* advertise as last remainder */
-- if (in_smallbin_range(nb))
-- av->last_remainder = remainder;
-+ /* Advance to bin with set bit. There must be one. */
-+ while ((bit & map) == 0) {
-+ bin = next_bin(bin);
-+ bit <<= 1;
-+ assert(bit != 0);
-+ }
-
-- set_head(victim, nb | PREV_INUSE);
-- set_head(remainder, remainder_size | PREV_INUSE);
-- set_foot(remainder, remainder_size);
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-- }
-- }
-+ /* Inspect the bin. It is likely to be non-empty */
-+ victim = last(bin);
-+
-+ /* If a false alarm (empty bin), clear the bit. */
-+ if (victim == bin) {
-+ av->binmap[block] = map &= ~bit; /* Write through */
-+ bin = next_bin(bin);
-+ bit <<= 1;
-+ }
-+
-+ else {
-+ size = chunksize(victim);
-+
-+ /* We know the first chunk in this bin is big enough to use. */
-+ assert((unsigned long)(size) >= (unsigned long)(nb));
-+
-+ remainder_size = size - nb;
-+
-+ /* unlink */
-+ bck = victim->bk;
-+ bin->bk = bck;
-+ bck->fd = bin;
-+
-+ /* Exhaust */
-+ if (remainder_size < MINSIZE) {
-+ set_inuse_bit_at_offset(victim, size);
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
-+
-+ /* Split */
-+ else {
-+ remainder = chunk_at_offset(victim, nb);
-+
-+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
-+ remainder->bk = remainder->fd = unsorted_chunks(av);
-+ /* advertise as last remainder */
-+ if (in_smallbin_range(nb))
-+ av->last_remainder = remainder;
-+
-+ set_head(victim, nb | PREV_INUSE);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+ set_foot(remainder, remainder_size);
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
-+ }
-+ }
- }
-
--use_top:
-+ use_top:
- /*
-- If large enough, split off the chunk bordering the end of memory
-- (held in av->top). Note that this is in accord with the best-fit
-- search rule. In effect, av->top is treated as larger (and thus
-- less well fitting) than any other available chunk since it can
-- be extended to be as large as necessary (up to system
-- limitations).
--
-- We require that av->top always exists (i.e., has size >=
-- MINSIZE) after initialization, so if it would otherwise be
-- exhuasted by current request, it is replenished. (The main
-- reason for ensuring it exists is that we may need MINSIZE space
-- to put in fenceposts in sysmalloc.)
-- */
-+ If large enough, split off the chunk bordering the end of memory
-+ (held in av->top). Note that this is in accord with the best-fit
-+ search rule. In effect, av->top is treated as larger (and thus
-+ less well fitting) than any other available chunk since it can
-+ be extended to be as large as necessary (up to system
-+ limitations).
-+
-+ We require that av->top always exists (i.e., has size >=
-+ MINSIZE) after initialization, so if it would otherwise be
-+ exhuasted by current request, it is replenished. (The main
-+ reason for ensuring it exists is that we may need MINSIZE space
-+ to put in fenceposts in sysmalloc.)
-+ */
-
- victim = av->top;
- size = chunksize(victim);
-
- if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
-- remainder_size = size - nb;
-- remainder = chunk_at_offset(victim, nb);
-- av->top = remainder;
-- set_head(victim, nb | PREV_INUSE);
-- set_head(remainder, remainder_size | PREV_INUSE);
--
-- check_malloced_chunk(victim, nb);
-- UNLOCK;
-- return chunk2mem(victim);
-+ remainder_size = size - nb;
-+ remainder = chunk_at_offset(victim, nb);
-+ av->top = remainder;
-+ set_head(victim, nb | PREV_INUSE);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+
-+ check_malloced_chunk(victim, nb);
-+ retval = chunk2mem(victim);
-+ goto DONE;
- }
-
- /* If no space in top, relay to handle system-dependent cases */
- sysmem = __malloc_alloc(nb, av);
-- UNLOCK;
-- return sysmem;
-+ retval = sysmem;
-+ DONE:
-+ __MALLOC_UNLOCK;
-+ return retval;
- }
-
-diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h
-index fbc1492..14a0dd9 100644
---- a/libc/stdlib/malloc-standard/malloc.h
-+++ b/libc/stdlib/malloc-standard/malloc.h
-@@ -22,16 +22,12 @@
- #include <malloc.h>
- #include <stdlib.h>
-
-+#include <bits/uClibc_mutex.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--extern pthread_mutex_t __malloc_lock;
--# define LOCK __pthread_mutex_lock(&__malloc_lock)
--# define UNLOCK __pthread_mutex_unlock(&__malloc_lock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+__UCLIBC_MUTEX_EXTERN(__malloc_lock);
-+
-+#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
-+#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
-
-
-
-diff --git a/libc/stdlib/malloc-standard/mallopt.c b/libc/stdlib/malloc-standard/mallopt.c
-index e287920..41aa614 100644
---- a/libc/stdlib/malloc-standard/mallopt.c
-+++ b/libc/stdlib/malloc-standard/mallopt.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -25,40 +25,40 @@ int mallopt(int param_number, int value)
-
- ret = 0;
-
-- LOCK;
-+ __MALLOC_LOCK;
- av = get_malloc_state();
- /* Ensure initialization/consolidation */
- __malloc_consolidate(av);
-
- switch(param_number) {
-- case M_MXFAST:
-- if (value >= 0 && value <= MAX_FAST_SIZE) {
-- set_max_fast(av, value);
-- ret = 1;
-- }
-- break;
--
-- case M_TRIM_THRESHOLD:
-- av->trim_threshold = value;
-- ret = 1;
-- break;
--
-- case M_TOP_PAD:
-- av->top_pad = value;
-- ret = 1;
-- break;
--
-- case M_MMAP_THRESHOLD:
-- av->mmap_threshold = value;
-- ret = 1;
-- break;
--
-- case M_MMAP_MAX:
-- av->n_mmaps_max = value;
-- ret = 1;
-- break;
-+ case M_MXFAST:
-+ if (value >= 0 && value <= MAX_FAST_SIZE) {
-+ set_max_fast(av, value);
-+ ret = 1;
-+ }
-+ break;
-+
-+ case M_TRIM_THRESHOLD:
-+ av->trim_threshold = value;
-+ ret = 1;
-+ break;
-+
-+ case M_TOP_PAD:
-+ av->top_pad = value;
-+ ret = 1;
-+ break;
-+
-+ case M_MMAP_THRESHOLD:
-+ av->mmap_threshold = value;
-+ ret = 1;
-+ break;
-+
-+ case M_MMAP_MAX:
-+ av->n_mmaps_max = value;
-+ ret = 1;
-+ break;
- }
-- UNLOCK;
-+ __MALLOC_UNLOCK;
- return ret;
- }
-
-diff --git a/libc/stdlib/malloc-standard/memalign.c b/libc/stdlib/malloc-standard/memalign.c
-index bd95362..e78d752 100644
---- a/libc/stdlib/malloc-standard/memalign.c
-+++ b/libc/stdlib/malloc-standard/memalign.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -35,6 +35,7 @@ void* memalign(size_t alignment, size_t
- mchunkptr remainder; /* spare room at end to split off */
- unsigned long remainder_size; /* its size */
- size_t size;
-+ void *retval;
-
- /* If need less alignment than we give anyway, just relay to malloc */
-
-@@ -46,12 +47,12 @@ void* memalign(size_t alignment, size_t
-
- /* Make sure alignment is power of 2 (in case MINSIZE is not). */
- if ((alignment & (alignment - 1)) != 0) {
-- size_t a = MALLOC_ALIGNMENT * 2;
-- while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
-- alignment = a;
-+ size_t a = MALLOC_ALIGNMENT * 2;
-+ while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
-+ alignment = a;
- }
-
-- LOCK;
-+ __MALLOC_LOCK;
- checked_request2size(bytes, nb);
-
- /* Strategy: find a spot within that chunk that meets the alignment
-@@ -63,64 +64,67 @@ void* memalign(size_t alignment, size_t
- m = (char*)(malloc(nb + alignment + MINSIZE));
-
- if (m == 0) {
-- UNLOCK;
-- return 0; /* propagate failure */
-+ retval = 0; /* propagate failure */
-+ goto DONE;
- }
-
- p = mem2chunk(m);
-
- if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */
-
-- /*
-- Find an aligned spot inside chunk. Since we need to give back
-- leading space in a chunk of at least MINSIZE, if the first
-- calculation places us at a spot with less than MINSIZE leader,
-- we can move to the next aligned spot -- we've allocated enough
-- total room so that this is always possible.
-- */
--
-- brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) &
-- -((signed long) alignment)));
-- if ((unsigned long)(brk - (char*)(p)) < MINSIZE)
-- brk += alignment;
--
-- newp = (mchunkptr)brk;
-- leadsize = brk - (char*)(p);
-- newsize = chunksize(p) - leadsize;
--
-- /* For mmapped chunks, just adjust offset */
-- if (chunk_is_mmapped(p)) {
-- newp->prev_size = p->prev_size + leadsize;
-- set_head(newp, newsize|IS_MMAPPED);
-- UNLOCK;
-- return chunk2mem(newp);
-- }
--
-- /* Otherwise, give back leader, use the rest */
-- set_head(newp, newsize | PREV_INUSE);
-- set_inuse_bit_at_offset(newp, newsize);
-- set_head_size(p, leadsize);
-- free(chunk2mem(p));
-- p = newp;
-+ /*
-+ Find an aligned spot inside chunk. Since we need to give back
-+ leading space in a chunk of at least MINSIZE, if the first
-+ calculation places us at a spot with less than MINSIZE leader,
-+ we can move to the next aligned spot -- we've allocated enough
-+ total room so that this is always possible.
-+ */
-+
-+ brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) &
-+ -((signed long) alignment)));
-+ if ((unsigned long)(brk - (char*)(p)) < MINSIZE)
-+ brk += alignment;
-+
-+ newp = (mchunkptr)brk;
-+ leadsize = brk - (char*)(p);
-+ newsize = chunksize(p) - leadsize;
-+
-+ /* For mmapped chunks, just adjust offset */
-+ if (chunk_is_mmapped(p)) {
-+ newp->prev_size = p->prev_size + leadsize;
-+ set_head(newp, newsize|IS_MMAPPED);
-+ retval = chunk2mem(newp);
-+ goto DONE;
-+ }
-+
-+ /* Otherwise, give back leader, use the rest */
-+ set_head(newp, newsize | PREV_INUSE);
-+ set_inuse_bit_at_offset(newp, newsize);
-+ set_head_size(p, leadsize);
-+ free(chunk2mem(p));
-+ p = newp;
-
-- assert (newsize >= nb &&
-- (((unsigned long)(chunk2mem(p))) % alignment) == 0);
-+ assert (newsize >= nb &&
-+ (((unsigned long)(chunk2mem(p))) % alignment) == 0);
- }
-
- /* Also give back spare room at the end */
- if (!chunk_is_mmapped(p)) {
-- size = chunksize(p);
-- if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
-- remainder_size = size - nb;
-- remainder = chunk_at_offset(p, nb);
-- set_head(remainder, remainder_size | PREV_INUSE);
-- set_head_size(p, nb);
-- free(chunk2mem(remainder));
-- }
-+ size = chunksize(p);
-+ if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) {
-+ remainder_size = size - nb;
-+ remainder = chunk_at_offset(p, nb);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+ set_head_size(p, nb);
-+ free(chunk2mem(remainder));
-+ }
- }
-
- check_inuse_chunk(p);
-- UNLOCK;
-- return chunk2mem(p);
-+ retval = chunk2mem(p);
-+
-+ DONE:
-+ __MALLOC_UNLOCK;
-+ return retval;
- }
-
-diff --git a/libc/stdlib/malloc-standard/realloc.c b/libc/stdlib/malloc-standard/realloc.c
-index 1950130..9ca4b26 100644
---- a/libc/stdlib/malloc-standard/realloc.c
-+++ b/libc/stdlib/malloc-standard/realloc.c
-@@ -8,7 +8,7 @@
- VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-
- Note: There may be an updated version of this malloc obtainable at
-- ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
- Check before installing!
-
- Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
-@@ -23,14 +23,14 @@ void* realloc(void* oldmem, size_t bytes
- {
- mstate av;
-
-- size_t nb; /* padded request size */
-+ size_t nb; /* padded request size */
-
- mchunkptr oldp; /* chunk corresponding to oldmem */
-- size_t oldsize; /* its size */
-+ size_t oldsize; /* its size */
-
- mchunkptr newp; /* chunk to return */
-- size_t newsize; /* its size */
-- void* newmem; /* corresponding user mem */
-+ size_t newsize; /* its size */
-+ void* newmem; /* corresponding user mem */
-
- mchunkptr next; /* next contiguous chunk after oldp */
-
-@@ -40,21 +40,23 @@ void* realloc(void* oldmem, size_t bytes
- mchunkptr bck; /* misc temp for linking */
- mchunkptr fwd; /* misc temp for linking */
-
-- unsigned long copysize; /* bytes to copy */
-+ unsigned long copysize; /* bytes to copy */
- unsigned int ncopies; /* size_t words to copy */
-- size_t* s; /* copy source */
-- size_t* d; /* copy destination */
-+ size_t* s; /* copy source */
-+ size_t* d; /* copy destination */
-+
-+ void *retval;
-
-
- /* Check for special cases. */
- if (! oldmem)
-- return malloc(bytes);
-+ return malloc(bytes);
- if (! bytes) {
-- free (oldmem);
-- return malloc(bytes);
-+ free (oldmem);
-+ return malloc(bytes);
- }
-
-- LOCK;
-+ __MALLOC_LOCK;
- av = get_malloc_state();
- checked_request2size(bytes, nb);
-
-@@ -65,173 +67,176 @@ void* realloc(void* oldmem, size_t bytes
-
- if (!chunk_is_mmapped(oldp)) {
-
-- if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
-- /* already big enough; split below */
-- newp = oldp;
-- newsize = oldsize;
-- }
--
-- else {
-- next = chunk_at_offset(oldp, oldsize);
--
-- /* Try to expand forward into top */
-- if (next == av->top &&
-- (unsigned long)(newsize = oldsize + chunksize(next)) >=
-- (unsigned long)(nb + MINSIZE)) {
-- set_head_size(oldp, nb);
-- av->top = chunk_at_offset(oldp, nb);
-- set_head(av->top, (newsize - nb) | PREV_INUSE);
-- UNLOCK;
-- return chunk2mem(oldp);
-- }
--
-- /* Try to expand forward into next chunk; split off remainder below */
-- else if (next != av->top &&
-- !inuse(next) &&
-- (unsigned long)(newsize = oldsize + chunksize(next)) >=
-- (unsigned long)(nb)) {
-- newp = oldp;
-- unlink(next, bck, fwd);
-- }
--
-- /* allocate, copy, free */
-- else {
-- newmem = malloc(nb - MALLOC_ALIGN_MASK);
-- if (newmem == 0) {
-- UNLOCK;
-- return 0; /* propagate failure */
-- }
--
-- newp = mem2chunk(newmem);
-- newsize = chunksize(newp);
--
-- /*
-- Avoid copy if newp is next chunk after oldp.
-- */
-- if (newp == next) {
-- newsize += oldsize;
-- newp = oldp;
-+ if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
-+ /* already big enough; split below */
-+ newp = oldp;
-+ newsize = oldsize;
- }
-+
- else {
-- /*
-- Unroll copy of <= 36 bytes (72 if 8byte sizes)
-- We know that contents have an odd number of
-- size_t-sized words; minimally 3.
-- */
--
-- copysize = oldsize - (sizeof(size_t));
-- s = (size_t*)(oldmem);
-- d = (size_t*)(newmem);
-- ncopies = copysize / sizeof(size_t);
-- assert(ncopies >= 3);
--
-- if (ncopies > 9)
-- memcpy(d, s, copysize);
--
-- else {
-- *(d+0) = *(s+0);
-- *(d+1) = *(s+1);
-- *(d+2) = *(s+2);
-- if (ncopies > 4) {
-- *(d+3) = *(s+3);
-- *(d+4) = *(s+4);
-- if (ncopies > 6) {
-- *(d+5) = *(s+5);
-- *(d+6) = *(s+6);
-- if (ncopies > 8) {
-- *(d+7) = *(s+7);
-- *(d+8) = *(s+8);
-+ next = chunk_at_offset(oldp, oldsize);
-+
-+ /* Try to expand forward into top */
-+ if (next == av->top &&
-+ (unsigned long)(newsize = oldsize + chunksize(next)) >=
-+ (unsigned long)(nb + MINSIZE)) {
-+ set_head_size(oldp, nb);
-+ av->top = chunk_at_offset(oldp, nb);
-+ set_head(av->top, (newsize - nb) | PREV_INUSE);
-+ retval = chunk2mem(oldp);
-+ goto DONE;
-+ }
-+
-+ /* Try to expand forward into next chunk; split off remainder below */
-+ else if (next != av->top &&
-+ !inuse(next) &&
-+ (unsigned long)(newsize = oldsize + chunksize(next)) >=
-+ (unsigned long)(nb)) {
-+ newp = oldp;
-+ unlink(next, bck, fwd);
-+ }
-+
-+ /* allocate, copy, free */
-+ else {
-+ newmem = malloc(nb - MALLOC_ALIGN_MASK);
-+ if (newmem == 0) {
-+ retval = 0; /* propagate failure */
-+ goto DONE;
-+ }
-+
-+ newp = mem2chunk(newmem);
-+ newsize = chunksize(newp);
-+
-+ /*
-+ Avoid copy if newp is next chunk after oldp.
-+ */
-+ if (newp == next) {
-+ newsize += oldsize;
-+ newp = oldp;
-+ }
-+ else {
-+ /*
-+ Unroll copy of <= 36 bytes (72 if 8byte sizes)
-+ We know that contents have an odd number of
-+ size_t-sized words; minimally 3.
-+ */
-+
-+ copysize = oldsize - (sizeof(size_t));
-+ s = (size_t*)(oldmem);
-+ d = (size_t*)(newmem);
-+ ncopies = copysize / sizeof(size_t);
-+ assert(ncopies >= 3);
-+
-+ if (ncopies > 9)
-+ memcpy(d, s, copysize);
-+
-+ else {
-+ *(d+0) = *(s+0);
-+ *(d+1) = *(s+1);
-+ *(d+2) = *(s+2);
-+ if (ncopies > 4) {
-+ *(d+3) = *(s+3);
-+ *(d+4) = *(s+4);
-+ if (ncopies > 6) {
-+ *(d+5) = *(s+5);
-+ *(d+6) = *(s+6);
-+ if (ncopies > 8) {
-+ *(d+7) = *(s+7);
-+ *(d+8) = *(s+8);
-+ }
-+ }
-+ }
-+ }
-+
-+ free(oldmem);
-+ check_inuse_chunk(newp);
-+ retval = chunk2mem(newp);
-+ goto DONE;
- }
-- }
- }
-- }
-+ }
-+
-+ /* If possible, free extra space in old or extended chunk */
-+
-+ assert((unsigned long)(newsize) >= (unsigned long)(nb));
-+
-+ remainder_size = newsize - nb;
-
-- free(oldmem);
-- check_inuse_chunk(newp);
-- UNLOCK;
-- return chunk2mem(newp);
-- }
-- }
-- }
--
-- /* If possible, free extra space in old or extended chunk */
--
-- assert((unsigned long)(newsize) >= (unsigned long)(nb));
--
-- remainder_size = newsize - nb;
--
-- if (remainder_size < MINSIZE) { /* not enough extra to split off */
-- set_head_size(newp, newsize);
-- set_inuse_bit_at_offset(newp, newsize);
-- }
-- else { /* split remainder */
-- remainder = chunk_at_offset(newp, nb);
-- set_head_size(newp, nb);
-- set_head(remainder, remainder_size | PREV_INUSE);
-- /* Mark remainder as inuse so free() won't complain */
-- set_inuse_bit_at_offset(remainder, remainder_size);
-- free(chunk2mem(remainder));
-- }
--
-- check_inuse_chunk(newp);
-- UNLOCK;
-- return chunk2mem(newp);
-+ if (remainder_size < MINSIZE) { /* not enough extra to split off */
-+ set_head_size(newp, newsize);
-+ set_inuse_bit_at_offset(newp, newsize);
-+ }
-+ else { /* split remainder */
-+ remainder = chunk_at_offset(newp, nb);
-+ set_head_size(newp, nb);
-+ set_head(remainder, remainder_size | PREV_INUSE);
-+ /* Mark remainder as inuse so free() won't complain */
-+ set_inuse_bit_at_offset(remainder, remainder_size);
-+ free(chunk2mem(remainder));
-+ }
-+
-+ check_inuse_chunk(newp);
-+ retval = chunk2mem(newp);
-+ goto DONE;
- }
-
- /*
-- Handle mmap cases
-- */
-+ Handle mmap cases
-+ */
-
- else {
-- size_t offset = oldp->prev_size;
-- size_t pagemask = av->pagesize - 1;
-- char *cp;
-- unsigned long sum;
--
-- /* Note the extra (sizeof(size_t)) overhead */
-- newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask;
--
-- /* don't need to remap if still within same page */
-- if (oldsize == newsize - offset) {
-- UNLOCK;
-- return oldmem;
-- }
--
-- cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
--
-- if (cp != (char*)MORECORE_FAILURE) {
--
-- newp = (mchunkptr)(cp + offset);
-- set_head(newp, (newsize - offset)|IS_MMAPPED);
--
-- assert(aligned_OK(chunk2mem(newp)));
-- assert((newp->prev_size == offset));
--
-- /* update statistics */
-- sum = av->mmapped_mem += newsize - oldsize;
-- if (sum > (unsigned long)(av->max_mmapped_mem))
-- av->max_mmapped_mem = sum;
-- sum += av->sbrked_mem;
-- if (sum > (unsigned long)(av->max_total_mem))
-- av->max_total_mem = sum;
--
-- UNLOCK;
-- return chunk2mem(newp);
-- }
--
-- /* Note the extra (sizeof(size_t)) overhead. */
-- if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t))))
-- newmem = oldmem; /* do nothing */
-- else {
-- /* Must alloc, copy, free. */
-- newmem = malloc(nb - MALLOC_ALIGN_MASK);
-- if (newmem != 0) {
-- memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t)));
-- free(oldmem);
-- }
-- }
-- UNLOCK;
-- return newmem;
-+ size_t offset = oldp->prev_size;
-+ size_t pagemask = av->pagesize - 1;
-+ char *cp;
-+ unsigned long sum;
-+
-+ /* Note the extra (sizeof(size_t)) overhead */
-+ newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask;
-+
-+ /* don't need to remap if still within same page */
-+ if (oldsize == newsize - offset) {
-+ retval = oldmem;
-+ goto DONE;
-+ }
-+
-+ cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
-+
-+ if (cp != (char*)MORECORE_FAILURE) {
-+
-+ newp = (mchunkptr)(cp + offset);
-+ set_head(newp, (newsize - offset)|IS_MMAPPED);
-+
-+ assert(aligned_OK(chunk2mem(newp)));
-+ assert((newp->prev_size == offset));
-+
-+ /* update statistics */
-+ sum = av->mmapped_mem += newsize - oldsize;
-+ if (sum > (unsigned long)(av->max_mmapped_mem))
-+ av->max_mmapped_mem = sum;
-+ sum += av->sbrked_mem;
-+ if (sum > (unsigned long)(av->max_total_mem))
-+ av->max_total_mem = sum;
-+
-+ retval = chunk2mem(newp);
-+ goto DONE;
-+ }
-+
-+ /* Note the extra (sizeof(size_t)) overhead. */
-+ if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t))))
-+ newmem = oldmem; /* do nothing */
-+ else {
-+ /* Must alloc, copy, free. */
-+ newmem = malloc(nb - MALLOC_ALIGN_MASK);
-+ if (newmem != 0) {
-+ memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t)));
-+ free(oldmem);
-+ }
-+ }
-+ retval = newmem;
- }
-+
-+ DONE:
-+ __MALLOC_UNLOCK;
-+ return retval;
- }
-
-diff --git a/libc/stdlib/random.c b/libc/stdlib/random.c
-index b0a00e1..1bd63bc 100644
---- a/libc/stdlib/random.c
-+++ b/libc/stdlib/random.c
-@@ -27,16 +27,14 @@
- #include <limits.h>
- #include <stddef.h>
- #include <stdlib.h>
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
-+
- /* POSIX.1c requires that there is mutual exclusion for the `rand' and
- `srand' functions to prevent concurrent calls from modifying common
- data. */
--static pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
--#else
--#define __pthread_mutex_lock(x)
--#define __pthread_mutex_unlock(x)
--#endif
-+
-+#include <bits/uClibc_mutex.h>
-+
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
-
- /* An improved random number generation package. In addition to the standard
- rand()/srand() like interface, this package also has a special state info
-@@ -184,9 +182,9 @@ static struct random_data unsafe_state =
- for default usage relies on values produced by this routine. */
- void srandom (unsigned int x)
- {
-- __pthread_mutex_lock(&lock);
-+ __UCLIBC_MUTEX_LOCK(mylock);
- srandom_r (x, &unsafe_state);
-- __pthread_mutex_unlock(&lock);
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- }
- weak_alias (srandom, srand)
-
-@@ -205,10 +203,10 @@ char * initstate (unsigned int seed, cha
- {
- int32_t *ostate;
-
-- __pthread_mutex_lock(&lock);
-+ __UCLIBC_MUTEX_LOCK(mylock);
- ostate = &unsafe_state.state[-1];
- initstate_r (seed, arg_state, n, &unsafe_state);
-- __pthread_mutex_unlock(&lock);
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return (char *) ostate;
- }
-
-@@ -224,11 +222,11 @@ char * setstate (char *arg_state)
- {
- int32_t *ostate;
-
-- __pthread_mutex_lock(&lock);
-+ __UCLIBC_MUTEX_LOCK(mylock);
- ostate = &unsafe_state.state[-1];
- if (setstate_r (arg_state, &unsafe_state) < 0)
- ostate = NULL;
-- __pthread_mutex_unlock(&lock);
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return (char *) ostate;
- }
-
-@@ -247,9 +245,9 @@ long int random ()
- {
- int32_t retval;
-
-- __pthread_mutex_lock(&lock);
-+ __UCLIBC_MUTEX_LOCK(mylock);
- random_r (&unsafe_state, &retval);
-- __pthread_mutex_unlock(&lock);
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return retval;
- }
-
-diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c
-index d0cfe52..2d899cc 100644
---- a/libc/stdlib/setenv.c
-+++ b/libc/stdlib/setenv.c
-@@ -17,7 +17,7 @@
- 02111-1307 USA.
-
- modified for uClibc by Erik Andersen <andersen@codepoet.org>
-- */
-+*/
-
- #define _GNU_SOURCE
- #include <features.h>
-@@ -26,16 +26,9 @@
- #include <string.h>
- #include <unistd.h>
-
--#ifdef __UCLIBC_HAS_THREADS__
--#include <pthread.h>
--static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
--# define LOCK __pthread_mutex_lock(&mylock)
--# define UNLOCK __pthread_mutex_unlock(&mylock);
--#else
--# define LOCK
--# define UNLOCK
--#endif
-+#include <bits/uClibc_mutex.h>
-
-+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
-
- /* If this variable is not a null pointer we allocated the current
- environment. */
-@@ -49,14 +42,15 @@ static char **last_environ;
- to reuse values once generated for a `setenv' call since we can never
- free the strings. */
- int __add_to_environ (const char *name, const char *value,
-- const char *combined, int replace)
-+ const char *combined, int replace)
- {
- register char **ep;
- register size_t size;
- const size_t namelen = strlen (name);
- const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
-+ int rv = -1;
-
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
-
- /* We have to get the pointer now that we have the lock and not earlier
- since another thread might have created a new environment. */
-@@ -64,72 +58,72 @@ int __add_to_environ (const char *name,
-
- size = 0;
- if (ep != NULL) {
-- for (; *ep != NULL; ++ep) {
-- if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
-- break;
-- else
-- ++size;
-- }
-+ for (; *ep != NULL; ++ep) {
-+ if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
-+ break;
-+ else
-+ ++size;
-+ }
- }
-
- if (ep == NULL || *ep == NULL) {
-- char **new_environ;
-+ char **new_environ;
-
-- /* We allocated this space; we can extend it. */
-- new_environ = (char **) realloc (last_environ,
-- (size + 2) * sizeof (char *));
-- if (new_environ == NULL) {
-- UNLOCK;
-- return -1;
-- }
--
-- /* If the whole entry is given add it. */
-- if (combined != NULL) {
-- /* We must not add the string to the search tree since it belongs
-- to the user. */
-- new_environ[size] = (char *) combined;
-- } else {
-- /* See whether the value is already known. */
-- new_environ[size] = (char *) malloc (namelen + 1 + vallen);
-- if (new_environ[size] == NULL) {
-- __set_errno (ENOMEM);
-- UNLOCK;
-- return -1;
-- }
--
-- memcpy (new_environ[size], name, namelen);
-- new_environ[size][namelen] = '=';
-- memcpy (&new_environ[size][namelen + 1], value, vallen);
-- }
--
-- if (__environ != last_environ) {
-- memcpy ((char *) new_environ, (char *) __environ,
-- size * sizeof (char *));
-- }
-+ /* We allocated this space; we can extend it. */
-+ new_environ = (char **) realloc (last_environ,
-+ (size + 2) * sizeof (char *));
-+ if (new_environ == NULL) {
-+ goto DONE;
-+ }
-+
-+ /* If the whole entry is given add it. */
-+ if (combined != NULL) {
-+ /* We must not add the string to the search tree since it belongs
-+ to the user. */
-+ new_environ[size] = (char *) combined;
-+ } else {
-+ /* See whether the value is already known. */
-+ new_environ[size] = (char *) malloc (namelen + 1 + vallen);
-+ if (new_environ[size] == NULL) {
-+ __set_errno (ENOMEM);
-+ goto DONE;
-+ }
-+
-+ memcpy (new_environ[size], name, namelen);
-+ new_environ[size][namelen] = '=';
-+ memcpy (&new_environ[size][namelen + 1], value, vallen);
-+ }
-+
-+ if (__environ != last_environ) {
-+ memcpy ((char *) new_environ, (char *) __environ,
-+ size * sizeof (char *));
-+ }
-
-- new_environ[size + 1] = NULL;
-- last_environ = __environ = new_environ;
-+ new_environ[size + 1] = NULL;
-+ last_environ = __environ = new_environ;
- } else if (replace) {
-- char *np;
-+ char *np;
-
-- /* Use the user string if given. */
-- if (combined != NULL) {
-- np = (char *) combined;
-- } else {
-- np = malloc (namelen + 1 + vallen);
-- if (np == NULL) {
-- UNLOCK;
-- return -1;
-- }
-- memcpy (np, name, namelen);
-- np[namelen] = '=';
-- memcpy (&np[namelen + 1], value, vallen);
-- }
-- *ep = np;
-- }
--
-- UNLOCK;
-- return 0;
-+ /* Use the user string if given. */
-+ if (combined != NULL) {
-+ np = (char *) combined;
-+ } else {
-+ np = malloc (namelen + 1 + vallen);
-+ if (np == NULL) {
-+ goto DONE;
-+ }
-+ memcpy (np, name, namelen);
-+ np[namelen] = '=';
-+ memcpy (&np[namelen + 1], value, vallen);
-+ }
-+ *ep = np;
-+ }
-+
-+ rv = 0;
-+
-+ DONE:
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
-+ return rv;
- }
-
- int setenv (const char *name, const char *value, int replace)
-@@ -143,26 +137,26 @@ int unsetenv (const char *name)
- char **ep;
-
- if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) {
-- __set_errno (EINVAL);
-- return -1;
-+ __set_errno (EINVAL);
-+ return -1;
- }
-
- len = strlen (name);
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- ep = __environ;
- while (*ep != NULL) {
-- if (!strncmp (*ep, name, len) && (*ep)[len] == '=') {
-- /* Found it. Remove this pointer by moving later ones back. */
-- char **dp = ep;
-- do {
-- dp[0] = dp[1];
-- } while (*dp++);
-- /* Continue the loop in case NAME appears again. */
-- } else {
-- ++ep;
-- }
-+ if (!strncmp (*ep, name, len) && (*ep)[len] == '=') {
-+ /* Found it. Remove this pointer by moving later ones back. */
-+ char **dp = ep;
-+ do {
-+ dp[0] = dp[1];
-+ } while (*dp++);
-+ /* Continue the loop in case NAME appears again. */
-+ } else {
-+ ++ep;
-+ }
- }
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return 0;
- }
-
-@@ -171,15 +165,15 @@ int unsetenv (const char *name)
- for Fortran 77) requires this function. */
- int clearenv (void)
- {
-- LOCK;
-+ __UCLIBC_MUTEX_LOCK(mylock);
- if (__environ == last_environ && __environ != NULL) {
-- /* We allocated this environment so we can free it. */
-- free (__environ);
-- last_environ = NULL;
-+ /* We allocated this environment so we can free it. */
-+ free (__environ);
-+ last_environ = NULL;
- }
- /* Clear the environment pointer removes the whole environment. */
- __environ = NULL;
-- UNLOCK;
-+ __UCLIBC_MUTEX_UNLOCK(mylock);
- return 0;
- }
-
-@@ -190,10 +184,10 @@ int putenv (char *string)
- const char *const name_end = strchr (string, '=');
-
- if (name_end != NULL) {
-- char *name = strndup(string, name_end - string);
-- result = __add_to_environ (name, NULL, string, 1);
-- free(name);
-- return(result);
-+ char *name = strndup(string, name_end - string);
-+ result = __add_to_environ (name, NULL, string, 1);
-+ free(name);
-+ return(result);
- }
- unsetenv (string);
- return 0;
-diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h
-index 40cd5fe..3c6911e 100644
---- a/libc/sysdeps/linux/common/bits/uClibc_stdio.h
-+++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h
-@@ -116,9 +116,7 @@
- #endif
-
- /**********************************************************************/
--#ifdef __UCLIBC_HAS_THREADS__
--/* Need this for pthread_mutex_t. */
--#include <bits/pthreadtypes.h>
-+#include <bits/uClibc_mutex.h>
-
- /* user_locking
- * 0 : do auto locking/unlocking
-@@ -132,43 +130,37 @@
- * This way, we avoid calling the weak lock/unlock functions.
- */
-
--#define __STDIO_AUTO_THREADLOCK_VAR int __infunc_user_locking
--
--#define __STDIO_AUTO_THREADLOCK(__stream) \
-- if ((__infunc_user_locking = (__stream)->__user_locking) == 0) { \
-- __pthread_mutex_lock(&(__stream)->__lock); \
-- }
--
--#define __STDIO_AUTO_THREADUNLOCK(__stream) \
-- if (__infunc_user_locking == 0) { \
-- __pthread_mutex_unlock(&(__stream)->__lock); \
-- }
-+#define __STDIO_AUTO_THREADLOCK_VAR \
-+ __UCLIBC_MUTEX_AUTO_LOCK_VAR(__infunc_user_locking)
-
--#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1)
-+#define __STDIO_AUTO_THREADLOCK(__stream) \
-+ __UCLIBC_MUTEX_AUTO_LOCK((__stream)->__lock, __infunc_user_locking, \
-+ (__stream)->__user_locking)
-
--#define __STDIO_ALWAYS_THREADLOCK(__stream) \
-- __pthread_mutex_lock(&(__stream)->__lock)
-+#define __STDIO_AUTO_THREADUNLOCK(__stream) \
-+ __UCLIBC_MUTEX_AUTO_UNLOCK((__stream)->__lock, __infunc_user_locking)
-
--#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) \
-- __pthread_mutex_trylock(&(__stream)->__lock)
-+#define __STDIO_ALWAYS_THREADLOCK(__stream) \
-+ __UCLIBC_MUTEX_LOCK((__stream)->__lock)
-
--#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \
-- __pthread_mutex_unlock(&(__stream)->__lock)
-+#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \
-+ __UCLIBC_MUTEX_UNLOCK((__stream)->__lock)
-
--#else /* __UCLIBC_HAS_THREADS__ */
-+#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream) \
-+ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE((__stream)->__lock)
-
--#define __STDIO_AUTO_THREADLOCK_VAR ((void)0)
-+#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream) \
-+ __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE((__stream)->__lock)
-
--#define __STDIO_AUTO_THREADLOCK(__stream) ((void)0)
--#define __STDIO_AUTO_THREADUNLOCK(__stream) ((void)0)
-+#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) \
-+ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE((__stream)->__lock)
-
-+#ifdef __UCLIBC_HAS_THREADS__
-+#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1)
-+#else
- #define __STDIO_SET_USER_LOCKING(__stream) ((void)0)
-+#endif
-
--#define __STDIO_ALWAYS_THREADLOCK(__stream) ((void)0)
--#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) (0) /* Always succeed. */
--#define __STDIO_ALWAYS_THREADUNLOCK(__stream) ((void)0)
--
--#endif /* __UCLIBC_HAS_THREADS__ */
- /**********************************************************************/
-
- #define __STDIO_IOFBF 0 /* Fully buffered. */
-@@ -283,7 +275,7 @@ struct __STDIO_FILE_STRUCT {
- #endif
- #ifdef __UCLIBC_HAS_THREADS__
- int __user_locking;
-- pthread_mutex_t __lock;
-+ __UCLIBC_MUTEX(__lock);
- #endif
- /* Everything after this is unimplemented... and may be trashed. */
- #if __STDIO_BUILTIN_BUF_SIZE > 0
-@@ -358,10 +350,14 @@ extern void _stdio_term(void);
- extern struct __STDIO_FILE_STRUCT *_stdio_openlist;
-
- #ifdef __UCLIBC_HAS_THREADS__
--extern pthread_mutex_t _stdio_openlist_lock;
--extern int _stdio_openlist_delflag;
-+__UCLIBC_MUTEX_EXTERN(_stdio_openlist_add_lock);
-+#ifdef __STDIO_BUFFERS
-+__UCLIBC_MUTEX_EXTERN(_stdio_openlist_del_lock);
-+extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */
-+extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */
-+#endif
- extern int _stdio_user_locking;
--extern void __stdio_init_mutex(pthread_mutex_t *m);
-+extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m);
- #endif
-
- #endif
-diff --git a/libc/sysdeps/linux/common/getdents.c b/libc/sysdeps/linux/common/getdents.c
-index ab6a276..23463e5 100644
---- a/libc/sysdeps/linux/common/getdents.c
-+++ b/libc/sysdeps/linux/common/getdents.c
-@@ -30,8 +30,6 @@
- #include <sys/syscall.h>
-
-
--#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
--
- struct kernel_dirent
- {
- long d_ino;
-diff --git a/libc/sysdeps/linux/common/sigprocmask.c b/libc/sysdeps/linux/common/sigprocmask.c
-index 70ff366..565318d 100644
---- a/libc/sysdeps/linux/common/sigprocmask.c
-+++ b/libc/sysdeps/linux/common/sigprocmask.c
-@@ -23,6 +23,8 @@ int sigprocmask(int how, const sigset_t
- if (set &&
- #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2)
- (((unsigned int) how) > 2)
-+#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3)
-+ (((unsigned int)(how-1)) > 2)
- #else
- #warning "compile time assumption violated.. slow path..."
- ((how != SIG_BLOCK) && (how != SIG_UNBLOCK)
-@@ -48,6 +50,8 @@ int sigprocmask(int how, const sigset_t
- if (set &&
- #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2)
- (((unsigned int) how) > 2)
-+#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3)
-+ (((unsigned int)(how-1)) > 2)
- #else
- #warning "compile time assumption violated.. slow path..."
- ((how != SIG_BLOCK) && (how != SIG_UNBLOCK)
-diff --git a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h
-index b6f52cc..317e5b3 100644
---- a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h
-+++ b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h
-@@ -38,3 +38,6 @@ struct kernel_sigaction {
- void (*sa_restorer)(void);
- int s_resv[1]; /* reserved */
- };
-+
-+extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded,
-+ struct kernel_sigaction *__unbounded, size_t);
-diff --git a/libc/sysdeps/linux/mips/pipe.S b/libc/sysdeps/linux/mips/pipe.S
-index c3afae5..cd88074 100644
---- a/libc/sysdeps/linux/mips/pipe.S
-+++ b/libc/sysdeps/linux/mips/pipe.S
-@@ -7,25 +7,36 @@
- #include <asm/unistd.h>
- #include <asm/regdef.h>
-
-- .globl pipe
-- .ent pipe, 0
-+ .globl pipe
-+ .ent pipe, 0
- pipe:
-- addiu sp,sp,-24
-- sw a0,16(sp)
-- li v0,__NR_pipe
-- syscall
-- beqz a3, 1f
-- la t3, errno
-- sw v0, (t3)
-- li v0, -1
-- b 2f
-+ .frame sp, 24, sp
-+#ifdef __PIC__
-+ .set noreorder
-+ .cpload $25
-+ .set reorder
-+ addiu sp,sp,-24
-+ .cprestore 16
-+#else
-+ addiu sp,sp,-24
-+#endif
-+ sw a0,16(sp)
-+ li v0,__NR_pipe
-+ syscall
-+ beqz a3, 1f
-+#ifdef __PIC__
-+ la t0, __syscall_error
-+ jr t9
-+#else
-+ j __syscall_error
-+#endif
- 1:
-- lw a0, 16(sp)
-- sw v0, 0(a0)
-- sw v1, 4(a0)
-- li v0, 0
-+ lw a0, 16(sp)
-+ sw v0, 0(a0)
-+ sw v1, 4(a0)
-+ li v0, 0
- 2:
-- addiu sp,sp,24
-- j ra
-- .end pipe
-- .size pipe,.-pipe
-+ addiu sp,sp,24
-+ j ra
-+ .end pipe
-+ .size pipe,.-pipe
-diff --git a/libcrypt/des.c b/libcrypt/des.c
-index 3b49a7a..f7a6be1 100644
---- a/libcrypt/des.c
-+++ b/libcrypt/des.c
-@@ -504,7 +504,7 @@ do_des( u_int32_t l_in, u_int32_t r_in,
- kl = kl1;
- kr = kr1;
- round = 16;
-- while (round--) {
-+ do {
- /*
- * Expand R to 48 bits (simulate the E-box).
- */
-@@ -540,7 +540,7 @@ do_des( u_int32_t l_in, u_int32_t r_in,
- f ^= l;
- l = r;
- r = f;
-- }
-+ } while (--round);
- r = l;
- l = f;
- }
-diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c
-index eb544f3..cfec2b7 100644
---- a/libpthread/linuxthreads/ptfork.c
-+++ b/libpthread/linuxthreads/ptfork.c
-@@ -26,6 +26,15 @@
- #include "pthread.h"
- #include "internals.h"
-
-+#warning hack alert... should be sufficent for system(), but what about other libc mutexes?
-+#include <bits/uClibc_mutex.h>
-+
-+__UCLIBC_MUTEX_EXTERN(__malloc_lock);
-+
-+#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
-+#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
-+#warning hack alert block end
-+
- struct handler_list {
- void (*handler)(void);
- struct handler_list * next;
-@@ -91,9 +100,18 @@ pid_t __fork(void)
- parent = pthread_atfork_parent;
- pthread_mutex_unlock(&pthread_atfork_lock);
- pthread_call_handlers(prepare);
-+
-+#warning hack alert
-+ __MALLOC_LOCK;
-+
- pid = __libc_fork();
-+
-+#warning hack alert
-+ __MALLOC_UNLOCK;
-+
- if (pid == 0) {
- __pthread_reset_main_thread();
-+#warning need to reconsider __fresetlockfiles!
- __fresetlockfiles();
- pthread_call_handlers(child);
- } else {
-diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h
---- uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h 1969-12-31 17:00:00.000000000 -0700
-+++ uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h 2006-03-08 11:21:58.000000000 -0700
-@@ -0,0 +1,87 @@
-+/* Copyright (C) 2006 Manuel Novoa III <mjn3@codepoet.org>
-+ *
-+ * GNU Library General Public License (LGPL) version 2 or later.
-+ *
-+ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
-+ */
-+
-+#ifndef _UCLIBC_MUTEX_H
-+#define _UCLIBC_MUTEX_H
-+
-+#include <features.h>
-+
-+#ifdef __UCLIBC_HAS_THREADS__
-+
-+#include <pthread.h>
-+
-+#define __UCLIBC_MUTEX_TYPE pthread_mutex_t
-+
-+#define __UCLIBC_MUTEX(M) pthread_mutex_t M
-+#define __UCLIBC_MUTEX_INIT(M,I) pthread_mutex_t M = I
-+#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I
-+#define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M
-+
-+#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \
-+ __pthread_mutex_lock(&(M))
-+
-+#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \
-+ __pthread_mutex_unlock(&(M))
-+
-+#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \
-+ __pthread_mutex_trylock(&(M))
-+
-+#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \
-+ do { \
-+ struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \
-+ if (C) { \
-+ _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \
-+ __pthread_mutex_unlock, \
-+ &(M)); \
-+ __pthread_mutex_lock(&(M)); \
-+ } \
-+ ((void)0)
-+
-+#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) \
-+ if (C) { \
-+ _pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);\
-+ } \
-+ } while (0)
-+
-+#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) int A
-+
-+#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) \
-+ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,((A=(V)) == 0))
-+
-+#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) \
-+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,(A == 0))
-+
-+#define __UCLIBC_MUTEX_LOCK(M) \
-+ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1)
-+
-+#define __UCLIBC_MUTEX_UNLOCK(M) \
-+ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1)
-+
-+#else
-+
-+#define __UCLIBC_MUTEX(M) void *__UCLIBC_MUTEX_DUMMY_ ## M
-+#define __UCLIBC_MUTEX_INIT(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M
-+#define __UCLIBC_MUTEX_STATIC(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M
-+#define __UCLIBC_MUTEX_EXTERN(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M
-+
-+#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) ((void)0)
-+#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) ((void)0)
-+#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) (0) /* Always succeed? */
-+
-+#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) ((void)0)
-+#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) ((void)0)
-+
-+#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) ((void)0)
-+#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) ((void)0)
-+#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) ((void)0)
-+
-+#define __UCLIBC_MUTEX_LOCK(M) ((void)0)
-+#define __UCLIBC_MUTEX_UNLOCK(M) ((void)0)
-+
-+#endif
-+
-+#endif /* _UCLIBC_MUTEX_H */
-diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c
---- uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c 2005-08-17 16:49:44.000000000 -0600
-+++ uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c 1969-12-31 17:00:00.000000000 -0700
-@@ -1,23 +0,0 @@
--/* pipe system call for Linux/MIPS */
--
--/*see uClibc's sh/pipe.c and glibc-2.2.4's mips/pipe.S */
--
--#include <errno.h>
--#include <unistd.h>
--#include <syscall.h>
--
--int pipe(int *fd)
--{
-- register long int res __asm__ ("$2"); // v0
-- register long int res2 __asm__ ("$3"); // v1
--
-- asm ("move\t$4,%2\n\t" // $4 = a0
-- "syscall" /* Perform the system call. */
-- : "=r" (res)
-- : "0" (__NR_pipe), "r" (fd)
-- : "$4", "$7");
--
-- fd[0] = res;
-- fd[1] = res2;
-- return(0);
--}
+++ /dev/null
---- uClibc/libc/misc/time/time.c (revision 16488)
-+++ uClibc/libc/misc/time/time.c (working copy)
-@@ -157,6 +157,22 @@
- #define TZNAME_MAX _POSIX_TZNAME_MAX
- #endif
-
-+#if defined (L_tzset) || defined (L_localtime_r) || defined(L_strftime) || \
-+ defined(L__time_mktime) || defined(L__time_mktime_tzi) || \
-+ ((defined(L_strftime) || defined(L_strftime_l)) && \
-+ defined(__UCLIBC_HAS_XLOCALE__))
-+
-+void _time_tzset (int);
-+
-+#ifndef L__time_mktime
-+
-+ /* Jan 1, 2007 Z - tm = 0,0,0,1,0,107,1,0,0 */
-+
-+const static time_t new_rule_starts = 1167609600;
-+
-+#endif
-+#endif
-+
- /**********************************************************************/
- /* The era code is currently unfinished. */
- /* #define ENABLE_ERA_CODE */
-@@ -532,7 +548,7 @@
- {
- __UCLIBC_MUTEX_LOCK(_time_tzlock);
-
-- tzset();
-+ _time_tzset(*timer < new_rule_starts);
-
- __time_localtime_tzi(timer, result, _time_tzinfo);
-
-@@ -956,7 +972,8 @@
- unsigned char mod;
- unsigned char code;
-
-- tzset(); /* We'll, let's get this out of the way. */
-+ /* We'll, let's get this out of the way. */
-+ _time_tzset(_time_mktime((struct tm *) timeptr, 0) < new_rule_starts);
-
- lvl = 0;
- p = format;
-@@ -1644,7 +1661,9 @@
- 6, 0, 0, /* Note: overloaded for non-M non-J case... */
- 0, 1, 0, /* J */
- ',', 'M', '4', '.', '1', '.', '0',
-- ',', 'M', '1', '0', '.', '5', '.', '0', 0
-+ ',', 'M', '1', '0', '.', '5', '.', '0', 0,
-+ ',', 'M', '3', '.', '2', '.', '0',
-+ ',', 'M', '1', '1', '.', '1', '.', '0', 0
- };
-
- #define TZ vals
-@@ -1652,6 +1671,7 @@
- #define RANGE (vals + 7)
- #define RULE (vals + 11 - 1)
- #define DEFAULT_RULES (vals + 22)
-+#define DEFAULT_2007_RULES (vals + 38)
-
- /* Initialize to UTC. */
- int daylight = 0;
-@@ -1774,6 +1794,11 @@
-
- void tzset(void)
- {
-+ _time_tzset((time(NULL)) < new_rule_starts);
-+}
-+
-+void _time_tzset(int use_old_rules)
-+{
- register const char *e;
- register char *s;
- long off;
-@@ -1896,7 +1921,15 @@
- } else { /* OK, we have dst, so get some rules. */
- count = 0;
- if (!*e) { /* No rules so default to US rules. */
-- e = DEFAULT_RULES;
-+ e = use_old_rules ? DEFAULT_RULES : DEFAULT_2007_RULES;
-+#ifdef DEBUG_TZSET
-+ if (e == DEFAULT_RULES)
-+ printf("tzset: Using old rules.\n");
-+ else if (e == DEFAULT_2007_RULES)
-+ printf("tzset: Using new rules\n");
-+ else
-+ printf("tzset: Using undefined rules\n");
-+#endif /* DEBUG_TZSET */
- }
-
- do {
-@@ -2230,6 +2263,8 @@
- --d;
- }
-
-+ _time_tzset (x.tm_year < 2007); /* tm_year was expanded above */
-+
- #ifdef __BCC__
- d = p[5] - 1;
- days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]);
+++ /dev/null
-diff -urN uClibc-0.9.29-0rig/include/assert.h uClibc-0.9.29/include/assert.h
---- uClibc-0.9.29-0rig/include/assert.h 2005-11-03 23:42:46.000000000 +0100
-+++ uClibc-0.9.29/include/assert.h 2007-08-13 19:10:57.000000000 +0200
-@@ -31,7 +31,7 @@
- #define _ASSERT_H 1
- #include <features.h>
-
--#if defined __cplusplus && __GNUC_PREREQ (2,95)
-+#if defined __cplusplus && __GNUC_PREREQ(2,95)
- # define __ASSERT_VOID_CAST static_cast<void>
- #else
- # define __ASSERT_VOID_CAST (void)
-@@ -59,13 +59,17 @@
- (__ASSERT_VOID_CAST ((expr) ? 0 : \
- (__assert (__STRING(expr), __FILE__, __LINE__, \
- __ASSERT_FUNCTION), 0)))
--
-+
-+/* Define some temporaries to workaround tinyx makedepend bug */
-+#define __GNUC_PREREQ_2_6 __GNUC_PREREQ(2, 6)
-+#define __GNUC_PREREQ_2_4 __GNUC_PREREQ(2, 4)
- /* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__'
- which contains the name of the function currently being defined.
- This is broken in G++ before version 2.6.
- C9x has a similar variable called __func__, but prefer the GCC one since
- it demangles C++ function names. */
--# if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4)
-+
-+# if defined __cplusplus ? __GNUC_PREREQ_2_6 : __GNUC_PREREQ_2_4
- # define __ASSERT_FUNCTION __PRETTY_FUNCTION__
- # else
- # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
-diff -urN uClibc-0.9.29-0rig/include/complex.h uClibc-0.9.29/include/complex.h
---- uClibc-0.9.29-0rig/include/complex.h 2002-05-09 10:15:21.000000000 +0200
-+++ uClibc-0.9.29/include/complex.h 2007-08-13 17:55:29.000000000 +0200
-@@ -33,7 +33,7 @@
- /* We might need to add support for more compilers here. But since ISO
- C99 is out hopefully all maintained compilers will soon provide the data
- types `float complex' and `double complex'. */
--#if __GNUC_PREREQ (2, 7) && !__GNUC_PREREQ (2, 97)
-+#if __GNUC_PREREQ(2, 7) && !__GNUC_PREREQ(2, 97)
- # define _Complex __complex__
- #endif
-
-diff -urN uClibc-0.9.29-0rig/include/features.h uClibc-0.9.29/include/features.h
---- uClibc-0.9.29-0rig/include/features.h 2006-11-29 22:10:04.000000000 +0100
-+++ uClibc-0.9.29/include/features.h 2007-08-13 17:55:51.000000000 +0200
-@@ -143,7 +143,7 @@
-
- /* Convenience macros to test the versions of glibc and gcc.
- Use them like this:
-- #if __GNUC_PREREQ (2,8)
-+ #if __GNUC_PREREQ(2,8)
- ... code requiring gcc 2.8 or later ...
- #endif
- Note - they won't work for gcc1 or glibc1, since the _MINOR macros
-@@ -297,7 +297,7 @@
- /* uClibc does not support _FORTIFY_SOURCE */
- #undef _FORTIFY_SOURCE
- #if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 \
-- && __GNUC_PREREQ (4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0
-+ && __GNUC_PREREQ(4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0
- # if _FORTIFY_SOURCE > 1
- # define __USE_FORTIFY_LEVEL 2
- # else
-@@ -366,7 +366,7 @@
- #endif /* !ASSEMBLER */
-
- /* Decide whether we can define 'extern inline' functions in headers. */
--#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \
-+#if __GNUC_PREREQ(2, 7) && defined __OPTIMIZE__ \
- && !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__
- # define __USE_EXTERN_INLINES 1
- #endif
-diff -urN uClibc-0.9.29-0rig/include/tgmath.h uClibc-0.9.29/include/tgmath.h
---- uClibc-0.9.29-0rig/include/tgmath.h 2002-05-09 10:15:21.000000000 +0200
-+++ uClibc-0.9.29/include/tgmath.h 2007-08-13 17:56:17.000000000 +0200
-@@ -34,7 +34,7 @@
- do not try this for now and instead concentrate only on GNU CC. Once
- we have more information support for other compilers might follow. */
-
--#if __GNUC_PREREQ (2, 7)
-+#if __GNUC_PREREQ(2, 7)
-
- # ifdef __NO_LONG_DOUBLE_MATH
- # define __tgml(fct) fct
--- /dev/null
+diff -Nrup a/extra/Configs/Config.avr32 b/extra/Configs/Config.avr32
+--- a/extra/Configs/Config.avr32 1969-12-31 19:00:00.000000000 -0500
++++ b/extra/Configs/Config.avr32 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,42 @@
++#
++# For a description of the syntax of this configuration file,
++# see extra/config/Kconfig-language.txt
++#
++
++config HAVE_ELF
++ bool
++ default y
++
++config TARGET_ARCH
++ default "avr32"
++
++config ARCH_CFLAGS
++ string
++
++config ARCH_LDFLAGS
++ string
++
++config LIBGCC_CFLAGS
++ string
++
++config ARCH_SUPPORTS_BIG_ENDIAN
++ bool
++ default y
++
++config UCLIBC_COMPLETELY_PIC
++ select FORCE_SHAREABLE_TEXT_SEGMENTS
++ bool
++ default y
++
++choice
++ prompt "Target CPU Type"
++ default CONFIG_AP7000
++
++config CONFIG_AP7000
++ bool "AP7000"
++
++endchoice
++
++config LINKRELAX
++ bool "Enable linker optimizations"
++ default n
+diff -Nrup a/extra/Configs/Config.in b/extra/Configs/Config.in
+--- a/extra/Configs/Config.in 2007-01-25 19:01:55.000000000 -0500
++++ b/extra/Configs/Config.in 2008-02-28 19:02:10.000000000 -0500
+@@ -16,6 +16,9 @@ config TARGET_alpha
+ config TARGET_arm
+ bool "arm"
+
++config TARGET_avr32
++ bool "avr32"
++
+ config TARGET_bfin
+ bool "bfin"
+
+@@ -83,6 +86,10 @@ if TARGET_arm
+ source "extra/Configs/Config.arm"
+ endif
+
++if TARGET_avr32
++source "extra/Configs/Config.avr32"
++endif
++
+ if TARGET_bfin
+ source "extra/Configs/Config.bfin"
+ endif
+diff -Nrup a/include/elf.h b/include/elf.h
+--- a/include/elf.h 2007-01-25 19:22:03.000000000 -0500
++++ b/include/elf.h 2008-02-28 19:02:10.000000000 -0500
+@@ -305,6 +305,8 @@ typedef struct
+ /* D30V backend magic number. Written in the absence of an ABI. */
+ #define EM_CYGNUS_D30V 0x7676
+
++#define EM_AVR32 0x18ad
++
+ /* V850 backend magic number. Written in the absense of an ABI. */
+ #define EM_CYGNUS_V850 0x9080
+
+@@ -2751,6 +2753,55 @@ typedef Elf32_Addr Elf32_Conflict;
+ /* Keep this the last entry. */
+ #define R_960_NUM 8
+
++/* Atmel AVR32 relocations. */
++#define R_AVR32_NONE 0
++#define R_AVR32_32 1
++#define R_AVR32_16 2
++#define R_AVR32_8 3
++#define R_AVR32_32_PCREL 4
++#define R_AVR32_16_PCREL 5
++#define R_AVR32_8_PCREL 6
++#define R_AVR32_DIFF32 7
++#define R_AVR32_DIFF16 8
++#define R_AVR32_DIFF8 9
++#define R_AVR32_GOT32 10
++#define R_AVR32_GOT16 11
++#define R_AVR32_GOT8 12
++#define R_AVR32_21S 13
++#define R_AVR32_16U 14
++#define R_AVR32_16S 15
++#define R_AVR32_8S 16
++#define R_AVR32_8S_EXT 17
++#define R_AVR32_22H_PCREL 18
++#define R_AVR32_18W_PCREL 19
++#define R_AVR32_16B_PCREL 20
++#define R_AVR32_16N_PCREL 21
++#define R_AVR32_14UW_PCREL 22
++#define R_AVR32_11H_PCREL 23
++#define R_AVR32_10UW_PCREL 24
++#define R_AVR32_9H_PCREL 25
++#define R_AVR32_9UW_PCREL 26
++#define R_AVR32_HI16 27
++#define R_AVR32_LO16 28
++#define R_AVR32_GOTPC 29
++#define R_AVR32_GOTCALL 30
++#define R_AVR32_LDA_GOT 31
++#define R_AVR32_GOT21S 32
++#define R_AVR32_GOT18SW 33
++#define R_AVR32_GOT16S 34
++#define R_AVR32_GOT7UW 35
++#define R_AVR32_32_CPENT 36
++#define R_AVR32_CPCALL 37
++#define R_AVR32_16_CP 38
++#define R_AVR32_9W_CP 39
++#define R_AVR32_RELATIVE 40
++#define R_AVR32_GLOB_DAT 41
++#define R_AVR32_JMP_SLOT 42
++#define R_AVR32_ALIGN 43
++#define R_AVR32_NUM 44
++
++/* AVR32 dynamic tags */
++#define DT_AVR32_GOTSZ 0x70000001 /* Total size of GOT in bytes */
+
+ /* v850 relocations. */
+ #define R_V850_NONE 0
+diff -Nrup a/include/elf.h.orig b/include/elf.h.orig
+--- a/include/elf.h.orig 1969-12-31 19:00:00.000000000 -0500
++++ b/include/elf.h.orig 2007-01-25 19:22:03.000000000 -0500
+@@ -0,0 +1,2886 @@
++/* This file defines standard ELF types, structures, and macros.
++ Copyright (C) 1995-2003, 2004, 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.
++
++ 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. */
++
++#ifndef _ELF_H
++#define _ELF_H 1
++
++#include <features.h>
++
++__BEGIN_DECLS
++
++/* Standard ELF types. */
++
++#include <stdint.h>
++
++/* Type for a 16-bit quantity. */
++typedef uint16_t Elf32_Half;
++typedef uint16_t Elf64_Half;
++
++/* Types for signed and unsigned 32-bit quantities. */
++typedef uint32_t Elf32_Word;
++typedef int32_t Elf32_Sword;
++typedef uint32_t Elf64_Word;
++typedef int32_t Elf64_Sword;
++
++/* Types for signed and unsigned 64-bit quantities. */
++typedef uint64_t Elf32_Xword;
++typedef int64_t Elf32_Sxword;
++typedef uint64_t Elf64_Xword;
++typedef int64_t Elf64_Sxword;
++
++/* Type of addresses. */
++typedef uint32_t Elf32_Addr;
++typedef uint64_t Elf64_Addr;
++
++/* Type of file offsets. */
++typedef uint32_t Elf32_Off;
++typedef uint64_t Elf64_Off;
++
++/* Type for section indices, which are 16-bit quantities. */
++typedef uint16_t Elf32_Section;
++typedef uint16_t Elf64_Section;
++
++/* Type for version symbol information. */
++typedef Elf32_Half Elf32_Versym;
++typedef Elf64_Half Elf64_Versym;
++
++
++/* The ELF file header. This appears at the start of every ELF file. */
++
++#define EI_NIDENT (16)
++
++typedef struct
++{
++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
++ Elf32_Half e_type; /* Object file type */
++ Elf32_Half e_machine; /* Architecture */
++ Elf32_Word e_version; /* Object file version */
++ Elf32_Addr e_entry; /* Entry point virtual address */
++ Elf32_Off e_phoff; /* Program header table file offset */
++ Elf32_Off e_shoff; /* Section header table file offset */
++ Elf32_Word e_flags; /* Processor-specific flags */
++ Elf32_Half e_ehsize; /* ELF header size in bytes */
++ Elf32_Half e_phentsize; /* Program header table entry size */
++ Elf32_Half e_phnum; /* Program header table entry count */
++ Elf32_Half e_shentsize; /* Section header table entry size */
++ Elf32_Half e_shnum; /* Section header table entry count */
++ Elf32_Half e_shstrndx; /* Section header string table index */
++} Elf32_Ehdr;
++
++typedef struct
++{
++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
++ Elf64_Half e_type; /* Object file type */
++ Elf64_Half e_machine; /* Architecture */
++ Elf64_Word e_version; /* Object file version */
++ Elf64_Addr e_entry; /* Entry point virtual address */
++ Elf64_Off e_phoff; /* Program header table file offset */
++ Elf64_Off e_shoff; /* Section header table file offset */
++ Elf64_Word e_flags; /* Processor-specific flags */
++ Elf64_Half e_ehsize; /* ELF header size in bytes */
++ Elf64_Half e_phentsize; /* Program header table entry size */
++ Elf64_Half e_phnum; /* Program header table entry count */
++ Elf64_Half e_shentsize; /* Section header table entry size */
++ Elf64_Half e_shnum; /* Section header table entry count */
++ Elf64_Half e_shstrndx; /* Section header string table index */
++} Elf64_Ehdr;
++
++/* Fields in the e_ident array. The EI_* macros are indices into the
++ array. The macros under each EI_* macro are the values the byte
++ may have. */
++
++#define EI_MAG0 0 /* File identification byte 0 index */
++#define ELFMAG0 0x7f /* Magic number byte 0 */
++
++#define EI_MAG1 1 /* File identification byte 1 index */
++#define ELFMAG1 'E' /* Magic number byte 1 */
++
++#define EI_MAG2 2 /* File identification byte 2 index */
++#define ELFMAG2 'L' /* Magic number byte 2 */
++
++#define EI_MAG3 3 /* File identification byte 3 index */
++#define ELFMAG3 'F' /* Magic number byte 3 */
++
++/* Conglomeration of the identification bytes, for easy testing as a word. */
++#define ELFMAG "\177ELF"
++#define SELFMAG 4
++
++#define EI_CLASS 4 /* File class byte index */
++#define ELFCLASSNONE 0 /* Invalid class */
++#define ELFCLASS32 1 /* 32-bit objects */
++#define ELFCLASS64 2 /* 64-bit objects */
++#define ELFCLASSNUM 3
++
++#define EI_DATA 5 /* Data encoding byte index */
++#define ELFDATANONE 0 /* Invalid data encoding */
++#define ELFDATA2LSB 1 /* 2's complement, little endian */
++#define ELFDATA2MSB 2 /* 2's complement, big endian */
++#define ELFDATANUM 3
++
++#define EI_VERSION 6 /* File version byte index */
++ /* Value must be EV_CURRENT */
++
++#define EI_OSABI 7 /* OS ABI identification */
++#define ELFOSABI_NONE 0 /* UNIX System V ABI */
++#define ELFOSABI_SYSV 0 /* Alias. */
++#define ELFOSABI_HPUX 1 /* HP-UX */
++#define ELFOSABI_NETBSD 2 /* NetBSD. */
++#define ELFOSABI_LINUX 3 /* Linux. */
++#define ELFOSABI_HURD 4 /* GNU/Hurd */
++#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
++#define ELFOSABI_AIX 7 /* IBM AIX. */
++#define ELFOSABI_IRIX 8 /* SGI Irix. */
++#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
++#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
++#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
++#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
++#define ELFOSABI_OPENVMS 13 /* OpenVMS */
++#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */
++#define ELFOSABI_AROS 15 /* Amiga Research OS */
++#define ELFOSABI_ARM 97 /* ARM */
++#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
++
++#define EI_ABIVERSION 8 /* ABI version */
++
++#define EI_PAD 9 /* Byte index of padding bytes */
++
++/* Legal values for e_type (object file type). */
++
++#define ET_NONE 0 /* No file type */
++#define ET_REL 1 /* Relocatable file */
++#define ET_EXEC 2 /* Executable file */
++#define ET_DYN 3 /* Shared object file */
++#define ET_CORE 4 /* Core file */
++#define ET_NUM 5 /* Number of defined types */
++#define ET_LOOS 0xfe00 /* OS-specific range start */
++#define ET_HIOS 0xfeff /* OS-specific range end */
++#define ET_LOPROC 0xff00 /* Processor-specific range start */
++#define ET_HIPROC 0xffff /* Processor-specific range end */
++
++/* Legal values for e_machine (architecture). */
++
++#define EM_NONE 0 /* No machine */
++#define EM_M32 1 /* AT&T WE 32100 */
++#define EM_SPARC 2 /* SUN SPARC */
++#define EM_386 3 /* Intel 80386 */
++#define EM_68K 4 /* Motorola m68k family */
++#define EM_88K 5 /* Motorola m88k family */
++#define EM_486 6 /* Intel 80486 *//* Reserved for future use */
++#define EM_860 7 /* Intel 80860 */
++#define EM_MIPS 8 /* MIPS R3000 big-endian */
++#define EM_S370 9 /* IBM System/370 */
++#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
++
++#define EM_PARISC 15 /* HPPA */
++#define EM_VPP500 17 /* Fujitsu VPP500 */
++#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
++#define EM_960 19 /* Intel 80960 */
++#define EM_PPC 20 /* PowerPC */
++#define EM_PPC64 21 /* PowerPC 64-bit */
++#define EM_S390 22 /* IBM S390 */
++
++#define EM_V800 36 /* NEC V800 series */
++#define EM_FR20 37 /* Fujitsu FR20 */
++#define EM_RH32 38 /* TRW RH-32 */
++#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */
++#define EM_RCE 39 /* Old name for MCore */
++#define EM_ARM 40 /* ARM */
++#define EM_FAKE_ALPHA 41 /* Digital Alpha */
++#define EM_SH 42 /* Renesas SH */
++#define EM_SPARCV9 43 /* SPARC v9 64-bit */
++#define EM_TRICORE 44 /* Siemens Tricore */
++#define EM_ARC 45 /* Argonaut RISC Core */
++#define EM_H8_300 46 /* Renesas H8/300 */
++#define EM_H8_300H 47 /* Renesas H8/300H */
++#define EM_H8S 48 /* Renesas H8S */
++#define EM_H8_500 49 /* Renesas H8/500 */
++#define EM_IA_64 50 /* Intel Merced */
++#define EM_MIPS_X 51 /* Stanford MIPS-X */
++#define EM_COLDFIRE 52 /* Motorola Coldfire */
++#define EM_68HC12 53 /* Motorola M68HC12 */
++#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
++#define EM_PCP 55 /* Siemens PCP */
++#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
++#define EM_NDR1 57 /* Denso NDR1 microprocessor */
++#define EM_STARCORE 58 /* Motorola Start*Core processor */
++#define EM_ME16 59 /* Toyota ME16 processor */
++#define EM_ST100 60 /* STMicroelectronic ST100 processor */
++#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
++#define EM_X86_64 62 /* AMD x86-64 architecture */
++#define EM_PDSP 63 /* Sony DSP Processor */
++
++#define EM_FX66 66 /* Siemens FX66 microcontroller */
++#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
++#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
++#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
++#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
++#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
++#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
++#define EM_SVX 73 /* Silicon Graphics SVx */
++#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
++#define EM_VAX 75 /* Digital VAX */
++#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
++#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
++#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
++#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
++#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
++#define EM_HUANY 81 /* Harvard University machine-independent object files */
++#define EM_PRISM 82 /* SiTera Prism */
++#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
++#define EM_FR30 84 /* Fujitsu FR30 */
++#define EM_D10V 85 /* Mitsubishi D10V */
++#define EM_D30V 86 /* Mitsubishi D30V */
++#define EM_V850 87 /* NEC v850 */
++#define EM_M32R 88 /* Renesas M32R */
++#define EM_MN10300 89 /* Matsushita MN10300 */
++#define EM_MN10200 90 /* Matsushita MN10200 */
++#define EM_PJ 91 /* picoJava */
++#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
++#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
++#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
++#define EM_IP2K 101 /* Ubicom IP2022 micro controller */
++#define EM_CR 103 /* National Semiconductor CompactRISC */
++#define EM_MSP430 105 /* TI msp430 micro controller */
++#define EM_BLACKFIN 106 /* Analog Devices Blackfin */
++#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
++#define EM_CRX 114 /* National Semiconductor CRX */
++#define EM_NUM 95
++
++/* If it is necessary to assign new unofficial EM_* values, please pick large
++ random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
++ with official or non-GNU unofficial values.
++
++ NOTE: Do not just increment the most recent number by one.
++ Somebody else somewhere will do exactly the same thing, and you
++ will have a collision. Instead, pick a random number.
++
++ Normally, each entity or maintainer responsible for a machine with an
++ unofficial e_machine number should eventually ask registry@caldera.com for
++ an officially blessed number to be added to the list above. */
++
++/* picoJava */
++#define EM_PJ_OLD 99
++
++/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */
++#define EM_CYGNUS_POWERPC 0x9025
++
++/* Old version of Sparc v9, from before the ABI; this should be
++ removed shortly. */
++#define EM_OLD_SPARCV9 11
++
++/* Old version of PowerPC, this should be removed shortly. */
++#define EM_PPC_OLD 17
++
++/* (Deprecated) Temporary number for the OpenRISC processor. */
++#define EM_OR32 0x8472
++
++/* Renesas M32C and M16C. */
++#define EM_M32C 0xFEB0
++
++/* Cygnus M32R ELF backend. Written in the absence of an ABI. */
++#define EM_CYGNUS_M32R 0x9041
++
++/* old S/390 backend magic number. Written in the absence of an ABI. */
++#define EM_S390_OLD 0xa390
++
++/* D10V backend magic number. Written in the absence of an ABI. */
++#define EM_CYGNUS_D10V 0x7650
++
++/* D30V backend magic number. Written in the absence of an ABI. */
++#define EM_CYGNUS_D30V 0x7676
++
++/* V850 backend magic number. Written in the absense of an ABI. */
++#define EM_CYGNUS_V850 0x9080
++
++/* mn10200 and mn10300 backend magic numbers.
++ Written in the absense of an ABI. */
++#define EM_CYGNUS_MN10200 0xdead
++#define EM_CYGNUS_MN10300 0xbeef
++
++/* FR30 magic number - no EABI available. */
++#define EM_CYGNUS_FR30 0x3330
++
++/* AVR magic number
++ Written in the absense of an ABI. */
++#define EM_AVR_OLD 0x1057
++
++/* OpenRISC magic number
++ Written in the absense of an ABI. */
++#define EM_OPENRISC_OLD 0x3426
++
++/* DLX magic number
++ Written in the absense of an ABI. */
++#define EM_DLX 0x5aa5
++
++#define EM_XSTORMY16 0xad45
++
++/* FRV magic number - no EABI available??. */
++#define EM_CYGNUS_FRV 0x5441
++
++/* Ubicom IP2xxx; no ABI */
++#define EM_IP2K_OLD 0x8217
++
++#define EM_MT 0x2530 /* Morpho MT; no ABI */
++
++/* MSP430 magic number
++ Written in the absense everything. */
++#define EM_MSP430_OLD 0x1059
++
++/* Vitesse IQ2000. */
++#define EM_IQ2000 0xFEBA
++
++/* Old, unofficial value for Xtensa. */
++#define EM_XTENSA_OLD 0xabc7
++
++/* Alpha backend magic number. Written in the absence of an ABI. */
++#define EM_ALPHA 0x9026
++
++/* NIOS magic number - no EABI available. */
++#define EM_NIOS32 0xFEBB
++
++/* V850 backend magic number. Written in the absense of an ABI. */
++#define EM_CYGNUS_V850 0x9080
++
++/* Legal values for e_version (version). */
++
++#define EV_NONE 0 /* Invalid ELF version */
++#define EV_CURRENT 1 /* Current version */
++#define EV_NUM 2
++
++/* Section header. */
++
++typedef struct
++{
++ Elf32_Word sh_name; /* Section name (string tbl index) */
++ Elf32_Word sh_type; /* Section type */
++ Elf32_Word sh_flags; /* Section flags */
++ Elf32_Addr sh_addr; /* Section virtual addr at execution */
++ Elf32_Off sh_offset; /* Section file offset */
++ Elf32_Word sh_size; /* Section size in bytes */
++ Elf32_Word sh_link; /* Link to another section */
++ Elf32_Word sh_info; /* Additional section information */
++ Elf32_Word sh_addralign; /* Section alignment */
++ Elf32_Word sh_entsize; /* Entry size if section holds table */
++} Elf32_Shdr;
++
++typedef struct
++{
++ Elf64_Word sh_name; /* Section name (string tbl index) */
++ Elf64_Word sh_type; /* Section type */
++ Elf64_Xword sh_flags; /* Section flags */
++ Elf64_Addr sh_addr; /* Section virtual addr at execution */
++ Elf64_Off sh_offset; /* Section file offset */
++ Elf64_Xword sh_size; /* Section size in bytes */
++ Elf64_Word sh_link; /* Link to another section */
++ Elf64_Word sh_info; /* Additional section information */
++ Elf64_Xword sh_addralign; /* Section alignment */
++ Elf64_Xword sh_entsize; /* Entry size if section holds table */
++} Elf64_Shdr;
++
++/* Special section indices. */
++
++#define SHN_UNDEF 0 /* Undefined section */
++#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
++#define SHN_LOPROC 0xff00 /* Start of processor-specific */
++#define SHN_BEFORE 0xff00 /* Order section before all others
++ (Solaris). */
++#define SHN_AFTER 0xff01 /* Order section after all others
++ (Solaris). */
++#define SHN_HIPROC 0xff1f /* End of processor-specific */
++#define SHN_LOOS 0xff20 /* Start of OS-specific */
++#define SHN_HIOS 0xff3f /* End of OS-specific */
++#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
++#define SHN_COMMON 0xfff2 /* Associated symbol is common */
++#define SHN_XINDEX 0xffff /* Index is in extra table. */
++#define SHN_HIRESERVE 0xffff /* End of reserved indices */
++
++/* Legal values for sh_type (section type). */
++
++#define SHT_NULL 0 /* Section header table entry unused */
++#define SHT_PROGBITS 1 /* Program data */
++#define SHT_SYMTAB 2 /* Symbol table */
++#define SHT_STRTAB 3 /* String table */
++#define SHT_RELA 4 /* Relocation entries with addends */
++#define SHT_HASH 5 /* Symbol hash table */
++#define SHT_DYNAMIC 6 /* Dynamic linking information */
++#define SHT_NOTE 7 /* Notes */
++#define SHT_NOBITS 8 /* Program space with no data (bss) */
++#define SHT_REL 9 /* Relocation entries, no addends */
++#define SHT_SHLIB 10 /* Reserved */
++#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
++#define SHT_INIT_ARRAY 14 /* Array of constructors */
++#define SHT_FINI_ARRAY 15 /* Array of destructors */
++#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
++#define SHT_GROUP 17 /* Section group */
++#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
++#define SHT_NUM 19 /* Number of defined types. */
++#define SHT_LOOS 0x60000000 /* Start OS-specific */
++#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
++#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
++#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
++#define SHT_SUNW_move 0x6ffffffa
++#define SHT_SUNW_COMDAT 0x6ffffffb
++#define SHT_SUNW_syminfo 0x6ffffffc
++#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
++#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
++#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
++#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
++#define SHT_HIOS 0x6fffffff /* End OS-specific type */
++#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
++#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
++#define SHT_LOUSER 0x80000000 /* Start of application-specific */
++#define SHT_HIUSER 0x8fffffff /* End of application-specific */
++
++/* Legal values for sh_flags (section flags). */
++
++#define SHF_WRITE (1 << 0) /* Writable */
++#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
++#define SHF_EXECINSTR (1 << 2) /* Executable */
++#define SHF_MERGE (1 << 4) /* Might be merged */
++#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
++#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
++#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
++#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
++ required */
++#define SHF_GROUP (1 << 9) /* Section is member of a group. */
++#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
++#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
++#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
++#define SHF_ORDERED (1 << 30) /* Special ordering requirement
++ (Solaris). */
++#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
++ referenced or allocated (Solaris).*/
++
++/* Section group handling. */
++#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
++
++/* Symbol table entry. */
++
++typedef struct
++{
++ Elf32_Word st_name; /* Symbol name (string tbl index) */
++ Elf32_Addr st_value; /* Symbol value */
++ Elf32_Word st_size; /* Symbol size */
++ unsigned char st_info; /* Symbol type and binding */
++ unsigned char st_other; /* Symbol visibility */
++ Elf32_Section st_shndx; /* Section index */
++} Elf32_Sym;
++
++typedef struct
++{
++ Elf64_Word st_name; /* Symbol name (string tbl index) */
++ unsigned char st_info; /* Symbol type and binding */
++ unsigned char st_other; /* Symbol visibility */
++ Elf64_Section st_shndx; /* Section index */
++ Elf64_Addr st_value; /* Symbol value */
++ Elf64_Xword st_size; /* Symbol size */
++} Elf64_Sym;
++
++/* The syminfo section if available contains additional information about
++ every dynamic symbol. */
++
++typedef struct
++{
++ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
++ Elf32_Half si_flags; /* Per symbol flags */
++} Elf32_Syminfo;
++
++typedef struct
++{
++ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
++ Elf64_Half si_flags; /* Per symbol flags */
++} Elf64_Syminfo;
++
++/* Possible values for si_boundto. */
++#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
++#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
++#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
++
++/* Possible bitmasks for si_flags. */
++#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
++#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
++#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
++#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
++ loaded */
++/* Syminfo version values. */
++#define SYMINFO_NONE 0
++#define SYMINFO_CURRENT 1
++#define SYMINFO_NUM 2
++
++
++/* How to extract and insert information held in the st_info field. */
++
++#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
++#define ELF32_ST_TYPE(val) ((val) & 0xf)
++#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
++
++/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
++#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
++#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
++#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
++
++/* Legal values for ST_BIND subfield of st_info (symbol binding). */
++
++#define STB_LOCAL 0 /* Local symbol */
++#define STB_GLOBAL 1 /* Global symbol */
++#define STB_WEAK 2 /* Weak symbol */
++#define STB_NUM 3 /* Number of defined types. */
++#define STB_LOOS 10 /* Start of OS-specific */
++#define STB_HIOS 12 /* End of OS-specific */
++#define STB_LOPROC 13 /* Start of processor-specific */
++#define STB_HIPROC 15 /* End of processor-specific */
++
++/* Legal values for ST_TYPE subfield of st_info (symbol type). */
++
++#define STT_NOTYPE 0 /* Symbol type is unspecified */
++#define STT_OBJECT 1 /* Symbol is a data object */
++#define STT_FUNC 2 /* Symbol is a code object */
++#define STT_SECTION 3 /* Symbol associated with a section */
++#define STT_FILE 4 /* Symbol's name is file name */
++#define STT_COMMON 5 /* Symbol is a common data object */
++#define STT_TLS 6 /* Symbol is thread-local data object*/
++#define STT_NUM 7 /* Number of defined types. */
++#define STT_LOOS 10 /* Start of OS-specific */
++#define STT_HIOS 12 /* End of OS-specific */
++#define STT_LOPROC 13 /* Start of processor-specific */
++#define STT_HIPROC 15 /* End of processor-specific */
++
++
++/* Symbol table indices are found in the hash buckets and chain table
++ of a symbol hash table section. This special index value indicates
++ the end of a chain, meaning no further symbols are found in that bucket. */
++
++#define STN_UNDEF 0 /* End of a chain. */
++
++
++/* How to extract and insert information held in the st_other field. */
++
++#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
++
++/* For ELF64 the definitions are the same. */
++#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
++
++/* Symbol visibility specification encoded in the st_other field. */
++#define STV_DEFAULT 0 /* Default symbol visibility rules */
++#define STV_INTERNAL 1 /* Processor specific hidden class */
++#define STV_HIDDEN 2 /* Sym unavailable in other modules */
++#define STV_PROTECTED 3 /* Not preemptible, not exported */
++
++
++/* Relocation table entry without addend (in section of type SHT_REL). */
++
++typedef struct
++{
++ Elf32_Addr r_offset; /* Address */
++ Elf32_Word r_info; /* Relocation type and symbol index */
++} Elf32_Rel;
++
++/* I have seen two different definitions of the Elf64_Rel and
++ Elf64_Rela structures, so we'll leave them out until Novell (or
++ whoever) gets their act together. */
++/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
++
++typedef struct
++{
++ Elf64_Addr r_offset; /* Address */
++ Elf64_Xword r_info; /* Relocation type and symbol index */
++} Elf64_Rel;
++
++/* Relocation table entry with addend (in section of type SHT_RELA). */
++
++typedef struct
++{
++ Elf32_Addr r_offset; /* Address */
++ Elf32_Word r_info; /* Relocation type and symbol index */
++ Elf32_Sword r_addend; /* Addend */
++} Elf32_Rela;
++
++typedef struct
++{
++ Elf64_Addr r_offset; /* Address */
++ Elf64_Xword r_info; /* Relocation type and symbol index */
++ Elf64_Sxword r_addend; /* Addend */
++} Elf64_Rela;
++
++/* How to extract and insert information held in the r_info field. */
++
++#define ELF32_R_SYM(val) ((val) >> 8)
++#define ELF32_R_TYPE(val) ((val) & 0xff)
++#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
++
++#define ELF64_R_SYM(i) ((i) >> 32)
++#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
++#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
++
++/* Program segment header. */
++
++typedef struct
++{
++ Elf32_Word p_type; /* Segment type */
++ Elf32_Off p_offset; /* Segment file offset */
++ Elf32_Addr p_vaddr; /* Segment virtual address */
++ Elf32_Addr p_paddr; /* Segment physical address */
++ Elf32_Word p_filesz; /* Segment size in file */
++ Elf32_Word p_memsz; /* Segment size in memory */
++ Elf32_Word p_flags; /* Segment flags */
++ Elf32_Word p_align; /* Segment alignment */
++} Elf32_Phdr;
++
++typedef struct
++{
++ Elf64_Word p_type; /* Segment type */
++ Elf64_Word p_flags; /* Segment flags */
++ Elf64_Off p_offset; /* Segment file offset */
++ Elf64_Addr p_vaddr; /* Segment virtual address */
++ Elf64_Addr p_paddr; /* Segment physical address */
++ Elf64_Xword p_filesz; /* Segment size in file */
++ Elf64_Xword p_memsz; /* Segment size in memory */
++ Elf64_Xword p_align; /* Segment alignment */
++} Elf64_Phdr;
++
++/* Legal values for p_type (segment type). */
++
++#define PT_NULL 0 /* Program header table entry unused */
++#define PT_LOAD 1 /* Loadable program segment */
++#define PT_DYNAMIC 2 /* Dynamic linking information */
++#define PT_INTERP 3 /* Program interpreter */
++#define PT_NOTE 4 /* Auxiliary information */
++#define PT_SHLIB 5 /* Reserved */
++#define PT_PHDR 6 /* Entry for header table itself */
++#define PT_TLS 7 /* Thread-local storage segment */
++#define PT_NUM 8 /* Number of defined types */
++#define PT_LOOS 0x60000000 /* Start of OS-specific */
++#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
++#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
++#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
++#define PT_PAX_FLAGS 0x65041580 /* Indicates PaX flag markings */
++#define PT_LOSUNW 0x6ffffffa
++#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
++#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
++#define PT_HISUNW 0x6fffffff
++#define PT_HIOS 0x6fffffff /* End of OS-specific */
++#define PT_LOPROC 0x70000000 /* Start of processor-specific */
++#define PT_HIPROC 0x7fffffff /* End of processor-specific */
++
++/* Legal values for p_flags (segment flags). */
++
++#define PF_X (1 << 0) /* Segment is executable */
++#define PF_W (1 << 1) /* Segment is writable */
++#define PF_R (1 << 2) /* Segment is readable */
++#define PF_PAGEEXEC (1 << 4) /* Enable PAGEEXEC */
++#define PF_NOPAGEEXEC (1 << 5) /* Disable PAGEEXEC */
++#define PF_SEGMEXEC (1 << 6) /* Enable SEGMEXEC */
++#define PF_NOSEGMEXEC (1 << 7) /* Disable SEGMEXEC */
++#define PF_MPROTECT (1 << 8) /* Enable MPROTECT */
++#define PF_NOMPROTECT (1 << 9) /* Disable MPROTECT */
++#define PF_RANDEXEC (1 << 10) /* Enable RANDEXEC */
++#define PF_NORANDEXEC (1 << 11) /* Disable RANDEXEC */
++#define PF_EMUTRAMP (1 << 12) /* Enable EMUTRAMP */
++#define PF_NOEMUTRAMP (1 << 13) /* Disable EMUTRAMP */
++#define PF_RANDMMAP (1 << 14) /* Enable RANDMMAP */
++#define PF_NORANDMMAP (1 << 15) /* Disable RANDMMAP */
++#define PF_MASKOS 0x0ff00000 /* OS-specific */
++#define PF_MASKPROC 0xf0000000 /* Processor-specific */
++
++/* Legal values for note segment descriptor types for core files. */
++
++#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
++#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
++#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
++#define NT_PRXREG 4 /* Contains copy of prxregset struct */
++#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
++#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
++#define NT_AUXV 6 /* Contains copy of auxv array */
++#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
++#define NT_ASRS 8 /* Contains copy of asrset struct */
++#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
++#define NT_PSINFO 13 /* Contains copy of psinfo struct */
++#define NT_PRCRED 14 /* Contains copy of prcred struct */
++#define NT_UTSNAME 15 /* Contains copy of utsname struct */
++#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
++#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
++#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/
++
++/* Legal values for the note segment descriptor types for object files. */
++
++#define NT_VERSION 1 /* Contains a version string. */
++
++
++/* Dynamic section entry. */
++
++typedef struct
++{
++ Elf32_Sword d_tag; /* Dynamic entry type */
++ union
++ {
++ Elf32_Word d_val; /* Integer value */
++ Elf32_Addr d_ptr; /* Address value */
++ } d_un;
++} Elf32_Dyn;
++
++typedef struct
++{
++ Elf64_Sxword d_tag; /* Dynamic entry type */
++ union
++ {
++ Elf64_Xword d_val; /* Integer value */
++ Elf64_Addr d_ptr; /* Address value */
++ } d_un;
++} Elf64_Dyn;
++
++/* Legal values for d_tag (dynamic entry type). */
++
++#define DT_NULL 0 /* Marks end of dynamic section */
++#define DT_NEEDED 1 /* Name of needed library */
++#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
++#define DT_PLTGOT 3 /* Processor defined value */
++#define DT_HASH 4 /* Address of symbol hash table */
++#define DT_STRTAB 5 /* Address of string table */
++#define DT_SYMTAB 6 /* Address of symbol table */
++#define DT_RELA 7 /* Address of Rela relocs */
++#define DT_RELASZ 8 /* Total size of Rela relocs */
++#define DT_RELAENT 9 /* Size of one Rela reloc */
++#define DT_STRSZ 10 /* Size of string table */
++#define DT_SYMENT 11 /* Size of one symbol table entry */
++#define DT_INIT 12 /* Address of init function */
++#define DT_FINI 13 /* Address of termination function */
++#define DT_SONAME 14 /* Name of shared object */
++#define DT_RPATH 15 /* Library search path (deprecated) */
++#define DT_SYMBOLIC 16 /* Start symbol search here */
++#define DT_REL 17 /* Address of Rel relocs */
++#define DT_RELSZ 18 /* Total size of Rel relocs */
++#define DT_RELENT 19 /* Size of one Rel reloc */
++#define DT_PLTREL 20 /* Type of reloc in PLT */
++#define DT_DEBUG 21 /* For debugging; unspecified */
++#define DT_TEXTREL 22 /* Reloc might modify .text */
++#define DT_JMPREL 23 /* Address of PLT relocs */
++#define DT_BIND_NOW 24 /* Process relocations of object */
++#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
++#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
++#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
++#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
++#define DT_RUNPATH 29 /* Library search path */
++#define DT_FLAGS 30 /* Flags for the object being loaded */
++#define DT_ENCODING 32 /* Start of encoded range */
++#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
++#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
++#define DT_NUM 34 /* Number used */
++#define DT_LOOS 0x6000000d /* Start of OS-specific */
++#define DT_HIOS 0x6ffff000 /* End of OS-specific */
++#define DT_LOPROC 0x70000000 /* Start of processor-specific */
++#define DT_HIPROC 0x7fffffff /* End of processor-specific */
++#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
++
++/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
++ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
++ approach. */
++#define DT_VALRNGLO 0x6ffffd00
++#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
++#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
++#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
++#define DT_CHECKSUM 0x6ffffdf8
++#define DT_PLTPADSZ 0x6ffffdf9
++#define DT_MOVEENT 0x6ffffdfa
++#define DT_MOVESZ 0x6ffffdfb
++#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
++#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
++ the following DT_* entry. */
++#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
++#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
++#define DT_VALRNGHI 0x6ffffdff
++#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
++#define DT_VALNUM 12
++
++/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
++ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
++
++ If any adjustment is made to the ELF object after it has been
++ built these entries will need to be adjusted. */
++#define DT_ADDRRNGLO 0x6ffffe00
++#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
++#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
++#define DT_CONFIG 0x6ffffefa /* Configuration information. */
++#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
++#define DT_AUDIT 0x6ffffefc /* Object auditing. */
++#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
++#define DT_MOVETAB 0x6ffffefe /* Move table. */
++#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
++#define DT_ADDRRNGHI 0x6ffffeff
++#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
++#define DT_ADDRNUM 10
++
++/* The versioning entry types. The next are defined as part of the
++ GNU extension. */
++#define DT_VERSYM 0x6ffffff0
++
++#define DT_RELACOUNT 0x6ffffff9
++#define DT_RELCOUNT 0x6ffffffa
++
++/* These were chosen by Sun. */
++#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
++#define DT_VERDEF 0x6ffffffc /* Address of version definition
++ table */
++#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
++#define DT_VERNEED 0x6ffffffe /* Address of table with needed
++ versions */
++#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
++#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
++#define DT_VERSIONTAGNUM 16
++
++/* Sun added these machine-independent extensions in the "processor-specific"
++ range. Be compatible. */
++#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
++#define DT_FILTER 0x7fffffff /* Shared object to get values from */
++#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
++#define DT_EXTRANUM 3
++
++/* Values of `d_un.d_val' in the DT_FLAGS entry. */
++#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
++#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
++#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
++#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
++#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
++
++/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
++ entry in the dynamic section. */
++#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
++#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
++#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
++#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
++#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
++#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
++#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
++#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
++#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
++#define DF_1_TRANS 0x00000200
++#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
++#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
++#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */
++#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/
++#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */
++#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */
++#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */
++
++/* Flags for the feature selection in DT_FEATURE_1. */
++#define DTF_1_PARINIT 0x00000001
++#define DTF_1_CONFEXP 0x00000002
++
++/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
++#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
++#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
++ generally available. */
++
++/* Version definition sections. */
++
++typedef struct
++{
++ Elf32_Half vd_version; /* Version revision */
++ Elf32_Half vd_flags; /* Version information */
++ Elf32_Half vd_ndx; /* Version Index */
++ Elf32_Half vd_cnt; /* Number of associated aux entries */
++ Elf32_Word vd_hash; /* Version name hash value */
++ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
++ Elf32_Word vd_next; /* Offset in bytes to next verdef
++ entry */
++} Elf32_Verdef;
++
++typedef struct
++{
++ Elf64_Half vd_version; /* Version revision */
++ Elf64_Half vd_flags; /* Version information */
++ Elf64_Half vd_ndx; /* Version Index */
++ Elf64_Half vd_cnt; /* Number of associated aux entries */
++ Elf64_Word vd_hash; /* Version name hash value */
++ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
++ Elf64_Word vd_next; /* Offset in bytes to next verdef
++ entry */
++} Elf64_Verdef;
++
++
++/* Legal values for vd_version (version revision). */
++#define VER_DEF_NONE 0 /* No version */
++#define VER_DEF_CURRENT 1 /* Current version */
++#define VER_DEF_NUM 2 /* Given version number */
++
++/* Legal values for vd_flags (version information flags). */
++#define VER_FLG_BASE 0x1 /* Version definition of file itself */
++#define VER_FLG_WEAK 0x2 /* Weak version identifier */
++
++/* Versym symbol index values. */
++#define VER_NDX_LOCAL 0 /* Symbol is local. */
++#define VER_NDX_GLOBAL 1 /* Symbol is global. */
++#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
++#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
++
++/* Auxialiary version information. */
++
++typedef struct
++{
++ Elf32_Word vda_name; /* Version or dependency names */
++ Elf32_Word vda_next; /* Offset in bytes to next verdaux
++ entry */
++} Elf32_Verdaux;
++
++typedef struct
++{
++ Elf64_Word vda_name; /* Version or dependency names */
++ Elf64_Word vda_next; /* Offset in bytes to next verdaux
++ entry */
++} Elf64_Verdaux;
++
++
++/* Version dependency section. */
++
++typedef struct
++{
++ Elf32_Half vn_version; /* Version of structure */
++ Elf32_Half vn_cnt; /* Number of associated aux entries */
++ Elf32_Word vn_file; /* Offset of filename for this
++ dependency */
++ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
++ Elf32_Word vn_next; /* Offset in bytes to next verneed
++ entry */
++} Elf32_Verneed;
++
++typedef struct
++{
++ Elf64_Half vn_version; /* Version of structure */
++ Elf64_Half vn_cnt; /* Number of associated aux entries */
++ Elf64_Word vn_file; /* Offset of filename for this
++ dependency */
++ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
++ Elf64_Word vn_next; /* Offset in bytes to next verneed
++ entry */
++} Elf64_Verneed;
++
++
++/* Legal values for vn_version (version revision). */
++#define VER_NEED_NONE 0 /* No version */
++#define VER_NEED_CURRENT 1 /* Current version */
++#define VER_NEED_NUM 2 /* Given version number */
++
++/* Auxiliary needed version information. */
++
++typedef struct
++{
++ Elf32_Word vna_hash; /* Hash value of dependency name */
++ Elf32_Half vna_flags; /* Dependency specific information */
++ Elf32_Half vna_other; /* Unused */
++ Elf32_Word vna_name; /* Dependency name string offset */
++ Elf32_Word vna_next; /* Offset in bytes to next vernaux
++ entry */
++} Elf32_Vernaux;
++
++typedef struct
++{
++ Elf64_Word vna_hash; /* Hash value of dependency name */
++ Elf64_Half vna_flags; /* Dependency specific information */
++ Elf64_Half vna_other; /* Unused */
++ Elf64_Word vna_name; /* Dependency name string offset */
++ Elf64_Word vna_next; /* Offset in bytes to next vernaux
++ entry */
++} Elf64_Vernaux;
++
++
++/* Legal values for vna_flags. */
++#define VER_FLG_WEAK 0x2 /* Weak version identifier */
++
++
++/* Auxiliary vector. */
++
++/* This vector is normally only used by the program interpreter. The
++ usual definition in an ABI supplement uses the name auxv_t. The
++ vector is not usually defined in a standard <elf.h> file, but it
++ can't hurt. We rename it to avoid conflicts. The sizes of these
++ types are an arrangement between the exec server and the program
++ interpreter, so we don't fully specify them here. */
++
++typedef struct
++{
++ uint32_t a_type; /* Entry type */
++ union
++ {
++ uint32_t a_val; /* Integer value */
++ /* We use to have pointer elements added here. We cannot do that,
++ though, since it does not work when using 32-bit definitions
++ on 64-bit platforms and vice versa. */
++ } a_un;
++} Elf32_auxv_t;
++
++typedef struct
++{
++ uint64_t a_type; /* Entry type */
++ union
++ {
++ uint64_t a_val; /* Integer value */
++ /* We use to have pointer elements added here. We cannot do that,
++ though, since it does not work when using 32-bit definitions
++ on 64-bit platforms and vice versa. */
++ } a_un;
++} Elf64_auxv_t;
++
++/* Legal values for a_type (entry type). */
++
++#define AT_NULL 0 /* End of vector */
++#define AT_IGNORE 1 /* Entry should be ignored */
++#define AT_EXECFD 2 /* File descriptor of program */
++#define AT_PHDR 3 /* Program headers for program */
++#define AT_PHENT 4 /* Size of program header entry */
++#define AT_PHNUM 5 /* Number of program headers */
++#define AT_PAGESZ 6 /* System page size */
++#define AT_BASE 7 /* Base address of interpreter */
++#define AT_FLAGS 8 /* Flags */
++#define AT_ENTRY 9 /* Entry point of program */
++#define AT_NOTELF 10 /* Program is not ELF */
++#define AT_UID 11 /* Real uid */
++#define AT_EUID 12 /* Effective uid */
++#define AT_GID 13 /* Real gid */
++#define AT_EGID 14 /* Effective gid */
++#define AT_CLKTCK 17 /* Frequency of times() */
++
++/* Some more special a_type values describing the hardware. */
++#define AT_PLATFORM 15 /* String identifying platform. */
++#define AT_HWCAP 16 /* Machine dependent hints about
++ processor capabilities. */
++
++/* This entry gives some information about the FPU initialization
++ performed by the kernel. */
++#define AT_FPUCW 18 /* Used FPU control word. */
++
++/* Cache block sizes. */
++#define AT_DCACHEBSIZE 19 /* Data cache block size. */
++#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */
++#define AT_UCACHEBSIZE 21 /* Unified cache block size. */
++
++/* A special ignored value for PPC, used by the kernel to control the
++ interpretation of the AUXV. Must be > 16. */
++#define AT_IGNOREPPC 22 /* Entry should be ignored. */
++
++#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
++
++/* Pointer to the global system page used for system calls and other
++ nice things. */
++#define AT_SYSINFO 32
++#define AT_SYSINFO_EHDR 33
++
++/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
++ log2 of line size; mask those to get cache size. */
++#define AT_L1I_CACHESHAPE 34
++#define AT_L1D_CACHESHAPE 35
++#define AT_L2_CACHESHAPE 36
++#define AT_L3_CACHESHAPE 37
++
++/* Note section contents. Each entry in the note section begins with
++ a header of a fixed form. */
++
++typedef struct
++{
++ Elf32_Word n_namesz; /* Length of the note's name. */
++ Elf32_Word n_descsz; /* Length of the note's descriptor. */
++ Elf32_Word n_type; /* Type of the note. */
++} Elf32_Nhdr;
++
++typedef struct
++{
++ Elf64_Word n_namesz; /* Length of the note's name. */
++ Elf64_Word n_descsz; /* Length of the note's descriptor. */
++ Elf64_Word n_type; /* Type of the note. */
++} Elf64_Nhdr;
++
++/* Known names of notes. */
++
++/* Solaris entries in the note section have this name. */
++#define ELF_NOTE_SOLARIS "SUNW Solaris"
++
++/* Note entries for GNU systems have this name. */
++#define ELF_NOTE_GNU "GNU"
++
++
++/* Defined types of notes for Solaris. */
++
++/* Value of descriptor (one word) is desired pagesize for the binary. */
++#define ELF_NOTE_PAGESIZE_HINT 1
++
++
++/* Defined note types for GNU systems. */
++
++/* ABI information. The descriptor consists of words:
++ word 0: OS descriptor
++ word 1: major version of the ABI
++ word 2: minor version of the ABI
++ word 3: subminor version of the ABI
++*/
++#define ELF_NOTE_ABI 1
++
++/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI
++ note section entry. */
++#define ELF_NOTE_OS_LINUX 0
++#define ELF_NOTE_OS_GNU 1
++#define ELF_NOTE_OS_SOLARIS2 2
++#define ELF_NOTE_OS_FREEBSD 3
++
++
++/* Move records. */
++typedef struct
++{
++ Elf32_Xword m_value; /* Symbol value. */
++ Elf32_Word m_info; /* Size and index. */
++ Elf32_Word m_poffset; /* Symbol offset. */
++ Elf32_Half m_repeat; /* Repeat count. */
++ Elf32_Half m_stride; /* Stride info. */
++} Elf32_Move;
++
++typedef struct
++{
++ Elf64_Xword m_value; /* Symbol value. */
++ Elf64_Xword m_info; /* Size and index. */
++ Elf64_Xword m_poffset; /* Symbol offset. */
++ Elf64_Half m_repeat; /* Repeat count. */
++ Elf64_Half m_stride; /* Stride info. */
++} Elf64_Move;
++
++/* Macro to construct move records. */
++#define ELF32_M_SYM(info) ((info) >> 8)
++#define ELF32_M_SIZE(info) ((unsigned char) (info))
++#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
++
++#define ELF64_M_SYM(info) ELF32_M_SYM (info)
++#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
++#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
++
++
++/* Motorola 68k specific definitions. */
++
++/* Values for Elf32_Ehdr.e_flags. */
++#define EF_CPU32 0x00810000
++
++/* m68k relocs. */
++
++#define R_68K_NONE 0 /* No reloc */
++#define R_68K_32 1 /* Direct 32 bit */
++#define R_68K_16 2 /* Direct 16 bit */
++#define R_68K_8 3 /* Direct 8 bit */
++#define R_68K_PC32 4 /* PC relative 32 bit */
++#define R_68K_PC16 5 /* PC relative 16 bit */
++#define R_68K_PC8 6 /* PC relative 8 bit */
++#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
++#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
++#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
++#define R_68K_GOT32O 10 /* 32 bit GOT offset */
++#define R_68K_GOT16O 11 /* 16 bit GOT offset */
++#define R_68K_GOT8O 12 /* 8 bit GOT offset */
++#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
++#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
++#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
++#define R_68K_PLT32O 16 /* 32 bit PLT offset */
++#define R_68K_PLT16O 17 /* 16 bit PLT offset */
++#define R_68K_PLT8O 18 /* 8 bit PLT offset */
++#define R_68K_COPY 19 /* Copy symbol at runtime */
++#define R_68K_GLOB_DAT 20 /* Create GOT entry */
++#define R_68K_JMP_SLOT 21 /* Create PLT entry */
++#define R_68K_RELATIVE 22 /* Adjust by program base */
++/* Keep this the last entry. */
++#define R_68K_NUM 23
++
++/* Intel 80386 specific definitions. */
++
++/* i386 relocs. */
++
++#define R_386_NONE 0 /* No reloc */
++#define R_386_32 1 /* Direct 32 bit */
++#define R_386_PC32 2 /* PC relative 32 bit */
++#define R_386_GOT32 3 /* 32 bit GOT entry */
++#define R_386_PLT32 4 /* 32 bit PLT address */
++#define R_386_COPY 5 /* Copy symbol at runtime */
++#define R_386_GLOB_DAT 6 /* Create GOT entry */
++#define R_386_JMP_SLOT 7 /* Create PLT entry */
++#define R_386_RELATIVE 8 /* Adjust by program base */
++#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
++#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
++#define R_386_32PLT 11
++#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
++#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
++ block offset */
++#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block
++ offset */
++#define R_386_TLS_LE 17 /* Offset relative to static TLS
++ block */
++#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of
++ general dynamic thread local data */
++#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of
++ local dynamic thread local data
++ in LE code */
++#define R_386_16 20
++#define R_386_PC16 21
++#define R_386_8 22
++#define R_386_PC8 23
++#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic
++ thread local data */
++#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
++#define R_386_TLS_GD_CALL 26 /* Relocation for call to
++ __tls_get_addr() */
++#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
++#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic
++ thread local data in LE code */
++#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
++#define R_386_TLS_LDM_CALL 30 /* Relocation for call to
++ __tls_get_addr() in LDM code */
++#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
++#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
++#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS
++ block offset */
++#define R_386_TLS_LE_32 34 /* Negated offset relative to static
++ TLS block */
++#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
++#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
++#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
++/* Keep this the last entry. */
++#define R_386_NUM 38
++
++/* FR-V specific definitions. */
++#define R_FRV_NONE 0 /* No reloc. */
++#define R_FRV_32 1 /* Direct 32 bit. */
++/* Canonical function descriptor address. */
++#define R_FRV_FUNCDESC 14
++/* Private function descriptor initialization. */
++#define R_FRV_FUNCDESC_VALUE 18
++
++ /* gpr support */
++#define EF_FRV_GPR_MASK 0x00000003 /* mask for # of gprs */
++#define EF_FRV_GPR_32 0x00000001 /* -mgpr-32 */
++#define EF_FRV_GPR_64 0x00000002 /* -mgpr-64 */
++
++ /* fpr support */
++#define EF_FRV_FPR_MASK 0x0000000c /* mask for # of fprs */
++#define EF_FRV_FPR_32 0x00000004 /* -mfpr-32 */
++#define EF_FRV_FPR_64 0x00000008 /* -mfpr-64 */
++#define EF_FRV_FPR_NONE 0x0000000c /* -msoft-float */
++
++#define EF_FRV_PIC 0x00000100
++#define EF_FRV_FDPIC 0x00008000
++
++/* SUN SPARC specific definitions. */
++
++/* Legal values for ST_TYPE subfield of st_info (symbol type). */
++
++#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */
++
++/* Values for Elf64_Ehdr.e_flags. */
++
++#define EF_SPARCV9_MM 3
++#define EF_SPARCV9_TSO 0
++#define EF_SPARCV9_PSO 1
++#define EF_SPARCV9_RMO 2
++#define EF_SPARC_LEDATA 0x800000 /* little endian data */
++#define EF_SPARC_EXT_MASK 0xFFFF00
++#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
++#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
++#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */
++#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */
++
++/* SPARC relocs. */
++
++#define R_SPARC_NONE 0 /* No reloc */
++#define R_SPARC_8 1 /* Direct 8 bit */
++#define R_SPARC_16 2 /* Direct 16 bit */
++#define R_SPARC_32 3 /* Direct 32 bit */
++#define R_SPARC_DISP8 4 /* PC relative 8 bit */
++#define R_SPARC_DISP16 5 /* PC relative 16 bit */
++#define R_SPARC_DISP32 6 /* PC relative 32 bit */
++#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
++#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
++#define R_SPARC_HI22 9 /* High 22 bit */
++#define R_SPARC_22 10 /* Direct 22 bit */
++#define R_SPARC_13 11 /* Direct 13 bit */
++#define R_SPARC_LO10 12 /* Truncated 10 bit */
++#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
++#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
++#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
++#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
++#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
++#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
++#define R_SPARC_COPY 19 /* Copy symbol at runtime */
++#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
++#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
++#define R_SPARC_RELATIVE 22 /* Adjust by program base */
++#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
++
++/* Additional Sparc64 relocs. */
++
++#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
++#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
++#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
++#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
++#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
++#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
++#define R_SPARC_10 30 /* Direct 10 bit */
++#define R_SPARC_11 31 /* Direct 11 bit */
++#define R_SPARC_64 32 /* Direct 64 bit */
++#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */
++#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
++#define R_SPARC_HM10 35 /* High middle 10 bits of ... */
++#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
++#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
++#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
++#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
++#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
++#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
++#define R_SPARC_7 43 /* Direct 7 bit */
++#define R_SPARC_5 44 /* Direct 5 bit */
++#define R_SPARC_6 45 /* Direct 6 bit */
++#define R_SPARC_DISP64 46 /* PC relative 64 bit */
++#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
++#define R_SPARC_HIX22 48 /* High 22 bit complemented */
++#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
++#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
++#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
++#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
++#define R_SPARC_REGISTER 53 /* Global register usage */
++#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
++#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
++#define R_SPARC_TLS_GD_HI22 56
++#define R_SPARC_TLS_GD_LO10 57
++#define R_SPARC_TLS_GD_ADD 58
++#define R_SPARC_TLS_GD_CALL 59
++#define R_SPARC_TLS_LDM_HI22 60
++#define R_SPARC_TLS_LDM_LO10 61
++#define R_SPARC_TLS_LDM_ADD 62
++#define R_SPARC_TLS_LDM_CALL 63
++#define R_SPARC_TLS_LDO_HIX22 64
++#define R_SPARC_TLS_LDO_LOX10 65
++#define R_SPARC_TLS_LDO_ADD 66
++#define R_SPARC_TLS_IE_HI22 67
++#define R_SPARC_TLS_IE_LO10 68
++#define R_SPARC_TLS_IE_LD 69
++#define R_SPARC_TLS_IE_LDX 70
++#define R_SPARC_TLS_IE_ADD 71
++#define R_SPARC_TLS_LE_HIX22 72
++#define R_SPARC_TLS_LE_LOX10 73
++#define R_SPARC_TLS_DTPMOD32 74
++#define R_SPARC_TLS_DTPMOD64 75
++#define R_SPARC_TLS_DTPOFF32 76
++#define R_SPARC_TLS_DTPOFF64 77
++#define R_SPARC_TLS_TPOFF32 78
++#define R_SPARC_TLS_TPOFF64 79
++/* Keep this the last entry. */
++#define R_SPARC_NUM 80
++
++/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
++
++#define DT_SPARC_REGISTER 0x70000001
++#define DT_SPARC_NUM 2
++
++/* Bits present in AT_HWCAP, primarily for Sparc32. */
++
++#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */
++#define HWCAP_SPARC_STBAR 2
++#define HWCAP_SPARC_SWAP 4
++#define HWCAP_SPARC_MULDIV 8
++#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */
++#define HWCAP_SPARC_ULTRA3 32
++
++/* MIPS R3000 specific definitions. */
++
++/* Legal values for e_flags field of Elf32_Ehdr. */
++
++#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
++#define EF_MIPS_PIC 2 /* Contains PIC code */
++#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
++#define EF_MIPS_XGOT 8
++#define EF_MIPS_64BIT_WHIRL 16
++#define EF_MIPS_ABI2 32
++#define EF_MIPS_ABI_ON32 64
++#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
++
++/* Legal values for MIPS architecture level. */
++
++#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
++#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
++#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
++#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
++#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
++#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
++#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
++
++/* The following are non-official names and should not be used. */
++
++#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
++#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
++#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
++#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
++#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
++#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
++#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
++
++/* Special section indices. */
++
++#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
++#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
++#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
++#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
++#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
++
++/* Legal values for sh_type field of Elf32_Shdr. */
++
++#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
++#define SHT_MIPS_MSYM 0x70000001
++#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
++#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
++#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
++#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
++#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
++#define SHT_MIPS_PACKAGE 0x70000007
++#define SHT_MIPS_PACKSYM 0x70000008
++#define SHT_MIPS_RELD 0x70000009
++#define SHT_MIPS_IFACE 0x7000000b
++#define SHT_MIPS_CONTENT 0x7000000c
++#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
++#define SHT_MIPS_SHDR 0x70000010
++#define SHT_MIPS_FDESC 0x70000011
++#define SHT_MIPS_EXTSYM 0x70000012
++#define SHT_MIPS_DENSE 0x70000013
++#define SHT_MIPS_PDESC 0x70000014
++#define SHT_MIPS_LOCSYM 0x70000015
++#define SHT_MIPS_AUXSYM 0x70000016
++#define SHT_MIPS_OPTSYM 0x70000017
++#define SHT_MIPS_LOCSTR 0x70000018
++#define SHT_MIPS_LINE 0x70000019
++#define SHT_MIPS_RFDESC 0x7000001a
++#define SHT_MIPS_DELTASYM 0x7000001b
++#define SHT_MIPS_DELTAINST 0x7000001c
++#define SHT_MIPS_DELTACLASS 0x7000001d
++#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
++#define SHT_MIPS_DELTADECL 0x7000001f
++#define SHT_MIPS_SYMBOL_LIB 0x70000020
++#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
++#define SHT_MIPS_TRANSLATE 0x70000022
++#define SHT_MIPS_PIXIE 0x70000023
++#define SHT_MIPS_XLATE 0x70000024
++#define SHT_MIPS_XLATE_DEBUG 0x70000025
++#define SHT_MIPS_WHIRL 0x70000026
++#define SHT_MIPS_EH_REGION 0x70000027
++#define SHT_MIPS_XLATE_OLD 0x70000028
++#define SHT_MIPS_PDR_EXCEPTION 0x70000029
++
++/* Legal values for sh_flags field of Elf32_Shdr. */
++
++#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
++#define SHF_MIPS_MERGE 0x20000000
++#define SHF_MIPS_ADDR 0x40000000
++#define SHF_MIPS_STRINGS 0x80000000
++#define SHF_MIPS_NOSTRIP 0x08000000
++#define SHF_MIPS_LOCAL 0x04000000
++#define SHF_MIPS_NAMES 0x02000000
++#define SHF_MIPS_NODUPE 0x01000000
++
++
++/* Symbol tables. */
++
++/* MIPS specific values for `st_other'. */
++#define STO_MIPS_DEFAULT 0x0
++#define STO_MIPS_INTERNAL 0x1
++#define STO_MIPS_HIDDEN 0x2
++#define STO_MIPS_PROTECTED 0x3
++#define STO_MIPS_SC_ALIGN_UNUSED 0xff
++
++/* MIPS specific values for `st_info'. */
++#define STB_MIPS_SPLIT_COMMON 13
++
++/* Entries found in sections of type SHT_MIPS_GPTAB. */
++
++typedef union
++{
++ struct
++ {
++ Elf32_Word gt_current_g_value; /* -G value used for compilation */
++ Elf32_Word gt_unused; /* Not used */
++ } gt_header; /* First entry in section */
++ struct
++ {
++ Elf32_Word gt_g_value; /* If this value were used for -G */
++ Elf32_Word gt_bytes; /* This many bytes would be used */
++ } gt_entry; /* Subsequent entries in section */
++} Elf32_gptab;
++
++/* Entry found in sections of type SHT_MIPS_REGINFO. */
++
++typedef struct
++{
++ Elf32_Word ri_gprmask; /* General registers used */
++ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
++ Elf32_Sword ri_gp_value; /* $gp register value */
++} Elf32_RegInfo;
++
++/* Entries found in sections of type SHT_MIPS_OPTIONS. */
++
++typedef struct
++{
++ unsigned char kind; /* Determines interpretation of the
++ variable part of descriptor. */
++ unsigned char size; /* Size of descriptor, including header. */
++ Elf32_Section section; /* Section header index of section affected,
++ 0 for global options. */
++ Elf32_Word info; /* Kind-specific information. */
++} Elf_Options;
++
++/* Values for `kind' field in Elf_Options. */
++
++#define ODK_NULL 0 /* Undefined. */
++#define ODK_REGINFO 1 /* Register usage information. */
++#define ODK_EXCEPTIONS 2 /* Exception processing options. */
++#define ODK_PAD 3 /* Section padding options. */
++#define ODK_HWPATCH 4 /* Hardware workarounds performed */
++#define ODK_FILL 5 /* record the fill value used by the linker. */
++#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
++#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
++#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
++
++/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
++
++#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
++#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
++#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
++#define OEX_SMM 0x20000 /* Force sequential memory mode? */
++#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
++#define OEX_PRECISEFP OEX_FPDBUG
++#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
++
++#define OEX_FPU_INVAL 0x10
++#define OEX_FPU_DIV0 0x08
++#define OEX_FPU_OFLO 0x04
++#define OEX_FPU_UFLO 0x02
++#define OEX_FPU_INEX 0x01
++
++/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
++
++#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
++#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
++#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
++#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
++
++#define OPAD_PREFIX 0x1
++#define OPAD_POSTFIX 0x2
++#define OPAD_SYMBOL 0x4
++
++/* Entry found in `.options' section. */
++
++typedef struct
++{
++ Elf32_Word hwp_flags1; /* Extra flags. */
++ Elf32_Word hwp_flags2; /* Extra flags. */
++} Elf_Options_Hw;
++
++/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
++
++#define OHWA0_R4KEOP_CHECKED 0x00000001
++#define OHWA1_R4KEOP_CLEAN 0x00000002
++
++/* MIPS relocs. */
++
++#define R_MIPS_NONE 0 /* No reloc */
++#define R_MIPS_16 1 /* Direct 16 bit */
++#define R_MIPS_32 2 /* Direct 32 bit */
++#define R_MIPS_REL32 3 /* PC relative 32 bit */
++#define R_MIPS_26 4 /* Direct 26 bit shifted */
++#define R_MIPS_HI16 5 /* High 16 bit */
++#define R_MIPS_LO16 6 /* Low 16 bit */
++#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
++#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
++#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
++#define R_MIPS_PC16 10 /* PC relative 16 bit */
++#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
++#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
++
++#define R_MIPS_SHIFT5 16
++#define R_MIPS_SHIFT6 17
++#define R_MIPS_64 18
++#define R_MIPS_GOT_DISP 19
++#define R_MIPS_GOT_PAGE 20
++#define R_MIPS_GOT_OFST 21
++#define R_MIPS_GOT_HI16 22
++#define R_MIPS_GOT_LO16 23
++#define R_MIPS_SUB 24
++#define R_MIPS_INSERT_A 25
++#define R_MIPS_INSERT_B 26
++#define R_MIPS_DELETE 27
++#define R_MIPS_HIGHER 28
++#define R_MIPS_HIGHEST 29
++#define R_MIPS_CALL_HI16 30
++#define R_MIPS_CALL_LO16 31
++#define R_MIPS_SCN_DISP 32
++#define R_MIPS_REL16 33
++#define R_MIPS_ADD_IMMEDIATE 34
++#define R_MIPS_PJUMP 35
++#define R_MIPS_RELGOT 36
++#define R_MIPS_JALR 37
++#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */
++#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */
++#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */
++#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */
++#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */
++#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */
++#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */
++#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */
++#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */
++#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */
++#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
++#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
++#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
++/* Keep this the last entry. */
++#define R_MIPS_NUM 51
++
++/* Legal values for p_type field of Elf32_Phdr. */
++
++#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
++#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
++#define PT_MIPS_OPTIONS 0x70000002
++
++/* Special program header types. */
++
++#define PF_MIPS_LOCAL 0x10000000
++
++/* Legal values for d_tag field of Elf32_Dyn. */
++
++#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
++#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
++#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
++#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
++#define DT_MIPS_FLAGS 0x70000005 /* Flags */
++#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
++#define DT_MIPS_MSYM 0x70000007
++#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
++#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
++#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
++#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
++#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
++#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
++#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
++#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
++#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
++#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
++#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
++#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in
++ DT_MIPS_DELTA_CLASS. */
++#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
++#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
++ DT_MIPS_DELTA_INSTANCE. */
++#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
++#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
++ DT_MIPS_DELTA_RELOC. */
++#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta
++ relocations refer to. */
++#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
++ DT_MIPS_DELTA_SYM. */
++#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
++ class declaration. */
++#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
++ DT_MIPS_DELTA_CLASSSYM. */
++#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
++#define DT_MIPS_PIXIE_INIT 0x70000023
++#define DT_MIPS_SYMBOL_LIB 0x70000024
++#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
++#define DT_MIPS_LOCAL_GOTIDX 0x70000026
++#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
++#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
++#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
++#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
++#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
++#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
++#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
++ function stored in GOT. */
++#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
++ by rld on dlopen() calls. */
++#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
++#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
++#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
++#define DT_MIPS_NUM 0x32
++
++/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
++
++#define RHF_NONE 0 /* No flags */
++#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
++#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
++#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
++#define RHF_NO_MOVE (1 << 3)
++#define RHF_SGI_ONLY (1 << 4)
++#define RHF_GUARANTEE_INIT (1 << 5)
++#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
++#define RHF_GUARANTEE_START_INIT (1 << 7)
++#define RHF_PIXIE (1 << 8)
++#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
++#define RHF_REQUICKSTART (1 << 10)
++#define RHF_REQUICKSTARTED (1 << 11)
++#define RHF_CORD (1 << 12)
++#define RHF_NO_UNRES_UNDEF (1 << 13)
++#define RHF_RLD_ORDER_SAFE (1 << 14)
++
++/* Entries found in sections of type SHT_MIPS_LIBLIST. */
++
++typedef struct
++{
++ Elf32_Word l_name; /* Name (string table index) */
++ Elf32_Word l_time_stamp; /* Timestamp */
++ Elf32_Word l_checksum; /* Checksum */
++ Elf32_Word l_version; /* Interface version */
++ Elf32_Word l_flags; /* Flags */
++} Elf32_Lib;
++
++typedef struct
++{
++ Elf64_Word l_name; /* Name (string table index) */
++ Elf64_Word l_time_stamp; /* Timestamp */
++ Elf64_Word l_checksum; /* Checksum */
++ Elf64_Word l_version; /* Interface version */
++ Elf64_Word l_flags; /* Flags */
++} Elf64_Lib;
++
++
++/* Legal values for l_flags. */
++
++#define LL_NONE 0
++#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
++#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
++#define LL_REQUIRE_MINOR (1 << 2)
++#define LL_EXPORTS (1 << 3)
++#define LL_DELAY_LOAD (1 << 4)
++#define LL_DELTA (1 << 5)
++
++/* Entries found in sections of type SHT_MIPS_CONFLICT. */
++
++typedef Elf32_Addr Elf32_Conflict;
++
++
++/* HPPA specific definitions. */
++
++/* Legal values for e_flags field of Elf32_Ehdr. */
++
++#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */
++#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */
++#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */
++#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */
++#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch
++ prediction. */
++#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */
++#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */
++
++/* Defined values for `e_flags & EF_PARISC_ARCH' are: */
++
++#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */
++#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */
++#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */
++
++/* Additional section indeces. */
++
++#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared
++ symbols in ANSI C. */
++#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */
++
++/* Legal values for sh_type field of Elf32_Shdr. */
++
++#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */
++#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */
++#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */
++
++/* Legal values for sh_flags field of Elf32_Shdr. */
++
++#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
++#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */
++#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */
++
++/* Legal values for ST_TYPE subfield of st_info (symbol type). */
++
++#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
++
++#define STT_HP_OPAQUE (STT_LOOS + 0x1)
++#define STT_HP_STUB (STT_LOOS + 0x2)
++
++/* HPPA relocs. */
++
++#define R_PARISC_NONE 0 /* No reloc. */
++#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
++#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
++#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
++#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */
++#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */
++#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */
++#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */
++#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */
++#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */
++#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */
++#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */
++#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */
++#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */
++#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */
++#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */
++#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */
++#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */
++#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */
++#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */
++#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */
++#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */
++#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */
++#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */
++#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */
++#define R_PARISC_FPTR64 64 /* 64 bits function address. */
++#define R_PARISC_PLABEL32 65 /* 32 bits function address. */
++#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */
++#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */
++#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */
++#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */
++#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */
++#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */
++#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */
++#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */
++#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */
++#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */
++#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */
++#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */
++#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */
++#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */
++#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */
++#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */
++#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */
++#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */
++#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */
++#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */
++#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */
++#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */
++#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */
++#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */
++#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */
++#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */
++#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */
++#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */
++#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */
++#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */
++#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */
++#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */
++#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */
++#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */
++#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */
++#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */
++#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */
++#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */
++#define R_PARISC_LORESERVE 128
++#define R_PARISC_COPY 128 /* Copy relocation. */
++#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */
++#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */
++#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */
++#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */
++#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */
++#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */
++#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/
++#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */
++#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */
++#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */
++#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */
++#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */
++#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */
++#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */
++#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */
++#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/
++#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/
++#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */
++#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */
++#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */
++#define R_PARISC_HIRESERVE 255
++
++/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
++
++#define PT_HP_TLS (PT_LOOS + 0x0)
++#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
++#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
++#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
++#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
++#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
++#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
++#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
++#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
++#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
++#define PT_HP_PARALLEL (PT_LOOS + 0x10)
++#define PT_HP_FASTBIND (PT_LOOS + 0x11)
++#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
++#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
++#define PT_HP_STACK (PT_LOOS + 0x14)
++
++#define PT_PARISC_ARCHEXT 0x70000000
++#define PT_PARISC_UNWIND 0x70000001
++
++/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */
++
++#define PF_PARISC_SBP 0x08000000
++
++#define PF_HP_PAGE_SIZE 0x00100000
++#define PF_HP_FAR_SHARED 0x00200000
++#define PF_HP_NEAR_SHARED 0x00400000
++#define PF_HP_CODE 0x01000000
++#define PF_HP_MODIFY 0x02000000
++#define PF_HP_LAZYSWAP 0x04000000
++#define PF_HP_SBP 0x08000000
++
++
++/* Alpha specific definitions. */
++
++/* Legal values for e_flags field of Elf64_Ehdr. */
++
++#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
++#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
++
++/* Legal values for sh_type field of Elf64_Shdr. */
++
++/* These two are primerily concerned with ECOFF debugging info. */
++#define SHT_ALPHA_DEBUG 0x70000001
++#define SHT_ALPHA_REGINFO 0x70000002
++
++/* Legal values for sh_flags field of Elf64_Shdr. */
++
++#define SHF_ALPHA_GPREL 0x10000000
++
++/* Legal values for st_other field of Elf64_Sym. */
++#define STO_ALPHA_NOPV 0x80 /* No PV required. */
++#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
++
++/* Alpha relocs. */
++
++#define R_ALPHA_NONE 0 /* No reloc */
++#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
++#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
++#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
++#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
++#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
++#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
++#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
++#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
++#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
++#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
++#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
++#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */
++#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */
++#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */
++#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
++#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
++#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
++#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
++#define R_ALPHA_TLS_GD_HI 28
++#define R_ALPHA_TLSGD 29
++#define R_ALPHA_TLS_LDM 30
++#define R_ALPHA_DTPMOD64 31
++#define R_ALPHA_GOTDTPREL 32
++#define R_ALPHA_DTPREL64 33
++#define R_ALPHA_DTPRELHI 34
++#define R_ALPHA_DTPRELLO 35
++#define R_ALPHA_DTPREL16 36
++#define R_ALPHA_GOTTPREL 37
++#define R_ALPHA_TPREL64 38
++#define R_ALPHA_TPRELHI 39
++#define R_ALPHA_TPRELLO 40
++#define R_ALPHA_TPREL16 41
++/* Keep this the last entry. */
++#define R_ALPHA_NUM 46
++
++/* Magic values of the LITUSE relocation addend. */
++#define LITUSE_ALPHA_ADDR 0
++#define LITUSE_ALPHA_BASE 1
++#define LITUSE_ALPHA_BYTOFF 2
++#define LITUSE_ALPHA_JSR 3
++#define LITUSE_ALPHA_TLS_GD 4
++#define LITUSE_ALPHA_TLS_LDM 5
++
++/* Legal values for d_tag of Elf64_Dyn. */
++#define DT_ALPHA_PLTRO (DT_LOPROC + 0)
++#define DT_ALPHA_NUM 1
++
++/* PowerPC specific declarations */
++
++/* Values for Elf32/64_Ehdr.e_flags. */
++#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
++
++/* Cygnus local bits below */
++#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
++#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib
++ flag */
++
++/* PowerPC relocations defined by the ABIs */
++#define R_PPC_NONE 0
++#define R_PPC_ADDR32 1 /* 32bit absolute address */
++#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
++#define R_PPC_ADDR16 3 /* 16bit absolute address */
++#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
++#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
++#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
++#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
++#define R_PPC_ADDR14_BRTAKEN 8
++#define R_PPC_ADDR14_BRNTAKEN 9
++#define R_PPC_REL24 10 /* PC relative 26 bit */
++#define R_PPC_REL14 11 /* PC relative 16 bit */
++#define R_PPC_REL14_BRTAKEN 12
++#define R_PPC_REL14_BRNTAKEN 13
++#define R_PPC_GOT16 14
++#define R_PPC_GOT16_LO 15
++#define R_PPC_GOT16_HI 16
++#define R_PPC_GOT16_HA 17
++#define R_PPC_PLTREL24 18
++#define R_PPC_COPY 19
++#define R_PPC_GLOB_DAT 20
++#define R_PPC_JMP_SLOT 21
++#define R_PPC_RELATIVE 22
++#define R_PPC_LOCAL24PC 23
++#define R_PPC_UADDR32 24
++#define R_PPC_UADDR16 25
++#define R_PPC_REL32 26
++#define R_PPC_PLT32 27
++#define R_PPC_PLTREL32 28
++#define R_PPC_PLT16_LO 29
++#define R_PPC_PLT16_HI 30
++#define R_PPC_PLT16_HA 31
++#define R_PPC_SDAREL16 32
++#define R_PPC_SECTOFF 33
++#define R_PPC_SECTOFF_LO 34
++#define R_PPC_SECTOFF_HI 35
++#define R_PPC_SECTOFF_HA 36
++
++/* PowerPC relocations defined for the TLS access ABI. */
++#define R_PPC_TLS 67 /* none (sym+add)@tls */
++#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
++#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
++#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
++#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
++#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
++#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
++#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
++#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
++#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
++#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
++#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
++#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
++#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
++#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
++#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
++#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
++#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
++#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
++#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
++#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
++#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
++#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
++#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
++#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
++#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
++#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
++#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
++
++/* Keep this the last entry. */
++#define R_PPC_NUM 95
++
++/* The remaining relocs are from the Embedded ELF ABI, and are not
++ in the SVR4 ELF ABI. */
++#define R_PPC_EMB_NADDR32 101
++#define R_PPC_EMB_NADDR16 102
++#define R_PPC_EMB_NADDR16_LO 103
++#define R_PPC_EMB_NADDR16_HI 104
++#define R_PPC_EMB_NADDR16_HA 105
++#define R_PPC_EMB_SDAI16 106
++#define R_PPC_EMB_SDA2I16 107
++#define R_PPC_EMB_SDA2REL 108
++#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
++#define R_PPC_EMB_MRKREF 110
++#define R_PPC_EMB_RELSEC16 111
++#define R_PPC_EMB_RELST_LO 112
++#define R_PPC_EMB_RELST_HI 113
++#define R_PPC_EMB_RELST_HA 114
++#define R_PPC_EMB_BIT_FLD 115
++#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
++
++/* Diab tool relocations. */
++#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
++#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
++#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
++#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
++#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
++#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
++
++/* GNU relocs used in PIC code sequences. */
++#define R_PPC_REL16 249 /* word32 (sym-.) */
++#define R_PPC_REL16_LO 250 /* half16 (sym-.)@l */
++#define R_PPC_REL16_HI 251 /* half16 (sym-.)@h */
++#define R_PPC_REL16_HA 252 /* half16 (sym-.)@ha */
++
++/* This is a phony reloc to handle any old fashioned TOC16 references
++ that may still be in object files. */
++#define R_PPC_TOC16 255
++
++/* PowerPC specific values for the Dyn d_tag field. */
++#define DT_PPC_GOT (DT_LOPROC + 0)
++#define DT_PPC_NUM 1
++
++/* PowerPC64 relocations defined by the ABIs */
++#define R_PPC64_NONE R_PPC_NONE
++#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */
++#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */
++#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */
++#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */
++#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */
++#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
++#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */
++#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
++#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
++#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
++#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */
++#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
++#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
++#define R_PPC64_GOT16 R_PPC_GOT16
++#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
++#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
++#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
++
++#define R_PPC64_COPY R_PPC_COPY
++#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
++#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
++#define R_PPC64_RELATIVE R_PPC_RELATIVE
++
++#define R_PPC64_UADDR32 R_PPC_UADDR32
++#define R_PPC64_UADDR16 R_PPC_UADDR16
++#define R_PPC64_REL32 R_PPC_REL32
++#define R_PPC64_PLT32 R_PPC_PLT32
++#define R_PPC64_PLTREL32 R_PPC_PLTREL32
++#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
++#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
++#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
++
++#define R_PPC64_SECTOFF R_PPC_SECTOFF
++#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
++#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
++#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
++#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */
++#define R_PPC64_ADDR64 38 /* doubleword64 S + A */
++#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */
++#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */
++#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */
++#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */
++#define R_PPC64_UADDR64 43 /* doubleword64 S + A */
++#define R_PPC64_REL64 44 /* doubleword64 S + A - P */
++#define R_PPC64_PLT64 45 /* doubleword64 L + A */
++#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */
++#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */
++#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */
++#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */
++#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */
++#define R_PPC64_TOC 51 /* doubleword64 .TOC */
++#define R_PPC64_PLTGOT16 52 /* half16* M + A */
++#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */
++#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */
++#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */
++
++#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */
++#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */
++#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */
++#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */
++#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */
++#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */
++#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */
++#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */
++#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */
++#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */
++#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */
++
++/* PowerPC64 relocations defined for the TLS access ABI. */
++#define R_PPC64_TLS 67 /* none (sym+add)@tls */
++#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
++#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
++#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
++#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
++#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
++#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
++#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
++#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
++#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
++#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
++#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
++#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
++#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
++#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
++#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
++#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
++#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
++#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
++#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
++#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
++#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
++#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
++#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
++#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
++#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
++#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
++#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
++#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
++#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
++#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
++#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
++#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
++#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
++#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
++#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
++#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
++#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
++#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
++#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
++
++/* Keep this the last entry. */
++#define R_PPC64_NUM 107
++
++/* PowerPC64 specific values for the Dyn d_tag field. */
++#define DT_PPC64_GLINK (DT_LOPROC + 0)
++#define DT_PPC64_OPD (DT_LOPROC + 1)
++#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
++#define DT_PPC64_NUM 3
++
++
++/* ARM specific declarations */
++
++/* Processor specific flags for the ELF header e_flags field. */
++#define EF_ARM_RELEXEC 0x01
++#define EF_ARM_HASENTRY 0x02
++#define EF_ARM_INTERWORK 0x04
++#define EF_ARM_APCS_26 0x08
++#define EF_ARM_APCS_FLOAT 0x10
++#define EF_ARM_PIC 0x20
++#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */
++#define EF_ARM_NEW_ABI 0x80
++#define EF_ARM_OLD_ABI 0x100
++
++/* Other constants defined in the ARM ELF spec. version B-01. */
++/* NB. These conflict with values defined above. */
++#define EF_ARM_SYMSARESORTED 0x04
++#define EF_ARM_DYNSYMSUSESEGIDX 0x08
++#define EF_ARM_MAPSYMSFIRST 0x10
++#define EF_ARM_EABIMASK 0XFF000000
++
++#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
++#define EF_ARM_EABI_UNKNOWN 0x00000000
++#define EF_ARM_EABI_VER1 0x01000000
++#define EF_ARM_EABI_VER2 0x02000000
++
++/* Additional symbol types for Thumb */
++#define STT_ARM_TFUNC 0xd
++
++/* ARM-specific values for sh_flags */
++#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
++#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
++ in the input to a link step */
++
++/* ARM-specific program header flags */
++#define PF_ARM_SB 0x10000000 /* Segment contains the location
++ addressed by the static base */
++
++/* Processor specific values for the Phdr p_type field. */
++#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */
++
++/* ARM relocs. */
++
++#define R_ARM_NONE 0 /* No reloc */
++#define R_ARM_PC24 1 /* PC relative 26 bit branch */
++#define R_ARM_ABS32 2 /* Direct 32 bit */
++#define R_ARM_REL32 3 /* PC relative 32 bit */
++#define R_ARM_PC13 4
++#define R_ARM_ABS16 5 /* Direct 16 bit */
++#define R_ARM_ABS12 6 /* Direct 12 bit */
++#define R_ARM_THM_ABS5 7
++#define R_ARM_ABS8 8 /* Direct 8 bit */
++#define R_ARM_SBREL32 9
++#define R_ARM_THM_PC22 10
++#define R_ARM_THM_PC8 11
++#define R_ARM_AMP_VCALL9 12
++#define R_ARM_SWI24 13
++#define R_ARM_THM_SWI8 14
++#define R_ARM_XPC25 15
++#define R_ARM_THM_XPC22 16
++#define R_ARM_COPY 20 /* Copy symbol at runtime */
++#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
++#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
++#define R_ARM_RELATIVE 23 /* Adjust by program base */
++#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
++#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
++#define R_ARM_GOT32 26 /* 32 bit GOT entry */
++#define R_ARM_PLT32 27 /* 32 bit PLT address */
++#define R_ARM_ALU_PCREL_7_0 32
++#define R_ARM_ALU_PCREL_15_8 33
++#define R_ARM_ALU_PCREL_23_15 34
++#define R_ARM_LDR_SBREL_11_0 35
++#define R_ARM_ALU_SBREL_19_12 36
++#define R_ARM_ALU_SBREL_27_20 37
++#define R_ARM_GNU_VTENTRY 100
++#define R_ARM_GNU_VTINHERIT 101
++#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
++#define R_ARM_THM_PC9 103 /* thumb conditional branch */
++#define R_ARM_RXPC25 249
++#define R_ARM_RSBREL32 250
++#define R_ARM_THM_RPC22 251
++#define R_ARM_RREL32 252
++#define R_ARM_RABS22 253
++#define R_ARM_RPC24 254
++#define R_ARM_RBASE 255
++/* Keep this the last entry. */
++#define R_ARM_NUM 256
++
++/* IA-64 specific declarations. */
++
++/* Processor specific flags for the Ehdr e_flags field. */
++#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
++#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
++#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
++
++/* Processor specific values for the Phdr p_type field. */
++#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
++#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
++#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
++#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
++#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
++
++/* Processor specific flags for the Phdr p_flags field. */
++#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
++
++/* Processor specific values for the Shdr sh_type field. */
++#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
++#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
++
++/* Processor specific flags for the Shdr sh_flags field. */
++#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
++#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
++
++/* Processor specific values for the Dyn d_tag field. */
++#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
++#define DT_IA_64_NUM 1
++
++/* IA-64 relocations. */
++#define R_IA64_NONE 0x00 /* none */
++#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
++#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
++#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
++#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
++#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
++#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
++#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
++#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */
++#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */
++#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */
++#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */
++#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */
++#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */
++#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */
++#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */
++#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */
++#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */
++#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */
++#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */
++#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */
++#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */
++#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */
++#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */
++#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */
++#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */
++#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */
++#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */
++#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */
++#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */
++#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */
++#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */
++#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */
++#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
++#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
++#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */
++#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */
++#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */
++#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */
++#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */
++#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */
++#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */
++#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */
++#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */
++#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */
++#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */
++#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */
++#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
++#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
++#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
++#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
++#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */
++#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */
++#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */
++#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */
++#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */
++#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */
++#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */
++#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
++#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
++#define R_IA64_COPY 0x84 /* copy relocation */
++#define R_IA64_SUB 0x85 /* Addend and symbol difference */
++#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
++#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
++#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */
++#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */
++#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */
++#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */
++#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */
++#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */
++#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */
++#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */
++#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */
++#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */
++#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */
++#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */
++#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */
++#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */
++#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */
++#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */
++#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */
++
++/* SH specific declarations */
++
++/* SH specific values for `st_other'. */
++
++/* If set, this is a symbol pointing to SHmedia code, which will be branched
++ to, so need to add 1 to the symbol value. */
++#define STO_SH5_ISA32 (1 << 2)
++
++/* SH relocs. */
++#define R_SH_NONE 0
++#define R_SH_DIR32 1
++#define R_SH_REL32 2
++#define R_SH_DIR8WPN 3
++#define R_SH_IND12W 4
++#define R_SH_DIR8WPL 5
++#define R_SH_DIR8WPZ 6
++#define R_SH_DIR8BP 7
++#define R_SH_DIR8W 8
++#define R_SH_DIR8L 9
++#define R_SH_SWITCH16 25
++#define R_SH_SWITCH32 26
++#define R_SH_USES 27
++#define R_SH_COUNT 28
++#define R_SH_ALIGN 29
++#define R_SH_CODE 30
++#define R_SH_DATA 31
++#define R_SH_LABEL 32
++#define R_SH_SWITCH8 33
++#define R_SH_GNU_VTINHERIT 34
++#define R_SH_GNU_VTENTRY 35
++#define R_SH_TLS_GD_32 144
++#define R_SH_TLS_LD_32 145
++#define R_SH_TLS_LDO_32 146
++#define R_SH_TLS_IE_32 147
++#define R_SH_TLS_LE_32 148
++#define R_SH_TLS_DTPMOD32 149
++#define R_SH_TLS_DTPOFF32 150
++#define R_SH_TLS_TPOFF32 151
++#define R_SH_GOT32 160
++#define R_SH_PLT32 161
++#define R_SH_COPY 162
++#define R_SH_GLOB_DAT 163
++#define R_SH_JMP_SLOT 164
++#define R_SH_RELATIVE 165
++#define R_SH_GOTOFF 166
++#define R_SH_GOTPC 167
++#define R_SH_RELATIVE_LOW16 197
++#define R_SH_RELATIVE_MEDLOW16 198
++#define R_SH_IMM_LOW16 246
++#define R_SH_IMM_LOW16_PCREL 247
++#define R_SH_IMM_MEDLOW16 248
++#define R_SH_IMM_MEDLOW16_PCREL 249
++
++/* Keep this the last entry. */
++#define R_SH_NUM 256
++
++/* Additional s390 relocs */
++
++#define R_390_NONE 0 /* No reloc. */
++#define R_390_8 1 /* Direct 8 bit. */
++#define R_390_12 2 /* Direct 12 bit. */
++#define R_390_16 3 /* Direct 16 bit. */
++#define R_390_32 4 /* Direct 32 bit. */
++#define R_390_PC32 5 /* PC relative 32 bit. */
++#define R_390_GOT12 6 /* 12 bit GOT offset. */
++#define R_390_GOT32 7 /* 32 bit GOT offset. */
++#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
++#define R_390_COPY 9 /* Copy symbol at runtime. */
++#define R_390_GLOB_DAT 10 /* Create GOT entry. */
++#define R_390_JMP_SLOT 11 /* Create PLT entry. */
++#define R_390_RELATIVE 12 /* Adjust by program base. */
++#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */
++#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
++#define R_390_GOT16 15 /* 16 bit GOT offset. */
++#define R_390_PC16 16 /* PC relative 16 bit. */
++#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
++#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
++#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
++#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
++#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
++#define R_390_64 22 /* Direct 64 bit. */
++#define R_390_PC64 23 /* PC relative 64 bit. */
++#define R_390_GOT64 24 /* 64 bit GOT offset. */
++#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
++#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
++#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
++#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
++#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
++#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
++#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
++#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
++#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
++#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
++#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
++#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
++#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
++#define R_390_TLS_GDCALL 38 /* Tag for function call in general
++ dynamic TLS code. */
++#define R_390_TLS_LDCALL 39 /* Tag for function call in local
++ dynamic TLS code. */
++#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic
++ thread local data. */
++#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic
++ thread local data. */
++#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS
++ block offset. */
++#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS
++ block offset. */
++#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS
++ block offset. */
++#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic
++ thread local data in LE code. */
++#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic
++ thread local data in LE code. */
++#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for
++ negated static TLS block offset. */
++#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for
++ negated static TLS block offset. */
++#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for
++ negated static TLS block offset. */
++#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to
++ static TLS block. */
++#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to
++ static TLS block. */
++#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS
++ block. */
++#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS
++ block. */
++#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
++#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
++#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS
++ block. */
++#define R_390_20 57 /* Direct 20 bit. */
++#define R_390_GOT20 58 /* 20 bit GOT offset. */
++#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */
++#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS
++ block offset. */
++/* Keep this the last entry. */
++#define R_390_NUM 61
++
++
++/* CRIS flags. */
++#define EF_CRIS_VARIANT_MASK 0x0000000e
++#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000
++#define EF_CRIS_VARIANT_V32 0x00000002
++#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004
++
++/* CRIS relocations. */
++#define R_CRIS_NONE 0
++#define R_CRIS_8 1
++#define R_CRIS_16 2
++#define R_CRIS_32 3
++#define R_CRIS_8_PCREL 4
++#define R_CRIS_16_PCREL 5
++#define R_CRIS_32_PCREL 6
++#define R_CRIS_GNU_VTINHERIT 7
++#define R_CRIS_GNU_VTENTRY 8
++#define R_CRIS_COPY 9
++#define R_CRIS_GLOB_DAT 10
++#define R_CRIS_JUMP_SLOT 11
++#define R_CRIS_RELATIVE 12
++#define R_CRIS_16_GOT 13
++#define R_CRIS_32_GOT 14
++#define R_CRIS_16_GOTPLT 15
++#define R_CRIS_32_GOTPLT 16
++#define R_CRIS_32_GOTREL 17
++#define R_CRIS_32_PLT_GOTREL 18
++#define R_CRIS_32_PLT_PCREL 19
++
++/* Keep this the last entry. */
++#define R_CRIS_NUM 20
++
++
++/* AMD x86-64 relocations. */
++#define R_X86_64_NONE 0 /* No reloc */
++#define R_X86_64_64 1 /* Direct 64 bit */
++#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
++#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
++#define R_X86_64_PLT32 4 /* 32 bit PLT address */
++#define R_X86_64_COPY 5 /* Copy symbol at runtime */
++#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
++#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
++#define R_X86_64_RELATIVE 8 /* Adjust by program base */
++#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
++ offset to GOT */
++#define R_X86_64_32 10 /* Direct 32 bit zero extended */
++#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
++#define R_X86_64_16 12 /* Direct 16 bit zero extended */
++#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
++#define R_X86_64_8 14 /* Direct 8 bit sign extended */
++#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
++#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
++#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
++#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
++#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset
++ to two GOT entries for GD symbol */
++#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset
++ to two GOT entries for LD symbol */
++#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
++#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset
++ to GOT entry for IE symbol */
++#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
++
++#define R_X86_64_NUM 24
++
++
++/* AM33 relocations. */
++#define R_MN10300_NONE 0 /* No reloc. */
++#define R_MN10300_32 1 /* Direct 32 bit. */
++#define R_MN10300_16 2 /* Direct 16 bit. */
++#define R_MN10300_8 3 /* Direct 8 bit. */
++#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */
++#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */
++#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
++#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */
++#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */
++#define R_MN10300_24 9 /* Direct 24 bit. */
++#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */
++#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */
++#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */
++#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */
++#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */
++#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */
++#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */
++#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */
++#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */
++#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */
++#define R_MN10300_COPY 20 /* Copy symbol at runtime. */
++#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */
++#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */
++#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
++
++#define R_MN10300_NUM 24
++
++
++/* M32R relocs. */
++#define R_M32R_NONE 0 /* No reloc. */
++#define R_M32R_16 1 /* Direct 16 bit. */
++#define R_M32R_32 2 /* Direct 32 bit. */
++#define R_M32R_24 3 /* Direct 24 bit. */
++#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */
++#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */
++#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */
++#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */
++#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */
++#define R_M32R_LO16 9 /* Low 16 bit. */
++#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */
++#define R_M32R_GNU_VTINHERIT 11
++#define R_M32R_GNU_VTENTRY 12
++/* M32R relocs use SHT_RELA. */
++#define R_M32R_16_RELA 33 /* Direct 16 bit. */
++#define R_M32R_32_RELA 34 /* Direct 32 bit. */
++#define R_M32R_24_RELA 35 /* Direct 24 bit. */
++#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */
++#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */
++#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */
++#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */
++#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */
++#define R_M32R_LO16_RELA 41 /* Low 16 bit */
++#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */
++#define R_M32R_RELA_GNU_VTINHERIT 43
++#define R_M32R_RELA_GNU_VTENTRY 44
++
++#define R_M32R_GOT24 48 /* 24 bit GOT entry */
++#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */
++#define R_M32R_COPY 50 /* Copy symbol at runtime */
++#define R_M32R_GLOB_DAT 51 /* Create GOT entry */
++#define R_M32R_JMP_SLOT 52 /* Create PLT entry */
++#define R_M32R_RELATIVE 53 /* Adjust by program base */
++#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */
++#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */
++#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned
++ low */
++#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed
++ low */
++#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */
++#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to
++ GOT with unsigned low */
++#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to
++ GOT with signed low */
++#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to
++ GOT */
++#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT
++ with unsigned low */
++#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT
++ with signed low */
++#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */
++#define R_M32R_NUM 256 /* Keep this the last entry. */
++
++/* i960 Relocations */
++#define R_960_NONE 0
++#define R_960_12 1
++#define R_960_32 2
++#define R_960_IP24 3
++#define R_960_SUB 4
++#define R_960_OPTCALL 5
++#define R_960_OPTCALLX 6
++#define R_960_OPTCALLXA 7
++/* Keep this the last entry. */
++#define R_960_NUM 8
++
++
++/* v850 relocations. */
++#define R_V850_NONE 0
++#define R_V850_9_PCREL 1
++#define R_V850_22_PCREL 2
++#define R_V850_HI16_S 3
++#define R_V850_HI16 4
++#define R_V850_LO16 5
++#define R_V850_32 6
++#define R_V850_16 7
++#define R_V850_8 8
++#define R_V850_SDA_16_16_OFFSET 9 /* For ld.b, st.b, set1, clr1,
++ not1, tst1, movea, movhi */
++#define R_V850_SDA_15_16_OFFSET 10 /* For ld.w, ld.h, ld.hu, st.w, st.h */
++#define R_V850_ZDA_16_16_OFFSET 11 /* For ld.b, st.b, set1, clr1,
++ not1, tst1, movea, movhi */
++#define R_V850_ZDA_15_16_OFFSET 12 /* For ld.w, ld.h, ld.hu, st.w, st.h */
++#define R_V850_TDA_6_8_OFFSET 13 /* For sst.w, sld.w */
++#define R_V850_TDA_7_8_OFFSET 14 /* For sst.h, sld.h */
++#define R_V850_TDA_7_7_OFFSET 15 /* For sst.b, sld.b */
++#define R_V850_TDA_16_16_OFFSET 16 /* For set1, clr1, not1, tst1,
++ movea, movhi */
++/* CYGNUS LOCAL v850e */
++#define R_V850_TDA_4_5_OFFSET 17 /* For sld.hu */
++#define R_V850_TDA_4_4_OFFSET 18 /* For sld.bu */
++#define R_V850_SDA_16_16_SPLIT_OFFSET 19 /* For ld.bu */
++#define R_V850_ZDA_16_16_SPLIT_OFFSET 20 /* For ld.bu */
++#define R_V850_CALLT_6_7_OFFSET 21 /* For callt */
++#define R_V850_CALLT_16_16_OFFSET 22 /* For callt */
++/* END CYGNUS LOCAL */
++#define R_V850_GNU_VTINHERIT 23
++#define R_V850_GNU_VTENTRY 24
++/* Keep this the last entry. */
++#define R_V850_NUM 25
++
++
++/* Renesas H8/300 Relocations */
++#define R_H8_NONE 0
++#define R_H8_DIR32 1
++#define R_H8_DIR32_28 2
++#define R_H8_DIR32_24 3
++#define R_H8_DIR32_16 4
++#define R_H8_DIR32U 6
++#define R_H8_DIR32U_28 7
++#define R_H8_DIR32U_24 8
++#define R_H8_DIR32U_20 9
++#define R_H8_DIR32U_16 10
++#define R_H8_DIR24 11
++#define R_H8_DIR24_20 12
++#define R_H8_DIR24_16 13
++#define R_H8_DIR24U 14
++#define R_H8_DIR24U_20 15
++#define R_H8_DIR24U_16 16
++#define R_H8_DIR16 17
++#define R_H8_DIR16U 18
++#define R_H8_DIR16S_32 19
++#define R_H8_DIR16S_28 20
++#define R_H8_DIR16S_24 21
++#define R_H8_DIR16S_20 22
++#define R_H8_DIR16S 23
++#define R_H8_DIR8 24
++#define R_H8_DIR8U 25
++#define R_H8_DIR8Z_32 26
++#define R_H8_DIR8Z_28 27
++#define R_H8_DIR8Z_24 28
++#define R_H8_DIR8Z_20 29
++#define R_H8_DIR8Z_16 30
++#define R_H8_PCREL16 31
++#define R_H8_PCREL8 32
++#define R_H8_BPOS 33
++#define R_H8_PCREL32 34
++#define R_H8_GOT32O 35
++#define R_H8_GOT16O 36
++#define R_H8_DIR16A8 59
++#define R_H8_DIR16R8 60
++#define R_H8_DIR24A8 61
++#define R_H8_DIR24R8 62
++#define R_H8_DIR32A16 63
++#define R_H8_ABS32 65
++#define R_H8_ABS32A16 127
++#define R_H8_NUM 128
++
++/* NIOS relocations. */
++#define R_NIOS_NONE 0
++#define R_NIOS_32 1 /* A 32 bit absolute relocation.*/
++#define R_NIOS_LO16_LO5 2 /* A LO-16 5 bit absolute relocation. */
++#define R_NIOS_LO16_HI11 3 /* A LO-16 top 11 bit absolute relocation. */
++#define R_NIOS_HI16_LO5 4 /* A HI-16 5 bit absolute relocation. */
++#define R_NIOS_HI16_HI11 5 /* A HI-16 top 11 bit absolute relocation. */
++#define R_NIOS_PCREL6 6 /* A 6 bit relative relocation. */
++#define R_NIOS_PCREL8 7 /* An 8 bit relative relocation. */
++#define R_NIOS_PCREL11 8 /* An 11 bit relative relocation. */
++#define R_NIOS_16 9 /* A 16 bit absolute relocation. */
++#define R_NIOS_H_LO5 10 /* Low 5-bits of absolute relocation in halfwords. */
++#define R_NIOS_H_HI11 11 /* Top 11 bits of 16-bit absolute relocation in halfwords. */
++#define R_NIOS_H_XLO5 12 /* Low 5 bits of top 16-bits of 32-bit absolute relocation in halfwords. */
++#define R_NIOS_H_XHI11 13 /* Top 11 bits of top 16-bits of 32-bit absolute relocation in halfwords. */
++#define R_NIOS_H_16 14 /* Half-word @h value */
++#define R_NIOS_H_32 15 /* Word @h value */
++#define R_NIOS_GNU_VTINHERIT 200 /* GNU extension to record C++ vtable hierarchy */
++#define R_NIOS_GNU_VTENTRY 201 /* GNU extension to record C++ vtable member usage */
++/* Keep this the last entry. */
++#define R_NIOS_NUM 202
++
++/* NIOS II relocations */
++#define R_NIOS2_NONE 0
++#define R_NIOS2_S16 1
++#define R_NIOS2_U16 2
++#define R_NIOS2_PCREL16 3
++#define R_NIOS2_CALL26 4
++#define R_NIOS2_IMM5 5
++#define R_NIOS2_CACHE_OPX 6
++#define R_NIOS2_IMM6 7
++#define R_NIOS2_IMM8 8
++#define R_NIOS2_HI16 9
++#define R_NIOS2_LO16 10
++#define R_NIOS2_HIADJ16 11
++#define R_NIOS2_BFD_RELOC_32 12
++#define R_NIOS2_BFD_RELOC_16 13
++#define R_NIOS2_BFD_RELOC_8 14
++#define R_NIOS2_GPREL 15
++#define R_NIOS2_GNU_VTINHERIT 16
++#define R_NIOS2_GNU_VTENTRY 17
++#define R_NIOS2_UJMP 18
++#define R_NIOS2_CJMP 19
++#define R_NIOS2_CALLR 20
++#define R_NIOS2_ALIGN 21
++/* Keep this the last entry. */
++#define R_NIOS2_NUM 22
++
++__END_DECLS
++
++#endif /* elf.h */
+diff -Nrup a/ldso/include/dl-string.h b/ldso/include/dl-string.h
+--- a/ldso/include/dl-string.h 2007-01-25 19:22:03.000000000 -0500
++++ b/ldso/include/dl-string.h 2008-02-28 19:03:13.000000000 -0500
+@@ -285,7 +285,9 @@ static __always_inline char * _dl_simple
+ /* 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(__mips__) || defined(__sh__) || defined(__powerpc__) || \
++ defined(__avr32__)
++
+ # define CONSTANT_STRING_GOT_FIXUP(X) \
+ if ((X) < (const char *) load_addr) (X) += load_addr
+ # define NO_EARLY_SEND_STDERR
+diff -Nrup a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
+--- a/ldso/include/dl-syscall.h 2007-01-28 00:51:31.000000000 -0500
++++ b/ldso/include/dl-syscall.h 2008-02-28 19:06:04.000000000 -0500
+@@ -54,69 +54,69 @@
+ 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 inline _syscall1(void, _dl_exit, int, status);
++static __always_inline _syscall1(void, _dl_exit, int, status);
+
+ #define __NR__dl_close __NR_close
+-static inline _syscall1(int, _dl_close, int, fd);
++static __always_inline _syscall1(int, _dl_close, int, fd);
+
+ #define __NR__dl_open __NR_open
+-static inline _syscall3(int, _dl_open, const char *, fn, int, flags,
++static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags,
+ __kernel_mode_t, mode);
+
+ #define __NR__dl_write __NR_write
+-static inline _syscall3(unsigned long, _dl_write, int, fd,
++static __always_inline _syscall3(unsigned long, _dl_write, int, fd,
+ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_read __NR_read
+-static inline _syscall3(unsigned long, _dl_read, int, fd,
++static __always_inline _syscall3(unsigned long, _dl_read, int, fd,
+ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_mprotect __NR_mprotect
+-static inline _syscall3(int, _dl_mprotect, const void *, addr,
++static __always_inline _syscall3(int, _dl_mprotect, const void *, addr,
+ unsigned long, len, int, prot);
+
+ #define __NR__dl_stat __NR_stat
+-static inline _syscall2(int, _dl_stat, const char *, file_name,
++static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
+ struct stat *, buf);
+
+ #define __NR__dl_fstat __NR_fstat
+-static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
++static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
+
+ #define __NR__dl_munmap __NR_munmap
+-static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
++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 inline _syscall0(uid_t, _dl_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 inline _syscall0(uid_t, _dl_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 inline _syscall0(gid_t, _dl_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 inline _syscall0(gid_t, _dl_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 inline _syscall0(gid_t, _dl_getpid);
++static __always_inline _syscall0(gid_t, _dl_getpid);
+
+ #define __NR__dl_readlink __NR_readlink
+-static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
++static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
+ size_t, bufsiz);
+
+
+@@ -134,14 +134,14 @@ static inline _syscall3(int, _dl_readlin
+ #if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
+
+ # define __NR__dl_mmap __NR_mmap
+-static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
++static __always_inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
+ int, prot, int, flags, int, fd, off_t, offset);
+
+ /* then try mmap2() */
+ #elif defined(__NR_mmap2)
+
+ # define __NR___syscall_mmap2 __NR_mmap2
+-static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
++static __always_inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
+ int, prot, int, flags, int, fd, off_t, offset);
+
+ /* Some architectures always use 12 as page shift for mmap2() eventhough the
+@@ -152,7 +152,7 @@ static inline _syscall6(__ptr_t, __sysca
+ # define MMAP2_PAGE_SHIFT 12
+ #endif
+
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
+@@ -165,8 +165,8 @@ static inline void * _dl_mmap(void * add
+ #elif defined(__NR_mmap)
+
+ # define __NR__dl_mmap_real __NR_mmap
+-static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++static __always_inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+ unsigned long buffer[6];
+diff -Nrup a/ldso/ldso/avr32/dl-debug.h b/ldso/ldso/avr32/dl-debug.h
+--- a/ldso/ldso/avr32/dl-debug.h 1969-12-31 19:00:00.000000000 -0500
++++ b/ldso/ldso/avr32/dl-debug.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,45 @@
++/*
++ * AVR32 ELF shared libary loader support
++ *
++ * Copyright (C) 2005 Atmel Norway
++ * 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 *_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 -Nrup a/ldso/ldso/avr32/dl-startup.h b/ldso/ldso/avr32/dl-startup.h
+--- a/ldso/ldso/avr32/dl-startup.h 1969-12-31 19:00:00.000000000 -0500
++++ b/ldso/ldso/avr32/dl-startup.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,110 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Architecture specific code used by dl-startup.c
++ * Copyright (C) 2005 Atmel Norway
++ */
++
++/* 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 if 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(ELF32_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(ELF32_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);
++ }
++}
++
++/* Transfer control to the user's application, once the dynamic loader
++ * is done. This routine has to exit the current function, then call
++ * the _dl_elf_main function.
++ *
++ * Since our _dl_boot will simply call whatever is returned by
++ * _dl_boot2, we can just return the address we're supposed to
++ * call. */
++#define START() return _dl_elf_main;
+diff -Nrup a/ldso/ldso/avr32/dl-syscalls.h b/ldso/ldso/avr32/dl-syscalls.h
+--- a/ldso/ldso/avr32/dl-syscalls.h 1969-12-31 19:00:00.000000000 -0500
++++ b/ldso/ldso/avr32/dl-syscalls.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,5 @@
++/* We can't use the real errno in ldso, since it has not yet
++ * been dynamicly linked in yet. */
++extern int _dl_errno;
++#define __set_errno(X) {(_dl_errno) = (X);}
++#include "sys/syscall.h"
+diff -Nrup a/ldso/ldso/avr32/dl-sysdep.h b/ldso/ldso/avr32/dl-sysdep.h
+--- a/ldso/ldso/avr32/dl-sysdep.h 1969-12-31 19:00:00.000000000 -0500
++++ b/ldso/ldso/avr32/dl-sysdep.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,103 @@
++/* 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) 2004-2005 Atmel Norway
++ */
++
++/* 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"
++
++unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
++
++/* 4096 bytes alignment */
++#define PAGE_ALIGN 0xfffff000
++#define ADDR_ALIGN 0xfff
++#define OFFS_ALIGN 0x7ffff000
++
++#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 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 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 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 -Nrup a/ldso/ldso/avr32/elfinterp.c b/ldso/ldso/avr32/elfinterp.c
+--- a/ldso/ldso/avr32/elfinterp.c 1969-12-31 19:00:00.000000000 -0500
++++ b/ldso/ldso/avr32/elfinterp.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,191 @@
++/*
++ * 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)
++{
++ struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
++ Elf32_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;
++
++#if 0
++ local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
++ gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
++
++ sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
++ + sym_index;
++ strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
++ symname = strtab + sym->st_name;
++
++#if 0
++ new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
++ tpnt->symbol_scope, tpnt,
++ resolver);
++#endif
++
++ entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
++ *entry = 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_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
++{
++ Elf32_Sym *symtab;
++ Elf32_Rela *rpnt;
++ char *strtab;
++ int i;
++
++ rpnt = (Elf32_Rela *)rel_addr;
++ rel_size /= sizeof(Elf32_Rela);
++ symtab = (Elf32_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 = ELF32_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 = ELF32_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 dyn_elf *scope,
++ Elf32_Rela *rpnt, Elf32_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
++
++ reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
++ reloc_type = ELF32_R_TYPE(rpnt->r_info);
++ symtab_index = ELF32_R_SYM(rpnt->r_info);
++ symbol_addr = 0;
++ symname = strtab + symtab[symtab_index].st_name;
++
++ if (symtab_index) {
++ symbol_addr = (unsigned long)
++ _dl_find_hash(strtab + symtab[symtab_index].st_name,
++ tpnt->symbol_scope, tpnt,
++ elf_machine_type_class(reloc_type));
++
++ /* Allow undefined references to weak symbols */
++ if (!symbol_addr &&
++ ELF32_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 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,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
++ _dl_do_reloc);
++}
+diff -Nrup a/ldso/ldso/avr32/resolve.S b/ldso/ldso/avr32/resolve.S
+--- a/ldso/ldso/avr32/resolve.S 1969-12-31 19:00:00.000000000 -0500
++++ b/ldso/ldso/avr32/resolve.S 2008-02-28 19:02:10.000000000 -0500
+@@ -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 Atmel Norway
++ */
++
++#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 -Nrup a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
+--- a/ldso/ldso/dl-startup.c 2007-01-25 19:22:03.000000000 -0500
++++ b/ldso/ldso/dl-startup.c 2008-02-28 19:02:10.000000000 -0500
+@@ -217,7 +217,9 @@ static void * __attribute_used__ _dl_sta
+ /* some arches (like MIPS) we have to tweak the GOT before relocations */
+ PERFORM_BOOTSTRAP_GOT(tpnt);
+
+-#else
++#endif
++
++#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__)
+
+ /* OK, now do the relocations. We do not do a lazy binding here, so
+ that once we are done, we have considerably more flexibility. */
+@@ -259,7 +261,7 @@ static void * __attribute_used__ _dl_sta
+ rel_addr += relative_count * sizeof(ELF_RELOC);;
+ }
+
+- rpnt = (ELF_RELOC *) (rel_addr + load_addr);
++ rpnt = (ELF_RELOC *) (rel_addr /* + load_addr */);
+ for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+ reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
+diff -Nrup a/libc/Makefile b/libc/Makefile
+--- a/libc/Makefile 2007-02-28 16:23:09.000000000 -0500
++++ b/libc/Makefile 2008-02-28 19:02:10.000000000 -0500
+@@ -59,7 +59,7 @@ $(LIBNAME) shared_$(LIBNAME) ar-target:
+ $(AR) dN 2 $(LIBNAME) $$objs && \
+ $(AR) dN 2 $(LIBNAME) $$objs
+ @for objfile in obj.signal \
+- obj.string.generic obj.string.$(TARGET_ARCH) obj.string \
++ obj.string obj.string.generic obj.string.$(TARGET_ARCH) \
+ obj.sysdeps.common obj.sysdeps.$(TARGET_ARCH) ; do \
+ if [ -e $$objfile ] ; then \
+ if [ "$(MAKE_IS_SILENT)" = "n" ] ; then \
+diff -Nrup a/libc/string/avr32/bcopy.S b/libc/string/avr32/bcopy.S
+--- a/libc/string/avr32/bcopy.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/bcopy.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,15 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++ .text
++ .global bcopy
++ .type bcopy, @function
++ .align 1
++bcopy:
++ /* Swap the first two arguments */
++ eor r11, r12
++ eor r12, r11
++ eor r11, r12
++ rjmp __memmove
++ .size bcopy, . - bcopy
+diff -Nrup a/libc/string/avr32/bzero.S b/libc/string/avr32/bzero.S
+--- a/libc/string/avr32/bzero.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/bzero.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,12 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++ .text
++ .global bzero
++ .type bzero, @function
++ .align 1
++bzero:
++ mov r10, r11
++ mov r11, 0
++ rjmp __memset
+diff -Nrup a/libc/string/avr32/Makefile b/libc/string/avr32/Makefile
+--- a/libc/string/avr32/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/Makefile 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,40 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++TOPDIR=../../../
++include $(TOPDIR)Rules.mak
++
++SSRC := bcopy.S bzero.S memcmp.S memcpy.S memmove.S
++SSRC += memset.S strcmp.S strlen.S
++# memchr.S, strcat.S, strcpy.S, strncpy.S is broken
++SOBJS := $(patsubst %.S,%.o, $(SSRC))
++OBJS := $(SOBJS)
++
++OBJ_LIST:= ../../obj.string.$(TARGET_ARCH)
++
++all: $(OBJ_LIST)
++
++$(OBJ_LIST): $(OBJS)
++ echo $(addprefix string/$(TARGET_ARCH)/, $(OBJS)) > $@
++
++$(SOBJS): %.o: %.S
++ $(CC) $(ASFLAGS) -c $< -o $@
++ $(STRIPTOOL) -x -R .note -R .comment $@
++
++clean:
++ $(RM) *.[oa] *~ core
+diff -Nrup a/libc/string/avr32/memchr.S b/libc/string/avr32/memchr.S
+--- a/libc/string/avr32/memchr.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/memchr.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,62 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define str r12
++#define chr r11
++#define len r10
++
++ .text
++ .global memchr
++ .type memchr, @function
++memchr:
++ or chr, chr, chr << 8
++ or chr, chr, chr << 16
++
++ mov r9, str
++ andl r9, 3, COH
++ brne .Lunaligned_str
++
++1: sub len, 4
++ brlt 2f
++ ld.w r8, str++
++ psub.b r9, r8, r11
++ tnbz r9
++ brne 1b
++
++ sub str, 4
++ bfextu r9, r8, 24, 8
++ cp.b r9, r11
++ reteq str
++ sub str, -1
++ bfextu r9, r8, 16, 8
++ cp.b r9, r11
++ reteq str
++ sub str, -1
++ bfextu r9, r8, 8, 8
++ cp.b r9, r11
++ reteq str
++ sub str, -1
++ retal str
++
++2: sub len, -4
++ reteq 0
++
++3: ld.ub r8, str++
++ cp.w r8, 0
++ reteq str
++ sub len, 1
++ brne 3b
++
++ retal 0
++
++.Lunaligned_str:
++1: sub len, 1
++ retlt 0
++ ld.ub r8, str++
++ cp.b r8, r11
++ reteq str
++ sub r9, 1
++ brge 1b
++
++ rjmp .Laligned_search
+diff -Nrup a/libc/string/avr32/memcmp.S b/libc/string/avr32/memcmp.S
+--- a/libc/string/avr32/memcmp.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/memcmp.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2004 Atmel Norway.
++ */
++
++#define s1 r12
++#define s2 r11
++#define len r10
++
++ .text
++ .global memcmp
++ .type memcmp, @function
++ .align 1
++memcmp:
++ sub len, 4
++ brlt .Lless_than_4
++
++1: ld.w r8, s1++
++ ld.w r9, s2++
++ cp.w r8, r9
++ brne .Lfound_word
++ sub len, 4
++ brge 1b
++
++.Lless_than_4:
++ sub len, -4
++ reteq 0
++
++1: ld.ub r8, s1++
++ ld.ub r9, s2++
++ sub r8, r9
++ retne r8
++ sub len, 1
++ brgt 1b
++
++ retal 0
++
++.Lfound_word:
++ psub.b r9, r8, r9
++ bfextu r8, r9, 24, 8
++ retne r8
++ bfextu r8, r9, 16, 8
++ retne r8
++ bfextu r8, r9, 8, 8
++ retne r8
++ retal r9
++
++ .size memcmp, . - memcmp
++
++ .weak bcmp
++ bcmp = memcmp
+diff -Nrup a/libc/string/avr32/memcpy.S b/libc/string/avr32/memcpy.S
+--- a/libc/string/avr32/memcpy.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/memcpy.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,110 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++/* Don't use r12 as dst since we must return it unmodified */
++#define dst r9
++#define src r11
++#define len r10
++
++ .text
++ .global memcpy
++ .type memcpy, @function
++
++ .global __memcpy
++ .hidden __memcpy
++ .type __memcpy, @function
++memcpy:
++__memcpy:
++ pref src[0]
++ mov dst, r12
++
++ /* If we have less than 32 bytes, don't do anything fancy */
++ cp.w len, 32
++ brge .Lmore_than_31
++
++ sub len, 1
++ retlt r12
++1: ld.ub r8, src++
++ st.b dst++, r8
++ sub len, 1
++ brge 1b
++ retal r12
++
++.Lmore_than_31:
++ pushm r0-r7, lr
++
++ /* Check alignment */
++ mov r8, src
++ andl r8, 31, COH
++ brne .Lunaligned_src
++ mov r8, dst
++ andl r8, 3, COH
++ brne .Lunaligned_dst
++
++.Laligned_copy:
++ sub len, 32
++ brlt .Lless_than_32
++
++1: /* Copy 32 bytes at a time */
++ ldm src, r0-r7
++ sub src, -32
++ stm dst, r0-r7
++ sub dst, -32
++ sub len, 32
++ brge 1b
++
++.Lless_than_32:
++ /* Copy 16 more bytes if possible */
++ sub len, -16
++ brlt .Lless_than_16
++ ldm src, r0-r3
++ sub src, -16
++ sub len, 16
++ stm dst, r0-r3
++ sub dst, -16
++
++.Lless_than_16:
++ /* Do the remaining as byte copies */
++ neg len
++ add pc, pc, len << 2
++ .rept 15
++ ld.ub r0, src++
++ st.b dst++, r0
++ .endr
++
++ popm r0-r7, pc
++
++.Lunaligned_src:
++ /* Make src cacheline-aligned. r8 = (src & 31) */
++ rsub r8, r8, 32
++ sub len, r8
++1: ld.ub r0, src++
++ st.b dst++, r0
++ sub r8, 1
++ brne 1b
++
++ /* If dst is word-aligned, we're ready to go */
++ pref src[0]
++ mov r8, 3
++ tst dst, r8
++ breq .Laligned_copy
++
++.Lunaligned_dst:
++ /* src is aligned, but dst is not. Expect bad performance */
++ sub len, 4
++ brlt 2f
++1: ld.w r0, src++
++ st.w dst++, r0
++ sub len, 4
++ brge 1b
++
++2: neg len
++ add pc, pc, len << 2
++ .rept 3
++ ld.ub r0, src++
++ st.b dst++, r0
++ .endr
++
++ popm r0-r7, pc
++ .size memcpy, . - memcpy
+diff -Nrup a/libc/string/avr32/memmove.S b/libc/string/avr32/memmove.S
+--- a/libc/string/avr32/memmove.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/memmove.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,114 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define dst r12
++#define src r11
++#define len r10
++
++ .text
++ .global memmove
++ .type memmove, @function
++
++ .global __memmove
++ .hidden __memmove
++ .type __memmove, @function
++memmove:
++__memmove:
++ cp.w src, dst
++ brge __memcpy
++
++ add dst, len
++ add src, len
++ pref src[-1]
++
++ /*
++ * The rest is basically the same as in memcpy.S except that
++ * the direction is reversed.
++ */
++ cp.w len, 32
++ brge .Lmore_than_31
++
++ sub len, 1
++ retlt r12
++1: ld.ub r8, --src
++ st.b --dst, r8
++ sub len, 1
++ brge 1b
++ retal r12
++
++.Lmore_than_31:
++ pushm r0-r7, lr
++
++ /* Check alignment */
++ mov r8, src
++ andl r8, 31, COH
++ brne .Lunaligned_src
++ mov r8, r12
++ andl r8, 3, COH
++ brne .Lunaligned_dst
++
++.Laligned_copy:
++ sub len, 32
++ brlt .Lless_than_32
++
++1: /* Copy 32 bytes at a time */
++ sub src, 32
++ ldm src, r0-r7
++ sub dst, 32
++ sub len, 32
++ stm dst, r0-r7
++ brge 1b
++
++.Lless_than_32:
++ /* Copy 16 more bytes if possible */
++ sub len, -16
++ brlt .Lless_than_16
++ sub src, 16
++ ldm src, r0-r3
++ sub dst, 16
++ sub len, 16
++ stm dst, r0-r3
++
++.Lless_than_16:
++ /* Do the remaining as byte copies */
++ sub len, -16
++ breq 2f
++1: ld.ub r0, --src
++ st.b --dst, r0
++ sub len, 1
++ brne 1b
++
++2: popm r0-r7, pc
++
++.Lunaligned_src:
++ /* Make src cacheline-aligned. r8 = (src & 31) */
++ sub len, r8
++1: ld.ub r0, --src
++ st.b --dst, r0
++ sub r8, 1
++ brne 1b
++
++ /* If dst is word-aligned, we're ready to go */
++ pref src[-4]
++ mov r8, 3
++ tst dst, r8
++ breq .Laligned_copy
++
++.Lunaligned_dst:
++ /* src is aligned, but dst is not. Expect bad performance */
++ sub len, 4
++ brlt 2f
++1: ld.w r0, --src
++ st.w --dst, r0
++ sub len, 4
++ brge 1b
++
++2: neg len
++ add pc, pc, len << 2
++ .rept 3
++ ld.ub r0, --src
++ st.b --dst, r0
++ .endr
++
++ popm r0-r7, pc
+diff -Nrup a/libc/string/avr32/memset.S b/libc/string/avr32/memset.S
+--- a/libc/string/avr32/memset.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/memset.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2004 Atmel Norway.
++ */
++
++#define s r12
++#define c r11
++#define n r10
++
++ .text
++ .global memset
++ .type memset, @function
++
++ .global __memset
++ .hidden __memset
++ .type __memset, @function
++
++ .align 1
++memset:
++__memset:
++ cp.w n, 32
++ mov r9, s
++ brge .Llarge_memset
++
++ sub n, 1
++ retlt s
++1: st.b s++, c
++ sub n, 1
++ brge 1b
++
++ retal r9
++
++.Llarge_memset:
++ mov r8, r11
++ mov r11, 3
++ bfins r8, r8, 8, 8
++ bfins r8, r8, 16, 16
++ tst s, r11
++ breq 2f
++
++1: st.b s++, r8
++ sub n, 1
++ tst s, r11
++ brne 1b
++
++2: mov r11, r9
++ mov r9, r8
++ sub n, 8
++
++3: st.d s++, r8
++ sub n, 8
++ brge 3b
++
++ /* If we are done, n == -8 and we'll skip all st.b insns below */
++ neg n
++ lsl n, 1
++ add pc, n
++ .rept 7
++ st.b s++, r8
++ .endr
++ retal r11
+diff -Nrup a/libc/string/avr32/strcat.S b/libc/string/avr32/strcat.S
+--- a/libc/string/avr32/strcat.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/strcat.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,95 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define s1 r9
++#define s2 r11
++
++ .text
++ .global strcat
++ .type strcat, @function
++ .align 1
++strcat:
++ mov s1, r12
++
++ /* Make sure s1 is word-aligned */
++ mov r10, s1
++ andl r10, 3, COH
++ breq 2f
++
++ add pc, pc, r10 << 3
++ sub r0, r0, 0 /* 4-byte nop */
++ ld.ub r8, s1++
++ sub r8, r8, 0
++ breq 2f
++ ld.ub r8, s1++
++ sub r8, r8, 0
++ breq 3f
++ ld.ub r8, s1++
++ sub r8, r8, 0
++ breq 4f
++
++ /* Find the end of the first string */
++5: ld.w r8, s1++
++ tnbz r8
++ brne 5b
++
++ sub s1, 4
++
++ bfextu r10, r8, 24, 8
++ cp.w r10, 0
++ breq 1f
++ sub s1, -1
++ bfextu r10, r8, 16, 8
++ cp.w r10, 0
++ breq 2f
++ sub s1, -1
++ bfextu r10, r8, 8, 8
++ cp.w r10, 0
++ breq 3f
++ sub s1, -1
++ rjmp 4f
++
++ /* Now, append s2 */
++1: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++2: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++3: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++4: ld.ub r8, s2++
++ st.b s1++, r8
++ cp.w r8, 0
++ reteq r12
++
++ /* Copy one word at a time */
++ ld.w r8, s2++
++ tnbz r8
++ breq 2f
++1: st.w r8, s2++
++ ld.w r8, s2++
++ tnbz r8
++ brne 1b
++
++ /* Copy the remaining bytes */
++ bfextu r10, r8, 24, 8
++ st.b s1++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 16, 8
++ st.b s1++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 8, 8
++ st.b s1++, r10
++ cp.w r10, 0
++ reteq r12
++ st.b s1++, r8
++ retal r12
++ .size strcat, . - strcat
+diff -Nrup a/libc/string/avr32/strcmp.S b/libc/string/avr32/strcmp.S
+--- a/libc/string/avr32/strcmp.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/strcmp.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,80 @@
++/*
++ * Copyright (C) 2004 Atmel Norway.
++ */
++
++#define s1 r12
++#define s2 r11
++#define len r10
++
++ .text
++ .global strcmp
++ .type strcmp, @function
++ .align 1
++strcmp:
++ mov r8, 3
++ tst s1, r8
++ brne .Lunaligned_s1
++ tst s2, r8
++ brne .Lunaligned_s2
++
++1: ld.w r8, s1++
++ ld.w r9, s2++
++ cp.w r8, r9
++ brne 2f
++ tnbz r8
++ brne 1b
++ retal 0
++
++2: bfextu r12, r8, 24, 8
++ bfextu r11, r9, 24, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 16, 8
++ bfextu r11, r9, 16, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 8, 8
++ bfextu r11, r9, 8, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 0, 8
++ bfextu r11, r9, 0, 8
++ sub r12, r11
++ retal r12
++
++.Lunaligned_s1:
++3: tst s1, r8
++ breq 4f
++ ld.ub r10, s1++
++ ld.ub r9, s2++
++ sub r10, r9
++ retne r10
++ cp.w r9, 0
++ brne 3b
++ retal r10
++
++4: tst s2, r8
++ breq 1b
++
++.Lunaligned_s2:
++ /*
++ * s1 and s2 can't both be aligned, and unaligned word loads
++ * can trigger spurious exceptions if we cross a page boundary.
++ * Do it the slow way...
++ */
++1: ld.ub r8, s1++
++ ld.ub r9, s2++
++ sub r8, r9
++ retne r8
++ cp.w r9, 0
++ brne 1b
++ retal 0
++
++ .weak strcoll
++ strcoll = strcmp
+diff -Nrup a/libc/string/avr32/strcpy.S b/libc/string/avr32/strcpy.S
+--- a/libc/string/avr32/strcpy.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/strcpy.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ *
++ * To reduce the size, this one might simply call strncpy with len = -1.
++ */
++
++#define dst r9
++#define src r11
++
++ .text
++ .global strcpy
++ .type strcpy, @function
++strcpy:
++ mov dst, r12
++
++ pref src[0]
++
++ /*
++ * Check alignment. If src is aligned but dst isn't, we can't
++ * do much about it...
++ */
++ mov r8, src
++ andl r8, 3 COH
++ brne .Lunaligned_src
++
++.Laligned_copy:
++1: ld.w r8, src++
++ tnbz r8
++ breq 2f
++ st.w dst++, r8
++ rjmp 1b
++
++2: /*
++ * Ok, r8 now contains the terminating '\0'. Copy the
++ * remaining bytes individually.
++ */
++ bfextu r10, r8, 24, 8
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 16, 8
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++ bfextu r10, r8, 8, 8
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++ st.b dst++, r8
++ retal r12
++
++.Lunaligned_src:
++ /* Copy bytes until we're aligned */
++ rsub r8, r8, 4
++ add pc, pc, r8 << 3
++ nop
++ nop
++ ld.ub r10, src++
++ st.b dst++, r10
++ cp.w r10, 0
++ reteq r12
++
++ rjmp .Laligned_copy
+diff -Nrup a/libc/string/avr32/stringtest.c b/libc/string/avr32/stringtest.c
+--- a/libc/string/avr32/stringtest.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/stringtest.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,144 @@
++
++#include <stdio.h>
++#include <string.h>
++#include <time.h>
++#include <sys/mman.h>
++
++#define BUF_SIZE (8 * 1024)
++
++static char *buf1;
++static char *buf1_ref;
++static char *buf2;
++
++extern void *optimized_memcpy(void *dest, void *src, size_t len);
++extern void *optimized_memmove(void *dest, void *src, size_t len);
++extern char *optimized_strcpy(char *dest, char *src);
++extern char *optimized_strncpy(char *dest, char *src, size_t len);
++
++void dump_mismatch(char *buf, char *ref, size_t len)
++{
++ int i, j;
++
++ for (i = 0; i < len; i += 16) {
++ if (memcmp(buf + i, ref + i, 16) == 0)
++ continue;
++
++ printf("%4x buf:", i);
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", buf[j]);
++ printf("\n ref:");
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", ref[j]);
++ printf("\n");
++ }
++}
++
++static void test_memcpy(int src_offset, int dst_offset, int len)
++{
++ clock_t start, old, new;
++ int i;
++
++ memset(buf1, 0x55, BUF_SIZE);
++ memset(buf1_ref, 0x55, BUF_SIZE);
++ memset(buf2, 0xaa, BUF_SIZE);
++
++ printf("Testing memcpy with offsets %d => %d and len %d...",
++ src_offset, dst_offset, len);
++
++ start = clock();
++ for (i = 0; i < 8192; i++)
++ optimized_memcpy(buf1 + dst_offset, buf2 + src_offset, len);
++ new = clock() - start;
++ start = clock();
++ for ( i = 0; i < 8192; i++)
++ memcpy(buf1_ref + dst_offset, buf2 + src_offset, len);
++ old = clock() - start;
++
++ if (memcmp(buf1, buf1_ref, BUF_SIZE) == 0)
++ printf("OK\n");
++ else {
++ printf("FAILED\n");
++ dump_mismatch(buf1, buf1_ref, BUF_SIZE);
++ }
++ printf("CPU time used: %d vs. %d\n", new, old);
++}
++
++static void test_memmove(int src_offset, int dst_offset, int len)
++{
++ clock_t start, old, new;
++
++ memset(buf1, 0x55, BUF_SIZE);
++ memset(buf1_ref, 0x55, BUF_SIZE);
++ memset(buf2, 0xaa, BUF_SIZE);
++
++ printf("Testing memmove with offsets %d => %d and len %d...",
++ src_offset, dst_offset, len);
++
++ start = clock();
++ optimized_memmove(buf1 + dst_offset, buf2 + src_offset, len);
++ new = clock() - start;
++ start = clock();
++ memmove(buf1_ref + dst_offset, buf2 + src_offset, len);
++ old = clock() - start;
++
++ if (memcmp(buf1, buf1_ref, BUF_SIZE) == 0)
++ printf("OK\n");
++ else {
++ printf("FAILED\n");
++ dump_mismatch(buf1, buf1_ref, BUF_SIZE);
++ }
++ printf("CPU time used: %d vs. %d\n", new, old);
++}
++
++int main(int argc, char *argv[])
++{
++ buf2 = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf2 == MAP_FAILED) {
++ perror("Failed to allocate memory for buf2");
++ return 1;
++ }
++ buf1 = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf1 == MAP_FAILED) {
++ perror("Failed to allocate memory for buf1");
++ return 1;
++ }
++ buf1_ref = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf1_ref == MAP_FAILED) {
++ perror("Failed to allocate memory for buf1_ref");
++ return 1;
++ }
++ printf("\n === MEMCPY ===\n\n");
++
++ test_memcpy(0, 0, BUF_SIZE - 32);
++ test_memcpy(0, 0, 1);
++ test_memcpy(0, 0, 31);
++ test_memcpy(0, 0, 32);
++ test_memcpy(0, 0, 127);
++ test_memcpy(0, 0, 128);
++ test_memcpy(4, 4, BUF_SIZE - 32 - 4);
++ test_memcpy(1, 1, BUF_SIZE - 32 - 1);
++ test_memcpy(1, 1, 126);
++ test_memcpy(0, 3, 128);
++ test_memcpy(1, 4, 128);
++ test_memcpy(0, 0, 0);
++
++ printf("\n === MEMMOVE ===\n\n");
++
++ test_memmove(0, 0, BUF_SIZE - 32);
++ test_memmove(0, 0, 1);
++ test_memmove(0, 0, 31);
++ test_memmove(0, 0, 32);
++ test_memmove(0, 0, BUF_SIZE - 33);
++ test_memmove(0, 0, 128);
++ test_memmove(4, 4, BUF_SIZE - 32 - 4);
++ test_memmove(1, 1, BUF_SIZE - 32 - 1);
++ test_memmove(1, 1, BUF_SIZE - 130);
++ test_memmove(0, 3, BUF_SIZE - 128);
++ test_memmove(1, 4, BUF_SIZE - 128);
++ test_memmove(0, 0, 0);
++
++ return 0;
++}
+diff -Nrup a/libc/string/avr32/strlen.S b/libc/string/avr32/strlen.S
+--- a/libc/string/avr32/strlen.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/strlen.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,52 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define str r12
++
++ .text
++ .global strlen
++ .type strlen, @function
++strlen:
++ mov r11, r12
++
++ mov r9, str
++ andl r9, 3, COH
++ brne .Lunaligned_str
++
++1: ld.w r8, str++
++ tnbz r8
++ brne 1b
++
++ sub r12, r11
++ bfextu r9, r8, 24, 8
++ cp.w r9, 0
++ subeq r12, 4
++ reteq r12
++ bfextu r9, r8, 16, 8
++ cp.w r9, 0
++ subeq r12, 3
++ reteq r12
++ bfextu r9, r8, 8, 8
++ cp.w r9, 0
++ subeq r12, 2
++ reteq r12
++ sub r12, 1
++ retal r12
++
++.Lunaligned_str:
++ add pc, pc, r9 << 3
++ sub r0, r0, 0 /* 4-byte nop */
++ ld.ub r8, str++
++ sub r8, r8, 0
++ breq 1f
++ ld.ub r8, str++
++ sub r8, r8, 0
++ breq 1f
++ ld.ub r8, str++
++ sub r8, r8, 0
++ brne 1b
++
++1: sub r12, 1
++ sub r12, r11
++ retal r12
+diff -Nrup a/libc/string/avr32/strncpy.S b/libc/string/avr32/strncpy.S
+--- a/libc/string/avr32/strncpy.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/strncpy.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,77 @@
++/*
++ * Copyright (C) 2004 Atmel Norway
++ */
++
++#define dst r9
++#define src r11
++
++ .text
++ .global strcpy
++ .type strncpy, @function
++strncpy:
++ mov dst, r12
++
++ pref src[0]
++ mov dst, r12
++
++ /*
++ * Check alignment. If src is aligned but dst isn't, we can't
++ * do much about it...
++ */
++ mov r8, src
++ andl r8, 3 COH
++ brne .Lunaligned_src
++
++.Laligned_copy:
++ sub r10, 4
++ brlt 3f
++1: ld.w r8, src++
++ tnbz r8
++ breq 2f
++ st.w dst++, r8
++ sub r10, 4
++ brne 1b
++
++3: sub r10, -4
++ reteq r12
++
++ /* This is safe as long as src is word-aligned and r10 > 0 */
++ ld.w r8, src++
++
++2: /*
++ * Ok, r8 now contains the terminating '\0'. Copy the
++ * remaining bytes individually.
++ */
++ bfextu r11, r8, 24, 8
++ st.b dst++, r11
++ cp.w r11, 0
++ reteq r12
++ sub r10, 1
++ reteq r12
++ bfextu r11, r8, 16, 8
++ st.b dst++, r11
++ cp.w r11, 0
++ reteq r12
++ sub r10, 1
++ reteq r12
++ bfextu r11, r8, 8, 8
++ st.b dst++, r11
++ cp.w r11, 0
++ reteq r12
++ sub r10, 1
++ reteq r12
++ st.b dst++, r8
++ retal r12
++
++.Lunaligned_src:
++ /* Copy bytes until we're aligned */
++ min r8, r8, r10
++ sub r10, r8
++ sub r8, 1
++ retlt r12
++1: ld.ub r10, src++
++ st.b dst++, r10
++ sub r8, 1
++ brge 1b
++
++ rjmp .Laligned_copy
+diff -Nrup a/libc/string/avr32/test_memcpy.c b/libc/string/avr32/test_memcpy.c
+--- a/libc/string/avr32/test_memcpy.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/string/avr32/test_memcpy.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,66 @@
++
++#include <stdio.h>
++#include <string.h>
++
++#define BUF_SIZE 32768
++
++static char buf1[BUF_SIZE] __attribute__((aligned(32)));
++static char buf1_ref[BUF_SIZE] __attribute__((aligned(32)));
++static char buf2[BUF_SIZE] __attribute__((aligned(32)));
++
++extern void *new_memcpy(void *dest, void *src, size_t len);
++
++void dump_mismatch(char *buf, char *ref, size_t len)
++{
++ int i, j;
++
++ for (i = 0; i < len; i += 16) {
++ if (memcmp(buf + i, ref + i, 16) == 0)
++ continue;
++
++ printf("% 4x buf:", i);
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", buf[j]);
++ printf("\n ref:");
++ for (j = i; j < (i + 16); j++)
++ printf(" %02x", ref[j]);
++ printf("\n");
++ }
++}
++
++void test(int src_offset, int dst_offset, int len)
++{
++ memset(buf1, 0x55, sizeof(buf1));
++ memset(buf1_ref, 0x55, sizeof(buf1_ref));
++ memset(buf2, 0xaa, sizeof(buf2));
++
++ printf("Testing with offsets %d => %d and len %d...",
++ src_offset, dst_offset, len);
++
++ new_memcpy(buf1 + dst_offset, buf2 + src_offset, len);
++ memcpy(buf1_ref + dst_offset, buf2 + src_offset, len);
++
++ if (memcmp(buf1, buf1_ref, sizeof(buf1)) == 0)
++ printf("OK\n");
++ else {
++ printf("FAILED\n");
++ dump_mismatch(buf1, buf1_ref, sizeof(buf1));
++ }
++}
++
++int main(int argc, char *argv[])
++{
++ test(0, 0, BUF_SIZE);
++ test(0, 0, 1);
++ test(0, 0, 31);
++ test(0, 0, 32);
++ test(0, 0, 127);
++ test(0, 0, 128);
++ test(4, 4, BUF_SIZE - 4);
++ test(1, 1, BUF_SIZE - 1);
++ test(1, 1, 126);
++ test(0, 3, 128);
++ test(1, 4, 128);
++
++ return 0;
++}
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/atomicity.h b/libc/sysdeps/linux/avr32/bits/atomicity.h
+--- a/libc/sysdeps/linux/avr32/bits/atomicity.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/atomicity.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,86 @@
++/* Low-level functions for atomic operations. AVR32 version.
++ Copyright (C) 1997, 1998, 1999, 2000 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _ATOMICITY_H
++#define _ATOMICITY_H 1
++
++#include <inttypes.h>
++
++static inline int
++__attribute__((unused))
++exchange_and_add (volatile uint32_t *mem, int val)
++{
++ int tmp, result;
++
++ __asm__ __volatile__(
++ "/* Inline exchange and add */\n"
++ "1: ssrf 5\n"
++ " ld.w %0, %3\n"
++ " add %1, %0, %4\n"
++ " stcond %2, %1\n"
++ " brne 1b"
++ : "=&r"(result), "=&r"(tmp), "=m"(*mem)
++ : "m"(*mem), "r"(val)
++ : "cc", "memory");
++
++ return result;
++}
++
++static inline void
++__attribute__((unused))
++atomic_add (volatile uin32_t *mem, int val)
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline atomic add */\n"
++ "1: ssrf 5\n"
++ " ld.w %0, %2\n"
++ " add %0, %3\n"
++ " stcond %2, %0\n"
++ " brne 1b"
++ : "=&r"(result), "=m"(*mem)
++ : "m"(*mem), "r"(val)
++ : "cc", "memory");
++}
++
++static inline int
++__attribute__((unused))
++compare_and_swap(volatile long int *p, long int oldval, long int newval)
++{
++ long int result, tmp;
++
++ __asm__ __volatile__(
++ "/* Inline compare and swap */\n"
++ "1: ssrf 5\n"
++ " ld.w %1, %3\n"
++ " cp.w %1, %5\n"
++ " sreq %0\n"
++ " brne 2f\n"
++ " stcond %2, %4\n"
++ " brne 1b\n"
++ "2:"
++ : "=&r"(result), "=&r"(tmp), "=m"(*p)
++ : "m"(*p), "r"(newval), "r"(oldval)
++ : "cc", "memory");
++
++ return result;
++}
++
++#endif /* atomicity.h */
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/byteswap.h b/libc/sysdeps/linux/avr32/bits/byteswap.h
+--- a/libc/sysdeps/linux/avr32/bits/byteswap.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/byteswap.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,80 @@
++/* Macros to swap the order of bytes in integer values.
++ Copyright (C) 2005 Atmel Norway.
++
++ 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. */
++
++#if !defined _BYTESWAP_H && !defined _NETINET_IN_H
++# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
++#endif
++
++#ifndef _BITS_BYTESWAP_H
++#define _BITS_BYTESWAP_H 1
++
++/* Swap bytes in 16 bit value. */
++#if defined __GNUC__
++# define __bswap_16(x) (__extension__ __builtin_bswap_16(x))
++#else
++/* This is better than nothing. */
++static __inline unsigned short int
++__bswap_16 (unsigned short int __bsx)
++{
++ return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
++}
++#endif
++
++/* Swap bytes in 32 bit value. */
++#if defined __GNUC__
++# define __bswap_32(x) (__extension__ __builtin_bswap_32(x))
++#else
++static __inline unsigned int
++__bswap_32 (unsigned int __bsx)
++{
++ return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
++ (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));
++}
++#endif
++
++#if defined __GNUC__
++/* Swap bytes in 64 bit value. */
++# define __bswap_constant_64(x) \
++ ((((x) & 0xff00000000000000ull) >> 56) \
++ | (((x) & 0x00ff000000000000ull) >> 40) \
++ | (((x) & 0x0000ff0000000000ull) >> 24) \
++ | (((x) & 0x000000ff00000000ull) >> 8) \
++ | (((x) & 0x00000000ff000000ull) << 8) \
++ | (((x) & 0x0000000000ff0000ull) << 24) \
++ | (((x) & 0x000000000000ff00ull) << 40) \
++ | (((x) & 0x00000000000000ffull) << 56))
++
++# define __bswap_64(x) \
++ (__extension__ \
++ ({ \
++ union { \
++ __extension__ unsigned long long int __ll; \
++ unsigned int __l[2]; \
++ } __w, __r; \
++ if (__builtin_constant_p(x)) \
++ __r.__ll = __bswap_constant_64(x); \
++ else { \
++ __w.__ll = (x); \
++ __r.__l[0] = __bswap_32(__w.__l[1]); \
++ __r.__l[1] = __bswap_32(__w.__l[0]); \
++ } \
++ __r.__ll; \
++ }))
++#endif
++
++#endif /* _BITS_BYTESWAP_H */
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/endian.h b/libc/sysdeps/linux/avr32/bits/endian.h
+--- a/libc/sysdeps/linux/avr32/bits/endian.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/endian.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,7 @@
++/* AVR32 is big-endian */
++
++#ifndef _ENDIAN_H
++# error "Never use <bits/endian.h> directly; include <endian.h> instead."
++#endif
++
++#define __BYTE_ORDER __BIG_ENDIAN
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/fcntl.h b/libc/sysdeps/linux/avr32/bits/fcntl.h
+--- a/libc/sysdeps/linux/avr32/bits/fcntl.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/fcntl.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,168 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ *
++ * This file is part of the Linux kernel
++ */
++#ifndef _FCNTL_H
++# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
++#endif
++
++#include <sys/types.h>
++
++/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
++ located on an ext2 file system */
++#define O_ACCMODE 00000003
++#define O_RDONLY 00000000
++#define O_WRONLY 00000001
++#define O_RDWR 00000002
++#define O_CREAT 00000100 /* not fcntl */
++#define O_EXCL 00000200 /* not fcntl */
++#define O_NOCTTY 00000400 /* not fcntl */
++#define O_TRUNC 00001000 /* not fcntl */
++#define O_APPEND 00002000
++#define O_NONBLOCK 00004000
++#define O_NDELAY O_NONBLOCK
++#define O_SYNC 00010000
++#define O_ASYNC 00020000
++
++#ifdef __USE_GNU
++# define O_DIRECT 00040000 /* must be a directory */
++# define O_DIRECTORY 00200000 /* direct disk access */
++# define O_NOFOLLOW 00400000 /* don't follow links */
++# define O_NOATIME 01000000 /* don't set atime */
++#endif
++
++#ifdef __USE_LARGEFILE64
++# define O_LARGEFILE 00100000
++#endif
++
++/* For now Linux has synchronisity options for data and read operations.
++ We define the symbols here but let them do the same as O_SYNC since
++ this is a superset. */
++#if defined __USE_POSIX199309 || defined __USE_UNIX98
++# define O_DSYNC O_SYNC /* Synchronize data. */
++# define O_RSYNC O_SYNC /* Synchronize read operations. */
++#endif
++
++#define F_DUPFD 0 /* dup */
++#define F_GETFD 1 /* get close_on_exec */
++#define F_SETFD 2 /* set/clear close_on_exec */
++#define F_GETFL 3 /* get file->f_flags */
++#define F_SETFL 4 /* set file->f_flags */
++
++#ifndef __USE_FILE_OFFSET64
++# define F_GETLK 5
++# define F_SETLK 6
++# define F_SETLKW 7
++#else
++# define F_GETLK F_GETLK64
++# define F_SETLK F_SETLK64
++# define F_SETLKW F_SETLKW64
++#endif
++#define F_GETLK64 12 /* using 'struct flock64' */
++#define F_SETLK64 13
++#define F_SETLKW64 14
++
++#if defined __USE_BSD || defined __USE_XOPEN2K
++# define F_SETOWN 8 /* for sockets. */
++# define F_GETOWN 9 /* for sockets. */
++#endif
++
++#ifdef __USE_GNU
++# define F_SETSIG 10 /* for sockets. */
++# define F_GETSIG 11 /* for sockets. */
++#endif
++
++#ifdef __USE_GNU
++# define F_SETLEASE 1024 /* Set a lease. */
++# define F_GETLEASE 1025 /* Enquire what lease is active. */
++# define F_NOTIFY 1026 /* Request notfications on a directory. */
++#endif
++
++/* for F_[GET|SET]FL */
++#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
++
++/* for posix fcntl() and lockf() */
++#define F_RDLCK 0
++#define F_WRLCK 1
++#define F_UNLCK 2
++
++/* for old implementation of bsd flock () */
++#define F_EXLCK 4 /* or 3 */
++#define F_SHLCK 8 /* or 4 */
++
++/* for leases */
++#define F_INPROGRESS 16
++
++#ifdef __USE_BSD
++/* operations for bsd flock(), also used by the kernel implementation */
++# define LOCK_SH 1 /* shared lock */
++# define LOCK_EX 2 /* exclusive lock */
++# define LOCK_NB 4 /* or'd with one of the above to prevent
++ blocking */
++# define LOCK_UN 8 /* remove lock */
++#endif
++
++#ifdef __USE_GNU
++# define LOCK_MAND 32 /* This is a mandatory flock */
++# define LOCK_READ 64 /* ... Which allows concurrent
++ read operations */
++# define LOCK_WRITE 128 /* ... Which allows concurrent
++ write operations */
++# define LOCK_RW 192 /* ... Which allows concurrent
++ read & write ops */
++#endif
++
++#ifdef __USE_GNU
++/* Types of directory notifications that may be requested with F_NOTIFY. */
++# define DN_ACCESS 0x00000001 /* File accessed. */
++# define DN_MODIFY 0x00000002 /* File modified. */
++# define DN_CREATE 0x00000004 /* File created. */
++# define DN_DELETE 0x00000008 /* File removed. */
++# define DN_RENAME 0x00000010 /* File renamed. */
++# define DN_ATTRIB 0x00000020 /* File changed attibutes. */
++# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */
++#endif
++
++struct flock {
++ short l_type;
++ short l_whence;
++#ifndef __USE_FILE_OFFSET64
++ __off_t l_start;
++ __off_t l_len;
++#else
++ __off64_t l_start;
++ __off64_t l_len;
++#endif
++ __pid_t l_pid;
++};
++
++#ifdef __USE_LARGEFILE64
++struct flock64 {
++ short l_type;
++ short l_whence;
++ __off64_t l_start;
++ __off64_t l_len;
++ __pid_t l_pid;
++};
++#endif
++
++/* Define some more compatibility macros to be backward compatible with
++ * BSD systems which did not managed to hide these kernel macros. */
++#ifdef __USE_BSD
++# define FAPPEND O_APPEND
++# define FFSYNC O_FSYNC
++# define FASYNC O_ASYNC
++# define FNONBLOCK O_NONBLOCK
++# define FNDELAY O_NDELAY
++#endif /* Use BSD. */
++
++/* Advise to `posix_fadvise'. */
++#ifdef __USE_XOPEN2K
++# define POSIX_FADV_NORMAL 0 /* No further special treatment. */
++# define POSIX_FADV_RANDOM 1 /* Expect random page references. */
++# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */
++# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
++# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
++#endif
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/kernel_stat.h b/libc/sysdeps/linux/avr32/bits/kernel_stat.h
+--- a/libc/sysdeps/linux/avr32/bits/kernel_stat.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/kernel_stat.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,63 @@
++#ifndef _BITS_STAT_STRUCT_H
++#define _BITS_STAT_STRUCT_H
++
++/*
++ * This file provides struct stat, taken from kernel 2.6.4
++ * (include/asm-avr32/stat.h revision 1.1).
++ */
++
++struct kernel_stat {
++ unsigned long st_dev;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned long st_rdev;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#define STAT_HAVE_NSEC 1
++
++struct kernel_stat64 {
++ unsigned long long st_dev;
++
++ unsigned long long st_ino;
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++
++ long long st_size;
++ unsigned long __pad1;
++ unsigned long st_blksize;
++
++ unsigned long long st_blocks;
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* _BITS_STAT_STRUCT_H */
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/kernel_types.h b/libc/sysdeps/linux/avr32/bits/kernel_types.h
+--- a/libc/sysdeps/linux/avr32/bits/kernel_types.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/kernel_types.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,56 @@
++/* Note that we use the exact same include guard #define names
++ * as asm/posix_types.h. This will avoid gratuitous conflicts
++ * with the posix_types.h kernel header, and will ensure that
++ * our private content, and not the kernel header, will win.
++ * -Erik
++ */
++#ifndef __ASM_AVR32_POSIX_TYPES_H
++#define __ASM_AVR32_POSIX_TYPES_H
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_dev_t;
++typedef unsigned long __kernel_ino_t;
++typedef unsigned short __kernel_mode_t;
++typedef unsigned short __kernel_nlink_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned short __kernel_ipc_pid_t;
++typedef unsigned int __kernel_uid_t;
++typedef unsigned int __kernel_gid_t;
++typedef unsigned long __kernel_size_t;
++typedef int __kernel_ssize_t;
++typedef int __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_suseconds_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++
++typedef unsigned short __kernel_old_uid_t;
++typedef unsigned short __kernel_old_gid_t;
++typedef unsigned short __kernel_old_dev_t;
++
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++
++typedef struct {
++#if defined(__USE_ALL)
++ int val[2];
++#else
++ int __val[2];
++#endif
++} __kernel_fsid_t;
++
++#endif /* __ASM_AVR32_POSIX_TYPES_H */
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/machine-gmon.h b/libc/sysdeps/linux/avr32/bits/machine-gmon.h
+--- a/libc/sysdeps/linux/avr32/bits/machine-gmon.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/machine-gmon.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,69 @@
++/* Machine-dependent definitions for profiling support. AVR32 version.
++ Copyright (C) 1996, 1997, 1998 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#define mcount_internal __mcount_internal
++
++#define _MCOUNT_DECL(frompc, selfpc) \
++static void __attribute((used)) mcount_internal(unsigned long frompc, unsigned long selfpc)
++
++/*
++ * This mcount implementation expects to get called after the prologue
++ * has been run. It also expects that r7 contains a valid frame
++ * pointer.
++ *
++ * When profiling, the compiler should generate something like this at
++ * each function entry:
++ *
++ * pushm r0-r7,lr // lr mandatory, others optional
++ * mov r7, sp
++ * // rest of prologue goes here
++ * mcall pc[.LC1 - .]
++ * // rest of function goes here
++ * .LC1:
++ * .long mcount
++ *
++ * or for PIC:
++ *
++ * pushm r0-r7,lr
++ * mov r7, sp
++ * // rest of prologue goes here
++ * lddpc r0, .LC1
++ * .L1: rsub r0, pc
++ * mcall r0[mcount@GOT]
++ * // rest of function goes here
++ * .LC1:
++ * .long .L1 - _GLOBAL_OFFSET_TABLE_
++ *
++ * This way, when mcount() is called, r7 points to the calling
++ * function's return address. It is guaranteed that calling mcount
++ * will clobber no registers except LR, which is unavoidable.
++ */
++#define MCOUNT asm( \
++ " .align 4\n" \
++ " .global _mcount\n" \
++ " .type _mcount,@function\n" \
++ "_mcount:\n" \
++ " pushm r8-r12,lr\n" \
++ " mov r11, lr\n" \
++ " ld.w r12, r7[0]\n" \
++ " rcall __mcount_internal\n" \
++ " popm r8-r12,pc\n" \
++ " .size _mcount, . - _mcount\n" \
++ " .weak mcount\n" \
++ " mcount = _mcount");
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/mman.h b/libc/sysdeps/linux/avr32/bits/mman.h
+--- a/libc/sysdeps/linux/avr32/bits/mman.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/mman.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,95 @@
++/* Definitions for POSIX memory map interface. Linux/AVR32 version.
++ Copyright (C) 1997, 2000 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_MMAN_H
++# error "Never include this file directly. Use <sys/mman.h> instead"
++#endif
++
++/* The following definitions basically come from the kernel headers.
++ But the kernel header is not namespace clean. */
++
++
++/* Protections are chosen from these bits, OR'd together. The
++ implementation does not necessarily support PROT_EXEC or PROT_WRITE
++ without PROT_READ. The only guarantees are that no writing will be
++ allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
++
++#define PROT_READ 0x1 /* Page can be read. */
++#define PROT_WRITE 0x2 /* Page can be written. */
++#define PROT_EXEC 0x4 /* Page can be executed. */
++#define PROT_NONE 0x0 /* Page can not be accessed. */
++
++/* Sharing types (must choose one and only one of these). */
++#define MAP_SHARED 0x01 /* Share changes. */
++#define MAP_PRIVATE 0x02 /* Changes are private. */
++#ifdef __USE_MISC
++# define MAP_TYPE 0x0f /* Mask for type of mapping. */
++#endif
++
++/* Other flags. */
++#define MAP_FIXED 0x10 /* Interpret addr exactly. */
++#ifdef __USE_MISC
++# define MAP_FILE 0
++# define MAP_ANONYMOUS 0x20 /* Don't use a file. */
++# define MAP_ANON MAP_ANONYMOUS
++#endif
++
++/* These are Linux-specific. */
++#ifdef __USE_MISC
++# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */
++# define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */
++# define MAP_LOCKED 0x2000 /* Lock the mapping. */
++# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */
++# define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
++# define MAP_NONBLOCK 0x10000 /* do not block on IO */
++#endif
++
++/* Flags to `msync'. */
++#define MS_ASYNC 1 /* Sync memory asynchronously. */
++#define MS_SYNC 4 /* Synchronous memory sync. */
++#define MS_INVALIDATE 2 /* Invalidate the caches. */
++
++/* Flags for `mlockall'. */
++#define MCL_CURRENT 1 /* Lock all currently mapped pages. */
++#define MCL_FUTURE 2 /* Lock all additions to address
++ space. */
++
++/* Flags for `mremap'. */
++#ifdef __USE_GNU
++# define MREMAP_MAYMOVE 1
++#endif
++
++/* Advise to `madvise'. */
++#ifdef __USE_BSD
++# define MADV_NORMAL 0 /* No further special treatment. */
++# define MADV_RANDOM 1 /* Expect random page references. */
++# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define MADV_WILLNEED 3 /* Will need these pages. */
++# define MADV_DONTNEED 4 /* Don't need these pages. */
++#endif
++
++/* The POSIX people had to invent similar names for the same things. */
++#ifdef __USE_XOPEN2K
++# define POSIX_MADV_NORMAL 0 /* No further special treatment. */
++# define POSIX_MADV_RANDOM 1 /* Expect random page references. */
++# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */
++# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */
++#endif
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/profil-counter.h b/libc/sysdeps/linux/avr32/bits/profil-counter.h
+--- a/libc/sysdeps/linux/avr32/bits/profil-counter.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/profil-counter.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,26 @@
++/* Low-level statistical profiling support function. Linux/AVR32 version.
++ Copyright (C) 1996, 1997, 1998, 2002 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <signal.h>
++
++void
++profil_counter(int signo, siginfo_t *si, struct sigcontext *sc)
++{
++ profil_count((void *)sc->pc);
++}
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/setjmp.h b/libc/sysdeps/linux/avr32/bits/setjmp.h
+--- a/libc/sysdeps/linux/avr32/bits/setjmp.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/setjmp.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,21 @@
++/*
++ * Copyright (C) 2004-2005 Atmel Norway
++ */
++#ifndef _SETJMP_H
++# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
++#endif
++
++#ifndef _ASM
++/*
++ * The jump buffer contains r0-r7, sr, sp and lr. Other registers are
++ * not saved.
++ */
++typedef int __jmp_buf[11];
++#endif
++
++#define __JMP_BUF_SP 4
++
++/* Test if longjmp to JMPBUF would unwind the frame containing a local
++ variable at ADDRESS. */
++#define _JMPBUF_UNWINDS(jmpbuf, address) \
++ ((void *)(address) < (void *)(jmpbuf[__JMP_BUF_SP]))
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/syscalls.h b/libc/sysdeps/linux/avr32/bits/syscalls.h
+--- a/libc/sysdeps/linux/avr32/bits/syscalls.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/syscalls.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,143 @@
++#ifndef _SYSCALL_H
++# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
++#endif
++
++/*
++ * This includes the `__NR_<name>' syscall numbers taken from the
++ * Linux kernel header files. It also defines the traditional
++ * `SYS_<name>' macros for older programs.
++ */
++#include <bits/sysnum.h>
++
++#ifndef __set_errno
++# define __set_errno(val) (*__errno_location()) = (val)
++#endif
++#ifndef SYS_ify
++# define SYS_ify(syscall_name) (__NR_##syscall_name)
++#endif
++
++#ifndef __ASSEMBLER__
++
++#undef _syscall0
++#define _syscall0(type,name) \
++ type name(void) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 0)); \
++ }
++
++#undef _syscall1
++#define _syscall1(type,name,type1,arg1) \
++ type name(type1 arg1) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 1, arg1)); \
++ }
++
++#undef _syscall2
++#define _syscall2(type,name,type1,arg1,type2,arg2) \
++ type name(type1 arg1, type2 arg2) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 2, arg1, arg2)); \
++ }
++
++#undef _syscall3
++#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
++ type name(type1 arg1, type2 arg2, type3 arg3) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 3, arg1, \
++ arg2, arg3)); \
++ }
++
++#undef _syscall4
++#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 4, arg1, arg2, \
++ arg3, arg4)); \
++ }
++
++#undef _syscall5
++#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4,type5,arg5) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
++ type5 arg5) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 5, arg1, arg2, \
++ arg3, arg4, arg5)); \
++ }
++
++#undef _syscall6
++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4,type5,arg5,type6,arg6) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
++ type5 arg5, type6 arg6) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 6, arg1, arg2, arg3, \
++ arg4, arg5, arg6)); \
++ }
++
++#undef unlikely
++#define unlikely(x) __builtin_expect((x), 0)
++
++#undef INLINE_SYSCALL
++#define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ unsigned _sys_result = INTERNAL_SYSCALL(name, , nr, args); \
++ if (unlikely(INTERNAL_SYSCALL_ERROR_P(_sys_result, ))) { \
++ __set_errno(INTERNAL_SYSCALL_ERRNO(_sys_result, )); \
++ _sys_result = (unsigned int) -1; \
++ } \
++ (int) _sys_result; \
++ })
++
++#undef INTERNAL_SYSCALL_DECL
++#define INTERNAL_SYSCALL_DECL(err) do { } while(0)
++
++#undef INTERNAL_SYSCALL
++#define INTERNAL_SYSCALL(name, err, nr, args...) \
++ ({ \
++ register int _a1 asm ("r12"); \
++ register int _scno asm("r8") = SYS_ify(name); \
++ LOAD_ARGS_##nr (args); \
++ asm volatile ("scall /* syscall " #name " */" \
++ : "=r" (_a1) \
++ : "r"(_scno) ASM_ARGS_##nr \
++ : "lr", "cc", "memory"); \
++ _a1; \
++ })
++
++#undef INTERNAL_SYSCALL_ERROR_P
++#define INTERNAL_SYSCALL_ERROR_P(val, err) \
++ ((unsigned int)(val) >= 0xfffff001U)
++
++#undef INTERNAL_SYSCALL_ERRNO
++#define INTERNAL_SYSCALL_ERRNO(val, errr) (-(val))
++
++#define LOAD_ARGS_0() do { } while(0)
++#define ASM_ARGS_0
++#define LOAD_ARGS_1(a1) \
++ _a1 = (int) (a1); \
++ LOAD_ARGS_0()
++#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a1)
++#define LOAD_ARGS_2(a1, a2) \
++ register int _a2 asm("r11") = (int)(a2); \
++ LOAD_ARGS_1(a1)
++#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a2)
++#define LOAD_ARGS_3(a1, a2, a3) \
++ register int _a3 asm("r10") = (int)(a3); \
++ LOAD_ARGS_2(a1, a2)
++#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a3)
++#define LOAD_ARGS_4(a1, a2, a3, a4) \
++ register int _a4 asm("r9") = (int)(a4); \
++ LOAD_ARGS_3(a1, a2, a3)
++#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a4)
++#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
++ register int _a5 asm("r5") = (int)(a5); \
++ LOAD_ARGS_4(a1, a2, a3, a4)
++#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a5)
++#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
++ register int _a6 asm("r3") = (int)(a6); \
++ LOAD_ARGS_5(a1, a2, a3, a4, a5)
++#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a6)
++
++#endif /* __ASSEMBLER__ */
+diff -Nrup a/libc/sysdeps/linux/avr32/bits/wordsize.h b/libc/sysdeps/linux/avr32/bits/wordsize.h
+--- a/libc/sysdeps/linux/avr32/bits/wordsize.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bits/wordsize.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1 @@
++#define __WORDSIZE 32
+diff -Nrup a/libc/sysdeps/linux/avr32/brk.c b/libc/sysdeps/linux/avr32/brk.c
+--- a/libc/sysdeps/linux/avr32/brk.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/brk.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,23 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <errno.h>
++#include <sys/syscall.h>
++
++void *__curbrk = 0;
++
++int brk (void *addr)
++{
++ void *newbrk;
++
++ newbrk = INLINE_SYSCALL(brk, 1, addr);
++
++ __curbrk = newbrk;
++
++ if (newbrk < addr) {
++ __set_errno (ENOMEM);
++ return -1;
++ }
++
++ return 0;
++}
+diff -Nrup a/libc/sysdeps/linux/avr32/bsd-_setjmp.S b/libc/sysdeps/linux/avr32/bsd-_setjmp.S
+--- a/libc/sysdeps/linux/avr32/bsd-_setjmp.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bsd-_setjmp.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,12 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++
++ /* This just does a tail-call to __sigsetjmp(env, 0) */
++ .global _setjmp
++ .type _setjmp,"function"
++ .align 1
++_setjmp:
++ mov r11, 0
++ bral __sigsetjmp_internal
++ .size _setjmp, . - _setjmp
+diff -Nrup a/libc/sysdeps/linux/avr32/bsd-setjmp.S b/libc/sysdeps/linux/avr32/bsd-setjmp.S
+--- a/libc/sysdeps/linux/avr32/bsd-setjmp.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/bsd-setjmp.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,12 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++
++ /* This just does a tail-call to __sigsetjmp(env, 1) */
++ .global setjmp
++ .type setjmp,"function"
++ .align 1
++setjmp:
++ mov r11, 1
++ bral __sigsetjmp_internal
++ .size setjmp, . - setjmp
+diff -Nrup a/libc/sysdeps/linux/avr32/clone.c b/libc/sysdeps/linux/avr32/clone.c
+--- a/libc/sysdeps/linux/avr32/clone.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/clone.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <errno.h>
++#include <sys/syscall.h>
++#include <unistd.h>
++
++/*
++ * I don't know if we can be absolutely certain that the fn and arg
++ * parameters are preserved when returning as the child. If the
++ * compiler stores them in registers (r0-r7), they should be.
++ */
++int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg)
++{
++ register int (*_fn)(void *arg) = fn;
++ register void *_arg = arg;
++ int err;
++
++ /* Sanity check the arguments */
++ err = -EINVAL;
++ if (!fn)
++ goto syscall_error;
++ if (!child_stack)
++ goto syscall_error;
++
++ err = INLINE_SYSCALL(clone, 2, flags, child_stack);
++ if (err < 0)
++ goto syscall_error;
++ else if (err != 0)
++ return err;
++
++ _exit(_fn(_arg));
++
++syscall_error:
++ __set_errno (-err);
++ return -1;
++}
+diff -Nrup a/libc/sysdeps/linux/avr32/crt1.S b/libc/sysdeps/linux/avr32/crt1.S
+--- a/libc/sysdeps/linux/avr32/crt1.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/crt1.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,93 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ *
++ * When we enter _start, the stack looks like this:
++ * argc argument counter
++ * argv[0] pointer to program name
++ * argv[1..argc-1] pointers to program args
++ * NULL
++ * env[0..N] pointers to environment variables
++ * NULL
++ *
++ * r12 contains a function pointer to be registered with `atexit'.
++ * This is how the dynamic linker arranges to have DT_FINI functions
++ * called for shared libraries that have been loaded before this
++ * code runs.
++ *
++ * We're going to call the following function:
++ * __uClibc_main(int (*main)(int, char **, char **), int argc,
++ * char **argv, void (*app_init)(void), void (*app_fini)(void),
++ * void (*rtld_fini)(void), void *stack_end)
++ *
++ * So we need to set up things as follows:
++ * r12 = address of main
++ * r11 = argc
++ * r10 = &argv[0]
++ * r9 = address of _init
++ * r8 = address of _fini
++ * sp[0] = whatever we got passed in r12
++ */
++
++#include <features.h>
++
++ .text
++ .global _start
++ .type _start, @function
++_start:
++ /* Clear the frame pointer and link register since this is the outermost frame. */
++ mov r7, 0
++ mov lr, 0
++
++ ld.w r11, sp++ /* argc */
++ mov r10, sp /* &argv[0] */
++
++ st.w --sp, r10 /* stack_end */
++ st.w --sp, r12 /* rtld_fini */
++
++#ifdef __PIC__
++ lddpc r6, .L_GOT
++.L_RGOT:
++ rsub r6, pc
++ lda.w r9, _init
++ lda.w r8, _fini
++ lda.w r12, main
++
++ /* Ok, now run uClibc's main() -- should not return */
++ call __uClibc_main
++
++ .align 2
++.L_GOT:
++ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
++#else
++ lddpc r9, __init_addr /* app_init */
++ lddpc r8, __fini_addr /* app_fini */
++ lddpc r12, __main_addr /* main */
++
++ /* Ok, now run uClibc's main() -- should not return */
++ lddpc pc, ___uClibc_main_addr
++
++ .align 2
++__init_addr:
++ .long _init
++__fini_addr:
++ .long _fini
++__main_addr:
++ .long main
++___uClibc_main_addr:
++ .long __uClibc_main
++#endif
++ .size _start, . - _start
++
++ /*
++ * The LSB says we need this.
++ */
++ .section ".note.ABI-tag", "a"
++ .align 4
++ .long 2f - 1f /* namesz */
++ .long 4f - 3f /* descsz */
++ .long 1 /* type */
++1: .asciz "GNU" /* name */
++2: .align 4
++3: .long 0 /* Linux executable */
++ .long 2,6,0 /* Earliest compatible kernel */
++4: .align 4
+diff -Nrup a/libc/sysdeps/linux/avr32/crti.S b/libc/sysdeps/linux/avr32/crti.S
+--- a/libc/sysdeps/linux/avr32/crti.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/crti.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,17 @@
++
++ .section .init
++ .align 2
++ .global _init
++ .type _init, @function
++_init:
++ /* Use a four-byte instruction to avoid NOPs */
++ stm --sp, r0-r7,lr
++ .align 2
++
++ .section .fini
++ .align 2
++ .global _fini
++ .type _fini, @function
++_fini:
++ stm --sp, r0-r7,lr
++ .align 2
+diff -Nrup a/libc/sysdeps/linux/avr32/crtn.S b/libc/sysdeps/linux/avr32/crtn.S
+--- a/libc/sysdeps/linux/avr32/crtn.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/crtn.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,14 @@
++
++ .section .init
++ .align 2
++ .global _init
++ .type _init, @function
++ ldm sp++, r0-r7,pc
++ .size _init, . - _init
++
++ .section .fini
++ .align 2
++ .global _fini
++ .type _fini, @function
++ ldm sp++, r0-r7,pc
++ .size _fini, . - _fini
+diff -Nrup a/libc/sysdeps/linux/avr32/__longjmp.S b/libc/sysdeps/linux/avr32/__longjmp.S
+--- a/libc/sysdeps/linux/avr32/__longjmp.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/__longjmp.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,17 @@
++/* longjmp for AVR32
++ *
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++
++ .global __longjmp
++ .type __longjmp,"function"
++ .align 1
++__longjmp:
++ ldm r12++, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr
++ mov r12, r11 /* get the return value right */
++ mustr r8 /* restore status register (lower half) */
++ cp r12, 0 /* can't return zero */
++ frs
++ moveq r12, 1
++ mov pc,lr
++ .size __longjmp, . - __longjmp
+diff -Nrup a/libc/sysdeps/linux/avr32/Makefile b/libc/sysdeps/linux/avr32/Makefile
+--- a/libc/sysdeps/linux/avr32/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/Makefile 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,93 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++TOPDIR=../../../../
++include $(TOPDIR)Rules.mak
++ASFLAGS=$(CFLAGS)
++
++CRT_SRC = crt1.S
++CRT_OBJ = crt1.o
++SCRT_OBJ = $(patsubst %,S%, $(CRT_OBJ))
++CTOR_TARGETS=$(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o
++
++SSRC=__longjmp.S setjmp.S bsd-setjmp.S vfork.S \
++ bsd-_setjmp.S sigrestorer.S syscall.S
++SOBJS=$(patsubst %.S,%.o, $(SSRC))
++
++CSRC=clone.c brk.c sigaction.c mmap.c
++COBJS=$(patsubst %.c,%.o, $(CSRC))
++
++OBJS=$(SOBJS) $(COBJS)
++
++OBJ_LIST=../../../obj.sysdeps.$(TARGET_ARCH)
++
++all: $(OBJ_LIST)
++
++$(OBJ_LIST): $(OBJS) $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS)
++ echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $(OBJ_LIST)
++ $(INSTALL) -d $(TOPDIR)lib/
++ cp $(CRT_OBJ) $(SCRT_OBJ) $(TOPDIR)lib/
++
++$(CRT_OBJ): $(CRT_SRC)
++ $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++$(SCRT_OBJ): $(CRT_SRC)
++ $(CC) $(ASFLAGS) $(PIEFLAG) -DL_$* $< -c -o $*.o
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++$(SOBJS): %.o : %.S
++ $(CC) $(ASFLAGS) -c $< -o $@
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++$(COBJS): %.o : %.c
++ $(CC) $(CFLAGS) -c $< -o $@
++ $(STRIPTOOL) -x -R .note -R .comment $*.o
++
++ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y)
++crti.o: crti.S
++ $(CC) $(ASFLAGS) -c crti.S -o crti.o
++
++$(TOPDIR)lib/crti.o: crti.o
++ $(INSTALL) -d $(TOPDIR)lib/
++ cp crti.o $(TOPDIR)lib/
++
++crtn.o: crtn.S
++ $(CC) $(ASFLAGS) -c crtn.S -o crtn.o
++
++$(TOPDIR)lib/crtn.o: crtn.o
++ $(INSTALL) -d $(TOPDIR)lib/
++ cp crtn.o $(TOPDIR)lib/
++else
++$(TOPDIR)lib/crti.o:
++ $(INSTALL) -d $(TOPDIR)lib/
++ $(AR) $(ARFLAGS) $(TOPDIR)lib/crti.o
++$(TOPDIR)lib/crtn.o:
++ $(INSTALL) -d $(TOPDIR)lib/
++ $(AR) $(ARFLAGS) $(TOPDIR)lib/crtn.o
++endif
++
++
++headers:
++# $(LN) -fs ../libc/sysdeps/linux/avr32/fpu_control.h $(TOPDIR)/include/
++
++clean:
++ $(RM) *.[oa] *~ core
++ $(RM) bits/sysnum.h
++ $(RM) gmon-start.S
++
+diff -Nrup a/libc/sysdeps/linux/avr32/_mmap.c b/libc/sysdeps/linux/avr32/_mmap.c
+--- a/libc/sysdeps/linux/avr32/_mmap.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/_mmap.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,33 @@
++/* Copyright (C) 2005 Atmel Norway
++
++ This program is free software; you can redistribute it and/or modify it under
++ the terms of the GNU Library General Public License as published by the Free
++ Software Foundation; either version 2 of the License, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++ details.
++
++ You should have received a copy of the GNU Library General Public License
++ along with this program; if not, write to the Free Software Foundation, Inc.,
++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ 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.
++ */
++
++#include <errno.h>
++#include <sys/mman.h>
++#include <sys/syscall.h>
++
++#define __NR_mmap2 __NR_mmap
++
++static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, __off_t, pgoff);
++
++__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
++{
++ return mmap2(addr, len, prot, flags, fd, offset >> 12);
++}
+diff -Nrup a/libc/sysdeps/linux/avr32/mmap.c b/libc/sysdeps/linux/avr32/mmap.c
+--- a/libc/sysdeps/linux/avr32/mmap.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/mmap.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,31 @@
++/* Copyright (C) 2005 Atmel Norway
++
++ This program is free software; you can redistribute it and/or modify it under
++ the terms of the GNU Library General Public License as published by the Free
++ Software Foundation; either version 2 of the License, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++ details.
++
++ You should have received a copy of the GNU Library General Public License
++ along with this program; if not, write to the Free Software Foundation, Inc.,
++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ 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.
++ */
++
++#include <errno.h>
++#include <sys/mman.h>
++#include <sys/syscall.h>
++
++static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, __off_t, pgoff);
++
++__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
++{
++ return mmap2(addr, len, prot, flags, fd, offset >> 12);
++}
+diff -Nrup a/libc/sysdeps/linux/avr32/setjmp.S b/libc/sysdeps/linux/avr32/setjmp.S
+--- a/libc/sysdeps/linux/avr32/setjmp.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/setjmp.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#define _SETJMP_H
++#define _ASM
++#include <bits/setjmp.h>
++
++ .text
++
++ .global __sigsetjmp
++ .type __sigsetjmp,"function"
++
++ /* Create a global, hidden symbol for use by setjmp() and _setjmp().
++ If it's not hidden, the linker will complain about a relative
++ jump to a dynamic symbol when building a shared library.
++
++ Also, if a user overrides the __sigsetjmp function, he might not
++ expect the setjmp() and _setjmp() function to effectively be
++ overridden as well. */
++ .global __sigsetjmp_internal
++ .hidden __sigsetjmp_internal
++ .type __sigsetjmp_internal,"function"
++ .align 1
++__sigsetjmp:
++__sigsetjmp_internal:
++ mustr r8
++ stm r12, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr
++
++ /* Make a tail call to __sigjmp_save; it takes the same args. */
++#ifdef __PIC__
++ mov r9, r6
++ lddpc r6, .LG
++.L1: rsub r6, pc
++ ld.w r8, r6[__sigjmp_save@got]
++ mov r6, r9
++ mov pc, r8
++
++ .align 2
++.LG: .long .L1 - _GLOBAL_OFFSET_TABLE_
++#else
++ rjmp __sigjmp_save
++#endif
++ .size __sigsetjmp, . - __sigsetjmp
+diff -Nrup a/libc/sysdeps/linux/avr32/sigaction.c b/libc/sysdeps/linux/avr32/sigaction.c
+--- a/libc/sysdeps/linux/avr32/sigaction.c 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sigaction.c 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <errno.h>
++#include <signal.h>
++#include <string.h>
++#include <sys/syscall.h>
++#include <bits/kernel_sigaction.h>
++
++#define SA_RESTORER 0x04000000
++extern void __default_rt_sa_restorer(void);
++
++/*
++ * If act is not NULL, change the action for sig to *act.
++ * If oact is not NULL, put the old action for sig in *oact.
++ */
++int __libc_sigaction(int signum, const struct sigaction *act,
++ struct sigaction *oldact)
++{
++ struct kernel_sigaction kact, koact;
++ int result;
++
++ if (act) {
++ kact.k_sa_handler = act->sa_handler;
++ memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
++ kact.sa_flags = act->sa_flags;
++ if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK))
++ kact.sa_restorer = act->sa_restorer;
++ else
++ kact.sa_restorer = __default_rt_sa_restorer;
++ kact.sa_flags |= SA_RESTORER;
++ }
++
++ result = __syscall_rt_sigaction(signum, act ? __ptrvalue(&kact) : NULL,
++ oldact ? __ptrvalue(&koact) : NULL,
++ _NSIG / 8);
++
++ if (oldact && result >= 0) {
++ oldact->sa_handler = koact.k_sa_handler;
++ memcpy(&oldact->sa_mask, &koact.sa_mask,
++ sizeof(oldact->sa_mask));
++ oldact->sa_flags = koact.sa_flags;
++ oldact->sa_restorer = koact.sa_restorer;
++ }
++
++ return result;
++}
++
++weak_alias(__libc_sigaction, sigaction)
+diff -Nrup a/libc/sysdeps/linux/avr32/sigrestorer.S b/libc/sysdeps/linux/avr32/sigrestorer.S
+--- a/libc/sysdeps/linux/avr32/sigrestorer.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sigrestorer.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,11 @@
++/*
++ * Copyright (C) 2004 Atmel Norway AS
++ */
++#include <sys/syscall.h>
++
++ .global __default_rt_sa_restorer
++ .type __default_rt_sa_restorer,"function"
++ .align 1
++__default_rt_sa_restorer:
++ mov r8, __NR_rt_sigreturn
++ scall
+diff -Nrup a/libc/sysdeps/linux/avr32/sys/elf.h b/libc/sysdeps/linux/avr32/sys/elf.h
+--- a/libc/sysdeps/linux/avr32/sys/elf.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sys/elf.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,26 @@
++/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_ELF_H
++#define _SYS_ELF_H 1
++
++#warning "This header is obsolete; use <sys/procfs.h> instead."
++
++#include <sys/procfs.h>
++
++#endif /* sys/elf.h */
+diff -Nrup a/libc/sysdeps/linux/avr32/sys/io.h b/libc/sysdeps/linux/avr32/sys/io.h
+--- a/libc/sysdeps/linux/avr32/sys/io.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sys/io.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,48 @@
++/* Copyright (C) 1996, 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_IO_H
++
++#define _SYS_IO_H 1
++#include <features.h>
++
++__BEGIN_DECLS
++
++/* If TURN_ON is TRUE, request for permission to do direct i/o on the
++ port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O
++ permission off for that range. This call requires root privileges. */
++extern int ioperm (unsigned long int __from, unsigned long int __num,
++ int __turn_on) __THROW;
++
++/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero,
++ permission to access any I/O port is granted. This call requires
++ root privileges. */
++extern int iopl (int __level) __THROW;
++
++/* The functions that actually perform reads and writes. */
++extern unsigned char inb (unsigned long int port) __THROW;
++extern unsigned short int inw (unsigned long int port) __THROW;
++extern unsigned long int inl (unsigned long int port) __THROW;
++
++extern void outb (unsigned char value, unsigned long int port) __THROW;
++extern void outw (unsigned short value, unsigned long int port) __THROW;
++extern void outl (unsigned long value, unsigned long int port) __THROW;
++
++__END_DECLS
++
++#endif /* _SYS_IO_H */
+diff -Nrup a/libc/sysdeps/linux/avr32/sys/procfs.h b/libc/sysdeps/linux/avr32/sys/procfs.h
+--- a/libc/sysdeps/linux/avr32/sys/procfs.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sys/procfs.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,123 @@
++/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_PROCFS_H
++#define _SYS_PROCFS_H 1
++
++/* This is somewhat modelled after the file of the same name on SVR4
++ systems. It provides a definition of the core file format for ELF
++ used on Linux. It doesn't have anything to do with the /proc file
++ system, even though Linux has one.
++
++ Anyway, the whole purpose of this file is for GDB and GDB only.
++ Don't read too much into it. Don't use it for anything other than
++ GDB unless you know what you are doing. */
++
++#include <features.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/user.h>
++
++__BEGIN_DECLS
++
++/* Type for a general-purpose register. */
++typedef unsigned long elf_greg_t;
++
++/* And the whole bunch of them. We could have used `struct
++ user_regs' directly in the typedef, but tradition says that
++ the register set is an array, which does have some peculiar
++ semantics, so leave it that way. */
++#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++/* Register set for the floating-point registers. */
++typedef struct user_fpregs elf_fpregset_t;
++
++/* Signal info. */
++struct elf_siginfo
++ {
++ int si_signo; /* Signal number. */
++ int si_code; /* Extra code. */
++ int si_errno; /* Errno. */
++ };
++
++/* Definitions to generate Intel SVR4-like core files. These mostly
++ have the same names as the SVR4 types with "elf_" tacked on the
++ front to prevent clashes with Linux definitions, and the typedef
++ forms have been avoided. This is mostly like the SVR4 structure,
++ but more Linuxy, with things that Linux does not support and which
++ GDB doesn't really use excluded. */
++
++struct elf_prstatus
++ {
++ struct elf_siginfo pr_info; /* Info associated with signal. */
++ short int pr_cursig; /* Current signal. */
++ unsigned long int pr_sigpend; /* Set of pending signals. */
++ unsigned long int pr_sighold; /* Set of held signals. */
++ __pid_t pr_pid;
++ __pid_t pr_ppid;
++ __pid_t pr_pgrp;
++ __pid_t pr_sid;
++ struct timeval pr_utime; /* User time. */
++ struct timeval pr_stime; /* System time. */
++ struct timeval pr_cutime; /* Cumulative user time. */
++ struct timeval pr_cstime; /* Cumulative system time. */
++ elf_gregset_t pr_reg; /* GP registers. */
++ int pr_fpvalid; /* True if math copro being used. */
++ };
++
++
++#define ELF_PRARGSZ (80) /* Number of chars for args. */
++
++struct elf_prpsinfo
++ {
++ char pr_state; /* Numeric process state. */
++ char pr_sname; /* Char for pr_state. */
++ char pr_zomb; /* Zombie. */
++ char pr_nice; /* Nice val. */
++ unsigned long int pr_flag; /* Flags. */
++ unsigned short int pr_uid;
++ unsigned short int pr_gid;
++ int pr_pid, pr_ppid, pr_pgrp, pr_sid;
++ /* Lots missing */
++ char pr_fname[16]; /* Filename of executable. */
++ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
++ };
++
++/* The rest of this file provides the types for emulation of the
++ Solaris <proc_service.h> interfaces that should be implemented by
++ users of libthread_db. */
++
++/* Addresses. */
++typedef void *psaddr_t;
++
++/* Register sets. Linux has different names. */
++typedef elf_gregset_t prgregset_t;
++typedef elf_fpregset_t prfpregset_t;
++
++/* We don't have any differences between processes and threads,
++ therefore have only one PID type. */
++typedef __pid_t lwpid_t;
++
++/* Process status and info. In the end we do provide typedefs for them. */
++typedef struct elf_prstatus prstatus_t;
++typedef struct elf_prpsinfo prpsinfo_t;
++
++__END_DECLS
++
++#endif /* sys/procfs.h */
+diff -Nrup a/libc/sysdeps/linux/avr32/sys/ucontext.h b/libc/sysdeps/linux/avr32/sys/ucontext.h
+--- a/libc/sysdeps/linux/avr32/sys/ucontext.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sys/ucontext.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,94 @@
++/* Copyright (C) 1998, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++/* Linux/AVR32 ABI compliant context switching support. */
++
++#ifndef _SYS_UCONTEXT_H
++#define _SYS_UCONTEXT_H 1
++
++#include <features.h>
++#include <signal.h>
++#include <sys/procfs.h>
++#include <bits/sigcontext.h>
++
++typedef int greg_t;
++
++/* Number of general registers. */
++#define NGREG 16
++
++/* Container for all general registers. */
++typedef elf_gregset_t gregset_t;
++
++/* Number of each register is the `gregset_t' array. */
++enum
++{
++ R0 = 0,
++#define R0 R0
++ R1 = 1,
++#define R1 R1
++ R2 = 2,
++#define R2 R2
++ R3 = 3,
++#define R3 R3
++ R4 = 4,
++#define R4 R4
++ R5 = 5,
++#define R5 R5
++ R6 = 6,
++#define R6 R6
++ R7 = 7,
++#define R7 R7
++ R8 = 8,
++#define R8 R8
++ R9 = 9,
++#define R9 R9
++ R10 = 10,
++#define R10 R10
++ R11 = 11,
++#define R11 R11
++ R12 = 12,
++#define R12 R12
++ R13 = 13,
++#define R13 R13
++ R14 = 14,
++#define R14 R14
++ R15 = 15
++#define R15 R15
++};
++
++/* Structure to describe FPU registers. */
++typedef elf_fpregset_t fpregset_t;
++
++/* Context to describe whole processor state. */
++typedef struct
++ {
++ gregset_t gregs;
++ fpregset_t fpregs;
++ } mcontext_t;
++
++/* Userlevel context. */
++typedef struct ucontext
++{
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ struct sigcontext uc_mcontext;
++ sigset_t uc_sigmask; /* mask last for extensibility */
++} ucontext_t;
++
++#endif /* sys/ucontext.h */
+diff -Nrup a/libc/sysdeps/linux/avr32/sys/user.h b/libc/sysdeps/linux/avr32/sys/user.h
+--- a/libc/sysdeps/linux/avr32/sys/user.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/sys/user.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,46 @@
++#ifndef _SYS_USER_H
++#define _SYS_USER_H
++
++struct user_fpregs
++{
++
++};
++
++struct user_regs
++{
++ unsigned long sr;
++ unsigned long pc;
++ unsigned long lr;
++ unsigned long sp;
++ unsigned long r12;
++ unsigned long r11;
++ unsigned long r10;
++ unsigned long r9;
++ unsigned long r8;
++ unsigned long r7;
++ unsigned long r6;
++ unsigned long r5;
++ unsigned long r4;
++ unsigned long r3;
++ unsigned long r2;
++ unsigned long r1;
++ unsigned long r0;
++ unsigned long r12_orig;
++};
++
++struct user
++{
++ struct user_regs regs; /* general registers */
++ size_t u_tsize; /* text size (pages) */
++ size_t u_dsize; /* data size (pages) */
++ size_t u_ssize; /* stack size (pages) */
++ unsigned long start_code; /* text starting address */
++ unsigned long start_data; /* data starting address */
++ unsigned long start_stack; /* stack starting address */
++ long int signal; /* signal causing core dump */
++ struct user_regs * u_ar0; /* help gdb find registers */
++ unsigned long magic; /* identifies a core file */
++ char u_comm[32]; /* user command name */
++};
++
++#endif /* _SYS_USER_H */
+diff -Nrup a/libc/sysdeps/linux/avr32/syscall.S b/libc/sysdeps/linux/avr32/syscall.S
+--- a/libc/sysdeps/linux/avr32/syscall.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/syscall.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,81 @@
++/*
++ * syscall for AVR32/uClibc
++ *
++ * Copyright (C) 2004 Atmel Norway
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Library General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <features.h>
++
++ .text
++
++ /*
++ * long int syscall(long int sysno, ...)
++ */
++ .global syscall
++ .type syscall, @function
++ .align 2
++syscall:
++ stm --sp, r3,r5,lr
++ sub lr, sp, -12
++ mov r8, r12
++ ldm lr, r3,r5,r9-r12
++ scall
++ cp.w r12, -4095
++ brlo .Ldone
++
++#ifdef __PIC__
++ lddpc r5, .Lgot
++.Lgotcalc:
++ rsub r5, pc
++# ifdef __UCLIBC_HAS_THREADS__
++ mov r3, r12
++ mcall r5[__errno_location@got]
++ st.w r12[0], r3
++# else
++ ld.w r3, r5[errno@got]
++ st.w r3[0], r12
++# endif
++#else
++# ifdef __UCLIBC_HAS_THREADS__
++ mov r3, r12
++ mcall .Lerrno_location
++ st.w r12[0], r3
++# else
++ lddpc r3, .Lerrno
++ st.w r3[0], r12
++# endif
++#endif
++ mov r12, -1
++
++.Ldone:
++ ldm sp++, r3,r5,pc
++
++ .align 2
++#ifdef __PIC__
++.Lgot:
++ .long .Lgotcalc - _GLOBAL_OFFSET_TABLE_
++#else
++# ifdef __UCLIBC_HAS_THREADS__
++.Lerrno_location:
++ .long __errno_location
++# else
++.Lerrno:
++ .long errno
++# endif
++#endif
++
++
++ .size syscall, . - syscall
+diff -Nrup a/libc/sysdeps/linux/avr32/vfork.S b/libc/sysdeps/linux/avr32/vfork.S
+--- a/libc/sysdeps/linux/avr32/vfork.S 1969-12-31 19:00:00.000000000 -0500
++++ b/libc/sysdeps/linux/avr32/vfork.S 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,55 @@
++ /*
++ * vfork for uClibc
++ *
++ * Copyright (C) 2005 Atmel Norway
++ */
++
++ /*
++ * Clone the process without copying the address space. The
++ * calling process is suspended until the child either exits
++ * or calls execve.
++ *
++ * This all means that we cannot rely on the stack to store
++ * away registers, since they will be overwritten by the child
++ * as soon as it makes another function call (e.g. execve()).
++ * Fortunately, the Linux kernel preserves LR across system calls.
++ */
++#include <features.h>
++#include <sys/syscall.h>
++
++ .global __vfork
++ .type __vfork,@function
++ .align 1
++__vfork:
++ mov r8, __NR_vfork
++ scall
++ cp.w r12, -4096
++ retls r12
++
++ /* vfork failed, so we may use the stack freely */
++ pushm r4-r7,lr
++#ifdef __PIC__
++ lddpc r6, .L_GOT
++ rsub r4, r12, 0
++.L_RGOT:
++ rsub r6, pc
++ mcall r6[__errno_location@got]
++#else
++ rsub r4, r12, 0
++ mcall .L__errno_location
++#endif
++ st.w r12[0], r4
++ popm r4-r7,pc,r12=-1
++
++ .align 2
++#ifdef __PIC__
++.L_GOT:
++ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
++#else
++.L__errno_location:
++ .long __errno_location
++#endif
++ .size __vfork, . - __vfork
++
++ .weak vfork
++ vfork = __vfork
+diff -Nrup a/libc/sysdeps/linux/common/create_module.c b/libc/sysdeps/linux/common/create_module.c
+--- a/libc/sysdeps/linux/common/create_module.c 2004-03-11 19:21:20.000000000 -0500
++++ b/libc/sysdeps/linux/common/create_module.c 2008-02-28 19:02:10.000000000 -0500
+@@ -61,7 +61,8 @@ unsigned long create_module(const char *
+ {
+ return __create_module(name, size, 0, 0);
+ }
+-#else
++/* create_module is obsolete in Linux 2.6, so AVR32 doesn't have it */
++#elif !defined(__avr32__)
+ /* Sparc, MIPS, etc don't mistake return values for errors. */
+ _syscall2(unsigned long, create_module, const char *, name, size_t, size);
+ #endif
+diff -Nrup a/libc/sysdeps/linux/common/getrusage.c b/libc/sysdeps/linux/common/getrusage.c
+--- a/libc/sysdeps/linux/common/getrusage.c 2005-01-05 18:11:28.000000000 -0500
++++ b/libc/sysdeps/linux/common/getrusage.c 2008-02-28 19:02:10.000000000 -0500
+@@ -10,4 +10,4 @@
+ #include "syscalls.h"
+ #include <unistd.h>
+ #include <wait.h>
+-_syscall2(int, getrusage, int, who, struct rusage *, usage);
++_syscall2(int, getrusage, __rusage_who_t, who, struct rusage *, usage);
+diff -Nrup a/libc/sysdeps/linux/common/open64.c b/libc/sysdeps/linux/common/open64.c
+--- a/libc/sysdeps/linux/common/open64.c 2002-10-31 13:20:21.000000000 -0500
++++ b/libc/sysdeps/linux/common/open64.c 2008-02-28 19:02:10.000000000 -0500
+@@ -26,7 +26,7 @@
+ #endif
+
+ #ifdef __UCLIBC_HAS_LFS__
+-extern int __libc_open (__const char *file, int oflag, mode_t mode);
++extern int __libc_open (__const char *file, int oflag, ...);
+
+ /* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
+ a third argument is the file protection. */
+diff -Nrup a/libc/sysdeps/linux/common/__syscall_fcntl.c b/libc/sysdeps/linux/common/__syscall_fcntl.c
+--- a/libc/sysdeps/linux/common/__syscall_fcntl.c 2005-07-30 10:02:24.000000000 -0400
++++ b/libc/sysdeps/linux/common/__syscall_fcntl.c 2008-02-28 19:02:10.000000000 -0500
+@@ -12,7 +12,7 @@
+ #include <fcntl.h>
+
+ #if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64
+-extern int __libc_fcntl64(int fd, int cmd, long arg);
++extern int __libc_fcntl64(int fd, int cmd, ...);
+ #endif
+
+ #define __NR___syscall_fcntl __NR_fcntl
+diff -Nrup a/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h
+--- a/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h 1969-12-31 19:00:00.000000000 -0500
++++ b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,92 @@
++/* Machine-dependent pthreads configuration and inline functions.
++
++ Copyright (C) 2005 Atmel Norway
++ 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; see the file COPYING.LIB. If not,
++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#ifndef _PT_MACHINE_H
++#define _PT_MACHINE_H 1
++
++#include <features.h>
++
++static inline int
++_test_and_set (int *p, int v) __THROW
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline test and set */\n"
++ "1: ssrf 5\n"
++ " ld.w %0, %2\n"
++ " tst %0, %3\n"
++ " breq 2f\n"
++ " stcond %1, %3\n"
++ " brne 1b\n"
++ "2:"
++ : "=&r"(result), "=m"(*p)
++ : "m"(*p), "r"(v)
++ : "memory", "cc");
++
++ return result;
++}
++
++#ifndef PT_EI
++# define PT_EI extern inline
++#endif
++
++extern long int testandset (int *spinlock);
++extern int __compare_and_swap (long int *p, long int oldval, long int newval);
++
++/* Spinlock implementation; required. */
++PT_EI long int
++testandset (int *spinlock)
++{
++ return _test_and_set(spinlock, 1);
++}
++
++
++/* Get some notion of the current stack. Need not be exactly the top
++ of the stack, just something somewhere in the current frame. */
++#define CURRENT_STACK_FRAME stack_pointer
++register char * stack_pointer __asm__ ("sp");
++
++/* Compare-and-swap for semaphores. */
++
++#define HAS_COMPARE_AND_SWAP
++PT_EI int
++__compare_and_swap(long int *p, long int oldval, long int newval)
++{
++ long int result, tmp;
++
++ __asm__ __volatile__(
++ "/* Inline compare and swap */\n"
++ "1: ssrf 5\n"
++ " ld.w %1, %3\n"
++ " cp.w %1, %5\n"
++ " sreq %0\n"
++ " brne 2f\n"
++ " stcond %2, %4\n"
++ " brne 1b\n"
++ "2:"
++ : "=&r"(result), "=&r"(tmp), "=m"(*p)
++ : "m"(*p), "r"(newval), "r"(oldval)
++ : "cc", "memory");
++
++ return result;
++}
++
++#endif /* pt-machine.h */
+diff -Nrup a/Makefile b/Makefile
+--- a/Makefile 2007-02-01 21:24:29.000000000 -0500
++++ b/Makefile 2008-02-28 19:02:10.000000000 -0500
+@@ -163,7 +163,7 @@ install_dev:
+ else \
+ extra_exclude="" ; \
+ fi ; \
+- tar -chf - include --exclude .svn --exclude CVS $$extra_exclude \
++ tar -chf - --exclude .svn --exclude CVS $$extra_exclude include \
+ | tar -xf - -C $(PREFIX)$(DEVEL_PREFIX)
+ echo '/* Dont use _syscall#() macros; use the syscall() function */' > \
+ $(PREFIX)$(DEVEL_PREFIX)include/bits/syscalls.h
+diff -Nrup a/Makefile.orig b/Makefile.orig
+--- a/Makefile.orig 1969-12-31 19:00:00.000000000 -0500
++++ b/Makefile.orig 2007-02-01 21:24:29.000000000 -0500
+@@ -0,0 +1,383 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Library General Public
++# License as published by the Free Software Foundation; either
++# version 2 of the License, or (at your option) any later
++# version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU Library General Public License for more details.
++#
++# You should have received a copy of the GNU Library General
++# Public License along with this program; if not, write to the
++# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
++# Boston, MA 02111-1307 USA
++
++
++#--------------------------------------------------------------
++# You shouldn't need to mess with anything beyond this point...
++#--------------------------------------------------------------
++noconfig_targets := menuconfig config oldconfig randconfig \
++ defconfig allyesconfig allnoconfig clean distclean \
++ release tags TAGS
++TOPDIR=./
++include Rules.mak
++
++DIRS = ldso libc libcrypt libresolv libnsl libutil libm libpthread librt
++ifeq ($(strip $(UCLIBC_HAS_GETTEXT_AWARENESS)),y)
++ DIRS += libintl
++endif
++
++ifeq ($(strip $(HAVE_DOT_CONFIG)),y)
++
++all: headers pregen subdirs shared finished
++
++# In this section, we need .config
++-include .config.cmd
++
++shared: subdirs
++ifeq ($(strip $(HAVE_SHARED)),y)
++ $(SECHO)
++ $(SECHO) Building shared libraries ...
++ $(SECHO)
++ @$(MAKE) -C libc shared
++ @$(MAKE) -C ldso shared
++ @$(MAKE) -C libcrypt shared
++ @$(MAKE) -C libresolv shared
++ @$(MAKE) -C libnsl shared
++ @$(MAKE) -C libutil shared
++ @$(MAKE) -C libm shared
++ @$(MAKE) -C libpthread shared
++ @$(MAKE) -C librt shared
++ifeq ($(strip $(UCLIBC_HAS_GETTEXT_AWARENESS)),y)
++ @$(MAKE) -C libintl shared
++endif
++else
++ $(SECHO)
++ $(SECHO) Not building shared libraries ...
++ $(SECHO)
++endif
++
++finished: shared
++ $(SECHO)
++ $(SECHO) Finally finished compiling ...
++ $(SECHO)
++
++include/bits/uClibc_config.h: .config
++ @if [ ! -x ./extra/config/conf ] ; then \
++ $(MAKE) -C extra/config conf; \
++ fi;
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf -o extra/Configs/Config.in
++
++# For the moment, we have to keep re-running this target
++# because the fix includes scripts rely on pre-processers
++# in order to generate the headers correctly :(. That
++# means we can't use the $(HOSTCC) in order to get the
++# correct output.
++ifeq ($(strip $(ARCH_HAS_MMU)),y)
++export header_extra_args =
++else
++export header_extra_args = -n
++endif
++headers: include/bits/uClibc_config.h
++ @$(SHELL_SET_X); \
++ ./extra/scripts/fix_includes.sh \
++ -k $(KERNEL_SOURCE) -t $(TARGET_ARCH) \
++ $(header_extra_args)
++ @cd include/bits; \
++ set -e; \
++ for i in `ls ../../libc/sysdeps/linux/common/bits/*.h` ; do \
++ $(LN) -fs $$i .; \
++ done; \
++ if [ -d ../../libc/sysdeps/linux/$(TARGET_ARCH)/bits ] ; then \
++ for i in `ls ../../libc/sysdeps/linux/$(TARGET_ARCH)/bits/*.h` ; do \
++ $(LN) -fs $$i .; \
++ done; \
++ fi
++ @cd include/sys; \
++ set -e; \
++ for i in `ls ../../libc/sysdeps/linux/common/sys/*.h` ; do \
++ $(LN) -fs $$i .; \
++ done; \
++ if [ -d ../../libc/sysdeps/linux/$(TARGET_ARCH)/sys ] ; then \
++ for i in `ls ../../libc/sysdeps/linux/$(TARGET_ARCH)/sys/*.h` ; do \
++ $(LN) -fs $$i .; \
++ done; \
++ fi
++ @cd $(TOPDIR); \
++ set -e; \
++ $(SHELL_SET_X); \
++ TOPDIR=. CC="$(CC)" /bin/sh extra/scripts/gen_bits_syscall_h.sh > include/bits/sysnum.h.new; \
++ if cmp include/bits/sysnum.h include/bits/sysnum.h.new >/dev/null 2>&1; then \
++ $(RM) include/bits/sysnum.h.new; \
++ else \
++ mv -f include/bits/sysnum.h.new include/bits/sysnum.h; \
++ fi
++ $(MAKE) -C libc/sysdeps/linux/common headers
++ $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) headers
++
++# Command used to download source code
++WGET:=wget --passive-ftp
++
++LOCALE_DATA_FILENAME:=uClibc-locale-030818.tgz
++
++pregen: headers
++ifeq ($(strip $(UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA)),y)
++ (cd extra/locale; \
++ if [ ! -f $(LOCALE_DATA_FILENAME) ] ; then \
++ $(WGET) http://www.uclibc.org/downloads/$(LOCALE_DATA_FILENAME) ; \
++ fi );
++endif
++ifeq ($(strip $(UCLIBC_PREGENERATED_LOCALE_DATA)),y)
++ (cd extra/locale; zcat $(LOCALE_DATA_FILENAME) | tar -xvf -)
++ $(MAKE) -C extra/locale pregen
++endif
++
++
++subdirs: $(patsubst %, _dir_%, $(DIRS))
++$(patsubst %, _dir_%, $(DIRS)): headers
++ $(MAKE) -C $(patsubst _dir_%, %, $@)
++
++tags:
++ ctags -R
++
++install: install_runtime install_dev finished2
++
++
++RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB=$(shell extra/scripts/relative_path.sh $(DEVEL_PREFIX)lib $(RUNTIME_PREFIX)lib)
++
++# Installs header files and development library links.
++install_dev:
++ $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)lib
++ $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)include
++ -$(INSTALL) -m 644 lib/*.[ao] $(PREFIX)$(DEVEL_PREFIX)lib/
++ if [ "$(KERNEL_SOURCE)" = "$(DEVEL_PREFIX)" ] ; then \
++ extra_exclude="--exclude include/linux --exclude include/asm'*'" ; \
++ else \
++ extra_exclude="" ; \
++ fi ; \
++ tar -chf - include --exclude .svn --exclude CVS $$extra_exclude \
++ | tar -xf - -C $(PREFIX)$(DEVEL_PREFIX)
++ echo '/* Dont use _syscall#() macros; use the syscall() function */' > \
++ $(PREFIX)$(DEVEL_PREFIX)include/bits/syscalls.h
++ifneq ($(strip $(UCLIBC_HAS_FLOATS)),y)
++ # Remove floating point related headers since float support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/complex.h
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/fpu_control.h
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/ieee754.h
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/math.h
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/tgmath.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_WCHAR)),y)
++ # Remove wide char headers since wide char support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/wctype.h
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/wchar.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_LOCALE)),y)
++ # Remove iconv header since locale support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/iconv.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_GLIBC_CUSTOM_PRINTF)),y)
++ # Remove printf header since custom print specifier support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/printf.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_XLOCALE)),y)
++ # Remove xlocale header since extended locale support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/xlocale.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_GETTEXT_AWARENESS)),y)
++ # Remove libintl header since gettext support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/libintl.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_REGEX)),y)
++ # Remove regex headers since regex support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/regex.h
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/regexp.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_WORDEXP)),y)
++ # Remove wordexp header since wordexp support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/wordexp.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_FTW)),y)
++ # Remove ftw header since ftw support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/ftw.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_GLOB)),y)
++ # Remove glob header since glob support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/glob.h
++endif
++ifneq ($(strip $(UCLIBC_HAS_GNU_GETOPT)),y)
++ # Remove getopt header since gnu getopt support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/getopt.h
++endif
++ifneq ($(strip $(HAS_SHADOW)),y)
++ # Remove getopt header since shadow password support is disabled.
++ $(RM) $(PREFIX)$(DEVEL_PREFIX)include/shadow.h
++endif
++ -@for i in `find $(PREFIX)$(DEVEL_PREFIX) -type d` ; do \
++ chmod 755 $$i; chmod 644 $$i/*.h > /dev/null 2>&1; \
++ done;
++ -find $(PREFIX)$(DEVEL_PREFIX) -name .svn | xargs $(RM) -r;
++ -chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$$/\1:\2/'` $(PREFIX)$(DEVEL_PREFIX)
++ifeq ($(strip $(HAVE_SHARED)),y)
++ for i in `find lib/ -type l -name 'lib[a-zA-Z]*.so' | \
++ sed -e 's/lib\///'` ; do \
++ $(LN) -sf $(RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB)$$i.$(MAJOR_VERSION) \
++ $(PREFIX)$(DEVEL_PREFIX)lib/$$i; \
++ done;
++ifeq ($(strip $(PTHREADS_DEBUG_SUPPORT)),y)
++ $(LN) -sf $(RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB)libthread_db.so.1 \
++ $(PREFIX)$(DEVEL_PREFIX)lib/libthread_db.so
++endif
++# # If we build shared libraries then the static libs are PIC...
++# # Make _pic.a symlinks to make mklibs.py and similar tools happy.
++ for i in `find lib/ -type f -name '*.a' | sed -e 's/lib\///'` ; do \
++ $(LN) -sf $$i $(PREFIX)$(DEVEL_PREFIX)lib/`echo $$i \
++ | sed -e 's/\.a$$/_pic.a/'`; \
++ done;
++ # Ugh!!! Remember that libdl.a and libdl_pic.a are different. Since
++ # libdl is pretty small, and not likely to benefit from mklibs.py and
++ # similar, lets just remove libdl_pic.a and avoid the issue
++ rm -f $(PREFIX)$(DEVEL_PREFIX)lib/libdl_pic.a
++endif
++
++
++# Installs run-time libraries
++install_runtime:
++ifeq ($(strip $(HAVE_SHARED)),y)
++ $(INSTALL) -d $(PREFIX)$(RUNTIME_PREFIX)lib
++ $(INSTALL) -m 644 lib/lib*-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so \
++ $(PREFIX)$(RUNTIME_PREFIX)lib
++ cp -dRf lib/*.so.* $(PREFIX)$(RUNTIME_PREFIX)lib
++ @if [ -x lib/ld-uClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so ] ; then \
++ set -e; \
++ $(SHELL_SET_X); \
++ $(INSTALL) -m 755 lib/ld-uClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so \
++ $(PREFIX)$(RUNTIME_PREFIX)lib; \
++ fi;
++endif
++
++.PHONY: utils
++ifeq ($(strip $(HAVE_SHARED)),y)
++utils:
++ $(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils
++else
++utils: dummy
++endif
++
++# Installs helper applications, such as 'ldd' and 'ldconfig'
++install_utils: utils
++ $(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils install
++#ifeq ($(strip $(UCLIBC_HAS_LOCALE)),y)
++# @$(MAKE) -C libc/misc/wchar iconv.target
++# $(INSTALL) -d $(PREFIX)$(RUNTIME_PREFIX)/usr/bin;
++# $(INSTALL) -m 755 libc/misc/wchar/iconv.target $(PREFIX)$(RUNTIME_PREFIX)/usr/bin/iconv
++#endif
++
++finished2:
++ $(SECHO)
++ $(SECHO) Finished installing ...
++ $(SECHO)
++
++else # ifeq ($(strip $(HAVE_DOT_CONFIG)),y)
++
++all: menuconfig
++
++# configuration
++# ---------------------------------------------------------------------------
++extra/config/conf:
++ $(MAKE) -C extra/config conf
++
++extra/config/mconf:
++ $(MAKE) -C extra/config ncurses mconf
++
++menuconfig: extra/config/mconf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/mconf extra/Configs/Config.in
++
++config: extra/config/conf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf extra/Configs/Config.in
++
++oldconfig: extra/config/conf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf -o extra/Configs/Config.in
++
++randconfig: extra/config/conf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf -r extra/Configs/Config.in
++
++allyesconfig: extra/config/conf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf -y extra/Configs/Config.in
++ sed -i -e "s/^DODEBUG=.*/# DODEBUG is not set/" .config
++ sed -i -e "s/^DOASSERTS=.*/# DOASSERTS is not set/" .config
++ sed -i -e "s/^SUPPORT_LD_DEBUG_EARLY=.*/# SUPPORT_LD_DEBUG_EARLY is not set/" .config
++ sed -i -e "s/^SUPPORT_LD_DEBUG=.*/# SUPPORT_LD_DEBUG is not set/" .config
++ sed -i -e "s/^UCLIBC_MJN3_ONLY=.*/# UCLIBC_MJN3_ONLY is not set/" .config
++ @./extra/config/conf -o extra/Configs/Config.in
++
++allnoconfig: extra/config/conf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf -n extra/Configs/Config.in
++
++defconfig: extra/config/conf
++ $(RM) -r include/bits
++ $(INSTALL) -d include/bits
++ @./extra/config/conf -d extra/Configs/Config.in
++
++clean:
++ - find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec $(RM) {} \;
++ @$(RM) -r tmp lib include/bits libc/tmp _install
++ $(RM) libc/obj.* headers
++ $(MAKE) -C test clean
++ $(MAKE) -C ldso clean
++ $(MAKE) -C libc/misc/internals clean
++ $(MAKE) -C libc/misc/wchar clean
++ $(MAKE) -C libc/unistd clean
++ $(MAKE) -C libc/sysdeps/linux/common clean
++ $(MAKE) -C extra/locale clean
++ $(MAKE) -C utils clean
++ @set -e; \
++ for i in `(cd $(TOPDIR)/libc/sysdeps/linux/common/sys; ls *.h)` ; do \
++ $(RM) include/sys/$$i; \
++ done; \
++ if [ -d libc/sysdeps/linux/$(TARGET_ARCH)/sys ] ; then \
++ for i in `(cd libc/sysdeps/linux/$(TARGET_ARCH)/sys; ls *.h)` ; do \
++ $(RM) include/sys/$$i; \
++ done; \
++ fi;
++ @$(RM) include/linux include/asm*
++ @if [ -d libc/sysdeps/linux/$(TARGET_ARCH) ]; then \
++ $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean; \
++ fi;
++
++distclean: clean
++ $(RM) .config .config.old .config.cmd
++ $(MAKE) -C extra clean
++
++dist release:
++ $(RM) -r ../uClibc-$(VERSION) ../uClibc-$(VERSION).tar.bz2
++ svn -q export . ../uClibc-$(VERSION)
++ tar cjf ../uClibc-$(VERSION).tar.bz2 -C .. uClibc-$(VERSION)
++ du -b ../uClibc-$(VERSION).tar.bz2
++
++endif # ifeq ($(strip $(HAVE_DOT_CONFIG)),y)
++
++check:
++ $(MAKE) -C test
++
++.PHONY: dummy subdirs release distclean clean config oldconfig menuconfig
+diff -Nrup a/Rules.mak b/Rules.mak
+--- a/Rules.mak 2007-02-28 16:12:06.000000000 -0500
++++ b/Rules.mak 2008-02-28 19:02:10.000000000 -0500
+@@ -234,6 +234,12 @@ ifeq ($(strip $(TARGET_ARCH)),frv)
+ UCLIBC_LDSO=ld.so.1
+ endif
+
++ifeq ($(strip $(TARGET_ARCH)),avr32)
++ CPU_CFLAGS-$(CONFIG_AP7000) += -mcpu=ap7000
++ CPU_CFLAGS-$(LINKRELAX) += -masm-addr-pseudos -Wa,--pic,--linkrelax
++ CPU_LDFLAGS-$(LINKRELAX) += --relax
++endif
++
+ # Keep the check_gcc from being needlessly executed
+ ifndef PIEFLAG
+ ifneq ($(UCLIBC_BUILD_PIE),y)
+diff -Nrup a/Rules.mak.orig b/Rules.mak.orig
+--- a/Rules.mak.orig 1969-12-31 19:00:00.000000000 -0500
++++ b/Rules.mak.orig 2008-02-28 19:02:10.000000000 -0500
+@@ -0,0 +1,361 @@
++# Rules.make for uClibc
++#
++# Copyright (C) 2000 by Lineo, inc.
++# Copyright (C) 2000-2002 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++
++#-----------------------------------------------------------
++# This file contains rules which are shared between multiple
++# Makefiles. All normal configuration options live in the
++# file named ".config". Don't mess with this file unless
++# you know what you are doing.
++
++
++#-----------------------------------------------------------
++# If you are running a cross compiler, you will want to set
++# 'CROSS' to something more interesting ... Target
++# architecture is determined by asking the CC compiler what
++# arch it compiles things for, so unless your compiler is
++# broken, you should not need to specify TARGET_ARCH.
++#
++# Most people will set this stuff on the command line, i.e.
++# make CROSS=arm-linux-
++# will build uClibc for 'arm'.
++
++ifndef CROSS
++CROSS=
++endif
++CC = $(CROSS)gcc
++AR = $(CROSS)ar
++LD = $(CROSS)ld
++NM = $(CROSS)nm
++RANLIB = $(CROSS)ranlib
++STRIPTOOL = $(CROSS)strip
++
++INSTALL = install
++LN = ln
++RM = rm -f
++
++# Select the compiler needed to build binaries for your development system
++HOSTCC = gcc
++HOSTCFLAGS = -O2 -Wall
++
++
++#---------------------------------------------------------
++# Nothing beyond this point should ever be touched by mere
++# mortals. Unless you hang out with the gods, you should
++# probably leave all this stuff alone.
++MAJOR_VERSION := 0
++MINOR_VERSION := 9
++SUBLEVEL := 28
++EXTRAVERSION := 3
++VERSION := $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).$(EXTRAVERSION)
++# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
++LC_ALL := C
++export MAJOR_VERSION MINOR_VERSION SUBLEVEL VERSION LC_ALL
++
++SHARED_FULLNAME:=libuClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so
++SHARED_MAJORNAME:=libc.so.$(MAJOR_VERSION)
++UCLIBC_LDSO:=ld-uClibc.so.$(MAJOR_VERSION)
++LIBNAME:=libc.a
++LIBC:=$(TOPDIR)libc/$(LIBNAME)
++
++# Make sure DESTDIR and PREFIX can be used to install
++# PREFIX is a uClibcism while DESTDIR is a common GNUism
++ifndef PREFIX
++PREFIX = $(DESTDIR)
++endif
++
++# Pull in the user's uClibc configuration
++ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),)
++-include $(TOPDIR).config
++endif
++
++ifndef CROSS
++CROSS=$(subst ",, $(strip $(CROSS_COMPILER_PREFIX)))
++endif
++
++# A nifty macro to make testing gcc features easier
++check_gcc=$(shell \
++ if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \
++ then echo "$(1)"; else echo "$(2)"; fi)
++check_as=$(shell \
++ if $(CC) -Wa,$(1) -Wa,-Z -c -o /dev/null -xassembler /dev/null > /dev/null 2>&1; \
++ then echo "-Wa,$(1)"; fi)
++
++# Setup some shortcuts so that silent mode is silent like it should be
++ifeq ($(subst s,,$(MAKEFLAGS)),$(MAKEFLAGS))
++export MAKE_IS_SILENT=n
++SECHO=@echo
++SHELL_SET_X=set -x
++else
++export MAKE_IS_SILENT=y
++SECHO=-@false
++SHELL_SET_X=set +x
++endif
++
++# Make certain these contain a final "/", but no "//"s.
++TARGET_ARCH:=$(shell grep -s ^TARGET_ARCH $(TOPDIR)/.config | sed -e 's/^TARGET_ARCH=//' -e 's/"//g')
++RUNTIME_PREFIX:=$(strip $(subst //,/, $(subst ,/, $(subst ",, $(strip $(RUNTIME_PREFIX))))))
++DEVEL_PREFIX:=$(strip $(subst //,/, $(subst ,/, $(subst ",, $(strip $(DEVEL_PREFIX))))))
++export RUNTIME_PREFIX DEVEL_PREFIX
++
++ARFLAGS:=cr
++
++OPTIMIZATION:=
++PICFLAG:=-fPIC
++PIEFLAG_NAME:=-fPIE
++
++# Some nice CPU specific optimizations
++ifeq ($(strip $(TARGET_ARCH)),i386)
++ OPTIMIZATION+=$(call check_gcc,-mpreferred-stack-boundary=2,)
++ OPTIMIZATION+=$(call check_gcc,-falign-jumps=0 -falign-loops=0,-malign-jumps=0 -malign-loops=0)
++ CPU_CFLAGS-$(CONFIG_386)+=-march=i386
++ CPU_CFLAGS-$(CONFIG_486)+=-march=i486
++ CPU_CFLAGS-$(CONFIG_ELAN)+=-march=i486
++ CPU_CFLAGS-$(CONFIG_586)+=-march=i586
++ CPU_CFLAGS-$(CONFIG_586MMX)+=$(call check_gcc,-march=pentium-mmx,-march=i586)
++ CPU_CFLAGS-$(CONFIG_686)+=-march=i686
++ CPU_CFLAGS-$(CONFIG_PENTIUMII)+=$(call check_gcc,-march=pentium2,-march=i686)
++ CPU_CFLAGS-$(CONFIG_PENTIUMIII)+=$(call check_gcc,-march=pentium3,-march=i686)
++ CPU_CFLAGS-$(CONFIG_PENTIUM4)+=$(call check_gcc,-march=pentium4,-march=i686)
++ CPU_CFLAGS-$(CONFIG_K6)+=$(call check_gcc,-march=k6,-march=i586)
++ CPU_CFLAGS-$(CONFIG_K7)+=$(call check_gcc,-march=athlon,-malign-functions=4 -march=i686)
++ CPU_CFLAGS-$(CONFIG_CRUSOE)+=-march=i686 -malign-functions=0 -malign-jumps=0 -malign-loops=0
++ CPU_CFLAGS-$(CONFIG_WINCHIPC6)+=$(call check_gcc,-march=winchip-c6,-march=i586)
++ CPU_CFLAGS-$(CONFIG_WINCHIP2)+=$(call check_gcc,-march=winchip2,-march=i586)
++ CPU_CFLAGS-$(CONFIG_CYRIXIII)+=$(call check_gcc,-march=c3,-march=i486) -malign-functions=0 -malign-jumps=0 -malign-loops=0
++ CPU_CFLAGS-$(CONFIG_NEHEMIAH)+=$(call check_gcc,-march=c3-2,-march=i686)
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),arm)
++ OPTIMIZATION+=-fstrict-aliasing
++ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-EL
++ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-EB
++ CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-mlittle-endian
++ CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mbig-endian
++ CPU_CFLAGS-$(CONFIG_GENERIC_ARM)+=
++ CPU_CFLAGS-$(CONFIG_ARM610)+=-mtune=arm610 -march=armv3
++ CPU_CFLAGS-$(CONFIG_ARM710)+=-mtune=arm710 -march=armv3
++ CPU_CFLAGS-$(CONFIG_ARM720T)+=-mtune=arm7tdmi -march=armv4
++ CPU_CFLAGS-$(CONFIG_ARM920T)+=-mtune=arm9tdmi -march=armv4
++ CPU_CFLAGS-$(CONFIG_ARM922T)+=-mtune=arm9tdmi -march=armv4
++ CPU_CFLAGS-$(CONFIG_ARM926T)+=-mtune=arm9tdmi -march=armv5
++ CPU_CFLAGS-$(CONFIG_ARM1136JF_S)+=-mtune=arm1136jf-s -march=armv6
++ CPU_CFLAGS-$(CONFIG_ARM_SA110)+=-mtune=strongarm110 -march=armv4
++ CPU_CFLAGS-$(CONFIG_ARM_SA1100)+=-mtune=strongarm1100 -march=armv4
++ CPU_CFLAGS-$(CONFIG_ARM_XSCALE)+=$(call check_gcc,-mtune=xscale,-mtune=strongarm110)
++ CPU_CFLAGS-$(CONFIG_ARM_XSCALE)+=-march=armv4 -Wa,-mcpu=xscale
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),mips)
++ CPU_CFLAGS-$(CONFIG_MIPS_ISA_1)+=-mips1
++ CPU_CFLAGS-$(CONFIG_MIPS_ISA_2)+=-mips2 -mtune=mips2
++ CPU_CFLAGS-$(CONFIG_MIPS_ISA_3)+=-mips3 -mtune=mips3
++ CPU_CFLAGS-$(CONFIG_MIPS_ISA_4)+=-mips4 -mtune=mips4
++ CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS32)+=-mips32 -mtune=mips32
++ CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS64)+=-mips64 -mtune=mips32
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),sh)
++ OPTIMIZATION+=-fstrict-aliasing
++ OPTIMIZATION+= $(call check_gcc,-mprefergot,)
++ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-EL
++ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-EB
++ CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-ml
++ CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mb
++ CPU_CFLAGS-$(CONFIG_SH2)+=-m2
++ CPU_CFLAGS-$(CONFIG_SH3)+=-m3
++ifeq ($(strip $(UCLIBC_HAS_FLOATS)),y)
++ CPU_CFLAGS-$(CONFIG_SH2A)+=-m2a
++ CPU_CFLAGS-$(CONFIG_SH4)+=-m4
++else
++ CPU_CFLAGS-$(CONFIG_SH2A)+=-m2a-nofpu
++ CPU_CFLAGS-$(CONFIG_SH4)+=-m4-nofpu
++endif
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),sh64)
++ OPTIMIZATION+=-fstrict-aliasing
++ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN):=-EL
++ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN):=-EB
++ CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN):=-ml
++ CPU_CFLAGS-$(ARCH_BIG_ENDIAN):=-mb
++ CPU_CFLAGS-$(CONFIG_SH5)+=-m5-32media
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),h8300)
++ CPU_LDFLAGS-$(CONFIG_H8300H)+= -ms8300h
++ CPU_LDFLAGS-$(CONFIG_H8S) += -ms8300s
++ CPU_CFLAGS-$(CONFIG_H8300H) += -mh -mint32 -fsigned-char
++ CPU_CFLAGS-$(CONFIG_H8S) += -ms -mint32 -fsigned-char
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),cris)
++ CPU_LDFLAGS-$(CONFIG_CRIS)+=-mcrislinux
++ CPU_CFLAGS-$(CONFIG_CRIS)+=-mlinux
++ PICFLAG:=-fpic
++ PIEFLAG_NAME:=-fpie
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),powerpc)
++# PowerPC can hold 8192 entries in its GOT with -fpic which is more than
++# enough. Therefore use -fpic which will reduce code size and generates
++# faster code.
++ PICFLAG:=-fpic
++ PIEFLAG_NAME:=-fpie
++ PPC_HAS_REL16:=$(shell echo -e "\t.text\n\taddis 11,30,_GLOBAL_OFFSET_TABLE_-.@ha" | $(CC) -c -x assembler -o /dev/null - 2> /dev/null && echo -n y || echo -n n)
++ CPU_CFLAGS-$(PPC_HAS_REL16)+= -DHAVE_ASM_PPC_REL16
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),frv)
++ CPU_LDFLAGS-$(CONFIG_FRV)+=-melf32frvfd
++ CPU_CFLAGS-$(CONFIG_FRV)+=-mfdpic
++ # Using -pie causes the program to have an interpreter, which is
++ # forbidden, so we must make do with -shared. Unfortunately,
++ # -shared by itself would get us global function descriptors
++ # and calls through PLTs, dynamic resolution of symbols, etc,
++ # which would break as well, but -Bsymbolic comes to the rescue.
++ export LDPIEFLAG:=-shared -Bsymbolic
++ UCLIBC_LDSO=ld.so.1
++endif
++
++ifeq ($(strip $(TARGET_ARCH)),avr32)
++ CPU_CFLAGS-$(CONFIG_AP7000) += -mcpu=ap7000
++endif
++
++# Keep the check_gcc from being needlessly executed
++ifndef PIEFLAG
++ifneq ($(UCLIBC_BUILD_PIE),y)
++export PIEFLAG:=
++else
++export PIEFLAG:=$(call check_gcc,$(PIEFLAG_NAME),$(PICFLAG))
++endif
++endif
++# We need to keep track of both the CC PIE flag (above) as
++# well as the LD PIE flag (below) because we can't rely on
++# gcc passing -pie if we used -fPIE
++ifndef LDPIEFLAG
++ifneq ($(UCLIBC_BUILD_PIE),y)
++export LDPIEFLAG:=
++else
++export LDPIEFLAG:=$(shell $(LD) --help | grep -q pie && echo "-Wl,-pie")
++endif
++endif
++
++# Use '-Os' optimization if available, else use -O2, allow Config to override
++OPTIMIZATION+=$(call check_gcc,-Os,-O2)
++# Use the gcc 3.4 -funit-at-a-time optimization when available
++OPTIMIZATION+=$(call check_gcc,-funit-at-a-time,)
++
++# Add a bunch of extra pedantic annoyingly strict checks
++XWARNINGS=$(subst ",, $(strip $(WARNINGS))) -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing
++XARCH_CFLAGS=$(subst ",, $(strip $(ARCH_CFLAGS)))
++CPU_CFLAGS=$(subst ",, $(strip $(CPU_CFLAGS-y)))
++
++LDADD_LIBFLOAT=
++ifeq ($(strip $(UCLIBC_HAS_SOFT_FLOAT)),y)
++# Add -msoft-float to the CPU_FLAGS since ldso and libdl ignore CFLAGS.
++# If -msoft-float isn't supported, we want an error anyway.
++# Hmm... might need to revisit this for arm since it has 2 different
++# soft float encodings.
++ CPU_CFLAGS += -msoft-float
++ifeq ($(strip $(TARGET_ARCH)),arm)
++# No longer needed with current toolchains, but leave it here for now.
++# If anyone is actually still using gcc 2.95 (say), they can uncomment it.
++# LDADD_LIBFLOAT=-lfloat
++endif
++endif
++
++SSP_DISABLE_FLAGS:=$(call check_gcc,-fno-stack-protector,)
++ifeq ($(UCLIBC_BUILD_SSP),y)
++SSP_CFLAGS:=$(call check_gcc,-fno-stack-protector-all,)
++SSP_CFLAGS+=$(call check_gcc,-fstack-protector,)
++SSP_ALL_CFLAGS:=$(call check_gcc,-fstack-protector-all,)
++else
++SSP_CFLAGS:=$(SSP_DISABLE_FLAGS)
++endif
++
++# Some nice CFLAGS to work with
++CFLAGS:=$(XWARNINGS) $(CPU_CFLAGS) $(SSP_CFLAGS) \
++ -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)include -I.
++LDFLAGS_NOSTRIP:=$(CPU_LDFLAGS-y) -shared --warn-common --warn-once -z combreloc -z defs
++
++ifeq ($(DODEBUG),y)
++ #CFLAGS += -g3
++ CFLAGS += -O0 -g3
++ LDFLAGS := $(LDFLAGS_NOSTRIP)
++ STRIPTOOL:= true -Since_we_are_debugging
++else
++ CFLAGS += $(OPTIMIZATION) $(XARCH_CFLAGS)
++ LDFLAGS := $(LDFLAGS_NOSTRIP) -s
++endif
++
++ifeq ($(UCLIBC_BUILD_RELRO),y)
++LDFLAGS+=-z relro
++endif
++
++ifeq ($(UCLIBC_BUILD_NOW),y)
++LDFLAGS+=-z now
++endif
++
++# Sigh, some stupid versions of gcc can't seem to cope with '-iwithprefix include'
++#CFLAGS+=-iwithprefix include
++CFLAGS+=-isystem $(shell $(CC) -print-file-name=include)
++
++ifneq ($(DOASSERTS),y)
++ CFLAGS += -DNDEBUG
++endif
++
++CFLAGS_NOPIC:=$(CFLAGS)
++ifeq ($(DOPIC),y)
++ CFLAGS += $(PICFLAG)
++endif
++
++ifeq ($(DL_FINI_CRT_COMPAT),y)
++CFLAGS += -D_DL_FINI_CRT_COMPAT
++endif
++
++# Keep the check_as from being needlessly executed
++ASFLAGS = $(CFLAGS)
++ifndef ASFLAGS_NOEXEC
++ifeq ($(UCLIBC_BUILD_NOEXECSTACK),y)
++export ASFLAGS_NOEXEC := $(call check_as,--noexecstack)
++else
++export ASFLAGS_NOEXEC :=
++endif
++endif
++ASFLAGS += $(ASFLAGS_NOEXEC)
++
++LIBGCC_CFLAGS ?= $(CFLAGS) $(CPU_CFLAGS-y)
++LIBGCC:=$(shell $(CC) $(LIBGCC_CFLAGS) -print-libgcc-file-name)
++LIBGCC_DIR:=$(dir $(LIBGCC))
++
++########################################
++#
++# uClinux shared lib support
++#
++
++ifeq ($(CONFIG_BINFMT_SHARED_FLAT),y)
++ # For the shared version of this, we specify no stack and its library ID
++ FLTFLAGS += -s 0
++ LIBID=1
++ export LIBID FLTFLAGS
++ SHARED_TARGET = lib/libc
++endif
++
++TARGET_ARCH:=$(strip $(subst ",, $(strip $(TARGET_ARCH))))
+diff -Nrup a/utils/ldd.c b/utils/ldd.c
+--- a/utils/ldd.c 2004-10-06 03:34:17.000000000 -0400
++++ b/utils/ldd.c 2008-02-28 19:02:10.000000000 -0500
+@@ -56,6 +56,11 @@
+ #define ELFCLASSM ELFCLASS32
+ #endif
+
++#if defined(__avr32__)
++#define MATCH_MACHINE(x) (x == EM_AVR32)
++#define ELFCLASSM ELFCLASS32
++#endif
++
+ #if defined(__s390__)
+ #define MATCH_MACHINE(x) (x == EM_S390)
+ #define ELFCLASSM ELFCLASS32
--- /dev/null
+diff --git a/Rules.mak b/Rules.mak
+index d054bbb..55381cf 100644
+--- a/Rules.mak
++++ b/Rules.mak
+@@ -313,6 +313,12 @@ ifeq ($(TARGET_ARCH),frv)
+ UCLIBC_LDSO=ld.so.1
+ endif
+
++ifeq ($(strip $(TARGET_ARCH)),avr32)
++ CPU_CFLAGS-$(CONFIG_AVR32_AP7) += -march=ap
++ CPU_CFLAGS-$(CONFIG_LINKRELAX) += -mrelax
++ CPU_LDFLAGS-$(CONFIG_LINKRELAX) += --relax
++endif
++
+ # Keep the check_gcc from being needlessly executed
+ ifndef PIEFLAG
+ ifneq ($(UCLIBC_BUILD_PIE),y)
+diff --git a/extra/Configs/Config.avr32 b/extra/Configs/Config.avr32
+new file mode 100644
+index 0000000..8d70e6e
+--- /dev/null
++++ b/extra/Configs/Config.avr32
+@@ -0,0 +1,31 @@
++#
++# For a description of the syntax of this configuration file,
++# see extra/config/Kconfig-language.txt
++#
++
++config TARGET_ARCH
++ string
++ default "avr32"
++
++config FORCE_OPTIONS_FOR_ARCH
++ bool
++ default y
++ select ARCH_BIG_ENDIAN
++ select FORCE_SHAREABLE_TEXT_SEGMENTS
++
++config ARCH_CFLAGS
++ string
++
++choice
++ prompt "Target CPU Type"
++ default CONFIG_AVR32_AP7
++
++config CONFIG_AVR32_AP7
++ bool "AVR32 AP7"
++ select ARCH_HAS_MMU
++
++endchoice
++
++config LINKRELAX
++ bool "Enable linker optimizations"
++ default y
+diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
+index 8eab394..10c9f7b 100644
+--- a/extra/Configs/Config.in
++++ b/extra/Configs/Config.in
+@@ -16,6 +16,9 @@ config TARGET_alpha
+ config TARGET_arm
+ bool "arm"
+
++config TARGET_avr32
++ bool "avr32"
++
+ config TARGET_bfin
+ bool "bfin"
+
+@@ -92,6 +95,10 @@ if TARGET_arm
+ source "extra/Configs/Config.arm"
+ endif
+
++if TARGET_avr32
++source "extra/Configs/Config.avr32"
++endif
++
+ if TARGET_bfin
+ source "extra/Configs/Config.bfin"
+ endif
+diff --git a/extra/Configs/defconfigs/avr32 b/extra/Configs/defconfigs/avr32
+new file mode 100644
+index 0000000..0b890a2
+--- /dev/null
++++ b/extra/Configs/defconfigs/avr32
+@@ -0,0 +1 @@
++TARGET_avr32=y
+diff --git a/include/elf.h b/include/elf.h
+index 19805d7..ab90160 100644
+--- a/include/elf.h
++++ b/include/elf.h
+@@ -354,6 +354,8 @@ typedef struct
+ /* NIOS magic number - no EABI available. */
+ #define EM_NIOS32 0xFEBB
+
++#define EM_AVR32 0x18ad
++
+ /* V850 backend magic number. Written in the absense of an ABI. */
+ #define EM_CYGNUS_V850 0x9080
+
+@@ -2828,6 +2830,55 @@ typedef Elf32_Addr Elf32_Conflict;
+ /* Keep this the last entry. */
+ #define R_V850_NUM 25
+
++/* Atmel AVR32 relocations. */
++#define R_AVR32_NONE 0
++#define R_AVR32_32 1
++#define R_AVR32_16 2
++#define R_AVR32_8 3
++#define R_AVR32_32_PCREL 4
++#define R_AVR32_16_PCREL 5
++#define R_AVR32_8_PCREL 6
++#define R_AVR32_DIFF32 7
++#define R_AVR32_DIFF16 8
++#define R_AVR32_DIFF8 9
++#define R_AVR32_GOT32 10
++#define R_AVR32_GOT16 11
++#define R_AVR32_GOT8 12
++#define R_AVR32_21S 13
++#define R_AVR32_16U 14
++#define R_AVR32_16S 15
++#define R_AVR32_8S 16
++#define R_AVR32_8S_EXT 17
++#define R_AVR32_22H_PCREL 18
++#define R_AVR32_18W_PCREL 19
++#define R_AVR32_16B_PCREL 20
++#define R_AVR32_16N_PCREL 21
++#define R_AVR32_14UW_PCREL 22
++#define R_AVR32_11H_PCREL 23
++#define R_AVR32_10UW_PCREL 24
++#define R_AVR32_9H_PCREL 25
++#define R_AVR32_9UW_PCREL 26
++#define R_AVR32_HI16 27
++#define R_AVR32_LO16 28
++#define R_AVR32_GOTPC 29
++#define R_AVR32_GOTCALL 30
++#define R_AVR32_LDA_GOT 31
++#define R_AVR32_GOT21S 32
++#define R_AVR32_GOT18SW 33
++#define R_AVR32_GOT16S 34
++#define R_AVR32_GOT7UW 35
++#define R_AVR32_32_CPENT 36
++#define R_AVR32_CPCALL 37
++#define R_AVR32_16_CP 38
++#define R_AVR32_9W_CP 39
++#define R_AVR32_RELATIVE 40
++#define R_AVR32_GLOB_DAT 41
++#define R_AVR32_JMP_SLOT 42
++#define R_AVR32_ALIGN 43
++#define R_AVR32_NUM 44
++
++/* AVR32 dynamic tags */
++#define DT_AVR32_GOTSZ 0x70000001 /* Total size of GOT in bytes */
+
+ /* Renesas H8/300 Relocations */
+ #define R_H8_NONE 0
+diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h
+index 32c5bf8..eb43bd9 100644
+--- a/ldso/include/dl-string.h
++++ b/ldso/include/dl-string.h
+@@ -285,7 +285,8 @@ static __always_inline char * _dl_simple_ltoahex(char * local, unsigned long i)
+ /* 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(__mips__) || defined(__sh__) || defined(__powerpc__) || \
++ defined(__avr32__)
+ # define CONSTANT_STRING_GOT_FIXUP(X) \
+ if ((X) < (const char *) load_addr) (X) += load_addr
+ # define NO_EARLY_SEND_STDERR
+diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
+index b42416a..4404219 100644
+--- a/ldso/include/dl-syscall.h
++++ b/ldso/include/dl-syscall.h
+@@ -55,69 +55,69 @@
+ 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 inline _syscall1(void, _dl_exit, int, status);
++static __always_inline _syscall1(void, _dl_exit, int, status);
+
+ #define __NR__dl_close __NR_close
+-static inline _syscall1(int, _dl_close, int, fd);
++static __always_inline _syscall1(int, _dl_close, int, fd);
+
+ #define __NR__dl_open __NR_open
+-static inline _syscall3(int, _dl_open, const char *, fn, int, flags,
++static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags,
+ __kernel_mode_t, mode);
+
+ #define __NR__dl_write __NR_write
+-static inline _syscall3(unsigned long, _dl_write, int, fd,
++static __always_inline _syscall3(unsigned long, _dl_write, int, fd,
+ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_read __NR_read
+-static inline _syscall3(unsigned long, _dl_read, int, fd,
++static __always_inline _syscall3(unsigned long, _dl_read, int, fd,
+ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_mprotect __NR_mprotect
+-static inline _syscall3(int, _dl_mprotect, const void *, addr,
++static __always_inline _syscall3(int, _dl_mprotect, const void *, addr,
+ unsigned long, len, int, prot);
+
+ #define __NR__dl_stat __NR_stat
+-static inline _syscall2(int, _dl_stat, const char *, file_name,
++static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
+ struct stat *, buf);
+
+ #define __NR__dl_fstat __NR_fstat
+-static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
++static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
+
+ #define __NR__dl_munmap __NR_munmap
+-static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
++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 inline _syscall0(uid_t, _dl_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 inline _syscall0(uid_t, _dl_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 inline _syscall0(gid_t, _dl_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 inline _syscall0(gid_t, _dl_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 inline _syscall0(gid_t, _dl_getpid);
++static __always_inline _syscall0(gid_t, _dl_getpid);
+
+ #define __NR__dl_readlink __NR_readlink
+-static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
++static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
+ size_t, bufsiz);
+
+ #ifdef __UCLIBC_HAS_SSP__
+@@ -146,14 +146,14 @@ static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
+ #if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
+
+ # define __NR__dl_mmap __NR_mmap
+-static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
++static __always_inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
+ int, prot, int, flags, int, fd, off_t, offset);
+
+ /* then try mmap2() */
+ #elif defined(__NR_mmap2)
+
+ # define __NR___syscall_mmap2 __NR_mmap2
+-static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
++static __always_inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
+ int, prot, int, flags, int, fd, off_t, offset);
+
+ /* Some architectures always use 12 as page shift for mmap2() eventhough the
+@@ -164,7 +164,7 @@ static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
+ # define MMAP2_PAGE_SHIFT 12
+ #endif
+
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
+@@ -177,8 +177,8 @@ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ #elif defined(__NR_mmap)
+
+ # define __NR__dl_mmap_real __NR_mmap
+-static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++static __always_inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+ int flags, int fd, unsigned long offset)
+ {
+ unsigned long buffer[6];
+diff --git a/ldso/ldso/avr32/dl-debug.h b/ldso/ldso/avr32/dl-debug.h
+new file mode 100644
+index 0000000..fe35539
+--- /dev/null
++++ b/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 *_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/ldso/ldso/avr32/dl-startup.h b/ldso/ldso/avr32/dl-startup.h
+new file mode 100644
+index 0000000..3b9a641
+--- /dev/null
++++ b/ldso/ldso/avr32/dl-startup.h
+@@ -0,0 +1,112 @@
++/*
++ * 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 if 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(ELF32_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(ELF32_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);
++ }
++}
++
++/* Transfer control to the user's application, once the dynamic loader
++ * is done. This routine has to exit the current function, then call
++ * the _dl_elf_main function.
++ *
++ * Since our _dl_boot will simply call whatever is returned by
++ * _dl_boot2, we can just return the address we're supposed to
++ * call. */
++#define START() return _dl_elf_main;
+diff --git a/ldso/ldso/avr32/dl-syscalls.h b/ldso/ldso/avr32/dl-syscalls.h
+new file mode 100644
+index 0000000..996bb87
+--- /dev/null
++++ b/ldso/ldso/avr32/dl-syscalls.h
+@@ -0,0 +1,6 @@
++/* 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);}
+diff --git a/ldso/ldso/avr32/dl-sysdep.h b/ldso/ldso/avr32/dl-sysdep.h
+new file mode 100644
+index 0000000..1a30172
+--- /dev/null
++++ b/ldso/ldso/avr32/dl-sysdep.h
+@@ -0,0 +1,105 @@
++/*
++ * 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"
++
++unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
++
++/* 4096 bytes alignment */
++#define PAGE_ALIGN 0xfffff000
++#define ADDR_ALIGN 0xfff
++#define OFFS_ALIGN 0x7ffff000
++
++#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 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 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 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/ldso/ldso/avr32/elfinterp.c b/ldso/ldso/avr32/elfinterp.c
+new file mode 100644
+index 0000000..196292b
+--- /dev/null
++++ b/ldso/ldso/avr32/elfinterp.c
+@@ -0,0 +1,191 @@
++/*
++ * 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)
++{
++ struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
++ Elf32_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;
++
++#if 0
++ local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
++ gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
++
++ sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
++ + sym_index;
++ strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
++ symname = strtab + sym->st_name;
++
++#if 0
++ new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
++ tpnt->symbol_scope, tpnt,
++ resolver);
++#endif
++
++ entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
++ *entry = 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_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
++{
++ Elf32_Sym *symtab;
++ Elf32_Rela *rpnt;
++ char *strtab;
++ int i;
++
++ rpnt = (Elf32_Rela *)rel_addr;
++ rel_size /= sizeof(Elf32_Rela);
++ symtab = (Elf32_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 = ELF32_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 = ELF32_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 dyn_elf *scope,
++ Elf32_Rela *rpnt, Elf32_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
++
++ reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
++ reloc_type = ELF32_R_TYPE(rpnt->r_info);
++ symtab_index = ELF32_R_SYM(rpnt->r_info);
++ symbol_addr = 0;
++ symname = strtab + symtab[symtab_index].st_name;
++
++ if (symtab_index) {
++ symbol_addr = (unsigned long)
++ _dl_find_hash(strtab + symtab[symtab_index].st_name,
++ tpnt->symbol_scope, tpnt,
++ elf_machine_type_class(reloc_type));
++
++ /* Allow undefined references to weak symbols */
++ if (!symbol_addr &&
++ ELF32_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 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,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
++ _dl_do_reloc);
++}
+diff --git a/ldso/ldso/avr32/resolve.S b/ldso/ldso/avr32/resolve.S
+new file mode 100644
+index 0000000..e3cb7f4
+--- /dev/null
++++ b/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/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
+index 5cf1d04..d4294ec 100644
+--- a/ldso/ldso/dl-startup.c
++++ b/ldso/ldso/dl-startup.c
+@@ -217,7 +217,9 @@ DL_START(unsigned long args)
+ /* some arches (like MIPS) we have to tweak the GOT before relocations */
+ PERFORM_BOOTSTRAP_GOT(tpnt);
+
+-#else
++#endif
++
++#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__)
+
+ /* OK, now do the relocations. We do not do a lazy binding here, so
+ that once we are done, we have considerably more flexibility. */
+diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
+index f4e6cac..9cdc3fe 100644
+--- a/libc/inet/resolv.c
++++ b/libc/inet/resolv.c
+@@ -1643,7 +1643,7 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,
+ *result=result_buf;
+ ret=NETDB_SUCCESS;
+ #ifdef __UCLIBC_HAS_IPV6__
+- } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) {
++ } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) {
+ DPRINTF("Found INET6\n");
+ addr_list6[0] = in6;
+ addr_list6[1] = 0;
+@@ -1658,8 +1658,8 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,
+ } else {
+ DPRINTF("Error\n");
+ ret=TRY_AGAIN;
+- break; /* bad ip address */
+- }
++ continue; /* bad ip address, keep searching */
++ }
+
+ if (action!=GETHOSTENT) {
+ fclose(fp);
+diff --git a/libc/string/avr32/Makefile b/libc/string/avr32/Makefile
+new file mode 100644
+index 0000000..e19e9d9
+--- /dev/null
++++ b/libc/string/avr32/Makefile
+@@ -0,0 +1,26 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++top_srcdir := ../../../
++top_builddir := ../../../
++
++all: objs
++
++include $(top_builddir)Rules.mak
++include ../Makefile.in
++include $(top_srcdir)Makerules
+diff --git a/libc/string/avr32/bcopy.S b/libc/string/avr32/bcopy.S
+new file mode 100644
+index 0000000..87c1e04
+--- /dev/null
++++ b/libc/string/avr32/bcopy.S
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#include <features.h>
++
++#ifdef __UCLIBC_SUSV3_LEGACY__
++
++ .text
++ .global bcopy
++ .type bcopy, @function
++ .align 1
++bcopy:
++ /* Swap the first two arguments */
++ eor r11, r12
++ eor r12, r11
++ eor r11, r12
++ rjmp __GI_memmove
++
++ .size bcopy, . - bcopy
++
++#endif /* __UCLIBC_SUSV3_LEGACY__ */
+diff --git a/libc/string/avr32/bzero.S b/libc/string/avr32/bzero.S
+new file mode 100644
+index 0000000..c999e65
+--- /dev/null
++++ b/libc/string/avr32/bzero.S
+@@ -0,0 +1,22 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#ifdef __UCLIBC_SUSV3_LEGACY__
++
++ .text
++ .global bzero
++ .type bzero, @function
++ .align 1
++bzero:
++ mov r10, r11
++ mov r11, 0
++ rjmp __memset
++
++ .size bzero, . - bzero
++
++#endif /* __UCLIBC_SUSV3_LEGACY__ */
+diff --git a/libc/string/avr32/memcmp.S b/libc/string/avr32/memcmp.S
+new file mode 100644
+index 0000000..ae6cc91
+--- /dev/null
++++ b/libc/string/avr32/memcmp.S
+@@ -0,0 +1,61 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#include <features.h>
++
++#define s1 r12
++#define s2 r11
++#define len r10
++
++ .text
++ .global memcmp
++ .type memcmp, @function
++ .align 1
++memcmp:
++ sub len, 4
++ brlt .Lless_than_4
++
++1: ld.w r8, s1++
++ ld.w r9, s2++
++ cp.w r8, r9
++ brne .Lfound_word
++ sub len, 4
++ brge 1b
++
++.Lless_than_4:
++ sub len, -4
++ reteq 0
++
++1: ld.ub r8, s1++
++ ld.ub r9, s2++
++ sub r8, r9
++ retne r8
++ sub len, 1
++ brgt 1b
++
++ retal 0
++
++.Lfound_word:
++ mov len, 4
++
++2: bfextu r11, r9, 24, 8
++ bfextu r12, r8, 24, 8
++ sub r12, r11
++ retne r12
++ lsl r8, 8
++ lsl r9, 8
++ sub len, 1
++ brne 2b
++ retal r12
++
++ .size memcmp, . - memcmp
++
++libc_hidden_def(memcmp)
++#ifdef __UCLIBC_SUSV3_LEGACY__
++strong_alias(memcmp,bcmp)
++#endif
+diff --git a/libc/string/avr32/memcpy.S b/libc/string/avr32/memcpy.S
+new file mode 100644
+index 0000000..bf091ab
+--- /dev/null
++++ b/libc/string/avr32/memcpy.S
+@@ -0,0 +1,111 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++/* Don't use r12 as dst since we must return it unmodified */
++#define dst r9
++#define src r11
++#define len r10
++
++ .text
++ .global memcpy
++ .type memcpy, @function
++memcpy:
++ pref src[0]
++ mov dst, r12
++
++ /* If we have less than 32 bytes, don't do anything fancy */
++ cp.w len, 32
++ brge .Lmore_than_31
++
++ sub len, 1
++ retlt r12
++1: ld.ub r8, src++
++ st.b dst++, r8
++ sub len, 1
++ brge 1b
++ retal r12
++
++.Lmore_than_31:
++ pushm r0-r7, lr
++
++ /* Check alignment */
++ mov r8, src
++ andl r8, 31, COH
++ brne .Lunaligned_src
++ mov r8, dst
++ andl r8, 3, COH
++ brne .Lunaligned_dst
++
++.Laligned_copy:
++ sub len, 32
++ brlt .Lless_than_32
++
++1: /* Copy 32 bytes at a time */
++ ldm src, r0-r7
++ sub src, -32
++ stm dst, r0-r7
++ sub dst, -32
++ sub len, 32
++ brge 1b
++
++.Lless_than_32:
++ /* Copy 16 more bytes if possible */
++ sub len, -16
++ brlt .Lless_than_16
++ ldm src, r0-r3
++ sub src, -16
++ sub len, 16
++ stm dst, r0-r3
++ sub dst, -16
++
++.Lless_than_16:
++ /* Do the remaining as byte copies */
++ neg len
++ add pc, pc, len << 2
++ .rept 15
++ ld.ub r0, src++
++ st.b dst++, r0
++ .endr
++
++ popm r0-r7, pc
++
++.Lunaligned_src:
++ /* Make src cacheline-aligned. r8 = (src & 31) */
++ rsub r8, r8, 32
++ sub len, r8
++1: ld.ub r0, src++
++ st.b dst++, r0
++ sub r8, 1
++ brne 1b
++
++ /* If dst is word-aligned, we're ready to go */
++ pref src[0]
++ mov r8, 3
++ tst dst, r8
++ breq .Laligned_copy
++
++.Lunaligned_dst:
++ /* src is aligned, but dst is not. Expect bad performance */
++ sub len, 4
++ brlt 2f
++1: ld.w r0, src++
++ st.w dst++, r0
++ sub len, 4
++ brge 1b
++
++2: neg len
++ add pc, pc, len << 2
++ .rept 3
++ ld.ub r0, src++
++ st.b dst++, r0
++ .endr
++
++ popm r0-r7, pc
++ .size memcpy, . - memcpy
++
++libc_hidden_def(memcpy)
+diff --git a/libc/string/avr32/memmove.S b/libc/string/avr32/memmove.S
+new file mode 100644
+index 0000000..98287c5
+--- /dev/null
++++ b/libc/string/avr32/memmove.S
+@@ -0,0 +1,116 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#define dst r12
++#define src r11
++#define len r10
++
++ .text
++ .global memmove
++ .type memmove, @function
++memmove:
++ cp.w src, dst
++ brge __GI_memcpy
++
++ add dst, len
++ add src, len
++ pref src[-1]
++
++ /*
++ * The rest is basically the same as in memcpy.S except that
++ * the direction is reversed.
++ */
++ cp.w len, 32
++ brge .Lmore_than_31
++
++ sub len, 1
++ retlt r12
++1: ld.ub r8, --src
++ st.b --dst, r8
++ sub len, 1
++ brge 1b
++ retal r12
++
++.Lmore_than_31:
++ pushm r0-r7, lr
++
++ /* Check alignment */
++ mov r8, src
++ andl r8, 31, COH
++ brne .Lunaligned_src
++ mov r8, r12
++ andl r8, 3, COH
++ brne .Lunaligned_dst
++
++.Laligned_copy:
++ sub len, 32
++ brlt .Lless_than_32
++
++1: /* Copy 32 bytes at a time */
++ sub src, 32
++ ldm src, r0-r7
++ sub dst, 32
++ sub len, 32
++ stm dst, r0-r7
++ brge 1b
++
++.Lless_than_32:
++ /* Copy 16 more bytes if possible */
++ sub len, -16
++ brlt .Lless_than_16
++ sub src, 16
++ ldm src, r0-r3
++ sub dst, 16
++ sub len, 16
++ stm dst, r0-r3
++
++.Lless_than_16:
++ /* Do the remaining as byte copies */
++ sub len, -16
++ breq 2f
++1: ld.ub r0, --src
++ st.b --dst, r0
++ sub len, 1
++ brne 1b
++
++2: popm r0-r7, pc
++
++.Lunaligned_src:
++ /* Make src cacheline-aligned. r8 = (src & 31) */
++ sub len, r8
++1: ld.ub r0, --src
++ st.b --dst, r0
++ sub r8, 1
++ brne 1b
++
++ /* If dst is word-aligned, we're ready to go */
++ pref src[-4]
++ mov r8, 3
++ tst dst, r8
++ breq .Laligned_copy
++
++.Lunaligned_dst:
++ /* src is aligned, but dst is not. Expect bad performance */
++ sub len, 4
++ brlt 2f
++1: ld.w r0, --src
++ st.w --dst, r0
++ sub len, 4
++ brge 1b
++
++2: neg len
++ add pc, pc, len << 2
++ .rept 3
++ ld.ub r0, --src
++ st.b --dst, r0
++ .endr
++
++ popm r0-r7, pc
++ .size memmove, . - memmove
++
++libc_hidden_def(memmove)
+diff --git a/libc/string/avr32/memset.S b/libc/string/avr32/memset.S
+new file mode 100644
+index 0000000..33cfaed
+--- /dev/null
++++ b/libc/string/avr32/memset.S
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#include <features.h>
++
++#define s r12
++#define c r11
++#define n r10
++
++ .text
++ .global memset
++ .type memset, @function
++
++ .global __memset
++ .hidden __memset
++ .type __memset, @function
++
++ .align 1
++memset:
++__memset:
++ cp.w n, 32
++ mov r9, s
++ brge .Llarge_memset
++
++ sub n, 1
++ retlt s
++1: st.b s++, c
++ sub n, 1
++ brge 1b
++
++ retal r9
++
++.Llarge_memset:
++ mov r8, r11
++ mov r11, 3
++ bfins r8, r8, 8, 8
++ bfins r8, r8, 16, 16
++ tst s, r11
++ breq 2f
++
++1: st.b s++, r8
++ sub n, 1
++ tst s, r11
++ brne 1b
++
++2: mov r11, r9
++ mov r9, r8
++ sub n, 8
++
++3: st.d s++, r8
++ sub n, 8
++ brge 3b
++
++ /* If we are done, n == -8 and we'll skip all st.b insns below */
++ neg n
++ lsl n, 1
++ add pc, n
++ .rept 7
++ st.b s++, r8
++ .endr
++ retal r11
++
++ .size memset, . - memset
++
++libc_hidden_def(memset)
+diff --git a/libc/string/avr32/strcmp.S b/libc/string/avr32/strcmp.S
+new file mode 100644
+index 0000000..f73bd43
+--- /dev/null
++++ b/libc/string/avr32/strcmp.S
+@@ -0,0 +1,91 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#include <features.h>
++
++#define s1 r12
++#define s2 r11
++#define len r10
++
++ .text
++ .global strcmp
++ .type strcmp, @function
++ .align 1
++strcmp:
++ mov r8, 3
++ tst s1, r8
++ brne .Lunaligned_s1
++ tst s2, r8
++ brne .Lunaligned_s2
++
++1: ld.w r8, s1++
++ ld.w r9, s2++
++ cp.w r8, r9
++ brne 2f
++ tnbz r8
++ brne 1b
++ retal 0
++
++2: bfextu r12, r8, 24, 8
++ bfextu r11, r9, 24, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 16, 8
++ bfextu r11, r9, 16, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 8, 8
++ bfextu r11, r9, 8, 8
++ sub r12, r11
++ retne r12
++ cp.w r11, 0
++ reteq 0
++ bfextu r12, r8, 0, 8
++ bfextu r11, r9, 0, 8
++ sub r12, r11
++ retal r12
++
++.Lunaligned_s1:
++3: tst s1, r8
++ breq 4f
++ ld.ub r10, s1++
++ ld.ub r9, s2++
++ sub r10, r9
++ retne r10
++ cp.w r9, 0
++ brne 3b
++ retal r10
++
++4: tst s2, r8
++ breq 1b
++
++.Lunaligned_s2:
++ /*
++ * s1 and s2 can't both be aligned, and unaligned word loads
++ * can trigger spurious exceptions if we cross a page boundary.
++ * Do it the slow way...
++ */
++1: ld.ub r8, s1++
++ ld.ub r9, s2++
++ sub r8, r9
++ retne r8
++ cp.w r9, 0
++ brne 1b
++ retal 0
++
++ .size strcmp, . - strcmp
++
++libc_hidden_def(strcmp)
++#ifndef __UCLIBC_HAS_LOCALE__
++strong_alias(strcmp, strcoll)
++libc_hidden_def(strcoll)
++#endif
+diff --git a/libc/string/avr32/strlen.S b/libc/string/avr32/strlen.S
+new file mode 100644
+index 0000000..5223e53
+--- /dev/null
++++ b/libc/string/avr32/strlen.S
+@@ -0,0 +1,62 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#include <features.h>
++
++#define str r12
++
++ .text
++ .global strlen
++ .type strlen, @function
++strlen:
++ mov r11, r12
++
++ mov r9, str
++ andl r9, 3, COH
++ brne .Lunaligned_str
++
++1: ld.w r8, str++
++ tnbz r8
++ brne 1b
++
++ sub r12, r11
++ bfextu r9, r8, 24, 8
++ cp.w r9, 0
++ subeq r12, 4
++ reteq r12
++ bfextu r9, r8, 16, 8
++ cp.w r9, 0
++ subeq r12, 3
++ reteq r12
++ bfextu r9, r8, 8, 8
++ cp.w r9, 0
++ subeq r12, 2
++ reteq r12
++ sub r12, 1
++ retal r12
++
++.Lunaligned_str:
++ add pc, pc, r9 << 3
++ sub r0, r0, 0 /* 4-byte nop */
++ ld.ub r8, str++
++ sub r8, r8, 0
++ breq 1f
++ ld.ub r8, str++
++ sub r8, r8, 0
++ breq 1f
++ ld.ub r8, str++
++ sub r8, r8, 0
++ brne 1b
++
++1: sub r12, 1
++ sub r12, r11
++ retal r12
++
++ .size strlen, . - strlen
++
++libc_hidden_def(strlen)
+diff --git a/libc/sysdeps/linux/avr32/Makefile b/libc/sysdeps/linux/avr32/Makefile
+new file mode 100644
+index 0000000..338abc0
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/Makefile
+@@ -0,0 +1,25 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
++#
++# This program is free software; you can redistribute it and/or modify it under
++# the terms of the GNU Library General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or (at your option) any
++# later version.
++#
++# This program is distributed in the hope that it will be useful, but WITHOUT
++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
++# details.
++#
++# You should have received a copy of the GNU Library General Public License
++# along with this program; if not, write to the Free Software Foundation, Inc.,
++# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++top_srcdir=../../../../
++top_builddir=../../../../
++all: objs
++
++include $(top_builddir)Rules.mak
++include Makefile.arch
++include $(top_srcdir)Makerules
+diff --git a/libc/sysdeps/linux/avr32/Makefile.arch b/libc/sysdeps/linux/avr32/Makefile.arch
+new file mode 100644
+index 0000000..44fc01e
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/Makefile.arch
+@@ -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.
++#
++
++CSRC := brk.c clone.c mmap.c sigaction.c
++
++SSRC := __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \
++ sigrestorer.S syscall.S vfork.S
++
++include $(top_srcdir)/libc/sysdeps/linux/Makefile.commonarch
+diff --git a/libc/sysdeps/linux/avr32/__longjmp.S b/libc/sysdeps/linux/avr32/__longjmp.S
+new file mode 100644
+index 0000000..6154bb2
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/__longjmp.S
+@@ -0,0 +1,21 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++ .global __longjmp
++ .type __longjmp,"function"
++ .align 1
++__longjmp:
++ ldm r12++, r0-r8,sp,lr
++ mustr r8 /* restore status register (lower half) */
++ cp r11, 0 /* can't return zero */
++ frs
++ moveq r11, 1
++ retal r11
++ .size __longjmp, . - __longjmp
++
++libc_hidden_def(__longjmp)
+diff --git a/libc/sysdeps/linux/avr32/bits/atomic.h b/libc/sysdeps/linux/avr32/bits/atomic.h
+new file mode 100644
+index 0000000..e6be41f
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/atomic.h
+@@ -0,0 +1,120 @@
++/*
++ * Copyright (C) 2007 Atmel Corporation
++ *
++ * 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.
++ */
++#ifndef _AVR32_BITS_ATOMIC_H
++#define _AVR32_BITS_ATOMIC_H 1
++
++#include <inttypes.h>
++
++typedef int32_t atomic32_t;
++typedef uint32_t uatomic32_t;
++typedef int_fast32_t atomic_fast32_t;
++typedef uint_fast32_t uatomic_fast32_t;
++
++typedef intptr_t atomicptr_t;
++typedef uintptr_t uatomicptr_t;
++typedef intmax_t atomic_max_t;
++typedef uintmax_t uatomic_max_t;
++
++#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
++ (abort(), 0)
++
++#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
++ (abort(), 0)
++
++#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
++ ({ \
++ __typeof__(*(mem)) __prev; \
++ __asm__ __volatile__( \
++ "/* __arch_compare_and_exchange_val_32_acq */\n" \
++ "1: ssrf 5\n" \
++ " ld.w %[result], %[m]\n" \
++ " cp.w %[result], %[old]\n" \
++ " brne 2f\n" \
++ " stcond %[m], %[new]\n" \
++ " brne 1b\n" \
++ "2:" \
++ : [result] "=&r"(__result), [m] "=m"(*(mem)) \
++ : "m"(*(mem)), [old] "ir"(oldval), \
++ [new] "r"(newval) \
++ : "memory", "cc"); \
++ __prev; \
++ })
++
++#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
++ (abort(), 0)
++
++#define __arch_exchange_32_acq(mem, newval) \
++ ({ \
++ __typeof__(*(mem)) __oldval; \
++ __asm__ __volatile__( \
++ "/*__arch_exchange_32_acq */\n" \
++ " xchg %[old], %[m], %[new]" \
++ : [old] "=&r"(__oldval) \
++ : [m] "r"(mem), [new] "r"(newval) \
++ : "memory"); \
++ __oldval; \
++ })
++
++#define __arch_atomic_exchange_and_add_32(mem, value) \
++ ({ \
++ __typeof__(*(mem)) __oldval, __tmp; \
++ __asm__ __volatile__( \
++ "/* __arch_atomic_exchange_and_add_32 */\n" \
++ "1: ssrf 5\n" \
++ " ld.w %[old], %[m]\n" \
++ " add %[tmp], %[old], %[val]\n" \
++ " stcond %[m], %[tmp]\n" \
++ " brne 1b" \
++ : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \
++ [m] "=m"(*(mem)) \
++ : "m"(*(mem)), [val] "r"(value) \
++ : "memory", "cc"); \
++ __oldval; \
++ })
++
++#define __arch_atomic_decrement_if_positive_32(mem) \
++ ({ \
++ __typeof__(*(mem)) __oldval, __tmp; \
++ __asm__ __volatile__( \
++ "/* __arch_atomic_decrement_if_positive_32 */\n" \
++ "1: ssrf 5\n" \
++ " ld.w %[old], %[m]\n" \
++ " sub %[tmp], %[old], 1\n" \
++ " brlt 2f\n" \
++ " stcond %[m], %[tmp]\n" \
++ " brne 1b" \
++ "2:" \
++ : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \
++ [m] "=m"(*(mem)) \
++ : "m"(*(mem)) \
++ : "memory", "cc"); \
++ __oldval; \
++ })
++
++#define atomic_exchange_acq(mem, newval) \
++ ({ \
++ if (sizeof(*(mem)) != 4) \
++ abort(); \
++ __arch_exchange_32_acq(mem, newval); \
++ })
++
++#define atomic_exchange_and_add(mem, newval) \
++ ({ \
++ if (sizeof(*(mem)) != 4) \
++ abort(); \
++ __arch_atomic_exchange_and_add_32(mem, newval); \
++ })
++
++#define atomic_decrement_if_positive(mem) \
++ ({ \
++ if (sizeof(*(mem)) != 4) \
++ abort(); \
++ __arch_atomic_decrement_if_positive_32(mem); \
++ })
++
++#endif /* _AVR32_BITS_ATOMIC_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/byteswap.h b/libc/sysdeps/linux/avr32/bits/byteswap.h
+new file mode 100644
+index 0000000..1c030b9
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/byteswap.h
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (C) 2005 Atmel Corporation
++ *
++ * 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.
++ */
++
++#if !defined _BYTESWAP_H && !defined _NETINET_IN_H
++# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
++#endif
++
++#ifndef _BITS_BYTESWAP_H
++#define _BITS_BYTESWAP_H 1
++
++/* Swap bytes in 16 bit value. */
++#if defined __GNUC__
++# define __bswap_16(x) (__extension__ __builtin_bswap_16(x))
++#else
++/* This is better than nothing. */
++static __inline unsigned short int
++__bswap_16 (unsigned short int __bsx)
++{
++ return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
++}
++#endif
++
++/* Swap bytes in 32 bit value. */
++#if defined __GNUC__
++# define __bswap_32(x) (__extension__ __builtin_bswap_32(x))
++#else
++static __inline unsigned int
++__bswap_32 (unsigned int __bsx)
++{
++ return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
++ (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));
++}
++#endif
++
++#if defined __GNUC__
++/* Swap bytes in 64 bit value. */
++# define __bswap_constant_64(x) \
++ ((((x) & 0xff00000000000000ull) >> 56) \
++ | (((x) & 0x00ff000000000000ull) >> 40) \
++ | (((x) & 0x0000ff0000000000ull) >> 24) \
++ | (((x) & 0x000000ff00000000ull) >> 8) \
++ | (((x) & 0x00000000ff000000ull) << 8) \
++ | (((x) & 0x0000000000ff0000ull) << 24) \
++ | (((x) & 0x000000000000ff00ull) << 40) \
++ | (((x) & 0x00000000000000ffull) << 56))
++
++# define __bswap_64(x) \
++ (__extension__ \
++ ({ \
++ union { \
++ __extension__ unsigned long long int __ll; \
++ unsigned int __l[2]; \
++ } __w, __r; \
++ if (__builtin_constant_p(x)) \
++ __r.__ll = __bswap_constant_64(x); \
++ else { \
++ __w.__ll = (x); \
++ __r.__l[0] = __bswap_32(__w.__l[1]); \
++ __r.__l[1] = __bswap_32(__w.__l[0]); \
++ } \
++ __r.__ll; \
++ }))
++#endif
++
++#endif /* _BITS_BYTESWAP_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/endian.h b/libc/sysdeps/linux/avr32/bits/endian.h
+new file mode 100644
+index 0000000..7bb6358
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/endian.h
+@@ -0,0 +1,7 @@
++/* AVR32 is big-endian */
++
++#ifndef _ENDIAN_H
++# error "Never use <bits/endian.h> directly; include <endian.h> instead."
++#endif
++
++#define __BYTE_ORDER __BIG_ENDIAN
+diff --git a/libc/sysdeps/linux/avr32/bits/fcntl.h b/libc/sysdeps/linux/avr32/bits/fcntl.h
+new file mode 100644
+index 0000000..1abff17
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/fcntl.h
+@@ -0,0 +1,165 @@
++#ifndef _FCNTL_H
++# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
++#endif
++
++#include <sys/types.h>
++
++/*
++ * open/fcntl - O_SYNC is only implemented on blocks devices and on files
++ * located on an ext2 file system
++ */
++#define O_ACCMODE 00000003
++#define O_RDONLY 00000000
++#define O_WRONLY 00000001
++#define O_RDWR 00000002
++#define O_CREAT 00000100 /* not fcntl */
++#define O_EXCL 00000200 /* not fcntl */
++#define O_NOCTTY 00000400 /* not fcntl */
++#define O_TRUNC 00001000 /* not fcntl */
++#define O_APPEND 00002000
++#define O_NONBLOCK 00004000
++#define O_NDELAY O_NONBLOCK
++#define O_SYNC 00010000
++#define O_ASYNC 00020000
++
++#ifdef __USE_GNU
++# define O_DIRECT 00040000 /* must be a directory */
++# define O_DIRECTORY 00200000 /* direct disk access */
++# define O_NOFOLLOW 00400000 /* don't follow links */
++# define O_NOATIME 01000000 /* don't set atime */
++#endif
++
++#ifdef __USE_LARGEFILE64
++# define O_LARGEFILE 00100000
++#endif
++
++/* For now Linux has synchronisity options for data and read operations.
++ We define the symbols here but let them do the same as O_SYNC since
++ this is a superset. */
++#if defined __USE_POSIX199309 || defined __USE_UNIX98
++# define O_DSYNC O_SYNC /* Synchronize data. */
++# define O_RSYNC O_SYNC /* Synchronize read operations. */
++#endif
++
++#define F_DUPFD 0 /* dup */
++#define F_GETFD 1 /* get close_on_exec */
++#define F_SETFD 2 /* set/clear close_on_exec */
++#define F_GETFL 3 /* get file->f_flags */
++#define F_SETFL 4 /* set file->f_flags */
++
++#ifndef __USE_FILE_OFFSET64
++# define F_GETLK 5
++# define F_SETLK 6
++# define F_SETLKW 7
++#else
++# define F_GETLK F_GETLK64
++# define F_SETLK F_SETLK64
++# define F_SETLKW F_SETLKW64
++#endif
++#define F_GETLK64 12 /* using 'struct flock64' */
++#define F_SETLK64 13
++#define F_SETLKW64 14
++
++#if defined __USE_BSD || defined __USE_XOPEN2K
++# define F_SETOWN 8 /* for sockets. */
++# define F_GETOWN 9 /* for sockets. */
++#endif
++
++#ifdef __USE_GNU
++# define F_SETSIG 10 /* for sockets. */
++# define F_GETSIG 11 /* for sockets. */
++#endif
++
++#ifdef __USE_GNU
++# define F_SETLEASE 1024 /* Set a lease. */
++# define F_GETLEASE 1025 /* Enquire what lease is active. */
++# define F_NOTIFY 1026 /* Request notfications on a directory. */
++#endif
++
++/* for F_[GET|SET]FL */
++#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
++
++/* for posix fcntl() and lockf() */
++#define F_RDLCK 0
++#define F_WRLCK 1
++#define F_UNLCK 2
++
++/* for old implementation of bsd flock () */
++#define F_EXLCK 4 /* or 3 */
++#define F_SHLCK 8 /* or 4 */
++
++/* for leases */
++#define F_INPROGRESS 16
++
++#ifdef __USE_BSD
++/* operations for bsd flock(), also used by the kernel implementation */
++# define LOCK_SH 1 /* shared lock */
++# define LOCK_EX 2 /* exclusive lock */
++# define LOCK_NB 4 /* or'd with one of the above to prevent
++ blocking */
++# define LOCK_UN 8 /* remove lock */
++#endif
++
++#ifdef __USE_GNU
++# define LOCK_MAND 32 /* This is a mandatory flock */
++# define LOCK_READ 64 /* ... Which allows concurrent
++ read operations */
++# define LOCK_WRITE 128 /* ... Which allows concurrent
++ write operations */
++# define LOCK_RW 192 /* ... Which allows concurrent
++ read & write ops */
++#endif
++
++#ifdef __USE_GNU
++/* Types of directory notifications that may be requested with F_NOTIFY. */
++# define DN_ACCESS 0x00000001 /* File accessed. */
++# define DN_MODIFY 0x00000002 /* File modified. */
++# define DN_CREATE 0x00000004 /* File created. */
++# define DN_DELETE 0x00000008 /* File removed. */
++# define DN_RENAME 0x00000010 /* File renamed. */
++# define DN_ATTRIB 0x00000020 /* File changed attibutes. */
++# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */
++#endif
++
++struct flock {
++ short l_type;
++ short l_whence;
++#ifndef __USE_FILE_OFFSET64
++ __off_t l_start;
++ __off_t l_len;
++#else
++ __off64_t l_start;
++ __off64_t l_len;
++#endif
++ __pid_t l_pid;
++};
++
++#ifdef __USE_LARGEFILE64
++struct flock64 {
++ short l_type;
++ short l_whence;
++ __off64_t l_start;
++ __off64_t l_len;
++ __pid_t l_pid;
++};
++#endif
++
++/* Define some more compatibility macros to be backward compatible with
++ * BSD systems which did not managed to hide these kernel macros. */
++#ifdef __USE_BSD
++# define FAPPEND O_APPEND
++# define FFSYNC O_FSYNC
++# define FASYNC O_ASYNC
++# define FNONBLOCK O_NONBLOCK
++# define FNDELAY O_NDELAY
++#endif /* Use BSD. */
++
++/* Advise to `posix_fadvise'. */
++#ifdef __USE_XOPEN2K
++# define POSIX_FADV_NORMAL 0 /* No further special treatment. */
++# define POSIX_FADV_RANDOM 1 /* Expect random page references. */
++# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */
++# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
++# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
++#endif
+diff --git a/libc/sysdeps/linux/avr32/bits/kernel_stat.h b/libc/sysdeps/linux/avr32/bits/kernel_stat.h
+new file mode 100644
+index 0000000..f97d23b
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/kernel_stat.h
+@@ -0,0 +1,67 @@
++#ifndef _BITS_STAT_STRUCT_H
++#define _BITS_STAT_STRUCT_H
++
++#ifndef _LIBC
++#error bits/kernel_stat.h is for internal uClibc use only!
++#endif
++
++/*
++ * This file provides struct stat, taken from kernel 2.6.4. Verified
++ * to match kernel 2.6.22.
++ */
++
++struct kernel_stat {
++ unsigned long st_dev;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned long st_rdev;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#define STAT_HAVE_NSEC 1
++
++struct kernel_stat64 {
++ unsigned long long st_dev;
++
++ unsigned long long st_ino;
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++
++ long long st_size;
++ unsigned long __pad1;
++ unsigned long st_blksize;
++
++ unsigned long long st_blocks;
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* _BITS_STAT_STRUCT_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/kernel_types.h b/libc/sysdeps/linux/avr32/bits/kernel_types.h
+new file mode 100644
+index 0000000..f7d8b52
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/kernel_types.h
+@@ -0,0 +1,55 @@
++/* Note that we use the exact same include guard #define names
++ * as asm/posix_types.h. This will avoid gratuitous conflicts
++ * with the posix_types.h kernel header, and will ensure that
++ * our private content, and not the kernel header, will win.
++ * -Erik
++ */
++#ifndef __ASM_AVR32_POSIX_TYPES_H
++#define __ASM_AVR32_POSIX_TYPES_H
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_dev_t;
++typedef unsigned long __kernel_ino_t;
++typedef unsigned short __kernel_mode_t;
++typedef unsigned short __kernel_nlink_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned short __kernel_ipc_pid_t;
++typedef unsigned int __kernel_uid_t;
++typedef unsigned int __kernel_gid_t;
++typedef unsigned long __kernel_size_t;
++typedef long __kernel_ssize_t;
++typedef int __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_suseconds_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++typedef unsigned short __kernel_old_uid_t;
++typedef unsigned short __kernel_old_gid_t;
++typedef unsigned short __kernel_old_dev_t;
++
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++
++typedef struct {
++#if defined(__USE_ALL)
++ int val[2];
++#else
++ int __val[2];
++#endif
++} __kernel_fsid_t;
++
++#endif /* __ASM_AVR32_POSIX_TYPES_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/mman.h b/libc/sysdeps/linux/avr32/bits/mman.h
+new file mode 100644
+index 0000000..5f6e3c3
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/mman.h
+@@ -0,0 +1,103 @@
++/* Definitions for POSIX memory map interface. Linux/AVR32 version.
++ Copyright (C) 1997, 2000 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_MMAN_H
++# error "Never include this file directly. Use <sys/mman.h> instead"
++#endif
++
++/* The following definitions basically come from the kernel headers.
++ But the kernel header is not namespace clean. */
++
++
++/* Protections are chosen from these bits, OR'd together. The
++ implementation does not necessarily support PROT_EXEC or PROT_WRITE
++ without PROT_READ. The only guarantees are that no writing will be
++ allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
++
++#define PROT_READ 0x1 /* Page can be read. */
++#define PROT_WRITE 0x2 /* Page can be written. */
++#define PROT_EXEC 0x4 /* Page can be executed. */
++#define PROT_NONE 0x0 /* Page can not be accessed. */
++#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of
++ growsdown vma (mprotect only). */
++#define PROT_GROWSUP 0x02000000 /* Extend change to start of
++ growsup vma (mprotect only). */
++
++/* Sharing types (must choose one and only one of these). */
++#define MAP_SHARED 0x01 /* Share changes. */
++#define MAP_PRIVATE 0x02 /* Changes are private. */
++#ifdef __USE_MISC
++# define MAP_TYPE 0x0f /* Mask for type of mapping. */
++#endif
++
++/* Other flags. */
++#define MAP_FIXED 0x10 /* Interpret addr exactly. */
++#ifdef __USE_MISC
++# define MAP_FILE 0
++# define MAP_ANONYMOUS 0x20 /* Don't use a file. */
++# define MAP_ANON MAP_ANONYMOUS
++#endif
++
++/* These are Linux-specific. */
++#ifdef __USE_MISC
++# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */
++# define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */
++# define MAP_LOCKED 0x2000 /* Lock the mapping. */
++# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */
++# define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
++# define MAP_NONBLOCK 0x10000 /* do not block on IO */
++#endif
++
++/* Flags to `msync'. */
++#define MS_ASYNC 1 /* Sync memory asynchronously. */
++#define MS_SYNC 4 /* Synchronous memory sync. */
++#define MS_INVALIDATE 2 /* Invalidate the caches. */
++
++/* Flags for `mlockall'. */
++#define MCL_CURRENT 1 /* Lock all currently mapped pages. */
++#define MCL_FUTURE 2 /* Lock all additions to address
++ space. */
++
++/* Flags for `mremap'. */
++#ifdef __USE_GNU
++# define MREMAP_MAYMOVE 1
++# define MREMAP_FIXED 2
++#endif
++
++/* Advise to `madvise'. */
++#ifdef __USE_BSD
++# define MADV_NORMAL 0 /* No further special treatment. */
++# define MADV_RANDOM 1 /* Expect random page references. */
++# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define MADV_WILLNEED 3 /* Will need these pages. */
++# define MADV_DONTNEED 4 /* Don't need these pages. */
++# define MADV_REMOVE 9 /* Remove these pages and resources. */
++# define MADV_DONTFORK 10 /* Do not inherit across fork. */
++# define MADV_DOFORK 11 /* Do inherit across fork. */
++#endif
++
++/* The POSIX people had to invent similar names for the same things. */
++#ifdef __USE_XOPEN2K
++# define POSIX_MADV_NORMAL 0 /* No further special treatment. */
++# define POSIX_MADV_RANDOM 1 /* Expect random page references. */
++# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */
++# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */
++# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */
++#endif
+diff --git a/libc/sysdeps/linux/avr32/bits/setjmp.h b/libc/sysdeps/linux/avr32/bits/setjmp.h
+new file mode 100644
+index 0000000..78348a3
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/setjmp.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2004-2005 Atmel Corporation
++ *
++ * 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.
++ */
++#ifndef _BITS_SETJMP_H
++#define _BITS_SETJMP_H 1
++
++#if !defined _SETJMP_H && !defined _PTHREAD_H
++# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
++#endif
++
++#ifndef _ASM
++/*
++ * The jump buffer contains r0-r7, sr, sp and lr. Other registers are
++ * not saved.
++ */
++typedef int __jmp_buf[11];
++#endif
++
++#define __JMP_BUF_SP 4
++
++/* Test if longjmp to JMPBUF would unwind the frame containing a local
++ variable at ADDRESS. */
++#define _JMPBUF_UNWINDS(jmpbuf, address) \
++ ((void *)(address) < (void *)(jmpbuf[__JMP_BUF_SP]))
++
++#endif /* _BITS_SETJMP_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/stackinfo.h b/libc/sysdeps/linux/avr32/bits/stackinfo.h
+new file mode 100644
+index 0000000..29b8452
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/stackinfo.h
+@@ -0,0 +1,28 @@
++/* Copyright (C) 1999 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++/* This file contains a bit of information about the stack allocation
++ of the processor. */
++
++#ifndef _STACKINFO_H
++#define _STACKINFO_H 1
++
++/* On AVR32 the stack grows down. */
++#define _STACK_GROWS_DOWN 1
++
++#endif /* stackinfo.h */
+diff --git a/libc/sysdeps/linux/avr32/bits/syscalls.h b/libc/sysdeps/linux/avr32/bits/syscalls.h
+new file mode 100644
+index 0000000..22ac059
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/syscalls.h
+@@ -0,0 +1,143 @@
++#ifndef _BITS_SYSCALLS_H
++#define _BITS_SYSCALLS_H
++#ifndef _SYSCALL_H
++# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
++#endif
++
++/*
++ * This includes the `__NR_<name>' syscall numbers taken from the
++ * Linux kernel header files. It also defines the traditional
++ * `SYS_<name>' macros for older programs.
++ */
++#include <bits/sysnum.h>
++
++#ifndef __ASSEMBLER__
++
++#include <errno.h>
++
++#define SYS_ify(syscall_name) (__NR_##syscall_name)
++
++#undef _syscall0
++#define _syscall0(type,name) \
++ type name(void) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 0)); \
++ }
++
++#undef _syscall1
++#define _syscall1(type,name,type1,arg1) \
++ type name(type1 arg1) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 1, arg1)); \
++ }
++
++#undef _syscall2
++#define _syscall2(type,name,type1,arg1,type2,arg2) \
++ type name(type1 arg1, type2 arg2) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 2, arg1, arg2)); \
++ }
++
++#undef _syscall3
++#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
++ type name(type1 arg1, type2 arg2, type3 arg3) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 3, arg1, \
++ arg2, arg3)); \
++ }
++
++#undef _syscall4
++#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 4, arg1, arg2, \
++ arg3, arg4)); \
++ }
++
++#undef _syscall5
++#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4,type5,arg5) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
++ type5 arg5) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 5, arg1, arg2, \
++ arg3, arg4, arg5)); \
++ }
++
++#undef _syscall6
++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3, \
++ type4,arg4,type5,arg5,type6,arg6) \
++ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
++ type5 arg5, type6 arg6) \
++ { \
++ return (type)(INLINE_SYSCALL(name, 6, arg1, arg2, arg3, \
++ arg4, arg5, arg6)); \
++ }
++
++#undef unlikely
++#define unlikely(x) __builtin_expect((x), 0)
++
++#undef INLINE_SYSCALL
++#define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ unsigned _sys_result = INTERNAL_SYSCALL(name, , nr, args); \
++ if (unlikely(INTERNAL_SYSCALL_ERROR_P(_sys_result, ))) { \
++ __set_errno(INTERNAL_SYSCALL_ERRNO(_sys_result, )); \
++ _sys_result = (unsigned int) -1; \
++ } \
++ (int) _sys_result; \
++ })
++
++#undef INTERNAL_SYSCALL_DECL
++#define INTERNAL_SYSCALL_DECL(err) do { } while(0)
++
++#undef INTERNAL_SYSCALL
++#define INTERNAL_SYSCALL(name, err, nr, args...) \
++ ({ \
++ register int _a1 asm ("r12"); \
++ register int _scno asm("r8") = SYS_ify(name); \
++ LOAD_ARGS_##nr (args); \
++ asm volatile ("scall /* syscall " #name " */" \
++ : "=r" (_a1) \
++ : "r"(_scno) ASM_ARGS_##nr \
++ : "cc", "memory"); \
++ _a1; \
++ })
++
++#undef INTERNAL_SYSCALL_ERROR_P
++#define INTERNAL_SYSCALL_ERROR_P(val, err) \
++ ((unsigned int)(val) >= 0xfffff001U)
++
++#undef INTERNAL_SYSCALL_ERRNO
++#define INTERNAL_SYSCALL_ERRNO(val, errr) (-(val))
++
++#define LOAD_ARGS_0() do { } while(0)
++#define ASM_ARGS_0
++#define LOAD_ARGS_1(a1) \
++ _a1 = (int) (a1); \
++ LOAD_ARGS_0()
++#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a1)
++#define LOAD_ARGS_2(a1, a2) \
++ register int _a2 asm("r11") = (int)(a2); \
++ LOAD_ARGS_1(a1)
++#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a2)
++#define LOAD_ARGS_3(a1, a2, a3) \
++ register int _a3 asm("r10") = (int)(a3); \
++ LOAD_ARGS_2(a1, a2)
++#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a3)
++#define LOAD_ARGS_4(a1, a2, a3, a4) \
++ register int _a4 asm("r9") = (int)(a4); \
++ LOAD_ARGS_3(a1, a2, a3)
++#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a4)
++#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
++ register int _a5 asm("r5") = (int)(a5); \
++ LOAD_ARGS_4(a1, a2, a3, a4)
++#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a5)
++#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
++ register int _a6 asm("r3") = (int)(a6); \
++ LOAD_ARGS_5(a1, a2, a3, a4, a5)
++#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a6)
++
++#endif /* __ASSEMBLER__ */
++#endif /* _BITS_SYSCALLS_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h b/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h
+new file mode 100644
+index 0000000..e95e8a5
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h
+@@ -0,0 +1,45 @@
++/*
++ * Track misc arch-specific features that aren't config options
++ */
++
++#ifndef _BITS_UCLIBC_ARCH_FEATURES_H
++#define _BITS_UCLIBC_ARCH_FEATURES_H
++
++/* instruction used when calling abort() to kill yourself */
++/* trigger illegal instruction exception, same as BUG in Linux */
++#define __UCLIBC_ABORT_INSTRUCTION__ ".short 0x5df0"
++
++/* can your target use syscall6() for mmap ? */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++/* does your target use syscall4() for truncate64 ? (32bit arches only) */
++#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
++
++/* does your target have a broken create_module() ? */
++#undef __UCLIBC_BROKEN_CREATE_MODULE__
++
++/* does your target have to worry about older [gs]etrlimit() ? */
++#undef __UCLIBC_HANDLE_OLDER_RLIMIT__
++
++/* does your target prefix all symbols with an _ ? */
++#define __UCLIBC_NO_UNDERSCORES__
++
++/* does your target have an asm .set ? */
++#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
++
++/* define if target doesn't like .global */
++#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__
++
++/* define if target supports .weak */
++#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__
++
++/* define if target supports .weakext */
++#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__
++
++/* needed probably only for ppc64 */
++#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__
++
++/* define if target supports IEEE signed zero floats */
++#define __UCLIBC_HAVE_SIGNED_ZERO__
++
++#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
+diff --git a/libc/sysdeps/linux/avr32/bits/wordsize.h b/libc/sysdeps/linux/avr32/bits/wordsize.h
+new file mode 100644
+index 0000000..1b5842a
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bits/wordsize.h
+@@ -0,0 +1 @@
++#define __WORDSIZE 32
+diff --git a/libc/sysdeps/linux/avr32/brk.c b/libc/sysdeps/linux/avr32/brk.c
+new file mode 100644
+index 0000000..a54b49a
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/brk.c
+@@ -0,0 +1,31 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++#include <errno.h>
++#include <unistd.h>
++#include <sys/syscall.h>
++
++libc_hidden_proto(brk)
++
++void *__curbrk attribute_hidden = 0;
++
++int brk (void *addr)
++{
++ void *newbrk;
++
++ newbrk = (void *)INLINE_SYSCALL(brk, 1, addr);
++
++ __curbrk = newbrk;
++
++ if (newbrk < addr) {
++ __set_errno (ENOMEM);
++ return -1;
++ }
++
++ return 0;
++}
++libc_hidden_def(brk)
+diff --git a/libc/sysdeps/linux/avr32/bsd-_setjmp.S b/libc/sysdeps/linux/avr32/bsd-_setjmp.S
+new file mode 100644
+index 0000000..be66a10
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bsd-_setjmp.S
+@@ -0,0 +1,16 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++ /* This just does a tail-call to __sigsetjmp(env, 0) */
++ .global _setjmp
++ .type _setjmp,"function"
++ .align 1
++_setjmp:
++ mov r11, 0
++ bral __GI___sigsetjmp
++ .size _setjmp, . - _setjmp
+diff --git a/libc/sysdeps/linux/avr32/bsd-setjmp.S b/libc/sysdeps/linux/avr32/bsd-setjmp.S
+new file mode 100644
+index 0000000..4635eeb
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/bsd-setjmp.S
+@@ -0,0 +1,16 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++ /* This just does a tail-call to __sigsetjmp(env, 1) */
++ .global setjmp
++ .type setjmp,"function"
++ .align 1
++setjmp:
++ mov r11, 1
++ bral __GI___sigsetjmp
++ .size setjmp, . - setjmp
+diff --git a/libc/sysdeps/linux/avr32/clone.c b/libc/sysdeps/linux/avr32/clone.c
+new file mode 100644
+index 0000000..e43b0f3
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/clone.c
+@@ -0,0 +1,41 @@
++/*
++ * Copyright (C) 2004 Atmel Corporation
++ *
++ * 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.
++ */
++#include <errno.h>
++#include <sys/syscall.h>
++#include <unistd.h>
++
++/*
++ * I don't know if we can be absolutely certain that the fn and arg
++ * parameters are preserved when returning as the child. If the
++ * compiler stores them in registers (r0-r7), they should be.
++ */
++int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg)
++{
++ register int (*_fn)(void *arg) = fn;
++ register void *_arg = arg;
++ int err;
++
++ /* Sanity check the arguments */
++ err = -EINVAL;
++ if (!fn)
++ goto syscall_error;
++ if (!child_stack)
++ goto syscall_error;
++
++ err = INLINE_SYSCALL(clone, 2, flags, child_stack);
++ if (err < 0)
++ goto syscall_error;
++ else if (err != 0)
++ return err;
++
++ _exit(_fn(_arg));
++
++syscall_error:
++ __set_errno (-err);
++ return -1;
++}
+diff --git a/libc/sysdeps/linux/avr32/crt1.S b/libc/sysdeps/linux/avr32/crt1.S
+new file mode 100644
+index 0000000..ca1fa7a
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/crt1.S
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ *
++ * When we enter _start, the stack looks like this:
++ * argc argument counter
++ * argv[0] pointer to program name
++ * argv[1..argc-1] pointers to program args
++ * NULL
++ * env[0..N] pointers to environment variables
++ * NULL
++ *
++ * r12 contains a function pointer to be registered with `atexit'.
++ * This is how the dynamic linker arranges to have DT_FINI functions
++ * called for shared libraries that have been loaded before this
++ * code runs.
++ *
++ * We're going to call the following function:
++ * __uClibc_main(int (*main)(int, char **, char **), int argc,
++ * char **argv, void (*app_init)(void), void (*app_fini)(void),
++ * void (*rtld_fini)(void), void *stack_end)
++ *
++ * So we need to set up things as follows:
++ * r12 = address of main
++ * r11 = argc
++ * r10 = &argv[0]
++ * r9 = address of _init
++ * r8 = address of _fini
++ * sp[0] = whatever we got passed in r12
++ */
++
++#include <features.h>
++
++ .text
++ .global _start
++ .type _start, @function
++_start:
++ /* Clear the frame pointer and link register since this is the outermost frame. */
++ mov r7, 0
++ mov lr, 0
++
++ ld.w r11, sp++ /* argc */
++ mov r10, sp /* &argv[0] */
++
++ st.w --sp, r10 /* stack_end */
++ st.w --sp, r12 /* rtld_fini */
++
++#ifdef __PIC__
++ lddpc r6, .L_GOT
++.L_RGOT:
++ rsub r6, pc
++ lda.w r9, _init
++ lda.w r8, _fini
++ lda.w r12, main
++
++ /* Ok, now run uClibc's main() -- should not return */
++ call __uClibc_main
++
++ .align 2
++.L_GOT:
++ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
++#else
++ lddpc r9, __init_addr /* app_init */
++ lddpc r8, __fini_addr /* app_fini */
++ lddpc r12, __main_addr /* main */
++
++ /* Ok, now run uClibc's main() -- should not return */
++ lddpc pc, ___uClibc_main_addr
++
++ .align 2
++__init_addr:
++ .long _init
++__fini_addr:
++ .long _fini
++__main_addr:
++ .long main
++___uClibc_main_addr:
++ .long __uClibc_main
++#endif
++ .size _start, . - _start
++
++ /*
++ * The LSB says we need this.
++ */
++ .section ".note.ABI-tag", "a"
++ .align 4
++ .long 2f - 1f /* namesz */
++ .long 4f - 3f /* descsz */
++ .long 1 /* type */
++1: .asciz "GNU" /* name */
++2: .align 4
++3: .long 0 /* Linux executable */
++ .long 2,6,0 /* Earliest compatible kernel */
++4: .align 4
+diff --git a/libc/sysdeps/linux/avr32/crti.S b/libc/sysdeps/linux/avr32/crti.S
+new file mode 100644
+index 0000000..660f47c
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/crti.S
+@@ -0,0 +1,26 @@
++
++ .section .init
++ .align 2
++ .global _init
++ .type _init, @function
++_init:
++ stm --sp, r6, lr
++ lddpc r6, 2f
++1: rsub r6, pc
++ rjmp 3f
++ .align 2
++2: .long 1b - _GLOBAL_OFFSET_TABLE_
++3:
++
++ .section .fini
++ .align 2
++ .global _fini
++ .type _fini, @function
++_fini:
++ stm --sp, r6, lr
++ lddpc r6, 2f
++1: rsub r6, pc
++ rjmp 3f
++ .align 2
++2: .long 1b - _GLOBAL_OFFSET_TABLE_
++3:
+diff --git a/libc/sysdeps/linux/avr32/crtn.S b/libc/sysdeps/linux/avr32/crtn.S
+new file mode 100644
+index 0000000..f7d1040
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/crtn.S
+@@ -0,0 +1,14 @@
++
++ .section .init
++ .align 2
++ .global _init
++ .type _init, @function
++ ldm sp++, r6, pc
++ .size _init, . - _init
++
++ .section .fini
++ .align 2
++ .global _fini
++ .type _fini, @function
++ ldm sp++, r6, pc
++ .size _fini, . - _fini
+diff --git a/libc/sysdeps/linux/avr32/mmap.c b/libc/sysdeps/linux/avr32/mmap.c
+new file mode 100644
+index 0000000..2ee025a
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/mmap.c
+@@ -0,0 +1,33 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++
++#include <errno.h>
++#include <unistd.h>
++#include <sys/mman.h>
++#include <sys/syscall.h>
++
++libc_hidden_proto(mmap)
++
++static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot,
++ int, flags, int, fd, __off_t, pgoff);
++
++__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
++{
++ unsigned long page_size = sysconf(_SC_PAGESIZE);
++ unsigned long pgoff;
++
++ if (offset & (page_size - 1)) {
++ __set_errno(EINVAL);
++ return MAP_FAILED;
++ }
++
++ pgoff = (unsigned long)offset >> (31 - __builtin_clz(page_size));
++
++ return mmap2(addr, len, prot, flags, fd, pgoff);
++}
++libc_hidden_def(mmap)
+diff --git a/libc/sysdeps/linux/avr32/setjmp.S b/libc/sysdeps/linux/avr32/setjmp.S
+new file mode 100644
+index 0000000..7d0354b
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/setjmp.S
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++#define _SETJMP_H
++#define _ASM
++#include <bits/setjmp.h>
++
++ .text
++
++ .global __sigsetjmp
++ .type __sigsetjmp,"function"
++
++ .align 1
++__sigsetjmp:
++ mustr r8
++ stm r12, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr
++
++ /*
++ * Make a tail call to __sigjmp_save; it takes the same args
++ * and is hidden so we don't need to mess around with the GOT.
++ */
++ rjmp __sigjmp_save
++ .size __sigsetjmp, . - __sigsetjmp
++
++libc_hidden_def(__sigsetjmp)
+diff --git a/libc/sysdeps/linux/avr32/sigaction.c b/libc/sysdeps/linux/avr32/sigaction.c
+new file mode 100644
+index 0000000..a97ff3d
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/sigaction.c
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++#include <errno.h>
++#include <signal.h>
++#include <string.h>
++#include <sys/syscall.h>
++#include <bits/kernel_sigaction.h>
++
++#define SA_RESTORER 0x04000000
++extern void __default_rt_sa_restorer(void);
++
++libc_hidden_proto(memcpy)
++
++/*
++ * If act is not NULL, change the action for sig to *act.
++ * If oact is not NULL, put the old action for sig in *oact.
++ */
++int __libc_sigaction(int signum, const struct sigaction *act,
++ struct sigaction *oldact)
++{
++ struct kernel_sigaction kact, koact;
++ int result;
++
++ if (act) {
++ kact.k_sa_handler = act->sa_handler;
++ memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
++ kact.sa_flags = act->sa_flags;
++ if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK))
++ kact.sa_restorer = act->sa_restorer;
++ else
++ kact.sa_restorer = __default_rt_sa_restorer;
++ kact.sa_flags |= SA_RESTORER;
++ }
++
++ result = __syscall_rt_sigaction(signum, act ? __ptrvalue(&kact) : NULL,
++ oldact ? __ptrvalue(&koact) : NULL,
++ _NSIG / 8);
++
++ if (oldact && result >= 0) {
++ oldact->sa_handler = koact.k_sa_handler;
++ memcpy(&oldact->sa_mask, &koact.sa_mask,
++ sizeof(oldact->sa_mask));
++ oldact->sa_flags = koact.sa_flags;
++ oldact->sa_restorer = koact.sa_restorer;
++ }
++
++ return result;
++}
++
++#ifndef LIBC_SIGACTION
++libc_hidden_proto(sigaction)
++weak_alias(__libc_sigaction, sigaction)
++libc_hidden_weak(sigaction)
++#endif
+diff --git a/libc/sysdeps/linux/avr32/sigrestorer.S b/libc/sysdeps/linux/avr32/sigrestorer.S
+new file mode 100644
+index 0000000..df6a1ba
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/sigrestorer.S
+@@ -0,0 +1,15 @@
++/*
++ * Copyright (C) 2004 Atmel Corporation
++ *
++ * 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.
++ */
++#include <sys/syscall.h>
++
++ .global __default_rt_sa_restorer
++ .type __default_rt_sa_restorer,"function"
++ .align 1
++__default_rt_sa_restorer:
++ mov r8, __NR_rt_sigreturn
++ scall
+diff --git a/libc/sysdeps/linux/avr32/sys/elf.h b/libc/sysdeps/linux/avr32/sys/elf.h
+new file mode 100644
+index 0000000..faa7310
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/sys/elf.h
+@@ -0,0 +1,26 @@
++/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_ELF_H
++#define _SYS_ELF_H 1
++
++#warning "This header is obsolete; use <sys/procfs.h> instead."
++
++#include <sys/procfs.h>
++
++#endif /* sys/elf.h */
+diff --git a/libc/sysdeps/linux/avr32/sys/procfs.h b/libc/sysdeps/linux/avr32/sys/procfs.h
+new file mode 100644
+index 0000000..3b37363
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/sys/procfs.h
+@@ -0,0 +1,123 @@
++/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SYS_PROCFS_H
++#define _SYS_PROCFS_H 1
++
++/* This is somewhat modelled after the file of the same name on SVR4
++ systems. It provides a definition of the core file format for ELF
++ used on Linux. It doesn't have anything to do with the /proc file
++ system, even though Linux has one.
++
++ Anyway, the whole purpose of this file is for GDB and GDB only.
++ Don't read too much into it. Don't use it for anything other than
++ GDB unless you know what you are doing. */
++
++#include <features.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/user.h>
++
++__BEGIN_DECLS
++
++/* Type for a general-purpose register. */
++typedef unsigned long elf_greg_t;
++
++/* And the whole bunch of them. We could have used `struct
++ user_regs' directly in the typedef, but tradition says that
++ the register set is an array, which does have some peculiar
++ semantics, so leave it that way. */
++#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++/* Register set for the floating-point registers. */
++typedef struct user_fpregs elf_fpregset_t;
++
++/* Signal info. */
++struct elf_siginfo
++ {
++ int si_signo; /* Signal number. */
++ int si_code; /* Extra code. */
++ int si_errno; /* Errno. */
++ };
++
++/* Definitions to generate Intel SVR4-like core files. These mostly
++ have the same names as the SVR4 types with "elf_" tacked on the
++ front to prevent clashes with Linux definitions, and the typedef
++ forms have been avoided. This is mostly like the SVR4 structure,
++ but more Linuxy, with things that Linux does not support and which
++ GDB doesn't really use excluded. */
++
++struct elf_prstatus
++ {
++ struct elf_siginfo pr_info; /* Info associated with signal. */
++ short int pr_cursig; /* Current signal. */
++ unsigned long int pr_sigpend; /* Set of pending signals. */
++ unsigned long int pr_sighold; /* Set of held signals. */
++ __pid_t pr_pid;
++ __pid_t pr_ppid;
++ __pid_t pr_pgrp;
++ __pid_t pr_sid;
++ struct timeval pr_utime; /* User time. */
++ struct timeval pr_stime; /* System time. */
++ struct timeval pr_cutime; /* Cumulative user time. */
++ struct timeval pr_cstime; /* Cumulative system time. */
++ elf_gregset_t pr_reg; /* GP registers. */
++ int pr_fpvalid; /* True if math copro being used. */
++ };
++
++
++#define ELF_PRARGSZ (80) /* Number of chars for args. */
++
++struct elf_prpsinfo
++ {
++ char pr_state; /* Numeric process state. */
++ char pr_sname; /* Char for pr_state. */
++ char pr_zomb; /* Zombie. */
++ char pr_nice; /* Nice val. */
++ unsigned long int pr_flag; /* Flags. */
++ unsigned short int pr_uid;
++ unsigned short int pr_gid;
++ int pr_pid, pr_ppid, pr_pgrp, pr_sid;
++ /* Lots missing */
++ char pr_fname[16]; /* Filename of executable. */
++ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
++ };
++
++/* The rest of this file provides the types for emulation of the
++ Solaris <proc_service.h> interfaces that should be implemented by
++ users of libthread_db. */
++
++/* Addresses. */
++typedef void *psaddr_t;
++
++/* Register sets. Linux has different names. */
++typedef elf_gregset_t prgregset_t;
++typedef elf_fpregset_t prfpregset_t;
++
++/* We don't have any differences between processes and threads,
++ therefore have only one PID type. */
++typedef __pid_t lwpid_t;
++
++/* Process status and info. In the end we do provide typedefs for them. */
++typedef struct elf_prstatus prstatus_t;
++typedef struct elf_prpsinfo prpsinfo_t;
++
++__END_DECLS
++
++#endif /* sys/procfs.h */
+diff --git a/libc/sysdeps/linux/avr32/sys/ucontext.h b/libc/sysdeps/linux/avr32/sys/ucontext.h
+new file mode 100644
+index 0000000..82c7fe2
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/sys/ucontext.h
+@@ -0,0 +1,90 @@
++/* Copyright (C) 1998, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++/* Linux/AVR32 ABI compliant context switching support. */
++
++#ifndef _SYS_UCONTEXT_H
++#define _SYS_UCONTEXT_H 1
++
++#include <features.h>
++#include <signal.h>
++#include <sys/procfs.h>
++#include <bits/sigcontext.h>
++
++typedef int greg_t;
++
++/* Number of general registers. */
++#define NGREG 16
++
++/* Container for all general registers. */
++typedef elf_gregset_t gregset_t;
++
++/* Number of each register is the `gregset_t' array. */
++enum
++{
++ R0 = 0,
++#define R0 R0
++ R1 = 1,
++#define R1 R1
++ R2 = 2,
++#define R2 R2
++ R3 = 3,
++#define R3 R3
++ R4 = 4,
++#define R4 R4
++ R5 = 5,
++#define R5 R5
++ R6 = 6,
++#define R6 R6
++ R7 = 7,
++#define R7 R7
++ R8 = 8,
++#define R8 R8
++ R9 = 9,
++#define R9 R9
++ R10 = 10,
++#define R10 R10
++ R11 = 11,
++#define R11 R11
++ R12 = 12,
++#define R12 R12
++ R13 = 13,
++#define R13 R13
++ R14 = 14,
++#define R14 R14
++ R15 = 15
++#define R15 R15
++};
++
++/* Structure to describe FPU registers. */
++typedef elf_fpregset_t fpregset_t;
++
++/* Context to describe whole processor state. */
++typedef struct sigcontext mcontext_t;
++
++/* Userlevel context. */
++typedef struct ucontext
++{
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ mcontext_t uc_mcontext;
++ sigset_t uc_sigmask; /* mask last for extensibility */
++} ucontext_t;
++
++#endif /* sys/ucontext.h */
+diff --git a/libc/sysdeps/linux/avr32/sys/user.h b/libc/sysdeps/linux/avr32/sys/user.h
+new file mode 100644
+index 0000000..c0b3d38
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/sys/user.h
+@@ -0,0 +1,46 @@
++#ifndef _SYS_USER_H
++#define _SYS_USER_H
++
++struct user_fpregs
++{
++
++};
++
++struct user_regs
++{
++ unsigned long sr;
++ unsigned long pc;
++ unsigned long lr;
++ unsigned long sp;
++ unsigned long r12;
++ unsigned long r11;
++ unsigned long r10;
++ unsigned long r9;
++ unsigned long r8;
++ unsigned long r7;
++ unsigned long r6;
++ unsigned long r5;
++ unsigned long r4;
++ unsigned long r3;
++ unsigned long r2;
++ unsigned long r1;
++ unsigned long r0;
++ unsigned long r12_orig;
++};
++
++struct user
++{
++ struct user_regs regs; /* general registers */
++ size_t u_tsize; /* text size (pages) */
++ size_t u_dsize; /* data size (pages) */
++ size_t u_ssize; /* stack size (pages) */
++ unsigned long start_code; /* text starting address */
++ unsigned long start_data; /* data starting address */
++ unsigned long start_stack; /* stack starting address */
++ long int signal; /* signal causing core dump */
++ struct user_regs * u_ar0; /* help gdb find registers */
++ unsigned long magic; /* identifies a core file */
++ char u_comm[32]; /* user command name */
++};
++
++#endif /* _SYS_USER_H */
+diff --git a/libc/sysdeps/linux/avr32/syscall.S b/libc/sysdeps/linux/avr32/syscall.S
+new file mode 100644
+index 0000000..55c1b1f
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/syscall.S
+@@ -0,0 +1,71 @@
++/*
++ * Copyright (C) 2004-2007 Atmel Corporation
++ *
++ * 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.
++ */
++#include <features.h>
++
++ .text
++
++ /*
++ * long int syscall(long int sysno, ...)
++ */
++ .global syscall
++ .type syscall, @function
++ .align 2
++syscall:
++ stm --sp, r3,r5,r6,lr
++ sub lr, sp, -16
++ mov r8, r12
++ ldm lr, r3,r5,r9-r12
++ scall
++ cp.w r12, -4095
++ brlo .Ldone
++
++#ifdef __PIC__
++ lddpc r6, .Lgot
++.Lgotcalc:
++ rsub r6, pc
++# ifdef __UCLIBC_HAS_THREADS__
++ rsub r3, r12, 0
++ mcall r6[__errno_location@got]
++ st.w r12[0], r3
++# else
++ ld.w r3, r6[errno@got]
++ neg r12
++ st.w r3[0], r12
++# endif
++#else
++# ifdef __UCLIBC_HAS_THREADS__
++ rsub r3, r12, 0
++ mcall .Lerrno_location
++ st.w r12[0], r3
++# else
++ lddpc r3, .Lerrno
++ neg r12
++ st.w r3[0], r12
++# endif
++#endif
++ mov r12, -1
++
++.Ldone:
++ ldm sp++, r3,r5,r6,pc
++
++ .align 2
++#ifdef __PIC__
++.Lgot:
++ .long .Lgotcalc - _GLOBAL_OFFSET_TABLE_
++#else
++# ifdef __UCLIBC_HAS_THREADS__
++.Lerrno_location:
++ .long __errno_location
++# else
++.Lerrno:
++ .long errno
++# endif
++#endif
++
++
++ .size syscall, . - syscall
+diff --git a/libc/sysdeps/linux/avr32/vfork.S b/libc/sysdeps/linux/avr32/vfork.S
+new file mode 100644
+index 0000000..03ca99f
+--- /dev/null
++++ b/libc/sysdeps/linux/avr32/vfork.S
+@@ -0,0 +1,58 @@
++/*
++ * Copyright (C) 2005 Atmel Corporation
++ *
++ * 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.
++ */
++
++/*
++ * Clone the process without copying the address space. The
++ * calling process is suspended until the child either exits
++ * or calls execve.
++ *
++ * This all means that we cannot rely on the stack to store
++ * away registers, since they will be overwritten by the child
++ * as soon as it makes another function call (e.g. execve()).
++ * Fortunately, the Linux kernel preserves LR across system calls.
++ */
++
++#include <features.h>
++#include <sys/syscall.h>
++
++ .global __vfork
++ .type __vfork,@function
++ .align 1
++__vfork:
++ mov r8, __NR_vfork
++ scall
++ cp.w r12, -4096
++ retls r12
++
++ /* vfork failed, so we may use the stack freely */
++ pushm r4-r7,lr
++#ifdef __PIC__
++ lddpc r6, .L_GOT
++ rsub r4, r12, 0
++.L_RGOT:
++ rsub r6, pc
++ mcall r6[__errno_location@got]
++#else
++ rsub r4, r12, 0
++ mcall .L__errno_location
++#endif
++ st.w r12[0], r4
++ popm r4-r7,pc,r12=-1
++
++ .align 2
++#ifdef __PIC__
++.L_GOT:
++ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
++#else
++.L__errno_location:
++ .long __errno_location
++#endif
++ .size __vfork, . - __vfork
++
++weak_alias(__vfork,vfork)
++libc_hidden_weak(vfork)
+diff --git a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
+new file mode 100644
+index 0000000..eccf329
+--- /dev/null
++++ b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
+@@ -0,0 +1,73 @@
++/* Machine-dependent pthreads configuration and inline functions.
++ *
++ * Copyright (C) 2005-2007 Atmel Corporation
++ *
++ * 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.
++ */
++#ifndef _PT_MACHINE_H
++#define _PT_MACHINE_H 1
++
++#include <features.h>
++
++static inline int
++_test_and_set (int *p, int v)
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline test and set */\n"
++ " xchg %[old], %[mem], %[new]"
++ : [old] "=&r"(result)
++ : [mem] "r"(p), [new] "r"(v)
++ : "memory");
++
++ return result;
++}
++
++#ifndef PT_EI
++# define PT_EI extern inline
++#endif
++
++extern long int testandset (int *spinlock);
++extern int __compare_and_swap (long int *p, long int oldval, long int newval);
++
++/* Spinlock implementation; required. */
++PT_EI long int
++testandset (int *spinlock)
++{
++ return _test_and_set(spinlock, 1);
++}
++
++
++/* Get some notion of the current stack. Need not be exactly the top
++ of the stack, just something somewhere in the current frame. */
++#define CURRENT_STACK_FRAME stack_pointer
++register char * stack_pointer __asm__ ("sp");
++
++/* Compare-and-swap for semaphores. */
++
++#define HAS_COMPARE_AND_SWAP
++PT_EI int
++__compare_and_swap(long int *p, long int oldval, long int newval)
++{
++ long int result;
++
++ __asm__ __volatile__(
++ "/* Inline compare and swap */\n"
++ "1: ssrf 5\n"
++ " ld.w %[result], %[mem]\n"
++ " eor %[result], %[old]\n"
++ " brne 2f\n"
++ " stcond %[mem], %[new]\n"
++ " brne 1b\n"
++ "2:"
++ : [result] "=&r"(result), [mem] "=m"(*p)
++ : "m"(*p), [new] "r"(newval), [old] "r"(oldval)
++ : "cc", "memory");
++
++ return result == 0;
++}
++
++#endif /* pt-machine.h */
+diff --git a/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h
+new file mode 100644
+index 0000000..fe12bf8
+--- /dev/null
++++ b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h
+@@ -0,0 +1,73 @@
++/* Machine-dependent pthreads configuration and inline functions.
++ *
++ * Copyright (C) 2005-2007 Atmel Corporation
++ *
++ * 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.
++ */
++#ifndef _PT_MACHINE_H
++#define _PT_MACHINE_H 1
++
++#include <features.h>
++
++static inline int
++_test_and_set (int *p, int v) __THROW
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline test and set */\n"
++ " xchg %[old], %[mem], %[new]"
++ : [old] "=&r"(result)
++ : [mem] "r"(p), [new] "r"(v)
++ : "memory");
++
++ return result;
++}
++
++#ifndef PT_EI
++# define PT_EI extern inline
++#endif
++
++extern long int testandset (int *spinlock);
++extern int __compare_and_swap (long int *p, long int oldval, long int newval);
++
++/* Spinlock implementation; required. */
++PT_EI long int
++testandset (int *spinlock)
++{
++ return _test_and_set(spinlock, 1);
++}
++
++
++/* Get some notion of the current stack. Need not be exactly the top
++ of the stack, just something somewhere in the current frame. */
++#define CURRENT_STACK_FRAME stack_pointer
++register char * stack_pointer __asm__ ("sp");
++
++/* Compare-and-swap for semaphores. */
++
++#define HAS_COMPARE_AND_SWAP
++PT_EI int
++__compare_and_swap(long int *p, long int oldval, long int newval)
++{
++ int result;
++
++ __asm__ __volatile__(
++ "/* Inline compare and swap */\n"
++ "1: ssrf 5\n"
++ " ld.w %[result], %[mem]\n"
++ " eor %[result], %[old]\n"
++ " brne 2f\n"
++ " stcond %[mem], %[new]\n"
++ " brne 1b\n"
++ "2:"
++ : [result] "=&r"(result), [mem] "=m"(*p)
++ : "m"(*p), [new] "r"(newval), [old] "r"(oldval)
++ : "cc", "memory");
++
++ return result == 0;
++}
++
++#endif /* pt-machine.h */
+diff --git a/utils/ldd.c b/utils/ldd.c
+index 75ad628..e34acd9 100644
+--- a/utils/ldd.c
++++ b/utils/ldd.c
+@@ -44,6 +44,11 @@
+ #define ELFCLASSM ELFCLASS32
+ #endif
+
++#if defined(__avr32__)
++#define MATCH_MACHINE(x) (x == EM_AVR32)
++#define ELFCLASSM ELFCLASS32
++#endif
++
+ #if defined(__s390__)
+ #define MATCH_MACHINE(x) (x == EM_S390)
+ #define ELFCLASSM ELFCLASS32
--- /dev/null
+From 974a769cc135bcfb1ea751db34a84ed6b5ceb509 Mon Sep 17 00:00:00 2001
+From: Haavard Skinnemoen <hskinnemoen@atmel.com>
+Date: Fri, 7 Dec 2007 14:02:19 +0100
+Subject: [PATCH] AVR32: Fix sa_restorer when SA_ONSTACK is set
+
+I don't remember exactly why we decided to pick the caller's value of
+sa_restorer when SA_ONSTACK is set, but it seems to break LTP's
+sigaltstack testcase. Some users have reported problems with
+sigaltstack as well; hopefully this will fix it.
+
+Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
+---
+ libc/sysdeps/linux/avr32/sigaction.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/libc/sysdeps/linux/avr32/sigaction.c b/libc/sysdeps/linux/avr32/sigaction.c
+index a97ff3d..6dcca91 100644
+--- a/libc/sysdeps/linux/avr32/sigaction.c
++++ b/libc/sysdeps/linux/avr32/sigaction.c
+@@ -30,7 +30,7 @@ int __libc_sigaction(int signum, const struct sigaction *act,
+ kact.k_sa_handler = act->sa_handler;
+ memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
+ kact.sa_flags = act->sa_flags;
+- if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK))
++ if (kact.sa_flags & SA_RESTORER)
+ kact.sa_restorer = act->sa_restorer;
+ else
+ kact.sa_restorer = __default_rt_sa_restorer;
+--
+1.5.3.4
+
+++ /dev/null
-diff --git a/.gitignore b/.gitignore
-new file mode 100644
-index 0000000..f474699
---- /dev/null
-+++ b/.gitignore
-@@ -0,0 +1,63 @@
-+#
-+# NOTE! Don't add files that are generated in specific
-+# subdirectories here. Add them in the ".gitignore" file
-+# in that subdirectory instead.
-+#
-+# Normal rules
-+#
-+.*
-+*.o
-+*.a
-+*.so
-+*.os
-+*.oS
-+.config*
-+
-+#
-+# Top-level generic files
-+#
-+obj.*
-+
-+#
-+# Generated files
-+#
-+extra/config/conf
-+extra/config/lex.zconf.c
-+extra/config/lkc_defs.h
-+extra/config/mconf
-+extra/config/zconf.hash.c
-+extra/config/zconf.tab.c
-+extra/config/zconf.tab.h
-+
-+lib
-+
-+include/asm
-+include/asm-*
-+include/bits
-+include/linux
-+
-+include/sys/acct.h
-+include/sys/elf.h
-+include/sys/epoll.h
-+include/sys/inotify.h
-+include/sys/io.h
-+include/sys/prctl.h
-+include/sys/procfs.h
-+include/sys/ptrace.h
-+include/sys/ucontext.h
-+include/sys/user.h
-+
-+include/dl-osinfo.h
-+include/fpu_control.h
-+include/hp-timing.h
-+include/pthread.h
-+include/semaphore.h
-+include/thread_db.h
-+
-+ldso/include/dl-debug.h
-+ldso/include/dl-startup.h
-+ldso/include/dl-syscalls.h
-+ldso/include/dl-sysdep.h
-+ldso/include/elf.h
-+
-+libc/misc/internals/interp.c
-diff --git a/Rules.mak b/Rules.mak
-index d054bbb..55381cf 100644
---- a/Rules.mak
-+++ b/Rules.mak
-@@ -313,6 +313,12 @@ ifeq ($(TARGET_ARCH),frv)
- UCLIBC_LDSO=ld.so.1
- endif
-
-+ifeq ($(strip $(TARGET_ARCH)),avr32)
-+ CPU_CFLAGS-$(CONFIG_AVR32_AP7) += -march=ap
-+ CPU_CFLAGS-$(CONFIG_LINKRELAX) += -mrelax
-+ CPU_LDFLAGS-$(CONFIG_LINKRELAX) += --relax
-+endif
-+
- # Keep the check_gcc from being needlessly executed
- ifndef PIEFLAG
- ifneq ($(UCLIBC_BUILD_PIE),y)
-diff --git a/extra/Configs/Config.avr32 b/extra/Configs/Config.avr32
-new file mode 100644
-index 0000000..8d70e6e
---- /dev/null
-+++ b/extra/Configs/Config.avr32
-@@ -0,0 +1,31 @@
-+#
-+# For a description of the syntax of this configuration file,
-+# see extra/config/Kconfig-language.txt
-+#
-+
-+config TARGET_ARCH
-+ string
-+ default "avr32"
-+
-+config FORCE_OPTIONS_FOR_ARCH
-+ bool
-+ default y
-+ select ARCH_BIG_ENDIAN
-+ select FORCE_SHAREABLE_TEXT_SEGMENTS
-+
-+config ARCH_CFLAGS
-+ string
-+
-+choice
-+ prompt "Target CPU Type"
-+ default CONFIG_AVR32_AP7
-+
-+config CONFIG_AVR32_AP7
-+ bool "AVR32 AP7"
-+ select ARCH_HAS_MMU
-+
-+endchoice
-+
-+config LINKRELAX
-+ bool "Enable linker optimizations"
-+ default y
-diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
-index 8eab394..10c9f7b 100644
---- a/extra/Configs/Config.in
-+++ b/extra/Configs/Config.in
-@@ -16,6 +16,9 @@ config TARGET_alpha
- config TARGET_arm
- bool "arm"
-
-+config TARGET_avr32
-+ bool "avr32"
-+
- config TARGET_bfin
- bool "bfin"
-
-@@ -92,6 +95,10 @@ if TARGET_arm
- source "extra/Configs/Config.arm"
- endif
-
-+if TARGET_avr32
-+source "extra/Configs/Config.avr32"
-+endif
-+
- if TARGET_bfin
- source "extra/Configs/Config.bfin"
- endif
-diff --git a/extra/Configs/defconfigs/avr32 b/extra/Configs/defconfigs/avr32
-new file mode 100644
-index 0000000..0b890a2
---- /dev/null
-+++ b/extra/Configs/defconfigs/avr32
-@@ -0,0 +1 @@
-+TARGET_avr32=y
-diff --git a/include/elf.h b/include/elf.h
-index 19805d7..ab90160 100644
---- a/include/elf.h
-+++ b/include/elf.h
-@@ -354,6 +354,8 @@ typedef struct
- /* NIOS magic number - no EABI available. */
- #define EM_NIOS32 0xFEBB
-
-+#define EM_AVR32 0x18ad
-+
- /* V850 backend magic number. Written in the absense of an ABI. */
- #define EM_CYGNUS_V850 0x9080
-
-@@ -2828,6 +2830,55 @@ typedef Elf32_Addr Elf32_Conflict;
- /* Keep this the last entry. */
- #define R_V850_NUM 25
-
-+/* Atmel AVR32 relocations. */
-+#define R_AVR32_NONE 0
-+#define R_AVR32_32 1
-+#define R_AVR32_16 2
-+#define R_AVR32_8 3
-+#define R_AVR32_32_PCREL 4
-+#define R_AVR32_16_PCREL 5
-+#define R_AVR32_8_PCREL 6
-+#define R_AVR32_DIFF32 7
-+#define R_AVR32_DIFF16 8
-+#define R_AVR32_DIFF8 9
-+#define R_AVR32_GOT32 10
-+#define R_AVR32_GOT16 11
-+#define R_AVR32_GOT8 12
-+#define R_AVR32_21S 13
-+#define R_AVR32_16U 14
-+#define R_AVR32_16S 15
-+#define R_AVR32_8S 16
-+#define R_AVR32_8S_EXT 17
-+#define R_AVR32_22H_PCREL 18
-+#define R_AVR32_18W_PCREL 19
-+#define R_AVR32_16B_PCREL 20
-+#define R_AVR32_16N_PCREL 21
-+#define R_AVR32_14UW_PCREL 22
-+#define R_AVR32_11H_PCREL 23
-+#define R_AVR32_10UW_PCREL 24
-+#define R_AVR32_9H_PCREL 25
-+#define R_AVR32_9UW_PCREL 26
-+#define R_AVR32_HI16 27
-+#define R_AVR32_LO16 28
-+#define R_AVR32_GOTPC 29
-+#define R_AVR32_GOTCALL 30
-+#define R_AVR32_LDA_GOT 31
-+#define R_AVR32_GOT21S 32
-+#define R_AVR32_GOT18SW 33
-+#define R_AVR32_GOT16S 34
-+#define R_AVR32_GOT7UW 35
-+#define R_AVR32_32_CPENT 36
-+#define R_AVR32_CPCALL 37
-+#define R_AVR32_16_CP 38
-+#define R_AVR32_9W_CP 39
-+#define R_AVR32_RELATIVE 40
-+#define R_AVR32_GLOB_DAT 41
-+#define R_AVR32_JMP_SLOT 42
-+#define R_AVR32_ALIGN 43
-+#define R_AVR32_NUM 44
-+
-+/* AVR32 dynamic tags */
-+#define DT_AVR32_GOTSZ 0x70000001 /* Total size of GOT in bytes */
-
- /* Renesas H8/300 Relocations */
- #define R_H8_NONE 0
-diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h
-index 32c5bf8..eb43bd9 100644
---- a/ldso/include/dl-string.h
-+++ b/ldso/include/dl-string.h
-@@ -285,7 +285,8 @@ static __always_inline char * _dl_simple_ltoahex(char * local, unsigned long i)
- /* 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(__mips__) || defined(__sh__) || defined(__powerpc__) || \
-+ defined(__avr32__)
- # define CONSTANT_STRING_GOT_FIXUP(X) \
- if ((X) < (const char *) load_addr) (X) += load_addr
- # define NO_EARLY_SEND_STDERR
-diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
-index b42416a..4404219 100644
---- a/ldso/include/dl-syscall.h
-+++ b/ldso/include/dl-syscall.h
-@@ -55,69 +55,69 @@
- 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 inline _syscall1(void, _dl_exit, int, status);
-+static __always_inline _syscall1(void, _dl_exit, int, status);
-
- #define __NR__dl_close __NR_close
--static inline _syscall1(int, _dl_close, int, fd);
-+static __always_inline _syscall1(int, _dl_close, int, fd);
-
- #define __NR__dl_open __NR_open
--static inline _syscall3(int, _dl_open, const char *, fn, int, flags,
-+static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags,
- __kernel_mode_t, mode);
-
- #define __NR__dl_write __NR_write
--static inline _syscall3(unsigned long, _dl_write, int, fd,
-+static __always_inline _syscall3(unsigned long, _dl_write, int, fd,
- const void *, buf, unsigned long, count);
-
- #define __NR__dl_read __NR_read
--static inline _syscall3(unsigned long, _dl_read, int, fd,
-+static __always_inline _syscall3(unsigned long, _dl_read, int, fd,
- const void *, buf, unsigned long, count);
-
- #define __NR__dl_mprotect __NR_mprotect
--static inline _syscall3(int, _dl_mprotect, const void *, addr,
-+static __always_inline _syscall3(int, _dl_mprotect, const void *, addr,
- unsigned long, len, int, prot);
-
- #define __NR__dl_stat __NR_stat
--static inline _syscall2(int, _dl_stat, const char *, file_name,
-+static __always_inline _syscall2(int, _dl_stat, const char *, file_name,
- struct stat *, buf);
-
- #define __NR__dl_fstat __NR_fstat
--static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
-+static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
-
- #define __NR__dl_munmap __NR_munmap
--static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
-+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 inline _syscall0(uid_t, _dl_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 inline _syscall0(uid_t, _dl_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 inline _syscall0(gid_t, _dl_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 inline _syscall0(gid_t, _dl_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 inline _syscall0(gid_t, _dl_getpid);
-+static __always_inline _syscall0(gid_t, _dl_getpid);
-
- #define __NR__dl_readlink __NR_readlink
--static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
-+static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
- size_t, bufsiz);
-
- #ifdef __UCLIBC_HAS_SSP__
-@@ -146,14 +146,14 @@ static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
- #if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
-
- # define __NR__dl_mmap __NR_mmap
--static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
-+static __always_inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
- int, prot, int, flags, int, fd, off_t, offset);
-
- /* then try mmap2() */
- #elif defined(__NR_mmap2)
-
- # define __NR___syscall_mmap2 __NR_mmap2
--static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
-+static __always_inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
- int, prot, int, flags, int, fd, off_t, offset);
-
- /* Some architectures always use 12 as page shift for mmap2() eventhough the
-@@ -164,7 +164,7 @@ static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
- # define MMAP2_PAGE_SHIFT 12
- #endif
-
--static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
-+static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
- int flags, int fd, unsigned long offset)
- {
- if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
-@@ -177,8 +177,8 @@ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
- #elif defined(__NR_mmap)
-
- # define __NR__dl_mmap_real __NR_mmap
--static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
--static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
-+static __always_inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
-+static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot,
- int flags, int fd, unsigned long offset)
- {
- unsigned long buffer[6];
-diff --git a/ldso/ldso/avr32/dl-debug.h b/ldso/ldso/avr32/dl-debug.h
-new file mode 100644
-index 0000000..fe35539
---- /dev/null
-+++ b/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 *_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/ldso/ldso/avr32/dl-startup.h b/ldso/ldso/avr32/dl-startup.h
-new file mode 100644
-index 0000000..3b9a641
---- /dev/null
-+++ b/ldso/ldso/avr32/dl-startup.h
-@@ -0,0 +1,112 @@
-+/*
-+ * 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 if 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(ELF32_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(ELF32_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);
-+ }
-+}
-+
-+/* Transfer control to the user's application, once the dynamic loader
-+ * is done. This routine has to exit the current function, then call
-+ * the _dl_elf_main function.
-+ *
-+ * Since our _dl_boot will simply call whatever is returned by
-+ * _dl_boot2, we can just return the address we're supposed to
-+ * call. */
-+#define START() return _dl_elf_main;
-diff --git a/ldso/ldso/avr32/dl-syscalls.h b/ldso/ldso/avr32/dl-syscalls.h
-new file mode 100644
-index 0000000..996bb87
---- /dev/null
-+++ b/ldso/ldso/avr32/dl-syscalls.h
-@@ -0,0 +1,6 @@
-+/* 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);}
-diff --git a/ldso/ldso/avr32/dl-sysdep.h b/ldso/ldso/avr32/dl-sysdep.h
-new file mode 100644
-index 0000000..1a30172
---- /dev/null
-+++ b/ldso/ldso/avr32/dl-sysdep.h
-@@ -0,0 +1,105 @@
-+/*
-+ * 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"
-+
-+unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
-+
-+/* 4096 bytes alignment */
-+#define PAGE_ALIGN 0xfffff000
-+#define ADDR_ALIGN 0xfff
-+#define OFFS_ALIGN 0x7ffff000
-+
-+#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 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 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 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/ldso/ldso/avr32/elfinterp.c b/ldso/ldso/avr32/elfinterp.c
-new file mode 100644
-index 0000000..196292b
---- /dev/null
-+++ b/ldso/ldso/avr32/elfinterp.c
-@@ -0,0 +1,191 @@
-+/*
-+ * 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)
-+{
-+ struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
-+ Elf32_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;
-+
-+#if 0
-+ local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
-+ gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
-+
-+ sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
-+ + sym_index;
-+ strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
-+ symname = strtab + sym->st_name;
-+
-+#if 0
-+ new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
-+ tpnt->symbol_scope, tpnt,
-+ resolver);
-+#endif
-+
-+ entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
-+ *entry = 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_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
-+ Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
-+{
-+ Elf32_Sym *symtab;
-+ Elf32_Rela *rpnt;
-+ char *strtab;
-+ int i;
-+
-+ rpnt = (Elf32_Rela *)rel_addr;
-+ rel_size /= sizeof(Elf32_Rela);
-+ symtab = (Elf32_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 = ELF32_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 = ELF32_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 dyn_elf *scope,
-+ Elf32_Rela *rpnt, Elf32_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
-+
-+ reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
-+ reloc_type = ELF32_R_TYPE(rpnt->r_info);
-+ symtab_index = ELF32_R_SYM(rpnt->r_info);
-+ symbol_addr = 0;
-+ symname = strtab + symtab[symtab_index].st_name;
-+
-+ if (symtab_index) {
-+ symbol_addr = (unsigned long)
-+ _dl_find_hash(strtab + symtab[symtab_index].st_name,
-+ tpnt->symbol_scope, tpnt,
-+ elf_machine_type_class(reloc_type));
-+
-+ /* Allow undefined references to weak symbols */
-+ if (!symbol_addr &&
-+ ELF32_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 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,
-+ unsigned long rel_addr,
-+ unsigned long rel_size)
-+{
-+ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
-+ _dl_do_reloc);
-+}
-diff --git a/ldso/ldso/avr32/resolve.S b/ldso/ldso/avr32/resolve.S
-new file mode 100644
-index 0000000..e3cb7f4
---- /dev/null
-+++ b/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/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
-index 5cf1d04..d4294ec 100644
---- a/ldso/ldso/dl-startup.c
-+++ b/ldso/ldso/dl-startup.c
-@@ -217,7 +217,9 @@ DL_START(unsigned long args)
- /* some arches (like MIPS) we have to tweak the GOT before relocations */
- PERFORM_BOOTSTRAP_GOT(tpnt);
-
--#else
-+#endif
-+
-+#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__)
-
- /* OK, now do the relocations. We do not do a lazy binding here, so
- that once we are done, we have considerably more flexibility. */
-diff --git a/libc/string/avr32/Makefile b/libc/string/avr32/Makefile
-new file mode 100644
-index 0000000..e19e9d9
---- /dev/null
-+++ b/libc/string/avr32/Makefile
-@@ -0,0 +1,26 @@
-+# Makefile for uClibc
-+#
-+# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
-+#
-+# This program is free software; you can redistribute it and/or modify it under
-+# the terms of the GNU Library General Public License as published by the Free
-+# Software Foundation; either version 2 of the License, or (at your option) any
-+# later version.
-+#
-+# This program is distributed in the hope that it will be useful, but WITHOUT
-+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
-+# details.
-+#
-+# You should have received a copy of the GNU Library General Public License
-+# along with this program; if not, write to the Free Software Foundation, Inc.,
-+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+
-+top_srcdir := ../../../
-+top_builddir := ../../../
-+
-+all: objs
-+
-+include $(top_builddir)Rules.mak
-+include ../Makefile.in
-+include $(top_srcdir)Makerules
-diff --git a/libc/string/avr32/bcopy.S b/libc/string/avr32/bcopy.S
-new file mode 100644
-index 0000000..87c1e04
---- /dev/null
-+++ b/libc/string/avr32/bcopy.S
-@@ -0,0 +1,26 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#include <features.h>
-+
-+#ifdef __UCLIBC_SUSV3_LEGACY__
-+
-+ .text
-+ .global bcopy
-+ .type bcopy, @function
-+ .align 1
-+bcopy:
-+ /* Swap the first two arguments */
-+ eor r11, r12
-+ eor r12, r11
-+ eor r11, r12
-+ rjmp __GI_memmove
-+
-+ .size bcopy, . - bcopy
-+
-+#endif /* __UCLIBC_SUSV3_LEGACY__ */
-diff --git a/libc/string/avr32/bzero.S b/libc/string/avr32/bzero.S
-new file mode 100644
-index 0000000..c999e65
---- /dev/null
-+++ b/libc/string/avr32/bzero.S
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#ifdef __UCLIBC_SUSV3_LEGACY__
-+
-+ .text
-+ .global bzero
-+ .type bzero, @function
-+ .align 1
-+bzero:
-+ mov r10, r11
-+ mov r11, 0
-+ rjmp __memset
-+
-+ .size bzero, . - bzero
-+
-+#endif /* __UCLIBC_SUSV3_LEGACY__ */
-diff --git a/libc/string/avr32/memcmp.S b/libc/string/avr32/memcmp.S
-new file mode 100644
-index 0000000..7359a64
---- /dev/null
-+++ b/libc/string/avr32/memcmp.S
-@@ -0,0 +1,58 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#include <features.h>
-+
-+#define s1 r12
-+#define s2 r11
-+#define len r10
-+
-+ .text
-+ .global memcmp
-+ .type memcmp, @function
-+ .align 1
-+memcmp:
-+ sub len, 4
-+ brlt .Lless_than_4
-+
-+1: ld.w r8, s1++
-+ ld.w r9, s2++
-+ cp.w r8, r9
-+ brne .Lfound_word
-+ sub len, 4
-+ brge 1b
-+
-+.Lless_than_4:
-+ sub len, -4
-+ reteq 0
-+
-+1: ld.ub r8, s1++
-+ ld.ub r9, s2++
-+ sub r8, r9
-+ retne r8
-+ sub len, 1
-+ brgt 1b
-+
-+ retal 0
-+
-+.Lfound_word:
-+ psub.b r9, r8, r9
-+ bfextu r8, r9, 24, 8
-+ retne r8
-+ bfextu r8, r9, 16, 8
-+ retne r8
-+ bfextu r8, r9, 8, 8
-+ retne r8
-+ retal r9
-+
-+ .size memcmp, . - memcmp
-+
-+libc_hidden_def(memcmp)
-+#ifdef __UCLIBC_SUSV3_LEGACY__
-+strong_alias(memcmp,bcmp)
-+#endif
-diff --git a/libc/string/avr32/memcpy.S b/libc/string/avr32/memcpy.S
-new file mode 100644
-index 0000000..bf091ab
---- /dev/null
-+++ b/libc/string/avr32/memcpy.S
-@@ -0,0 +1,111 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+/* Don't use r12 as dst since we must return it unmodified */
-+#define dst r9
-+#define src r11
-+#define len r10
-+
-+ .text
-+ .global memcpy
-+ .type memcpy, @function
-+memcpy:
-+ pref src[0]
-+ mov dst, r12
-+
-+ /* If we have less than 32 bytes, don't do anything fancy */
-+ cp.w len, 32
-+ brge .Lmore_than_31
-+
-+ sub len, 1
-+ retlt r12
-+1: ld.ub r8, src++
-+ st.b dst++, r8
-+ sub len, 1
-+ brge 1b
-+ retal r12
-+
-+.Lmore_than_31:
-+ pushm r0-r7, lr
-+
-+ /* Check alignment */
-+ mov r8, src
-+ andl r8, 31, COH
-+ brne .Lunaligned_src
-+ mov r8, dst
-+ andl r8, 3, COH
-+ brne .Lunaligned_dst
-+
-+.Laligned_copy:
-+ sub len, 32
-+ brlt .Lless_than_32
-+
-+1: /* Copy 32 bytes at a time */
-+ ldm src, r0-r7
-+ sub src, -32
-+ stm dst, r0-r7
-+ sub dst, -32
-+ sub len, 32
-+ brge 1b
-+
-+.Lless_than_32:
-+ /* Copy 16 more bytes if possible */
-+ sub len, -16
-+ brlt .Lless_than_16
-+ ldm src, r0-r3
-+ sub src, -16
-+ sub len, 16
-+ stm dst, r0-r3
-+ sub dst, -16
-+
-+.Lless_than_16:
-+ /* Do the remaining as byte copies */
-+ neg len
-+ add pc, pc, len << 2
-+ .rept 15
-+ ld.ub r0, src++
-+ st.b dst++, r0
-+ .endr
-+
-+ popm r0-r7, pc
-+
-+.Lunaligned_src:
-+ /* Make src cacheline-aligned. r8 = (src & 31) */
-+ rsub r8, r8, 32
-+ sub len, r8
-+1: ld.ub r0, src++
-+ st.b dst++, r0
-+ sub r8, 1
-+ brne 1b
-+
-+ /* If dst is word-aligned, we're ready to go */
-+ pref src[0]
-+ mov r8, 3
-+ tst dst, r8
-+ breq .Laligned_copy
-+
-+.Lunaligned_dst:
-+ /* src is aligned, but dst is not. Expect bad performance */
-+ sub len, 4
-+ brlt 2f
-+1: ld.w r0, src++
-+ st.w dst++, r0
-+ sub len, 4
-+ brge 1b
-+
-+2: neg len
-+ add pc, pc, len << 2
-+ .rept 3
-+ ld.ub r0, src++
-+ st.b dst++, r0
-+ .endr
-+
-+ popm r0-r7, pc
-+ .size memcpy, . - memcpy
-+
-+libc_hidden_def(memcpy)
-diff --git a/libc/string/avr32/memmove.S b/libc/string/avr32/memmove.S
-new file mode 100644
-index 0000000..98287c5
---- /dev/null
-+++ b/libc/string/avr32/memmove.S
-@@ -0,0 +1,116 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#define dst r12
-+#define src r11
-+#define len r10
-+
-+ .text
-+ .global memmove
-+ .type memmove, @function
-+memmove:
-+ cp.w src, dst
-+ brge __GI_memcpy
-+
-+ add dst, len
-+ add src, len
-+ pref src[-1]
-+
-+ /*
-+ * The rest is basically the same as in memcpy.S except that
-+ * the direction is reversed.
-+ */
-+ cp.w len, 32
-+ brge .Lmore_than_31
-+
-+ sub len, 1
-+ retlt r12
-+1: ld.ub r8, --src
-+ st.b --dst, r8
-+ sub len, 1
-+ brge 1b
-+ retal r12
-+
-+.Lmore_than_31:
-+ pushm r0-r7, lr
-+
-+ /* Check alignment */
-+ mov r8, src
-+ andl r8, 31, COH
-+ brne .Lunaligned_src
-+ mov r8, r12
-+ andl r8, 3, COH
-+ brne .Lunaligned_dst
-+
-+.Laligned_copy:
-+ sub len, 32
-+ brlt .Lless_than_32
-+
-+1: /* Copy 32 bytes at a time */
-+ sub src, 32
-+ ldm src, r0-r7
-+ sub dst, 32
-+ sub len, 32
-+ stm dst, r0-r7
-+ brge 1b
-+
-+.Lless_than_32:
-+ /* Copy 16 more bytes if possible */
-+ sub len, -16
-+ brlt .Lless_than_16
-+ sub src, 16
-+ ldm src, r0-r3
-+ sub dst, 16
-+ sub len, 16
-+ stm dst, r0-r3
-+
-+.Lless_than_16:
-+ /* Do the remaining as byte copies */
-+ sub len, -16
-+ breq 2f
-+1: ld.ub r0, --src
-+ st.b --dst, r0
-+ sub len, 1
-+ brne 1b
-+
-+2: popm r0-r7, pc
-+
-+.Lunaligned_src:
-+ /* Make src cacheline-aligned. r8 = (src & 31) */
-+ sub len, r8
-+1: ld.ub r0, --src
-+ st.b --dst, r0
-+ sub r8, 1
-+ brne 1b
-+
-+ /* If dst is word-aligned, we're ready to go */
-+ pref src[-4]
-+ mov r8, 3
-+ tst dst, r8
-+ breq .Laligned_copy
-+
-+.Lunaligned_dst:
-+ /* src is aligned, but dst is not. Expect bad performance */
-+ sub len, 4
-+ brlt 2f
-+1: ld.w r0, --src
-+ st.w --dst, r0
-+ sub len, 4
-+ brge 1b
-+
-+2: neg len
-+ add pc, pc, len << 2
-+ .rept 3
-+ ld.ub r0, --src
-+ st.b --dst, r0
-+ .endr
-+
-+ popm r0-r7, pc
-+ .size memmove, . - memmove
-+
-+libc_hidden_def(memmove)
-diff --git a/libc/string/avr32/memset.S b/libc/string/avr32/memset.S
-new file mode 100644
-index 0000000..33cfaed
---- /dev/null
-+++ b/libc/string/avr32/memset.S
-@@ -0,0 +1,70 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#include <features.h>
-+
-+#define s r12
-+#define c r11
-+#define n r10
-+
-+ .text
-+ .global memset
-+ .type memset, @function
-+
-+ .global __memset
-+ .hidden __memset
-+ .type __memset, @function
-+
-+ .align 1
-+memset:
-+__memset:
-+ cp.w n, 32
-+ mov r9, s
-+ brge .Llarge_memset
-+
-+ sub n, 1
-+ retlt s
-+1: st.b s++, c
-+ sub n, 1
-+ brge 1b
-+
-+ retal r9
-+
-+.Llarge_memset:
-+ mov r8, r11
-+ mov r11, 3
-+ bfins r8, r8, 8, 8
-+ bfins r8, r8, 16, 16
-+ tst s, r11
-+ breq 2f
-+
-+1: st.b s++, r8
-+ sub n, 1
-+ tst s, r11
-+ brne 1b
-+
-+2: mov r11, r9
-+ mov r9, r8
-+ sub n, 8
-+
-+3: st.d s++, r8
-+ sub n, 8
-+ brge 3b
-+
-+ /* If we are done, n == -8 and we'll skip all st.b insns below */
-+ neg n
-+ lsl n, 1
-+ add pc, n
-+ .rept 7
-+ st.b s++, r8
-+ .endr
-+ retal r11
-+
-+ .size memset, . - memset
-+
-+libc_hidden_def(memset)
-diff --git a/libc/string/avr32/strcmp.S b/libc/string/avr32/strcmp.S
-new file mode 100644
-index 0000000..f73bd43
---- /dev/null
-+++ b/libc/string/avr32/strcmp.S
-@@ -0,0 +1,91 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#include <features.h>
-+
-+#define s1 r12
-+#define s2 r11
-+#define len r10
-+
-+ .text
-+ .global strcmp
-+ .type strcmp, @function
-+ .align 1
-+strcmp:
-+ mov r8, 3
-+ tst s1, r8
-+ brne .Lunaligned_s1
-+ tst s2, r8
-+ brne .Lunaligned_s2
-+
-+1: ld.w r8, s1++
-+ ld.w r9, s2++
-+ cp.w r8, r9
-+ brne 2f
-+ tnbz r8
-+ brne 1b
-+ retal 0
-+
-+2: bfextu r12, r8, 24, 8
-+ bfextu r11, r9, 24, 8
-+ sub r12, r11
-+ retne r12
-+ cp.w r11, 0
-+ reteq 0
-+ bfextu r12, r8, 16, 8
-+ bfextu r11, r9, 16, 8
-+ sub r12, r11
-+ retne r12
-+ cp.w r11, 0
-+ reteq 0
-+ bfextu r12, r8, 8, 8
-+ bfextu r11, r9, 8, 8
-+ sub r12, r11
-+ retne r12
-+ cp.w r11, 0
-+ reteq 0
-+ bfextu r12, r8, 0, 8
-+ bfextu r11, r9, 0, 8
-+ sub r12, r11
-+ retal r12
-+
-+.Lunaligned_s1:
-+3: tst s1, r8
-+ breq 4f
-+ ld.ub r10, s1++
-+ ld.ub r9, s2++
-+ sub r10, r9
-+ retne r10
-+ cp.w r9, 0
-+ brne 3b
-+ retal r10
-+
-+4: tst s2, r8
-+ breq 1b
-+
-+.Lunaligned_s2:
-+ /*
-+ * s1 and s2 can't both be aligned, and unaligned word loads
-+ * can trigger spurious exceptions if we cross a page boundary.
-+ * Do it the slow way...
-+ */
-+1: ld.ub r8, s1++
-+ ld.ub r9, s2++
-+ sub r8, r9
-+ retne r8
-+ cp.w r9, 0
-+ brne 1b
-+ retal 0
-+
-+ .size strcmp, . - strcmp
-+
-+libc_hidden_def(strcmp)
-+#ifndef __UCLIBC_HAS_LOCALE__
-+strong_alias(strcmp, strcoll)
-+libc_hidden_def(strcoll)
-+#endif
-diff --git a/libc/string/avr32/strlen.S b/libc/string/avr32/strlen.S
-new file mode 100644
-index 0000000..5223e53
---- /dev/null
-+++ b/libc/string/avr32/strlen.S
-@@ -0,0 +1,62 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#include <features.h>
-+
-+#define str r12
-+
-+ .text
-+ .global strlen
-+ .type strlen, @function
-+strlen:
-+ mov r11, r12
-+
-+ mov r9, str
-+ andl r9, 3, COH
-+ brne .Lunaligned_str
-+
-+1: ld.w r8, str++
-+ tnbz r8
-+ brne 1b
-+
-+ sub r12, r11
-+ bfextu r9, r8, 24, 8
-+ cp.w r9, 0
-+ subeq r12, 4
-+ reteq r12
-+ bfextu r9, r8, 16, 8
-+ cp.w r9, 0
-+ subeq r12, 3
-+ reteq r12
-+ bfextu r9, r8, 8, 8
-+ cp.w r9, 0
-+ subeq r12, 2
-+ reteq r12
-+ sub r12, 1
-+ retal r12
-+
-+.Lunaligned_str:
-+ add pc, pc, r9 << 3
-+ sub r0, r0, 0 /* 4-byte nop */
-+ ld.ub r8, str++
-+ sub r8, r8, 0
-+ breq 1f
-+ ld.ub r8, str++
-+ sub r8, r8, 0
-+ breq 1f
-+ ld.ub r8, str++
-+ sub r8, r8, 0
-+ brne 1b
-+
-+1: sub r12, 1
-+ sub r12, r11
-+ retal r12
-+
-+ .size strlen, . - strlen
-+
-+libc_hidden_def(strlen)
-diff --git a/libc/sysdeps/linux/avr32/Makefile b/libc/sysdeps/linux/avr32/Makefile
-new file mode 100644
-index 0000000..338abc0
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/Makefile
-@@ -0,0 +1,25 @@
-+# Makefile for uClibc
-+#
-+# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
-+#
-+# This program is free software; you can redistribute it and/or modify it under
-+# the terms of the GNU Library General Public License as published by the Free
-+# Software Foundation; either version 2 of the License, or (at your option) any
-+# later version.
-+#
-+# This program is distributed in the hope that it will be useful, but WITHOUT
-+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
-+# details.
-+#
-+# You should have received a copy of the GNU Library General Public License
-+# along with this program; if not, write to the Free Software Foundation, Inc.,
-+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+
-+top_srcdir=../../../../
-+top_builddir=../../../../
-+all: objs
-+
-+include $(top_builddir)Rules.mak
-+include Makefile.arch
-+include $(top_srcdir)Makerules
-diff --git a/libc/sysdeps/linux/avr32/Makefile.arch b/libc/sysdeps/linux/avr32/Makefile.arch
-new file mode 100644
-index 0000000..44fc01e
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/Makefile.arch
-@@ -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.
-+#
-+
-+CSRC := brk.c clone.c mmap.c sigaction.c
-+
-+SSRC := __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \
-+ sigrestorer.S syscall.S vfork.S
-+
-+include $(top_srcdir)/libc/sysdeps/linux/Makefile.commonarch
-diff --git a/libc/sysdeps/linux/avr32/__longjmp.S b/libc/sysdeps/linux/avr32/__longjmp.S
-new file mode 100644
-index 0000000..6154bb2
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/__longjmp.S
-@@ -0,0 +1,21 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+ .global __longjmp
-+ .type __longjmp,"function"
-+ .align 1
-+__longjmp:
-+ ldm r12++, r0-r8,sp,lr
-+ mustr r8 /* restore status register (lower half) */
-+ cp r11, 0 /* can't return zero */
-+ frs
-+ moveq r11, 1
-+ retal r11
-+ .size __longjmp, . - __longjmp
-+
-+libc_hidden_def(__longjmp)
-diff --git a/libc/sysdeps/linux/avr32/bits/atomic.h b/libc/sysdeps/linux/avr32/bits/atomic.h
-new file mode 100644
-index 0000000..e6be41f
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/atomic.h
-@@ -0,0 +1,120 @@
-+/*
-+ * Copyright (C) 2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#ifndef _AVR32_BITS_ATOMIC_H
-+#define _AVR32_BITS_ATOMIC_H 1
-+
-+#include <inttypes.h>
-+
-+typedef int32_t atomic32_t;
-+typedef uint32_t uatomic32_t;
-+typedef int_fast32_t atomic_fast32_t;
-+typedef uint_fast32_t uatomic_fast32_t;
-+
-+typedef intptr_t atomicptr_t;
-+typedef uintptr_t uatomicptr_t;
-+typedef intmax_t atomic_max_t;
-+typedef uintmax_t uatomic_max_t;
-+
-+#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
-+ (abort(), 0)
-+
-+#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
-+ (abort(), 0)
-+
-+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
-+ ({ \
-+ __typeof__(*(mem)) __prev; \
-+ __asm__ __volatile__( \
-+ "/* __arch_compare_and_exchange_val_32_acq */\n" \
-+ "1: ssrf 5\n" \
-+ " ld.w %[result], %[m]\n" \
-+ " cp.w %[result], %[old]\n" \
-+ " brne 2f\n" \
-+ " stcond %[m], %[new]\n" \
-+ " brne 1b\n" \
-+ "2:" \
-+ : [result] "=&r"(__result), [m] "=m"(*(mem)) \
-+ : "m"(*(mem)), [old] "ir"(oldval), \
-+ [new] "r"(newval) \
-+ : "memory", "cc"); \
-+ __prev; \
-+ })
-+
-+#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
-+ (abort(), 0)
-+
-+#define __arch_exchange_32_acq(mem, newval) \
-+ ({ \
-+ __typeof__(*(mem)) __oldval; \
-+ __asm__ __volatile__( \
-+ "/*__arch_exchange_32_acq */\n" \
-+ " xchg %[old], %[m], %[new]" \
-+ : [old] "=&r"(__oldval) \
-+ : [m] "r"(mem), [new] "r"(newval) \
-+ : "memory"); \
-+ __oldval; \
-+ })
-+
-+#define __arch_atomic_exchange_and_add_32(mem, value) \
-+ ({ \
-+ __typeof__(*(mem)) __oldval, __tmp; \
-+ __asm__ __volatile__( \
-+ "/* __arch_atomic_exchange_and_add_32 */\n" \
-+ "1: ssrf 5\n" \
-+ " ld.w %[old], %[m]\n" \
-+ " add %[tmp], %[old], %[val]\n" \
-+ " stcond %[m], %[tmp]\n" \
-+ " brne 1b" \
-+ : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \
-+ [m] "=m"(*(mem)) \
-+ : "m"(*(mem)), [val] "r"(value) \
-+ : "memory", "cc"); \
-+ __oldval; \
-+ })
-+
-+#define __arch_atomic_decrement_if_positive_32(mem) \
-+ ({ \
-+ __typeof__(*(mem)) __oldval, __tmp; \
-+ __asm__ __volatile__( \
-+ "/* __arch_atomic_decrement_if_positive_32 */\n" \
-+ "1: ssrf 5\n" \
-+ " ld.w %[old], %[m]\n" \
-+ " sub %[tmp], %[old], 1\n" \
-+ " brlt 2f\n" \
-+ " stcond %[m], %[tmp]\n" \
-+ " brne 1b" \
-+ "2:" \
-+ : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \
-+ [m] "=m"(*(mem)) \
-+ : "m"(*(mem)) \
-+ : "memory", "cc"); \
-+ __oldval; \
-+ })
-+
-+#define atomic_exchange_acq(mem, newval) \
-+ ({ \
-+ if (sizeof(*(mem)) != 4) \
-+ abort(); \
-+ __arch_exchange_32_acq(mem, newval); \
-+ })
-+
-+#define atomic_exchange_and_add(mem, newval) \
-+ ({ \
-+ if (sizeof(*(mem)) != 4) \
-+ abort(); \
-+ __arch_atomic_exchange_and_add_32(mem, newval); \
-+ })
-+
-+#define atomic_decrement_if_positive(mem) \
-+ ({ \
-+ if (sizeof(*(mem)) != 4) \
-+ abort(); \
-+ __arch_atomic_decrement_if_positive_32(mem); \
-+ })
-+
-+#endif /* _AVR32_BITS_ATOMIC_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/byteswap.h b/libc/sysdeps/linux/avr32/bits/byteswap.h
-new file mode 100644
-index 0000000..1c030b9
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/byteswap.h
-@@ -0,0 +1,70 @@
-+/*
-+ * Copyright (C) 2005 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#if !defined _BYTESWAP_H && !defined _NETINET_IN_H
-+# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
-+#endif
-+
-+#ifndef _BITS_BYTESWAP_H
-+#define _BITS_BYTESWAP_H 1
-+
-+/* Swap bytes in 16 bit value. */
-+#if defined __GNUC__
-+# define __bswap_16(x) (__extension__ __builtin_bswap_16(x))
-+#else
-+/* This is better than nothing. */
-+static __inline unsigned short int
-+__bswap_16 (unsigned short int __bsx)
-+{
-+ return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
-+}
-+#endif
-+
-+/* Swap bytes in 32 bit value. */
-+#if defined __GNUC__
-+# define __bswap_32(x) (__extension__ __builtin_bswap_32(x))
-+#else
-+static __inline unsigned int
-+__bswap_32 (unsigned int __bsx)
-+{
-+ return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
-+ (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));
-+}
-+#endif
-+
-+#if defined __GNUC__
-+/* Swap bytes in 64 bit value. */
-+# define __bswap_constant_64(x) \
-+ ((((x) & 0xff00000000000000ull) >> 56) \
-+ | (((x) & 0x00ff000000000000ull) >> 40) \
-+ | (((x) & 0x0000ff0000000000ull) >> 24) \
-+ | (((x) & 0x000000ff00000000ull) >> 8) \
-+ | (((x) & 0x00000000ff000000ull) << 8) \
-+ | (((x) & 0x0000000000ff0000ull) << 24) \
-+ | (((x) & 0x000000000000ff00ull) << 40) \
-+ | (((x) & 0x00000000000000ffull) << 56))
-+
-+# define __bswap_64(x) \
-+ (__extension__ \
-+ ({ \
-+ union { \
-+ __extension__ unsigned long long int __ll; \
-+ unsigned int __l[2]; \
-+ } __w, __r; \
-+ if (__builtin_constant_p(x)) \
-+ __r.__ll = __bswap_constant_64(x); \
-+ else { \
-+ __w.__ll = (x); \
-+ __r.__l[0] = __bswap_32(__w.__l[1]); \
-+ __r.__l[1] = __bswap_32(__w.__l[0]); \
-+ } \
-+ __r.__ll; \
-+ }))
-+#endif
-+
-+#endif /* _BITS_BYTESWAP_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/endian.h b/libc/sysdeps/linux/avr32/bits/endian.h
-new file mode 100644
-index 0000000..7bb6358
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/endian.h
-@@ -0,0 +1,7 @@
-+/* AVR32 is big-endian */
-+
-+#ifndef _ENDIAN_H
-+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
-+#endif
-+
-+#define __BYTE_ORDER __BIG_ENDIAN
-diff --git a/libc/sysdeps/linux/avr32/bits/fcntl.h b/libc/sysdeps/linux/avr32/bits/fcntl.h
-new file mode 100644
-index 0000000..1abff17
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/fcntl.h
-@@ -0,0 +1,165 @@
-+#ifndef _FCNTL_H
-+# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
-+#endif
-+
-+#include <sys/types.h>
-+
-+/*
-+ * open/fcntl - O_SYNC is only implemented on blocks devices and on files
-+ * located on an ext2 file system
-+ */
-+#define O_ACCMODE 00000003
-+#define O_RDONLY 00000000
-+#define O_WRONLY 00000001
-+#define O_RDWR 00000002
-+#define O_CREAT 00000100 /* not fcntl */
-+#define O_EXCL 00000200 /* not fcntl */
-+#define O_NOCTTY 00000400 /* not fcntl */
-+#define O_TRUNC 00001000 /* not fcntl */
-+#define O_APPEND 00002000
-+#define O_NONBLOCK 00004000
-+#define O_NDELAY O_NONBLOCK
-+#define O_SYNC 00010000
-+#define O_ASYNC 00020000
-+
-+#ifdef __USE_GNU
-+# define O_DIRECT 00040000 /* must be a directory */
-+# define O_DIRECTORY 00200000 /* direct disk access */
-+# define O_NOFOLLOW 00400000 /* don't follow links */
-+# define O_NOATIME 01000000 /* don't set atime */
-+#endif
-+
-+#ifdef __USE_LARGEFILE64
-+# define O_LARGEFILE 00100000
-+#endif
-+
-+/* For now Linux has synchronisity options for data and read operations.
-+ We define the symbols here but let them do the same as O_SYNC since
-+ this is a superset. */
-+#if defined __USE_POSIX199309 || defined __USE_UNIX98
-+# define O_DSYNC O_SYNC /* Synchronize data. */
-+# define O_RSYNC O_SYNC /* Synchronize read operations. */
-+#endif
-+
-+#define F_DUPFD 0 /* dup */
-+#define F_GETFD 1 /* get close_on_exec */
-+#define F_SETFD 2 /* set/clear close_on_exec */
-+#define F_GETFL 3 /* get file->f_flags */
-+#define F_SETFL 4 /* set file->f_flags */
-+
-+#ifndef __USE_FILE_OFFSET64
-+# define F_GETLK 5
-+# define F_SETLK 6
-+# define F_SETLKW 7
-+#else
-+# define F_GETLK F_GETLK64
-+# define F_SETLK F_SETLK64
-+# define F_SETLKW F_SETLKW64
-+#endif
-+#define F_GETLK64 12 /* using 'struct flock64' */
-+#define F_SETLK64 13
-+#define F_SETLKW64 14
-+
-+#if defined __USE_BSD || defined __USE_XOPEN2K
-+# define F_SETOWN 8 /* for sockets. */
-+# define F_GETOWN 9 /* for sockets. */
-+#endif
-+
-+#ifdef __USE_GNU
-+# define F_SETSIG 10 /* for sockets. */
-+# define F_GETSIG 11 /* for sockets. */
-+#endif
-+
-+#ifdef __USE_GNU
-+# define F_SETLEASE 1024 /* Set a lease. */
-+# define F_GETLEASE 1025 /* Enquire what lease is active. */
-+# define F_NOTIFY 1026 /* Request notfications on a directory. */
-+#endif
-+
-+/* for F_[GET|SET]FL */
-+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-+
-+/* for posix fcntl() and lockf() */
-+#define F_RDLCK 0
-+#define F_WRLCK 1
-+#define F_UNLCK 2
-+
-+/* for old implementation of bsd flock () */
-+#define F_EXLCK 4 /* or 3 */
-+#define F_SHLCK 8 /* or 4 */
-+
-+/* for leases */
-+#define F_INPROGRESS 16
-+
-+#ifdef __USE_BSD
-+/* operations for bsd flock(), also used by the kernel implementation */
-+# define LOCK_SH 1 /* shared lock */
-+# define LOCK_EX 2 /* exclusive lock */
-+# define LOCK_NB 4 /* or'd with one of the above to prevent
-+ blocking */
-+# define LOCK_UN 8 /* remove lock */
-+#endif
-+
-+#ifdef __USE_GNU
-+# define LOCK_MAND 32 /* This is a mandatory flock */
-+# define LOCK_READ 64 /* ... Which allows concurrent
-+ read operations */
-+# define LOCK_WRITE 128 /* ... Which allows concurrent
-+ write operations */
-+# define LOCK_RW 192 /* ... Which allows concurrent
-+ read & write ops */
-+#endif
-+
-+#ifdef __USE_GNU
-+/* Types of directory notifications that may be requested with F_NOTIFY. */
-+# define DN_ACCESS 0x00000001 /* File accessed. */
-+# define DN_MODIFY 0x00000002 /* File modified. */
-+# define DN_CREATE 0x00000004 /* File created. */
-+# define DN_DELETE 0x00000008 /* File removed. */
-+# define DN_RENAME 0x00000010 /* File renamed. */
-+# define DN_ATTRIB 0x00000020 /* File changed attibutes. */
-+# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */
-+#endif
-+
-+struct flock {
-+ short l_type;
-+ short l_whence;
-+#ifndef __USE_FILE_OFFSET64
-+ __off_t l_start;
-+ __off_t l_len;
-+#else
-+ __off64_t l_start;
-+ __off64_t l_len;
-+#endif
-+ __pid_t l_pid;
-+};
-+
-+#ifdef __USE_LARGEFILE64
-+struct flock64 {
-+ short l_type;
-+ short l_whence;
-+ __off64_t l_start;
-+ __off64_t l_len;
-+ __pid_t l_pid;
-+};
-+#endif
-+
-+/* Define some more compatibility macros to be backward compatible with
-+ * BSD systems which did not managed to hide these kernel macros. */
-+#ifdef __USE_BSD
-+# define FAPPEND O_APPEND
-+# define FFSYNC O_FSYNC
-+# define FASYNC O_ASYNC
-+# define FNONBLOCK O_NONBLOCK
-+# define FNDELAY O_NDELAY
-+#endif /* Use BSD. */
-+
-+/* Advise to `posix_fadvise'. */
-+#ifdef __USE_XOPEN2K
-+# define POSIX_FADV_NORMAL 0 /* No further special treatment. */
-+# define POSIX_FADV_RANDOM 1 /* Expect random page references. */
-+# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */
-+# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */
-+# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
-+# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
-+#endif
-diff --git a/libc/sysdeps/linux/avr32/bits/kernel_stat.h b/libc/sysdeps/linux/avr32/bits/kernel_stat.h
-new file mode 100644
-index 0000000..f97d23b
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/kernel_stat.h
-@@ -0,0 +1,67 @@
-+#ifndef _BITS_STAT_STRUCT_H
-+#define _BITS_STAT_STRUCT_H
-+
-+#ifndef _LIBC
-+#error bits/kernel_stat.h is for internal uClibc use only!
-+#endif
-+
-+/*
-+ * This file provides struct stat, taken from kernel 2.6.4. Verified
-+ * to match kernel 2.6.22.
-+ */
-+
-+struct kernel_stat {
-+ unsigned long st_dev;
-+ unsigned long st_ino;
-+ unsigned short st_mode;
-+ unsigned short st_nlink;
-+ unsigned short st_uid;
-+ unsigned short st_gid;
-+ unsigned long st_rdev;
-+ unsigned long st_size;
-+ unsigned long st_blksize;
-+ unsigned long st_blocks;
-+ unsigned long st_atime;
-+ unsigned long st_atime_nsec;
-+ unsigned long st_mtime;
-+ unsigned long st_mtime_nsec;
-+ unsigned long st_ctime;
-+ unsigned long st_ctime_nsec;
-+ unsigned long __unused4;
-+ unsigned long __unused5;
-+};
-+
-+#define STAT_HAVE_NSEC 1
-+
-+struct kernel_stat64 {
-+ unsigned long long st_dev;
-+
-+ unsigned long long st_ino;
-+ unsigned int st_mode;
-+ unsigned int st_nlink;
-+
-+ unsigned long st_uid;
-+ unsigned long st_gid;
-+
-+ unsigned long long st_rdev;
-+
-+ long long st_size;
-+ unsigned long __pad1;
-+ unsigned long st_blksize;
-+
-+ unsigned long long st_blocks;
-+
-+ unsigned long st_atime;
-+ unsigned long st_atime_nsec;
-+
-+ unsigned long st_mtime;
-+ unsigned long st_mtime_nsec;
-+
-+ unsigned long st_ctime;
-+ unsigned long st_ctime_nsec;
-+
-+ unsigned long __unused1;
-+ unsigned long __unused2;
-+};
-+
-+#endif /* _BITS_STAT_STRUCT_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/kernel_types.h b/libc/sysdeps/linux/avr32/bits/kernel_types.h
-new file mode 100644
-index 0000000..f7d8b52
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/kernel_types.h
-@@ -0,0 +1,55 @@
-+/* Note that we use the exact same include guard #define names
-+ * as asm/posix_types.h. This will avoid gratuitous conflicts
-+ * with the posix_types.h kernel header, and will ensure that
-+ * our private content, and not the kernel header, will win.
-+ * -Erik
-+ */
-+#ifndef __ASM_AVR32_POSIX_TYPES_H
-+#define __ASM_AVR32_POSIX_TYPES_H
-+
-+/*
-+ * This file is generally used by user-level software, so you need to
-+ * be a little careful about namespace pollution etc. Also, we cannot
-+ * assume GCC is being used.
-+ */
-+
-+typedef unsigned long __kernel_dev_t;
-+typedef unsigned long __kernel_ino_t;
-+typedef unsigned short __kernel_mode_t;
-+typedef unsigned short __kernel_nlink_t;
-+typedef long __kernel_off_t;
-+typedef int __kernel_pid_t;
-+typedef unsigned short __kernel_ipc_pid_t;
-+typedef unsigned int __kernel_uid_t;
-+typedef unsigned int __kernel_gid_t;
-+typedef unsigned long __kernel_size_t;
-+typedef long __kernel_ssize_t;
-+typedef int __kernel_ptrdiff_t;
-+typedef long __kernel_time_t;
-+typedef long __kernel_suseconds_t;
-+typedef long __kernel_clock_t;
-+typedef int __kernel_timer_t;
-+typedef int __kernel_clockid_t;
-+typedef int __kernel_daddr_t;
-+typedef char * __kernel_caddr_t;
-+typedef unsigned short __kernel_uid16_t;
-+typedef unsigned short __kernel_gid16_t;
-+typedef unsigned int __kernel_uid32_t;
-+typedef unsigned int __kernel_gid32_t;
-+typedef unsigned short __kernel_old_uid_t;
-+typedef unsigned short __kernel_old_gid_t;
-+typedef unsigned short __kernel_old_dev_t;
-+
-+#ifdef __GNUC__
-+typedef long long __kernel_loff_t;
-+#endif
-+
-+typedef struct {
-+#if defined(__USE_ALL)
-+ int val[2];
-+#else
-+ int __val[2];
-+#endif
-+} __kernel_fsid_t;
-+
-+#endif /* __ASM_AVR32_POSIX_TYPES_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/mman.h b/libc/sysdeps/linux/avr32/bits/mman.h
-new file mode 100644
-index 0000000..5f6e3c3
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/mman.h
-@@ -0,0 +1,103 @@
-+/* Definitions for POSIX memory map interface. Linux/AVR32 version.
-+ Copyright (C) 1997, 2000 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., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+#ifndef _SYS_MMAN_H
-+# error "Never include this file directly. Use <sys/mman.h> instead"
-+#endif
-+
-+/* The following definitions basically come from the kernel headers.
-+ But the kernel header is not namespace clean. */
-+
-+
-+/* Protections are chosen from these bits, OR'd together. The
-+ implementation does not necessarily support PROT_EXEC or PROT_WRITE
-+ without PROT_READ. The only guarantees are that no writing will be
-+ allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
-+
-+#define PROT_READ 0x1 /* Page can be read. */
-+#define PROT_WRITE 0x2 /* Page can be written. */
-+#define PROT_EXEC 0x4 /* Page can be executed. */
-+#define PROT_NONE 0x0 /* Page can not be accessed. */
-+#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of
-+ growsdown vma (mprotect only). */
-+#define PROT_GROWSUP 0x02000000 /* Extend change to start of
-+ growsup vma (mprotect only). */
-+
-+/* Sharing types (must choose one and only one of these). */
-+#define MAP_SHARED 0x01 /* Share changes. */
-+#define MAP_PRIVATE 0x02 /* Changes are private. */
-+#ifdef __USE_MISC
-+# define MAP_TYPE 0x0f /* Mask for type of mapping. */
-+#endif
-+
-+/* Other flags. */
-+#define MAP_FIXED 0x10 /* Interpret addr exactly. */
-+#ifdef __USE_MISC
-+# define MAP_FILE 0
-+# define MAP_ANONYMOUS 0x20 /* Don't use a file. */
-+# define MAP_ANON MAP_ANONYMOUS
-+#endif
-+
-+/* These are Linux-specific. */
-+#ifdef __USE_MISC
-+# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */
-+# define MAP_DENYWRITE 0x0800 /* ETXTBSY */
-+# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */
-+# define MAP_LOCKED 0x2000 /* Lock the mapping. */
-+# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */
-+# define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
-+# define MAP_NONBLOCK 0x10000 /* do not block on IO */
-+#endif
-+
-+/* Flags to `msync'. */
-+#define MS_ASYNC 1 /* Sync memory asynchronously. */
-+#define MS_SYNC 4 /* Synchronous memory sync. */
-+#define MS_INVALIDATE 2 /* Invalidate the caches. */
-+
-+/* Flags for `mlockall'. */
-+#define MCL_CURRENT 1 /* Lock all currently mapped pages. */
-+#define MCL_FUTURE 2 /* Lock all additions to address
-+ space. */
-+
-+/* Flags for `mremap'. */
-+#ifdef __USE_GNU
-+# define MREMAP_MAYMOVE 1
-+# define MREMAP_FIXED 2
-+#endif
-+
-+/* Advise to `madvise'. */
-+#ifdef __USE_BSD
-+# define MADV_NORMAL 0 /* No further special treatment. */
-+# define MADV_RANDOM 1 /* Expect random page references. */
-+# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
-+# define MADV_WILLNEED 3 /* Will need these pages. */
-+# define MADV_DONTNEED 4 /* Don't need these pages. */
-+# define MADV_REMOVE 9 /* Remove these pages and resources. */
-+# define MADV_DONTFORK 10 /* Do not inherit across fork. */
-+# define MADV_DOFORK 11 /* Do inherit across fork. */
-+#endif
-+
-+/* The POSIX people had to invent similar names for the same things. */
-+#ifdef __USE_XOPEN2K
-+# define POSIX_MADV_NORMAL 0 /* No further special treatment. */
-+# define POSIX_MADV_RANDOM 1 /* Expect random page references. */
-+# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */
-+# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */
-+# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */
-+#endif
-diff --git a/libc/sysdeps/linux/avr32/bits/setjmp.h b/libc/sysdeps/linux/avr32/bits/setjmp.h
-new file mode 100644
-index 0000000..78348a3
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/setjmp.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2004-2005 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#ifndef _BITS_SETJMP_H
-+#define _BITS_SETJMP_H 1
-+
-+#if !defined _SETJMP_H && !defined _PTHREAD_H
-+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
-+#endif
-+
-+#ifndef _ASM
-+/*
-+ * The jump buffer contains r0-r7, sr, sp and lr. Other registers are
-+ * not saved.
-+ */
-+typedef int __jmp_buf[11];
-+#endif
-+
-+#define __JMP_BUF_SP 4
-+
-+/* Test if longjmp to JMPBUF would unwind the frame containing a local
-+ variable at ADDRESS. */
-+#define _JMPBUF_UNWINDS(jmpbuf, address) \
-+ ((void *)(address) < (void *)(jmpbuf[__JMP_BUF_SP]))
-+
-+#endif /* _BITS_SETJMP_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/stackinfo.h b/libc/sysdeps/linux/avr32/bits/stackinfo.h
-new file mode 100644
-index 0000000..29b8452
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/stackinfo.h
-@@ -0,0 +1,28 @@
-+/* Copyright (C) 1999 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., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+/* This file contains a bit of information about the stack allocation
-+ of the processor. */
-+
-+#ifndef _STACKINFO_H
-+#define _STACKINFO_H 1
-+
-+/* On AVR32 the stack grows down. */
-+#define _STACK_GROWS_DOWN 1
-+
-+#endif /* stackinfo.h */
-diff --git a/libc/sysdeps/linux/avr32/bits/syscalls.h b/libc/sysdeps/linux/avr32/bits/syscalls.h
-new file mode 100644
-index 0000000..22ac059
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/syscalls.h
-@@ -0,0 +1,143 @@
-+#ifndef _BITS_SYSCALLS_H
-+#define _BITS_SYSCALLS_H
-+#ifndef _SYSCALL_H
-+# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
-+#endif
-+
-+/*
-+ * This includes the `__NR_<name>' syscall numbers taken from the
-+ * Linux kernel header files. It also defines the traditional
-+ * `SYS_<name>' macros for older programs.
-+ */
-+#include <bits/sysnum.h>
-+
-+#ifndef __ASSEMBLER__
-+
-+#include <errno.h>
-+
-+#define SYS_ify(syscall_name) (__NR_##syscall_name)
-+
-+#undef _syscall0
-+#define _syscall0(type,name) \
-+ type name(void) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 0)); \
-+ }
-+
-+#undef _syscall1
-+#define _syscall1(type,name,type1,arg1) \
-+ type name(type1 arg1) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 1, arg1)); \
-+ }
-+
-+#undef _syscall2
-+#define _syscall2(type,name,type1,arg1,type2,arg2) \
-+ type name(type1 arg1, type2 arg2) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 2, arg1, arg2)); \
-+ }
-+
-+#undef _syscall3
-+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-+ type name(type1 arg1, type2 arg2, type3 arg3) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 3, arg1, \
-+ arg2, arg3)); \
-+ }
-+
-+#undef _syscall4
-+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3, \
-+ type4,arg4) \
-+ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 4, arg1, arg2, \
-+ arg3, arg4)); \
-+ }
-+
-+#undef _syscall5
-+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3, \
-+ type4,arg4,type5,arg5) \
-+ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
-+ type5 arg5) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 5, arg1, arg2, \
-+ arg3, arg4, arg5)); \
-+ }
-+
-+#undef _syscall6
-+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3, \
-+ type4,arg4,type5,arg5,type6,arg6) \
-+ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
-+ type5 arg5, type6 arg6) \
-+ { \
-+ return (type)(INLINE_SYSCALL(name, 6, arg1, arg2, arg3, \
-+ arg4, arg5, arg6)); \
-+ }
-+
-+#undef unlikely
-+#define unlikely(x) __builtin_expect((x), 0)
-+
-+#undef INLINE_SYSCALL
-+#define INLINE_SYSCALL(name, nr, args...) \
-+ ({ \
-+ unsigned _sys_result = INTERNAL_SYSCALL(name, , nr, args); \
-+ if (unlikely(INTERNAL_SYSCALL_ERROR_P(_sys_result, ))) { \
-+ __set_errno(INTERNAL_SYSCALL_ERRNO(_sys_result, )); \
-+ _sys_result = (unsigned int) -1; \
-+ } \
-+ (int) _sys_result; \
-+ })
-+
-+#undef INTERNAL_SYSCALL_DECL
-+#define INTERNAL_SYSCALL_DECL(err) do { } while(0)
-+
-+#undef INTERNAL_SYSCALL
-+#define INTERNAL_SYSCALL(name, err, nr, args...) \
-+ ({ \
-+ register int _a1 asm ("r12"); \
-+ register int _scno asm("r8") = SYS_ify(name); \
-+ LOAD_ARGS_##nr (args); \
-+ asm volatile ("scall /* syscall " #name " */" \
-+ : "=r" (_a1) \
-+ : "r"(_scno) ASM_ARGS_##nr \
-+ : "cc", "memory"); \
-+ _a1; \
-+ })
-+
-+#undef INTERNAL_SYSCALL_ERROR_P
-+#define INTERNAL_SYSCALL_ERROR_P(val, err) \
-+ ((unsigned int)(val) >= 0xfffff001U)
-+
-+#undef INTERNAL_SYSCALL_ERRNO
-+#define INTERNAL_SYSCALL_ERRNO(val, errr) (-(val))
-+
-+#define LOAD_ARGS_0() do { } while(0)
-+#define ASM_ARGS_0
-+#define LOAD_ARGS_1(a1) \
-+ _a1 = (int) (a1); \
-+ LOAD_ARGS_0()
-+#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a1)
-+#define LOAD_ARGS_2(a1, a2) \
-+ register int _a2 asm("r11") = (int)(a2); \
-+ LOAD_ARGS_1(a1)
-+#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a2)
-+#define LOAD_ARGS_3(a1, a2, a3) \
-+ register int _a3 asm("r10") = (int)(a3); \
-+ LOAD_ARGS_2(a1, a2)
-+#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a3)
-+#define LOAD_ARGS_4(a1, a2, a3, a4) \
-+ register int _a4 asm("r9") = (int)(a4); \
-+ LOAD_ARGS_3(a1, a2, a3)
-+#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a4)
-+#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
-+ register int _a5 asm("r5") = (int)(a5); \
-+ LOAD_ARGS_4(a1, a2, a3, a4)
-+#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a5)
-+#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
-+ register int _a6 asm("r3") = (int)(a6); \
-+ LOAD_ARGS_5(a1, a2, a3, a4, a5)
-+#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a6)
-+
-+#endif /* __ASSEMBLER__ */
-+#endif /* _BITS_SYSCALLS_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h b/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h
-new file mode 100644
-index 0000000..e95e8a5
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h
-@@ -0,0 +1,45 @@
-+/*
-+ * Track misc arch-specific features that aren't config options
-+ */
-+
-+#ifndef _BITS_UCLIBC_ARCH_FEATURES_H
-+#define _BITS_UCLIBC_ARCH_FEATURES_H
-+
-+/* instruction used when calling abort() to kill yourself */
-+/* trigger illegal instruction exception, same as BUG in Linux */
-+#define __UCLIBC_ABORT_INSTRUCTION__ ".short 0x5df0"
-+
-+/* can your target use syscall6() for mmap ? */
-+#define __UCLIBC_MMAP_HAS_6_ARGS__
-+
-+/* does your target use syscall4() for truncate64 ? (32bit arches only) */
-+#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
-+
-+/* does your target have a broken create_module() ? */
-+#undef __UCLIBC_BROKEN_CREATE_MODULE__
-+
-+/* does your target have to worry about older [gs]etrlimit() ? */
-+#undef __UCLIBC_HANDLE_OLDER_RLIMIT__
-+
-+/* does your target prefix all symbols with an _ ? */
-+#define __UCLIBC_NO_UNDERSCORES__
-+
-+/* does your target have an asm .set ? */
-+#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
-+
-+/* define if target doesn't like .global */
-+#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__
-+
-+/* define if target supports .weak */
-+#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__
-+
-+/* define if target supports .weakext */
-+#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__
-+
-+/* needed probably only for ppc64 */
-+#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__
-+
-+/* define if target supports IEEE signed zero floats */
-+#define __UCLIBC_HAVE_SIGNED_ZERO__
-+
-+#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */
-diff --git a/libc/sysdeps/linux/avr32/bits/wordsize.h b/libc/sysdeps/linux/avr32/bits/wordsize.h
-new file mode 100644
-index 0000000..1b5842a
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bits/wordsize.h
-@@ -0,0 +1 @@
-+#define __WORDSIZE 32
-diff --git a/libc/sysdeps/linux/avr32/brk.c b/libc/sysdeps/linux/avr32/brk.c
-new file mode 100644
-index 0000000..a54b49a
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/brk.c
-@@ -0,0 +1,31 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#include <errno.h>
-+#include <unistd.h>
-+#include <sys/syscall.h>
-+
-+libc_hidden_proto(brk)
-+
-+void *__curbrk attribute_hidden = 0;
-+
-+int brk (void *addr)
-+{
-+ void *newbrk;
-+
-+ newbrk = (void *)INLINE_SYSCALL(brk, 1, addr);
-+
-+ __curbrk = newbrk;
-+
-+ if (newbrk < addr) {
-+ __set_errno (ENOMEM);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+libc_hidden_def(brk)
-diff --git a/libc/sysdeps/linux/avr32/bsd-_setjmp.S b/libc/sysdeps/linux/avr32/bsd-_setjmp.S
-new file mode 100644
-index 0000000..be66a10
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bsd-_setjmp.S
-@@ -0,0 +1,16 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+ /* This just does a tail-call to __sigsetjmp(env, 0) */
-+ .global _setjmp
-+ .type _setjmp,"function"
-+ .align 1
-+_setjmp:
-+ mov r11, 0
-+ bral __GI___sigsetjmp
-+ .size _setjmp, . - _setjmp
-diff --git a/libc/sysdeps/linux/avr32/bsd-setjmp.S b/libc/sysdeps/linux/avr32/bsd-setjmp.S
-new file mode 100644
-index 0000000..4635eeb
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/bsd-setjmp.S
-@@ -0,0 +1,16 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+ /* This just does a tail-call to __sigsetjmp(env, 1) */
-+ .global setjmp
-+ .type setjmp,"function"
-+ .align 1
-+setjmp:
-+ mov r11, 1
-+ bral __GI___sigsetjmp
-+ .size setjmp, . - setjmp
-diff --git a/libc/sysdeps/linux/avr32/clone.c b/libc/sysdeps/linux/avr32/clone.c
-new file mode 100644
-index 0000000..e43b0f3
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/clone.c
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (C) 2004 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#include <errno.h>
-+#include <sys/syscall.h>
-+#include <unistd.h>
-+
-+/*
-+ * I don't know if we can be absolutely certain that the fn and arg
-+ * parameters are preserved when returning as the child. If the
-+ * compiler stores them in registers (r0-r7), they should be.
-+ */
-+int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg)
-+{
-+ register int (*_fn)(void *arg) = fn;
-+ register void *_arg = arg;
-+ int err;
-+
-+ /* Sanity check the arguments */
-+ err = -EINVAL;
-+ if (!fn)
-+ goto syscall_error;
-+ if (!child_stack)
-+ goto syscall_error;
-+
-+ err = INLINE_SYSCALL(clone, 2, flags, child_stack);
-+ if (err < 0)
-+ goto syscall_error;
-+ else if (err != 0)
-+ return err;
-+
-+ _exit(_fn(_arg));
-+
-+syscall_error:
-+ __set_errno (-err);
-+ return -1;
-+}
-diff --git a/libc/sysdeps/linux/avr32/crt1.S b/libc/sysdeps/linux/avr32/crt1.S
-new file mode 100644
-index 0000000..ca1fa7a
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/crt1.S
-@@ -0,0 +1,97 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ *
-+ * When we enter _start, the stack looks like this:
-+ * argc argument counter
-+ * argv[0] pointer to program name
-+ * argv[1..argc-1] pointers to program args
-+ * NULL
-+ * env[0..N] pointers to environment variables
-+ * NULL
-+ *
-+ * r12 contains a function pointer to be registered with `atexit'.
-+ * This is how the dynamic linker arranges to have DT_FINI functions
-+ * called for shared libraries that have been loaded before this
-+ * code runs.
-+ *
-+ * We're going to call the following function:
-+ * __uClibc_main(int (*main)(int, char **, char **), int argc,
-+ * char **argv, void (*app_init)(void), void (*app_fini)(void),
-+ * void (*rtld_fini)(void), void *stack_end)
-+ *
-+ * So we need to set up things as follows:
-+ * r12 = address of main
-+ * r11 = argc
-+ * r10 = &argv[0]
-+ * r9 = address of _init
-+ * r8 = address of _fini
-+ * sp[0] = whatever we got passed in r12
-+ */
-+
-+#include <features.h>
-+
-+ .text
-+ .global _start
-+ .type _start, @function
-+_start:
-+ /* Clear the frame pointer and link register since this is the outermost frame. */
-+ mov r7, 0
-+ mov lr, 0
-+
-+ ld.w r11, sp++ /* argc */
-+ mov r10, sp /* &argv[0] */
-+
-+ st.w --sp, r10 /* stack_end */
-+ st.w --sp, r12 /* rtld_fini */
-+
-+#ifdef __PIC__
-+ lddpc r6, .L_GOT
-+.L_RGOT:
-+ rsub r6, pc
-+ lda.w r9, _init
-+ lda.w r8, _fini
-+ lda.w r12, main
-+
-+ /* Ok, now run uClibc's main() -- should not return */
-+ call __uClibc_main
-+
-+ .align 2
-+.L_GOT:
-+ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
-+#else
-+ lddpc r9, __init_addr /* app_init */
-+ lddpc r8, __fini_addr /* app_fini */
-+ lddpc r12, __main_addr /* main */
-+
-+ /* Ok, now run uClibc's main() -- should not return */
-+ lddpc pc, ___uClibc_main_addr
-+
-+ .align 2
-+__init_addr:
-+ .long _init
-+__fini_addr:
-+ .long _fini
-+__main_addr:
-+ .long main
-+___uClibc_main_addr:
-+ .long __uClibc_main
-+#endif
-+ .size _start, . - _start
-+
-+ /*
-+ * The LSB says we need this.
-+ */
-+ .section ".note.ABI-tag", "a"
-+ .align 4
-+ .long 2f - 1f /* namesz */
-+ .long 4f - 3f /* descsz */
-+ .long 1 /* type */
-+1: .asciz "GNU" /* name */
-+2: .align 4
-+3: .long 0 /* Linux executable */
-+ .long 2,6,0 /* Earliest compatible kernel */
-+4: .align 4
-diff --git a/libc/sysdeps/linux/avr32/crti.S b/libc/sysdeps/linux/avr32/crti.S
-new file mode 100644
-index 0000000..3e132d0
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/crti.S
-@@ -0,0 +1,17 @@
-+
-+ .section .init
-+ .align 2
-+ .global _init
-+ .type _init, @function
-+_init:
-+ /* Use a four-byte instruction to avoid NOPs */
-+ stm --sp, r0-r7,lr
-+ .align 2
-+
-+ .section .fini
-+ .align 2
-+ .global _fini
-+ .type _fini, @function
-+_fini:
-+ stm --sp, r0-r7,lr
-+ .align 2
-diff --git a/libc/sysdeps/linux/avr32/crtn.S b/libc/sysdeps/linux/avr32/crtn.S
-new file mode 100644
-index 0000000..577adcc
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/crtn.S
-@@ -0,0 +1,14 @@
-+
-+ .section .init
-+ .align 2
-+ .global _init
-+ .type _init, @function
-+ ldm sp++, r0-r7,pc
-+ .size _init, . - _init
-+
-+ .section .fini
-+ .align 2
-+ .global _fini
-+ .type _fini, @function
-+ ldm sp++, r0-r7,pc
-+ .size _fini, . - _fini
-diff --git a/libc/sysdeps/linux/avr32/mmap.c b/libc/sysdeps/linux/avr32/mmap.c
-new file mode 100644
-index 0000000..2ee025a
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/mmap.c
-@@ -0,0 +1,33 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+#include <errno.h>
-+#include <unistd.h>
-+#include <sys/mman.h>
-+#include <sys/syscall.h>
-+
-+libc_hidden_proto(mmap)
-+
-+static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot,
-+ int, flags, int, fd, __off_t, pgoff);
-+
-+__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
-+{
-+ unsigned long page_size = sysconf(_SC_PAGESIZE);
-+ unsigned long pgoff;
-+
-+ if (offset & (page_size - 1)) {
-+ __set_errno(EINVAL);
-+ return MAP_FAILED;
-+ }
-+
-+ pgoff = (unsigned long)offset >> (31 - __builtin_clz(page_size));
-+
-+ return mmap2(addr, len, prot, flags, fd, pgoff);
-+}
-+libc_hidden_def(mmap)
-diff --git a/libc/sysdeps/linux/avr32/setjmp.S b/libc/sysdeps/linux/avr32/setjmp.S
-new file mode 100644
-index 0000000..7d0354b
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/setjmp.S
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#define _SETJMP_H
-+#define _ASM
-+#include <bits/setjmp.h>
-+
-+ .text
-+
-+ .global __sigsetjmp
-+ .type __sigsetjmp,"function"
-+
-+ .align 1
-+__sigsetjmp:
-+ mustr r8
-+ stm r12, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr
-+
-+ /*
-+ * Make a tail call to __sigjmp_save; it takes the same args
-+ * and is hidden so we don't need to mess around with the GOT.
-+ */
-+ rjmp __sigjmp_save
-+ .size __sigsetjmp, . - __sigsetjmp
-+
-+libc_hidden_def(__sigsetjmp)
-diff --git a/libc/sysdeps/linux/avr32/sigaction.c b/libc/sysdeps/linux/avr32/sigaction.c
-new file mode 100644
-index 0000000..a97ff3d
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/sigaction.c
-@@ -0,0 +1,59 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#include <errno.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <sys/syscall.h>
-+#include <bits/kernel_sigaction.h>
-+
-+#define SA_RESTORER 0x04000000
-+extern void __default_rt_sa_restorer(void);
-+
-+libc_hidden_proto(memcpy)
-+
-+/*
-+ * If act is not NULL, change the action for sig to *act.
-+ * If oact is not NULL, put the old action for sig in *oact.
-+ */
-+int __libc_sigaction(int signum, const struct sigaction *act,
-+ struct sigaction *oldact)
-+{
-+ struct kernel_sigaction kact, koact;
-+ int result;
-+
-+ if (act) {
-+ kact.k_sa_handler = act->sa_handler;
-+ memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask));
-+ kact.sa_flags = act->sa_flags;
-+ if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK))
-+ kact.sa_restorer = act->sa_restorer;
-+ else
-+ kact.sa_restorer = __default_rt_sa_restorer;
-+ kact.sa_flags |= SA_RESTORER;
-+ }
-+
-+ result = __syscall_rt_sigaction(signum, act ? __ptrvalue(&kact) : NULL,
-+ oldact ? __ptrvalue(&koact) : NULL,
-+ _NSIG / 8);
-+
-+ if (oldact && result >= 0) {
-+ oldact->sa_handler = koact.k_sa_handler;
-+ memcpy(&oldact->sa_mask, &koact.sa_mask,
-+ sizeof(oldact->sa_mask));
-+ oldact->sa_flags = koact.sa_flags;
-+ oldact->sa_restorer = koact.sa_restorer;
-+ }
-+
-+ return result;
-+}
-+
-+#ifndef LIBC_SIGACTION
-+libc_hidden_proto(sigaction)
-+weak_alias(__libc_sigaction, sigaction)
-+libc_hidden_weak(sigaction)
-+#endif
-diff --git a/libc/sysdeps/linux/avr32/sigrestorer.S b/libc/sysdeps/linux/avr32/sigrestorer.S
-new file mode 100644
-index 0000000..df6a1ba
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/sigrestorer.S
-@@ -0,0 +1,15 @@
-+/*
-+ * Copyright (C) 2004 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#include <sys/syscall.h>
-+
-+ .global __default_rt_sa_restorer
-+ .type __default_rt_sa_restorer,"function"
-+ .align 1
-+__default_rt_sa_restorer:
-+ mov r8, __NR_rt_sigreturn
-+ scall
-diff --git a/libc/sysdeps/linux/avr32/sys/elf.h b/libc/sysdeps/linux/avr32/sys/elf.h
-new file mode 100644
-index 0000000..faa7310
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/sys/elf.h
-@@ -0,0 +1,26 @@
-+/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+#ifndef _SYS_ELF_H
-+#define _SYS_ELF_H 1
-+
-+#warning "This header is obsolete; use <sys/procfs.h> instead."
-+
-+#include <sys/procfs.h>
-+
-+#endif /* sys/elf.h */
-diff --git a/libc/sysdeps/linux/avr32/sys/procfs.h b/libc/sysdeps/linux/avr32/sys/procfs.h
-new file mode 100644
-index 0000000..3b37363
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/sys/procfs.h
-@@ -0,0 +1,123 @@
-+/* Copyright (C) 1996, 1997, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+#ifndef _SYS_PROCFS_H
-+#define _SYS_PROCFS_H 1
-+
-+/* This is somewhat modelled after the file of the same name on SVR4
-+ systems. It provides a definition of the core file format for ELF
-+ used on Linux. It doesn't have anything to do with the /proc file
-+ system, even though Linux has one.
-+
-+ Anyway, the whole purpose of this file is for GDB and GDB only.
-+ Don't read too much into it. Don't use it for anything other than
-+ GDB unless you know what you are doing. */
-+
-+#include <features.h>
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <sys/user.h>
-+
-+__BEGIN_DECLS
-+
-+/* Type for a general-purpose register. */
-+typedef unsigned long elf_greg_t;
-+
-+/* And the whole bunch of them. We could have used `struct
-+ user_regs' directly in the typedef, but tradition says that
-+ the register set is an array, which does have some peculiar
-+ semantics, so leave it that way. */
-+#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t))
-+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-+
-+/* Register set for the floating-point registers. */
-+typedef struct user_fpregs elf_fpregset_t;
-+
-+/* Signal info. */
-+struct elf_siginfo
-+ {
-+ int si_signo; /* Signal number. */
-+ int si_code; /* Extra code. */
-+ int si_errno; /* Errno. */
-+ };
-+
-+/* Definitions to generate Intel SVR4-like core files. These mostly
-+ have the same names as the SVR4 types with "elf_" tacked on the
-+ front to prevent clashes with Linux definitions, and the typedef
-+ forms have been avoided. This is mostly like the SVR4 structure,
-+ but more Linuxy, with things that Linux does not support and which
-+ GDB doesn't really use excluded. */
-+
-+struct elf_prstatus
-+ {
-+ struct elf_siginfo pr_info; /* Info associated with signal. */
-+ short int pr_cursig; /* Current signal. */
-+ unsigned long int pr_sigpend; /* Set of pending signals. */
-+ unsigned long int pr_sighold; /* Set of held signals. */
-+ __pid_t pr_pid;
-+ __pid_t pr_ppid;
-+ __pid_t pr_pgrp;
-+ __pid_t pr_sid;
-+ struct timeval pr_utime; /* User time. */
-+ struct timeval pr_stime; /* System time. */
-+ struct timeval pr_cutime; /* Cumulative user time. */
-+ struct timeval pr_cstime; /* Cumulative system time. */
-+ elf_gregset_t pr_reg; /* GP registers. */
-+ int pr_fpvalid; /* True if math copro being used. */
-+ };
-+
-+
-+#define ELF_PRARGSZ (80) /* Number of chars for args. */
-+
-+struct elf_prpsinfo
-+ {
-+ char pr_state; /* Numeric process state. */
-+ char pr_sname; /* Char for pr_state. */
-+ char pr_zomb; /* Zombie. */
-+ char pr_nice; /* Nice val. */
-+ unsigned long int pr_flag; /* Flags. */
-+ unsigned short int pr_uid;
-+ unsigned short int pr_gid;
-+ int pr_pid, pr_ppid, pr_pgrp, pr_sid;
-+ /* Lots missing */
-+ char pr_fname[16]; /* Filename of executable. */
-+ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
-+ };
-+
-+/* The rest of this file provides the types for emulation of the
-+ Solaris <proc_service.h> interfaces that should be implemented by
-+ users of libthread_db. */
-+
-+/* Addresses. */
-+typedef void *psaddr_t;
-+
-+/* Register sets. Linux has different names. */
-+typedef elf_gregset_t prgregset_t;
-+typedef elf_fpregset_t prfpregset_t;
-+
-+/* We don't have any differences between processes and threads,
-+ therefore have only one PID type. */
-+typedef __pid_t lwpid_t;
-+
-+/* Process status and info. In the end we do provide typedefs for them. */
-+typedef struct elf_prstatus prstatus_t;
-+typedef struct elf_prpsinfo prpsinfo_t;
-+
-+__END_DECLS
-+
-+#endif /* sys/procfs.h */
-diff --git a/libc/sysdeps/linux/avr32/sys/ucontext.h b/libc/sysdeps/linux/avr32/sys/ucontext.h
-new file mode 100644
-index 0000000..82c7fe2
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/sys/ucontext.h
-@@ -0,0 +1,90 @@
-+/* Copyright (C) 1998, 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+/* Linux/AVR32 ABI compliant context switching support. */
-+
-+#ifndef _SYS_UCONTEXT_H
-+#define _SYS_UCONTEXT_H 1
-+
-+#include <features.h>
-+#include <signal.h>
-+#include <sys/procfs.h>
-+#include <bits/sigcontext.h>
-+
-+typedef int greg_t;
-+
-+/* Number of general registers. */
-+#define NGREG 16
-+
-+/* Container for all general registers. */
-+typedef elf_gregset_t gregset_t;
-+
-+/* Number of each register is the `gregset_t' array. */
-+enum
-+{
-+ R0 = 0,
-+#define R0 R0
-+ R1 = 1,
-+#define R1 R1
-+ R2 = 2,
-+#define R2 R2
-+ R3 = 3,
-+#define R3 R3
-+ R4 = 4,
-+#define R4 R4
-+ R5 = 5,
-+#define R5 R5
-+ R6 = 6,
-+#define R6 R6
-+ R7 = 7,
-+#define R7 R7
-+ R8 = 8,
-+#define R8 R8
-+ R9 = 9,
-+#define R9 R9
-+ R10 = 10,
-+#define R10 R10
-+ R11 = 11,
-+#define R11 R11
-+ R12 = 12,
-+#define R12 R12
-+ R13 = 13,
-+#define R13 R13
-+ R14 = 14,
-+#define R14 R14
-+ R15 = 15
-+#define R15 R15
-+};
-+
-+/* Structure to describe FPU registers. */
-+typedef elf_fpregset_t fpregset_t;
-+
-+/* Context to describe whole processor state. */
-+typedef struct sigcontext mcontext_t;
-+
-+/* Userlevel context. */
-+typedef struct ucontext
-+{
-+ unsigned long uc_flags;
-+ struct ucontext *uc_link;
-+ stack_t uc_stack;
-+ mcontext_t uc_mcontext;
-+ sigset_t uc_sigmask; /* mask last for extensibility */
-+} ucontext_t;
-+
-+#endif /* sys/ucontext.h */
-diff --git a/libc/sysdeps/linux/avr32/sys/user.h b/libc/sysdeps/linux/avr32/sys/user.h
-new file mode 100644
-index 0000000..c0b3d38
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/sys/user.h
-@@ -0,0 +1,46 @@
-+#ifndef _SYS_USER_H
-+#define _SYS_USER_H
-+
-+struct user_fpregs
-+{
-+
-+};
-+
-+struct user_regs
-+{
-+ unsigned long sr;
-+ unsigned long pc;
-+ unsigned long lr;
-+ unsigned long sp;
-+ unsigned long r12;
-+ unsigned long r11;
-+ unsigned long r10;
-+ unsigned long r9;
-+ unsigned long r8;
-+ unsigned long r7;
-+ unsigned long r6;
-+ unsigned long r5;
-+ unsigned long r4;
-+ unsigned long r3;
-+ unsigned long r2;
-+ unsigned long r1;
-+ unsigned long r0;
-+ unsigned long r12_orig;
-+};
-+
-+struct user
-+{
-+ struct user_regs regs; /* general registers */
-+ size_t u_tsize; /* text size (pages) */
-+ size_t u_dsize; /* data size (pages) */
-+ size_t u_ssize; /* stack size (pages) */
-+ unsigned long start_code; /* text starting address */
-+ unsigned long start_data; /* data starting address */
-+ unsigned long start_stack; /* stack starting address */
-+ long int signal; /* signal causing core dump */
-+ struct user_regs * u_ar0; /* help gdb find registers */
-+ unsigned long magic; /* identifies a core file */
-+ char u_comm[32]; /* user command name */
-+};
-+
-+#endif /* _SYS_USER_H */
-diff --git a/libc/sysdeps/linux/avr32/syscall.S b/libc/sysdeps/linux/avr32/syscall.S
-new file mode 100644
-index 0000000..55c1b1f
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/syscall.S
-@@ -0,0 +1,71 @@
-+/*
-+ * Copyright (C) 2004-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#include <features.h>
-+
-+ .text
-+
-+ /*
-+ * long int syscall(long int sysno, ...)
-+ */
-+ .global syscall
-+ .type syscall, @function
-+ .align 2
-+syscall:
-+ stm --sp, r3,r5,r6,lr
-+ sub lr, sp, -16
-+ mov r8, r12
-+ ldm lr, r3,r5,r9-r12
-+ scall
-+ cp.w r12, -4095
-+ brlo .Ldone
-+
-+#ifdef __PIC__
-+ lddpc r6, .Lgot
-+.Lgotcalc:
-+ rsub r6, pc
-+# ifdef __UCLIBC_HAS_THREADS__
-+ rsub r3, r12, 0
-+ mcall r6[__errno_location@got]
-+ st.w r12[0], r3
-+# else
-+ ld.w r3, r6[errno@got]
-+ neg r12
-+ st.w r3[0], r12
-+# endif
-+#else
-+# ifdef __UCLIBC_HAS_THREADS__
-+ rsub r3, r12, 0
-+ mcall .Lerrno_location
-+ st.w r12[0], r3
-+# else
-+ lddpc r3, .Lerrno
-+ neg r12
-+ st.w r3[0], r12
-+# endif
-+#endif
-+ mov r12, -1
-+
-+.Ldone:
-+ ldm sp++, r3,r5,r6,pc
-+
-+ .align 2
-+#ifdef __PIC__
-+.Lgot:
-+ .long .Lgotcalc - _GLOBAL_OFFSET_TABLE_
-+#else
-+# ifdef __UCLIBC_HAS_THREADS__
-+.Lerrno_location:
-+ .long __errno_location
-+# else
-+.Lerrno:
-+ .long errno
-+# endif
-+#endif
-+
-+
-+ .size syscall, . - syscall
-diff --git a/libc/sysdeps/linux/avr32/vfork.S b/libc/sysdeps/linux/avr32/vfork.S
-new file mode 100644
-index 0000000..03ca99f
---- /dev/null
-+++ b/libc/sysdeps/linux/avr32/vfork.S
-@@ -0,0 +1,58 @@
-+/*
-+ * Copyright (C) 2005 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+
-+/*
-+ * Clone the process without copying the address space. The
-+ * calling process is suspended until the child either exits
-+ * or calls execve.
-+ *
-+ * This all means that we cannot rely on the stack to store
-+ * away registers, since they will be overwritten by the child
-+ * as soon as it makes another function call (e.g. execve()).
-+ * Fortunately, the Linux kernel preserves LR across system calls.
-+ */
-+
-+#include <features.h>
-+#include <sys/syscall.h>
-+
-+ .global __vfork
-+ .type __vfork,@function
-+ .align 1
-+__vfork:
-+ mov r8, __NR_vfork
-+ scall
-+ cp.w r12, -4096
-+ retls r12
-+
-+ /* vfork failed, so we may use the stack freely */
-+ pushm r4-r7,lr
-+#ifdef __PIC__
-+ lddpc r6, .L_GOT
-+ rsub r4, r12, 0
-+.L_RGOT:
-+ rsub r6, pc
-+ mcall r6[__errno_location@got]
-+#else
-+ rsub r4, r12, 0
-+ mcall .L__errno_location
-+#endif
-+ st.w r12[0], r4
-+ popm r4-r7,pc,r12=-1
-+
-+ .align 2
-+#ifdef __PIC__
-+.L_GOT:
-+ .long .L_RGOT - _GLOBAL_OFFSET_TABLE_
-+#else
-+.L__errno_location:
-+ .long __errno_location
-+#endif
-+ .size __vfork, . - __vfork
-+
-+weak_alias(__vfork,vfork)
-+libc_hidden_weak(vfork)
-diff --git a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
-new file mode 100644
-index 0000000..2e8a33b
---- /dev/null
-+++ b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
-@@ -0,0 +1,73 @@
-+/* Machine-dependent pthreads configuration and inline functions.
-+ *
-+ * Copyright (C) 2005-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#ifndef _PT_MACHINE_H
-+#define _PT_MACHINE_H 1
-+
-+#include <features.h>
-+
-+static inline int
-+_test_and_set (int *p, int v)
-+{
-+ int result;
-+
-+ __asm__ __volatile__(
-+ "/* Inline test and set */\n"
-+ " xchg %[old], %[mem], %[new]"
-+ : [old] "=&r"(result)
-+ : [mem] "r"(p), [new] "r"(v)
-+ : "memory");
-+
-+ return result;
-+}
-+
-+#ifndef PT_EI
-+# define PT_EI extern inline
-+#endif
-+
-+extern long int testandset (int *spinlock);
-+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-+
-+/* Spinlock implementation; required. */
-+PT_EI long int
-+testandset (int *spinlock)
-+{
-+ return _test_and_set(spinlock, 1);
-+}
-+
-+
-+/* Get some notion of the current stack. Need not be exactly the top
-+ of the stack, just something somewhere in the current frame. */
-+#define CURRENT_STACK_FRAME stack_pointer
-+register char * stack_pointer __asm__ ("sp");
-+
-+/* Compare-and-swap for semaphores. */
-+
-+#define HAS_COMPARE_AND_SWAP
-+PT_EI int
-+__compare_and_swap(long int *p, long int oldval, long int newval)
-+{
-+ long int result;
-+
-+ __asm__ __volatile__(
-+ "/* Inline compare and swap */\n"
-+ "1: ssrf 5\n"
-+ " ld.w %[result], %[mem]\n"
-+ " eor %[result], %[old]\n"
-+ " brne 2f\n"
-+ " stcond %[mem], %[new]\n"
-+ " brne 1b\n"
-+ "2:"
-+ : [result] "=&r"(result), [mem] "=m"(*p)
-+ : "m"(*p), [new] "r"(newval), [old] "r"(oldval)
-+ : "cc", "memory");
-+
-+ return result;
-+}
-+
-+#endif /* pt-machine.h */
-diff --git a/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h
-new file mode 100644
-index 0000000..fe12bf8
---- /dev/null
-+++ b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h
-@@ -0,0 +1,73 @@
-+/* Machine-dependent pthreads configuration and inline functions.
-+ *
-+ * Copyright (C) 2005-2007 Atmel Corporation
-+ *
-+ * 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.
-+ */
-+#ifndef _PT_MACHINE_H
-+#define _PT_MACHINE_H 1
-+
-+#include <features.h>
-+
-+static inline int
-+_test_and_set (int *p, int v) __THROW
-+{
-+ int result;
-+
-+ __asm__ __volatile__(
-+ "/* Inline test and set */\n"
-+ " xchg %[old], %[mem], %[new]"
-+ : [old] "=&r"(result)
-+ : [mem] "r"(p), [new] "r"(v)
-+ : "memory");
-+
-+ return result;
-+}
-+
-+#ifndef PT_EI
-+# define PT_EI extern inline
-+#endif
-+
-+extern long int testandset (int *spinlock);
-+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
-+
-+/* Spinlock implementation; required. */
-+PT_EI long int
-+testandset (int *spinlock)
-+{
-+ return _test_and_set(spinlock, 1);
-+}
-+
-+
-+/* Get some notion of the current stack. Need not be exactly the top
-+ of the stack, just something somewhere in the current frame. */
-+#define CURRENT_STACK_FRAME stack_pointer
-+register char * stack_pointer __asm__ ("sp");
-+
-+/* Compare-and-swap for semaphores. */
-+
-+#define HAS_COMPARE_AND_SWAP
-+PT_EI int
-+__compare_and_swap(long int *p, long int oldval, long int newval)
-+{
-+ int result;
-+
-+ __asm__ __volatile__(
-+ "/* Inline compare and swap */\n"
-+ "1: ssrf 5\n"
-+ " ld.w %[result], %[mem]\n"
-+ " eor %[result], %[old]\n"
-+ " brne 2f\n"
-+ " stcond %[mem], %[new]\n"
-+ " brne 1b\n"
-+ "2:"
-+ : [result] "=&r"(result), [mem] "=m"(*p)
-+ : "m"(*p), [new] "r"(newval), [old] "r"(oldval)
-+ : "cc", "memory");
-+
-+ return result == 0;
-+}
-+
-+#endif /* pt-machine.h */
-diff --git a/utils/ldd.c b/utils/ldd.c
-index 75ad628..e34acd9 100644
---- a/utils/ldd.c
-+++ b/utils/ldd.c
-@@ -44,6 +44,11 @@
- #define ELFCLASSM ELFCLASS32
- #endif
-
-+#if defined(__avr32__)
-+#define MATCH_MACHINE(x) (x == EM_AVR32)
-+#define ELFCLASSM ELFCLASS32
-+#endif
-+
- #if defined(__s390__)
- #define MATCH_MACHINE(x) (x == EM_S390)
- #define ELFCLASSM ELFCLASS32
+++ /dev/null
-From: Haavard Skinnemoen <hskinnemoen@atmel.com>
-Date: Wed, 19 Sep 2007 10:03:36 +0200
-Subject: [Avr-gnu-toolchain] [uClibc PATCH] Fix inverted logic in
- __compare_and_swap in linuxthreads.old
-
-If the old value equals the value in memory, the result should be
-TRUE, not FALSE.
-
-Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
----
- .../linuxthreads.old/sysdeps/avr32/pt-machine.h | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
-index 2e8a33b..eccf329 100644
---- a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
-+++ b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
-@@ -67,7 +67,7 @@ __compare_and_swap(long int *p, long int oldval, long int newval)
- : "m"(*p), [new] "r"(newval), [old] "r"(oldval)
- : "cc", "memory");
-
-- return result;
-+ return result == 0;
- }
-
- #endif /* pt-machine.h */
---
-1.5.3.1
+++ /dev/null
-From 91cb4bb00e4d9463c0d41015152daa4b39acf762 Mon Sep 17 00:00:00 2001
-From: Hans-Christian Egtvedt <hcegtvedt@atmel.com>
-Date: Tue, 18 Sep 2007 10:15:05 +0200
-Subject: [PATCH] Fix resolve when identical IPv4 and IPv6 hosts are defined in /etc/hosts
-
-This patch will fix a problem when the same host is defined with both IPv4 and
-IPv6 entries in /etc/hosts. Previous only the first of these host would work,
-as uClibc would read the /etc/hosts file from top to bottom, failing if the
-first hit did not match the IP type.
-
-Now uClibc will continue reading, even if the first correct entry name, but wrong IP
-type fails. Thus, allowing a second correct entry name with correct IP type
-will result in a name resolve.
-
-Signed-off-by: Hans-Christian Egtvedt <hcegtvedt@atmel.com>
----
- libc/inet/resolv.c | 6 +++---
- 1 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
-index f4e6cac..9cdc3fe 100644
---- a/libc/inet/resolv.c
-+++ b/libc/inet/resolv.c
-@@ -1643,7 +1643,7 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,
- *result=result_buf;
- ret=NETDB_SUCCESS;
- #ifdef __UCLIBC_HAS_IPV6__
-- } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) {
-+ } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) {
- DPRINTF("Found INET6\n");
- addr_list6[0] = in6;
- addr_list6[1] = 0;
-@@ -1658,8 +1658,8 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type,
- } else {
- DPRINTF("Error\n");
- ret=TRY_AGAIN;
-- break; /* bad ip address */
-- }
-+ continue; /* bad ip address, keep searching */
-+ }
-
- if (action!=GETHOSTENT) {
- fclose(fp);
---
-1.5.2.5
-
--- /dev/null
+--- a/libpthread/linuxthreads.old/attr.c 2006-01-24 12:41:01.000000000 -0500
++++ b/libpthread/linuxthreads.old/attr.c 2008-02-10 11:35:32.000000000 -0500
+@@ -25,6 +25,14 @@
+ #include "pthread.h"
+ #include "internals.h"
+
++#include <sys/resource.h>
++#include <inttypes.h>
++#include <stdio.h>
++#include <stdio_ext.h>
++#include <stdlib.h>
++#include <sys/resource.h>
++
++
+ /* NOTE: With uClibc I don't think we need this versioning stuff.
+ * Therefore, define the function pthread_attr_init() here using
+ * a strong symbol. */
+@@ -209,4 +217,94 @@ int __pthread_attr_getstacksize(const pt
+ *stacksize = attr->__stacksize;
+ return 0;
+ }
++
++
++extern int *__libc_stack_end;
++
+ weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
++void* pthread_getattr_np(pthread_t thread, pthread_attr_t *attr)
++{
++ static void *stackBase = 0;
++ static size_t stackSize = 0;
++ int ret = 0;
++ /* Stack size limit. */
++ struct rlimit rl;
++
++ /* The safest way to get the top of the stack is to read
++ /proc/self/maps and locate the line into which
++ __libc_stack_end falls. */
++ FILE *fp = fopen("/proc/self/maps", "rc");
++ if (fp == NULL)
++ ret = errno;
++ /* We need the limit of the stack in any case. */
++ else if (getrlimit (RLIMIT_STACK, &rl) != 0)
++ ret = errno;
++ else {
++ /* We need no locking. */
++ __fsetlocking (fp, FSETLOCKING_BYCALLER);
++
++ /* Until we found an entry (which should always be the case)
++ mark the result as a failure. */
++ ret = ENOENT;
++
++ char *line = NULL;
++ size_t linelen = 0;
++ uintptr_t last_to = 0;
++
++ while (! feof_unlocked (fp)) {
++ if (getdelim (&line, &linelen, '\n', fp) <= 0)
++ break;
++
++ uintptr_t from;
++ uintptr_t to;
++ if (sscanf (line, "%x-%x", &from, &to) != 2)
++ continue;
++ if (from <= (uintptr_t) __libc_stack_end
++ && (uintptr_t) __libc_stack_end < to) {
++ /* Found the entry. Now we have the info we need. */
++ attr->__stacksize = rl.rlim_cur;
++#ifdef _STACK_GROWS_UP
++ /* Don't check to enforce a limit on the __stacksize */
++ attr->__stackaddr = (void *) from;
++#else
++ attr->__stackaddr = (void *) to;
++
++ /* The limit might be too high. */
++ if ((size_t) attr->__stacksize > (size_t) attr->__stackaddr - last_to)
++ attr->__stacksize = (size_t) attr->__stackaddr - last_to;
++#endif
++
++ /* We succeed and no need to look further. */
++ ret = 0;
++ break;
++ }
++ last_to = to;
++ }
++
++ fclose (fp);
++ free (line);
++ }
++#ifndef _STACK_GROWS_UP
++ stackBase = (char *) attr->__stackaddr - attr->__stacksize;
++#else
++ stackBase = attr->__stackaddr;
++#endif
++ stackSize = attr->__stacksize;
++ return (void*)(stackBase + stackSize);
++}
++
++int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
++ size_t *stacksize)
++{
++ /* XXX This function has a stupid definition. The standard specifies
++ no error value but what is if no stack address was set? We simply
++ return the value we have in the member. */
++#ifndef _STACK_GROWS_UP
++ *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
++#else
++ *stackaddr = attr->__stackaddr;
++#endif
++ *stacksize = attr->__stacksize;
++ return 0;
++}
++weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
+
+--- a/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h 2006-12-07 22:19:36.000000000 -0500
++++ b/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h 2008-02-10 11:42:35.000000000 -0500
+@@ -288,15 +288,11 @@ extern int pthread_attr_getstacksize (__
+ __attr, size_t *__restrict __stacksize)
+ __THROW;
+
+-#if 0
+-/* Not yet implemented in uClibc! */
+-
+ #ifdef __USE_GNU
+ /* Initialize thread attribute *ATTR with attributes corresponding to the
+ already running thread TH. It shall be called on unitialized ATTR
+ and destroyed with pthread_attr_destroy when no longer needed. */
+-extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW;
+-#endif
++extern void* pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
+ #endif
+
+ /* Functions for scheduling control. */
+@@ -599,6 +595,11 @@ extern int pthread_cancel (pthread_t __c
+ cancelled. */
+ extern void pthread_testcancel (void);
+
++/* Return the previously set address for the stack. */
++extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr,
++ void **__restrict __stackaddr,
++ size_t *__restrict __stacksize) __THROW;
++
+
+ /* Install a cleanup handler: ROUTINE will be called with arguments ARG
+ when the thread is cancelled or calls pthread_exit. ROUTINE will also
+
+++ /dev/null
-From: Haavard Skinnemoen <hskinnemoen@atmel.com>
-Date: Wed, 19 Sep 2007 10:03:35 +0200
-Subject: [Avr-gnu-toolchain] [uClibc PATCH] Load GOT pointer at the
- beginning of .init and .fini
-
-I don't know why this seems to have worked before, but the .init and
-.fini sections typically consist of a bunch of mcalls using r6 as the
-base pointer. This can cause "interesting" behaviour when r6 hasn't
-been initialized to point to the GOT.
-
-Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
----
- libc/sysdeps/linux/avr32/crti.S | 15 ++++++++++++---
- libc/sysdeps/linux/avr32/crtn.S | 4 ++--
- 2 files changed, 14 insertions(+), 5 deletions(-)
-
-diff --git a/libc/sysdeps/linux/avr32/crti.S b/libc/sysdeps/linux/avr32/crti.S
-index 3e132d0..660f47c 100644
---- a/libc/sysdeps/linux/avr32/crti.S
-+++ b/libc/sysdeps/linux/avr32/crti.S
-@@ -4,14 +4,23 @@
- .global _init
- .type _init, @function
- _init:
-- /* Use a four-byte instruction to avoid NOPs */
-- stm --sp, r0-r7,lr
-+ stm --sp, r6, lr
-+ lddpc r6, 2f
-+1: rsub r6, pc
-+ rjmp 3f
- .align 2
-+2: .long 1b - _GLOBAL_OFFSET_TABLE_
-+3:
-
- .section .fini
- .align 2
- .global _fini
- .type _fini, @function
- _fini:
-- stm --sp, r0-r7,lr
-+ stm --sp, r6, lr
-+ lddpc r6, 2f
-+1: rsub r6, pc
-+ rjmp 3f
- .align 2
-+2: .long 1b - _GLOBAL_OFFSET_TABLE_
-+3:
-diff --git a/libc/sysdeps/linux/avr32/crtn.S b/libc/sysdeps/linux/avr32/crtn.S
-index 577adcc..f7d1040 100644
---- a/libc/sysdeps/linux/avr32/crtn.S
-+++ b/libc/sysdeps/linux/avr32/crtn.S
-@@ -3,12 +3,12 @@
- .align 2
- .global _init
- .type _init, @function
-- ldm sp++, r0-r7,pc
-+ ldm sp++, r6, pc
- .size _init, . - _init
-
- .section .fini
- .align 2
- .global _fini
- .type _fini, @function
-- ldm sp++, r0-r7,pc
-+ ldm sp++, r6, pc
- .size _fini, . - _fini
---
-1.5.3.1