svn commit: branches/uClibc-nptl/ldso: include ldso libdl

carmelo at uclibc.org carmelo at uclibc.org
Fri Jan 18 16:21:36 UTC 2008


Author: carmelo
Date: 2008-01-18 08:21:35 -0800 (Fri, 18 Jan 2008)
New Revision: 20874

Log:
This patch solves a problem in dladdr caused by the wrong value
of elf_resolve's loadaddr field for the main application.

Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>


Modified:
   branches/uClibc-nptl/ldso/include/dl-hash.h
   branches/uClibc-nptl/ldso/ldso/dl-hash.c
   branches/uClibc-nptl/ldso/ldso/ldso.c
   branches/uClibc-nptl/ldso/libdl/libdl.c


Changeset:
Modified: branches/uClibc-nptl/ldso/include/dl-hash.h
===================================================================
--- branches/uClibc-nptl/ldso/include/dl-hash.h	2008-01-18 13:53:10 UTC (rev 20873)
+++ branches/uClibc-nptl/ldso/include/dl-hash.h	2008-01-18 16:21:35 UTC (rev 20874)
@@ -59,6 +59,7 @@
   unsigned int l_need_tls_init:1;
 #endif
 
+  ElfW(Addr) mapaddr;
   enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype;
   struct dyn_elf * symbol_scope;
   unsigned short usage_count;

Modified: branches/uClibc-nptl/ldso/ldso/dl-hash.c
===================================================================
--- branches/uClibc-nptl/ldso/ldso/dl-hash.c	2008-01-18 13:53:10 UTC (rev 20873)
+++ branches/uClibc-nptl/ldso/ldso/dl-hash.c	2008-01-18 16:21:35 UTC (rev 20874)
@@ -153,7 +153,7 @@
 		hash_addr += tpnt->nbucket;
 		tpnt->chains = hash_addr;
 	}
-	tpnt->loadaddr = (ElfW(Addr))loadaddr;
+	tpnt->loadaddr = tpnt->mapaddr = (ElfW(Addr))loadaddr;
 	for (i = 0; i < DYNAMIC_SIZE; i++)
 		tpnt->dynamic_info[i] = dynamic_info[i];
 	return tpnt;

Modified: branches/uClibc-nptl/ldso/ldso/ldso.c
===================================================================
--- branches/uClibc-nptl/ldso/ldso/ldso.c	2008-01-18 13:53:10 UTC (rev 20873)
+++ branches/uClibc-nptl/ldso/ldso/ldso.c	2008-01-18 16:21:35 UTC (rev 20874)
@@ -181,6 +181,7 @@
 			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp,
 			  char **argv)
 {
+	ElfW(Addr) app_loadaddr = NULL;
 	ElfW(Phdr) *ppnt;
 	ElfW(Dyn) *dpnt;
 	char *lpntstr;
@@ -329,6 +330,9 @@
 			relro_addr = ppnt->p_vaddr;
 			relro_size = ppnt->p_memsz;
 		}
+		if (!app_loadaddr && (ppnt->p_type == PT_LOAD)) {
+			app_loadaddr = ppnt->p_vaddr;
+		}
 		if (ppnt->p_type == PT_DYNAMIC) {
 			dpnt = (ElfW(Dyn) *) (ppnt->p_vaddr + app_tpnt->loadaddr);
 			_dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
@@ -366,6 +370,7 @@
 			_dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset(rpnt, 0, sizeof(struct dyn_elf));
 			rpnt->dyn = _dl_loaded_modules;
+			app_tpnt->mapaddr = app_loadaddr;
 			app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
 			app_tpnt->usage_count++;
 			app_tpnt->symbol_scope = _dl_symbol_tables;
@@ -873,7 +878,7 @@
 	 * ld.so.1, so we have to look up each symbol individually.
 	 */
 
-	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", _dl_symbol_tables, NULL, 0, NULL);	
+	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", _dl_symbol_tables, NULL, 0, NULL);
 	if (_dl_envp)
 		*_dl_envp = (unsigned long) envp;
 

Modified: branches/uClibc-nptl/ldso/libdl/libdl.c
===================================================================
--- branches/uClibc-nptl/ldso/libdl/libdl.c	2008-01-18 13:53:10 UTC (rev 20873)
+++ branches/uClibc-nptl/ldso/libdl/libdl.c	2008-01-18 16:21:35 UTC (rev 20874)
@@ -995,20 +995,18 @@
 	 */
 	pelf = NULL;
 
-#if 0
-	fprintf(stderr, "dladdr( %p, %p )\n", __address, __info);
-#endif
+	_dl_if_debug_print("dladdr( %p, %p )\n", __address, __info);
 
 	for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
 		struct elf_resolve *tpnt;
 
 		tpnt = rpnt;
-#if 0
-		fprintf(stderr, "Module \"%s\" at %p\n",
+
+		_dl_if_debug_print("Module \"%s\" at %p\n",
 				tpnt->libname, tpnt->loadaddr);
-#endif
-		if (tpnt->loadaddr < (ElfW(Addr)) __address
-				&& (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
+
+		if (tpnt->mapaddr < (ElfW(Addr)) __address
+				&& (pelf == NULL || pelf->mapaddr < tpnt->mapaddr)) {
 			pelf = tpnt;
 		}
 	}
@@ -1025,13 +1023,41 @@
 		char *strtab;
 		ElfW(Sym) *symtab;
 		unsigned int hn, si, sn, sf;
-		ElfW(Addr) sa;
+		ElfW(Addr) sa = 0;
 
-		sa = 0;
+		/* Set the info for the object the address lies in */
+		__info->dli_fname = pelf->libname;
+		__info->dli_fbase = (void *)(pelf->mapaddr);
+
 		symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
 		strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
 
 		sf = sn = 0;
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+		if (pelf->l_gnu_bitmask) {
+			for (hn = 0; hn < pelf->nbucket; hn++) {
+				si = pelf->l_gnu_buckets[hn];
+				if (!si)
+					continue;
+
+				const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
+				do {
+					ElfW(Addr) symbol_addr;
+
+					symbol_addr = (ElfW(Addr)) pelf->loadaddr + symtab[si].st_value;
+					if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
+						sa = symbol_addr;
+						sn = si;
+						sf = 1;
+					}
+
+					_dl_if_debug_print("Symbol \"%s\" at %p\n",
+									strtab + symtab[si].st_name, symbol_addr);
+					++si;
+				} while ((*hasharr++ & 1u) == 0);
+			}
+		} else
+#endif
 		for (hn = 0; hn < pelf->nbucket; hn++) {
 			for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
 				ElfW(Addr) symbol_addr;
@@ -1042,18 +1068,21 @@
 					sn = si;
 					sf = 1;
 				}
-#if 0
-				fprintf(stderr, "Symbol \"%s\" at %p\n",
+
+				_dl_if_debug_print("Symbol \"%s\" at %p\n",
 						strtab + symtab[si].st_name, symbol_addr);
-#endif
 			}
 		}
 
 		if (sf) {
-			__info->dli_fname = pelf->libname;
-			__info->dli_fbase = (void *)pelf->loadaddr;
+			/* A nearest symbol has been found; fill the entries */
 			__info->dli_sname = strtab + symtab[sn].st_name;
 			__info->dli_saddr = (void *)sa;
+		} else {
+			/* No symbol found, fill entries with NULL value,
+			only the containing object will be returned. */
+			__info->dli_sname = NULL;
+			__info->dli_saddr = NULL;
 		}
 		return 1;
 	}




More information about the uClibc-cvs mailing list