X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fldso%2Fdynlink.c;h=6ff8850c8eb89d55ac4c16799bc12e5e09ca0d45;hp=e1c2ad7d883a4eaa3abc1d1baee7a85095ec18ec;hb=f2baf4d7b8be043b231ecf7fc611247196acd9f5;hpb=c82f4a32ec694903a37d3f9e48da52486a470aa2 diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index e1c2ad7d..6ff8850c 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -47,8 +47,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 +472,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}; @@ -511,12 +526,16 @@ void *__dynlink(int argc, char **argv) ehdr->e_phnum, ehdr->e_phentsize)); decode_dyn(lib); - /* Assume base address of 0 for the main program. This is not - * valid for PIE code; we will have to search the PHDR to get - * the correct load address in the PIE case (not yet supported). */ + /* Find load address of the main program, via AT_PHDR vs PT_PHDR. */ app->base = 0; + phdr = (void *)aux[AT_PHDR]; + for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) { + if (phdr->p_type == PT_PHDR) + app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr); + } 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); @@ -560,10 +579,13 @@ void *__dynlink(int argc, char **argv) ehdr->e_phentsize, ehdr->e_phnum); /* Load preload/needed libraries, add their symbols to the global - * namespace, and perform all remaining relocations. */ + * namespace, and perform all remaining relocations. The main + * program must be relocated LAST since it may contain copy + * relocations which depend on libraries' relocations. */ if (env_preload) load_preload(env_preload); load_deps(app); make_global(app); + reloc_all(app->next); reloc_all(app); /* Switch to runtime mode: any further failures in the dynamic @@ -571,6 +593,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); @@ -585,9 +610,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)) { @@ -603,8 +630,8 @@ void *dlopen(const char *file, int mode) } tail = orig_tail; tail->next = 0; - pthread_rwlock_unlock(&lock); - return 0; + p = 0; + goto end; } p = load_library(file); @@ -630,8 +657,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; } @@ -668,6 +697,16 @@ 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() { @@ -678,4 +717,3 @@ int dlclose(void *p) { return 0; } -#endif