about summary refs log tree commit diff
path: root/src/ldso/dynlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldso/dynlink.c')
-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;