about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-06-26 21:21:04 -0400
committerRich Felker <dalias@aerifal.cx>2011-06-26 21:21:04 -0400
commit92ab5d8d156545ab0daff6062d7a519861684fb6 (patch)
tree0e9815a77c5f6ba283ae72704eaea339e82fa8db /src
parent59ab43f5f8dbd1baf98d3c483c723d155b6f95c8 (diff)
downloadmusl-92ab5d8d156545ab0daff6062d7a519861684fb6.tar.gz
musl-92ab5d8d156545ab0daff6062d7a519861684fb6.tar.xz
musl-92ab5d8d156545ab0daff6062d7a519861684fb6.zip
fix resolving symbols in objects loaded in RTLD_LOCAL mode
basically we temporarily make the library and all its dependencies
part of the global namespace but only for the duration of performing
relocations, then return them to their former state.
Diffstat (limited to 'src')
-rw-r--r--src/ldso/dynlink.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 35ff9626..305d70e0 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -493,6 +493,9 @@ void *dlopen(const char *file, int mode)
 
 	if (setjmp(rtld_fail)) {
 		/* Clean up anything new that was (partially) loaded */
+		if (p->deps) for (i=0; p->deps[i]; i++)
+			if (p->deps[i]->global < 0)
+				p->deps[i]->global = 0;
 		for (p=orig_tail->next; p; p=next) {
 			next = p->next;
 			munmap(p->map, p->map_len);
@@ -511,7 +514,15 @@ void *dlopen(const char *file, int mode)
 	/* First load handling */
 	if (!p->deps) {
 		load_deps(p);
+		for (i=0; p->deps[i]; i++)
+			if (!p->deps[i]->global)
+				p->deps[i]->global = -1;
+		if (!p->global) p->global = -1;
 		reloc_all(p);
+		for (i=0; p->deps[i]; i++)
+			if (p->deps[i]->global < 0)
+				p->deps[i]->global = 0;
+		if (p->global < 0) p->global = 0;
 	}
 
 	if (mode & RTLD_GLOBAL) {