static int errflag;
static char errbuf[128];
-#ifdef __PIC__
+#ifdef SHARED
#include "reloc.h"
size_t map_len;
dev_t dev;
ino_t ino;
- char global;
+ signed char global;
char relocated;
char constructed;
struct dso **deps;
prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
((ph->p_flags&PF_X) ? PROT_EXEC : 0));
- if (mmap(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED) {
- munmap(map, map_len);
- return 0;
- }
+ if (mmap(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
+ goto error;
if (ph->p_memsz > ph->p_filesz) {
size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
- if (pgbrk-(size_t)base < this_max && mmap((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
- munmap(map, map_len);
- return 0;
- }
+ if (pgbrk-(size_t)base < this_max && mmap((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
+ goto error;
}
}
for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
- mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC);
+ if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
+ goto error;
break;
}
if (!runtime) reclaim_gaps(base, (void *)((char *)buf + eh->e_phoff),
*basep = base;
*dynp = dyn;
return map;
+error:
+ munmap(map, map_len);
+ return 0;
}
static int path_open(const char *name, const char *search, char *buf, size_t buf_size)
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;
}
}
}
- /* 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);
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) {
}
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;
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;
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;
}
if (phdr->p_type == PT_PHDR)
app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
}
- app->name = app->shortname = argv[0];
+ app->name = argv[0];
app->dynv = (void *)(app->base + find_dyn(
(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
} else {
}
runtime = 0;
close(fd);
- app->name = app->shortname = argv[0];
+ app->name = argv[0];
app->dynv = (void *)(app->base + dyno);
aux[AT_ENTRY] = ehdr->e_entry;
}
if (p == RTLD_NEXT) {
for (p=head; p && (unsigned char *)ra-p->map>p->map_len; p=p->next);
if (!p) p=head;
- p=p->next;
+ void *res = find_sym(p->next, s, 0);
+ if (!res) goto failed;
+ return res;
}
if (p == head || p == RTLD_DEFAULT) {
void *res = find_sym(head, s, 0);