X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fldso%2Fdynlink.c;h=814f5c7e4ec0da2be423463f630730e9df06fa00;hb=f8c376da9512c8c8a97781100aa04533740171d4;hp=dbf404ef2dcefef43d76dd7883921f96f915b308;hpb=e69ae844dcc978f68761e4bc44fc5543717b9684;p=musl diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index dbf404ef..814f5c7e 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -91,6 +91,7 @@ struct symdef { void __init_ssp(size_t *); void *__install_initial_tls(void *); +void __init_libc(char **, char *); static struct dso *head, *tail, *ldso, *fini_head; static char *env_path, *sys_path, *r_path; @@ -100,7 +101,7 @@ static int runtime; static int ldd_mode; static int ldso_fail; static int noload; -static jmp_buf rtld_fail; +static jmp_buf *rtld_fail; static pthread_rwlock_t lock; static struct debug debug; static size_t tls_cnt, tls_offset, tls_align = 4*sizeof(size_t); @@ -189,7 +190,7 @@ static Sym *gnu_lookup(const char *s, uint32_t h1, struct dso *dso) } #define OK_TYPES (1<name, name); - if (runtime) longjmp(rtld_fail, 1); + if (runtime) longjmp(*rtld_fail, 1); dprintf(2, "%s\n", errbuf); ldso_fail = 1; continue; @@ -317,8 +318,12 @@ static void *map_library(int fd, struct dso *dso) size_t i; ssize_t l = read(fd, buf, sizeof buf); - if (le_type != ET_DYN && eh->e_type != ET_EXEC) { + errno = ENOEXEC; + return 0; + } phsize = eh->e_phentsize * eh->e_phnum; if (phsize + sizeof *eh > l) return 0; if (eh->e_phoff + phsize > l) { @@ -361,6 +366,12 @@ static void *map_library(int fd, struct dso *dso) * amount of virtual address space to map over later. */ map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start); if (map==MAP_FAILED) return 0; + /* If the loaded file is not relocatable and the requested address is + * not available, then the load operation must fail. */ + if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) { + errno = EBUSY; + goto error; + } base = map - addr_min; dso->phdr = 0; dso->phnum = 0; @@ -447,6 +458,7 @@ static struct dso *load_library(const char *name) struct stat st; size_t alloc_size; int n_th = 0; + int is_self = 0; /* Catch and block attempts to reload the implementation itself */ if (name[0]=='l' && name[1]=='i' && name[2]=='b') { @@ -457,15 +469,31 @@ static struct dso *load_library(const char *name) size_t l = z-name; for (rp=reserved; *rp && memcmp(name+3, rp, l-3); rp+=strlen(rp)+1); if (*rp) { - if (!ldso->prev) { - tail->next = ldso; - ldso->prev = tail; - tail = ldso->next ? ldso->next : ldso; + if (ldd_mode) { + /* Track which names have been resolved + * and only report each one once. */ + static unsigned reported; + unsigned mask = 1U<<(rp-reserved); + if (!(reported & mask)) { + reported |= mask; + dprintf(1, "\t%s => %s (%p)\n", + name, ldso->name, + ldso->base); + } } - return ldso; + is_self = 1; } } } + if (!strcmp(name, ldso->name)) is_self = 1; + if (is_self) { + if (!ldso->prev) { + tail->next = ldso; + ldso->prev = tail; + tail = ldso->next ? ldso->next : ldso; + } + return ldso; + } if (strchr(name, '/')) { pathname = name; fd = open(name, O_RDONLY|O_CLOEXEC); @@ -612,14 +640,14 @@ static void load_deps(struct dso *p) snprintf(errbuf, sizeof errbuf, "Error loading shared library %s: %m (needed by %s)", p->strings + p->dynv[i+1], p->name); - if (runtime) longjmp(rtld_fail, 1); + if (runtime) longjmp(*rtld_fail, 1); dprintf(2, "%s\n", errbuf); ldso_fail = 1; continue; } if (runtime) { tmp = realloc(*deps, sizeof(*tmp)*(ndeps+2)); - if (!tmp) longjmp(rtld_fail, 1); + if (!tmp) longjmp(*rtld_fail, 1); tmp[ndeps++] = dep; tmp[ndeps] = 0; *deps = tmp; @@ -698,11 +726,13 @@ static void do_fini() decode_vec(p->dynv, dyn, DYN_CNT); if (dyn[0] & (1<base + dyn[DT_FINI_ARRAY]); - while (n--) ((void (*)(void))*fn++)(); + size_t *fn = (size_t *)(p->base + dyn[DT_FINI_ARRAY])+n; + while (n--) ((void (*)(void))*--fn)(); } - if (dyn[0] & (1<base + dyn[DT_FINI]))(); +#endif } } @@ -722,8 +752,10 @@ static void do_init_fini(struct dso *p) p->fini_next = fini_head; fini_head = p; } - if (dyn[0] & (1<base + dyn[DT_INIT]))(); +#endif if (dyn[0] & (1<base + dyn[DT_INIT_ARRAY]); @@ -841,6 +873,7 @@ void *__dynlink(int argc, char **argv) char *env_preload=0; size_t vdso_base; size_t *auxv; + char **envp = argv+argc+1; /* Find aux vector just past environ[] */ for (i=argc+1; argv[i]; i++) @@ -878,7 +911,7 @@ void *__dynlink(int argc, char **argv) lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff); find_map_range(lib->phdr, ehdr->e_phnum, ehdr->e_phentsize, lib); lib->dynv = (void *)(lib->base + find_dyn(lib->phdr, - ehdr->e_phnum, ehdr->e_phentsize)); + ehdr->e_phnum, ehdr->e_phentsize)); decode_dyn(lib); if (aux[AT_PHDR]) { @@ -934,9 +967,17 @@ void *__dynlink(int argc, char **argv) close(fd); lib->name = ldname; app->name = argv[0]; - app->phnum = ehdr->e_phnum; - app->phdr = (void *)(app->base + ehdr->e_phoff); - aux[AT_ENTRY] = ehdr->e_entry; + aux[AT_ENTRY] = (size_t)app->base + ehdr->e_entry; + /* Find the name that would have been used for the dynamic + * linker had ldd not taken its place. */ + if (ldd_mode) { + for (i=0; iphnum; i++) { + if (app->phdr[i].p_type == PT_INTERP) + lib->name = (void *)(app->base + + app->phdr[i].p_vaddr); + } + dprintf(1, "\t%s (%p)\n", lib->name, lib->base); + } } if (app->tls_size) { app->tls_id = tls_cnt = 1; @@ -953,7 +994,6 @@ void *__dynlink(int argc, char **argv) tls_align = MAXP2(tls_align, app->tls_align); } app->global = 1; - app->constructed = 1; decode_dyn(app); /* Attach to vdso, if provided by the kernel */ @@ -1038,15 +1078,12 @@ void *__dynlink(int argc, char **argv) _dl_debug_state(); if (ssp_used) __init_ssp((void *)aux[AT_RANDOM]); - - errno = 0; - return (void *)aux[AT_ENTRY]; -} - -void __init_ldso_ctors(void) -{ + __init_libc(envp, argv[0]); atexit(do_fini); + errno = 0; do_init_fini(tail); + + return (void *)aux[AT_ENTRY]; } void *dlopen(const char *file, int mode) @@ -1055,6 +1092,7 @@ void *dlopen(const char *file, int mode) size_t orig_tls_cnt, orig_tls_offset, orig_tls_align; size_t i; int cs; + jmp_buf jb; if (!file) return head; @@ -1069,7 +1107,8 @@ void *dlopen(const char *file, int mode) orig_tail = tail; noload = mode & RTLD_NOLOAD; - if (setjmp(rtld_fail)) { + rtld_fail = &jb; + if (setjmp(*rtld_fail)) { /* Clean up anything new that was (partially) loaded */ if (p && p->deps) for (i=0; p->deps[i]; i++) if (p->deps[i]->global < 0)