about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-03-23 00:28:20 -0400
committerRich Felker <dalias@aerifal.cx>2012-03-23 00:28:20 -0400
commita9e85c0a5c690086c652f3a8ae9a109389f671a3 (patch)
tree9d8f357f2cac7385a85e8973dca3955d9cb578c9
parent494ba80e9a7f43be76dfee908bbd40ad0b608041 (diff)
downloadmusl-a9e85c0a5c690086c652f3a8ae9a109389f671a3.tar.gz
musl-a9e85c0a5c690086c652f3a8ae9a109389f671a3.tar.xz
musl-a9e85c0a5c690086c652f3a8ae9a109389f671a3.zip
make dlerror conform to posix
the error status is required to be sticky after failure of dlopen or
dlsym until cleared by dlerror. applications and especially libraries
should never rely on this since it is not thread-safe and subject to
race conditions, but glib does anyway.
-rw-r--r--src/ldso/dynlink.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 6ff8850c..e0013ec0 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -1,4 +1,3 @@
-#ifdef __PIC__
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -18,6 +17,10 @@
 #include <ctype.h>
 #include <dlfcn.h>
 
+static int errflag;
+
+#ifdef __PIC__
+
 #include "reloc.h"
 
 #if ULONG_MAX == 0xffffffff
@@ -631,12 +634,13 @@ void *dlopen(const char *file, int mode)
 		tail = orig_tail;
 		tail->next = 0;
 		p = 0;
+	} else p = load_library(file);
+
+	if (!p) {
+		errflag = 1;
 		goto end;
 	}
 
-	p = load_library(file);
-	if (!p) goto end;
-
 	/* First load handling */
 	if (!p->deps) {
 		load_deps(p);
@@ -674,8 +678,11 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
 		if (!p) p=head;
 		p=p->next;
 	}
-	if (p == head || p == RTLD_DEFAULT)
-		return find_sym(head, s, 0);
+	if (p == head || p == RTLD_DEFAULT) {
+		void *res = find_sym(head, s, 0);
+		if (!res) errflag = 1;
+		return res;
+	}
 	h = hash(s);
 	sym = lookup(s, h, p->syms, p->hashtab, p->strings);
 	if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
@@ -686,6 +693,7 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
 		if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
 			return p->deps[i]->base + sym->st_value;
 	}
+	errflag = 1;
 	return 0;
 }
 
@@ -710,6 +718,8 @@ void *__dlsym(void *p, const char *s, void *ra)
 
 char *dlerror()
 {
+	if (!errflag) return 0;
+	errflag = 0;
 	return "unknown error";
 }