Index: git/ldso/include/dl-defs.h
===================================================================
--- git.orig/ldso/include/dl-defs.h	2012-01-11 10:04:31.488413714 -0800
+++ git/ldso/include/dl-defs.h	2012-01-11 10:05:01.664415259 -0800
@@ -233,7 +233,7 @@
 /* Similar to DL_LOADADDR_UNMAP, but used for libraries that have been
    dlopen()ed successfully, when they're dlclose()d.  */
 #ifndef DL_LIB_UNMAP
-# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->loadaddr, (LEN)))
+# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->mapaddr, (LEN)))
 #endif
 
 /* Define this to verify that a library named LIBNAME, whose ELF
Index: git/ldso/include/dl-elf.h
===================================================================
--- git.orig/ldso/include/dl-elf.h	2012-01-11 10:04:31.480413714 -0800
+++ git/ldso/include/dl-elf.h	2012-01-11 10:06:08.740418360 -0800
@@ -15,6 +15,7 @@
 /* Forward declarations for stuff defined in ld_hash.h */
 struct dyn_elf;
 struct elf_resolve;
+struct r_scope_elem;
 
 #include <dl-defs.h>
 #ifdef __LDSO_CACHE_SUPPORT__
@@ -32,16 +33,16 @@
 extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 	unsigned long rel_addr, unsigned long rel_size);
 extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-	unsigned long rel_addr, unsigned long rel_size);
+        struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size);
 extern struct elf_resolve * _dl_load_shared_library(int resolve_flags,
 	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
 	int trace_loaded_objects);
 extern struct elf_resolve * _dl_load_elf_shared_library(int resolve_flags,
-	struct dyn_elf **rpnt, char *libname);
+	struct dyn_elf **rpnt, const char *libname);
 extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
 	int trace_loaded_objects);
 extern int _dl_linux_resolve(void);
-extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag);
 extern void _dl_protect_relro (struct elf_resolve *l);
 
 /*
@@ -97,13 +98,15 @@
 # define ARCH_NUM 0
 #endif
 
-#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
+#define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM)
 /* Keep ARCH specific entries into dynamic section at the end of the array */
 #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
 /* GNU hash comes just after the relocation count */
 # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
+#else
+# define DT_GNU_HASH_IDX DT_RELCONT_IDX
 #endif
 
 extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
Index: git/ldso/include/dl-hash.h
===================================================================
--- git.orig/ldso/include/dl-hash.h	2012-01-11 10:04:31.496413707 -0800
+++ git/ldso/include/dl-hash.h	2012-01-11 10:05:01.664415259 -0800
@@ -30,6 +30,14 @@
   struct elf_resolve *tpnt;
 };
 
+/* Structure to describe a single list of scope elements.  The lookup
+   functions get passed an array of pointers to such structures.  */
+struct r_scope_elem {
+  struct elf_resolve **r_list; /* Array of maps for the scope.  */
+  unsigned int r_nlist;        /* Number of entries in the scope.  */
+  struct r_scope_elem *next;
+};
+
 struct elf_resolve {
   /* These entries must be in this order to be compatible with the interface used
      by gdb to obtain the list of symbols. */
@@ -66,7 +74,8 @@
 
   ElfW(Addr) mapaddr;
   enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype;
-  struct dyn_elf * symbol_scope;
+  /* This is the local scope of the shared object */
+  struct r_scope_elem symbol_scope;
   unsigned short usage_count;
   unsigned short int init_flag;
   unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */
@@ -133,6 +142,7 @@
 #define INIT_FUNCS_CALLED   0x000004
 #define FINI_FUNCS_CALLED   0x000008
 #define DL_OPENED	    0x000010
+#define DL_RESERVED	    0x000020
 
 extern struct dyn_elf     * _dl_symbol_tables;
 extern struct elf_resolve * _dl_loaded_modules;
@@ -142,7 +152,7 @@
 	DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info,
 	unsigned long dynamic_addr, unsigned long dynamic_size);
 
-extern char *_dl_find_hash(const char *name, struct dyn_elf *rpnt,
+extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
 		struct elf_resolve *mytpnt, int type_class,
 		struct symbol_ref *symbol);
 
Index: git/ldso/include/ldso.h
===================================================================
--- git.orig/ldso/include/ldso.h	2012-01-11 10:04:31.472413693 -0800
+++ git/ldso/include/ldso.h	2012-01-11 11:02:54.032583639 -0800
@@ -27,6 +27,7 @@
 /* Pull in compiler and arch stuff */
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stddef.h> /* for ptrdiff_t */
 #define _FCNTL_H
 #include <bits/fcntl.h>
 #include <bits/wordsize.h>
Index: git/ldso/ldso/dl-elf.c
===================================================================
--- git.orig/ldso/ldso/dl-elf.c	2012-01-11 10:04:31.424413768 -0800
+++ git/ldso/ldso/dl-elf.c	2012-01-11 10:05:01.664415259 -0800
@@ -445,7 +445,7 @@
  */
 
 struct elf_resolve *_dl_load_elf_shared_library(int resolve_flags,
-	struct dyn_elf **rpnt, char *libname)
+	struct dyn_elf **rpnt, const char *libname)
 {
 	ElfW(Ehdr) *epnt;
 	unsigned long dynamic_addr = 0;
@@ -466,7 +466,7 @@
 	size_t relro_size = 0;
 	struct stat st;
 	uint32_t *p32;
-	DL_LOADADDR_TYPE lib_loadaddr;
+	DL_LOADADDR_TYPE lib_loadaddr = 0;
 	DL_INIT_LOADADDR_EXTRA_DECLS
 
 	libaddr = 0;
@@ -528,7 +528,7 @@
 #ifdef MAGIC2
 				&& epnt->e_machine != MAGIC2
 #endif
-				))
+		))
 	{
 		_dl_internal_error_number =
 			(epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
@@ -641,12 +641,6 @@
 			char *tryaddr;
 			ssize_t size;
 
-			/* See if this is a PIC library. */
-			if (i == 0 && ppnt->p_vaddr > 0x1000000) {
-				piclib = 0;
-				/* flags |= MAP_FIXED; */
-			}
-
 			if (ppnt->p_flags & PF_W) {
 				status = map_writeable (infile, ppnt, piclib, flags, libaddr);
 				if (status == NULL)
@@ -677,7 +671,10 @@
 		ppnt++;
 	}
 
-	/* For a non-PIC library, the addresses are all absolute */
+	/*
+	 * The dynamic_addr must be take into acount lib_loadaddr value, to note
+	 * it is zero when the SO has been mapped to the elf's physical addr
+	 */
 	if (piclib) {
 		dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
 	}
@@ -744,11 +741,12 @@
 
 	tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
 			dynamic_addr, 0);
+	tpnt->mapaddr = tpnt->loadaddr;
 	tpnt->relro_addr = relro_addr;
 	tpnt->relro_size = relro_size;
 	tpnt->st_dev = st.st_dev;
 	tpnt->st_ino = st.st_ino;
-	tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff);
+	tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);
 	tpnt->n_phent = epnt->e_phnum;
 	tpnt->rtld_flags |= rtld_flags;
 
@@ -806,7 +804,6 @@
 	}
 #endif
 	(*rpnt)->dyn = tpnt;
-	tpnt->symbol_scope = _dl_symbol_tables;
 	tpnt->usage_count++;
 	tpnt->libtype = elf_lib;
 
@@ -906,7 +903,7 @@
 }
 
 /* now_flag must be RTLD_NOW or zero */
-int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
+int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
 {
 	int goof = 0;
 	struct elf_resolve *tpnt;
@@ -914,7 +911,7 @@
 	ElfW(Addr) reloc_addr;
 
 	if (rpnt->next)
-		goof = _dl_fixup(rpnt->next, now_flag);
+		goof = _dl_fixup(rpnt->next, scope, now_flag);
 	if (goof)
 		return goof;
 	tpnt = rpnt->dyn;
@@ -944,7 +941,7 @@
 			elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
 			reloc_addr += relative_count * sizeof(ELF_RELOC);
 		}
-		goof += _dl_parse_relocation_information(rpnt,
+		goof += _dl_parse_relocation_information(rpnt, scope,
 				reloc_addr,
 				reloc_size);
 		tpnt->init_flag |= RELOCS_DONE;
@@ -960,7 +957,7 @@
 					tpnt->dynamic_info[DT_JMPREL],
 					tpnt->dynamic_info [DT_PLTRELSZ]);
 		} else {
-			goof += _dl_parse_relocation_information(rpnt,
+			goof += _dl_parse_relocation_information(rpnt, scope,
 					tpnt->dynamic_info[DT_JMPREL],
 					tpnt->dynamic_info[DT_PLTRELSZ]);
 		}
Index: git/ldso/ldso/dl-hash.c
===================================================================
--- git.orig/ldso/ldso/dl-hash.c	2012-01-11 10:04:31.416413769 -0800
+++ git/ldso/ldso/dl-hash.c	2012-01-11 10:05:01.668415211 -0800
@@ -146,7 +146,6 @@
 		tpnt->chains = hash_addr;
 	}
 	tpnt->loadaddr = loadaddr;
-	tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0);
 	for (i = 0; i < DYNAMIC_SIZE; i++)
 		tpnt->dynamic_info[i] = dynamic_info[i];
 	return tpnt;
@@ -268,16 +267,18 @@
  * This function resolves externals, and this is either called when we process
  * relocations or when we call an entry in the PLT table for the first time.
  */
-char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt,
+char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
 	int type_class, struct symbol_ref *sym_ref)
 {
 	struct elf_resolve *tpnt = NULL;
 	ElfW(Sym) *symtab;
+	int i = 0;
 
 	unsigned long elf_hash_number = 0xffffffff;
 	const ElfW(Sym) *sym = NULL;
 
 	char *weak_result = NULL;
+	struct r_scope_elem *loop_scope;
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
 	unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
@@ -288,57 +289,64 @@
 		if (mytpnt)
 			tpnt = mytpnt;
 	} else
-	for (; rpnt; rpnt = rpnt->next) {
-		tpnt = rpnt->dyn;
-
-		if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
-			if (mytpnt == tpnt)
-				;
-			else {
-				struct init_fini_list *tmp;
-
-				for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
-					if (tmp->tpnt == tpnt)
-						break;
+	for (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) {
+		for (i = 0; i < loop_scope->r_nlist; i++) {
+			tpnt = loop_scope->r_list[i];
+
+			if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) {
+				if (mytpnt == tpnt)
+					;
+				else {
+					struct init_fini_list *tmp;
+
+					for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) {
+						if (tmp->tpnt == tpnt)
+							break;
+					}
+					if (!tmp)
+						continue;
 				}
-				if (!tmp)
-					continue;
 			}
-		}
-		/* Don't search the executable when resolving a copy reloc. */
-		if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
-			continue;
-
-		/* If the hash table is empty there is nothing to do here.  */
-		if (tpnt->nbucket == 0)
-			continue;
+			/* Don't search the executable when resolving a copy reloc. */
+			if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+				continue;
+
+			/* If the hash table is empty there is nothing to do here.  */
+			if (tpnt->nbucket == 0)
+				continue;
 
-		symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
+			symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
-		/* Prefer GNU hash style, if any */
-		if (tpnt->l_gnu_bitmask) {
-			sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
-			if (sym != NULL)
-				/* If sym has been found, do not search further */
-				break;
-		} else {
+			/* Prefer GNU hash style, if any */
+			if (tpnt->l_gnu_bitmask) {
+				sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
+				if (sym != NULL)
+					/* If sym has been found, do not search further */
+					goto end_search;
+			} else {
 #endif
-		/* Use the old SysV-style hash table */
-
-		/* Calculate the old sysv hash number only once */
-		if (elf_hash_number == 0xffffffff)
-			elf_hash_number = _dl_elf_hash((const unsigned char *)name);
+				/* Use the old SysV-style hash table */
 
-		sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
-		if (sym != NULL)
-			break;
+				/* Calculate the old sysv hash number only once */
+				if (elf_hash_number == 0xffffffff)
+					elf_hash_number = _dl_elf_hash((const unsigned char *)name);
+
+				sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
+				if (sym != NULL)
+					/* If sym has been found, do not search further */
+					goto end_search;
 #ifdef __LDSO_GNU_HASH_SUPPORT__
-		}
+			}
 #endif
-	} /* end of for (; rpnt; rpnt = rpnt->next) { */
-
+		} /* End of inner for */
+	}
+end_search:
 	if (sym) {
+		if (sym_ref) {
+		//	sym_ref->sym = sym;
+		//	sym_ref->tpnt = tpnt;
+		}
 		/* At this point we have found the requested symbol, do binding */
 #if defined(USE_TLS) && USE_TLS
 		if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
Index: git/ldso/ldso/dl-startup.c
===================================================================
--- git.orig/ldso/ldso/dl-startup.c	2012-01-11 10:04:31.452413731 -0800
+++ git/ldso/ldso/dl-startup.c	2012-01-11 11:05:15.296590221 -0800
@@ -164,8 +164,11 @@
 		aux_dat += 2;
 	}
 
-	/* locate the ELF header.   We need this done as soon as possible
-	 * (esp since SEND_STDERR() needs this on some platforms... */
+	/*
+	 * Locate the dynamic linker 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();
 	DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val);
@@ -183,7 +186,7 @@
 		_dl_exit(0);
 	}
 	SEND_EARLY_STDERR_DEBUG("ELF header=");
-	SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(load_addr), 1);
+	SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(header), 1);
 
 	/* Locate the global offset table.  Since this code must be PIC
 	 * we can take advantage of the magic offset register, if we
@@ -192,7 +195,7 @@
 	DL_BOOT_COMPUTE_GOT(got);
 
 	/* Now, finally, fix up the location of the dynamic stuff */
-	DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr);
+	DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)header);
 
 	SEND_EARLY_STDERR_DEBUG("First Dynamic section entry=");
 	SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
@@ -321,7 +324,7 @@
 
 	__rtld_stack_end = (void *)(argv - 1);
 
-	_dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv
+	_dl_get_ready_to_run(tpnt, (DL_LOADADDR_TYPE) header, auxvt, envp, argv
 			     DL_GET_READY_TO_RUN_EXTRA_ARGS);
 
 	/* Transfer control to the application.  */
Index: git/ldso/ldso/i386/elfinterp.c
===================================================================
--- git.orig/ldso/ldso/i386/elfinterp.c	2012-01-11 10:04:31.436413641 -0800
+++ git/ldso/ldso/i386/elfinterp.c	2012-01-11 10:05:01.668415211 -0800
@@ -71,7 +71,7 @@
 	got_addr = (char **)instr_addr;
 
 	/* Get the address of the GOT entry. */
-	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
 	if (unlikely(!new_addr)) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
 		_dl_exit(1);
@@ -98,9 +98,9 @@
 }
 
 static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 	  unsigned long rel_addr, unsigned long rel_size,
-	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope,
+	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 			   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
 {
 	unsigned int i;
@@ -156,7 +156,7 @@
 }
 
 static int
-_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
 	int reloc_type;
@@ -196,7 +196,6 @@
 		tls_tpnt = tpnt;
 	}
 	
-
 #if defined (__SUPPORT_LD_DEBUG__)
 	old_val = *reloc_addr;
 #endif
@@ -266,7 +265,7 @@
 }
 
 static int
-_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
+_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 		  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
 	int reloc_type;
@@ -315,8 +314,9 @@
 
 int
 _dl_parse_relocation_information(struct dyn_elf *rpnt,
+				 struct r_scope_elem *scope,
 				 unsigned long rel_addr,
 				 unsigned long rel_size)
 {
-	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
 }
Index: git/ldso/ldso/ldso.c
===================================================================
--- git.orig/ldso/ldso/ldso.c	2012-01-11 10:04:31.460413711 -0800
+++ git/ldso/ldso/ldso.c	2012-01-11 11:02:31.404582943 -0800
@@ -70,8 +70,8 @@
 int   _dl_debug_file      = 2;
 #endif
 
-/* Needed for standalone execution. */
 unsigned long attribute_hidden _dl_skip_args = 0;
+
 const char *_dl_progname = UCLIBC_LDSO;      /* The name of the executable being run */
 #include "dl-startup.c"
 #include "dl-symbols.c"
@@ -97,6 +97,7 @@
 static unsigned char *_dl_mmap_zero   = NULL;	/* Also used by _dl_malloc */
 
 static struct elf_resolve **init_fini_list;
+static struct elf_resolve **scope_elem_list;
 static unsigned int nlist; /* # items in init_fini_list */
 extern void _start(void);
 
@@ -285,20 +286,78 @@
        }
 }
 
+static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
+									 DL_LOADADDR_TYPE load_addr,
+									 ElfW(auxv_t) auxvt[AT_EGID + 1],
+									 struct dyn_elf *rpnt)
+{
+		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+		ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
+								DL_RELOC_ADDR(load_addr, epnt->e_phoff);
+		int j;
+		struct stat st;
+
+		tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr,
+					      tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
+					      0);
+
+		tpnt->mapaddr = load_addr;
+		if (_dl_stat(tpnt->libname, &st) >= 0) {
+			tpnt->st_dev = st.st_dev;
+			tpnt->st_ino = st.st_ino;
+		}
+		tpnt->n_phent = epnt->e_phnum;
+		tpnt->ppnt = myppnt;
+		for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
+			if (myppnt->p_type ==  PT_GNU_RELRO) {
+				tpnt->relro_addr = myppnt->p_vaddr;
+				tpnt->relro_size = myppnt->p_memsz;
+				break;
+			}
+		}
+		tpnt->libtype = program_interpreter;
+		if (rpnt) {
+			rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
+			rpnt->next->prev = rpnt;
+			rpnt = rpnt->next;
+		} else {
+			rpnt = _dl_zalloc(sizeof(struct dyn_elf));
+		}
+		rpnt->dyn = tpnt;
+		tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
+
+	return tpnt;
+}
+
+static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
+										struct elf_resolve *map)
+{
+	struct elf_resolve **p = list;
+	struct init_fini_list *q;
+
+	*p++ = map;
+	map->init_flag |= DL_RESERVED;
+	if (map->init_fini)
+		for (q = map->init_fini; q; q = q->next)
+			if (! (q->tpnt->init_flag & DL_RESERVED))
+				p += _dl_build_local_scope (p, q->tpnt);
+	return p - list;
+}
+
 void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
-			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp,
-			  char **argv
+			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
 			  DL_GET_READY_TO_RUN_EXTRA_PARMS)
 {
 	ElfW(Addr) app_mapaddr = 0;
 	ElfW(Phdr) *ppnt;
 	ElfW(Dyn) *dpnt;
 	char *lpntstr;
-	unsigned int i;
+	unsigned int i, cnt, nscope_elem;
 	int unlazy = 0, trace_loaded_objects = 0;
 	struct dyn_elf *rpnt;
 	struct elf_resolve *tcurr;
 	struct elf_resolve *tpnt1;
+	struct elf_resolve *ldso_tpnt = NULL;
 	struct elf_resolve app_tpnt_tmp;
 	struct elf_resolve *app_tpnt = &app_tpnt_tmp;
 	struct r_debug *debug_addr;
@@ -306,7 +365,9 @@
 	unsigned long *_dl_envp;		/* The environment address */
 	ElfW(Addr) relro_addr = 0;
 	size_t relro_size = 0;
-	struct stat st;
+	struct r_scope_elem *global_scope;
+	struct elf_resolve **local_scope;
+
 #if defined(USE_TLS) && USE_TLS
 	void *tcbp = NULL;
 #endif
@@ -337,7 +398,7 @@
 	_dl_setup_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_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
 		_dl_exit(1);
 	}
 
@@ -391,6 +452,7 @@
 	_dl_init_static_tls = &_dl_nothread_init_static_tls;
 #endif
 
+
 	/* At this point we are now free to examine the user application,
 	 * and figure out which libraries are supposed to be called.  Until
 	 * we have this list, we will not be completely ready for dynamic
@@ -478,7 +540,6 @@
 			app_tpnt->mapaddr = app_mapaddr;
 			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]);
 #ifdef ALLOW_ZERO_PLTGOT
 			if (lpnt)
@@ -539,11 +600,11 @@
 	 * case the executable is actually an ET_DYN object.
 	 */
 	if (app_tpnt->l_tls_initimage != NULL) {
+		unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
 		app_tpnt->l_tls_initimage =
 			(char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
 		_dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
-			(unsigned int)app_tpnt->l_tls_initimage,
-			app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
+			tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
 	}
 #endif
 
@@ -786,12 +847,19 @@
 
 				lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
 				name = _dl_get_last_path_component(lpntstr);
-				if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
-					continue;
-
 				_dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", lpntstr, _dl_progname);
 
-				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))	{
+				if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
+						if (!ldso_tpnt) {
+							/* Insert the ld.so only once */
+							ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
+						}
+						ldso_tpnt->usage_count++;
+						tpnt1 = ldso_tpnt;
+				} else
+					tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects);
+
+				if (!tpnt1) {
 #ifdef __LDSO_LDD_SUPPORT__
 					if (trace_loaded_objects) {
 						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
@@ -826,12 +894,18 @@
 	}
 	_dl_unmap_cache();
 
-	--nlist; /* Exclude the application. */
+	/* Keep track of the number of elements in the global scope */
+	nscope_elem = nlist;
+
+	if (_dl_loaded_modules->libtype == elf_executable) {
+		--nlist; /* Exclude the application. */
+		tcurr = _dl_loaded_modules->next;
+	} else
+		tcurr = _dl_loaded_modules;
 	init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
 	i = 0;
-	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+	for (; tcurr; tcurr = tcurr->next)
 		init_fini_list[i++] = tcurr;
-	}
 
 	/* Sort the INIT/FINI list in dependency order. */
 	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
@@ -877,50 +951,13 @@
 	 * functions in the dynamic linker and to relocate the interpreter
 	 * again once all libs are loaded.
 	 */
-	if (tpnt) {
-		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
-		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff);
-		int j;
-#ifdef __DSBT__
-		struct elf_resolve *ref = _dl_loaded_modules;
-		_dl_if_debug_dprint("ref is %x, dsbt %x, ref-dsbt %x size %x\n",
-				    ref, tpnt->loadaddr.map->dsbt_table,
-				    ref->loadaddr.map->dsbt_table,
-				    tpnt->loadaddr.map->dsbt_size);
-
-		_dl_memcpy(tpnt->loadaddr.map->dsbt_table, ref->loadaddr.map->dsbt_table,
-			   tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
-#endif
-		tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr,
-					      tpnt->dynamic_info,
-					      (unsigned long)tpnt->dynamic_addr,
-					      0);
-
-		if (_dl_stat(tpnt->libname, &st) >= 0) {
-			tpnt->st_dev = st.st_dev;
-			tpnt->st_ino = st.st_ino;
-		}
-		tpnt->n_phent = epnt->e_phnum;
-		tpnt->ppnt = myppnt;
-		for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
-			if (myppnt->p_type ==  PT_GNU_RELRO) {
-				tpnt->relro_addr = myppnt->p_vaddr;
-				tpnt->relro_size = myppnt->p_memsz;
-				break;
-			}
-		}
-		tpnt->libtype = program_interpreter;
+	if (!ldso_tpnt) {
+		tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
 		tpnt->usage_count++;
-		tpnt->symbol_scope = _dl_symbol_tables;
-		if (rpnt) {
-			rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
-			rpnt->next->prev = rpnt;
-			rpnt = rpnt->next;
-		} else {
-			rpnt = _dl_zalloc(sizeof(struct dyn_elf));
-		}
-		rpnt->dyn = tpnt;
-		tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
+		nscope_elem++;
+	} else
+		tpnt = ldso_tpnt;
+
 #ifdef RERELOCATE_LDSO
 		/* Only rerelocate functions for now. */
 		tpnt->init_flag = RELOCS_DONE;
@@ -933,16 +970,44 @@
 		tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
 #endif
 		tpnt = NULL;
+
+	/*
+	 * Allocate the global scope array.
+	 */
+	scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+
+	for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
+		scope_elem_list[i++] = tcurr;
+
+	_dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
+	_dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
+	/*
+	 * The symbol scope of the application, that is the first entry of the
+	 * _dl_loaded_modules list, is just the global scope to be used for the
+	 * symbol lookup.
+	 */
+	global_scope = &_dl_loaded_modules->symbol_scope;
+
+	/* Build the local scope for each loaded modules. */
+	local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+	i = 1;
+	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+		unsigned int k;
+		cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
+		tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+		tcurr->symbol_scope.r_nlist = cnt;
+		_dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
+		/* Restoring the init_flag.*/
+		for (k = 1; k < nscope_elem; k++)
+			scope_elem_list[k]->init_flag &= ~DL_RESERVED;
 	}
 
+	_dl_free(local_scope);
+
 #ifdef __LDSO_LDD_SUPPORT__
-	/* End of the line for ldd.... */
-	if (trace_loaded_objects) {
-		_dl_dprintf(1, "\t%s => %s (%x)\n",
-			    rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1,
-			    rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr));
+	/* Exit if LD_TRACE_LOADED_OBJECTS is on. */
+	if (trace_loaded_objects)
 		_dl_exit(0);
-	}
 #endif
 
 #if defined(USE_TLS) && USE_TLS
@@ -990,7 +1055,7 @@
 	 * order so that COPY directives work correctly.
 	 */
 	if (_dl_symbol_tables)
-		if (_dl_fixup(_dl_symbol_tables, unlazy))
+		if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
 			_dl_exit(-1);
 
 	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
@@ -1027,7 +1092,7 @@
 	 * ld.so.1, so we have to look up each symbol individually.
 	 */
 
-	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", _dl_symbol_tables, NULL, 0, NULL);
+	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
 	if (_dl_envp)
 		*_dl_envp = (unsigned long) envp;
 
@@ -1083,21 +1148,21 @@
 
 	/* Find the real malloc function and make ldso functions use that from now on */
 	_dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
-			_dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+			global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #if defined(USE_TLS) && USE_TLS
 	/* Find the real functions and make ldso functions use them from now on */
 	_dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
-		_dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+		_dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 	_dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
-		_dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+		_dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 	_dl_free_function = (void (*)(void *)) (intptr_t)
-		_dl_find_hash(__C_SYMBOL_PREFIX__ "free", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+		_dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 	_dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
-		_dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+		_dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
 
 #endif
 
Index: git/ldso/libdl/libdl.c
===================================================================
--- git.orig/ldso/libdl/libdl.c	2012-01-11 10:04:31.508413705 -0800
+++ git/ldso/libdl/libdl.c	2012-01-11 10:05:01.668415211 -0800
@@ -55,7 +55,7 @@
 
 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,
 	struct elf_resolve *, char *, int);
-extern int _dl_fixup(struct dyn_elf *rpnt, int lazy);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);
 extern void _dl_protect_relro(struct elf_resolve * tpnt);
 extern int _dl_errno;
 extern struct dyn_elf *_dl_symbol_tables;
@@ -271,6 +271,21 @@
 	}
 }
 
+static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
+	struct elf_resolve *map)
+{
+	struct elf_resolve **p = list;
+	struct init_fini_list *q;
+
+	*p++ = map;
+	map->init_flag |= DL_RESERVED;
+	if (map->init_fini)
+		for (q = map->init_fini; q; q = q->next)
+			if (! (q->tpnt->init_flag & DL_RESERVED))
+				p += _dl_build_local_scope (p, q->tpnt);
+	return p - list;
+}
+
 void *dlopen(const char *libname, int flag)
 {
 	struct elf_resolve *tpnt, *tfrom;
@@ -283,6 +298,8 @@
 	unsigned int nlist, i;
 	struct elf_resolve **init_fini_list;
 	static bool _dl_init;
+	struct elf_resolve **local_scope;
+	struct r_scope_elem *ls;
 #if defined(USE_TLS) && USE_TLS
 	bool any_tls = false;
 #endif
@@ -459,6 +476,23 @@
 		}
 
 	}
+	/* Build the local scope for the dynamically loaded modules. */
+	local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */
+	for (i = 0; i < nlist; i++)
+		if (init_fini_list[i]->symbol_scope.r_nlist == 0) {
+			int k, cnt;
+			cnt = _dl_build_local_scope(local_scope, init_fini_list[i]);
+			init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+			init_fini_list[i]->symbol_scope.r_nlist = cnt;
+			_dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope,
+					cnt * sizeof (struct elf_resolve *));
+			/* Restoring the init_flag.*/
+			for (k = 0; k < nlist; k++)
+				init_fini_list[k]->init_flag &= ~DL_RESERVED;
+		}
+
+	_dl_free(local_scope);
+
 	/* Sort the INIT/FINI list in dependency order. */
 	for (runp2 = dep_list; runp2; runp2 = runp2->next) {
 		unsigned int j, k;
@@ -506,8 +540,13 @@
 	 */
 	_dl_perform_mips_global_got_relocations(tpnt, !now_flag);
 #endif
+	/* Get the tail of the list */
+	for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
 
-	if (_dl_fixup(dyn_chain, now_flag))
+	/* Extend the global scope by adding the local scope of the dlopened DSO. */
+	ls->next = &dyn_chain->dyn->symbol_scope;
+
+	if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
 		goto oops;
 
 	if (relro_ptr) {
@@ -668,10 +707,10 @@
 	tpnt = NULL;
 	if (handle == _dl_symbol_tables)
 		tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
-	ret = _dl_find_hash(name2, handle, tpnt, ELF_RTYPE_CLASS_DLSYM, &sym_ref);
+	ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, &sym_ref);
 
 #if defined(USE_TLS) && USE_TLS && defined SHARED
-	if (sym_ref.tpnt) {
+	if (sym_ref.sym && (ELF_ST_TYPE(sym_ref.sym->st_info) == STT_TLS) && (sym_ref.tpnt)) {
 		/* The found symbol is a thread-local storage variable.
 		Return its address for the current thread.  */
 		ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
@@ -709,6 +748,7 @@
 	struct dyn_elf *handle;
 	unsigned int end;
 	unsigned int i, j;
+	struct r_scope_elem *ls;
 #if defined(USE_TLS) && USE_TLS
 	bool any_tls = false;
 	size_t tls_free_start = NO_TLS_OFFSET;
@@ -874,7 +914,7 @@
 			}
 #endif
 
-			DL_LIB_UNMAP (tpnt, end);
+			DL_LIB_UNMAP (tpnt, end - tpnt->mapaddr);
 			/* Free elements in RTLD_LOCAL scope list */
 			for (runp = tpnt->rtld_local; runp; runp = tmp) {
 				tmp = runp->next;
@@ -898,6 +938,16 @@
 				}
 			}
 
+			if (handle->dyn == tpnt) {
+				/* Unlink the local scope from global one */
+				for (ls = &_dl_loaded_modules->symbol_scope; ls; ls = ls->next)
+					if (ls->next->r_list[0] == tpnt) {
+						_dl_if_debug_print("removing symbol_scope: %s\n", tpnt->libname);
+						break;
+					}
+				ls->next = ls->next->next;
+			}
+
 			/* Next, remove tpnt from the global symbol table list */
 			if (_dl_symbol_tables) {
 				if (_dl_symbol_tables->dyn == tpnt) {
@@ -919,6 +969,7 @@
 				}
 			}
 			free(tpnt->libname);
+			free(tpnt->symbol_scope.r_list);
 			free(tpnt);
 		}
 	}
