#include <dlfcn.h>
static int errflag;
+static char errbuf[128];
#ifdef __PIC__
#define R_SYM(x) ((x)>>32)
#endif
-struct dso
-{
+struct debug {
+ int ver;
+ void *head;
+ void (*bp)(void);
+ int state;
+ void *base;
+};
+
+struct dso {
+ unsigned char *base;
+ char *name;
+ size_t *dynv;
struct dso *next, *prev;
+
int refcnt;
- size_t *dynv;
Sym *syms;
uint32_t *hashtab;
char *strings;
- unsigned char *base;
unsigned char *map;
size_t map_len;
dev_t dev;
char relocated;
char constructed;
struct dso **deps;
- char *name;
char buf[];
};
+void __init_ssp(size_t *);
+
static struct dso *head, *tail, *libc;
static char *env_path, *sys_path, *r_path;
static int rtld_used;
+static int ssp_used;
static int runtime;
static jmp_buf rtld_fail;
static pthread_rwlock_t lock;
+static struct debug debug;
+
+struct debug *_dl_debug_addr = &debug;
#define AUX_CNT 24
#define DYN_CNT 34
void *def = 0;
if (h==0x6b366be && !strcmp(s, "dlopen")) rtld_used = 1;
if (h==0x6b3afd && !strcmp(s, "dlsym")) rtld_used = 1;
+ if (h==0x595a4cc && !strcmp(s, "__stack_chk_fail")) ssp_used = 1;
for (; dso; dso=dso->next) {
Sym *sym;
if (!dso->global) continue;
ctx = IS_COPY(type) ? dso->next : dso;
sym_val = (size_t)find_sym(ctx, name, IS_PLT(type));
if (!sym_val && sym->st_info>>4 != STB_WEAK) {
+ snprintf(errbuf, sizeof errbuf,
+ "Error relocating %s: %s: symbol not found",
+ dso->name, name);
if (runtime) longjmp(rtld_fail, 1);
- dprintf(2, "%s: symbol not found\n", name);
+ dprintf(2, "%s\n", errbuf);
_exit(127);
}
sym_size = sym->st_size;
if (p->dynv[i] != DT_NEEDED) continue;
dep = load_library(p->strings + p->dynv[i+1]);
if (!dep) {
- if (runtime) longjmp(rtld_fail, 1);
- dprintf(2, "%s: %m (needed by %s)\n",
+ snprintf(errbuf, sizeof errbuf,
+ "Error loading shared library %s: %m (needed by %s)",
p->strings + p->dynv[i+1], p->name);
+ if (runtime) longjmp(rtld_fail, 1);
+ dprintf(2, "%s\n", errbuf);
_exit(127);
}
if (runtime) {
}
}
+void _dl_debug_state(void)
+{
+}
+
void *__dynlink(int argc, char **argv)
{
size_t *auxv, aux[AUX_CNT] = {0};
* all memory used by the dynamic linker. */
runtime = 1;
+ for (i=0; app->dynv[i]; i+=2)
+ if (app->dynv[i]==DT_DEBUG)
+ app->dynv[i+1] = (size_t)&debug;
+ debug.ver = 1;
+ debug.bp = _dl_debug_state;
+ debug.head = head;
+ debug.base = lib->base;
+ debug.state = 0;
+ _dl_debug_state();
+
+ if (ssp_used) __init_ssp(auxv);
+
do_init_fini(tail);
if (!rtld_used) {
tail = orig_tail;
tail->next = 0;
p = 0;
+ errflag = 1;
+ goto end;
} else p = load_library(file);
if (!p) {
+ snprintf(errbuf, sizeof errbuf,
+ "Error loading shared library %s: %m", file);
errflag = 1;
goto end;
}
p->global = 1;
}
+ _dl_debug_state();
+
do_init_fini(tail);
end:
pthread_rwlock_unlock(&lock);
}
if (p == head || p == RTLD_DEFAULT) {
void *res = find_sym(head, s, 0);
- if (!res) errflag = 1;
+ if (!res) goto failed;
return res;
}
h = hash(s);
if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
return p->deps[i]->base + sym->st_value;
}
+failed:
errflag = 1;
+ snprintf(errbuf, sizeof errbuf, "Symbol not found: %s", s);
return 0;
}
{
if (!errflag) return 0;
errflag = 0;
- return "unknown error";
+ return errbuf;
}
int dlclose(void *p)