most importantly, the name for such libs was being set from an
uninitialized buffer. also, shortname always had an initial '/'
character, making it useless for looking up already-loaded libraries
by name, and thus causing repeated searches through the library path.
major changes now:
- shortname is the base name for library lookups with no explicit
pathname. it's initially clear for libraries loaded with an explicit
pathname (and for the main program), but will be set if the same
library (detected via inodes match) is later found by a search.
- exact name match is never used to identify libraries loaded with an
explicit pathname. in this case, there's no explicit search, so we
can just stat the file and check for inode match.
static struct dso *load_library(const char *name)
{
char buf[2*NAME_MAX+2];
static struct dso *load_library(const char *name)
{
char buf[2*NAME_MAX+2];
unsigned char *base, *map;
size_t dyno, map_len;
struct dso *p;
unsigned char *base, *map;
size_t dyno, map_len;
struct dso *p;
- /* 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;
- }
- }
fd = open(name, O_RDONLY);
} else {
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);
if (strlen(name) > NAME_MAX) return 0;
fd = -1;
if (r_path) fd = path_open(name, r_path, buf, sizeof buf);
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);
}
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);
}
}
if (fd < 0) return 0;
if (fstat(fd, &st) < 0) {
}
if (fd < 0) return 0;
if (fstat(fd, &st) < 0) {
}
for (p=head->next; p; p=p->next) {
if (p->dev == st.st_dev && p->ino == st.st_ino) {
}
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;
close(fd);
p->refcnt++;
return p;
map = map_library(fd, &map_len, &base, &dyno);
close(fd);
if (!map) return 0;
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;
if (!p) {
munmap(map, map_len);
return 0;
p->ino = st.st_ino;
p->refcnt = 1;
p->name = p->buf;
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;
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);
if (phdr->p_type == PT_PHDR)
app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
}
if (phdr->p_type == PT_PHDR)
app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
}
- app->name = app->shortname = argv[0];
app->dynv = (void *)(app->base + find_dyn(
(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
} else {
app->dynv = (void *)(app->base + find_dyn(
(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
} else {
}
runtime = 0;
close(fd);
}
runtime = 0;
close(fd);
- app->name = app->shortname = argv[0];
app->dynv = (void *)(app->base + dyno);
aux[AT_ENTRY] = ehdr->e_entry;
}
app->dynv = (void *)(app->base + dyno);
aux[AT_ENTRY] = ehdr->e_entry;
}