diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ldso/dynlink.c | 32 | 
1 files changed, 28 insertions, 4 deletions
| diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 0c3b36ce..cab30089 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1543,8 +1543,10 @@ _Noreturn void __dls3(size_t *sp)  		if (!app.loadmap) {  			app.loadmap = (void *)&app_dummy_loadmap;  			app.loadmap->nsegs = 1; -			app.loadmap->segs[0].addr = (size_t)app.base; -			app.loadmap->segs[0].p_memsz = -1; +			app.loadmap->segs[0].addr = (size_t)app.map; +			app.loadmap->segs[0].p_vaddr = (size_t)app.map +				- (size_t)app.base; +			app.loadmap->segs[0].p_memsz = app.map_len;  		}  		argv[-3] = (void *)app.loadmap;  	} @@ -1738,6 +1740,28 @@ static int invalid_dso_handle(void *h)  	return 1;  } +static void *addr2dso(size_t a) +{ +	struct dso *p; +	for (p=head; p; p=p->next) { +		if (DL_FDPIC && p->loadmap) { +			size_t i; +			for (i=0; i<p->loadmap->nsegs; i++) { +				if (a-p->loadmap->segs[i].p_vaddr +				    < p->loadmap->segs[i].p_memsz) +					return p; +			} +			i = count_syms(p); +			if (a-(size_t)p->funcdescs < i*sizeof(*p->funcdescs)) +				return p; +		} else { +			if (a-(size_t)p->map < p->map_len) +				return p; +		} +	} +	return 0; +} +  void *__tls_get_addr(size_t *);  static void *do_dlsym(struct dso *p, const char *s, void *ra) @@ -1749,7 +1773,7 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)  		if (p == RTLD_DEFAULT) {  			p = head;  		} else if (p == RTLD_NEXT) { -			for (p=head; p && (unsigned char *)ra-p->map>p->map_len; p=p->next); +			p = addr2dso((size_t)ra);  			if (!p) p=head;  			p = p->next;  		} @@ -1806,7 +1830,7 @@ int __dladdr(const void *addr, Dl_info *info)  	char *bestname;  	pthread_rwlock_rdlock(&lock); -	for (p=head; p && (unsigned char *)addr-p->map>p->map_len; p=p->next); +	p = addr2dso((size_t)addr);  	pthread_rwlock_unlock(&lock);  	if (!p) return 0; | 
