X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fldso%2Fdynlink.c;h=0cb025928617dffeb5ae1d52381457e3b14519e8;hp=263593ab75531e45e9d3f04f5f5740f68c611220;hb=05eff01e89ee345e70acdbebc9c3778766b76ee2;hpb=d93e028c6bbd491592313fc77e056f6424ea4668 diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 263593ab..0cb02592 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -20,7 +20,7 @@ static int errflag; static char errbuf[128]; -#ifdef __PIC__ +#ifdef SHARED #include "reloc.h" @@ -105,9 +105,12 @@ static uint32_t hash(const char *s0) return h & 0xfffffff; } -static Sym *lookup(const char *s, uint32_t h, Sym *syms, uint32_t *hashtab, char *strings) +static Sym *lookup(const char *s, uint32_t h, struct dso *dso) { size_t i; + Sym *syms = dso->syms; + uint32_t *hashtab = dso->hashtab; + char *strings = dso->strings; for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) { if (!strcmp(s, strings+syms[i].st_name)) return syms+i; @@ -128,7 +131,7 @@ static void *find_sym(struct dso *dso, const char *s, int need_def) for (; dso; dso=dso->next) { Sym *sym; if (!dso->global) continue; - sym = lookup(s, h, dso->syms, dso->hashtab, dso->strings); + sym = lookup(s, h, dso); if (sym && (!need_def || sym->st_shndx) && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES) && (1<<(sym->st_info>>4) & OK_BINDS)) { @@ -322,6 +325,7 @@ static void decode_dyn(struct dso *p) static struct dso *load_library(const char *name) { char buf[2*NAME_MAX+2]; + const char *pathname; unsigned char *base, *map; size_t dyno, map_len; struct dso *p; @@ -346,16 +350,17 @@ static struct dso *load_library(const char *name) } } } - /* Search for the name to see if it's already loaded */ - for (p=head->next; p; p=p->next) { - if (!strcmp(p->shortname, name)) { - p->refcnt++; - return p; - } - } if (strchr(name, '/')) { + pathname = name; fd = open(name, O_RDONLY); } else { + /* Search for the name to see if it's already loaded */ + for (p=head->next; p; p=p->next) { + if (p->shortname && !strcmp(p->shortname, name)) { + p->refcnt++; + return p; + } + } if (strlen(name) > NAME_MAX) return 0; fd = -1; if (r_path) fd = path_open(name, r_path, buf, sizeof buf); @@ -372,6 +377,7 @@ static struct dso *load_library(const char *name) if (sys_path) fd = path_open(name, sys_path, buf, sizeof buf); else fd = path_open(name, "/lib:/usr/local/lib:/usr/lib", buf, sizeof buf); } + pathname = buf; } if (fd < 0) return 0; if (fstat(fd, &st) < 0) { @@ -380,6 +386,10 @@ static struct dso *load_library(const char *name) } for (p=head->next; p; p=p->next) { if (p->dev == st.st_dev && p->ino == st.st_ino) { + /* If this library was previously loaded with a + * pathname but a search found the same inode, + * setup its shortname so it can be found by name. */ + if (!p->shortname) p->shortname = strrchr(p->name, '/')+1; close(fd); p->refcnt++; return p; @@ -388,7 +398,7 @@ static struct dso *load_library(const char *name) map = map_library(fd, &map_len, &base, &dyno); close(fd); if (!map) return 0; - p = calloc(1, sizeof *p + strlen(buf) + 1); + p = calloc(1, sizeof *p + strlen(pathname) + 1); if (!p) { munmap(map, map_len); return 0; @@ -404,15 +414,15 @@ static struct dso *load_library(const char *name) p->ino = st.st_ino; p->refcnt = 1; p->name = p->buf; - strcpy(p->name, buf); - if (!strchr(name, '/')) p->shortname = strrchr(p->name, '/'); - if (!p->shortname) p->shortname = p->name; + strcpy(p->name, pathname); + /* Add a shortname only if name arg was not an explicit pathname. */ + if (pathname != name) p->shortname = strrchr(p->name, '/')+1; tail->next = p; p->prev = tail; tail = p; - if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, buf, base); + if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, base); return p; } @@ -570,13 +580,17 @@ void *__dynlink(int argc, char **argv) decode_dyn(lib); if (aux[AT_PHDR]) { + size_t interp_off = 0; /* Find load address of the main program, via AT_PHDR vs PT_PHDR. */ 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); + else if (phdr->p_type == PT_INTERP) + interp_off = (size_t)phdr->p_vaddr; } - app->name = app->shortname = argv[0]; + if (interp_off) lib->name = (char *)app->base + interp_off; + app->name = argv[0]; app->dynv = (void *)(app->base + find_dyn( (void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT])); } else { @@ -605,7 +619,8 @@ void *__dynlink(int argc, char **argv) } runtime = 0; close(fd); - app->name = app->shortname = argv[0]; + lib->name = ldname; + app->name = argv[0]; app->dynv = (void *)(app->base + dyno); aux[AT_ENTRY] = ehdr->e_entry; } @@ -776,12 +791,11 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra) return res; } h = hash(s); - sym = lookup(s, h, p->syms, p->hashtab, p->strings); + sym = lookup(s, h, p); if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) return p->base + sym->st_value; if (p->deps) for (i=0; p->deps[i]; i++) { - sym = lookup(s, h, p->deps[i]->syms, - p->deps[i]->hashtab, p->deps[i]->strings); + sym = lookup(s, h, p); if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) return p->deps[i]->base + sym->st_value; }