summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ldso/dynlink.c32
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;