diff options
| -rw-r--r-- | ldso/include/dl-hash.h | 1 | ||||
| -rw-r--r-- | ldso/ldso/dl-hash.c | 2 | ||||
| -rw-r--r-- | ldso/ldso/ldso.c | 7 | ||||
| -rw-r--r-- | ldso/libdl/libdl.c | 59 | 
4 files changed, 52 insertions, 17 deletions
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index fb75c8611..758767f4d 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -59,6 +59,7 @@ struct elf_resolve {    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; diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 971b1842c..ff4f22a6f 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -153,7 +153,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  		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; diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 738b970f4..39e56f8a7 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -181,6 +181,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			  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 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			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 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			_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 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  	 * 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; diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index e4f564bc2..c5033df2d 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -995,20 +995,18 @@ int dladdr(const void *__address, Dl_info * __info)  	 */  	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 @@ int dladdr(const void *__address, Dl_info * __info)  		char *strtab;  		ElfW(Sym) *symtab;  		unsigned int hn, si, sn, sf; -		ElfW(Addr) sa; +		ElfW(Addr) sa = 0; + +		/* Set the info for the object the address lies in */ +		__info->dli_fname = pelf->libname; +		__info->dli_fbase = (void *)(pelf->mapaddr); -		sa = 0;  		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 @@ int dladdr(const void *__address, Dl_info * __info)  					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;  	}  | 
