diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/Makefile uClibc-08082005/ldso/Makefile
--- uClibc-0.9.27/ldso/Makefile	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/Makefile	2005-08-08 13:53:18.000000000 +0300
@@ -19,37 +19,37 @@
 TOPDIR=../
 include $(TOPDIR)Rules.mak
 
-ALL_SUBDIRS = ldso libdl
+DIRS = ldso libdl
 
+all: ldso libdl
 
-all: headers
 ifeq ($(strip $(BUILD_UCLIBC_LDSO)),y)
-	$(MAKE) -C ldso;
+ldso: headers
+	$(MAKE) -C ldso
+libdl: ldso headers
+	$(MAKE) -C libdl
+shared: libdl
+	$(MAKE) -C libdl shared
 else
-	echo "Not building ld-uClibc"
+ldso libdl shared:
+	echo "Skipping $@ target"
 endif
 
-shared:
-ifeq ($(strip $(BUILD_UCLIBC_LDSO)),y)
-	$(MAKE) -C libdl;
-else
-	echo "Not building libdl"
-endif
-
-include/dl-progname.h: Makefile
+HEADERS = $(patsubst %, include/%, elf.h dl-startup.h dl-syscalls.h dl-sysdep.h dl-debug.h)
+headers: $(HEADERS) include/dl-progname.h
+include/dl-progname.h:
 	echo "const char *_dl_progname=\""$(UCLIBC_LDSO)"\";" \
 		> include/dl-progname.h
 	echo "#include \"$(TARGET_ARCH)/elfinterp.c\"" \
 		>> include/dl-progname.h
-
-headers: include/dl-progname.h
+$(HEADERS):
 	$(LN) -fs $(TOPDIR)../include/elf.h include/
 	$(LN) -fs ../ldso/$(TARGET_ARCH)/dl-startup.h include/
 	$(LN) -fs ../ldso/$(TARGET_ARCH)/dl-syscalls.h include/
 	$(LN) -fs ../ldso/$(TARGET_ARCH)/dl-sysdep.h include/
+	$(LN) -fs ../ldso/$(TARGET_ARCH)/dl-debug.h include/
 
 clean:
-	set -e ; for d in $(ALL_SUBDIRS) ; do $(MAKE) -C $$d $@ ; done
+	set -e ; for d in $(DIRS) ; do $(MAKE) -C $$d $@ ; done
 	-find . -name '*~' | xargs $(RM)
-	$(RM) include/elf.h include/dl-startup.h include/dl-syscalls.h \
-		include/dl-sysdep.h include/dl-progname.h
+	$(RM) $(HEADERS) include/dl-progname.h
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/dl-elf.h uClibc-08082005/ldso/include/dl-elf.h
--- uClibc-0.9.27/ldso/include/dl-elf.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/dl-elf.h	2005-08-09 12:14:48.000000000 +0300
@@ -36,6 +36,28 @@
 extern void _dl_protect_relro (struct elf_resolve *l);
 
 /*
+ * Bitsize related settings for things ElfW()
+ * does not handle already
+ */
+#if __WORDSIZE == 64
+# define ELF_ST_BIND(val) ELF64_ST_BIND(val)
+# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
+# define ELF_R_SYM(i)     ELF64_R_SYM(i)
+# define ELF_R_TYPE(i)    ELF64_R_TYPE(i)
+# ifndef ELF_CLASS
+#  define ELF_CLASS ELFCLASS64
+# endif
+#else
+# define ELF_ST_BIND(val) ELF32_ST_BIND(val)
+# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
+# define ELF_R_SYM(i)     ELF32_R_SYM(i)
+# define ELF_R_TYPE(i)    ELF32_R_TYPE(i)
+# ifndef ELF_CLASS
+#  define ELF_CLASS ELFCLASS32
+# endif
+#endif
+
+/*
  * Datatype of a relocation on this platform
  */
 #ifdef ELF_USES_RELOCA
@@ -65,10 +87,10 @@
 
 #define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
 
-extern void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr);
+extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off);
 
-static inline __attribute__((always_inline))
-void __dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr)
+static inline
+void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off)
 {
 	for (; dpnt->d_tag; dpnt++) {
 		if (dpnt->d_tag < DT_NUM) {
@@ -84,6 +106,12 @@
 				dynamic_info[DT_BIND_NOW] = 1;
 			if (dpnt->d_tag == DT_TEXTREL)
 				dynamic_info[DT_TEXTREL] = 1;
+#ifdef __LDSO_RUNPATH__
+			if (dpnt->d_tag == DT_RUNPATH)
+				dynamic_info[DT_RPATH] = 0;
+			if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH])
+				dynamic_info[DT_RPATH] = 0;
+#endif
 		} else if (dpnt->d_tag < DT_LOPROC) {
 			if (dpnt->d_tag == DT_RELOCCOUNT)
 				dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
@@ -97,6 +125,18 @@
 		}
 #endif
 	}
+#define ADJUST_DYN_INFO(tag, load_off) \
+	do { \
+		if (dynamic_info[tag]) \
+			dynamic_info[tag] += load_off; \
+	} while(0)
+	ADJUST_DYN_INFO(DT_HASH, load_off);
+	ADJUST_DYN_INFO(DT_PLTGOT, load_off);
+	ADJUST_DYN_INFO(DT_STRTAB, load_off);
+	ADJUST_DYN_INFO(DT_SYMTAB, load_off);
+	ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
+	ADJUST_DYN_INFO(DT_JMPREL, load_off);
+#undef ADJUST_DYN_INFO
 }
 
 /* Reloc type classes as returned by elf_machine_type_class().
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/dl-hash.h uClibc-08082005/ldso/include/dl-hash.h
--- uClibc-0.9.27/ldso/include/dl-hash.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/dl-hash.h	2005-08-08 13:53:17.000000000 +0300
@@ -32,19 +32,19 @@
   unsigned short usage_count;
   unsigned short int init_flag;
   unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
-  unsigned int nbucket;
-  unsigned long * elf_buckets;
+  Elf32_Word nbucket;
+  Elf32_Word *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
    */
-  unsigned long nchain;
-  unsigned long * chains;
+  Elf32_Word nchain;
+  Elf32_Word *chains;
   unsigned long dynamic_info[DYNAMIC_SIZE];
 
   unsigned long n_phent;
-  Elf32_Phdr * ppnt;
+  ElfW(Phdr) * ppnt;
 
   ElfW(Addr) relro_addr;
   size_t relro_size;
@@ -56,10 +56,11 @@
 #endif
 };
 
-#define RELOCS_DONE         1
-#define JMP_RELOCS_DONE     2
-#define INIT_FUNCS_CALLED   4
-#define FINI_FUNCS_CALLED   8
+#define RELOCS_DONE	    0x000001
+#define JMP_RELOCS_DONE	    0x000002
+#define INIT_FUNCS_CALLED   0x000004
+#define FINI_FUNCS_CALLED   0x000008
+#define DL_OPENED	    0x000010
 
 extern struct dyn_elf     * _dl_symbol_tables;
 extern struct elf_resolve * _dl_loaded_modules;
@@ -77,7 +78,6 @@
 
 extern char * _dl_library_path;
 extern char * _dl_not_lazy;
-extern unsigned long _dl_elf_hash(const unsigned char *name);
 
 static inline int _dl_symbol(char * name)
 {
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/dl-string.h uClibc-08082005/ldso/include/dl-string.h
--- uClibc-0.9.27/ldso/include/dl-string.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/dl-string.h	2005-08-09 12:14:20.000000000 +0300
@@ -2,6 +2,7 @@
 #define _LINUX_STRING_H_
 
 #include <dl-sysdep.h> // for do_rem
+#include <features.h>
 
 static size_t _dl_strlen(const char * str);
 static char *_dl_strcat(char *dst, const char *src);
@@ -30,7 +31,7 @@
 	return (ptr - str);
 }
 
-static inline char *_dl_strcat(char *dst, const char *src)
+static inline char * _dl_strcat(char *dst, const char *src)
 {
 	register char *ptr = dst-1;
 
@@ -46,10 +47,10 @@
 static inline char * _dl_strcpy(char * dst,const char *src)
 {
 	register char *ptr = dst;
-	
+
 	dst--;src--;
 	while ((*++dst = *++src) != 0);
-		
+
 	return ptr;
 }
 
@@ -97,7 +98,7 @@
 	return 0;
 }
 
-static inline char *_dl_strrchr(const char *str, int c)
+static inline char * _dl_strrchr(const char *str, int c)
 {
     register char *prev = 0;
     register char *ptr = (char *) str-1;
@@ -111,7 +112,7 @@
     return(prev);
 }
 
-static inline char *_dl_strstr(const char *s1, const char *s2)
+static inline char * _dl_strstr(const char *s1, const char *s2)
 {
     register const char *s = s1;
     register const char *p = s2;
@@ -160,7 +161,7 @@
 
 #if defined(powerpc)
 /* Will generate smaller and faster code due to loop unrolling.*/
-static inline void *_dl_memset(void *to, int c, size_t n)
+static inline void * _dl_memset(void *to, int c, size_t n)
 {
         unsigned long chunks;
         unsigned long *tmp_to;
@@ -196,7 +197,7 @@
 }
 #endif
 
-static inline char *_dl_get_last_path_component(char *path)
+static inline char * _dl_get_last_path_component(char *path)
 {
 	register char *ptr = path-1;
 
@@ -217,9 +218,10 @@
 /* Early on, we can't call printf, so use this to print out
  * numbers using the SEND_STDERR() macro.  Avoid using mod
  * or using long division */
-static inline char *_dl_simple_ltoa(char * local, unsigned long i)
+static inline char * _dl_simple_ltoa(char * local, unsigned long i)
 {
-	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
+	/* 20 digits plus a null terminator should be good for
+	 * 64-bit or smaller ints (2^64 - 1)*/
 	char *p = &local[22];
 	*--p = '\0';
 	do {
@@ -231,9 +233,10 @@
 	return p;
 }
 
-static inline char *_dl_simple_ltoahex(char * local, unsigned long i)
+static inline char * _dl_simple_ltoahex(char * local, unsigned long i)
 {
-	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
+	/* 16 digits plus a leading "0x" plus a null terminator,
+	 * should be good for 64-bit or smaller ints */
 	char *p = &local[22];
 	*--p = '\0';
 	do {
@@ -250,47 +253,84 @@
 }
 
 
-#if defined(mc68000) || defined(__arm__) || defined(__mips__) || defined(__sh__) ||  defined(__powerpc__)
-/* On some arches constant strings are referenced through the GOT. */
-/* XXX Requires load_addr to be defined. */
-#define SEND_STDERR(X)				\
-  { const char *__s = (X);			\
-    if (__s < (const char *) load_addr) __s += load_addr;	\
-    _dl_write (2, __s, _dl_strlen (__s));	\
-  }
+
+
+/* The following macros may be used in dl-startup.c to debug
+ * ldso before ldso has fixed itself up to make function calls */
+
+/* On some (wierd) arches, none of this stuff works at all, so
+ * disable the whole lot... */
+#if defined(__mips__)
+
+# define SEND_STDERR(X)
+# define SEND_ADDRESS_STDERR(X, add_a_newline)
+# define SEND_NUMBER_STDERR(X, add_a_newline)
+
 #else
-#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X));
-#endif
 
-/* Some targets may have to override this to something that doesn't
-   reference constant strings through the GOT.  This macro should be
-   preferred over SEND_STDERR for constant strings before we complete
-   bootstrap.  */
-#ifndef SEND_EARLY_STDERR
-# define SEND_EARLY_STDERR(S) SEND_STDERR(S)
+/* 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__)
+# define CONSTANT_STRING_GOT_FIXUP(X) \
+	if ((X) < (const char *) load_addr) (X) += load_addr
+#else
+# define CONSTANT_STRING_GOT_FIXUP(X)
 #endif
 
-#define SEND_ADDRESS_STDERR(X, add_a_newline) { \
-    char tmp[22], *tmp1; \
-    _dl_memset(tmp, 0, sizeof(tmp)); \
-    tmp1=_dl_simple_ltoahex( tmp, (unsigned long)(X)); \
-    _dl_write(2, tmp1, _dl_strlen(tmp1)); \
-    if (add_a_newline) { \
-	tmp[0]='\n'; \
-	_dl_write(2, tmp, 1); \
-    } \
-};
-
-#define SEND_NUMBER_STDERR(X, add_a_newline) { \
-    char tmp[22], *tmp1; \
-    _dl_memset(tmp, 0, sizeof(tmp)); \
-    tmp1=_dl_simple_ltoa( tmp, (unsigned long)(X)); \
-    _dl_write(2, tmp1, _dl_strlen(tmp1)); \
-    if (add_a_newline) { \
-	tmp[0]='\n'; \
-	_dl_write(2, tmp, 1); \
-    } \
-};
+#define SEND_STDERR(X) \
+{ \
+	const char *tmp1 = (X); \
+	CONSTANT_STRING_GOT_FIXUP(tmp1); \
+	_dl_write(2, tmp1, _dl_strlen(tmp1)); \
+}
+
+#define SEND_ADDRESS_STDERR(ADR, add_a_newline) \
+{ \
+	char tmp[26], v, *tmp2, *tmp1 = tmp; \
+	unsigned long X = (unsigned long)(ADR); \
+	CONSTANT_STRING_GOT_FIXUP(tmp1); \
+	tmp2 = tmp1 + sizeof(tmp); \
+	*--tmp2 = '\0'; \
+	if (add_a_newline) *--tmp2 = '\n'; \
+	do { \
+		v = (X) & 0xf; \
+		if (v <= 0x09) \
+			*--tmp2 = '0' + v; \
+		else \
+			*--tmp2 = 'a' - 0x0a + v; \
+		(X) >>= 4; \
+	} while ((X) > 0); \
+	*--tmp2 = 'x'; \
+	*--tmp2 = '0'; \
+	_dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
+}
+
+#define SEND_NUMBER_STDERR(NUM, add_a_newline) \
+{ \
+	char tmp[26], v, *tmp2, *tmp1 = tmp; \
+	unsigned long X = (unsigned long)(NUM); \
+	CONSTANT_STRING_GOT_FIXUP(tmp1); \
+	tmp2 = tmp1 + sizeof(tmp); \
+	*--tmp2 = '\0'; \
+	if (add_a_newline) *--tmp2 = '\n'; \
+	do { \
+		do_rem(v, (X), 10); \
+		*--tmp2 = '0' + v; \
+		(X) /= 10; \
+	} while ((X) > 0); \
+	_dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \
+}
+#endif
 
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+# define SEND_STDERR_DEBUG(X) SEND_STDERR(X)
+# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) SEND_NUMBER_STDERR(X, add_a_newline)
+# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) SEND_ADDRESS_STDERR(X, add_a_newline)
+#else
+# define SEND_STDERR_DEBUG(X)
+# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline)
+# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline)
+#endif
 
 #endif
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/dl-syscall.h uClibc-08082005/ldso/include/dl-syscall.h
--- uClibc-0.9.27/ldso/include/dl-syscall.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/dl-syscall.h	2005-08-08 13:53:17.000000000 +0300
@@ -47,8 +47,8 @@
 #ifndef _dl_MAX_ERRNO
 #define _dl_MAX_ERRNO 4096
 #endif
-#define _dl_mmap_check_error(__res)     \
-        (((int)__res) < 0 && ((int)__res) >= -_dl_MAX_ERRNO)
+#define _dl_mmap_check_error(__res) \
+	(((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO)
 #endif
 
 
@@ -104,7 +104,7 @@
 static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
 
 #ifdef __NR_mmap
-#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) || defined(__sparc__)
+#if defined(__powerpc__) || defined(__mips__) || defined(__sh__) || defined(__sparc__) || defined(__x86_64__)
 /* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */
 #define __NR__dl_mmap __NR_mmap
 static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/dlfcn.h uClibc-08082005/ldso/include/dlfcn.h
--- uClibc-0.9.27/ldso/include/dlfcn.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/dlfcn.h	2005-08-08 13:53:17.000000000 +0300
@@ -12,11 +12,10 @@
    `dladdr'.  */
 typedef struct
 {
-	__const char *dli_fname;	/* File name of defining object.  */
-	void *dli_fbase;		/* Load address of that object.  */
-	__const char *dli_sname;	/* Name of nearest symbol.  */
-	void *dli_saddr;		/* Exact value of nearest symbol.  */
+	__const char *dli_fname;  /* File name of defining object.  */
+	void *dli_fbase;          /* Load address of that object.  */
+	__const char *dli_sname;  /* Name of nearest symbol.  */
+	void *dli_saddr;          /* Exact value of nearest symbol.  */
 } Dl_info;
 
-
-#endif	/* dlfcn.h */
+#endif	/* _DLFCN_H */
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/ldso.h uClibc-08082005/ldso/include/ldso.h
--- uClibc-0.9.27/ldso/include/ldso.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/ldso.h	2005-08-08 13:53:17.000000000 +0300
@@ -42,8 +42,6 @@
 extern char *_dl_preload;              /* Things to be loaded before the libs */
 extern char *_dl_ldsopath;             /* Where the shared lib loader was found */
 extern const char *_dl_progname;       /* The name of the executable being run */
-extern unsigned char *_dl_malloc_addr; /* Lets _dl_malloc use the already allocated memory page */
-extern unsigned char *_dl_mmap_zero;   /* Also used by _dl_malloc */
 extern int _dl_secure;                 /* Are we dealing with setuid stuff? */
 extern size_t _dl_pagesize;            /* Store the page size for use later */
 extern const char *_dl_progname;       /* The name of the shared library loader */
@@ -57,9 +55,21 @@
 extern char *_dl_debug_nofixups;
 extern char *_dl_debug_bindings;
 extern int   _dl_debug_file;
+# define __dl_debug_dprint(fmt, args...) \
+	_dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __FUNCTION__, __LINE__, ## args);
+# define _dl_if_debug_dprint(fmt, args...) \
+	do { if (_dl_debug) __dl_debug_dprint(fmt, ## args); } while (0)
 #else
-#define _dl_debug_file 2
-#endif
+# define _dl_debug_dprint(fmt, args...)
+# define _dl_if_debug_dprint(fmt, args...)
+# define _dl_debug_file 2
+#endif /* __SUPPORT_LD_DEBUG__ */
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+# define _dl_debug_early(fmt, args...) __dl_debug_dprint(fmt, ## args)
+#else
+# define _dl_debug_early(fmt, args...)
+#endif /* __SUPPORT_LD_DEBUG_EARLY__ */
 
 #ifndef NULL
 #define NULL ((void *) 0)
@@ -72,8 +82,6 @@
 extern void _dl_dprintf(int, const char *, ...);
 
 extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
-		Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, char **argv);
-
+		ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv);
 
 #endif /* _LDSO_H_ */
-
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/include/unsecvars.h uClibc-08082005/ldso/include/unsecvars.h
--- uClibc-0.9.27/ldso/include/unsecvars.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/include/unsecvars.h	2005-08-08 13:53:17.000000000 +0300
@@ -4,17 +4,17 @@
  * '\0' explicitly.
  */
 
-#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"			\
+#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"
 
 /* 
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/Makefile uClibc-08082005/ldso/ldso/Makefile
--- uClibc-0.9.27/ldso/ldso/Makefile	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/Makefile	2005-08-08 13:53:17.000000000 +0300
@@ -24,15 +24,19 @@
 # reset to initial (disabling predefined CFLAGS)
 ASFLAGS=
 ifeq ($(UCLIBC_BUILD_NOEXECSTACK),y)
-ASFLAGS+=$(check_as_noexecstack)
+ASFLAGS+=$(call check_as,--noexecstack)
 endif
 
 XXFLAGS=$(XWARNINGS) $(SSP_DISABLE_FLAGS)
+ifeq ($(DL_FINI_CRT_COMPAT),y)
+XXFLAGS+=-D_DL_FINI_CRT_COMPAT
+endif
+
 ifeq ($(DODEBUG),y)
 # Not really much point in including debugging info, since gdb
 # can't really debug ldso, since gdb requires help from ldso to
 # debug things....
-XXFLAGS+=-Os #-g3
+XXFLAGS+=-Os -g
 else
 XXFLAGS+=$(OPTIMIZATION)
 endif
@@ -43,7 +47,7 @@
 # BEWARE!!! At least mips* will die if -O0 is used!!!
 XXFLAGS:=$(XXFLAGS:-O0=-O1)
 XXFLAGS+=-isystem $(shell $(CC) -print-file-name=include)
-LDFLAGS=$(CPU_LDFLAGS-y) -z now -Bsymbolic -shared --warn-common --export-dynamic --sort-common \
+LDFLAGS=$(CPU_LDFLAGS-y) -e _start -z now -Bsymbolic -shared --warn-common --export-dynamic --sort-common \
 	-z combreloc --discard-locals --discard-all --no-undefined
 ifeq ($(UCLIBC_BUILD_RELRO),y)
 	LDFLAGS+=-z relro
@@ -70,24 +74,25 @@
 #This stuff will not work with -fomit-frame-pointer
 XXFLAGS := $(XXFLAGS:-fomit-frame-pointer=)
 
-all: lib
+all: $(LDSO_FULLNAME)
 
-lib:: $(OBJS) $(DLINK_OBJS)
-	$(LD) $(LDFLAGS) -e _dl_boot -soname=$(UCLIBC_LDSO) \
-		-o $(LDSO_FULLNAME) $(OBJS) $(LIBGCC);
+$(LDSO_FULLNAME): $(OBJS) $(DLINK_OBJS)
+	$(LD) $(LDFLAGS) -soname=$(UCLIBC_LDSO) \
+		-o $(LDSO_FULLNAME) $(OBJS) $(LIBGCC)
 	$(INSTALL) -d $(TOPDIR)lib
 	$(INSTALL) -m 755 $(LDSO_FULLNAME) $(TOPDIR)lib
 	$(LN) -sf $(LDSO_FULLNAME) $(TOPDIR)lib/$(UCLIBC_LDSO)
 
 $(COBJS): %.o : %.c
-	$(CC) $(XXFLAGS) -I../libdl -c $< -o $@
+	$(CC) $(XXFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(AOBJS): %.o : %.S
-	$(CC) $(XXFLAGS) $(ASFLAGS) -I../libdl -c $< -o $@
+	$(CC) $(XXFLAGS) $(ASFLAGS) -c $< -o $@
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-ldso.o: $(CSRC)
+ldso.o: $(CSRC) dl-elf.c dl-hash.c dl-startup.c dl-debug.c \
+	$(TARGET_ARCH)/*.h $(TARGET_ARCH)/*.c $(TOPDIR)ldso/include/*.h
 
 clean:
 	$(RM) $(UCLIBC_LDSO)* $(OBJS) $(LDSO_FULLNAME)* core *.o *.a *.s *.i ldso.h *~
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/cris/dl-debug.h uClibc-08082005/ldso/ldso/cris/dl-debug.h
--- uClibc-0.9.27/ldso/ldso/cris/dl-debug.h	1970-01-01 02:00:00.000000000 +0200
+++ uClibc-08082005/ldso/ldso/cris/dl-debug.h	2005-08-08 13:53:17.000000000 +0300
@@ -0,0 +1,42 @@
+/*
+ * CRIS ELF shared library loader support.
+ *
+ * Program to load an elf binary on a linux system, and run it.
+ * References to symbols in sharable libraries can be resolved
+ * by either an ELF sharable library or a linux style of shared
+ * library.
+ *
+ * Copyright (C) 2002-2004, Axis Communications AB
+ * All rights reserved
+ *
+ * Author: Tobias Anderberg, <tobiasa@axis.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+static const char *_dl_reltypes_tab[] = {
+	[0]  "R_CRIS_NONE", "R_CRIS_8", "R_CRIS_16", "R_CRIS_32",
+	[4]  "R_CRIS_8_PCREL", "R_CRIS_16_PCREL", "R_CRIS_32_PCREL", "R_CRIS_GNU_VTINHERIT",
+	[8]  "R_CRIS_GNU_VTENTRY", "R_CRIS_COPY", "R_CRIS_GLOB_DAT", "R_CRIS_JUMP_SLOT",
+	[16] "R_CRIS_RELATIVE", "R_CRIS_16_GOT", "R_CRIS_32_GOT", "R_CRIS_16_GOTPLT",
+	[32] "R_CRIS_32_GOTPLT", "R_CRIS_32_GOTREL", "R_CRIS_32_PLT_GOTREL", "R_CRIS_32_PLT_PCREL",
+};
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/cris/dl-startup.h uClibc-08082005/ldso/ldso/cris/dl-startup.h
--- uClibc-0.9.27/ldso/ldso/cris/dl-startup.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/cris/dl-startup.h	2005-08-08 13:53:17.000000000 +0300
@@ -6,22 +6,30 @@
  * can find argc, argv and auxvt (Auxillary Vector Table).  */
 asm(""					\
 "	.text\n"			\
-"	.globl _dl_boot\n"		\
-"	.type _dl_boot,@function\n"	\
-"_dl_boot:\n"				\
+"	.globl _start\n"		\
+"	.type _start,@function\n"	\
+"_start:\n"				\
 "	move.d $sp,$r10\n"		\
 "	move.d $pc,$r9\n"		\
-"	add.d _dl_boot2 - ., $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"			\
 );
 
-#define DL_BOOT(X) static void __attribute_used__ _dl_boot2 (X)
-
 
 /* Get a pointer to the argv array.  On many platforms this can be just
  * the address if the first argument, on other platforms we need to
  * do something a little more subtle here.  */
-#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1)
+
+
+/* We can't call functions earlier in the dl startup process */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
 
 /* Handle relocation of the symbols in the dynamic loader. */
 static inline
@@ -54,10 +62,4 @@
 /* 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 ("moveq 0,$r8\n\t" \
-				  "move $r8,$srp\n\t" \
-				  "move.d %1,$sp\n\t" \
-				  "jump %0\n\t" \
-				  : : "r" (_dl_elf_main), "r" (args))
-
-
+#define START()     return _dl_elf_main
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/cris/dl-sysdep.h uClibc-08082005/ldso/ldso/cris/dl-sysdep.h
--- uClibc-0.9.27/ldso/ldso/cris/dl-sysdep.h	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/cris/dl-sysdep.h	2005-08-08 13:53:17.000000000 +0300
@@ -1,6 +1,8 @@
 /* CRIS can never use Elf32_Rel relocations. */
 #define ELF_USES_RELOCA
 
+#include <elf.h>
+
 /* Initialization sequence for the GOT.  */
 #define INIT_GOT(GOT_BASE,MODULE)				\
 {								\
@@ -16,44 +18,7 @@
 struct elf_resolve;
 extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry);
 
-/* Cheap modulo implementation, taken from arm/dl-sysdep.h. */
-static inline unsigned long
-cris_mod(unsigned long m, unsigned long p)
-{
-	unsigned long i, t, inc;
-
-	i = p;
-	t = 0;
-
-	while (!(i & (1 << 31))) {
-		i <<= 1;
-		t++;
-	}
-
-	t--;
-
-	for (inc = t; inc > 2; inc--) {
-		i = p << inc;
-
-		if (i & (1 << 31))
-			break;
-
-		while (m >= i) {
-			m -= i;
-			i <<= 1;
-			if (i & (1 << 31))
-				break;
-			if (i < p)
-				break;
-		}
-	}
-
-	while (m >= p)
-		m -= p;
-
-	return m;
-}
-#define do_rem(result, n, base) ((result) = cris_mod(n, base))
+#define do_rem(result, n, base) ((result) = (n) % (base))
 
 /* 8192 bytes alignment */
 #define PAGE_ALIGN 0xffffe000
@@ -75,3 +40,50 @@
   ((((((type) == R_CRIS_JUMP_SLOT))				\
      || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT)	\
    | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
+
+static inline Elf32_Addr
+elf_machine_dynamic(void)
+{
+	/* Don't just set this to an asm variable "r0" since that's not logical
+	   (like, the variable is uninitialized and the register is fixed) and
+	   may make GCC trip over itself doing register allocation.  Yes, I'm
+	   paranoid.  Why do you ask?  */
+	Elf32_Addr *got;
+
+	__asm__ ("move.d $r0,%0" : "=rm" (got));
+	return *got;
+}
+
+/* Return the run-time load address of the shared object.  We do it like
+   m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry
+   for it, and peeking into the GOT table, which is set to the link-time
+   file-relative symbol value (regardless of whether the target is REL or
+   RELA).  We subtract this link-time file-relative value from the "local"
+   value we calculate from GOT position and GOT offset.  FIXME: Perhaps
+   there's some other symbol we could use, that we don't *have* to force a
+   GOT entry for.  */
+
+static inline Elf32_Addr
+elf_machine_load_address(void)
+{
+	Elf32_Addr gotaddr_diff;
+
+	__asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t"
+	         "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff));
+	return gotaddr_diff;
+}
+
+static inline void
+elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
+                     Elf32_Word relative_count)
+{
+	Elf32_Rela *rpnt = (void *)rel_addr;
+
+	--rpnt;
+	do {
+		Elf32_Addr *const reloc_addr =
+			(void *)(load_off + (++rpnt)->r_offset);
+
+		*reloc_addr =  load_off + rpnt->r_addend;
+	} while (--relative_count);
+}
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/cris/elfinterp.c uClibc-08082005/ldso/ldso/cris/elfinterp.c
--- uClibc-0.9.27/ldso/ldso/cris/elfinterp.c	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/cris/elfinterp.c	2005-08-08 13:53:17.000000000 +0300
@@ -35,76 +35,6 @@
 
 #include "ldso.h"
 
-/* Support for the LD_DEBUG variable. */
-#if defined (__SUPPORT_LD_DEBUG__)
-static const char *_dl_reltypes_tab[] = {
-	[0]  "R_CRIS_NONE", "R_CRIS_8", "R_CRIS_16", "R_CRIS_32",
-	[4]  "R_CRIS_8_PCREL", "R_CRIS_16_PCREL", "R_CRIS_32_PCREL", "R_CRIS_GNU_VTINHERIT",
-	[8]  "R_CRIS_GNU_VTENTRY", "R_CRIS_COPY", "R_CRIS_GLOB_DAT", "R_CRIS_JUMP_SLOT",
-	[16] "R_CRIS_RELATIVE", "R_CRIS_16_GOT", "R_CRIS_32_GOT", "R_CRIS_16_GOTPLT",
-	[32] "R_CRIS_32_GOTPLT", "R_CRIS_32_GOTREL", "R_CRIS_32_PLT_GOTREL", "R_CRIS_32_PLT_PCREL",
-};
-
-static const char *
-_dl_reltypes(int type)
-{
-	static char buf[22];
-	const char *str;
-
-	if (type >= (sizeof(_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
-	    NULL == (str = _dl_reltypes_tab[type])) {
-		str = _dl_simple_ltoa(buf, (unsigned long)type);
-	}
-
-	return str;
-}
-
-static void
-debug_sym(Elf32_Sym *symtab, char *strtab, int symtab_index)
-{
-	if (_dl_debug_symbols) {
-		if (symtab_index) {
-			_dl_dprintf(_dl_debug_file,
-				    "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
-				    strtab + symtab[symtab_index].st_name,
-				    symtab[symtab_index].st_value,
-				    symtab[symtab_index].st_size,
-				    symtab[symtab_index].st_info,
-				    symtab[symtab_index].st_other,
-				    symtab[symtab_index].st_shndx);
-		}
-	}
-}
-
-static void
-debug_reloc(Elf32_Sym *symtab, char *strtab, ELF_RELOC *rpnt)
-{
-	if (_dl_debug_reloc) {
-		int symtab_index;
-		const char *sym;
-
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-		sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
-
-		if (_dl_debug_symbols)
-			_dl_dprintf(_dl_debug_file, "\n\t");
-		else
-			_dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
-
-#ifdef ELF_USES_RELOCA
-		_dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
-			    _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
-			    rpnt->r_offset,
-			    rpnt->r_addend);
-#else
-		_dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
-			    _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
-			    rpnt->r_offset);
-#endif
-	}
-}
-#endif /* __SUPPORT_LD_DEBUG__ */
-
 /* Defined in resolve.S. */
 extern int _dl_linux_resolve(void);
 
@@ -122,14 +52,14 @@
 	ELF_RELOC *this_reloc;
 	unsigned long instr_addr;
 
-	rel_addr = (char *)(tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
+	rel_addr = (char *)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);
 
-	symtab = (Elf32_Sym *)(intptr_t)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
 	symname = strtab + symtab[symtab_index].st_name;
 
 	if (unlikely(reloc_type != R_CRIS_JUMP_SLOT)) {
@@ -181,21 +111,19 @@
 	ELF_RELOC *rpnt;
 
 	/* Parse the relocation information. */
-	rpnt = (ELF_RELOC *)(intptr_t)(rel_addr + tpnt->loadaddr);
+	rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
 	rel_size /= sizeof(ELF_RELOC);
 
-	symtab = (Elf32_Sym *)(intptr_t)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
 
 	for (i = 0; i < rel_size; i++, rpnt++) {
 		int res;
 
 		symtab_index = ELF32_R_SYM(rpnt->r_info);
 
-#if defined (__SUPPORT_LD_DEBUG__)
 		debug_sym(symtab, strtab, symtab_index);
 		debug_reloc(symtab, strtab, rpnt);
-#endif
 
 		/* Pass over to actual relocation function. */
 		res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/dl-debug.c uClibc-08082005/ldso/ldso/dl-debug.c
--- uClibc-0.9.27/ldso/ldso/dl-debug.c	1970-01-01 02:00:00.000000000 +0200
+++ uClibc-08082005/ldso/ldso/dl-debug.c	2005-08-08 13:53:17.000000000 +0300
@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/* common debug code for ELF shared library loader
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ *                         David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2004 Erik Andersen
+ * Copyright (C) 2002-2004, Axis Communications AB
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
+ * Copyright (C) 2001-2002 David A. Schleef
+ * Copyright (C) 2004 Joakim Tjernlund
+ * Copyright (C) 2002, Stefan Allius <allius@atecom.com> and
+ *                     Eddie C. Dost <ecd@atecom.com>
+ * Copyright (C) 2003, 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ldso.h"
+
+#if defined (__SUPPORT_LD_DEBUG__)
+
+/* include the arch-specific _dl_reltypes_tab */
+#include "dl-debug.h"
+
+static const char *_dl_reltypes(int type)
+{
+	static char buf[50];
+	const char *str;
+	int tabsize;
+
+	tabsize = (int)(sizeof(_dl_reltypes_tab) / sizeof(_dl_reltypes_tab[0]));
+
+	if (type >= tabsize || (str = _dl_reltypes_tab[type]) == NULL)
+		str = _dl_simple_ltoa(buf, (unsigned long)type);
+
+	return str;
+}
+static void debug_sym(ElfW(Sym) *symtab, char *strtab, int symtab_index)
+{
+	if (!_dl_debug_symbols || !symtab_index)
+		return;
+
+	_dl_dprintf(_dl_debug_file,
+		"\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
+		strtab + symtab[symtab_index].st_name,
+		symtab[symtab_index].st_value,
+		symtab[symtab_index].st_size,
+		symtab[symtab_index].st_info,
+		symtab[symtab_index].st_other,
+		symtab[symtab_index].st_shndx);
+}
+
+static void debug_reloc(ElfW(Sym) *symtab, char *strtab, ELF_RELOC *rpnt)
+{
+	if (!_dl_debug_reloc)
+		return;
+
+	if (_dl_debug_symbols) {
+		_dl_dprintf(_dl_debug_file, "\n\t");
+	} else {
+		int symtab_index;
+		const char *sym;
+
+		symtab_index = ELF_R_SYM(rpnt->r_info);
+		sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
+
+		_dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
+	}
+
+	_dl_dprintf(_dl_debug_file, "%s\toffset=%x",
+		_dl_reltypes(ELF_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset);
+#ifdef ELF_USES_RELOCA
+	_dl_dprintf(_dl_debug_file, "\taddend=%x", rpnt->r_addend);
+#endif
+	_dl_dprintf(_dl_debug_file, "\n");
+}
+
+#else
+
+#define debug_sym(symtab, strtab, symtab_index)
+#define debug_reloc(symtab, strtab, rpnt)
+
+#endif /* __SUPPORT_LD_DEBUG__ */
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/dl-elf.c uClibc-08082005/ldso/ldso/dl-elf.c
--- uClibc-0.9.27/ldso/ldso/dl-elf.c	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/dl-elf.c	2005-08-08 13:53:17.000000000 +0300
@@ -122,10 +122,7 @@
 			    & ~(_dl_pagesize - 1));
 	ElfW(Addr) end = ((l->loadaddr + l->relro_addr + l->relro_size)
 			  & ~(_dl_pagesize - 1));
-#if defined (__SUPPORT_LD_DEBUG__)
-	if (_dl_debug)
-		_dl_dprintf(2, "RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);
-#endif
+	_dl_if_debug_dprint("RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);
 	if (start != end &&
 	    _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
 		_dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname);
@@ -139,10 +136,10 @@
 search_for_named_library(const char *name, int secure, const char *path_list,
 	struct dyn_elf **rpnt)
 {
-	int i, count = 1;
 	char *path, *path_n;
 	char mylibname[2050];
-	struct elf_resolve *tpnt1;
+	struct elf_resolve *tpnt;
+	int done = 0;
 
 	if (path_list==NULL)
 		return NULL;
@@ -154,29 +151,32 @@
 		_dl_exit(0);
 	}
 
-
 	/* Unlike ldd.c, don't bother to eliminate double //s */
 
-
-	/* Replace colons with zeros in path_list and count them */
-	for(i=_dl_strlen(path); i > 0; i--) {
-		if (path[i]==':') {
-			path[i]=0;
-			count++;
-		}
-	}
-
+	/* Replace colons with zeros in path_list */
+	/* : at the beginning or end of path maps to CWD */
+	/* :: anywhere maps CWD */
+	/* "" maps to CWD */ 
 	path_n = path;
-	for (i = 0; i < count; i++) {
-		_dl_strcpy(mylibname, path_n);
-		_dl_strcat(mylibname, "/");
-		_dl_strcat(mylibname, name);
-		if ((tpnt1 = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL)
-		{
-			return tpnt1;
+	do {
+		if (*path == 0) {
+			*path = ':';
+			done = 1;
+		}
+		if (*path == ':') {
+			*path = 0;
+			if (*path_n)
+				_dl_strcpy(mylibname, path_n);
+			else
+				_dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
+			_dl_strcat(mylibname, "/");
+			_dl_strcat(mylibname, name);
+			if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL)
+				return tpnt;
+			path_n = path+1;
 		}
-		path_n += (_dl_strlen(path_n) + 1);
-	}
+		path++;
+	} while (!done);
 	return NULL;
 }
 
@@ -192,10 +192,7 @@
 
 	pnt = libname = full_libname;
 
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug)
-		_dl_dprintf(_dl_debug_file, "Checking if '%s' is already loaded\n", full_libname);
-#endif
+	_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)
@@ -255,7 +252,7 @@
 struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 	struct elf_resolve *tpnt, char *full_libname, int __attribute__((unused)) trace_loaded_objects)
 {
-	char *pnt, *pnt1;
+	char *pnt;
 	struct elf_resolve *tpnt1;
 	char *libname;
 
@@ -269,29 +266,26 @@
 
 	/* Skip over any initial initial './' and '/' stuff to
 	 * get the short form libname with no path garbage */
-	pnt1 = _dl_strrchr(libname, '/');
-	if (pnt1) {
-		libname = pnt1 + 1;
+	pnt = _dl_strrchr(libname, '/');
+	if (pnt) {
+		libname = pnt + 1;
 	}
-#if 0
+
 	/* 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)
+	if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) {
+		tpnt1->usage_count++;
 		return tpnt1;
-#endif
+	}
 
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfind library='%s'; searching\n", libname);
-#endif
+	_dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
 	/* If the filename has any '/', try it straight and leave it at that.
 	   For IBCS2 compatibility under linux, we substitute the string
 	   /usr/i486-sysv4/lib for /usr/lib in library names. */
 
 	if (libname != full_libname) {
-#if defined (__SUPPORT_LD_DEBUG__)
-		if(_dl_debug) _dl_dprintf(_dl_debug_file, "\ttrying file='%s'\n", full_libname);
-#endif
+		_dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
 		tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname);
 		if (tpnt1) {
 			return tpnt1;
@@ -300,30 +294,22 @@
 	}
 
 	/*
-	 * The ABI specifies that RPATH is searched before LD_*_PATH or
+	 * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
 	 * the default path of /usr/lib.  Check in rpath directories.
 	 */
-	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
-		if (tpnt->libtype == elf_executable) {
-			pnt = (char *) tpnt->dynamic_info[DT_RPATH];
-			if (pnt) {
-				pnt += (unsigned long) tpnt->loadaddr + tpnt->dynamic_info[DT_STRTAB];
-#if defined (__SUPPORT_LD_DEBUG__)
-				if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching RPATH='%s'\n", pnt);
-#endif
-				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
-				{
-					return tpnt1;
-				}
-			}
-		}
+#ifdef __LDSO_RUNPATH__
+	pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
+	if (pnt) {
+		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+		_dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
+		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
+			return tpnt1;
 	}
+#endif
 
 	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
 	if (_dl_library_path) {
-#if defined (__SUPPORT_LD_DEBUG__)
-		if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
-#endif
+		_dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
 		if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
 		{
 			return tpnt1;
@@ -331,6 +317,19 @@
 	}
 
 	/*
+	 * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
+	 */
+#ifdef __LDSO_RUNPATH__
+	pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
+	if (pnt) {
+		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+		_dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
+		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
+			return tpnt1;
+	}
+#endif
+
+	/*
 	 * Where should the cache be searched?  There is no such concept in the
 	 * ABI, so we have some flexibility here.  For now, search it before
 	 * the hard coded paths that follow (i.e before /lib and /usr/lib).
@@ -342,9 +341,7 @@
 		libentry_t *libent = (libentry_t *) & header[1];
 		char *strs = (char *) &libent[header->nlibs];
 
-#if defined (__SUPPORT_LD_DEBUG__)
-		if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching cache='%s'\n", LDSO_CACHE);
-#endif
+		_dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
 		for (i = 0; i < header->nlibs; i++) {
 			if ((libent[i].flags == LIB_ELF ||
 						libent[i].flags == LIB_ELF_LIBC0 ||
@@ -359,9 +356,7 @@
 
 	/* Look for libraries wherever the shared library loader
 	 * was installed */
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching ldso dir='%s'\n", _dl_ldsopath);
-#endif
+	_dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
 	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL)
 	{
 		return tpnt1;
@@ -370,9 +365,7 @@
 
 	/* Lastly, search the standard list of paths for the library.
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tsearching full lib path list\n");
-#endif
+	_dl_if_debug_dprint("\tsearching full lib path list\n");
 	if ((tpnt1 = search_for_named_library(libname, secure,
 					UCLIBC_RUNTIME_PREFIX "lib:"
 					UCLIBC_RUNTIME_PREFIX "usr/lib"
@@ -391,9 +384,7 @@
 		_dl_error_number = _dl_internal_error_number;
 	else
 		_dl_error_number = LD_ERROR_NOFILE;
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug) _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
-#endif
+	_dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
 	return NULL;
 }
 
@@ -409,7 +400,7 @@
 {
 	ElfW(Ehdr) *epnt;
 	unsigned long dynamic_addr = 0;
-	Elf32_Dyn *dpnt;
+	ElfW(Dyn) *dpnt;
 	struct elf_resolve *tpnt;
 	ElfW(Phdr) *ppnt;
 	char *status, *header;
@@ -434,9 +425,7 @@
 		}
 		tpnt->usage_count++;
 		tpnt->libtype = elf_lib;
-#if defined (__SUPPORT_LD_DEBUG__)
-		if(_dl_debug) _dl_dprintf(2, "file='%s';  already loaded\n", libname);
-#endif
+		_dl_if_debug_dprint("file='%s';  already loaded\n", libname);
 		return tpnt;
 	}
 
@@ -649,9 +638,9 @@
 		return NULL;
 	}
 
-	dpnt = (Elf32_Dyn *) dynamic_addr;
+	dpnt = (ElfW(Dyn) *) dynamic_addr;
 	_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
-	_dl_parse_dynamic_info(dpnt, dynamic_info, NULL);
+	_dl_parse_dynamic_info(dpnt, dynamic_info, NULL, libaddr);
 	/* If the TEXTREL is set, this means that we need to make the pages
 	   writable before we perform relocations.  Do this now. They get set
 	   back again later. */
@@ -702,48 +691,38 @@
 	lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
 
 	if (lpnt) {
-		lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
-				((int) libaddr));
+		lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
 		INIT_GOT(lpnt, tpnt);
 	};
 
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug) {
-		_dl_dprintf(2, "\n\tfile='%s';  generating link map\n", libname);
-		_dl_dprintf(2, "\t\tdynamic: %x  base: %x\n",
-				dynamic_addr, libaddr);
-		_dl_dprintf(2, "\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
-				epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
+	_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);
+	_dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
+			epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
 
-	}
-#endif
 	_dl_munmap(header, _dl_pagesize);
 
 	return tpnt;
 }
+
 /* now_flag must be RTLD_NOW or zero */
 int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
 {
 	int goof = 0;
 	struct elf_resolve *tpnt;
-	unsigned long reloc_size;
+	ElfW(Word) reloc_size, relative_count;
+	ElfW(Addr) reloc_addr;
 
 	if (rpnt->next)
 		goof += _dl_fixup(rpnt->next, now_flag);
 	tpnt = rpnt->dyn;
 
-#if defined (__SUPPORT_LD_DEBUG__)
-	if(_dl_debug && !(tpnt->init_flag & RELOCS_DONE)) 
-		_dl_dprintf(_dl_debug_file,"\nrelocation processing: %s\n", tpnt->libname);
-#endif
+	if(!(tpnt->init_flag & RELOCS_DONE)) 
+		_dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
 
 	if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
-#if defined (__SUPPORT_LD_DEBUG__)
-		if(_dl_debug) {
-			_dl_dprintf(2, "%s: can't handle %s relocation records\n",
-					_dl_progname, UNSUPPORTED_RELOC_STR);
-		}
-#endif
+		_dl_if_debug_dprint("%s: can't handle %s relocation records\n",
+				_dl_progname, UNSUPPORTED_RELOC_STR);
 		goof++;
 		return goof;
 	}
@@ -757,8 +736,15 @@
 	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 */
+			reloc_size -= relative_count * sizeof(ELF_RELOC);
+			elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
+			reloc_addr += relative_count * sizeof(ELF_RELOC);
+		}
 		goof += _dl_parse_relocation_information(rpnt,
-				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
+				reloc_addr,
 				reloc_size);
 	}
 	if (tpnt->dynamic_info[DT_BIND_NOW])
@@ -784,7 +770,7 @@
 /* Minimal printf which handles only %s, %d, and %x */
 void _dl_dprintf(int fd, const char *fmt, ...)
 {
-	int num;
+	long num;
 	va_list args;
 	char *start, *ptr, *string;
 	static char *buf;
@@ -832,7 +818,7 @@
 				case 'd':
 					{
 						char tmp[22];
-						num = va_arg(args, int);
+						num = va_arg(args, long);
 
 						string = _dl_simple_ltoa(tmp, num);
 						_dl_write(fd, string, _dl_strlen(string));
@@ -842,7 +828,7 @@
 				case 'X':
 					{
 						char tmp[22];
-						num = va_arg(args, int);
+						num = va_arg(args, long);
 
 						string = _dl_simple_ltoahex(tmp, num);
 						_dl_write(fd, string, _dl_strlen(string));
@@ -874,9 +860,9 @@
 	return retval;
 }
 
-void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr)
+void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off)
 {
-	__dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr);
+	__dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
 }
 #ifdef __USE_GNU
 #if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/dl-hash.c uClibc-08082005/ldso/ldso/dl-hash.c
--- uClibc-0.9.27/ldso/ldso/dl-hash.c	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/dl-hash.c	2005-08-08 13:53:17.000000000 +0300
@@ -57,16 +57,22 @@
 /* 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.  */
-unsigned long _dl_elf_hash(const unsigned char *name)
+static inline Elf32_Word _dl_elf_hash(const char *name)
 {
-	unsigned long hash = 0;
+	unsigned long hash=0;
 	unsigned long tmp;
 
 	while (*name) {
 		hash = (hash << 4) + *name++;
-		if ((tmp = hash & 0xf0000000))
-			hash ^= tmp >> 24;
-		hash &= ~tmp;
+		tmp = hash & 0xf0000000;
+		/* The algorithm specified in the ELF ABI is as follows:
+		   if (tmp != 0)
+		       hash ^= tmp >> 24;
+		   hash &= ~tmp;
+		   But the following is equivalent and a lot
+		   faster, especially on modern processors. */
+		hash ^= tmp;
+		hash ^= tmp >> 24;
 	}
 	return hash;
 }
@@ -79,7 +85,7 @@
 
 	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
 		if (_dl_strncmp(tpnt->libname, libname, len) == 0 &&
-				(tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
+		    (tpnt->libname[len] == '\0' || tpnt->libname[len] == '.'))
 			return tpnt;
 	}
 
@@ -95,7 +101,7 @@
 	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
 	unsigned long dynamic_size)
 {
-	unsigned long *hash_addr;
+	Elf32_Word *hash_addr;
 	struct elf_resolve *tpnt;
 	int i;
 
@@ -119,7 +125,7 @@
 	tpnt->libtype = loaded_file;
 
 	if (dynamic_info[DT_HASH] != 0) {
-		hash_addr = (unsigned long *) (intptr_t)(dynamic_info[DT_HASH] + loadaddr);
+		hash_addr = (Elf32_Word*)dynamic_info[DT_HASH];
 		tpnt->nbucket = *hash_addr++;
 		tpnt->nchain = *hash_addr++;
 		tpnt->elf_buckets = hash_addr;
@@ -142,13 +148,13 @@
 	struct elf_resolve *tpnt;
 	int si;
 	char *strtab;
-	Elf32_Sym *symtab;
+	ElfW(Sym) *symtab;
 	unsigned long elf_hash_number, hn;
 	const ElfW(Sym) *sym;
 	char *weak_result = NULL;
 
 	elf_hash_number = _dl_elf_hash(name);
-	   
+
 	for (; rpnt; rpnt = rpnt->next) {
 		tpnt = rpnt->dyn;
 
@@ -172,8 +178,8 @@
 
 		/* Avoid calling .urem here. */
 		do_rem(hn, elf_hash_number, tpnt->nbucket);
-		symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-		strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+		symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
+		strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
 
 		for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
 			sym = &symtab[si];
@@ -184,10 +190,10 @@
 				continue;
 			if (sym->st_value == 0)
 				continue;
-			if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
+			if (ELF_ST_TYPE(sym->st_info) > STT_FUNC)
 				continue;
 
-			switch (ELF32_ST_BIND(sym->st_info)) {
+			switch (ELF_ST_BIND(sym->st_info)) {
 			case STB_WEAK:
 #if 0
 /* Perhaps we should support old style weak symbol handling
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/dl-startup.c uClibc-08082005/ldso/ldso/dl-startup.c
--- uClibc-0.9.27/ldso/ldso/dl-startup.c	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/dl-startup.c	2005-08-08 13:53:17.000000000 +0300
@@ -3,6 +3,7 @@
  * Program to load an ELF binary on a linux system, and run it
  * after resolving ELF shared library symbols
  *
+ * Copyright (C) 2005 by Joakim Tjernlund
  * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
  * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  *				David Engel, Hongjiu Lu and Mitch D'Souza
@@ -96,38 +97,31 @@
 /* Static declarations */
 int (*_dl_elf_main) (int, char **, char **);
 
-
-
+static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */
+strong_alias(__rtld_stack_end, __libc_stack_end); /* Exported version of __rtld_stack_end */
 
 /* When we enter this piece of code, the program stack looks like this:
-        argc            argument counter (integer)
-        argv[0]         program name (pointer)
-        argv[1...N]     program args (pointers)
-        argv[argc-1]    end of args (integer)
-		NULL
-        env[0...N]      environment variables (pointers)
-        NULL
-		auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
+	argc            argument counter (integer)
+	argv[0]         program name (pointer)
+	argv[1...N]     program args (pointers)
+	argv[argc-1]    end of args (integer)
+	NULL
+	env[0...N]      environment variables (pointers)
+	NULL
+	auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
 */
-DL_BOOT(unsigned long args)
+static void * __attribute_used__ _dl_start(unsigned long args)
 {
 	unsigned int argc;
 	char **argv, **envp;
 	unsigned long load_addr;
-	unsigned long *got;
+	ElfW(Addr) got;
 	unsigned long *aux_dat;
-	int goof = 0;
 	ElfW(Ehdr) *header;
 	struct elf_resolve tpnt_tmp;
 	struct elf_resolve *tpnt = &tpnt_tmp;
-	Elf32_auxv_t auxvt[AT_EGID + 1];
-	Elf32_Dyn *dpnt;
-	int indx;
-#if defined(__i386__)
-	int status = 0;
-#endif
-
-
+	ElfW(auxv_t) auxvt[AT_EGID + 1];
+	ElfW(Dyn) *dpnt;
 
 	/* WARNING! -- we cannot make _any_ funtion calls until we have
 	 * taken care of fixing up our own relocations.  Making static
@@ -137,14 +131,17 @@
 	/* First obtain the information on the stack that tells us more about
 	   what binary is loaded, where it is loaded, etc, etc */
 	GET_ARGV(aux_dat, args);
-#if defined (__arm__) || defined (__mips__) || defined (__cris__)
-	aux_dat += 1;
-#endif
 	argc = *(aux_dat - 1);
 	argv = (char **) aux_dat;
 	aux_dat += argc;			/* Skip over the argv pointers */
 	aux_dat++;					/* Skip over NULL at end of argv */
 	envp = (char **) aux_dat;
+	SEND_STDERR_DEBUG("argc=");
+	SEND_NUMBER_STDERR_DEBUG(argc, 0);
+	SEND_STDERR_DEBUG(" argv=");
+	SEND_ADDRESS_STDERR_DEBUG(argv, 0);
+	SEND_STDERR_DEBUG(" envp=");
+	SEND_ADDRESS_STDERR_DEBUG(envp, 1);
 	while (*aux_dat)
 		aux_dat++;				/* Skip over the envp pointers */
 	aux_dat++;					/* Skip over NULL at end of envp */
@@ -157,21 +154,23 @@
 	 * the Auxiliary Vector Table.  Read out the elements of the auxvt,
 	 * sort and store them in auxvt for later use. */
 	while (*aux_dat) {
-		Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat;
+		ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat;
 
 		if (auxv_entry->a_type <= AT_EGID) {
-			_dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t));
+			_dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));
 		}
 		aux_dat += 2;
 	}
 
 	/* locate the ELF header.   We need this done as soon as possible
 	 * (esp since SEND_STDERR() needs this on some platforms... */
+	if (!auxvt[AT_BASE].a_un.a_val)
+		auxvt[AT_BASE].a_un.a_val = elf_machine_load_address();
 	load_addr = auxvt[AT_BASE].a_un.a_val;
-	header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
+	header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
 
 	/* Check the ELF header to make sure everything looks ok.  */
-	if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
+	if (!header || header->e_ident[EI_CLASS] != ELF_CLASS ||
 			header->e_ident[EI_VERSION] != EV_CURRENT
 			/* Do not use an inline _dl_strncmp here or some arches
 			* will blow chunks, i.e. those that need to relocate all
@@ -184,228 +183,127 @@
 		SEND_STDERR("Invalid ELF header\n");
 		_dl_exit(0);
 	}
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("ELF header=");
-	SEND_ADDRESS_STDERR(load_addr, 1);
-#endif
-
+	SEND_STDERR_DEBUG("ELF header=");
+	SEND_ADDRESS_STDERR_DEBUG(load_addr, 1);
 
 	/* Locate the global offset table.  Since this code must be PIC
 	 * we can take advantage of the magic offset register, if we
 	 * happen to know what that is for this architecture.  If not,
 	 * we can always read stuff out of the ELF file to find it... */
-#if defined(__i386__)
-	__asm__("\tmovl %%ebx,%0\n\t":"=a"(got));
-#elif defined(__m68k__)
-	__asm__("movel %%a5,%0":"=g"(got));
-#elif defined(__sparc__)
-	__asm__("\tmov %%l7,%0\n\t":"=r"(got));
-#elif defined(__arm__)
-	__asm__("\tmov %0, r10\n\t":"=r"(got));
-#elif defined(__powerpc__)
-	__asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
-#elif defined(__mips__)
-	__asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
-#elif defined(__sh__) && !defined(__SH5__)
-	__asm__(
-			"       mov.l    1f, %0\n"
-			"       mova     1f, r0\n"
-			"       bra      2f\n"
-			"       add r0,  %0\n"
-			"       .balign  4\n"
-			"1:     .long    _GLOBAL_OFFSET_TABLE_\n"
-			"2:" : "=r" (got) : : "r0");
-#elif defined(__cris__)
-	__asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%0\n\t":"=r"(got));
-#else
-	/* Do things the slow way in C */
-	{
-		unsigned long tx_reloc;
-		Elf32_Dyn *dynamic = NULL;
-		Elf32_Shdr *shdr;
-		Elf32_Phdr *pt_load;
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-		SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
-#endif
-		/* Find where the dynamic linking information section is hiding */
-		shdr = (Elf32_Shdr *) (header->e_shoff + (char *) header);
-		for (indx = header->e_shnum; --indx >= 0; ++shdr) {
-			if (shdr->sh_type == SHT_DYNAMIC) {
-				goto found_dynamic;
-			}
-		}
-		SEND_STDERR("missing dynamic linking information section \n");
-		_dl_exit(0);
-
-found_dynamic:
-		dynamic = (Elf32_Dyn *) (shdr->sh_offset + (char *) header);
-
-		/* Find where PT_LOAD is hiding */
-		pt_load = (Elf32_Phdr *) (header->e_phoff + (char *) header);
-		for (indx = header->e_phnum; --indx >= 0; ++pt_load) {
-			if (pt_load->p_type == PT_LOAD) {
-				goto found_pt_load;
-			}
-		}
-		SEND_STDERR("missing loadable program segment\n");
-		_dl_exit(0);
-
-found_pt_load:
-		/* Now (finally) find where DT_PLTGOT is hiding */
-		tx_reloc = pt_load->p_vaddr - pt_load->p_offset;
-		for (; DT_NULL != dynamic->d_tag; ++dynamic) {
-			if (dynamic->d_tag == DT_PLTGOT) {
-				goto found_got;
-			}
-		}
-		SEND_STDERR("missing global offset table\n");
-		_dl_exit(0);
-
-found_got:
-		got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc +
-				(char *) header);
-	}
-#endif
-
-	/* Now, finally, fix up the location of the dynamic stuff */
-	dpnt = (Elf32_Dyn *) (*got + load_addr);
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("First Dynamic section entry=");
-	SEND_ADDRESS_STDERR(dpnt, 1);
-#endif
+	got = elf_machine_dynamic();
+	dpnt = (ElfW(Dyn) *) (got + load_addr);
+	SEND_STDERR_DEBUG("First Dynamic section entry=");
+	SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
 	_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
-
+	tpnt->loadaddr = load_addr;
 	/* OK, that was easy.  Next scan the DYNAMIC section of the image.
 	   We are only doing ourself right now - we will have to do the rest later */
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("scanning DYNAMIC section\n");
-#endif
+	SEND_STDERR_DEBUG("Scanning DYNAMIC section\n");
 	tpnt->dynamic_addr = dpnt;
-#ifdef __mips__
-	/* MIPS cannot call functions here, must inline */
-	__dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL);
+#if defined(NO_FUNCS_BEFORE_BOOTSTRAP)
+	/* Some architectures cannot call functions here, must inline */
+	__dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
 #else
-	_dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL);
+	_dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
 #endif
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("done scanning DYNAMIC section\n");
-#endif
+	SEND_STDERR_DEBUG("Done scanning DYNAMIC section\n");
 
-#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
-	/* Ugly, ugly.  We need to call mprotect to change the protection of
-	   the text pages so that we can do the dynamic linking.  We can set the
-	   protection back again once we are done */
+#if defined(PERFORM_BOOTSTRAP_GOT)
 
-	{
-		ElfW(Phdr) *ppnt;
-		int i;
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-		SEND_STDERR("calling mprotect on the shared library/dynamic linker\n");
-#endif
+	SEND_STDERR_DEBUG("About to do specific GOT bootstrap\n");
+	/* some arches (like MIPS) we have to tweak the GOT before relocations */
+	PERFORM_BOOTSTRAP_GOT(tpnt);
 
-		/* First cover the shared library/dynamic linker. */
-		if (tpnt->dynamic_info[DT_TEXTREL]) {
-			header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
-			ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr +
-					header->e_phoff);
-			for (i = 0; i < header->e_phnum; i++, ppnt++) {
-				if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
-					_dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)),
-							(ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
-							PROT_READ | PROT_WRITE | PROT_EXEC);
-				}
-			}
-		}
-	}
-#endif
-#if defined(__mips__)
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
-#endif
-	/* For MIPS we have to do stuff to the GOT before we do relocations.  */
-	PERFORM_BOOTSTRAP_GOT(got, tpnt);
-#endif
+#else
 
 	/* OK, now do the relocations.  We do not do a lazy binding here, so
 	   that once we are done, we have considerably more flexibility. */
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("About to do library loader relocations\n");
-#endif
+	SEND_STDERR_DEBUG("About to do library loader relocations\n");
+
+	{
+		int goof, indx;
 #ifdef  ELF_MACHINE_PLTREL_OVERLAP
 # define INDX_MAX 1
 #else
 # define INDX_MAX 2
 #endif
-	goof = 0;
-	for (indx = 0; indx < INDX_MAX; indx++) {
-		unsigned int i;
-		ELF_RELOC *rpnt;
-		unsigned long *reloc_addr;
-		unsigned long symbol_addr;
-		int symtab_index;
-		unsigned long rel_addr, rel_size;
-		Elf32_Sym *sym;
-
-		rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
-				dynamic_info[DT_RELOC_TABLE_ADDR]);
-		rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
-				dynamic_info[DT_RELOC_TABLE_SIZE]);
-
-		if (!rel_addr)
-			continue;
-
-		/* Now parse the relocation information */
-		rpnt = (ELF_RELOC *) (rel_addr + load_addr);
-		for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
-			reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
-			symtab_index = ELF32_R_SYM(rpnt->r_info);
-			symbol_addr = 0;
-			sym = NULL;
-			if (symtab_index) {
-				char *strtab;
-				Elf32_Sym *symtab;
-
-				symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr);
-				strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr);
-				sym = &symtab[symtab_index];
-				symbol_addr = load_addr + sym->st_value;
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-				SEND_STDERR("relocating symbol: ");
-				SEND_STDERR(strtab + sym->st_name);
-				SEND_STDERR("\n");
-#endif
+		goof = 0;
+		for (indx = 0; indx < INDX_MAX; indx++) {
+			unsigned int i;
+			unsigned long *reloc_addr;
+			unsigned long symbol_addr;
+			int symtab_index;
+			ElfW(Sym) *sym;
+			ELF_RELOC *rpnt;
+			unsigned long rel_addr, rel_size;
+			ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
+
+			rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :
+			                   tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);
+			rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :
+			                   tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);
+
+			if (!rel_addr)
+				continue;
+
+			/* Now parse the relocation information */
+			/* Since ldso is linked with -Bsymbolic, all relocs will be RELATIVE(for those archs that have
+			   RELATIVE relocs) which means that the for(..) loop below has nothing to do and can be deleted.
+			   Possibly one should add a HAVE_RELATIVE_RELOCS directive and #ifdef away some code. */
+			if (!indx && relative_count) {
+				rel_size -= relative_count * sizeof(ELF_RELOC);
+				elf_machine_relative(load_addr, rel_addr, relative_count);
+				rel_addr += relative_count * sizeof(ELF_RELOC);;
+			}
+
+			rpnt = (ELF_RELOC *) (rel_addr + load_addr);
+			for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+				reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
+				symtab_index = ELF_R_SYM(rpnt->r_info);
+				symbol_addr = 0;
+				sym = NULL;
+				if (symtab_index) {
+					char *strtab;
+					ElfW(Sym) *symtab;
+
+					symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+					strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+					sym = &symtab[symtab_index];
+					symbol_addr = load_addr + sym->st_value;
+
+					SEND_STDERR_DEBUG("relocating symbol: ");
+					SEND_STDERR_DEBUG(strtab + sym->st_name);
+					SEND_STDERR_DEBUG("\n");
+				} else
+					SEND_STDERR_DEBUG("relocating unknown symbol\n");
+				/* Use this machine-specific macro to perform the actual relocation.  */
+				PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
 			}
-			/* Use this machine-specific macro to perform the actual relocation.  */
-			PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
 		}
-	}
 
-	if (goof) {
-		_dl_exit(14);
+		if (goof) {
+			_dl_exit(14);
+		}
 	}
+#endif
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
 	/* Wahoo!!! */
-	SEND_STDERR("Done relocating library loader, so we can now\n"
-			"\tuse globals and make function calls!\n");
-#endif
+	SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n");
 
 	/* Now we have done the mandatory linking of some things.  We are now
 	   free to start using global variables, since these things have all been
-	   fixed up by now.  Still no function calls outside of this library ,
+	   fixed up by now.  Still no function calls outside of this library,
 	   since the dynamic resolver is not yet ready. */
+
+	__rtld_stack_end = (void *)(argv - 1);
+
 	_dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv);
 
 
 	/* Transfer control to the application.  */
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	SEND_STDERR("transfering control to application\n");
-#endif
-	_dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
+	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);
 	START();
 }
-
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/frv/dl-debug.h uClibc-08082005/ldso/ldso/frv/dl-debug.h
--- uClibc-0.9.27/ldso/ldso/frv/dl-debug.h	1970-01-01 02:00:00.000000000 +0200
+++ uClibc-08082005/ldso/ldso/frv/dl-debug.h	2005-08-08 13:53:17.000000000 +0300
@@ -0,0 +1,43 @@
+/* FR-V FDPIC ELF shared library loader suppport
+   Copyright (C) 2003, 2004 Red Hat, Inc.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+   Lots of code copied from ../i386/elfinterp.c, so:
+   Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+  				David Engel, Hongjiu Lu and Mitch D'Souza
+   Copyright (C) 2001-2002, Erik Andersen
+   All rights reserved.
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA.  */
+
+static const char *_dl_reltypes_tab[] =
+{
+  [0]	"R_FRV_NONE",		"R_FRV_32",
+  [2]	"R_FRV_LABEL16",	"R_FRV_LABEL24",
+  [4]	"R_FRV_LO16",		"R_FRV_HI16",
+  [6]	"R_FRV_GPREL12",	"R_FRV_GPRELU12",
+  [8]	"R_FRV_GPREL32",	"R_FRV_GPRELHI",	"R_FRV_GPRELLO",
+  [11]	"R_FRV_GOT12",		"R_FRV_GOTHI",		"R_FRV_GOTLO",
+  [14]	"R_FRV_FUNCDESC",
+  [15]	"R_FRV_FUNCDESC_GOT12",	"R_FRV_FUNCDESC_GOTHI",	"R_FRV_FUNCDESC_GOTLO",
+  [18]	"R_FRV_FUNCDESC_VALUE", "R_FRV_FUNCDESC_GOTOFF12",
+  [20]	"R_FRV_FUNCDESC_GOTOFFHI", "R_FRV_FUNCDESC_GOTOFFLO",
+  [22]	"R_FRV_GOTOFF12",	"R_FRV_GOTOFFHI",	"R_FRV_GOTOFFLO",
+#if 0
+  [200]	"R_FRV_GNU_VTINHERIT",	"R_FRV_GNU_VTENTRY"
+#endif
+};
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/ldso/ldso.c uClibc-08082005/ldso/ldso/ldso.c
--- uClibc-0.9.27/ldso/ldso/ldso.c	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/ldso/ldso.c	2005-08-08 13:53:17.000000000 +0300
@@ -3,6 +3,7 @@
  * Program to load an ELF binary on a linux system, and run it
  * after resolving ELF shared library symbols
  *
+ * Copyright (C) 2005 by Joakim Tjernlund
  * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
  * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  *				David Engel, Hongjiu Lu and Mitch D'Souza
@@ -32,6 +33,9 @@
 #include "ldso.h"
 #include "unsecvars.h"
 
+/* Pull in common debug code */
+#include "dl-debug.c"
+
 #define ALLOW_ZERO_PLTGOT
 
 /* Pull in the value of _dl_progname */
@@ -58,6 +62,9 @@
 int   _dl_debug_file      = 2;
 #endif
 
+/* Needed for standalone execution. */
+unsigned long attribute_hidden _dl_skip_args = 0;
+
 #include "dl-startup.c"
 /* Forward function declarations */
 static int _dl_suid_ok(void);
@@ -74,23 +81,39 @@
 static unsigned char *_dl_malloc_addr = 0;	/* Lets _dl_malloc use the already allocated memory page */
 static unsigned char *_dl_mmap_zero   = 0;	/* Also used by _dl_malloc */
 
-#if defined (__SUPPORT_LD_DEBUG__)
-static void debug_fini (int status, void *arg)
+static struct elf_resolve **init_fini_list;
+static int nlist; /* # items in init_fini_list */
+
+extern void _start(void);
+
+static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
 {
-	(void)status;
-	_dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
+	int i;
+	struct elf_resolve * tpnt;
+
+	for (i = 0; i < nlist; ++i) {
+		tpnt = init_fini_list[i];
+		if (tpnt->init_flag & FINI_FUNCS_CALLED)
+			continue;
+		tpnt->init_flag |= FINI_FUNCS_CALLED;
+		if (tpnt->dynamic_info[DT_FINI]) {
+			void (*dl_elf_func) (void);
+
+			dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+			_dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
+			(*dl_elf_func) ();
+		}
+	}
 }
-#endif
 
 void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
-			  Elf32_auxv_t auxvt[AT_EGID + 1], char **envp,
+			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp,
 			  char **argv)
 {
 	ElfW(Phdr) *ppnt;
-	Elf32_Dyn *dpnt;
+	ElfW(Dyn) *dpnt;
 	char *lpntstr;
-	int i, nlist, goof = 0, unlazy = 0, trace_loaded_objects = 0;
-	struct elf_resolve **init_fini_list;
+	int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
 	struct dyn_elf *rpnt;
 	struct elf_resolve *tcurr;
 	struct elf_resolve *tpnt1;
@@ -98,18 +121,14 @@
 	struct elf_resolve *app_tpnt = &app_tpnt_tmp;
 	struct r_debug *debug_addr;
 	unsigned long *lpnt;
-	int (*_dl_atexit) (void *);
 	unsigned long *_dl_envp;		/* The environment address */
 	ElfW(Addr) relro_addr = 0;
 	size_t relro_size = 0;
-#if defined (__SUPPORT_LD_DEBUG__)
-	int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
-#endif
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	/* Wahoo!!! */
-	SEND_STDERR("Cool, we managed to make a function call.\n");
-#endif
+	/* Wahoo!!! We managed to make a function call!  Get malloc
+	 * setup so we can use _dl_dprintf() to print debug noise
+	 * instead of the SEND_STDERR macros used in dl-startup.c */
+
 
 	/* 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;
@@ -120,6 +139,9 @@
 	_dl_malloc_addr = (unsigned char *)_dl_pagesize;
 	_dl_mmap_zero = 0;
 
+	/* Wahoo!!! */
+	_dl_debug_early("Cool, ldso survived making function calls\n");
+
 	/* Now we have done the mandatory linking of some things.  We are now
 	 * free to start using global variables, since these things have all
 	 * been fixed up by now.  Still no function calls outside of this
@@ -129,6 +151,11 @@
 		_dl_progname = argv[0];
 	}
 
+	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
+		_dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n");
+		_dl_exit(1);
+	}
+
 	/* Start to build the tables of the modules that are required for
 	 * this beast to run.  We start with the basic executable, and then
 	 * go from there.  Eventually we will run across ourself, and we
@@ -138,6 +165,38 @@
 	if (_dl_getenv("LD_BIND_NOW", envp))
 		unlazy = RTLD_NOW;
 
+	/* Now we need to figure out what kind of options are selected.
+	 * Note that for SUID programs we ignore the settings in
+	 * LD_LIBRARY_PATH.
+	 */
+	if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
+	    (auxvt[AT_UID].a_un.a_val != -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;
+		_dl_preload = _dl_getenv("LD_PRELOAD", envp);
+		_dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
+	} else {
+		static const char unsecure_envvars[] =
+#ifdef EXTRA_UNSECURE_ENVVARS
+			EXTRA_UNSECURE_ENVVARS
+#endif
+			UNSECURE_ENVVARS;
+		const char *nextp;
+		_dl_secure = 1;
+
+		nextp = unsecure_envvars;
+		do {
+			_dl_unsetenv (nextp, envp);
+			/* We could use rawmemchr but this need not be fast.  */
+			nextp = (char *) _dl_strchr(nextp, '\0') + 1;
+		} while (*nextp != '\0');
+		_dl_preload = NULL;
+		_dl_library_path = NULL;
+		/* SUID binaries can be exploited if they do LAZY relocation. */
+		unlazy = RTLD_NOW;
+	}
+
 	/* 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
@@ -149,7 +208,7 @@
 	 */
 	{
 		int i;
-		ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+		ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
 
 		for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
 			if (ppnt->p_type == PT_PHDR) {
@@ -157,12 +216,9 @@
 				break;
 			}
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-		if (app_tpnt->loadaddr) {
-			SEND_STDERR("Position Independent Executable: app_tpnt->loadaddr=");
-			SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
-		}
-#endif
+		if (app_tpnt->loadaddr)
+			_dl_debug_early("Position Independent Executable: "
+					"app_tpnt->loadaddr=%x\n", app_tpnt->loadaddr);
 	}
 
 	/*
@@ -172,27 +228,25 @@
 	debug_addr = _dl_malloc(sizeof(struct r_debug));
 	_dl_memset(debug_addr, 0, sizeof(struct r_debug));
 
-	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
 	for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
 		if (ppnt->p_type == PT_GNU_RELRO) {
 			relro_addr = ppnt->p_vaddr;
 			relro_size = ppnt->p_memsz;
 		}
 		if (ppnt->p_type == PT_DYNAMIC) {
-			dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
-			_dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr);
+			dpnt = (ElfW(Dyn) *) (ppnt->p_vaddr + app_tpnt->loadaddr);
+			_dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
 			/* Ugly, ugly.  We need to call mprotect to change the
 			 * protection of the text pages so that we can do the
 			 * dynamic linking.  We can set the protection back
 			 * again once we are done.
 			 */
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-			SEND_STDERR("calling mprotect on the application program\n");
-#endif
+			_dl_debug_early("calling mprotect on the application program\n");
 			/* Now cover the application program. */
 			if (app_tpnt->dynamic_info[DT_TEXTREL]) {
-				ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+				ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
 				for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
 					if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
 						_dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
@@ -212,7 +266,7 @@
 			app_tpnt = _dl_add_elf_hash_table(_dl_progname, (char *)app_tpnt->loadaddr,
 					app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz);
 			_dl_loaded_modules->libtype = elf_executable;
-			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
 			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
 			_dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset(rpnt, 0, sizeof(struct dyn_elf));
@@ -220,7 +274,7 @@
 			app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
 			app_tpnt->usage_count++;
 			app_tpnt->symbol_scope = _dl_symbol_tables;
-			lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT] + app_tpnt->loadaddr);
+			lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
 #ifdef ALLOW_ZERO_PLTGOT
 			if (lpnt)
 #endif
@@ -229,77 +283,24 @@
 
 		/* OK, fill this in - we did not have this before */
 		if (ppnt->p_type == PT_INTERP) {
-			int readsize = 0;
-			char *pnt, *pnt1, buf[1024];
+			char *ptmp;
 
-			tpnt->libname = _dl_strdup((char *) ppnt->p_offset +
-					(auxvt[AT_PHDR].a_un.a_val & PAGE_ALIGN));
-
-			/* Determine if the shared lib loader is a symlink */
-			_dl_memset(buf, 0, sizeof(buf));
-			readsize = _dl_readlink(tpnt->libname, buf, sizeof(buf));
-			if (readsize > 0 && readsize < (int)(sizeof(buf)-1)) {
-				pnt1 = _dl_strrchr(buf, '/');
-				if (pnt1 && buf != pnt1) {
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-					_dl_dprintf(_dl_debug_file,
-						    "changing tpnt->libname from '%s' to '%s'\n",
-						    tpnt->libname, buf);
-#endif
-					tpnt->libname = _dl_strdup(buf);
-				}
-			}
+			tpnt->libname = (char *) ppnt->p_vaddr + app_tpnt->loadaddr;
 
 			/* Store the path where the shared lib loader was found
 			 * for later use
 			 */
-			pnt = _dl_strdup(tpnt->libname);
-			pnt1 = _dl_strrchr(pnt, '/');
-			if (pnt != pnt1) {
-				*pnt1 = '\0';
-				_dl_ldsopath = pnt;
-			} else {
-				_dl_ldsopath = tpnt->libname;
-			}
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-			_dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n",
-				    tpnt->loadaddr, tpnt->libname);
-#endif
+			_dl_ldsopath = _dl_strdup(tpnt->libname);
+			ptmp = _dl_strrchr(_dl_ldsopath, '/');
+			if (ptmp != _dl_ldsopath)
+				*ptmp = '\0';
+
+			_dl_debug_early("Lib Loader: (%x) %s\n", tpnt->loadaddr, tpnt->libname);
 		}
 	}
 	app_tpnt->relro_addr = relro_addr;
 	app_tpnt->relro_size = relro_size;
 
-	/* Now we need to figure out what kind of options are selected.
-	 * Note that for SUID programs we ignore the settings in
-	 * LD_LIBRARY_PATH.
-	 */
-	if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
-	    (auxvt[AT_UID].a_un.a_val != -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;
-		_dl_preload = _dl_getenv("LD_PRELOAD", envp);
-		_dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
-	} else {
-		static const char unsecure_envvars[] =
-#ifdef EXTRA_UNSECURE_ENVVARS
-			EXTRA_UNSECURE_ENVVARS
-#endif
-			UNSECURE_ENVVARS;
-		const char *nextp;
-		_dl_secure = 1;
-
-		nextp = unsecure_envvars;
-		do {
-			_dl_unsetenv (nextp, envp);
-			/* We could use rawmemchr but this need not be fast.  */
-			nextp = (char *) _dl_strchr(nextp, '\0') + 1;
-		} while (*nextp != '\0');
-		_dl_preload = NULL;
-		_dl_library_path = NULL;
-	}
-
 #ifdef __SUPPORT_LD_DEBUG__
 	_dl_debug = _dl_getenv("LD_DEBUG", envp);
 	if (_dl_debug) {
@@ -341,7 +342,7 @@
 				_dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644);
 				if (_dl_debug_file < 0) {
 					_dl_debug_file = 2;
-					_dl_dprintf (2, "can't open file: '%s'\n",filename);
+					_dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename);
 				}
 			}
 		}
@@ -397,17 +398,7 @@
 			*str2 = '\0';
 
 			if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
-				if ((tpnt1 = _dl_check_if_named_library_is_loaded(str, trace_loaded_objects))) {
-					tpnt1->usage_count++;
-					goto next_lib;
-				}
-
-#if defined (__SUPPORT_LD_DEBUG__)
-				if(_dl_debug)
-					_dl_dprintf(_dl_debug_file,
-						    "\tfile='%s';  needed by '%s'\n",
-						    str, _dl_progname);
-#endif
+				_dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", str, _dl_progname);
 
 				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
 				if (!tpnt1) {
@@ -417,18 +408,13 @@
 					else
 #endif
 					{
-						_dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
+						_dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
 						_dl_exit(15);
 					}
 				} else {
 					tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-					_dl_dprintf(_dl_debug_file,
-						    "Loading:\t(%x) %s\n",
-						    tpnt1->loadaddr,
-						    tpnt1->libname);
-#endif
+					_dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
 					if (trace_loaded_objects &&
@@ -440,13 +426,12 @@
 						 */
 						if (_dl_strcmp(_dl_progname, str) != 0)
 							_dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
-								    (unsigned)tpnt1->loadaddr);
+								    tpnt1->loadaddr);
 					}
 #endif
 				}
 			}
 
-next_lib:
 			*str2 = c;
 			str = str2;
 			while (*str == ':' || *str == ' ' || *str == '\t')
@@ -466,7 +451,7 @@
 		}
 
 		if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
-			_dl_dprintf(2, "%s: can't open file '%s'\n",
+			_dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
 				    _dl_progname, LDSO_PRELOAD);
 			break;
 		}
@@ -475,7 +460,7 @@
 					     PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 		_dl_close(fd);
 		if (preload == (caddr_t) -1) {
-			_dl_dprintf(2, "%s: can't map file '%s'\n",
+			_dl_dprintf(_dl_debug_file, "%s: can't map file '%s'\n",
 				    _dl_progname, LDSO_PRELOAD);
 			break;
 		}
@@ -504,17 +489,7 @@
 			c = *cp;
 			*cp = '\0';
 
-			if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2, trace_loaded_objects))) {
-				tpnt1->usage_count++;
-				goto next_lib2;
-			}
-
-#if defined (__SUPPORT_LD_DEBUG__)
-			if(_dl_debug)
-				_dl_dprintf(_dl_debug_file,
-					    "\tfile='%s';  needed by '%s'\n",
-					    cp2, _dl_progname);
-#endif
+			_dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", cp2, _dl_progname);
 
 			tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
 			if (!tpnt1) {
@@ -524,17 +499,13 @@
 				else
 #endif
 				{
-					_dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
+					_dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
 					_dl_exit(15);
 				}
 			} else {
 				tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-				_dl_dprintf(_dl_debug_file,
-					    "Loading:\t(%x) %s\n",
-					    tpnt1->loadaddr, tpnt1->libname);
-#endif
+				_dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
 				if (trace_loaded_objects &&
@@ -546,7 +517,6 @@
 #endif
 			}
 
-next_lib2:
 			/* find start of next library */
 			*cp = c;
 			for ( /*nada */ ; *cp && *cp == ' '; cp++)
@@ -559,40 +529,31 @@
 
 	nlist = 0;
 	for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
-		Elf32_Dyn *dpnt;
+		ElfW(Dyn) *dpnt;
 
 		nlist++;
-		for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
+		for (dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
 			if (dpnt->d_tag == DT_NEEDED) {
 				char *name;
 				struct init_fini_list *tmp;
 
-				lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
+				lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val);
 				name = _dl_get_last_path_component(lpntstr);
+				if (_dl_strcmp(name, "ld-uClibc.so.0") == 0)
+					continue;
 
-				if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects)))	{
-					tpnt1->usage_count++;
-				}
+				_dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", lpntstr, _dl_progname);
 
-#if defined (__SUPPORT_LD_DEBUG__)
-				if(_dl_debug)
-					_dl_dprintf(_dl_debug_file,
-						    "\tfile='%s';  needed by '%s'\n",
-						    lpntstr, _dl_progname);
-#endif
-
-				if (!tpnt1) {
-					if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))	{
+				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))	{
 #ifdef __LDSO_LDD_SUPPORT__
-						if (trace_loaded_objects) {
-							_dl_dprintf(1, "\t%s => not found\n", lpntstr);
-							continue;
-						} else
-#endif
-						{
-							_dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
-							_dl_exit(16);
-						}
+					if (trace_loaded_objects) {
+						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
+						continue;
+					} else
+#endif
+					{
+						_dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
+						_dl_exit(16);
 					}
 				}
 
@@ -603,11 +564,7 @@
 
 				tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-				_dl_dprintf(_dl_debug_file,
-					    "Loading:\t(%x) %s\n",
-					    tpnt1->loadaddr, tpnt1->libname);
-#endif
+				_dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
 				if (trace_loaded_objects &&
@@ -623,12 +580,7 @@
 	_dl_unmap_cache();
 
 	--nlist; /* Exclude the application. */
-
-	/* As long as atexit() is used to run the FINI functions, we can use
-	 * alloca here. The use of atexit() should go away at some time as that
-	 * will make Valgring happy.
-	 */
-	init_fini_list = alloca(nlist * sizeof(struct elf_resolve *));
+	init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
 	i = 0;
 	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
 		init_fini_list[i++] = tcurr;
@@ -646,10 +598,7 @@
 			for (; runp; runp = runp->next) {
 				if (runp->tpnt == tcurr) {
 					struct elf_resolve *here = init_fini_list[k];
-#ifdef __SUPPORT_LD_DEBUG__
-					if(_dl_debug)
-						_dl_dprintf(2, "Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
-#endif
+					_dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j);
 					for (i = (k - j); i; --i)
 						init_fini_list[i+j] = init_fini_list[i+j-1];
 					init_fini_list[j] = here;
@@ -661,16 +610,16 @@
 	}
 #ifdef __SUPPORT_LD_DEBUG__
 	if(_dl_debug) {
-		_dl_dprintf(2, "\nINIT/FINI order and dependencies:\n");
+		_dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n");
 		for (i = 0; i < nlist; i++) {
 			struct init_fini_list *tmp;
 
-			_dl_dprintf(2, "lib: %s has deps:\n",
+			_dl_dprintf(_dl_debug_file, "lib: %s has deps:\n",
 				    init_fini_list[i]->libname);
 			tmp = init_fini_list[i]->init_fini;
 			for (; tmp; tmp = tmp->next)
-				_dl_dprintf(2, " %s ", tmp->tpnt->libname);
-			_dl_dprintf(2, "\n");
+				_dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname);
+			_dl_dprintf(_dl_debug_file, "\n");
 		}
 	}
 #endif
@@ -682,7 +631,7 @@
 	 * again once all libs are loaded.
 	 */
 	if (tpnt) {
-		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
+		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
 		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
 		int j;
 		
@@ -717,7 +666,7 @@
 #ifdef RERELOCATE_LDSO
 		/* Only rerelocate functions for now. */
 		tpnt->init_flag = RELOCS_DONE;
-		lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr);
+		lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]);
 # ifdef ALLOW_ZERO_PLTGOT
 		if (tpnt->dynamic_info[DT_PLTGOT])
 # endif
@@ -738,9 +687,7 @@
 	}
 #endif
 
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	_dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
-#endif
+	_dl_debug_early("Beginning relocation fixups\n");
 
 #ifdef __mips__
 	/*
@@ -797,13 +744,6 @@
 
 	}
 #endif
-
-	_dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
-#if defined (__SUPPORT_LD_DEBUG__)
-	_dl_on_exit = (int (*)(void (*)(int, void *),void*))
-		(intptr_t) _dl_find_hash("on_exit", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
-#endif
-
 	/* Notify the debugger we have added some objects. */
 	_dl_debug_addr->r_state = RT_ADD;
 	_dl_debug_state();
@@ -819,41 +759,29 @@
 
 			dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
 
-#if defined (__SUPPORT_LD_DEBUG__)
-			if(_dl_debug)
-				_dl_dprintf(_dl_debug_file,
-					    "\ncalling init: %s\n\n",
-					    tpnt->libname);
-#endif
+			_dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
 
 			(*dl_elf_func) ();
 		}
-		tpnt->init_flag |= FINI_FUNCS_CALLED;
-		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
-			void (*dl_elf_func) (void);
+	}
+#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);
 
-			dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
-			(*_dl_atexit) (dl_elf_func);
-#if defined (__SUPPORT_LD_DEBUG__)
-			if(_dl_debug && _dl_on_exit) {
-				(*_dl_on_exit)(debug_fini, tpnt->libname);
-			}
-#endif
-		}
-#if defined (__SUPPORT_LD_DEBUG__)
-		else {
-			if (!_dl_atexit)
-				_dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
-		}
-#endif
+		if (_dl_atexit)
+			(*_dl_atexit) (_dl_fini);
 	}
+#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",
+			 _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
 
 	/* Notify the debugger that all objects are now mapped in.  */
 	_dl_debug_addr->r_state = RT_CONSISTENT;
 	_dl_debug_state();
-
-	/* 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", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
 }
 
 char *_dl_getenv(const char *symbol, char **envp)
@@ -910,22 +838,18 @@
 	void *retval;
 
 #if 0
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-	_dl_dprintf(2, "malloc: request for %d bytes\n", size);
-#endif
+	_dl_debug_early("request for %d bytes\n", size);
 #endif
 
 	if (_dl_malloc_function)
 		return (*_dl_malloc_function) (size);
 
 	if (_dl_malloc_addr - _dl_mmap_zero + (unsigned)size > _dl_pagesize) {
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-		_dl_dprintf(2, "malloc: mmapping more memory\n");
-#endif
+		_dl_debug_early("mmapping more memory\n");
 		_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size,
 				PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 		if (_dl_mmap_check_error(_dl_mmap_zero)) {
-			_dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname);
+			_dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
 			_dl_exit(20);
 		}
 	}
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/libdl/Makefile uClibc-08082005/ldso/libdl/Makefile
--- uClibc-0.9.27/ldso/libdl/Makefile	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/libdl/Makefile	2005-08-08 13:53:17.000000000 +0300
@@ -49,35 +49,32 @@
 OBJS=libdl.o
 PIC_OBJS=libdl_pic.o
 
-all: $(OBJS) $(LIBDL) shared
+all: $(LIBDL) $(LIBDL_PIC)
 
-$(LIBDL): ar-target
+ar-target: $(LIBDL) $(LIBDL_PIC)
 
-$(LIBDL_PIC): ar-target
-
-ar-target: $(OBJS) $(PIC_OBJS)
+$(LIBDL): $(OBJS)
 	$(AR) $(ARFLAGS) $(LIBDL) ../ldso/$(TARGET_ARCH)/resolve.o $(OBJS)
-	$(AR) $(ARFLAGS) $(LIBDL_PIC) $(PIC_OBJS)
 	$(INSTALL) -d $(TOPDIR)lib
 	$(RM) $(TOPDIR)lib/$(LIBDL)
 	$(INSTALL) -m 644 $(LIBDL) $(TOPDIR)lib
 
+$(LIBDL_PIC): $(PIC_OBJS)
+	$(AR) $(ARFLAGS) $(LIBDL_PIC) $(PIC_OBJS)
 
-libdl.o: libdl.c
+libdl.o: libdl.c $(TOPDIR)ldso/include/*.h
 	$(CC) $(XXFLAGS_NOPIC) -c libdl.c -o libdl.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-libdl_pic.o: libdl.c
+libdl_pic.o: libdl.c $(TOPDIR)ldso/include/*.h
 	$(CC) $(XXFLAGS) -c libdl.c -o libdl_pic.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
-$(OBJ): Makefile
-
 shared: $(LIBDL_PIC)
 	$(LD) $(LDFLAGS) -soname=$(LIBDL_SHARED).$(MAJOR_VERSION) \
 		-o $(LIBDL_SHARED_FULLNAME) -fini dl_cleanup --whole-archive $(LIBDL_PIC) \
 		--no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
-		-L$(TOPDIR)/lib -lc $(LDADD_LIBFLOAT) $(LIBGCC);
+		-L$(TOPDIR)/lib -lc $(LDADD_LIBFLOAT) $(TOPDIR)lib/ld-uClibc.so.0 $(LIBGCC);
 	$(INSTALL) -d $(TOPDIR)lib
 	$(RM) $(TOPDIR)lib/$(LIBDL_SHARED_FULLNAME) $(TOPDIR)lib/$(LIBDL_SHARED).$(MAJOR_VERSION)
 	$(INSTALL) -m 644 $(LIBDL_SHARED_FULLNAME) $(TOPDIR)lib
diff -uNr -x .svn -x .cvsignore uClibc-0.9.27/ldso/libdl/libdl.c uClibc-08082005/ldso/libdl/libdl.c
--- uClibc-0.9.27/ldso/libdl/libdl.c	2005-01-12 09:59:21.000000000 +0200
+++ uClibc-08082005/ldso/libdl/libdl.c	2005-08-08 13:53:17.000000000 +0300
@@ -40,33 +40,27 @@
 /* When libdl is loaded as a shared library, we need to load in
  * and use a pile of symbols from ldso... */
 
-extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, int)
-	__attribute__ ((__weak__));
+extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, int);
 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,
-	struct elf_resolve *, char *, int) __attribute__ ((__weak__));
-extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *, int)
-	__attribute__ ((__weak__));
-extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
-	 __attribute__ ((__weak__));
-extern void _dl_protect_relro(struct elf_resolve * tpnt)
-	__attribute__ ((__weak__));
-extern int _dl_errno __attribute__ ((__weak__));
-extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__));
-extern struct dyn_elf *_dl_handles __attribute__ ((__weak__));
-extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__));
-extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__));
-extern unsigned long _dl_error_number __attribute__ ((__weak__));
-extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__));
+	struct elf_resolve *, char *, int);
+extern int _dl_fixup(struct dyn_elf *rpnt, int lazy);
+extern void _dl_protect_relro(struct elf_resolve * tpnt);
+extern int _dl_errno;
+extern struct dyn_elf *_dl_symbol_tables;
+extern struct dyn_elf *_dl_handles;
+extern struct elf_resolve *_dl_loaded_modules;
+extern struct r_debug *_dl_debug_addr;
+extern unsigned long _dl_error_number;
+extern void *(*_dl_malloc_function)(size_t);
 #ifdef __LDSO_CACHE_SUPPORT__
-int _dl_map_cache(void) __attribute__ ((__weak__));
-int _dl_unmap_cache(void) __attribute__ ((__weak__));
+int _dl_map_cache(void);
+int _dl_unmap_cache(void);
 #endif
 #ifdef __mips__
-extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
-	__attribute__ ((__weak__));
+extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
 #endif
 #ifdef __SUPPORT_LD_DEBUG__
-extern char *_dl_debug __attribute__ ((__weak__));
+extern char *_dl_debug;
 #endif
 
 
@@ -78,17 +72,28 @@
 #ifdef __SUPPORT_LD_DEBUG__
 char *_dl_debug  = 0;
 #endif
-char *_dl_library_path         = 0;		    /* Where we look for libraries */
-char *_dl_ldsopath             = 0;		    /* Location of the shared lib loader */
+char *_dl_library_path         = 0;         /* Where we look for libraries */
+char *_dl_ldsopath             = 0;         /* Location of the shared lib loader */
 int _dl_errno                  = 0;         /* We can't use the real errno in ldso */
 size_t _dl_pagesize            = PAGE_SIZE; /* Store the page size for use later */
 /* This global variable is also to communicate with debuggers such as gdb. */
 struct r_debug *_dl_debug_addr = NULL;
 #define _dl_malloc malloc
+#include "../ldso/dl-debug.c"
 #include "dl-progname.h"
 #include "../ldso/dl-hash.c"
 #define _dl_trace_loaded_objects    0
 #include "../ldso/dl-elf.c"
+#endif /* __LIBDL_SHARED__ */
+
+#ifdef __SUPPORT_LD_DEBUG__
+# define _dl_if_debug_print(fmt, args...) \
+	do { \
+	if (_dl_debug) \
+		fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \
+	} while (0)
+#else
+# define _dl_if_debug_print(fmt, args...)
 #endif
 
 static int do_dlclose(void *, int need_fini);
@@ -130,14 +135,14 @@
 
 void *dlopen(const char *libname, int flag)
 {
-	struct elf_resolve *tpnt, *tfrom, *tcurr;
-	struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr;
+	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;
+	struct init_fini_list *tmp, *runp, *runp2, *dep_list;
 	int nlist, i;
 	struct elf_resolve **init_fini_list;
 
@@ -157,7 +162,7 @@
 
 	/*
 	 * Try and locate the module we were called from - we
-	 * need this so that we get the correct RPATH.  Note that
+	 * need this so that we get the correct RPATH/RUNPATH.  Note that
 	 * this is the current behavior under Solaris, but the
 	 * ABI+ specifies that we should only use the RPATH from
 	 * the application.  Thus this may go away at some time
@@ -170,24 +175,22 @@
 				&& (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
 			tfrom = tpnt;
 	}
-	for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next);
+	for(rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next);
 
 	relro_ptr = rpnt;
+	now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
+	if (getenv("LD_BIND_NOW"))
+		now_flag = RTLD_NOW;
+
 	/* Try to load the specified library */
-#ifdef __SUPPORT_LD_DEBUG__
-	if(_dl_debug)
-		fprintf(stderr, "Trying to dlopen '%s'\n", (char*)libname);
-#endif
-	tpnt = _dl_check_if_named_library_is_loaded((char *)libname, 0);
-	if (!(tpnt))
-		tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
-	else
-		tpnt->usage_count++;
+	_dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
+			(char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
+	tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
+
 	if (tpnt == NULL) {
 		_dl_unmap_cache();
 		return NULL;
 	}
-
 	dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
 	_dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
 	dyn_chain->dyn = tpnt;
@@ -196,48 +199,82 @@
 	dyn_chain->next_handle = _dl_handles;
 	_dl_handles = dyn_ptr = dyn_chain;
 
-#ifdef __SUPPORT_LD_DEBUG__
-	if(_dl_debug)
-		fprintf(stderr, "Looking for needed libraries\n");
-#endif
+	if (tpnt->usage_count > 1) {
+		_dl_if_debug_print("Lib: %s already opened\n", libname);
+		/* see if there is a handle from a earlier dlopen */
+		for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) {
+			if (handle->dyn == tpnt) {
+				dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
+				dyn_chain->init_fini.nlist = handle->init_fini.nlist;
+				for(i=0; i < dyn_chain->init_fini.nlist; i++)
+					dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
+				dyn_chain->next = handle->next;
+				break;
+			}
+		}
+		return dyn_chain;
+	} else {
+		tpnt->init_flag |= DL_OPENED;
+	}
+
+	_dl_if_debug_print("Looking for needed libraries\n");
 	nlist = 0;
-	for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
+	runp = alloca(sizeof(*runp));
+	runp->tpnt = tpnt;
+	runp->next = NULL;
+	dep_list = runp2 = runp;
+	for (; runp; runp = runp->next)
 	{
-		Elf32_Dyn *dpnt;
+		ElfW(Dyn) *dpnt;
 		char *lpntstr;
 
 		nlist++;
-		tcurr->init_fini = NULL; /* clear any previous dependcies */
-		for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
+		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*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
+				lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
 						dpnt->d_un.d_val);
 				name = _dl_get_last_path_component(lpntstr);
-				tpnt1 = _dl_check_if_named_library_is_loaded(name, 0);
-#ifdef __SUPPORT_LD_DEBUG__
-				if(_dl_debug)
-					fprintf(stderr, "Trying to load '%s', needed by '%s'\n",
-							lpntstr, tcurr->libname);
-#endif
-				if (tpnt1) {
-					tpnt1->usage_count++;
-				} else {
-					tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 0);
-					if (!tpnt1)
-						goto oops;
-				}
+				_dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
+						lpntstr, runp->tpnt->libname);
+				tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
+				if (!tpnt1)
+					goto oops;
+
 				tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
-				dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
-				_dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
-				dyn_ptr = dyn_ptr->next;
-				dyn_ptr->dyn = tpnt1;
-
-				tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */
-				tmp->tpnt = tpnt1;
-				tmp->next = tcurr->init_fini;
-				tcurr->init_fini = tmp;
+
+				if (tpnt1->usage_count == 1) {
+					tpnt1->init_flag |= DL_OPENED;
+					/* This list is for dlsym() and relocation */
+					dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
+					_dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
+					dyn_ptr = dyn_ptr->next;
+					dyn_ptr->dyn = tpnt1;
+				}
+				if (tpnt1->init_flag & DL_OPENED) {
+					/* Used to record RTLD_LOCAL scope */
+					tmp = alloca(sizeof(struct init_fini_list));
+					tmp->tpnt = tpnt1;
+					tmp->next = runp->tpnt->init_fini;
+					runp->tpnt->init_fini = tmp;
+
+					for (tmp=dep_list; tmp; tmp = tmp->next) {
+						if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
+							_dl_if_debug_print("Circular dependency, skipping '%s',\n",
+									tmp->tpnt->libname);
+							tpnt1->usage_count--;
+							break;
+						}
+					}
+					if (!tmp) { /* Don't add if circular dependency detected */
+						runp2->next = alloca(sizeof(*runp));
+						runp2 = runp2->next;
+						runp2->tpnt = tpnt1;
+						runp2->next = NULL;
+					}
+				}
 			}
 		}
 	}
@@ -245,33 +282,30 @@
 	dyn_chain->init_fini.init_fini = init_fini_list;
 	dyn_chain->init_fini.nlist = nlist;
 	i = 0;
-	for (tcurr = tpnt; tcurr; tcurr = tcurr->next) {
-		init_fini_list[i++] = tcurr;
-		for(runp = tcurr->init_fini; runp; runp = runp->next){
+	for (runp2 = dep_list; runp2; runp2 = runp2->next) {
+		init_fini_list[i++] = runp2->tpnt;
+		for(runp = runp2->tpnt->init_fini; runp; runp = runp->next){
 			if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) {
 				tmp = malloc(sizeof(struct init_fini_list));
 				tmp->tpnt = runp->tpnt;
-				tmp->next = tcurr->rtld_local;
-				tcurr->rtld_local = tmp;
+				tmp->next = runp2->tpnt->rtld_local;
+				runp2->tpnt->rtld_local = tmp;
 			}
 		}
 
 	}
 	/* Sort the INIT/FINI list in dependency order. */
-	for (tcurr = tpnt; tcurr; tcurr = tcurr->next) {
+	for (runp2 = dep_list; runp2; runp2 = runp2->next) {
 		int j, k;
-		for (j = 0; init_fini_list[j] != tcurr; ++j)
+		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;
 
 			for (; runp; runp = runp->next) {
-				if (runp->tpnt == tcurr) {
+				if (runp->tpnt == runp2->tpnt) {
 					struct elf_resolve *here = init_fini_list[k];
-#ifdef __SUPPORT_LD_DEBUG__
-					if(_dl_debug)
-						fprintf(stderr, "Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
-#endif
+					_dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
 					for (i = (k - j); i; --i)
 						init_fini_list[i+j] = init_fini_list[i+j-1];
 					init_fini_list[j] = here;
@@ -287,33 +321,19 @@
 		for (i=0;i < nlist;i++) {
 			fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname);
 			runp = init_fini_list[i]->init_fini;
-			for ( ;runp; runp = runp->next)
+			for (; runp; runp = runp->next)
 				printf(" %s ", runp->tpnt->libname);
 			printf("\n");
 		}
 	}
 #endif
 
-	if (dyn_chain->dyn->init_flag & INIT_FUNCS_CALLED) {
-		/* If the init and fini stuff has already been run, that means
-		 * the dlopen'd library has already been loaded, and nothing
-		 * further needs to be done. */
-		return (void *) dyn_chain;
-	}
-
-#ifdef __SUPPORT_LD_DEBUG__
-	if(_dl_debug)
-		fprintf(stderr, "Beginning dlopen relocation fixups\n");
-#endif
+	_dl_if_debug_print("Beginning dlopen relocation fixups\n");
 	/*
 	 * OK, now all of the kids are tucked into bed in their proper addresses.
 	 * Now we go through and look for REL and RELA records that indicate fixups
 	 * to the GOT tables.  We need to do this in reverse order so that COPY
 	 * directives work correctly */
-	now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
-	if (getenv("LD_BIND_NOW"))
-		now_flag = RTLD_NOW;
-
 #ifdef __mips__
 	/*
 	 * Relocation of the GOT entries for MIPS have to be done
@@ -325,9 +345,11 @@
 	if (_dl_fixup(dyn_chain, now_flag))
 		goto oops;
 
-	for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
-		if (rpnt->dyn->relro_size)
-			_dl_protect_relro(rpnt->dyn);
+	if (relro_ptr) {
+		for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
+			if (rpnt->dyn->relro_size)
+				_dl_protect_relro(rpnt->dyn);
+		}
 	}
 	/* TODO:  Should we set the protections of all pages back to R/O now ? */
 
@@ -356,10 +378,8 @@
 			void (*dl_elf_func) (void);
 			dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
 			if (dl_elf_func && *dl_elf_func != NULL) {
-#ifdef __SUPPORT_LD_DEBUG__
-				if(_dl_debug)
-					fprintf(stderr, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
-#endif
+				_dl_if_debug_print("running ctors for library %s at '%p'\n",
+						tpnt->libname, dl_elf_func);
 				(*dl_elf_func) ();
 			}
 		}
@@ -434,14 +454,16 @@
 	struct dyn_elf *rpnt, *rpnt1;
 	struct init_fini_list *runp, *tmp;
 	ElfW(Phdr) *ppnt;
-	struct elf_resolve *tpnt;
+	struct elf_resolve *tpnt, *run_tpnt;
 	int (*dl_elf_fini) (void);
 	void (*dl_brk) (void);
 	struct dyn_elf *handle;
 	unsigned int end;
-	int i = 0;
+	int i = 0, j;
 
 	handle = (struct dyn_elf *) vhandle;
+	if (handle == _dl_symbol_tables)
+		return 0;
 	rpnt1 = NULL;
 	for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
 		if (rpnt == handle)
@@ -457,27 +479,27 @@
 		rpnt1->next_handle = rpnt->next_handle;
 	else
 		_dl_handles = rpnt->next_handle;
-	if (need_fini) {
-		for (i = 0; i < handle->init_fini.nlist; ++i) {
-			tpnt = handle->init_fini.init_fini[i];
-			if (tpnt->dynamic_info[DT_FINI] && tpnt->usage_count == 1 &&
+	_dl_if_debug_print("%s: usage count: %d\n",
+			handle->dyn->libname, handle->dyn->usage_count);
+	if (handle->dyn->usage_count != 1) {
+		handle->dyn->usage_count--;
+		free(handle);
+		return 0;
+	}
+	/* OK, this is a valid handle - now close out the file */
+	for (j = 0; j < handle->init_fini.nlist; ++j) {
+		tpnt = handle->init_fini.init_fini[j];
+		if (--tpnt->usage_count == 0) {
+			if (tpnt->dynamic_info[DT_FINI] && 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]);
-#ifdef __SUPPORT_LD_DEBUG__
-				if(_dl_debug)
-					fprintf(stderr, "running dtors for library %s at '%x'\n", tpnt->libname, dl_elf_fini);
-#endif
+				_dl_if_debug_print("running dtors for library %s at '%p'\n",
+						tpnt->libname, dl_elf_fini);
 				(*dl_elf_fini) ();
 			}
-		}
-	}
-	if (handle->dyn->usage_count == 1)
-		free(handle->init_fini.init_fini);
-	/* OK, this is a valid handle - now close out the file */
-	for (rpnt = handle; rpnt; rpnt = rpnt->next) {
-		tpnt = rpnt->dyn;
-		if (--tpnt->usage_count == 0) {
+
+			_dl_if_debug_print("unmapping: %s\n", tpnt->libname);
 			end = 0;
 			for (i = 0, ppnt = tpnt->ppnt;
 					i < tpnt->n_phent; ppnt++, i++) {
@@ -492,40 +514,46 @@
 				tmp = runp->next;
 				free(runp);
 			}
+
 			/* Next, remove tpnt from the loaded_module list */
 			if (_dl_loaded_modules == tpnt) {
 				_dl_loaded_modules = tpnt->next;
 				if (_dl_loaded_modules)
 					_dl_loaded_modules->prev = 0;
 			} else
-				for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
-					if (tpnt->next == rpnt->dyn) {
-						tpnt->next = tpnt->next->next;
-						if (tpnt->next)
-							tpnt->next->prev = tpnt;
+				for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next)
+					if (run_tpnt->next == tpnt) {
+						_dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname);
+						run_tpnt->next = run_tpnt->next->next;
+						if (run_tpnt->next)
+							run_tpnt->next->prev = run_tpnt;
 						break;
 					}
 
 			/* Next, remove tpnt from the global symbol table list */
-			if (_dl_symbol_tables->dyn == rpnt->dyn) {
-				_dl_symbol_tables = rpnt->next;
-				if (_dl_symbol_tables)
-					_dl_symbol_tables->prev = 0;
-			} else
-				for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
-					if (rpnt1->next->dyn == rpnt->dyn) {
-						free(rpnt1->next);
-						rpnt1->next = rpnt1->next->next;
-						if (rpnt1->next)
-							rpnt1->next->prev = rpnt1;
-						break;
+			if (_dl_symbol_tables) {
+				if (_dl_symbol_tables->dyn == tpnt) {
+					_dl_symbol_tables = _dl_symbol_tables->next;
+					if (_dl_symbol_tables)
+						_dl_symbol_tables->prev = 0;
+				} else
+					for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
+						if (rpnt1->next->dyn == tpnt) {
+							_dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
+							free(rpnt1->next);
+							rpnt1->next = rpnt1->next->next;
+							if (rpnt1->next)
+								rpnt1->next->prev = rpnt1;
+							break;
+						}
 					}
-				}
-			free(rpnt->dyn->libname);
-			free(rpnt->dyn);
+			}
+			free(tpnt->libname);
+			free(tpnt);
 		}
-		free(rpnt);
 	}
+	free(handle->init_fini.init_fini);
+	free(handle);
 
 
 	if (_dl_debug_addr) {
@@ -555,7 +583,7 @@
 		return NULL;
 	retval = dl_error_names[_dl_error_number];
 	_dl_error_number = 0;
-	return retval;
+	return (char *)retval;
 }
 
 /*
@@ -571,24 +599,21 @@
 	fprintf(stderr, "List of loaded modules\n");
 	/* First start with a complete list of all of the loaded files. */
 	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
-		fprintf(stderr, "\t%x %x %x %s %d %s\n",
-				(unsigned) tpnt->loadaddr, (unsigned) tpnt,
-				(unsigned) tpnt->symbol_scope,
-				type[tpnt->libtype],
-				tpnt->usage_count, tpnt->libname);
+		fprintf(stderr, "\t%p %p %p %s %d %s\n",
+		        tpnt->loadaddr, tpnt, tpnt->symbol_scope,
+		        type[tpnt->libtype],
+		        tpnt->usage_count, tpnt->libname);
 	}
 
 	/* Next dump the module list for the application itself */
-	fprintf(stderr, "\nModules for application (%x):\n",
-			(unsigned) _dl_symbol_tables);
+	fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables);
 	for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
-		fprintf(stderr, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
+		fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
 
 	for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
-		fprintf(stderr, "Modules for handle %x\n", (unsigned) hpnt);
+		fprintf(stderr, "Modules for handle %p\n", hpnt);
 		for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
-			fprintf(stderr, "\t%x %s\n", (unsigned) rpnt->dyn,
-					rpnt->dyn->libname);
+			fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
 	}
 	return 0;
 }
@@ -606,7 +631,7 @@
 	pelf = NULL;
 
 #if 0
-	fprintf(stderr, "dladdr( %x, %x )\n", __address, __info);
+	fprintf(stderr, "dladdr( %p, %p )\n", __address, __info);
 #endif
 
 	for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
@@ -614,7 +639,7 @@
 
 		tpnt = rpnt;
 #if 0
-		fprintf(stderr, "Module \"%s\" at %x\n",
+		fprintf(stderr, "Module \"%s\" at %p\n",
 				tpnt->libname, tpnt->loadaddr);
 #endif
 		if (tpnt->loadaddr < (ElfW(Addr)) __address
@@ -633,15 +658,15 @@
 
 	{
 		char *strtab;
-		Elf32_Sym *symtab;
+		ElfW(Sym) *symtab;
 		int hn, si;
 		int sf;
 		int sn = 0;
 		ElfW(Addr) sa;
 
 		sa = 0;
-		symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
-		strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
+		symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
+		strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
 
 		sf = 0;
 		for (hn = 0; hn < pelf->nbucket; hn++) {
@@ -655,7 +680,7 @@
 					sf = 1;
 				}
 #if 0
-				fprintf(stderr, "Symbol \"%s\" at %x\n",
+				fprintf(stderr, "Symbol \"%s\" at %p\n",
 						strtab + symtab[si].st_name, symbol_addr);
 #endif
 			}

