static int errflag;
static char errbuf[128];
-#ifdef __PIC__
-
-#include "reloc.h"
+#ifdef SHARED
#if ULONG_MAX == 0xffffffff
typedef Elf32_Ehdr Ehdr;
size_t map_len;
dev_t dev;
ino_t ino;
- char global;
+ signed char global;
char relocated;
char constructed;
struct dso **deps;
char buf[];
};
+#include "reloc.h"
+
void __init_ssp(size_t *);
static struct dso *head, *tail, *libc;
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;
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)) {
return def;
}
-static void do_relocs(unsigned char *base, size_t *rel, size_t rel_size, size_t stride, Sym *syms, char *strings, struct dso *dso)
+static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
{
+ unsigned char *base = dso->base;
+ Sym *syms = dso->syms;
+ char *strings = dso->strings;
Sym *sym;
const char *name;
size_t sym_val, sym_size;
if (sym_index) {
sym = syms + sym_index;
name = strings + sym->st_name;
- ctx = IS_COPY(type) ? dso->next : dso;
+ ctx = IS_COPY(type) ? head->next : head;
sym_val = (size_t)find_sym(ctx, name, IS_PLT(type));
if (!sym_val && sym->st_info>>4 != STB_WEAK) {
snprintf(errbuf, sizeof errbuf,
_exit(127);
}
sym_size = sym->st_size;
+ } else {
+ sym_val = sym_size = 0;
}
do_single_reloc(reloc_addr, type, sym_val, sym_size, base, rel[2]);
}
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;
}
for (; p; p=p->next) {
if (p->relocated) continue;
decode_vec(p->dynv, dyn, DYN_CNT);
- do_relocs(p->base, (void *)(p->base+dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
- 2+(dyn[DT_PLTREL]==DT_RELA), p->syms, p->strings, head);
- do_relocs(p->base, (void *)(p->base+dyn[DT_REL]), dyn[DT_RELSZ],
- 2, p->syms, p->strings, head);
- do_relocs(p->base, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ],
- 3, p->syms, p->strings, head);
+#ifdef NEED_ARCH_RELOCS
+ do_arch_relocs(p, head);
+#endif
+ do_relocs(p, (void *)(p->base+dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
+ 2+(dyn[DT_PLTREL]==DT_RELA));
+ do_relocs(p, (void *)(p->base+dyn[DT_REL]), dyn[DT_RELSZ], 2);
+ do_relocs(p, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ], 3);
p->relocated = 1;
}
}
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 {
}
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;
}
* all memory used by the dynamic linker. */
runtime = 1;
+#ifndef DYNAMIC_IS_RO
for (i=0; app->dynv[i]; i+=2)
if (app->dynv[i]==DT_DEBUG)
app->dynv[i+1] = (size_t)&debug;
+#endif
debug.ver = 1;
debug.bp = _dl_debug_state;
debug.head = head;
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);
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;
}