X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fldso%2Fdynlink.c;h=e0013ec0eecfe698dd717135e79cb55b44214e78;hp=28b86bf761c81d3451494b164d07c87c3c2bcbf9;hb=a9e85c0a5c690086c652f3a8ae9a109389f671a3;hpb=fd7015d0c23edb9ae655e5ce3677f980f0cb1143 diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 28b86bf7..e0013ec0 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1,4 +1,3 @@ -#ifdef __PIC__ #include #include #include @@ -18,6 +17,10 @@ #include #include +static int errflag; + +#ifdef __PIC__ + #include "reloc.h" #if ULONG_MAX == 0xffffffff @@ -47,8 +50,9 @@ struct dso size_t map_len; dev_t dev; ino_t ino; - int global; - int relocated; + char global; + char relocated; + char constructed; struct dso **deps; char *name; char buf[]; @@ -471,6 +475,20 @@ static size_t find_dyn(Phdr *ph, size_t cnt, size_t stride) return 0; } +static void do_init_fini(struct dso *p) +{ + size_t dyn[DYN_CNT] = {0}; + for (; p; p=p->prev) { + if (p->constructed) return; + decode_vec(p->dynv, dyn, DYN_CNT); + if (dyn[0] & (1<base + dyn[DT_FINI])); + if (dyn[0] & (1<base + dyn[DT_INIT]))(); + p->constructed = 1; + } +} + void *__dynlink(int argc, char **argv) { size_t *auxv, aux[AUX_CNT] = {0}; @@ -520,6 +538,7 @@ void *__dynlink(int argc, char **argv) } app->name = argv[0]; app->global = 1; + app->constructed = 1; app->dynv = (void *)(app->base + find_dyn( (void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT])); decode_dyn(app); @@ -577,6 +596,9 @@ void *__dynlink(int argc, char **argv) * error. If the dynamic loader (dlopen) will not be used, free * all memory used by the dynamic linker. */ runtime = 1; + + do_init_fini(tail); + if (!rtld_used) { free_all(head); free(sys_path); @@ -591,9 +613,11 @@ void *dlopen(const char *file, int mode) { struct dso *volatile p, *orig_tail = tail, *next; size_t i; + int cs; if (!file) return head; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); pthread_rwlock_wrlock(&lock); if (setjmp(rtld_fail)) { @@ -609,12 +633,13 @@ void *dlopen(const char *file, int mode) } tail = orig_tail; tail->next = 0; - pthread_rwlock_unlock(&lock); - return 0; - } + p = 0; + } else p = load_library(file); - p = load_library(file); - if (!p) goto end; + if (!p) { + errflag = 1; + goto end; + } /* First load handling */ if (!p->deps) { @@ -636,8 +661,10 @@ void *dlopen(const char *file, int mode) p->global = 1; } + do_init_fini(tail); end: pthread_rwlock_unlock(&lock); + pthread_setcancelstate(cs, 0); return p; } @@ -651,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)) @@ -663,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; } @@ -674,9 +705,21 @@ void *__dlsym(void *p, const char *s, void *ra) pthread_rwlock_unlock(&lock); return res; } +#else +void *dlopen(const char *file, int mode) +{ + return 0; +} +void *__dlsym(void *p, const char *s, void *ra) +{ + return 0; +} +#endif char *dlerror() { + if (!errflag) return 0; + errflag = 0; return "unknown error"; } @@ -684,4 +727,3 @@ int dlclose(void *p) { return 0; } -#endif