diff options
author | Rich Felker <dalias@aerifal.cx> | 2012-03-23 00:28:20 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2012-03-23 00:28:20 -0400 |
commit | a9e85c0a5c690086c652f3a8ae9a109389f671a3 (patch) | |
tree | 9d8f357f2cac7385a85e8973dca3955d9cb578c9 /src/ldso/dynlink.c | |
parent | 494ba80e9a7f43be76dfee908bbd40ad0b608041 (diff) | |
download | musl-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.
Diffstat (limited to 'src/ldso/dynlink.c')
-rw-r--r-- | src/ldso/dynlink.c | 22 |
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"; } |