X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fldso%2Fdynlink.c;h=814f5c7e4ec0da2be423463f630730e9df06fa00;hb=f8c376da9512c8c8a97781100aa04533740171d4;hp=ff416838a65caba4d6493db0729c38303fae1f32;hpb=876748ead3de7798623c09af835a4b56dcc28e0f;p=musl diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index ff416838..814f5c7e 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -318,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) { @@ -362,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; @@ -448,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') { @@ -458,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); @@ -703,7 +730,7 @@ static void do_fini() while (n--) ((void (*)(void))*--fn)(); } #ifndef NO_LEGACY_INITFINI - if (dyn[0] & (1<base + dyn[DT_FINI]))(); #endif } @@ -726,7 +753,7 @@ static void do_init_fini(struct dso *p) fini_head = p; } #ifndef NO_LEGACY_INITFINI - if (dyn[0] & (1<base + dyn[DT_INIT]))(); #endif if (dyn[0] & (1<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]) { @@ -941,6 +968,16 @@ void *__dynlink(int argc, char **argv) lib->name = ldname; app->name = argv[0]; 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;