sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
tls_val = def.sym ? def.sym->st_value : 0;
+ if ((type == REL_TPOFF || type == REL_TPOFF_NEG)
+ && runtime && def.dso->tls_id > static_tls_cnt) {
+ error("Error relocating %s: %s: initial-exec TLS "
+ "resolves to dynamic definition in %s",
+ dso->name, name, def.dso->name);
+ longjmp(*rtld_fail, 1);
+ }
+
switch(type) {
case REL_NONE:
break;
#endif
case REL_TLSDESC:
if (stride<3) addend = reloc_addr[1];
- if (runtime && def.dso->tls_id >= static_tls_cnt) {
+ if (runtime && def.dso->tls_id > static_tls_cnt) {
struct td_index *new = malloc(sizeof *new);
if (!new) {
error(
return p;
}
} else {
+ Phdr *ph = p->phdr;
+ size_t phcnt = p->phnum;
+ size_t entsz = p->phentsize;
+ size_t base = (size_t)p->base;
+ for (; phcnt--; ph=(void *)((char *)ph+entsz)) {
+ if (ph->p_type != PT_LOAD) continue;
+ if (a-base-ph->p_vaddr < ph->p_memsz)
+ return p;
+ }
if (a-(size_t)p->map < p->map_len)
- return p;
+ return 0;
}
}
return 0;
return 0;
}
-int dladdr(const void *addr, Dl_info *info)
+int dladdr(const void *addr_arg, Dl_info *info)
{
+ size_t addr = (size_t)addr_arg;
struct dso *p;
Sym *sym, *bestsym;
uint32_t nsym;
char *strings;
- void *best = 0;
+ size_t best = 0;
+ size_t besterr = -1;
pthread_rwlock_rdlock(&lock);
- p = addr2dso((size_t)addr);
+ p = addr2dso(addr);
pthread_rwlock_unlock(&lock);
if (!p) return 0;
nsym = count_syms(p);
if (DL_FDPIC) {
- size_t idx = ((size_t)addr-(size_t)p->funcdescs)
+ size_t idx = (addr-(size_t)p->funcdescs)
/ sizeof(*p->funcdescs);
if (idx < nsym && (sym[idx].st_info&0xf) == STT_FUNC) {
- best = p->funcdescs + idx;
+ best = (size_t)(p->funcdescs + idx);
bestsym = sym + idx;
+ besterr = 0;
}
}
if (sym->st_value
&& (1<<(sym->st_info&0xf) & OK_TYPES)
&& (1<<(sym->st_info>>4) & OK_BINDS)) {
- void *symaddr = laddr(p, sym->st_value);
- if (symaddr > addr || symaddr < best)
+ size_t symaddr = (size_t)laddr(p, sym->st_value);
+ if (symaddr > addr || symaddr <= best)
continue;
best = symaddr;
bestsym = sym;
+ besterr = addr - symaddr;
if (addr == symaddr)
break;
}
}
- if (!best) return 0;
-
- if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC)
- best = p->funcdescs + (bestsym - p->syms);
+ if (bestsym && besterr > bestsym->st_size-1) {
+ best = 0;
+ bestsym = 0;
+ }
info->dli_fname = p->name;
info->dli_fbase = p->map;
+
+ if (!best) {
+ info->dli_sname = 0;
+ info->dli_saddr = 0;
+ return 1;
+ }
+
+ if (DL_FDPIC && (bestsym->st_info&0xf) == STT_FUNC)
+ best = (size_t)(p->funcdescs + (bestsym - p->syms));
info->dli_sname = strings + bestsym->st_name;
- info->dli_saddr = best;
+ info->dli_saddr = (void *)best;
return 1;
}