summaryrefslogtreecommitdiff
path: root/toolchain/uClibc/uClibc-0.9.28-300-ldso.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain/uClibc/uClibc-0.9.28-300-ldso.patch')
-rw-r--r--toolchain/uClibc/uClibc-0.9.28-300-ldso.patch5190
1 files changed, 5190 insertions, 0 deletions
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 000000000..4081fc7d1
--- /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 <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ #ifndef _LD_DEFS_H
+ #define _LD_DEFS_H
+
++#define FLAG_ANY -1
++#define FLAG_TYPE_MASK 0x00ff
++#define FLAG_LIBC4 0x0000
++#define FLAG_ELF 0x0001
++#define FLAG_ELF_LIBC5 0x0002
++#define FLAG_ELF_LIBC6 0x0003
++#define FLAG_ELF_UCLIBC 0x0004
++#define FLAG_REQUIRED_MASK 0xff00
++#define FLAG_SPARC_LIB64 0x0100
++#define FLAG_IA64_LIB64 0x0200
++#define FLAG_X8664_LIB64 0x0300
++#define FLAG_S390_LIB64 0x0400
++#define FLAG_POWERPC_LIB64 0x0500
++#define FLAG_MIPS64_LIBN32 0x0600
++#define FLAG_MIPS64_LIBN64 0x0700
++
+ #define LIB_ANY -1
+ #define LIB_DLL 0
+ #define LIB_ELF 1
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-elf.h uClibc-0.9.28/ldso/include/dl-elf.h
+--- uClibc-0.9.28.orig/ldso/include/dl-elf.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-elf.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ #ifndef LINUXELF_H
+ #define LINUXELF_H
+
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-hash.h uClibc-0.9.28/ldso/include/dl-hash.h
+--- uClibc-0.9.28.orig/ldso/include/dl-hash.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-hash.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ #ifndef _LD_HASH_H_
+ #define _LD_HASH_H_
+
+@@ -32,15 +39,15 @@
+ unsigned short usage_count;
+ unsigned short int init_flag;
+ unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
+- Elf32_Word nbucket;
+- Elf32_Word *elf_buckets;
++ Elf_Symndx nbucket;
++ Elf_Symndx *elf_buckets;
+ struct init_fini_list *init_fini;
+ struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */
+ /*
+ * These are only used with ELF style shared libraries
+ */
+- Elf32_Word nchain;
+- Elf32_Word *chains;
++ Elf_Symndx nchain;
++ Elf_Symndx *chains;
+ unsigned long dynamic_info[DYNAMIC_SIZE];
+
+ unsigned long n_phent;
+@@ -49,6 +56,9 @@
+ ElfW(Addr) relro_addr;
+ size_t relro_size;
+
++ dev_t st_dev; /* device */
++ ino_t st_ino; /* inode */
++
+ #ifdef __powerpc__
+ /* this is used to store the address of relocation data words, so
+ * we don't have to calculate it every time, which requires a divide */
+@@ -66,7 +76,6 @@
+ extern struct elf_resolve * _dl_loaded_modules;
+ extern struct dyn_elf * _dl_handles;
+
+-extern struct elf_resolve * _dl_check_hashed_files(const char * libname);
+ extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
+ char * loadaddr, unsigned long * dynamic_info,
+ unsigned long dynamic_addr, unsigned long dynamic_size);
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-string.h uClibc-0.9.28/ldso/include/dl-string.h
+--- uClibc-0.9.28.orig/ldso/include/dl-string.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-string.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,9 +1,24 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ #ifndef _LINUX_STRING_H_
+ #define _LINUX_STRING_H_
+
+-#include <dl-sysdep.h> // for do_rem
++#include <dl-sysdep.h> /* for do_rem */
+ #include <features.h>
+
++/* provide some sane defaults */
++#ifndef do_rem
++# define do_rem(result, n, base) ((result) = (n) % (base))
++#endif
++#ifndef do_div_10
++# define do_div_10(result, remain) ((result) /= 10)
++#endif
++
+ static size_t _dl_strlen(const char * str);
+ static char *_dl_strcat(char *dst, const char *src);
+ static char * _dl_strcpy(char * dst,const char *src);
+@@ -26,8 +41,8 @@
+ static __always_inline size_t _dl_strlen(const char * str)
+ {
+ register const char *ptr = (char *) str-1;
+-
+- while (*++ptr);
++ while (*++ptr)
++ ;/* empty */
+ return (ptr - str);
+ }
+
+@@ -49,7 +64,8 @@
+ register char *ptr = dst;
+
+ dst--;src--;
+- while ((*++dst = *++src) != 0);
++ while ((*++dst = *++src) != 0)
++ ;/* empty */
+
+ return ptr;
+ }
+@@ -63,8 +79,7 @@
+ c2 = (unsigned char) *++s2;
+ if (c1 == '\0')
+ return c1 - c2;
+- }
+- while (c1 == c2);
++ } while (c1 == c2);
+
+ return c1 - c2;
+ }
+@@ -98,43 +113,41 @@
+ return 0;
+ }
+
+-static inline char * _dl_strrchr(const char *str, int c)
++static __always_inline char * _dl_strrchr(const char *str, int c)
+ {
+- register char *prev = 0;
+- register char *ptr = (char *) str-1;
++ register char *prev = 0;
++ register char *ptr = (char *) str-1;
+
+- while (*++ptr != '\0') {
+- if (*ptr == c)
+- prev = ptr;
+- }
+- if (c == '\0')
+- return(ptr);
+- return(prev);
++ while (*++ptr != '\0') {
++ if (*ptr == c)
++ prev = ptr;
++ }
++ if (c == '\0')
++ return(ptr);
++ return(prev);
+ }
+
+-static inline char * _dl_strstr(const char *s1, const char *s2)
++static __always_inline char * _dl_strstr(const char *s1, const char *s2)
+ {
+- register const char *s = s1;
+- register const char *p = s2;
++ register const char *s = s1;
++ register const char *p = s2;
+
+- do {
+- if (!*p) {
+- return (char *) s1;;
+- }
+- if (*p == *s) {
+- ++p;
+- ++s;
+- } else {
+- p = s2;
+- if (!*s) {
+- return NULL;
+- }
+- s = ++s1;
+- }
+- } while (1);
++ do {
++ if (!*p)
++ return (char *) s1;;
++ if (*p == *s) {
++ ++p;
++ ++s;
++ } else {
++ p = s2;
++ if (!*s)
++ return NULL;
++ s = ++s1;
++ }
++ } while (1);
+ }
+
+-static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
++static __always_inline void * _dl_memcpy(void * dst, const void * src, size_t len)
+ {
+ register char *a = dst-1;
+ register const char *b = src-1;
+@@ -163,27 +176,28 @@
+ /* Will generate smaller and faster code due to loop unrolling.*/
+ static __always_inline void * _dl_memset(void *to, int c, size_t n)
+ {
+- unsigned long chunks;
+- unsigned long *tmp_to;
++ unsigned long chunks;
++ unsigned long *tmp_to;
+ unsigned char *tmp_char;
+
+- chunks = n / 4;
+- tmp_to = to + n;
+- c = c << 8 | c;
+- c = c << 16 | c;
+- if (!chunks)
+- goto lessthan4;
+- do {
+- *--tmp_to = c;
+- } while (--chunks);
+- lessthan4:
+- n = n % 4;
+- if (!n ) return to;
+- tmp_char = (unsigned char *)tmp_to;
+- do {
+- *--tmp_char = c;
+- } while (--n);
+- return to;
++ chunks = n / 4;
++ tmp_to = to + n;
++ c = c << 8 | c;
++ c = c << 16 | c;
++ if (!chunks)
++ goto lessthan4;
++ do {
++ *--tmp_to = c;
++ } while (--chunks);
++lessthan4:
++ n = n % 4;
++ if (!n)
++ return to;
++ tmp_char = (unsigned char *)tmp_to;
++ do {
++ *--tmp_char = c;
++ } while (--n);
++ return to;
+ }
+ #else
+ static __always_inline void * _dl_memset(void * str,int c,size_t len)
+@@ -225,10 +239,10 @@
+ char *p = &local[22];
+ *--p = '\0';
+ do {
+- char temp;
+- do_rem(temp, i, 10);
+- *--p = '0' + temp;
+- i /= 10;
++ char temp;
++ do_rem(temp, i, 10);
++ *--p = '0' + temp;
++ do_div_10(i, temp);
+ } while (i > 0);
+ return p;
+ }
+@@ -242,9 +256,9 @@
+ do {
+ char temp = i & 0xf;
+ if (temp <= 0x09)
+- *--p = '0' + temp;
++ *--p = '0' + temp;
+ else
+- *--p = 'a' - 0x0a + temp;
++ *--p = 'a' - 0x0a + temp;
+ i >>= 4;
+ } while (i > 0);
+ *--p = 'x';
+@@ -270,8 +284,8 @@
+
+ /* On some arches constant strings are referenced through the GOT.
+ * This requires that load_addr must already be defined... */
+-#if defined(mc68000) || defined(__arm__) || defined(__mips__) \
+- || defined(__sh__) || defined(__powerpc__)
++#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \
++ defined(__mips__) || defined(__sh__) || defined(__powerpc__)
+ # define CONSTANT_STRING_GOT_FIXUP(X) \
+ if ((X) < (const char *) load_addr) (X) += load_addr
+ # define NO_EARLY_SEND_STDERR
+@@ -318,7 +332,7 @@
+ do { \
+ do_rem(v, (X), 10); \
+ *--tmp2 = '0' + v; \
+- (X) /= 10; \
++ do_div_10((X), v); \
+ } while ((X) > 0); \
+ _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
+ }
+diff -urN uClibc-0.9.28.orig/ldso/include/dl-syscall.h uClibc-0.9.28/ldso/include/dl-syscall.h
+--- uClibc-0.9.28.orig/ldso/include/dl-syscall.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dl-syscall.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ #ifndef _LD_SYSCALL_H_
+ #define _LD_SYSCALL_H_
+
+@@ -12,9 +19,8 @@
+ #include <bits/kernel_stat.h>
+ #include <bits/kernel_types.h>
+
+-
+ /* _dl_open() parameters */
+-#define O_RDONLY 0x0000
++#define O_RDONLY 00
+ #define O_WRONLY 01
+ #define O_RDWR 02
+ #define O_CREAT 0100
+@@ -39,18 +45,6 @@
+ #define S_IWRITE 0200 /* Write by owner. */
+ #define S_IEXEC 0100 /* Execute by owner. */
+
+-/* Stuff for _dl_mmap */
+-#if 0
+-#define MAP_FAILED ((void *) -1)
+-#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
+-#else
+-#ifndef _dl_MAX_ERRNO
+-#define _dl_MAX_ERRNO 4096
+-#endif
+-#define _dl_mmap_check_error(__res) \
+- (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
+-#endif
+-
+
+
+ /* Here are the definitions for some syscalls that are used
+@@ -66,54 +60,125 @@
+ static inline _syscall1(int, _dl_close, int, fd);
+
+ #define __NR__dl_open __NR_open
+-static inline _syscall3(int, _dl_open, const char *, fn, int, flags, __kernel_mode_t, mode);
++static inline _syscall3(int, _dl_open, const char *, fn, int, flags,
++ __kernel_mode_t, mode);
+
+ #define __NR__dl_write __NR_write
+ static inline _syscall3(unsigned long, _dl_write, int, fd,
+- const void *, buf, unsigned long, count);
++ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_read __NR_read
+ static inline _syscall3(unsigned long, _dl_read, int, fd,
+- const void *, buf, unsigned long, count);
++ const void *, buf, unsigned long, count);
+
+ #define __NR__dl_mprotect __NR_mprotect
+-static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, len, int, prot);
++static inline _syscall3(int, _dl_mprotect, const void *, addr,
++ unsigned long, len, int, prot);
+
+ #define __NR__dl_stat __NR_stat
+-static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);
++static inline _syscall2(int, _dl_stat, const char *, file_name,
++ struct stat *, buf);
++
++#define __NR__dl_fstat __NR_fstat
++static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
+
+ #define __NR__dl_munmap __NR_munmap
+ static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
+
++#ifdef __NR_getxuid
++# define __NR_getuid __NR_getxuid
++#endif
+ #define __NR__dl_getuid __NR_getuid
+ static inline _syscall0(uid_t, _dl_getuid);
+
++#ifndef __NR_geteuid
++# define __NR_geteuid __NR_getuid
++#endif
+ #define __NR__dl_geteuid __NR_geteuid
+ static inline _syscall0(uid_t, _dl_geteuid);
+
++#ifdef __NR_getxgid
++# define __NR_getgid __NR_getxgid
++#endif
+ #define __NR__dl_getgid __NR_getgid
+ static inline _syscall0(gid_t, _dl_getgid);
+
++#ifndef __NR_getegid
++# define __NR_getegid __NR_getgid
++#endif
+ #define __NR__dl_getegid __NR_getegid
+ static inline _syscall0(gid_t, _dl_getegid);
+
++#ifdef __NR_getxpid
++# define __NR_getpid __NR_getxpid
++#endif
+ #define __NR__dl_getpid __NR_getpid
+ static inline _syscall0(gid_t, _dl_getpid);
+
+ #define __NR__dl_readlink __NR_readlink
+-static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
++static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf,
++ size_t, bufsiz);
+
+-#ifdef __NR_mmap
+-#ifdef MMAP_HAS_6_ARGS
+-#define __NR__dl_mmap __NR_mmap
+-static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
+- int, prot, int, flags, int, fd, off_t, offset);
++#ifdef __UCLIBC_HAS_SSP__
++# include <sys/time.h>
++# define __NR__dl_gettimeofday __NR_gettimeofday
++static inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
++# ifdef __USE_BSD
++ struct timezone *, tz);
++# else
++ void *, tz);
++# endif
++#endif
++
++
++/* handle all the fun mmap intricacies */
++#if (defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)) || !defined(__NR_mmap2)
++# define _dl_MAX_ERRNO 4096
++# define _dl_mmap_check_error(__res) \
++ (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
+ #else
+-#define __NR__dl_mmap_real __NR_mmap
+-static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++# define MAP_FAILED ((void *) -1)
++# define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED)
++#endif
++
++/* first try mmap(), syscall6() style */
++#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)
++
++# define __NR__dl_mmap __NR_mmap
++static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
++ int, prot, int, flags, int, fd, off_t, offset);
++
++/* then try mmap2() */
++#elif defined(__NR_mmap2)
++
++# define __NR___syscall_mmap2 __NR_mmap2
++static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len,
++ int, prot, int, flags, int, fd, off_t, offset);
++
++/* Some architectures always use 12 as page shift for mmap2() eventhough the
++ * real PAGE_SHIFT != 12. Other architectures use the same value as
++ * PAGE_SHIFT...
++ */
++#ifndef MMAP2_PAGE_SHIFT
++# define MMAP2_PAGE_SHIFT 12
++#endif
+
+ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+- int flags, int fd, unsigned long offset)
++ int flags, int fd, unsigned long offset)
++{
++ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
++ return MAP_FAILED;
++ return __syscall_mmap2(addr, size, prot, flags,
++ fd, (off_t) (offset >> MMAP2_PAGE_SHIFT));
++}
++
++/* finally, fall back to mmap(), syscall1() style */
++#elif defined(__NR_mmap)
++
++# define __NR__dl_mmap_real __NR_mmap
++static inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer);
++static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
++ int flags, int fd, unsigned long offset)
+ {
+ unsigned long buffer[6];
+
+@@ -125,24 +190,9 @@
+ buffer[5] = (unsigned long) offset;
+ return (void *) _dl_mmap_real(buffer);
+ }
+-#endif
+-#elif defined __NR_mmap2
+-#define __NR___syscall_mmap2 __NR_mmap2
+-static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
+- size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+-/*always 12, even on architectures where PAGE_SHIFT != 12 */
+-#define MMAP2_PAGE_SHIFT 12
+-static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
+- int flags, int fd, unsigned long offset)
+-{
+- if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1))
+- return MAP_FAILED;
+- return(__syscall_mmap2(addr, size, prot, flags,
+- fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
+-}
++
+ #else
+-#error "Your architecture doesn't seem to provide mmap() !?"
++# error "Your architecture doesn't seem to provide mmap() !?"
+ #endif
+
+ #endif /* _LD_SYSCALL_H_ */
+-
+diff -urN uClibc-0.9.28.orig/ldso/include/dlfcn.h uClibc-0.9.28/ldso/include/dlfcn.h
+--- uClibc-0.9.28.orig/ldso/include/dlfcn.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/dlfcn.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ /* User functions for run-time dynamic loading. libdl version */
+ #ifndef _DLFCN_H
+ #define _DLFCN_H 1
+diff -urN uClibc-0.9.28.orig/ldso/include/ldso.h uClibc-0.9.28/ldso/include/ldso.h
+--- uClibc-0.9.28.orig/ldso/include/ldso.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/ldso.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ #ifndef _LDSO_H_
+ #define _LDSO_H_
+
+@@ -20,13 +27,15 @@
+ /* Pull in compiler and arch stuff */
+ #include <stdlib.h>
+ #include <stdarg.h>
++#include <bits/wordsize.h>
+ /* Pull in the arch specific type information */
+ #include <sys/types.h>
++/* Pull in the arch specific page size */
++#include <bits/uClibc_page.h>
++#define attribute_unused __attribute__ ((unused))
+ /* Pull in the ldso syscalls and string functions */
+ #include <dl-syscall.h>
+ #include <dl-string.h>
+-/* Pull in the arch specific page size */
+-#include <bits/uClibc_page.h>
+ /* Now the ldso specific headers */
+ #include <dl-elf.h>
+ #include <dl-hash.h>
+diff -urN uClibc-0.9.28.orig/ldso/include/unsecvars.h uClibc-0.9.28/ldso/include/unsecvars.h
+--- uClibc-0.9.28.orig/ldso/include/unsecvars.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/include/unsecvars.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,3 +1,10 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Copyright (C) 2000-2005 by Erik Andersen <andersen@codepoet.org>
++ *
++ * GNU Lesser General Public License version 2.1 or later.
++ */
++
+ /*
+ * Environment variable to be removed for SUID programs. The names are all
+ * stuffed in a single string which means they have to be terminated with a
+@@ -5,22 +12,21 @@
+ */
+
+ #define UNSECURE_ENVVARS \
+- "LD_AOUT_PRELOAD\0" \
+- "LD_AOUT_LIBRARY_PATH\0" \
+ "LD_PRELOAD\0" \
+ "LD_LIBRARY_PATH\0" \
+ "LD_DEBUG\0" \
+ "LD_DEBUG_OUTPUT\0" \
+ "LD_TRACE_LOADED_OBJECTS\0" \
+- "HOSTALIASES\0" \
+- "LOCALDOMAIN\0" \
+- "RES_OPTIONS\0" \
+ "TMPDIR\0"
+
+ /*
++ * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h
++ * though used by ldd
++ *
+ * These environment variables are defined by glibc but ignored in
+ * uClibc, but may very well have an equivalent in uClibc.
+ *
+- * MALLOC_TRACE, RESOLV_HOST_CONF, TZDIR, GCONV_PATH, LD_USE_LOAD_BIAS,
+- * LD_PROFILE, LD_ORIGIN_PATH, LOCPATH, NLSPATH
++ * LD_ORIGIN_PATH, LD_PROFILE, LD_USE_LOAD_BIAS, LD_DYNAMIC_WEAK, LD_SHOW_AUXV,
++ * GCONV_PATH, GETCONF_DIR, HOSTALIASES, LOCALDOMAIN, LOCPATH, MALLOC_TRACE,
++ * NLSPATH, RESOLV_HOST_CONF, RES_OPTIONS, TZDIR
+ */
+diff -urN uClibc-0.9.28.orig/ldso/ldso/Makefile uClibc-0.9.28/ldso/ldso/Makefile
+--- uClibc-0.9.28.orig/ldso/ldso/Makefile 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/Makefile 2006-04-28 00:14:35.000000000 -0600
+@@ -42,7 +42,9 @@
+ endif
+ XXFLAGS+= -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \
+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I. -I$(TOPDIR)include
++ -fno-builtin -nostdinc -D_LIBC \
++ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \
++ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include
+
+ # BEWARE!!! At least mips* will die if -O0 is used!!!
+ XXFLAGS:=$(XXFLAGS:-O0=-O1)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h uClibc-0.9.28/ldso/ldso/arm/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,10 +1,15 @@
+ /* vi: set sw=4 ts=4: */
+ /*
+ * Architecture specific code used by dl-startup.c
+- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
++ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
++ *
++ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+-asm(
++#include <features.h>
++
++#if !defined(__thumb__)
++__asm__(
+ " .text\n"
+ " .globl _start\n"
+ " .type _start,%function\n"
+@@ -40,7 +45,78 @@
+ " ldr r0, .L_FINI_PROC\n"
+ " ldr r0, [sl, r0]\n"
+ " @ jump to the user_s entry point\n"
++#if defined(__USE_BX__)
++ " bx r6\n"
++#else
++ " mov pc, r6\n"
++#endif
++ ".L_GET_GOT:\n"
++ " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
++ ".L_SKIP_ARGS:\n"
++ " .word _dl_skip_args(GOTOFF)\n"
++ ".L_FINI_PROC:\n"
++ " .word _dl_fini(GOT)\n"
++ "\n\n"
++ " .size _start,.-_start\n"
++ ".previous\n"
++);
++#else
++__asm__(
++ " .text\n"
++ " .arm\n"
++ " .globl _start\n"
++ " .type _start,%function\n"
++ "_start:\n"
++ " @ dumb: can't persuade the linker to make the start address\n"
++ " @ odd, so use an arm function and change to thumb (_dl_start\n"
++ " @ is thumb)\n"
++ " adr r0, __dl_thumb_start+1\n"
++ " bx r0\n"
++ "\n\n"
++ " .thumb\n"
++ " .globl __dl_thumb_start\n"
++ " .thumb_func\n"
++ " .type __dl_thumb_start,%function\n"
++ "__dl_thumb_start:\n"
++ " @ at start time, all the args are on the stack\n"
++ " mov r0, sp\n"
++ " bl _dl_start\n"
++ " @ returns user entry point in r0\n"
++ " mov r6, r0\n"
++ " @ we are PIC code, so get global offset table\n"
++ " ldr r7, .L_GET_GOT\n"
++ ".L_GOT_GOT:\n"
++ " add r7, pc\n"
++ " @ See if we were run as a command with the executable file\n"
++ " @ name as an extra leading argument.\n"
++ " ldr r4, .L_SKIP_ARGS\n"
++ " ldr r4, [r7, r4]\n"
++ " @ get the original arg count\n"
++ " ldr r1, [sp]\n"
++ " @ subtract _dl_skip_args from it\n"
++ " sub r1, r1, r4\n"
++ " @ adjust the stack pointer to skip them\n"
++ " lsl r4, r4, #2\n"
++ " add sp, r4\n"
++ " @ get the argv address\n"
++ " add r2, sp, #4\n"
++ " @ store the new argc in the new stack location\n"
++ " str r1, [sp]\n"
++ " @ compute envp\n"
++ " lsl r3, r1, #2\n"
++ " add r3, r3, r2\n"
++ " add r3, #4\n"
++ "\n\n"
++ " @ load the finalizer function\n"
++ " ldr r0, .L_FINI_PROC\n"
++ " ldr r0, [r7, r0]\n"
++ " @ jump to the user_s entry point\n"
++#if defined(__USE_BX__)
++ " bx r6\n"
++#else
+ " mov pc, r6\n"
++#endif
++ "\n\n"
+ ".L_GET_GOT:\n"
+ " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
+ ".L_SKIP_ARGS:\n"
+@@ -51,6 +127,7 @@
+ " .size _start,.-_start\n"
+ ".previous\n"
+ );
++#endif
+
+
+ /* Get a pointer to the argv array. On many platforms this can be just
+@@ -115,9 +192,3 @@
+ _dl_exit(1);
+ }
+ }
+-
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,6 +1,7 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/arm/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -43,6 +43,7 @@
+ return m;
+ }
+ #define do_rem(result, n, base) ((result) = arm_modulus(n, base))
++#define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul))
+
+ /* Here we define the magic numbers that this dynamic loader should accept */
+ #define MAGIC1 EM_ARM
+@@ -85,7 +86,25 @@
+ extern void __dl_start asm ("_dl_start");
+ Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+ Elf32_Addr pcrel_addr;
++#if !defined __thumb__
+ asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
++#else
++ int tmp;
++ /* The above adr will not work on thumb because it
++ * is negative. The only safe way is to temporarily
++ * swap to arm.
++ */
++ asm( ".align 2\n"
++ " bx pc\n"
++ " nop \n"
++ " .arm \n"
++ " adr %0, _dl_start\n"
++ " .align 2\n"
++ " orr %1, pc, #1\n"
++ " bx %1\n"
++ " .force_thumb\n"
++ : "=r" (pcrel_addr), "=&r" (tmp));
++#endif
+ return pcrel_addr - got_addr;
+ }
+
+diff -urN uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c uClibc-0.9.28/ldso/ldso/arm/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/arm/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/arm/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -38,6 +38,8 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+@@ -63,7 +65,6 @@
+ strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+-
+ if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) {
+ _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
+ _dl_progname);
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h uClibc-0.9.28/ldso/ldso/cris/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -4,22 +4,43 @@
+
+ /* This code fixes the stack pointer so that the dynamic linker
+ * can find argc, argv and auxvt (Auxillary Vector Table). */
++#ifdef __arch_v32
++
++asm("" \
++" .text\n" \
++" .globl _start\n" \
++" .type _start,@function\n" \
++"_start:\n" \
++" move.d $sp,$r10\n" \
++" lapc _dl_start,$r9\n" \
++" jsr $r9\n" \
++" nop\n" \
++" moveq 0,$r8\n" \
++" jump $r10\n" \
++" move $r8,$srp\n" \
++" .size _start,.-_start\n" \
++" .previous\n" \
++);
++
++#else
++
+ asm("" \
+ " .text\n" \
+ " .globl _start\n" \
+ " .type _start,@function\n" \
+ "_start:\n" \
+-" move.d $sp,$r10\n" \
+-" move.d $pc,$r9\n" \
+-" add.d _dl_start - ., $r9\n" \
+-" jsr $r9\n" \
+-" moveq 0,$r8\n" \
+-" move $r8,$srp\n" \
+-" jump $r10\n" \
++" move.d $sp,$r10\n" \
++" move.d $pc,$r9\n" \
++" add.d _dl_start - ., $r9\n" \
++" jsr $r9\n" \
++" moveq 0,$r8\n" \
++" move $r8,$srp\n" \
++" jump $r10\n" \
+ " .size _start,.-_start\n" \
+ " .previous\n" \
+ );
+
++#endif /* __arch_v32 */
+
+ /* Get a pointer to the argv array. On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+@@ -58,8 +79,3 @@
+ break;
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,5 +1,6 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/cris/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -18,8 +18,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 8192 bytes alignment */
+ #define PAGE_ALIGN 0xffffe000
+ #define ADDR_ALIGN 0x1fff
+@@ -68,8 +66,32 @@
+ {
+ Elf32_Addr gotaddr_diff;
+
++#ifdef __arch_v32
++ extern char ___CRISv32_dummy[] __asm__ ("_dl_start");
++
++ __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t"
++ "lapc _dl_start,%0\n\t"
++ "sub.d [$acr],%0"
++ /* For v32, we need to force GCC to have R0 loaded with
++ _GLOBAL_OFFSET_TABLE_ at this point, which might not
++ otherwise have happened in the caller. (For v10, it's
++ loaded for non-global variables too, so we don't need
++ anything special there.) We accomplish this by faking the
++ address of a global variable (as seen by GCC) as input to
++ the asm; that address calculation goes through the GOT.
++ Use of this function happens before we've filled in the
++ GOT, so the address itself will not be correctly
++ calculated, therefore we don't use any symbol whose
++ address may be re-used later on. Let's just reuse the
++ _dl_start symbol, faking it as a global by renaming it as
++ another variable through an asm. */
++ : "=r" (gotaddr_diff)
++ : "g" (___CRISv32_dummy)
++ : "acr");
++#else
+ __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t"
+ "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff));
++#endif
+ return gotaddr_diff;
+ }
+
+diff -urN uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S uClibc-0.9.28/ldso/ldso/cris/resolve.S
+--- uClibc-0.9.28.orig/ldso/ldso/cris/resolve.S 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/cris/resolve.S 2006-04-28 00:14:35.000000000 -0600
+@@ -17,33 +17,73 @@
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve,@function
+
++#ifdef __arch_v32
++
++_dl_linux_resolve:
++ subq 4,$sp
++ move.d $r0,[$sp]
++ subq 4,$sp
++ move.d $r13,[$sp]
++ subq 4,$sp
++ move.d $r12,[$sp]
++ subq 4,$sp
++ move.d $r11,[$sp]
++ subq 4,$sp
++ addoq 5*4,$sp,$acr
++ move.d $r10,[$sp]
++ subq 4,$sp
++ move $mof,$r10
++ move.d $r9,[$sp]
++ subq 4,$sp
++ move.d [$acr],$r11
++ move $srp,[$sp]
++ lapc _GLOBAL_OFFSET_TABLE_,$r0
++ move.d _dl_linux_resolver:PLTG,$r9
++ add.d $r0,$r9
++ jsr $r9
++ nop
++ move.d $r10,$acr
++ move [$sp+],$srp
++ move.d [$sp+],$r9
++ move.d [$sp+],$r10
++ move.d [$sp+],$r11
++ move.d [$sp+],$r12
++ move.d [$sp+],$r13
++ move.d [$sp+],$r0
++ jump $acr
++ addq 4,$sp
++
++#else
++
+ _dl_linux_resolve:
+- push $r13
+- push $r12
+- push $r11
+- push $r10
+- push $r9
+- push $r0
+- push $srp
+- move.d [$sp+7*4],$r11
+- move $mof,$r10
++ push $r13
++ push $r12
++ push $r11
++ push $r10
++ push $r9
++ push $r0
++ push $srp
++ move.d [$sp+7*4],$r11
++ move $mof,$r10
+ #ifdef __PIC__
+- move.d $pc,$r0
+- sub.d .:GOTOFF,$r0
+- move.d _dl_linux_resolver:PLTG,$r9
+- add.d $r0,$r9
+- jsr $r9
++ move.d $pc,$r0
++ sub.d .:GOTOFF,$r0
++ move.d _dl_linux_resolver:PLTG,$r9
++ add.d $r0,$r9
++ jsr $r9
+ #else
+- jsr _dl_linux_resolver
++ jsr _dl_linux_resolver
+ #endif
+- move.d $r10,[$sp+7*4]
+- pop $srp
+- pop $r0
+- pop $r9
+- pop $r10
+- pop $r11
+- pop $r12
+- pop $r13
+- jump [$sp+]
++ move.d $r10,[$sp+7*4]
++ pop $srp
++ pop $r0
++ pop $r9
++ pop $r10
++ pop $r11
++ pop $r12
++ pop $r13
++ jump [$sp+]
++
++#endif /* __arch_v32 */
+
+ .size _dl_linux_resolve, . - _dl_linux_resolve
+diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-elf.c uClibc-0.9.28/ldso/ldso/dl-elf.c
+--- uClibc-0.9.28.orig/ldso/ldso/dl-elf.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/dl-elf.c 2006-05-02 13:50:58.000000000 -0600
+@@ -3,7 +3,7 @@
+ * This file contains the helper routines to load an ELF shared
+ * library into memory and add the symbol table info to the chain.
+ *
+- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
++ * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+@@ -60,8 +60,8 @@
+ _dl_cache_addr = (caddr_t) _dl_mmap(0, _dl_cache_size, PROT_READ, MAP_SHARED, fd, 0);
+ _dl_close(fd);
+ if (_dl_mmap_check_error(_dl_cache_addr)) {
+- _dl_dprintf(2, "%s: can't map cache '%s'\n",
+- _dl_progname, LDSO_CACHE);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
++ _dl_progname, __LINE__, LDSO_CACHE);
+ return -1;
+ }
+
+@@ -115,7 +115,7 @@
+ #endif
+
+
+-void
++void
+ _dl_protect_relro (struct elf_resolve *l)
+ {
+ ElfW(Addr) start = ((l->loadaddr + l->relro_addr)
+@@ -136,27 +136,41 @@
+ search_for_named_library(const char *name, int secure, const char *path_list,
+ struct dyn_elf **rpnt)
+ {
+- char *path, *path_n;
+- char mylibname[2050];
++ char *path, *path_n, *mylibname;
+ struct elf_resolve *tpnt;
+- int done = 0;
++ int done;
+
+ if (path_list==NULL)
+ return NULL;
+
+- /* We need a writable copy of this string */
+- path = _dl_strdup(path_list);
+- if (!path) {
++ /* We need a writable copy of this string, but we don't
++ * need this allocated permanently since we don't want
++ * to leak memory, so use alloca to put path on the stack */
++ done = _dl_strlen(path_list);
++ path = alloca(done + 1);
++
++ /* another bit of local storage */
++ mylibname = alloca(2050);
++
++ /* gcc inlines alloca using a single instruction adjusting
++ * the stack pointer and no stack overflow check and thus
++ * no NULL error return. No point leaving in dead code... */
++#if 0
++ if (!path || !mylibname) {
+ _dl_dprintf(2, "Out of memory!\n");
+ _dl_exit(0);
+ }
++#endif
++
++ _dl_memcpy(path, path_list, done+1);
+
+ /* Unlike ldd.c, don't bother to eliminate double //s */
+
+ /* Replace colons with zeros in path_list */
+ /* : at the beginning or end of path maps to CWD */
+ /* :: anywhere maps CWD */
+- /* "" maps to CWD */
++ /* "" maps to CWD */
++ done = 0;
+ path_n = path;
+ do {
+ if (*path == 0) {
+@@ -180,71 +194,6 @@
+ return NULL;
+ }
+
+-/* Check if the named library is already loaded... */
+-struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
+- int trace_loaded_objects)
+-{
+- const char *pnt, *pnt1;
+- struct elf_resolve *tpnt1;
+- const char *libname, *libname2;
+- static const char libc[] = "libc.so.";
+- static const char aborted_wrong_lib[] = "%s: aborted attempt to load %s!\n";
+-
+- pnt = libname = full_libname;
+-
+- _dl_if_debug_dprint("Checking if '%s' is already loaded\n", full_libname);
+- /* quick hack to ensure mylibname buffer doesn't overflow. don't
+- allow full_libname or any directory to be longer than 1024. */
+- if (_dl_strlen(full_libname) > 1024)
+- return NULL;
+-
+- /* Skip over any initial initial './' and '/' stuff to
+- * get the short form libname with no path garbage */
+- pnt1 = _dl_strrchr(pnt, '/');
+- if (pnt1) {
+- libname = pnt1 + 1;
+- }
+-
+- /* Make sure they are not trying to load the wrong C library!
+- * This sometimes happens esp with shared libraries when the
+- * library path is somehow wrong! */
+-#define isdigit(c) (c >= '0' && c <= '9')
+- if ((_dl_strncmp(libname, libc, 8) == 0) && _dl_strlen(libname) >=8 &&
+- isdigit(libname[8]))
+- {
+- /* Abort attempts to load glibc, libc5, etc */
+- if ( libname[8]!='0') {
+- if (!trace_loaded_objects) {
+- _dl_dprintf(2, aborted_wrong_lib, libname, _dl_progname);
+- _dl_exit(1);
+- }
+- return NULL;
+- }
+- }
+-
+- /* Critical step! Weed out duplicates early to avoid
+- * function aliasing, which wastes memory, and causes
+- * really bad things to happen with weaks and globals. */
+- for (tpnt1 = _dl_loaded_modules; tpnt1; tpnt1 = tpnt1->next) {
+-
+- /* Skip over any initial initial './' and '/' stuff to
+- * get the short form libname with no path garbage */
+- libname2 = tpnt1->libname;
+- pnt1 = _dl_strrchr(libname2, '/');
+- if (pnt1) {
+- libname2 = pnt1 + 1;
+- }
+-
+- if (_dl_strcmp(libname2, libname) == 0) {
+- /* Well, that was certainly easy */
+- return tpnt1;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-
+ /* Used to return error codes back to dlopen et. al. */
+ unsigned long _dl_error_number;
+ unsigned long _dl_internal_error_number;
+@@ -271,14 +220,6 @@
+ libname = pnt + 1;
+ }
+
+- /* Critical step! Weed out duplicates early to avoid
+- * function aliasing, which wastes memory, and causes
+- * really bad things to happen with weaks and globals. */
+- if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) {
+- tpnt1->usage_count++;
+- return tpnt1;
+- }
+-
+ _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
+ /* If the filename has any '/', try it straight and leave it at that.
+ For IBCS2 compatibility under linux, we substitute the string
+@@ -290,7 +231,6 @@
+ if (tpnt1) {
+ return tpnt1;
+ }
+- //goto goof;
+ }
+
+ /*
+@@ -411,56 +351,45 @@
+ int i, flags, piclib, infile;
+ ElfW(Addr) relro_addr = 0;
+ size_t relro_size = 0;
+-
+- /* If this file is already loaded, skip this step */
+- tpnt = _dl_check_hashed_files(libname);
+- if (tpnt) {
+- if (*rpnt) {
+- (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
+- _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
+- (*rpnt)->next->prev = (*rpnt);
+- *rpnt = (*rpnt)->next;
+- (*rpnt)->dyn = tpnt;
+- tpnt->symbol_scope = _dl_symbol_tables;
+- }
+- tpnt->usage_count++;
+- tpnt->libtype = elf_lib;
+- _dl_if_debug_dprint("file='%s'; already loaded\n", libname);
+- return tpnt;
+- }
+-
+- /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
+- we don't load the library if it isn't setuid. */
+-
+- if (secure) {
+- struct stat st;
+-
+- if (_dl_stat(libname, &st) || !(st.st_mode & S_ISUID))
+- return NULL;
+- }
++ struct stat st;
+
+ libaddr = 0;
+ infile = _dl_open(libname, O_RDONLY, 0);
+ if (infile < 0) {
+-#if 0
+- /*
+- * NO! When we open shared libraries we may search several paths.
+- * it is inappropriate to generate an error here.
+- */
+- _dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
+-#endif
+ _dl_internal_error_number = LD_ERROR_NOFILE;
+ return NULL;
+ }
+
++ if (_dl_fstat(infile, &st) < 0) {
++ _dl_internal_error_number = LD_ERROR_NOFILE;
++ _dl_close(infile);
++ return NULL;
++ }
++ /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
++ we don't load the library if it isn't setuid. */
++ if (secure)
++ if (!(st.st_mode & S_ISUID)) {
++ _dl_close(infile);
++ return NULL;
++ }
++
++ /* Check if file is already loaded */
++ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
++ if(tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
++ /* Already loaded */
++ tpnt->usage_count++;
++ _dl_close(infile);
++ return tpnt;
++ }
++ }
+ header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(header)) {
+- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_close(infile);
+ return NULL;
+- };
++ }
+
+ _dl_read(infile, header, _dl_pagesize);
+ epnt = (ElfW(Ehdr) *) (intptr_t) header;
+@@ -475,7 +404,7 @@
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1
+ #ifdef MAGIC2
+@@ -490,7 +419,7 @@
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
+
+@@ -502,7 +431,7 @@
+ _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
+ _dl_progname, libname);
+ dynamic_addr = ppnt->p_vaddr;
+- };
++ }
+
+ if (ppnt->p_type == PT_LOAD) {
+ /* See if this is a PIC library. */
+@@ -518,7 +447,7 @@
+ }
+ }
+ ppnt++;
+- };
++ }
+
+ maxvma = (maxvma + ADDR_ALIGN) & ~ADDR_ALIGN;
+ minvma = minvma & ~0xffffU;
+@@ -530,12 +459,12 @@
+ status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
+ maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(status)) {
+- _dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+ libaddr = (unsigned long) status;
+ flags |= MAP_FIXED;
+
+@@ -567,14 +496,14 @@
+ ppnt->p_offset & OFFS_ALIGN);
+
+ if (_dl_mmap_check_error(status)) {
+- _dl_dprintf(2, "%s: can't map '%s'\n",
+- _dl_progname, libname);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
++ _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_munmap((char *) libaddr, maxvma - minvma);
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ /* Pad the last page with zeroes. */
+ cpnt = (char *) (status + (ppnt->p_vaddr & ADDR_ALIGN) +
+@@ -601,21 +530,21 @@
+ ppnt->p_filesz, LXFLAGS(ppnt->p_flags), flags,
+ infile, ppnt->p_offset & OFFS_ALIGN);
+ if (_dl_mmap_check_error(status)) {
+- _dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
++ _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
+ _dl_munmap((char *) libaddr, maxvma - minvma);
+ _dl_close(infile);
+ _dl_munmap(header, _dl_pagesize);
+ return NULL;
+- };
++ }
+
+ /* if(libaddr == 0 && piclib) {
+ libaddr = (unsigned long) status;
+ flags |= MAP_FIXED;
+- }; */
+- };
++ } */
++ }
+ ppnt++;
+- };
++ }
+ _dl_close(infile);
+
+ /* For a non-PIC library, the addresses are all absolute */
+@@ -665,6 +594,8 @@
+ dynamic_addr, 0);
+ tpnt->relro_addr = relro_addr;
+ tpnt->relro_size = relro_size;
++ tpnt->st_dev = st.st_dev;
++ tpnt->st_ino = st.st_ino;
+ tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
+ tpnt->n_phent = epnt->e_phnum;
+
+@@ -693,7 +624,7 @@
+ if (lpnt) {
+ lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
+ INIT_GOT(lpnt, tpnt);
+- };
++ }
+
+ _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
+ _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, libaddr);
+@@ -714,10 +645,12 @@
+ ElfW(Addr) reloc_addr;
+
+ if (rpnt->next)
+- goof += _dl_fixup(rpnt->next, now_flag);
++ goof = _dl_fixup(rpnt->next, now_flag);
++ if (goof)
++ return goof;
+ tpnt = rpnt->dyn;
+
+- if(!(tpnt->init_flag & RELOCS_DONE))
++ if(!(tpnt->init_flag & RELOCS_DONE))
+ _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
+
+ if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
+@@ -735,7 +668,6 @@
+ #endif
+ if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
+ !(tpnt->init_flag & RELOCS_DONE)) {
+- tpnt->init_flag |= RELOCS_DONE;
+ reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
+ relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
+ if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
+@@ -746,14 +678,14 @@
+ goof += _dl_parse_relocation_information(rpnt,
+ reloc_addr,
+ reloc_size);
++ tpnt->init_flag |= RELOCS_DONE;
+ }
+ if (tpnt->dynamic_info[DT_BIND_NOW])
+ now_flag = RTLD_NOW;
+ if (tpnt->dynamic_info[DT_JMPREL] &&
+ (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
+ (now_flag && !(tpnt->rtld_flags & now_flag)))) {
+- tpnt->rtld_flags |= now_flag;
+- tpnt->init_flag |= JMP_RELOCS_DONE;
++ tpnt->rtld_flags |= now_flag;
+ if (!(tpnt->rtld_flags & RTLD_NOW)) {
+ _dl_parse_lazy_relocation_information(rpnt,
+ tpnt->dynamic_info[DT_JMPREL],
+@@ -763,6 +695,7 @@
+ tpnt->dynamic_info[DT_JMPREL],
+ tpnt->dynamic_info[DT_PLTRELSZ]);
+ }
++ tpnt->init_flag |= JMP_RELOCS_DONE;
+ }
+ return goof;
+ }
+@@ -770,11 +703,18 @@
+ /* Minimal printf which handles only %s, %d, and %x */
+ void _dl_dprintf(int fd, const char *fmt, ...)
+ {
+- long num;
++#if __WORDSIZE > 32
++ long int num;
++#else
++ int num;
++#endif
+ va_list args;
+ char *start, *ptr, *string;
+ static char *buf;
+
++ if (!fmt)
++ return;
++
+ buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (_dl_mmap_check_error(buf)) {
+@@ -784,9 +724,6 @@
+
+ start = ptr = buf;
+
+- if (!fmt)
+- return;
+-
+ if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
+ _dl_write(fd, "overflow\n", 11);
+ _dl_exit(20);
+@@ -818,8 +755,11 @@
+ case 'd':
+ {
+ char tmp[22];
+- num = va_arg(args, long);
+-
++#if __WORDSIZE > 32
++ num = va_arg(args, long int);
++#else
++ num = va_arg(args, int);
++#endif
+ string = _dl_simple_ltoa(tmp, num);
+ _dl_write(fd, string, _dl_strlen(string));
+ break;
+@@ -828,8 +768,11 @@
+ case 'X':
+ {
+ char tmp[22];
+- num = va_arg(args, long);
+-
++#if __WORDSIZE > 32
++ num = va_arg(args, long int);
++#else
++ num = va_arg(args, int);
++#endif
+ string = _dl_simple_ltoahex(tmp, num);
+ _dl_write(fd, string, _dl_strlen(string));
+ break;
+@@ -864,8 +807,10 @@
+ {
+ __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
+ }
++
++/* we want this in ldso.so and libdl.a but nowhere else */
+ #ifdef __USE_GNU
+-#if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
++#if ! defined SHARED || (! defined PIC && ! defined __PIC__)
+ int
+ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data)
+ {
+@@ -884,6 +829,6 @@
+ }
+ return ret;
+ }
+-strong_alias(__dl_iterate_phdr, dl_iterate_phdr);
++strong_alias(__dl_iterate_phdr, dl_iterate_phdr)
+ #endif
+ #endif
+diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-hash.c uClibc-0.9.28/ldso/ldso/dl-hash.c
+--- uClibc-0.9.28.orig/ldso/ldso/dl-hash.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/dl-hash.c 2006-04-28 00:14:35.000000000 -0600
+@@ -57,7 +57,7 @@
+ /* This is the hash function that is used by the ELF linker to generate the
+ * hash table that each executable and library is required to have. We need
+ * it to decode the hash table. */
+-static inline Elf32_Word _dl_elf_hash(const char *name)
++static inline Elf_Symndx _dl_elf_hash(const char *name)
+ {
+ unsigned long hash=0;
+ unsigned long tmp;
+@@ -77,21 +77,6 @@
+ return hash;
+ }
+
+-/* Check to see if a library has already been added to the hash chain. */
+-struct elf_resolve *_dl_check_hashed_files(const char *libname)
+-{
+- struct elf_resolve *tpnt;
+- int len = _dl_strlen(libname);
+-
+- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+- if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
+- (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
+- return tpnt;
+- }
+-
+- return NULL;
+-}
+-
+ /*
+ * We call this function when we have just read an ELF library or executable.
+ * We add the relevant info to the symbol chain, so that we can resolve all
+@@ -99,9 +84,10 @@
+ */
+ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
+ char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
++ //attribute_unused
+ unsigned long dynamic_size)
+ {
+- Elf32_Word *hash_addr;
++ Elf_Symndx *hash_addr;
+ struct elf_resolve *tpnt;
+ int i;
+
+@@ -125,7 +111,7 @@
+ tpnt->libtype = loaded_file;
+
+ if (dynamic_info[DT_HASH] != 0) {
+- hash_addr = (Elf32_Word*)dynamic_info[DT_HASH];
++ hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH];
+ tpnt->nbucket = *hash_addr++;
+ tpnt->nchain = *hash_addr++;
+ tpnt->elf_buckets = hash_addr;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/dl-startup.c uClibc-0.9.28/ldso/ldso/dl-startup.c
+--- uClibc-0.9.28.orig/ldso/ldso/dl-startup.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/dl-startup.c 2006-04-28 00:14:35.000000000 -0600
+@@ -98,7 +98,7 @@
+ int (*_dl_elf_main) (int, char **, char **);
+
+ static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */
+-strong_alias(__rtld_stack_end, __libc_stack_end); /* Exported version of __rtld_stack_end */
++strong_alias(__rtld_stack_end, __libc_stack_end) /* Exported version of __rtld_stack_end */
+
+ /* When we enter this piece of code, the program stack looks like this:
+ argc argument counter (integer)
+@@ -307,5 +307,11 @@
+ SEND_STDERR_DEBUG("transfering control to application @ ");
+ _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val;
+ SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1);
++
++#ifndef START
++ return _dl_elf_main;
++#else
++#warning You need to update your arch ldso code
+ START();
++#endif
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/frv/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/frv/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -20,9 +20,10 @@
+
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+ #include <sys/mman.h>
+
+ /* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
+diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/frv/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/frv/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -65,8 +65,6 @@
+
+ extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 16KiB page alignment. Should perhaps be made dynamic using
+ getpagesize(), based on AT_PAGESZ from auxvt? */
+ #define PAGE_ALIGN 0xffffc000
+diff -urN uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c uClibc-0.9.28/ldso/ldso/frv/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/frv/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/frv/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -24,7 +24,7 @@
+ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ USA. */
+
+-#include <sys/cdefs.h> /* __attribute_used__ */
++#include <features.h>
+
+ /* Program to load an ELF binary on a linux system, and run it.
+ References to symbols in sharable libraries can be resolved by either
+@@ -37,7 +37,7 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
+-struct funcdesc_value volatile *__attribute__((__visibility__("hidden")))
++struct funcdesc_value volatile attribute_hidden *
+ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+ {
+ int reloc_type;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h uClibc-0.9.28/ldso/ldso/i386/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -3,7 +3,7 @@
+ * Architecture specific code used by dl-startup.c
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+-asm(
++__asm__ (
+ " .text\n"
+ " .align 16\n"
+ " .globl _start\n"
+@@ -41,9 +41,9 @@
+ #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1)
+
+ /* Handle relocation of the symbols in the dynamic loader. */
+-static inline
++static __always_inline
+ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+- unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
++ unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
+ {
+ switch (ELF32_R_TYPE(rpnt->r_info))
+ {
+@@ -64,8 +64,3 @@
+ _dl_exit(1);
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,5 +1,6 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/i386/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,8 +25,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+@@ -44,16 +42,18 @@
+ /* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. */
+-static inline Elf32_Addr __attribute__ ((unused))
++static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused;
++static inline Elf32_Addr
+ elf_machine_dynamic (void)
+ {
+- register Elf32_Addr *got asm ("%ebx");
++ register Elf32_Addr *got __asm__ ("%ebx");
+ return *got;
+ }
+
+
+ /* Return the run-time load address of the shared object. */
+-static inline Elf32_Addr __attribute__ ((unused))
++static inline Elf32_Addr elf_machine_load_address (void) attribute_unused;
++static inline Elf32_Addr
+ elf_machine_load_address (void)
+ {
+ /* It doesn't matter what variable this is, the reference never makes
+@@ -61,7 +61,7 @@
+ via the GOT to make sure the compiler initialized %ebx in time. */
+ extern int _dl_errno;
+ Elf32_Addr addr;
+- asm ("leal _dl_start@GOTOFF(%%ebx), %0\n"
++ __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n"
+ "subl _dl_start@GOT(%%ebx), %0"
+ : "=r" (addr) : "m" (_dl_errno) : "cc");
+ return addr;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c uClibc-0.9.28/ldso/ldso/i386/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/i386/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/i386/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -67,12 +67,6 @@
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+- if (unlikely(reloc_type != R_386_JMP_SLOT)) {
+- _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
+- _dl_progname);
+- _dl_exit(1);
+- }
+-
+ /* Address of the jump instruction to fix up. */
+ instr_addr = ((unsigned long)this_reloc->r_offset +
+ (unsigned long)tpnt->loadaddr);
+@@ -81,7 +75,7 @@
+ /* Get the address of the GOT entry. */
+ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ if (unlikely(!new_addr)) {
+- _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ }
+
+@@ -147,15 +141,15 @@
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "can't handle reloc type %s\n",
+- _dl_reltypes(reloc_type));
++ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n",
++ _dl_reltypes(reloc_type), tpnt->libname);
+ #else
+- _dl_dprintf(2, "can't handle reloc type %x\n",
+- reloc_type);
++ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n",
++ reloc_type, tpnt->libname);
+ #endif
+- _dl_exit(-res);
++ return res;
+ } else if (unlikely(res > 0)) {
+- _dl_dprintf(2, "can't resolve symbol\n");
++ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ return res;
+ }
+ }
+@@ -191,10 +185,8 @@
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+- if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+- _dl_exit(1);
+- };
++ if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
++ return 1;
+ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -233,7 +225,7 @@
+ }
+ break;
+ default:
+- return -1; /* Calls _dl_exit(1). */
++ return -1;
+ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -273,7 +265,7 @@
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+- return -1; /* Calls _dl_exit(1). */
++ return -1;
+ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/ldso.c uClibc-0.9.28/ldso/ldso/ldso.c
+--- uClibc-0.9.28.orig/ldso/ldso/ldso.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/ldso.c 2006-05-02 13:55:54.000000000 -0600
+@@ -39,7 +39,7 @@
+ #define ALLOW_ZERO_PLTGOT
+
+ /* Pull in the value of _dl_progname */
+-#include "dl-progname.h"
++#include LDSO_ELFINTERP
+
+ /* Global variables used within the shared library loader */
+ char *_dl_library_path = 0; /* Where we look for libraries */
+@@ -74,7 +74,8 @@
+ * can set an internal breakpoint on it, so that we are notified when the
+ * address mapping is changed in some way.
+ */
+-void _dl_debug_state(void)
++void _dl_debug_state(void);
++void _dl_debug_state()
+ {
+ }
+
+@@ -82,9 +83,78 @@
+ static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */
+
+ static struct elf_resolve **init_fini_list;
+-static int nlist; /* # items in init_fini_list */
++static unsigned int nlist; /* # items in init_fini_list */
+ extern void _start(void);
+
++#ifdef __UCLIBC_HAS_SSP__
++#ifndef __UCLIBC_HAS_SSP_COMPAT__
++#define __UCLIBC_HAS_SSP_COMPAT__ 1
++#endif
++# include <dl-osinfo.h>
++uintptr_t stack_chk_guard;
++# ifndef THREAD_SET_STACK_GUARD
++/* Only exported for architectures that don't store the stack guard canary
++ * in local thread area. */
++uintptr_t __stack_chk_guard attribute_relro;
++# ifdef __UCLIBC_HAS_SSP_COMPAT__
++strong_alias(__stack_chk_guard,__guard)
++# endif
++# elif __UCLIBC_HAS_SSP_COMPAT__
++uintptr_t __guard attribute_relro;
++# endif
++#endif
++
++static void _dl_run_array_forward(unsigned long array, unsigned long size,
++ ElfW(Addr) loadaddr)
++{
++ if (array != 0) {
++ unsigned int j;
++ unsigned int jm;
++ ElfW(Addr) *addrs;
++ jm = size / sizeof (ElfW(Addr));
++ addrs = (ElfW(Addr) *) (array + loadaddr);
++ for (j = 0; j < jm; ++j) {
++ void (*dl_elf_func) (void);
++ dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
++ (*dl_elf_func) ();
++ }
++ }
++}
++
++void _dl_run_init_array(struct elf_resolve *tpnt);
++void _dl_run_init_array(struct elf_resolve *tpnt)
++{
++ _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY],
++ tpnt->dynamic_info[DT_INIT_ARRAYSZ],
++ tpnt->loadaddr);
++}
++
++void _dl_app_init_array(void);
++void _dl_app_init_array(void)
++{
++ _dl_run_init_array(_dl_loaded_modules);
++}
++
++void _dl_run_fini_array(struct elf_resolve *tpnt);
++void _dl_run_fini_array(struct elf_resolve *tpnt)
++{
++ if (tpnt->dynamic_info[DT_FINI_ARRAY]) {
++ ElfW(Addr) *array = (ElfW(Addr) *) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI_ARRAY]);
++ unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr)));
++ while (i-- > 0) {
++ void (*dl_elf_func) (void);
++ dl_elf_func = (void (*)(void)) (intptr_t) array[i];
++ (*dl_elf_func) ();
++ }
++ }
++}
++
++void _dl_app_fini_array(void);
++void _dl_app_fini_array(void)
++{
++ _dl_run_fini_array(_dl_loaded_modules);
++}
++
+ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
+ {
+ int i;
+@@ -95,6 +165,7 @@
+ if (tpnt->init_flag & FINI_FUNCS_CALLED)
+ continue;
+ tpnt->init_flag |= FINI_FUNCS_CALLED;
++ _dl_run_fini_array(tpnt);
+ if (tpnt->dynamic_info[DT_FINI]) {
+ void (*dl_elf_func) (void);
+
+@@ -112,7 +183,8 @@
+ ElfW(Phdr) *ppnt;
+ ElfW(Dyn) *dpnt;
+ char *lpntstr;
+- int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
++ unsigned int i;
++ int unlazy = 0, trace_loaded_objects = 0;
+ struct dyn_elf *rpnt;
+ struct elf_resolve *tcurr;
+ struct elf_resolve *tpnt1;
+@@ -128,6 +200,7 @@
+ * setup so we can use _dl_dprintf() to print debug noise
+ * instead of the SEND_STDERR macros used in dl-startup.c */
+
++ _dl_memset(app_tpnt, 0x00, sizeof(*app_tpnt));
+
+ /* Store the page size for later use */
+ _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
+@@ -168,8 +241,8 @@
+ * Note that for SUID programs we ignore the settings in
+ * LD_LIBRARY_PATH.
+ */
+- if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
+- (auxvt[AT_UID].a_un.a_val != -1 &&
++ if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
++ (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
+ auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
+ auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
+ _dl_secure = 0;
+@@ -196,6 +269,20 @@
+ unlazy = RTLD_NOW;
+ }
+
++ /* sjhill: your TLS init should go before this */
++#ifdef __UCLIBC_HAS_SSP__
++ /* Set up the stack checker's canary. */
++ stack_chk_guard = _dl_setup_stack_chk_guard ();
++# ifdef THREAD_SET_STACK_GUARD
++ THREAD_SET_STACK_GUARD (stack_chk_guard);
++# ifdef __UCLIBC_HAS_SSP_COMPAT__
++ __guard = stack_chk_guard;
++# endif
++# else
++ __stack_chk_guard = stack_chk_guard;
++# endif
++#endif
++
+ /* At this point we are now free to examine the user application,
+ * and figure out which libraries are supposed to be called. Until
+ * we have this list, we will not be completely ready for dynamic
+@@ -206,12 +293,12 @@
+ * different from what the ELF header says for ET_DYN/PIE executables.
+ */
+ {
+- int i;
+- ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
++ unsigned int idx;
++ ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
+
+- for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
+- if (ppnt->p_type == PT_PHDR) {
+- app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
++ for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
++ if (phdr->p_type == PT_PHDR) {
++ app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
+ break;
+ }
+
+@@ -459,8 +546,8 @@
+ PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ _dl_close(fd);
+ if (preload == (caddr_t) -1) {
+- _dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n",
+- _dl_progname, LDSO_PRELOAD);
++ _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
++ _dl_progname, __LINE__, LDSO_PRELOAD);
+ break;
+ }
+
+@@ -528,15 +615,15 @@
+
+ nlist = 0;
+ for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
+- ElfW(Dyn) *dpnt;
++ ElfW(Dyn) *this_dpnt;
+
+ nlist++;
+- for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
+- if (dpnt->d_tag == DT_NEEDED) {
++ for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) {
++ if (this_dpnt->d_tag == DT_NEEDED) {
+ char *name;
+ struct init_fini_list *tmp;
+
+- lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
++ lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
+ name = _dl_get_last_path_component(lpntstr);
+ if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
+ continue;
+@@ -633,7 +720,7 @@
+ ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+ ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
+ int j;
+-
++
+ tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
+ tpnt->dynamic_info,
+ (unsigned long)tpnt->dynamic_addr,
+@@ -703,16 +790,14 @@
+ * order so that COPY directives work correctly.
+ */
+ if (_dl_symbol_tables)
+- goof += _dl_fixup(_dl_symbol_tables, unlazy);
++ if (_dl_fixup(_dl_symbol_tables, unlazy))
++ _dl_exit(-1);
+
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ if (tpnt->relro_size)
+ _dl_protect_relro (tpnt);
+ }
+
+-
+-
+-
+ /* OK, at this point things are pretty much ready to run. Now we need
+ * to touch up a few items that are required, and then we can let the
+ * user application have at it. Note that the dynamic linker itself
+@@ -746,6 +831,14 @@
+ /* Notify the debugger we have added some objects. */
+ _dl_debug_addr->r_state = RT_ADD;
+ _dl_debug_state();
++
++ /* Run pre-initialization functions for the executable. */
++ _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
++ _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
++ _dl_loaded_modules->loadaddr);
++
++ /* Run initialization functions for loaded objects. For the
++ main executable, they will be run from __uClibc_main. */
+ for (i = nlist; i; --i) {
+ tpnt = init_fini_list[i-1];
+ tpnt->init_fini = NULL; /* Clear, since alloca was used */
+@@ -762,17 +855,9 @@
+
+ (*dl_elf_func) ();
+ }
+- }
+-#ifdef _DL_FINI_CRT_COMPAT
+- /* arches that have moved their ldso FINI handling should skip this part */
+- {
+- int (*_dl_atexit) (void *) = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit",
+- _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
+
+- if (_dl_atexit)
+- (*_dl_atexit) (_dl_fini);
++ _dl_run_init_array(tpnt);
+ }
+-#endif
+
+ /* Find the real malloc function and make ldso functions use that from now on */
+ _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash("malloc",
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -4,23 +4,48 @@
+ * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
+ */
+
+-asm(
+- " .text\n"
+- " .globl _start\n"
+- " .type _start,@function\n"
+- "_start:\n"
+- " .set _start,_dl_start\n"
+- " .size _start,.-_start\n"
+- " .previous\n"
+-);
++asm ("\
++ .text\n\
++ .globl _start\n\
++ .type _start,@function\n\
++_start:\n\
++ move.l %sp, -(%sp)\n\
++ jbsr _dl_start\n\
++ addq.l #4, %sp\n\
++ /* FALLTHRU */\n\
++\n\
++ .globl _dl_start_user\n\
++.type _dl_start_user,@function\n\
++_dl_start_user:\n\
++ # Save the user entry point address in %a4.\n\
++ move.l %d0, %a4\n\
++ # See if we were run as a command with the executable file\n\
++ # name as an extra leading argument.\n\
++ move.l _dl_skip_args(%pc), %d0\n\
++ # Pop the original argument count\n\
++ move.l (%sp)+, %d1\n\
++ # Subtract _dl_skip_args from it.\n\
++ sub.l %d0, %d1\n\
++ # Adjust the stack pointer to skip _dl_skip_args words.\n\
++ lea (%sp, %d0*4), %sp\n\
++ # Push back the modified argument count.\n\
++ move.l %d1, -(%sp)\n\
++ # Pass our finalizer function to the user in %a1.\n\
++ lea _dl_fini(%pc), %a1\n\
++ # Initialize %fp with the stack pointer.\n\
++ move.l %sp, %fp\n\
++ # Jump to the user's entry point.\n\
++ jmp (%a4)\n\
++ .size _dl_start_user, . - _dl_start_user\n\
++ .previous");
+
+ /* Get a pointer to the argv array. On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+ * do something a little more subtle here. */
+-#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned int *) & ARGS)
++#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+ /* Handle relocation of the symbols in the dynamic loader. */
+-static inline
++static __always_inline
+ void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+ unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
+ {
+@@ -59,12 +84,3 @@
+ _dl_exit (1);
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() \
+- __asm__ volatile ( \
+- "unlk %%a6\n\t" \
+- "jmp %0@" \
+- : : "a" (_dl_elf_main));
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,5 +1,6 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,10 +25,6 @@
+ struct elf_resolve;
+ extern unsigned int _dl_linux_resolver (struct elf_resolve *, int);
+
+-/* Define this because we do not want to call .udiv in the library.
+- Not needed for m68k. */
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -40,6 +40,8 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ unsigned int
+@@ -48,20 +50,20 @@
+ int reloc_type;
+ ELF_RELOC *this_reloc;
+ char *strtab;
+- Elf32_Sym *symtab;
++ ElfW(Sym) *symtab;
+ int symtab_index;
+- ELF_RELOC *rel_addr;
++ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+- unsigned int instr_addr;
++ ElfW(Addr) instr_addr;
+ char *symname;
+
+- rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL];
+- this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+- reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+- symtab_index = ELF32_R_SYM(this_reloc->r_info);
++ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
++ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
++ reloc_type = ELF_R_TYPE(this_reloc->r_info);
++ symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+- symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+ symname = strtab + symtab[symtab_index].st_name;
+
+@@ -72,7 +74,7 @@
+ }
+
+ /* Address of the jump instruction to fix up. */
+- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
++ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
+ got_addr = (char **)instr_addr;
+
+ /* Get the address of the GOT entry. */
+@@ -88,159 +90,237 @@
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if (_dl_debug_detail)
+ _dl_dprintf(_dl_debug_file,
+- "\n\tpatched: %x ==> %x @ %x",
++ "\tpatched: %x ==> %x @ %x\n",
+ *got_addr, new_addr, got_addr);
+ }
+ }
+- if (!_dl_debug_nofixups) {
+- *got_addr = new_addr;
+- }
+-#else
+- *got_addr = new_addr;
++ if (!_dl_debug_nofixups)
+ #endif
++ *got_addr = new_addr;
+
+- return (unsigned int)new_addr;
++ return (unsigned int)new_addr;
+ }
+
+-void
+-_dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
++static int
++_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ unsigned long rel_addr, unsigned long rel_size,
++ int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
+ {
+- int i;
++ unsigned int i;
+ char *strtab;
+- int reloc_type;
++ ElfW(Sym) *symtab;
++ ELF_RELOC *rpnt;
+ int symtab_index;
+- Elf32_Sym *symtab;
+- Elf32_Rela *rpnt;
+- unsigned int *reloc_addr;
+- struct elf_resolve *tpnt = arg_rpnt->dyn;
+-
+- /* Now parse the relocation information. */
+- rpnt = (Elf32_Rela *)rel_addr;
+- rel_size = rel_size / sizeof (Elf32_Rela);
+
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
++ /* Parse the relocation information. */
++ rpnt = (ELF_RELOC *)rel_addr;
++ rel_size /= sizeof(ELF_RELOC);
++
++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
+ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+
+ for (i = 0; i < rel_size; i++, rpnt++) {
+- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE (rpnt->r_info);
+- symtab_index = ELF32_R_SYM (rpnt->r_info);
++ int res;
+
+- switch (reloc_type)
+- {
+- case R_68K_NONE:
+- break;
+- case R_68K_JMP_SLOT:
+- *reloc_addr += (unsigned int) tpnt->loadaddr;
+- break;
+- default:
+- _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
++ symtab_index = ELF_R_SYM(rpnt->r_info);
++
++ debug_sym(symtab, strtab, symtab_index);
++ debug_reloc(symtab, strtab, rpnt);
++
++ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
++
++ if (res == 0)
++ continue;
++
++ _dl_dprintf(2, "\n%s: ", _dl_progname);
++
++ if (symtab_index)
++ _dl_dprintf(2, "symbol '%s': ",
++ strtab + symtab[symtab_index].st_name);
++
++ if (unlikely(res < 0)) {
++ int reloc_type = ELF_R_TYPE(rpnt->r_info);
++
++ _dl_dprintf(2, "can't handle reloc type "
+ #if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]);
++ "%s\n", _dl_reltypes(reloc_type));
++#else
++ "%x\n", reloc_type);
+ #endif
+- if (symtab_index)
+- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
+- _dl_dprintf (2, "\n");
+- _dl_exit (1);
++ _dl_exit(-res);
++ } else if (unlikely(res > 0)) {
++ _dl_dprintf(2, "can't resolve symbol\n");
++ return res;
+ }
+ }
++
++ return 0;
+ }
+
+-int
+-_dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
++static int
++_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+ {
+- int i;
+- char *strtab;
+ int reloc_type;
+- int goof = 0;
+- Elf32_Sym *symtab;
+- Elf32_Rela *rpnt;
+- unsigned int *reloc_addr;
+- unsigned int symbol_addr;
+ int symtab_index;
+- struct elf_resolve *tpnt = arg_rpnt->dyn;
+- /* Now parse the relocation information */
++ char *symname;
++ ElfW(Sym) *sym;
++ ElfW(Addr) *reloc_addr;
++ ElfW(Addr) symbol_addr;
++#if defined (__SUPPORT_LD_DEBUG__)
++ ElfW(Addr) old_val;
++#endif
+
+- rpnt = (Elf32_Rela *)rel_addr;
+- rel_size = rel_size / sizeof (Elf32_Rela);
++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
++ reloc_type = ELF_R_TYPE(rpnt->r_info);
++ symtab_index = ELF_R_SYM(rpnt->r_info);
++ sym = &symtab[symtab_index];
++ symbol_addr = 0;
++ symname = strtab + sym->st_name;
++
++ if (symtab_index) {
++ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
++ elf_machine_type_class(reloc_type));
++ /*
++ * We want to allow undefined references to weak symbols - this
++ * might have been intentional. We should not be linking local
++ * symbols here, so all bases should be covered.
++ */
++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
++ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_exit(1);
++ };
++ }
+
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
++#if defined (__SUPPORT_LD_DEBUG__)
++ old_val = *reloc_addr;
++#endif
+
+- for (i = 0; i < rel_size; i++, rpnt++) {
+- reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE (rpnt->r_info);
+- symtab_index = ELF32_R_SYM (rpnt->r_info);
+- symbol_addr = 0;
+- if (symtab_index) {
+- symbol_addr = (unsigned int)
+- _dl_find_hash (strtab + symtab[symtab_index].st_name,
+- tpnt->symbol_scope, tpnt,
+- elf_machine_type_class(reloc_type));
+-
+- /* We want to allow undefined references to weak symbols -
+- this might have been intentional. We should not be
+- linking local symbols here, so all bases should be
+- covered. */
+- if (!symbol_addr
+- && ELF32_ST_BIND (symtab[symtab_index].st_info) != STB_WEAK)
+- {
+- _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+- _dl_progname, strtab + symtab[symtab_index].st_name);
+- _dl_exit (1);
+- }
+- }
+- switch (reloc_type)
+- {
+- case R_68K_NONE:
+- break;
+- case R_68K_8:
+- *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_68K_16:
+- *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_68K_32:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_68K_PC8:
+- *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
+- - (unsigned int) reloc_addr);
+- break;
+- case R_68K_PC16:
+- *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
+- - (unsigned int) reloc_addr);
+- break;
+- case R_68K_PC32:
+- *reloc_addr = (symbol_addr + rpnt->r_addend
+- - (unsigned int) reloc_addr);
+- break;
+- case R_68K_GLOB_DAT:
+- case R_68K_JMP_SLOT:
+- *reloc_addr = symbol_addr;
+- break;
+- case R_68K_RELATIVE:
+- *reloc_addr = ((unsigned int) tpnt->loadaddr
+- /* Compatibility kludge. */
+- + (rpnt->r_addend ? : *reloc_addr));
+- break;
+- case R_68K_COPY:
++ switch (reloc_type) {
++ case R_68K_NONE:
++ break;
++ case R_68K_8:
++ *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
++ break;
++ case R_68K_16:
++ *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
++ break;
++ case R_68K_32:
++ *reloc_addr = symbol_addr + rpnt->r_addend;
++ break;
++ case R_68K_PC8:
++ *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
++ - (unsigned int) reloc_addr);
++ break;
++ case R_68K_PC16:
++ *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
++ - (unsigned int) reloc_addr);
++ break;
++ case R_68K_PC32:
++ *reloc_addr = (symbol_addr + rpnt->r_addend
++ - (unsigned int) reloc_addr);
++ break;
++ case R_68K_GLOB_DAT:
++ case R_68K_JMP_SLOT:
++ *reloc_addr = symbol_addr + rpnt->r_addend;
++ break;
++ /* handled by elf_machine_relative()
++ case R_68K_RELATIVE:
++ *reloc_addr = ((unsigned int) tpnt->loadaddr
++ / * Compatibility kludge. * /
++ + (rpnt->r_addend ? : *reloc_addr));
++ */
++ break;
++ case R_68K_COPY:
++ if (symbol_addr) {
++#if defined (__SUPPORT_LD_DEBUG__)
++ if (_dl_debug_move)
++ _dl_dprintf(_dl_debug_file,
++ "\t%s move %d bytes from %x to %x\n",
++ symname, sym->st_size,
++ symbol_addr, reloc_addr);
++#endif
+ _dl_memcpy ((void *) reloc_addr,
+ (void *) symbol_addr,
+- symtab[symtab_index].st_size);
+- break;
+- default:
+- _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
+-#if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf (2, "%s ", _dl_reltypes_tab[reloc_type]);
+-#endif
+- if (symtab_index)
+- _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
+- _dl_dprintf (2, "\n");
+- _dl_exit (1);
+- }
++ sym->st_size);
++ } else
++ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
++ break;
++
++ default:
++ return -1; /* Calls _dl_exit(1). */
++ }
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ if (_dl_debug_reloc && _dl_debug_detail)
++ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
++ old_val, *reloc_addr, reloc_addr);
++#endif
++
++ return 0;
++}
++
++#undef LAZY_RELOC_WORKS
++#ifdef LAZY_RELOC_WORKS
++static int
++_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
++{
++ int reloc_type;
++ int symtab_index;
++ ElfW(Addr) *reloc_addr;
++#if defined (__SUPPORT_LD_DEBUG__)
++ ElfW(Addr) old_val;
++#endif
++
++ (void)scope;
++ symtab_index = ELF_R_SYM(rpnt->r_info);
++ (void)strtab;
++
++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
++ reloc_type = ELF_R_TYPE(rpnt->r_info);
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ old_val = *reloc_addr;
++#endif
++
++ switch (reloc_type) {
++ case R_68K_NONE:
++ break;
++ case R_68K_JMP_SLOT:
++ *reloc_addr += (unsigned int) tpnt->loadaddr;
++ break;
++ default:
++ _dl_exit(1);
+ }
+- return goof;
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ if (_dl_debug_reloc && _dl_debug_detail)
++ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
++ old_val, *reloc_addr, reloc_addr);
++#endif
++
++ return 0;
++}
++#endif
++
++void
++_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++#ifdef LAZY_RELOC_WORKS
++ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
++#else
++ _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
++#endif
++}
++
++int
++_dl_parse_relocation_information(struct dyn_elf *rpnt,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S uClibc-0.9.28/ldso/ldso/m68k/resolve.S
+--- uClibc-0.9.28.orig/ldso/ldso/m68k/resolve.S 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/m68k/resolve.S 2006-04-28 00:14:35.000000000 -0600
+@@ -8,14 +8,16 @@
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve,@function
+ _dl_linux_resolve:
+- moveml %a0/%a1,%sp@-
+-#ifdef __PIC__
+- bsrl _dl_linux_resolver@PLTPC
+-#else
+- jbsr _dl_linux_resolver
+-#endif
+- moveml %sp@+,%a0/%a1
+- addql #8,%sp
+- jmp @(%d0)
+-.LFE2:
+- .size _dl_linux_resolve,.LFE2-_dl_linux_resolve
++ # Save %a0 (struct return address) and %a1.
++ move.l %a0, -(%sp)
++ move.l %a1, -(%sp)
++ # Call the real address resolver.
++ jbsr _dl_linux_resolver
++ # Restore register %a0 and %a1.
++ move.l (%sp)+, %a1
++ move.l (%sp)+, %a0
++ # Pop parameters
++ addq.l #8, %sp
++ # Call real function.
++ jmp (%d0)
++.size _dl_linux_resolve,.-_dl_linux_resolve
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h uClibc-0.9.28/ldso/ldso/mips/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -136,13 +136,3 @@
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
+-
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function. For MIPS, we do it in assembly
+- * because the stack doesn't get properly restored otherwise. Got look
+- * at boot1_arch.h
+- */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/dl-syscalls.h 2006-05-02 13:39:25.000000000 -0600
+@@ -1,7 +1,8 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+-
+-#define MMAP_HAS_6_ARGS
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/mips/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -30,7 +30,7 @@
+ /* Initialization sequence for the application/library GOT. */
+ #define INIT_GOT(GOT_BASE,MODULE) \
+ do { \
+- unsigned long i; \
++ unsigned long idx; \
+ \
+ /* Check if this is the dynamic linker itself */ \
+ if (MODULE->libtype == program_interpreter) \
+@@ -41,9 +41,9 @@
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+- i = 2; \
+- while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
+- GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
++ idx = 2; \
++ while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
++ GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \
+ \
+ } while (0)
+
+@@ -63,8 +63,6 @@
+ struct elf_resolve;
+ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c uClibc-0.9.28/ldso/ldso/mips/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/mips/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/mips/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -27,6 +27,8 @@
+ * SUCH DAMAGE.
+ */
+
++#include "ldso.h"
++
+ extern int _dl_runtime_resolve(void);
+
+ #define OFFSET_GP_GOT 0x7ff0
+@@ -146,7 +148,6 @@
+ break;
+ default:
+ {
+- int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -42,8 +42,10 @@
+ " bne 2b\n"
+ " addi 6,6,4\n"
+ #endif
+- /* Pass a termination function pointer (in this case _dl_fini) in r7. */
+- " lwz 7,_dl_fini@got(31)\n"
++ /* Pass a termination function pointer (in this case _dl_fini) in r3. */
++ /* Paulus promized he would keep r3 zero in the exec ABI. */
++ " lwz 3,_dl_fini@got(31)\n"
++ " mr 7,3\n" /* Pass _dl_fini in r7 to maintain compat */
+ " bctr\n" /* Jump to entry point */
+ " .size _start,.-_start\n"
+ " .previous\n"
+@@ -78,9 +80,3 @@
+ _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\
+ } \
+ }
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function.
+- */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-syscalls.h 2006-05-02 13:39:14.000000000 -0600
+@@ -1,251 +1,8 @@
+-/*
+- * This file contains the system call macros and syscall
+- * numbers used by the shared library loader.
+- */
+-
+-#define MMAP_HAS_6_ARGS
+-
+-#define __NR_exit 1
+-#define __NR_read 3
+-#define __NR_write 4
+-#define __NR_open 5
+-#define __NR_close 6
+-#define __NR_getpid 20
+-#define __NR_getuid 24
+-#define __NR_geteuid 49
+-#define __NR_getgid 47
+-#define __NR_getegid 50
+-#define __NR_readlink 85
+-#define __NR_mmap 90
+-#define __NR_munmap 91
+-#define __NR_stat 106
+-#define __NR_mprotect 125
+-
+-
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+-extern int _dl_errno;
+-
+-/* Here are the macros which define how this platform makes
+- * system calls. This particular variant does _not_ set
+- * errno (note how it is disabled in __syscall_return) since
+- * these will get called before the errno symbol is dynamicly
+- * linked. */
+-
+-#undef __syscall_return
+-#define __syscall_return(type) \
+- return (__sc_err & 0x10000000 ? _dl_errno = __sc_ret, __sc_ret = -1 : 0), \
+- (type) __sc_ret
+-
+-#undef __syscall_clobbers
+-#define __syscall_clobbers \
+- "r9", "r10", "r11", "r12"
+- //"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+-
+-#undef _syscall0
+-#define _syscall0(type,name) \
+-type name(void) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0) \
+- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall1
+-#define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0) \
+- : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall2
+-#define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1, type2 arg2) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4) \
+- : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall3
+-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1, type2 arg2, type3 arg3) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5) \
+- : "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall4
+-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_6 = (unsigned long) (arg4); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5), \
+- "r" (__sc_6) \
+- : "r7", "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-#undef _syscall5
+-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- register unsigned long __sc_7 __asm__ ("r7"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_6 = (unsigned long) (arg4); \
+- __sc_7 = (unsigned long) (arg5); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5), \
+- "r" (__sc_6), \
+- "r" (__sc_7) \
+- : "r8", "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
+-
+-#undef _syscall6
+-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+-{ \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- register unsigned long __sc_7 __asm__ ("r7"); \
+- register unsigned long __sc_8 __asm__ ("r8"); \
+- \
+- __sc_3 = (unsigned long) (arg1); \
+- __sc_4 = (unsigned long) (arg2); \
+- __sc_5 = (unsigned long) (arg3); \
+- __sc_6 = (unsigned long) (arg4); \
+- __sc_7 = (unsigned long) (arg5); \
+- __sc_8 = (unsigned long) (arg6); \
+- __sc_0 = __NR_##name; \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %1 " \
+- : "=&r" (__sc_3), "=&r" (__sc_0) \
+- : "0" (__sc_3), "1" (__sc_0), \
+- "r" (__sc_4), \
+- "r" (__sc_5), \
+- "r" (__sc_6), \
+- "r" (__sc_7), \
+- "r" (__sc_8) \
+- : "r9", "r10", "r11", "r12" ); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- __syscall_return (type); \
+-}
+-
++#define __UCLIBC_MMAP_HAS_6_ARGS__
+
++#include "sys/syscall.h"
++extern int _dl_errno;
++#undef __set_errno
++#define __set_errno(X) {(_dl_errno) = (X);}
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -67,9 +67,6 @@
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+ void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt);
+
+-
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/powerpc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/powerpc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -29,6 +29,8 @@
+ * SUCH DAMAGE.
+ */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
+@@ -138,7 +140,7 @@
+ finaladdr = (Elf32_Addr) _dl_find_hash(symname,
+ tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ if (unlikely(!finaladdr)) {
+- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
+ _dl_exit(1);
+ };
+ finaladdr += this_reloc->r_addend;
+@@ -379,15 +381,15 @@
+ {
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ #if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
++ _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname);
+ #else
+- _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
++ _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname);
+ #endif
+- _dl_exit(-res);
++ return res;
+ }
+ if (unlikely(res >0))
+ {
+- _dl_dprintf(2, "can't resolve symbol\n");
++ _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname);
+ return res;
+ }
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h uClibc-0.9.28/ldso/ldso/sh/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -55,11 +55,3 @@
+ default: \
+ _dl_exit(1); \
+ }
+-
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function.
+- */
+-#define START() return _dl_elf_main;
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/dl-syscalls.h 2006-05-02 13:39:28.000000000 -0600
+@@ -1,7 +1,8 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+-
+-#define MMAP_HAS_6_ARGS
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,7 +25,7 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-static __inline__ unsigned int
++static inline unsigned int
+ _dl_urem(unsigned int n, unsigned int base)
+ {
+ int res;
+@@ -104,7 +104,7 @@
+ elf_machine_dynamic (void)
+ {
+ register Elf32_Addr *got;
+- asm ("mov r12,%0" :"=r" (got));
++ __asm__ ("mov r12,%0" :"=r" (got));
+ return *got;
+ }
+
+@@ -113,7 +113,7 @@
+ elf_machine_load_address (void)
+ {
+ Elf32_Addr addr;
+- asm ("mov.l 1f,r0\n\
++ __asm__ ("mov.l 1f,r0\n\
+ mov.l 3f,r2\n\
+ add r12,r2\n\
+ mov.l @(r0,r12),r0\n\
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c uClibc-0.9.28/ldso/ldso/sh/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/sh/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -39,6 +39,8 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -115,12 +115,3 @@
+ default: \
+ _dl_exit(1); \
+ }
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. This routine has to exit the current function, then
+- * call the _dl_elf_main function.
+- */
+-
+-#define START() return _dl_elf_main;
+-
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/dl-syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,8 +1,9 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+
+ #undef __syscall_return
+ #define __syscall_return(type, res) \
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -25,8 +25,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/sh64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sh64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -41,6 +41,8 @@
+ a more than adequate job of explaining everything required to get this
+ working. */
+
++#include "ldso.h"
++
+ extern int _dl_linux_resolve(void);
+
+ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -3,15 +3,46 @@
+ * needed for this architecture. See arm/boot1_arch.h for an example of what
+ * can be done.
+ */
+-asm(
+- " .text\n"
+- " .global _start\n"
+- " .type _start,%function\n"
+- "_start:\n"
+- " .set _start,_dl_start\n"
+- " .size _start,.-_start\n"
+- " .previous\n"
+-);
++
++asm ("\
++ .text\n\
++ .global _start\n\
++ .type _start,%function\n\
++ .align 32\n\
++_start:\n\
++ /* Allocate space for functions to drop their arguments. */\n\
++ sub %sp, 6*4, %sp\n\
++ /* Pass pointer to argument block to _dl_start. */\n\
++ call _dl_start\n\
++ add %sp, 22*4, %o0\n\
++ /* FALTHRU */\n\
++ .globl _dl_start_user\n\
++ .type _dl_start_user, @function\n\
++_dl_start_user:\n\
++ /* Load the PIC register. */\n\
++1: call 2f\n\
++ sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\
++2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\
++ add %l7, %o7, %l7\n\
++ /* Save the user entry point address in %l0 */\n\
++ mov %o0, %l0\n\
++ /* See if we were run as a command with the executable file name as an\n\
++ extra leading argument. If so, adjust the contents of the stack. */\n\
++ sethi %hi(_dl_skip_args), %g2\n\
++ or %g2, %lo(_dl_skip_args), %g2\n\
++ ld [%l7+%g2], %i0\n\
++ ld [%i0], %i0\n\
++ tst %i0\n\
++ /* Pass our finalizer function to the user in %g1. */\n\
++ sethi %hi(_dl_fini), %g1\n\
++ or %g1, %lo(_dl_fini), %g1\n\
++ ld [%l7+%g1], %g1\n\
++ /* Jump to the user's entry point and deallocate the extra stack we got. */\n\
++ jmp %l0\n\
++ add %sp, 6*4, %sp\n\
++ .size _dl_start_user, . - _dl_start_user\n\
++ .previous\n\
++");
+
+ /*
+ * Get a pointer to the argv array. On many platforms this can be just
+@@ -19,17 +50,15 @@
+ * do something a little more subtle here. We assume that argc is stored
+ * at the word just below the argvp that we return here.
+ */
+-#define GET_ARGV(ARGVP, ARGS) __asm__("\tadd %%fp,68,%0\n" : "=r" (ARGVP));
++#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+ /*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader.
+ */
+ #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+- switch(ELF32_R_TYPE((RELP)->r_info)) { \
++switch(ELF_R_TYPE((RELP)->r_info)) { \
+ case R_SPARC_32: \
+- *REL = SYMBOL + (RELP)->r_addend; \
+- break; \
+ case R_SPARC_GLOB_DAT: \
+ *REL = SYMBOL + (RELP)->r_addend; \
+ break; \
+@@ -38,7 +67,6 @@
+ REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \
+ break; \
+ case R_SPARC_NONE: \
+- break; \
+ case R_SPARC_WDISP30: \
+ break; \
+ case R_SPARC_RELATIVE: \
+@@ -46,18 +74,4 @@
+ break; \
+ default: \
+ _dl_exit(1); \
+- }
+-
+-/*
+- * Transfer control to the user's application, once the dynamic loader
+- * is done. The crt calls atexit with $g1 if not null, so we need to
+- * ensure that it contains NULL.
+- */
+-
+-#define START() \
+- __asm__ volatile ( \
+- "add %%g0,%%g0,%%g1\n\t" \
+- "jmpl %0, %%o7\n\t" \
+- "restore %%g0,%%g0,%%g0\n\t" \
+- : /*"=r" (status) */ : \
+- "r" (_dl_elf_main): "g1", "o0", "o1")
++}
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/dl-syscalls.h 2006-05-02 13:39:21.000000000 -0600
+@@ -1,187 +1,8 @@
+-/*
+- * This file contains the system call macros and syscall
+- * numbers used by the shared library loader.
+- *
+- * NOTE: This should be integrated/moved to
+- * sysdeps/linux/sparc/bits/syscalls.h at some point ...
+- */
+-
+-#define MMAP_HAS_6_ARGS
+-
+-#define __NR_exit 1
+-#define __NR_read 3
+-#define __NR_write 4
+-#define __NR_open 5
+-#define __NR_close 6
+-#define __NR_getpid 20
+-#define __NR_getuid 24
+-#define __NR_getgid 47
+-#define __NR_geteuid 49
+-#define __NR_getegid 50
+-#define __NR_readlink 58
+-#define __NR_mmap 71
+-#define __NR_munmap 73
+-#define __NR_stat 38
+-#define __NR_mprotect 74
+-
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-
+-/* Here are the macros which define how this platform makes
+- * system calls. This particular variant does _not_ set
+- * errno (note how _dl_errno is used in __syscall_return) since
+- * these will get called before the errno symbol is dynamicly
+- * linked. */
+-
+-#define __syscall_return(type, res) \
+-do { \
+- if (res < -255 || res >= 0) \
+- return (type) res; \
+- __set_errno(-res); \
+- res = -1; \
+- return (type) res; \
+-} while (0)
+-
+-#define _syscall0(type,name) \
+-type name(void) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res)\
+- : "r" (__g1) \
+- : "o0", "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1,type2 arg2) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1,type2 arg2,type3 arg3) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- register long __o3 __asm__ ("o3") = (long)(arg4); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+- type5,arg5) \
+-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- register long __o3 __asm__ ("o3") = (long)(arg4); \
+- register long __o4 __asm__ ("o4") = (long)(arg5); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+-
+-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+- type5,arg5,type6,arg6) \
+-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
+-{ \
+- long __res; \
+- register long __g1 __asm__ ("g1") = __NR_##name; \
+- register long __o0 __asm__ ("o0") = (long)(arg1); \
+- register long __o1 __asm__ ("o1") = (long)(arg2); \
+- register long __o2 __asm__ ("o2") = (long)(arg3); \
+- register long __o3 __asm__ ("o3") = (long)(arg4); \
+- register long __o4 __asm__ ("o4") = (long)(arg5); \
+- register long __o5 __asm__ ("o5") = (long)(arg6); \
+- __asm__ __volatile__ ( \
+- "t 0x10\n\t" \
+- "bcc 1f\n\t" \
+- "mov %%o0, %0\n\t" \
+- "sub %%g0, %%o0, %0\n\t" \
+- "1:\n\t" \
+- : "=r" (__res), "=&r" (__o0) \
+- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \
+- : "cc"); \
+- __syscall_return(type, __res); \
+-}
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -1,9 +1,9 @@
+-
++/* vi: set sw=4 ts=4: */
+ /*
+ * Various assmbly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
++ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ */
+-#define LINUXBIN
+
+ /* Define this if the system uses RELOCA. */
+ #define ELF_USES_RELOCA
+@@ -31,19 +31,14 @@
+ #undef MAGIC2
+
+ /* Used for error messages */
+-#define ELF_TARGET "Sparc"
++#define ELF_TARGET "sparc"
+
+-#ifndef COMPILE_ASM
+-extern unsigned int _dl_linux_resolver(unsigned int reloc_entry,
+- unsigned int * i);
+-#endif
++struct elf_resolve;
++unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+ /*
+ * Define this if you want a dynamic loader that works on Solaris.
+ */
+-#ifndef __linux__
+-#define SOLARIS_COMPATIBLE
+-#endif
+
+ #ifndef COMPILE_ASM
+ /* Cheap modulo implementation, taken from arm/ld_sysdep.h. */
+@@ -87,13 +82,6 @@
+ #define do_rem(result, n, base) ((result) = sparc_mod(n, base))
+ #endif
+
+-/*
+- * dbx wants the binder to have a specific name. Mustn't disappoint it.
+- */
+-#ifdef SOLARIS_COMPATIBLE
+-#define _dl_linux_resolve _elf_rtbndr
+-#endif
+-
+ /* 4096 bytes alignment */
+ /* ...but 8192 is required for mmap() on sparc64 kernel */
+ #define PAGE_ALIGN 0xffffe000
+@@ -160,7 +148,7 @@
+ elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
+ Elf32_Word relative_count)
+ {
+- Elf32_Rela * rpnt = (void *)rel_addr;
++ Elf32_Rela * rpnt = (void *)rel_addr;
+ --rpnt;
+ do {
+ Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
+diff -urN uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/sparc/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/sparc/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -33,236 +33,340 @@
+ an ELF sharable library or a linux style of shared library. */
+
+ /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+- I ever taken any courses on internals. This program was developed using
+- information available through the book "UNIX SYSTEM V RELEASE 4,
+- Programmers guide: Ansi C and Programming Support Tools", which did
+- a more than adequate job of explaining everything required to get this
+- working. */
++ I ever taken any courses on internals. This program was developed using
++ information available through the book "UNIX SYSTEM V RELEASE 4,
++ Programmers guide: Ansi C and Programming Support Tools", which did
++ a more than adequate job of explaining everything required to get this
++ working. */
++
++/* Some SPARC opcodes we need to use for self-modifying code. */
++#define OPCODE_NOP 0x01000000 /* nop */
++#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */
++#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */
++#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */
++#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
++#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */
+
+ extern int _dl_linux_resolve(void);
+
+-unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
++unsigned long
++_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+ {
+- int reloc_type;
+- Elf32_Rela * this_reloc;
+- char * strtab;
+- Elf32_Sym * symtab;
+- Elf32_Rela * rel_addr;
+- struct elf_resolve * tpnt;
+- int symtab_index;
+- char * new_addr;
+- char ** got_addr;
+- unsigned int instr_addr;
+- tpnt = (struct elf_resolve *) plt[2];
+-
+- rel_addr = (Elf32_Rela *)tpnt->dynamic_info[DT_JMPREL];
+-
+- /*
+- * Generate the correct relocation index into the .rela.plt section.
+- */
+- reloc_entry = (reloc_entry >> 10) - 0xc;
+-
+- this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
+-
+- reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+- symtab_index = ELF32_R_SYM(this_reloc->r_info);
+-
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
+-
+-#ifdef __SUPPORT_LD_DEBUG__
+- if (_dl_debug_symbols) {
+- _dl_dprintf(2, "tpnt = %x\n", tpnt);
+- _dl_dprintf(2, "reloc = %x\n", this_reloc);
+- _dl_dprintf(2, "symtab = %x\n", symtab);
+- _dl_dprintf(2, "strtab = %x\n", strtab);
+- }
+-#endif
+-
+-
+- if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
+- _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
+- _dl_progname, reloc_type);
+- _dl_exit(30);
+- };
+-
+- /* Address of jump instruction to fix up */
+- instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
+- got_addr = (char **) instr_addr;
+-
+-#ifdef __SUPPORT_LD_DEBUG__
+- if (_dl_debug_symbols) {
+- _dl_dprintf(2, "symtab_index %x\n", symtab_index);
+-
+- _dl_dprintf(2, "Resolving symbol %s\n",
+- strtab + symtab[symtab_index].st_name);
+- }
+-#endif
+-
+- /* Get the address of the GOT entry */
+- new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
+- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+- if(unlikely(!new_addr)) {
+- _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+- _dl_progname, strtab + symtab[symtab_index].st_name);
+- _dl_exit(31);
+- };
++ int reloc_type;
++ ELF_RELOC *this_reloc;
++ char *strtab;
++ ElfW(Sym) *symtab;
++ int symtab_index;
++ char *rel_addr;
++ char *new_addr;
++ char **got_addr;
++ ElfW(Addr) instr_addr;
++ char *symname;
++
++ rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
++ /*
++ * Generate the correct relocation index into the .rela.plt section.
++ */
++ reloc_entry = (reloc_entry >> 10) - 0xc;
++
++ this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry);
++ reloc_type = ELF_R_TYPE(this_reloc->r_info);
++ symtab_index = ELF_R_SYM(this_reloc->r_info);
++
++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
++ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
++ symname = strtab + symtab[symtab_index].st_name;
++
++ if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
++ _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
++ _dl_progname);
++ _dl_exit(1);
++ }
++
++ /* Address of the jump instruction to fix up. */
++ instr_addr = (this_reloc->r_offset + tpnt->loadaddr);
++ got_addr = (char **)instr_addr;
++
++ /* Get the address of the GOT entry */
++ new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
++ if (unlikely(!new_addr)) {
++ _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_exit(1);
++ }
+
+ #if defined (__SUPPORT_LD_DEBUG__)
+- if ((unsigned long) got_addr < 0x40000000)
+- {
+- if (_dl_debug_bindings)
+- {
+- _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
+- strtab + symtab[symtab_index].st_name);
+- if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+- "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
++ if ((unsigned long)got_addr < 0x40000000) {
++ if (_dl_debug_bindings) {
++ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
++ if (_dl_debug_detail)
++ _dl_dprintf(_dl_debug_file,
++ "\tpatched: %x ==> %x @ %x\n",
++ *got_addr, new_addr, got_addr);
+ }
+ }
+- if (!_dl_debug_nofixups) {
++ if (!_dl_debug_nofixups)
++#endif
++ {
+ got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
+ got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
+ }
++
++ return (unsigned long)new_addr;
++}
++
++static int
++_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ unsigned long rel_addr, unsigned long rel_size,
++ int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))
++{
++ unsigned int i;
++ char *strtab;
++ ElfW(Sym) *symtab;
++ ELF_RELOC *rpnt;
++ int symtab_index;
++
++ /* Parse the relocation information. */
++ rpnt = (ELF_RELOC *)rel_addr;
++ rel_size /= sizeof(ELF_RELOC);
++
++ symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB];
++ strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
++
++ for (i = 0; i < rel_size; i++, rpnt++) {
++ int res;
++
++ symtab_index = ELF_R_SYM(rpnt->r_info);
++
++ debug_sym(symtab, strtab, symtab_index);
++ debug_reloc(symtab, strtab, rpnt);
++
++ res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
++
++ if (res == 0)
++ continue;
++
++ _dl_dprintf(2, "\n%s: ", _dl_progname);
++
++ if (symtab_index)
++ _dl_dprintf(2, "symbol '%s': ",
++ strtab + symtab[symtab_index].st_name);
++
++ if (unlikely(res < 0)) {
++ int reloc_type = ELF_R_TYPE(rpnt->r_info);
++
++ _dl_dprintf(2, "can't handle reloc type "
++#if defined (__SUPPORT_LD_DEBUG__)
++ "%s\n", _dl_reltypes(reloc_type));
+ #else
+- got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
+- got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
++ "%x\n", reloc_type);
+ #endif
++ _dl_exit(-res);
++ } else if (unlikely(res > 0)) {
++ _dl_dprintf(2, "can't resolve symbol\n");
++ return res;
++ }
++ }
++
++ return 0;
++}
+
+- _dl_dprintf(2, "Address = %x\n",new_addr);
+- _dl_exit(32);
++static int
++_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
++{
++ int reloc_type;
++ int symtab_index;
++ char *symname;
++ ElfW(Sym) *sym;
++ ElfW(Addr) *reloc_addr;
++ ElfW(Addr) symbol_addr;
++#if defined (__SUPPORT_LD_DEBUG__)
++ ElfW(Addr) old_val;
++#endif
++
++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
++ reloc_type = ELF_R_TYPE(rpnt->r_info);
++ symtab_index = ELF_R_SYM(rpnt->r_info);
++ sym = &symtab[symtab_index];
++ symbol_addr = 0;
++ symname = strtab + sym->st_name;
++
++ if (symtab_index) {
++ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
++ elf_machine_type_class(reloc_type));
++ /*
++ * We want to allow undefined references to weak symbols - this
++ * might have been intentional. We should not be linking local
++ * symbols here, so all bases should be covered.
++ */
++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
++ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
++ _dl_exit(1);
++ }
++ }
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ old_val = *reloc_addr;
++#endif
+
+- return (unsigned int) new_addr;
++ symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */
++
++ switch (reloc_type) {
++ case R_SPARC_NONE:
++ break;
++
++#if 0 /* these dont really seem to be useful */
++ case R_SPARC_8:
++ *(char *) reloc_addr = symbol_addr;
++ break;
++ case R_SPARC_16:
++ *(short *) reloc_addr = symbol_addr;
++ break;
++ case R_SPARC_DISP8:
++ *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr;
++ break;
++ case R_SPARC_DISP16:
++ *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr;
++ break;
++#endif
++
++ case R_SPARC_DISP32:
++ *reloc_addr = symbol_addr - (unsigned int) reloc_addr;
++ break;
++
++ case R_SPARC_LO10:
++ if (!symbol_addr)
++ symbol_addr = tpnt->loadaddr + rpnt->r_addend;
++ else
++ symbol_addr += rpnt->r_addend;
++ *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff);
++ break;
++
++ case R_SPARC_GLOB_DAT:
++ case R_SPARC_32:
++ *reloc_addr = symbol_addr;
++ break;
++
++ case R_SPARC_JMP_SLOT:
++/*
++value = symbol_addr;
++value += reloc->r_addend;
++disp = value - reloc_addr;
++reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff);
++reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10);
++ reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff);
++ reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10);
++*/
++ reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
++ reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
++ break;
++
++ case R_SPARC_RELATIVE:
++ *reloc_addr += tpnt->loadaddr + rpnt->r_addend;
++ break;
++
++ case R_SPARC_WDISP30:
++ *reloc_addr = (*reloc_addr & 0xc0000000)|
++ ((symbol_addr - (unsigned int) reloc_addr) >> 2);
++ break;
++
++ case R_SPARC_HI22:
++ if (!symbol_addr)
++ symbol_addr = tpnt->loadaddr + rpnt->r_addend;
++ else
++ symbol_addr += rpnt->r_addend;
++ *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10);
++ break;
++
++ case R_SPARC_COPY:
++ if (symbol_addr) {
++#if defined (__SUPPORT_LD_DEBUG__)
++ if (_dl_debug_move)
++ _dl_dprintf(_dl_debug_file,
++ "\t%s move %d bytes from %x to %x\n",
++ symname, sym->st_size,
++ symbol_addr, reloc_addr);
++#endif
++
++ _dl_memcpy((char *)reloc_addr,
++ (char *)symbol_addr,
++ sym->st_size);
++ } else
++ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
++ break;
++ default:
++ return -1; /* Calls _dl_exit(1). */
++ }
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ if (_dl_debug_reloc && _dl_debug_detail)
++ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
++ old_val, *reloc_addr, reloc_addr);
++#endif
++
++ return 0;
++}
++
++#undef __SPARC_LAZY_RELOC_WORKS
++#ifdef __SPARC_LAZY_RELOC_WORKS
++static int
++_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
++ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
++{
++ int reloc_type;
++ int symtab_index;
++ ElfW(Addr) *reloc_addr;
++#if defined (__SUPPORT_LD_DEBUG__)
++ ElfW(Addr) old_val;
++#endif
++
++ (void)scope;
++ symtab_index = ELF_R_SYM(rpnt->r_info);
++ (void)strtab;
++
++ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset);
++ reloc_type = ELF_R_TYPE(rpnt->r_info);
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ old_val = *reloc_addr;
++#endif
++
++ switch (reloc_type) {
++ case R_SPARC_NONE:
++ break;
++ case R_SPARC_JMP_SLOT:
++ break;
++ default:
++ _dl_exit(1);
++ }
++
++#if defined (__SUPPORT_LD_DEBUG__)
++ if (_dl_debug_reloc && _dl_debug_detail)
++ _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n",
++ old_val, *reloc_addr, reloc_addr);
++#endif
++
++ return 0;
+ }
++#endif
+
+-void _dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
+-{
+- int i;
+- char * strtab;
+- int reloc_type;
+- int symtab_index;
+- Elf32_Sym * symtab;
+- Elf32_Rela * rpnt;
+- unsigned int * reloc_addr;
+- struct elf_resolve * tpnt = arg_rpnt->dyn;
+-
+- /* Now parse the relocation information */
+- rpnt = (Elf32_Rela *)rel_addr;
+-
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
+-
+- for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
+- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE(rpnt->r_info);
+- symtab_index = ELF32_R_SYM(rpnt->r_info);
+-
+- switch(reloc_type){
+- case R_SPARC_NONE:
+- break;
+- case R_SPARC_JMP_SLOT:
+- break;
+- default:
+- _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
+-#if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]);
+-#endif
+- if(symtab_index) _dl_dprintf(2, "'%s'\n",
+- strtab + symtab[symtab_index].st_name);
+- _dl_exit(33);
+- };
+- };
+-}
+-
+-int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
+- unsigned long rel_addr, unsigned long rel_size)
+-{
+- int i;
+- char * strtab;
+- int reloc_type;
+- int goof = 0;
+- Elf32_Sym * symtab;
+- Elf32_Rela * rpnt;
+- unsigned int * reloc_addr;
+- unsigned int symbol_addr;
+- int symtab_index;
+- struct elf_resolve * tpnt = arg_rpnt->dyn;
+- /* Now parse the relocation information */
+-
+- rpnt = (Elf32_Rela *)rel_addr;
+-
+- symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
+- strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
+-
+- for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
+- reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
+- reloc_type = ELF32_R_TYPE(rpnt->r_info);
+- symtab_index = ELF32_R_SYM(rpnt->r_info);
+- symbol_addr = 0;
+-
+- if(symtab_index) {
+-
+- symbol_addr = (unsigned int)
+- _dl_find_hash(strtab + symtab[symtab_index].st_name,
+- tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type));
+-
+- if(!symbol_addr &&
+- ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) {
+- _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
+- _dl_progname, strtab + symtab[symtab_index].st_name);
+- _dl_exit (1);
+- };
+- };
+- switch(reloc_type){
+- case R_SPARC_NONE:
+- break;
+- case R_SPARC_32:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_SPARC_DISP32:
+- *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
+- break;
+- case R_SPARC_GLOB_DAT:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
+- break;
+- case R_SPARC_JMP_SLOT:
+- reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
+- reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
+- break;
+- case R_SPARC_RELATIVE:
+- *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
+- break;
+- case R_SPARC_HI22:
+- if (!symbol_addr)
+- symbol_addr = tpnt->loadaddr + rpnt->r_addend;
+- else
+- symbol_addr += rpnt->r_addend;
+- *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10);
+- break;
+- case R_SPARC_LO10:
+- if (!symbol_addr)
+- symbol_addr = tpnt->loadaddr + rpnt->r_addend;
+- else
+- symbol_addr += rpnt->r_addend;
+- *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff);
+- break;
+- case R_SPARC_WDISP30:
+- *reloc_addr = (*reloc_addr & 0xc0000000)|
+- ((symbol_addr - (unsigned int) reloc_addr) >> 2);
+- break;
+- case R_SPARC_COPY:
+- _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size);
+- break;
+- default:
+- _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+-#if defined (__SUPPORT_LD_DEBUG__)
+- _dl_dprintf(2, "%s ", _dl_reltypes_tab[reloc_type]);
+-#endif
+- if (symtab_index)
+- _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+- _dl_exit(34);
+- };
++void
++_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++#ifdef __SPARC_LAZY_RELOC_WORKS
++ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
++#else
++ _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
++#endif
++}
+
+- };
+- return goof;
++int
++_dl_parse_relocation_information(struct dyn_elf *rpnt,
++ unsigned long rel_addr,
++ unsigned long rel_size)
++{
++ return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+ }
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-debug.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-debug.h 2006-04-28 00:14:35.000000000 -0600
+@@ -30,7 +30,10 @@
+ */
+
+ static const char *_dl_reltypes_tab[] = {
+- [0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32",
+- [4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT",
+- [8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32"
++ [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32",
++ [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT",
++ [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S",
++ [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8",
++ [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD",
++ [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32"
+ };
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-startup.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-startup.h 2006-04-28 00:14:35.000000000 -0600
+@@ -6,7 +6,7 @@
+ *
+ * Parts taken from glibc/sysdeps/x86_64/dl-machine.h
+ */
+-asm(
++__asm__ (
+ " .text\n"
+ " .align 16\n"
+ " .global _start\n"
+@@ -42,10 +42,10 @@
+
+ /* Handle relocation of the symbols in the dynamic loader. */
+ static __always_inline
+-void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
+- unsigned long symbol_addr, unsigned long load_addr, Elf64_Sym *sym)
++void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr,
++ ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym)
+ {
+- switch (ELF64_R_TYPE(rpnt->r_info)) {
++ switch (ELF_R_TYPE(rpnt->r_info)) {
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_JUMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+@@ -63,8 +63,3 @@
+ _dl_exit(1);
+ }
+ }
+-
+-/* Transfer control to the user's application, once the dynamic loader is
+- * done. This routine has to exit the current function, then call the
+- * _dl_elf_main function. */
+-#define START() return _dl_elf_main
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-syscalls.h 2006-05-02 13:39:17.000000000 -0600
+@@ -1,7 +1,8 @@
+ /* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
++#define __UCLIBC_MMAP_HAS_6_ARGS__
++
++#include "sys/syscall.h"
+ extern int _dl_errno;
++#undef __set_errno
+ #define __set_errno(X) {(_dl_errno) = (X);}
+-#include "sys/syscall.h"
+-
+-#define MMAP_HAS_6_ARGS
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/dl-sysdep.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/dl-sysdep.h 2006-04-28 00:14:35.000000000 -0600
+@@ -41,8 +41,6 @@
+ struct elf_resolve;
+ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+-#define do_rem(result, n, base) ((result) = (n) % (base))
+-
+ /* 4096 bytes alignment */
+ #define PAGE_ALIGN 0xfffff000
+ #define ADDR_ALIGN 0xfff
+@@ -90,7 +88,7 @@
+ and compare it with the current value that we can get via
+ an RIP relative addressing mode. */
+
+- asm ("movq 1f(%%rip), %1\n"
++ __asm__ ("movq 1f(%%rip), %1\n"
+ "0:\tleaq _dl_start(%%rip), %0\n\t"
+ "subq %1, %0\n\t"
+ ".section\t.data\n"
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/elfinterp.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/ldso/x86_64/elfinterp.c 2006-04-28 00:14:35.000000000 -0600
+@@ -165,6 +165,7 @@
+ int reloc_type;
+ int symtab_index;
+ char *symname;
++ ElfW(Sym) *sym;
+ ElfW(Addr) *reloc_addr;
+ ElfW(Addr) symbol_addr;
+ #if defined (__SUPPORT_LD_DEBUG__)
+@@ -174,8 +175,9 @@
+ reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
+ reloc_type = ELF_R_TYPE(rpnt->r_info);
+ symtab_index = ELF_R_SYM(rpnt->r_info);
++ sym = &symtab[symtab_index];
+ symbol_addr = 0;
+- symname = strtab + symtab[symtab_index].st_name;
++ symname = strtab + sym->st_name;
+
+ if (symtab_index) {
+ symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
+@@ -185,7 +187,7 @@
+ * might have been intentional. We should not be linking local
+ * symbols here, so all bases should be covered.
+ */
+- if (unlikely(!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
++ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
+ _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+ _dl_exit(1);
+ };
+@@ -209,7 +211,7 @@
+
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_JUMP_SLOT:
+- *reloc_addr = symbol_addr;
++ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+
+ /* handled by elf_machine_relative()
+@@ -217,33 +219,33 @@
+ *reloc_addr = map->l_addr + rpnt->r_addend;
+ break;
+ */
+-#if 0
+ case R_X86_64_DTPMOD64:
++ *reloc_addr = 1;
+ break;
+ case R_X86_64_DTPOFF64:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
++ *reloc_addr = sym->st_value + rpnt->r_addend;
+ break;
+ case R_X86_64_TPOFF64:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
++ *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr;
+ break;
+ case R_X86_64_32:
+- *reloc_addr = symbol_addr + rpnt->r_addend;
++ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;
++ /* XXX: should check for overflow eh ? */
+ break;
+
+-#endif
+ case R_X86_64_COPY:
+ if (symbol_addr) {
+ #if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug_move)
+ _dl_dprintf(_dl_debug_file,
+ "\t%s move %d bytes from %x to %x\n",
+- symname, symtab[symtab_index].st_size,
++ symname, sym->st_size,
+ symbol_addr, reloc_addr);
+ #endif
+
+ _dl_memcpy((char *)reloc_addr,
+ (char *)symbol_addr,
+- symtab[symtab_index].st_size);
++ sym->st_size);
+ } else
+ _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
+ break;
+@@ -261,7 +263,6 @@
+ return 0;
+ }
+
+-#if 0
+ static int
+ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
+@@ -288,7 +289,7 @@
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_JUMP_SLOT:
+- *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value;
++ *reloc_addr += (unsigned long)tpnt->loadaddr;
+ break;
+ default:
+ _dl_exit(1);
+@@ -302,17 +303,13 @@
+
+ return 0;
+ }
+-#endif
+
+ void
+ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr,
+ unsigned long rel_size)
+ {
+- _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
+-/* jump slot isnt working
+ (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+-*/
+ }
+
+ int
+diff -urN uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S uClibc-0.9.28/ldso/ldso/x86_64/resolve.S
+--- uClibc-0.9.28.orig/ldso/ldso/x86_64/resolve.S 1969-12-31 17:00:00.000000000 -0700
++++ uClibc-0.9.28/ldso/ldso/x86_64/resolve.S 2006-04-28 00:14:35.000000000 -0600
+@@ -0,0 +1,63 @@
++/*
++ * This function is _not_ called directly. It is jumped to (so no return
++ * address is on the stack) when attempting to use a symbol that has not yet
++ * been resolved. The first time a jump symbol (such as a function call inside
++ * a shared library) is used (before it gets resolved) it will jump here to
++ * _dl_linux_resolve. When we get called the stack looks like this:
++ * reloc_entry
++ * tpnt
++ *
++ * This function saves all the registers, puts a copy of reloc_entry and tpnt
++ * on the stack (as function arguments) then make the function call
++ * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out
++ * where the jump symbol is _really_ supposed to have jumped to and returns
++ * that to us. Once we have that, we overwrite tpnt with this fixed up
++ * address. We then clean up after ourselves, put all the registers back how we
++ * found them, then we jump to where the fixed up address, which is where the
++ * jump symbol that got us here really wanted to jump to in the first place.
++ * found them, then we jump to the fixed up address, which is where the jump
++ * symbol that got us here really wanted to jump to in the first place.
++ * -Erik Andersen
++ */
++
++/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */
++
++.text
++
++.global _dl_linux_resolve
++.type _dl_linux_resolve,%function
++.align 16
++
++_dl_linux_resolve:
++ subq $56,%rsp
++ /* Preserve registers otherwise clobbered. */
++ movq %rax, (%rsp)
++ movq %rcx, 8(%rsp)
++ movq %rdx, 16(%rsp)
++ movq %rsi, 24(%rsp)
++ movq %rdi, 32(%rsp)
++ movq %r8, 40(%rsp)
++ movq %r9, 48(%rsp)
++
++ movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */
++ movq %rsi, %r11 /* Multiply by 24 */
++ addq %r11, %rsi
++ addq %r11, %rsi
++ shlq $3, %rsi
++ movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */
++ call _dl_linux_resolver /* Call resolver. */
++ movq %rax, %r11 /* Save return value */
++
++ /* Get register content back. */
++ movq 48(%rsp), %r9
++ movq 40(%rsp), %r8
++ movq 32(%rsp), %rdi
++ movq 24(%rsp), %rsi
++ movq 16(%rsp), %rdx
++ movq 8(%rsp), %rcx
++ movq (%rsp), %rax
++
++ addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */
++ jmp *%r11 /* Jump to function address. */
++
++.size _dl_linux_resolve,.-_dl_linux_resolve
+diff -urN uClibc-0.9.28.orig/ldso/libdl/Makefile uClibc-0.9.28/ldso/libdl/Makefile
+--- uClibc-0.9.28.orig/ldso/libdl/Makefile 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/libdl/Makefile 2006-04-28 00:14:35.000000000 -0600
+@@ -29,12 +29,14 @@
+ endif
+ XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) \
+ -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+- -fno-builtin -nostdinc -D_LIBC -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I. -I$(TOPDIR)include
++ -fno-builtin -nostdinc -D_LIBC \
++ -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" \
++ -I$(TOPDIR)ldso/ldso/$(TARGET_ARCH) -I$(TOPDIR)ldso/include -I$(TOPDIR)ldso/ldso -I$(TOPDIR)include
+
+ XXFLAGS+=-isystem $(shell $(CC) -print-file-name=include)
+ XXFLAGS_NOPIC:=$(XXFLAGS)
+ ifeq ($(DOPIC),y)
+- XXFLAGS += $(PICFLAG) -D__LIBDL_SHARED__
++ XXFLAGS += $(PICFLAG) -DSHARED
+ endif
+ ifeq ($(strip $(SUPPORT_LD_DEBUG)),y)
+ XXFLAGS+=-D__SUPPORT_LD_DEBUG__
+diff -urN uClibc-0.9.28.orig/ldso/libdl/libdl.c uClibc-0.9.28/ldso/libdl/libdl.c
+--- uClibc-0.9.28.orig/ldso/libdl/libdl.c 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/ldso/libdl/libdl.c 2006-04-28 00:14:35.000000000 -0600
+@@ -3,7 +3,7 @@
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+- * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
++ * Copyright (C) 2000-2006 by Erik Andersen <andersen@uclibc.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+@@ -30,12 +30,12 @@
+ */
+
+
+-#define _GNU_SOURCE
++#define _GNU_SOURCE
+ #include <ldso.h>
+ #include <stdio.h>
+
+
+-#if defined (__LIBDL_SHARED__)
++#ifdef SHARED
+
+ /* When libdl is loaded as a shared library, we need to load in
+ * and use a pile of symbols from ldso... */
+@@ -52,6 +51,8 @@
+ extern struct r_debug *_dl_debug_addr;
+ extern unsigned long _dl_error_number;
+ extern void *(*_dl_malloc_function)(size_t);
++extern void _dl_run_init_array(struct elf_resolve *);
++extern void _dl_run_fini_array(struct elf_resolve *);
+ #ifdef __LDSO_CACHE_SUPPORT__
+ int _dl_map_cache(void);
+ int _dl_unmap_cache(void);
+@@ -64,7 +65,7 @@
+ #endif
+
+
+-#else /* __LIBDL_SHARED__ */
++#else /* SHARED */
+
+ /* When libdl is linked as a static library, we need to replace all
+ * the symbols that otherwise would have been loaded in from ldso... */
+@@ -81,11 +82,11 @@
+ struct r_debug *_dl_debug_addr = NULL;
+ #define _dl_malloc malloc
+ #include "../ldso/dl-debug.c"
+-#include "dl-progname.h"
++#include LDSO_ELFINTERP
+ #include "../ldso/dl-hash.c"
+ #define _dl_trace_loaded_objects 0
+ #include "../ldso/dl-elf.c"
+-#endif /* __LIBDL_SHARED__ */
++#endif /* SHARED */
+
+ #ifdef __SUPPORT_LD_DEBUG__
+ # define _dl_if_debug_print(fmt, args...) \
+@@ -126,7 +127,8 @@
+ "Unable to resolve symbol"
+ };
+
+-void __attribute__ ((destructor)) dl_cleanup(void)
++void dl_cleanup(void) __attribute__ ((destructor));
++void dl_cleanup(void)
+ {
+ struct dyn_elf *d;
+ for (d = _dl_handles; d; d = d->next_handle) {
+@@ -138,13 +140,12 @@
+ {
+ struct elf_resolve *tpnt, *tfrom;
+ struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
+- struct dyn_elf *dpnt;
+ ElfW(Addr) from;
+ struct elf_resolve *tpnt1;
+ void (*dl_brk) (void);
+ int now_flag;
+ struct init_fini_list *tmp, *runp, *runp2, *dep_list;
+- int nlist, i;
++ unsigned int nlist, i;
+ struct elf_resolve **init_fini_list;
+
+ /* A bit of sanity checking... */
+@@ -169,12 +170,15 @@
+ * the application. Thus this may go away at some time
+ * in the future.
+ */
+- tfrom = NULL;
+- for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
+- tpnt = dpnt->dyn;
+- if (tpnt->loadaddr < from
+- && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
+- tfrom = tpnt;
++ {
++ struct dyn_elf *dpnt;
++ tfrom = NULL;
++ for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
++ tpnt = dpnt->dyn;
++ if (tpnt->loadaddr < from
++ && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
++ tfrom = tpnt;
++ }
+ }
+ for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next);
+
+@@ -233,11 +237,8 @@
+ runp->tpnt->init_fini = NULL; /* clear any previous dependcies */
+ for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) {
+ if (dpnt->d_tag == DT_NEEDED) {
+- char *name;
+-
+ lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
+ dpnt->d_un.d_val);
+- name = _dl_get_last_path_component(lpntstr);
+ _dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
+ lpntstr, runp->tpnt->libname);
+ tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
+@@ -297,14 +298,14 @@
+ }
+ /* Sort the INIT/FINI list in dependency order. */
+ for (runp2 = dep_list; runp2; runp2 = runp2->next) {
+- int j, k;
++ unsigned int j, k;
+ for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
+ /* Empty */;
+ for (k = j + 1; k < nlist; ++k) {
+- struct init_fini_list *runp = init_fini_list[k]->init_fini;
++ struct init_fini_list *ele = init_fini_list[k]->init_fini;
+
+- for (; runp; runp = runp->next) {
+- if (runp->tpnt == runp2->tpnt) {
++ for (; ele; ele = ele->next) {
++ if (ele->tpnt == runp2->tpnt) {
+ struct elf_resolve *here = init_fini_list[k];
+ _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
+ for (i = (k - j); i; --i)
+@@ -367,7 +368,7 @@
+ }
+ }
+
+-#if defined (__LIBDL_SHARED__)
++#ifdef SHARED
+ /* Run the ctors and setup the dtors */
+ for (i = nlist; i; --i) {
+ tpnt = init_fini_list[i-1];
+@@ -384,8 +385,11 @@
+ (*dl_elf_func) ();
+ }
+ }
++
++ _dl_run_init_array(tpnt);
+ }
+-#endif
++#endif /* SHARED */
++
+ _dl_unmap_cache();
+ return (void *) dyn_chain;
+
+@@ -450,9 +454,16 @@
+ return ret;
+ }
+
++#if 0
++void *dlvsym(void *vhandle, const char *name, const char *version)
++{
++ return dlsym(vhandle, name);
++}
++#endif
++
+ static int do_dlclose(void *vhandle, int need_fini)
+ {
+- struct dyn_elf *rpnt, *rpnt1;
++ struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
+ struct init_fini_list *runp, *tmp;
+ ElfW(Phdr) *ppnt;
+ struct elf_resolve *tpnt, *run_tpnt;
+@@ -460,7 +471,7 @@
+ void (*dl_brk) (void);
+ struct dyn_elf *handle;
+ unsigned int end;
+- int i = 0, j;
++ unsigned int i, j;
+
+ handle = (struct dyn_elf *) vhandle;
+ if (handle == _dl_symbol_tables)
+@@ -491,13 +502,21 @@
+ for (j = 0; j < handle->init_fini.nlist; ++j) {
+ tpnt = handle->init_fini.init_fini[j];
+ if (--tpnt->usage_count == 0) {
+- if (tpnt->dynamic_info[DT_FINI] && need_fini &&
++ if ((tpnt->dynamic_info[DT_FINI]
++ || tpnt->dynamic_info[DT_FINI_ARRAY])
++ && need_fini &&
+ !(tpnt->init_flag & FINI_FUNCS_CALLED)) {
+ tpnt->init_flag |= FINI_FUNCS_CALLED;
+- dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+- _dl_if_debug_print("running dtors for library %s at '%p'\n",
+- tpnt->libname, dl_elf_fini);
+- (*dl_elf_fini) ();
++#ifdef SHARED
++ _dl_run_fini_array(tpnt);
++#endif
++
++ if (tpnt->dynamic_info[DT_FINI]) {
++ dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
++ _dl_if_debug_print("running dtors for library %s at '%p'\n",
++ tpnt->libname, dl_elf_fini);
++ (*dl_elf_fini) ();
++ }
+ }
+
+ _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
+@@ -541,8 +560,9 @@
+ for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
+ if (rpnt1->next->dyn == tpnt) {
+ _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
++ rpnt1_tmp = rpnt1->next->next;
+ free(rpnt1->next);
+- rpnt1->next = rpnt1->next->next;
++ rpnt1->next = rpnt1_tmp;
+ if (rpnt1->next)
+ rpnt1->next->prev = rpnt1;
+ break;
+@@ -588,8 +608,9 @@
+ }
+
+ /*
+- * Dump information to stderrr about the current loaded modules
++ * Dump information to stderr about the current loaded modules
+ */
++#if 1
+ static char *type[] = { "Lib", "Exe", "Int", "Mod" };
+
+ int dlinfo(void)
+@@ -660,16 +681,14 @@
+ {
+ char *strtab;
+ ElfW(Sym) *symtab;
+- int hn, si;
+- int sf;
+- int sn = 0;
++ unsigned int hn, si, sn, sf;
+ ElfW(Addr) sa;
+
+ sa = 0;
+ symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
+ strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
+
+- sf = 0;
++ sf = sn = 0;
+ for (hn = 0; hn < pelf->nbucket; hn++) {
+ for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
+ ElfW(Addr) symbol_addr;
+@@ -696,3 +715,4 @@
+ return 1;
+ }
+ }
++#endif
+diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/i386/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/libc/sysdeps/linux/i386/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -4,17 +4,15 @@
+ # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+ #endif
+
++#include <errno.h>
++
+ /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
+ * header files. It also defines the traditional `SYS_<name>' macros for older
+ * programs. */
+ #include <bits/sysnum.h>
+
+-#ifndef __set_errno
+-# define __set_errno(val) (*__errno_location ()) = (val)
+-#endif
+-
+ /*
+- Some of the sneaky macros in the code were taken from
++ Some of the sneaky macros in the code were taken from
+ glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h
+ */
+
+@@ -22,7 +20,8 @@
+
+ /* We need some help from the assembler to generate optimal code. We
+ define some macros here which later will be used. */
+-asm (".L__X'%ebx = 1\n\t"
++
++__asm__ (".L__X'%ebx = 1\n\t"
+ ".L__X'%ecx = 2\n\t"
+ ".L__X'%edx = 2\n\t"
+ ".L__X'%eax = 3\n\t"
+@@ -56,7 +55,6 @@
+ ".endif\n\t"
+ ".endm\n\t");
+
+-
+ #undef _syscall0
+ #define _syscall0(type,name) \
+ type name(void) \
+@@ -90,7 +88,7 @@
+ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+ { \
+ return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \
+-}
++}
+
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+@@ -100,10 +98,18 @@
+ return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \
+ }
+
++#undef _syscall6
++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
++ type5,arg5,type6,arg6) \
++type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \
++{ \
++return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \
++}
++
+ #define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ unsigned int resultvar; \
+- asm volatile ( \
++ __asm__ __volatile__ ( \
+ LOADARGS_##nr \
+ "movl %1, %%eax\n\t" \
+ "int $0x80\n\t" \
+@@ -125,6 +131,7 @@
+ #define LOADARGS_3 LOADARGS_1
+ #define LOADARGS_4 LOADARGS_1
+ #define LOADARGS_5 LOADARGS_1
++#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t"
+
+ #define RESTOREARGS_0
+ #define RESTOREARGS_1 \
+@@ -133,6 +140,7 @@
+ #define RESTOREARGS_3 RESTOREARGS_1
+ #define RESTOREARGS_4 RESTOREARGS_1
+ #define RESTOREARGS_5 RESTOREARGS_1
++#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1
+
+ #define ASMFMT_0()
+ #define ASMFMT_1(arg1) \
+@@ -145,7 +153,8 @@
+ , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
+ #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
+ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
+-
++#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \
++ , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6)
+
+ #endif /* __ASSEMBLER__ */
+ #endif /* _BITS_SYSCALLS_H */
+diff -urN uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h
+--- uClibc-0.9.28.orig/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-05-02 10:47:27.000000000 -0600
++++ uClibc-0.9.28/libc/sysdeps/linux/powerpc/bits/syscalls.h 2006-04-28 00:14:35.000000000 -0600
+@@ -5,67 +5,164 @@
+ # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+ #endif
+
++#include <errno.h>
++
+ /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
+ * header files. It also defines the traditional `SYS_<name>' macros for older
+ * programs. */
+ #include <bits/sysnum.h>
+
+-
+-#define __STRINGIFY(s) __STRINGIFY2 (s)
+-#define __STRINGIFY2(s) #s
+-
+-#undef JUMPTARGET
+-#ifdef __PIC__
+-#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall@plt)
++/* Define a macro which expands inline into the wrapper code for a system
++ call. This use is for internal calls that do not need to handle errors
++ normally. It will never touch errno.
++ On powerpc a system call basically clobbers the same registers like a
++ function call, with the exception of LR (which is needed for the
++ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
++ an error return status). */
++
++# undef INLINE_SYSCALL
++#if 1
++# define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ INTERNAL_SYSCALL_DECL (sc_err); \
++ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
++ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
++ { \
++ __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
++ sc_ret = -1L; \
++ } \
++ sc_ret; \
++ })
+ #else
+-#define __MAKE_SYSCALL __STRINGIFY(__uClibc_syscall)
++# define INLINE_SYSCALL(name, nr, args...) \
++ ({ \
++ INTERNAL_SYSCALL_DECL (sc_err); \
++ long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
++ if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
++ { \
++ sc_ret = __syscall_error(INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));\
++ } \
++ sc_ret; \
++ })
+ #endif
+
+-#define unified_syscall_body(name) \
+- __asm__ ( \
+- ".section \".text\"\n\t" \
+- ".align 2\n\t" \
+- ".globl " __STRINGIFY(name) "\n\t" \
+- ".type " __STRINGIFY(name) ",@function\n\t" \
+- #name":\tli 0," __STRINGIFY(__NR_##name) "\n\t" \
+- "b " __MAKE_SYSCALL "\n\t" \
+- ".size\t" __STRINGIFY(name) ",.""-" __STRINGIFY(name) "\n" \
+- )
++/* Define a macro which expands inline into the wrapper code for a system
++ call. This use is for internal calls that do not need to handle errors
++ normally. It will never touch errno.
++ On powerpc a system call basically clobbers the same registers like a
++ function call, with the exception of LR (which is needed for the
++ "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
++ an error return status). */
++
++# undef INTERNAL_SYSCALL_DECL
++# define INTERNAL_SYSCALL_DECL(err) long int err
++
++# undef INTERNAL_SYSCALL
++# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
++ ({ \
++ register long int r0 __asm__ ("r0"); \
++ register long int r3 __asm__ ("r3"); \
++ register long int r4 __asm__ ("r4"); \
++ register long int r5 __asm__ ("r5"); \
++ register long int r6 __asm__ ("r6"); \
++ register long int r7 __asm__ ("r7"); \
++ register long int r8 __asm__ ("r8"); \
++ register long int r9 __asm__ ("r9"); \
++ register long int r10 __asm__ ("r10"); \
++ register long int r11 __asm__ ("r11"); \
++ register long int r12 __asm__ ("r12"); \
++ LOADARGS_##nr(name, args); \
++ __asm__ __volatile__ \
++ ("sc \n\t" \
++ "mfcr %0" \
++ : "=&r" (r0), \
++ "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
++ "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
++ : ASM_INPUT_##nr \
++ : "cr0", "ctr", "memory"); \
++ err = r0; \
++ (int) r3; \
++ })
++# define INTERNAL_SYSCALL(name, err, nr, args...) \
++ INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
++
++# undef INTERNAL_SYSCALL_ERROR_P
++# define INTERNAL_SYSCALL_ERROR_P(val, err) \
++ ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
++
++# undef INTERNAL_SYSCALL_ERRNO
++# define INTERNAL_SYSCALL_ERRNO(val, err) (val)
++
++# define LOADARGS_0(name, dummy) \
++ r0 = (long int)name
++# define LOADARGS_1(name, __arg1) \
++ LOADARGS_0(name, 0); \
++ r3 = (long int)__arg1
++# define LOADARGS_2(name, __arg1, __arg2) \
++ LOADARGS_1(name, __arg1); \
++ r4 = (long int)__arg2
++# define LOADARGS_3(name, __arg1, __arg2, __arg3) \
++ LOADARGS_2(name, __arg1, __arg2); \
++ r5 = (long int)__arg3
++# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
++ LOADARGS_3(name, __arg1, __arg2, __arg3); \
++ r6 = (long int)__arg4
++# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
++ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
++ r7 = (long int)__arg5
++# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
++ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
++ r8 = (long int)__arg6
++
++# define ASM_INPUT_0 "0" (r0)
++# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
++# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
++# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
++# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
++# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
++# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
+
+ #undef _syscall0
+-#define _syscall0(type,name) \
+-type name(void); \
+-unified_syscall_body(name)
++#define _syscall0(type,name) \
++type name(void){ \
++ return (type) INLINE_SYSCALL(name, 0); \
++}
+
+ #undef _syscall1
+ #define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1); \
+-unified_syscall_body(name)
++type name(type1 arg1){ \
++ return (type) INLINE_SYSCALL(name, 1, arg1); \
++}
+
+ #undef _syscall2
+ #define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1, type2 arg2); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2){ \
++ return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \
++}
+
+ #undef _syscall3
+ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1, type2 arg2, type3 arg3); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3){ \
++ return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \
++}
+
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \
++ return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \
++}
+
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \
++ return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \
++}
+
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6); \
+-unified_syscall_body(name)
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \
++ return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \
++}
+
+ #endif /* _BITS_SYSCALLS_H */
+