#include "pthread_impl.h"
#include "libc.h"
#include "dynlink.h"
+#include "malloc_impl.h"
static void error(const char *, ...);
struct dso *dso;
};
-int __init_tp(void *);
-void __init_libc(char **, char *);
-void *__copy_tls(unsigned char *);
-
-__attribute__((__visibility__("hidden")))
-const char *__libc_get_version(void);
-
static struct builtin_tls {
char c;
struct pthread pt;
struct debug *_dl_debug_addr = &debug;
-__attribute__((__visibility__("hidden")))
-extern int __malloc_replaced;
+extern hidden int __malloc_replaced;
-__attribute__((__visibility__("hidden")))
-void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0;
+hidden void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0;
-__attribute__((__visibility__("hidden")))
-extern void (*const __init_array_end)(void), (*const __fini_array_end)(void);
+extern hidden void (*const __init_array_end)(void), (*const __fini_array_end)(void);
weak_alias(__init_array_start, __init_array_end);
weak_alias(__fini_array_start, __fini_array_end);
return def;
}
-__attribute__((__visibility__("hidden")))
-ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic();
-
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
{
unsigned char *base = dso->base;
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(
static void reclaim(struct dso *dso, size_t start, size_t end)
{
- void __malloc_donate(char *, char *);
if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end;
if (end >= dso->relro_start && end < dso->relro_end) end = dso->relro_start;
if (start >= end) return;
{
}
-__attribute__((__visibility__("hidden")))
-void *__tls_get_new(tls_mod_off_t *v)
+hidden void *__tls_get_new(tls_mod_off_t *v)
{
pthread_t self = __pthread_self();
* linker itself, but some of the relocations performed may need to be
* replaced later due to copy relocations in the main program. */
-__attribute__((__visibility__("hidden")))
-void __dls2(unsigned char *base, size_t *sp)
+hidden void __dls2(unsigned char *base, size_t *sp)
{
if (DL_FDPIC) {
void *p1 = (void *)sp[-2];
"Version %s\n"
"Dynamic Program Loader\n"
"Usage: %s [options] [--] pathname%s\n",
- __libc_get_version(), ldname,
+ __libc_version, ldname,
ldd_mode ? "" : " [args]");
_exit(1);
}
return p;
}
-__attribute__((__visibility__("hidden")))
-int __dl_invalid_handle(void *h)
+hidden int __dl_invalid_handle(void *h)
{
struct dso *p;
for (p=head; p; p=p->next) if (h==p) return 0;
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;
}
-void *__tls_get_addr(tls_mod_off_t *);
-
static void *do_dlsym(struct dso *p, const char *s, void *ra)
{
size_t i;
uint32_t nsym;
char *strings;
size_t best = 0;
+ size_t besterr = -1;
pthread_rwlock_rdlock(&lock);
p = addr2dso(addr);
if (idx < nsym && (sym[idx].st_info&0xf) == STT_FUNC) {
best = (size_t)(p->funcdescs + idx);
bestsym = sym + idx;
+ besterr = 0;
}
}
&& (1<<(sym->st_info&0xf) & OK_TYPES)
&& (1<<(sym->st_info>>4) & OK_BINDS)) {
size_t symaddr = (size_t)laddr(p, sym->st_value);
- if (symaddr > addr || symaddr < best)
+ if (symaddr > addr || symaddr <= best)
continue;
- if (sym->st_size && symaddr+sym->st_size <= addr) {
- best = 0;
- bestsym = 0;
- continue;
- }
best = symaddr;
bestsym = sym;
+ besterr = addr - symaddr;
if (addr == symaddr)
break;
}
}
+ if (bestsym && besterr > bestsym->st_size-1) {
+ best = 0;
+ bestsym = 0;
+ }
+
info->dli_fname = p->name;
info->dli_fbase = p->map;
return 1;
}
-__attribute__((__visibility__("hidden")))
-void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
+hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
{
void *res;
pthread_rwlock_rdlock(&lock);
return ret;
}
-__attribute__((__visibility__("hidden")))
-void __dl_vseterr(const char *, va_list);
-
static void error(const char *fmt, ...)
{
va_list ap;