From: John Voltz Date: Thu, 6 Mar 2008 18:50:01 +0000 (-0000) Subject: added and removed uclibc patches X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3ab16b1fd65533d032008d409e0026fe2be43182;p=buildroot.git added and removed uclibc patches --- diff --git a/toolchain/uClibc/Config.in b/toolchain/uClibc/Config.in index b463f2bd05..6557f1980f 100644 --- a/toolchain/uClibc/Config.in +++ b/toolchain/uClibc/Config.in @@ -10,7 +10,7 @@ choice 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 @@ -19,7 +19,6 @@ choice depends BR2_EXT_UCLIBC_VERSION_0_9_29 config BR2_UCLIBC_VERSION_SNAPSHOT - depends !BR2_avr32 bool "daily snapshot" endchoice diff --git a/toolchain/uClibc/Glibc_vs_uClibc_Differences.txt b/toolchain/uClibc/Glibc_vs_uClibc_Differences.txt new file mode 100644 index 0000000000..4ed24639ee --- /dev/null +++ b/toolchain/uClibc/Glibc_vs_uClibc_Differences.txt @@ -0,0 +1,215 @@ + 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). + + + + + +****************************** 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/ + diff --git a/toolchain/uClibc/uClibc-0.9.28-100-fix_includes.patch b/toolchain/uClibc/uClibc-0.9.28-100-fix_includes.patch new file mode 100644 index 0000000000..52c89678e1 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-100-fix_includes.patch @@ -0,0 +1,327 @@ +--- 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 + # +-# 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 ++# ++# 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 +- diff --git a/toolchain/uClibc/uClibc-0.9.28-200-host-ldconfig.patch b/toolchain/uClibc/uClibc-0.9.28-200-host-ldconfig.patch new file mode 100644 index 0000000000..f55c3498a7 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-200-host-ldconfig.patch @@ -0,0 +1,635 @@ +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 + +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 ++ * ++ * 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 ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include /* for PATH_MAX */ ++#include /* for MAXPATHLEN */ ++#include ++#ifndef __set_errno ++#define __set_errno(val) ((errno) = (val)) ++#endif ++ ++#include /* 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 +@@ -37,6 +39,7 @@ + #include + #include + #include ++#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) diff --git a/toolchain/uClibc/uClibc-0.9.28-300-ldso.patch b/toolchain/uClibc/uClibc-0.9.28-300-ldso.patch new file mode 100644 index 0000000000..4081fc7d1b --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-300-ldso.patch @@ -0,0 +1,5190 @@ +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 ++ * ++ * 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 ++ * ++ * 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 ++ * ++ * 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 ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LINUX_STRING_H_ + #define _LINUX_STRING_H_ + +-#include // for do_rem ++#include /* for do_rem */ + #include + ++/* 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 ++ * ++ * GNU Lesser General Public License version 2.1 or later. ++ */ ++ + #ifndef _LD_SYSCALL_H_ + #define _LD_SYSCALL_H_ + +@@ -12,9 +19,8 @@ + #include + #include + +- + /* _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 ++# 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 ++ * ++ * 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 ++ * ++ * 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 + #include ++#include + /* Pull in the arch specific type information */ + #include ++/* Pull in the arch specific page size */ ++#include ++#define attribute_unused __attribute__ ((unused)) + /* Pull in the ldso syscalls and string functions */ + #include + #include +-/* Pull in the arch specific page size */ +-#include + /* Now the ldso specific headers */ + #include + #include +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 ++ * ++ * 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 ++ * Copyright (C) 2000-2006 Erik Andersen ++ * ++ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +-asm( ++#include ++ ++#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 ++ * Copyright (C) 2000-2006 by Erik Andersen + * 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 + + /* 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 /* __attribute_used__ */ ++#include + + /* 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 + */ +-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 ++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 + */ + +-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 + */ +-#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 ++ * Copyright (C) 2000-2006 by Erik Andersen + * 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 + #include + + +-#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 directly; include instead." + #endif + ++#include ++ + /* This includes the `__NR_' syscall numbers taken from the Linux kernel + * header files. It also defines the traditional `SYS_' macros for older + * programs. */ + #include + +-#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 directly; include instead." + #endif + ++#include ++ + /* This includes the `__NR_' syscall numbers taken from the Linux kernel + * header files. It also defines the traditional `SYS_' macros for older + * programs. */ + #include + +- +-#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 */ + diff --git a/toolchain/uClibc/uClibc-0.9.28-400-math-endianness.patch b/toolchain/uClibc/uClibc-0.9.28-400-math-endianness.patch new file mode 100644 index 0000000000..015f795687 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-400-math-endianness.patch @@ -0,0 +1,247 @@ +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 ++#include + + 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 ++ + 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 + #include ++#include + + 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 + #include ++#include + + #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 ++ + 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 ++ + 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 + #include ++#include + + 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 + #include ++#include + + #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 ++ + 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 ++ ++#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 ++ ++#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 */ diff --git a/toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch b/toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch new file mode 100644 index 0000000000..5e56a73970 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch @@ -0,0 +1,8631 @@ +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 + #include + ++#include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 + #include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 + ++__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 + #include + ++#include + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 + #include + ++#include ++ ++__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 +-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;jbuf; +- 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:"", class, type); ++ name, domain?domain:"", 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 +-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 + #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 + #include +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-#endif ++ ++#include + + /* 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 + #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 + #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 + #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 + #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 + #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 + #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 + #include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 ++ ++__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 + #include + ++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 + #include + ++#include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 + #include + ++#include ++ + #ifdef __UCLIBC_HAS_XLOCALE__ + #include + #endif +@@ -191,21 +193,7 @@ typedef struct { + char tzname[TZNAME_MAX+1]; + } rule_struct; + +-#ifdef __UCLIBC_HAS_THREADS__ +- +-#include +- +-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 + #include + #include +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-#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 + #include + ++#include + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 +@@ -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 + #include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 ++ ++__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 + #include + #include +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-#endif ++ ++#include + + /**********************************************************************/ + /* 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 +-#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 + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include ++#include + +-#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 + #include +@@ -21,6 +22,8 @@ + #include + #include + ++#include ++ + /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ + #include + #if ! defined __NR_vfork +@@ -29,19 +32,11 @@ + # define VFORK_UNLOCK ((void) 0) + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 +-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 + ++__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 + #include + ++#include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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_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 ++ ++__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 +@@ -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 +@@ -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 +@@ -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 +@@ -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 + #include + ++#include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 +@@ -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 +@@ -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 +@@ -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 + #include + #include +-#ifdef __UCLIBC_HAS_THREADS__ +-#include ++ + /* 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 ++ ++__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 +- */ ++*/ + + #define _GNU_SOURCE + #include +@@ -26,16 +26,9 @@ + #include + #include + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include +-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 + ++__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 ++#include + + /* 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 + + +-#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 + #include + +- .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 ++ ++__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 ++ * ++ * 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 ++ ++#ifdef __UCLIBC_HAS_THREADS__ ++ ++#include ++ ++#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 +-#include +-#include +- +-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); +-} diff --git a/toolchain/uClibc/uClibc-0.9.28-600-new_dst_rules.patch b/toolchain/uClibc/uClibc-0.9.28-600-new_dst_rules.patch new file mode 100644 index 0000000000..8b1a5a9ac9 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-600-new_dst_rules.patch @@ -0,0 +1,101 @@ +--- 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]); diff --git a/toolchain/uClibc/uClibc-0.9.28-700-rm-whitespace.patch b/toolchain/uClibc/uClibc-0.9.28-700-rm-whitespace.patch new file mode 100644 index 0000000000..6004f91e32 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-700-rm-whitespace.patch @@ -0,0 +1,86 @@ +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 + +-#if defined __cplusplus && __GNUC_PREREQ (2,95) ++#if defined __cplusplus && __GNUC_PREREQ(2,95) + # define __ASSERT_VOID_CAST static_cast + #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 diff --git a/toolchain/uClibc/uClibc-0.9.28-800-avr32-1.patch b/toolchain/uClibc/uClibc-0.9.28-800-avr32-1.patch new file mode 100644 index 0000000000..14c3b38ffa --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-800-avr32-1.patch @@ -0,0 +1,4433 @@ +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 +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 + #include +-_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 + + #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 +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 ++# ++# 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 ++#include ++#include ++ ++#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 ++ ++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 directly; include 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 directly; include 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 directly; include instead." ++#endif ++ ++#include ++ ++/* 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 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 ++ ++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 directly; use 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 directly; include instead." ++#endif ++ ++/* ++ * This includes the `__NR_' syscall numbers taken from the ++ * Linux kernel header files. It also defines the traditional ++ * `SYS_' macros for older programs. ++ */ ++#include ++ ++#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 ++#include ++ ++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 ++#include ++#include ++ ++/* ++ * 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 ++ ++ .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 ++#include ++#include ++ ++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 ++ ++ .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 ++#include ++#include ++#include ++#include ++ ++#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 ++ ++ .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 instead." ++ ++#include ++ ++#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 ++ ++__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 ++#include ++#include ++#include ++ ++__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 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 ++#include ++#include ++#include ++ ++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 ++ ++ .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 ++#include ++ ++ .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 +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 ++# ++# 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 ++#include ++#include ++#include ++ ++#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 ++#include ++ ++#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 ++ ++#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 ++ ++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. diff --git a/toolchain/uClibc/uClibc-0.9.28-fix_includes.patch b/toolchain/uClibc/uClibc-0.9.28-fix_includes.patch deleted file mode 100644 index 52c89678e1..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-fix_includes.patch +++ /dev/null @@ -1,327 +0,0 @@ ---- 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 - # --# 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 -+# -+# 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 -- diff --git a/toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch b/toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch deleted file mode 100644 index f55c3498a7..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-host-ldconfig.patch +++ /dev/null @@ -1,635 +0,0 @@ -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 - -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 -+ * -+ * 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 -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include /* for PATH_MAX */ -+#include /* for MAXPATHLEN */ -+#include -+#ifndef __set_errno -+#define __set_errno(val) ((errno) = (val)) -+#endif -+ -+#include /* 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 -@@ -37,6 +39,7 @@ - #include - #include - #include -+#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) diff --git a/toolchain/uClibc/uClibc-0.9.28-ldso.patch b/toolchain/uClibc/uClibc-0.9.28-ldso.patch deleted file mode 100644 index 4081fc7d1b..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-ldso.patch +++ /dev/null @@ -1,5190 +0,0 @@ -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 -+ * -+ * 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 -+ * -+ * 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 -+ * -+ * 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 -+ * -+ * GNU Lesser General Public License version 2.1 or later. -+ */ -+ - #ifndef _LINUX_STRING_H_ - #define _LINUX_STRING_H_ - --#include // for do_rem -+#include /* for do_rem */ - #include - -+/* 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 -+ * -+ * GNU Lesser General Public License version 2.1 or later. -+ */ -+ - #ifndef _LD_SYSCALL_H_ - #define _LD_SYSCALL_H_ - -@@ -12,9 +19,8 @@ - #include - #include - -- - /* _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 -+# 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 -+ * -+ * 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 -+ * -+ * 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 - #include -+#include - /* Pull in the arch specific type information */ - #include -+/* Pull in the arch specific page size */ -+#include -+#define attribute_unused __attribute__ ((unused)) - /* Pull in the ldso syscalls and string functions */ - #include - #include --/* Pull in the arch specific page size */ --#include - /* Now the ldso specific headers */ - #include - #include -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 -+ * -+ * 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 -+ * Copyright (C) 2000-2006 Erik Andersen -+ * -+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - */ - --asm( -+#include -+ -+#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 -+ * Copyright (C) 2000-2006 by Erik Andersen - * 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 - - /* 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 /* __attribute_used__ */ -+#include - - /* 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 - */ --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 -+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 - */ - --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 - */ --#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 -+ * Copyright (C) 2000-2006 by Erik Andersen - * 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 - #include - - --#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 directly; include instead." - #endif - -+#include -+ - /* This includes the `__NR_' syscall numbers taken from the Linux kernel - * header files. It also defines the traditional `SYS_' macros for older - * programs. */ - #include - --#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 directly; include instead." - #endif - -+#include -+ - /* This includes the `__NR_' syscall numbers taken from the Linux kernel - * header files. It also defines the traditional `SYS_' macros for older - * programs. */ - #include - -- --#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 */ - diff --git a/toolchain/uClibc/uClibc-0.9.28-math-endianness.patch b/toolchain/uClibc/uClibc-0.9.28-math-endianness.patch deleted file mode 100644 index 015f795687..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-math-endianness.patch +++ /dev/null @@ -1,247 +0,0 @@ -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 -+#include - - 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 -+ - 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 - #include -+#include - - 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 - #include -+#include - - #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 -+ - 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 -+ - 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 - #include -+#include - - 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 - #include -+#include - - #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 -+ - 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 -+ -+#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 -+ -+#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 */ diff --git a/toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch b/toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch deleted file mode 100644 index 5e56a73970..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-mutex-cancel.patch +++ /dev/null @@ -1,8631 +0,0 @@ -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 - #include - -+#include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 - #include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 - -+__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 - #include - -+#include - -- --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 - #include - -+#include -+ -+__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 --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;jbuf; -- 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:"", class, type); -+ name, domain?domain:"", 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 --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 - #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 - #include --#ifdef __UCLIBC_HAS_THREADS__ --#include --#endif -+ -+#include - - /* 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 - #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 - #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 - #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 - #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 - #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 - #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 - #include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 -+ -+__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 - #include - -+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 - #include - -+#include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 - #include - -+#include -+ - #ifdef __UCLIBC_HAS_XLOCALE__ - #include - #endif -@@ -191,21 +193,7 @@ typedef struct { - char tzname[TZNAME_MAX+1]; - } rule_struct; - --#ifdef __UCLIBC_HAS_THREADS__ -- --#include -- --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 - #include - #include --#ifdef __UCLIBC_HAS_THREADS__ --#include --#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 - #include - -+#include - -- --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 -@@ -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 - #include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 -+ -+__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 - #include - #include --#ifdef __UCLIBC_HAS_THREADS__ --#include --#endif -+ -+#include - - /**********************************************************************/ - /* 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 --#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 - #endif - --#ifdef __UCLIBC_HAS_THREADS__ --#include -+#include - --#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 - #include -@@ -21,6 +22,8 @@ - #include - #include - -+#include -+ - /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ - #include - #if ! defined __NR_vfork -@@ -29,19 +32,11 @@ - # define VFORK_UNLOCK ((void) 0) - #endif - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 --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 - -+__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 - #include - -+#include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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_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 -+ -+__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 -@@ -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 -@@ -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 -@@ -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 -@@ -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 - #include - -+#include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 -@@ -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 -@@ -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 -@@ -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 - #include - #include --#ifdef __UCLIBC_HAS_THREADS__ --#include -+ - /* 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 -+ -+__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 -- */ -+*/ - - #define _GNU_SOURCE - #include -@@ -26,16 +26,9 @@ - #include - #include - --#ifdef __UCLIBC_HAS_THREADS__ --#include --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 - -+__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 -+#include - - /* 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 - - --#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 - #include - -- .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 -+ -+__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 -+ * -+ * 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 -+ -+#ifdef __UCLIBC_HAS_THREADS__ -+ -+#include -+ -+#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 --#include --#include -- --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); --} diff --git a/toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch b/toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch deleted file mode 100644 index 8b1a5a9ac9..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-new_dst_rules.patch +++ /dev/null @@ -1,101 +0,0 @@ ---- 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]); diff --git a/toolchain/uClibc/uClibc-0.9.28-rm-whitespace.patch b/toolchain/uClibc/uClibc-0.9.28-rm-whitespace.patch deleted file mode 100644 index 6004f91e32..0000000000 --- a/toolchain/uClibc/uClibc-0.9.28-rm-whitespace.patch +++ /dev/null @@ -1,86 +0,0 @@ -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 - --#if defined __cplusplus && __GNUC_PREREQ (2,95) -+#if defined __cplusplus && __GNUC_PREREQ(2,95) - # define __ASSERT_VOID_CAST static_cast - #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 diff --git a/toolchain/uClibc/uClibc-0.9.28.3-avr32.patch b/toolchain/uClibc/uClibc-0.9.28.3-avr32.patch new file mode 100644 index 0000000000..2e0f541a8e --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28.3-avr32.patch @@ -0,0 +1,7650 @@ +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 ++ ++__BEGIN_DECLS ++ ++/* Standard ELF types. */ ++ ++#include ++ ++/* 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 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 ++ ++#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 ++# ++# 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 ++#include ++#include ++#include ++ ++#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 ++#include ++ ++#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 ++ ++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 directly; include 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 directly; include 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 directly; include instead." ++#endif ++ ++#include ++ ++/* 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 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 ++ ++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 directly; use 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 directly; include instead." ++#endif ++ ++/* ++ * This includes the `__NR_' syscall numbers taken from the ++ * Linux kernel header files. It also defines the traditional ++ * `SYS_' macros for older programs. ++ */ ++#include ++ ++#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 ++#include ++ ++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 ++#include ++#include ++ ++/* ++ * 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 ++ ++ .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 ++# ++# 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 ++#include ++#include ++ ++#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 ++#include ++#include ++ ++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 ++ ++ .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 ++#include ++#include ++#include ++#include ++ ++#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 ++ ++ .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 instead." ++ ++#include ++ ++#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 ++ ++__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 ++#include ++#include ++#include ++ ++__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 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 ++#include ++#include ++#include ++ ++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 ++ ++ .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 ++#include ++ ++ .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 + #include +-_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 + + #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 ++ ++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 ++# ++# 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 ++# ++# 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 diff --git a/toolchain/uClibc/uClibc-0.9.29-002-atmel.1.patch b/toolchain/uClibc/uClibc-0.9.29-002-atmel.1.patch new file mode 100644 index 0000000000..d275ac2302 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.29-002-atmel.1.patch @@ -0,0 +1,3546 @@ +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 ++ ++#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 ++# ++# 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 ++ ++#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 ++ ++#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 ++ ++#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 ++ ++#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 ++ ++#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 ++# ++# 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 ++# ++# 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 ++ ++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 directly; include 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 directly; include 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 directly; include instead." ++#endif ++ ++#include ++ ++/* ++ * 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 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 directly; use 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 directly; include instead." ++#endif ++ ++/* ++ * This includes the `__NR_' syscall numbers taken from the ++ * Linux kernel header files. It also defines the traditional ++ * `SYS_' macros for older programs. ++ */ ++#include ++ ++#ifndef __ASSEMBLER__ ++ ++#include ++ ++#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 ++#include ++#include ++ ++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 ++#include ++#include ++ ++/* ++ * 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 ++ ++ .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 ++#include ++#include ++#include ++ ++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 ++ ++ .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 ++#include ++#include ++#include ++#include ++ ++#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 ++ ++ .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 instead." ++ ++#include ++ ++#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 ++#include ++#include ++#include ++ ++__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 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 ++#include ++#include ++#include ++ ++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 ++ ++ .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 ++#include ++ ++ .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 ++ ++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 ++ ++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 diff --git a/toolchain/uClibc/uClibc-0.9.29-avr32-fix-sa_onstack.patch b/toolchain/uClibc/uClibc-0.9.29-avr32-fix-sa_onstack.patch new file mode 100644 index 0000000000..722decdbd7 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.29-avr32-fix-sa_onstack.patch @@ -0,0 +1,31 @@ +From 974a769cc135bcfb1ea751db34a84ed6b5ceb509 Mon Sep 17 00:00:00 2001 +From: Haavard Skinnemoen +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 +--- + 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 + diff --git a/toolchain/uClibc/uClibc-0.9.29-avr32.patch b/toolchain/uClibc/uClibc-0.9.29-avr32.patch deleted file mode 100644 index 4c6addfd30..0000000000 --- a/toolchain/uClibc/uClibc-0.9.29-avr32.patch +++ /dev/null @@ -1,3579 +0,0 @@ -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 -+ -+#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 -+# -+# 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 -+ -+#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 -+ -+#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 -+ -+#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 -+ -+#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 -+ -+#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 -+# -+# 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 -+# -+# 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 -+ -+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 directly; include 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 directly; include 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 directly; include instead." -+#endif -+ -+#include -+ -+/* -+ * 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 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 directly; use 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 directly; include instead." -+#endif -+ -+/* -+ * This includes the `__NR_' syscall numbers taken from the -+ * Linux kernel header files. It also defines the traditional -+ * `SYS_' macros for older programs. -+ */ -+#include -+ -+#ifndef __ASSEMBLER__ -+ -+#include -+ -+#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 -+#include -+#include -+ -+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 -+#include -+#include -+ -+/* -+ * 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 -+ -+ .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 -+#include -+#include -+#include -+ -+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 -+ -+ .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 -+#include -+#include -+#include -+#include -+ -+#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 -+ -+ .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 instead." -+ -+#include -+ -+#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 -+#include -+#include -+#include -+ -+__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 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 -+#include -+#include -+#include -+ -+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 -+ -+ .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 -+#include -+ -+ .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 -+ -+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 -+ -+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 diff --git a/toolchain/uClibc/uClibc-0.9.29-fix-inverted-login-in-compare_and_swap-in-linuxthreads.patch b/toolchain/uClibc/uClibc-0.9.29-fix-inverted-login-in-compare_and_swap-in-linuxthreads.patch deleted file mode 100644 index 0cb0d1780c..0000000000 --- a/toolchain/uClibc/uClibc-0.9.29-fix-inverted-login-in-compare_and_swap-in-linuxthreads.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Haavard Skinnemoen -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 ---- - .../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 diff --git a/toolchain/uClibc/uClibc-0.9.29-fix-resolve-in-etc-hosts.patch b/toolchain/uClibc/uClibc-0.9.29-fix-resolve-in-etc-hosts.patch deleted file mode 100644 index a64bd4cda5..0000000000 --- a/toolchain/uClibc/uClibc-0.9.29-fix-resolve-in-etc-hosts.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 91cb4bb00e4d9463c0d41015152daa4b39acf762 Mon Sep 17 00:00:00 2001 -From: Hans-Christian Egtvedt -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 ---- - 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 - diff --git a/toolchain/uClibc/uClibc-0.9.29-linuxthreads.patch b/toolchain/uClibc/uClibc-0.9.29-linuxthreads.patch new file mode 100644 index 0000000000..8ce2439b46 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.29-linuxthreads.patch @@ -0,0 +1,145 @@ +--- 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 ++#include ++#include ++#include ++#include ++#include ++ ++ + /* 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 + diff --git a/toolchain/uClibc/uClibc-0.9.29-load-got-pointer-at-the-beginning-of-init-and-fini.patch b/toolchain/uClibc/uClibc-0.9.29-load-got-pointer-at-the-beginning-of-init-and-fini.patch deleted file mode 100644 index 27aa5a59c7..0000000000 --- a/toolchain/uClibc/uClibc-0.9.29-load-got-pointer-at-the-beginning-of-init-and-fini.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: Haavard Skinnemoen -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 ---- - 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