-#ifdef __PIC__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dlfcn.h>
+static int errflag;
+static char errbuf[128];
+
+#ifdef __PIC__
+
#include "reloc.h"
#if ULONG_MAX == 0xffffffff
#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;
ino_t ino;
- int global;
- int relocated;
+ char global;
+ char relocated;
+ char constructed;
struct dso **deps;
- char *name;
char buf[];
};
+struct __pthread;
+struct __pthread *__pthread_self_init(void);
+
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) {
return 0;
}
+static void do_init_fini(struct dso *p)
+{
+ size_t dyn[DYN_CNT] = {0};
+ for (; p; p=p->prev) {
+ if (p->constructed) return;
+ decode_vec(p->dynv, dyn, DYN_CNT);
+ if (dyn[0] & (1<<DT_FINI))
+ atexit((void (*)(void))(p->base + dyn[DT_FINI]));
+ if (dyn[0] & (1<<DT_INIT))
+ ((void (*)(void))(p->base + dyn[DT_INIT]))();
+ p->constructed = 1;
+ }
+}
+
+void _dl_debug_state(void)
+{
+}
+
void *__dynlink(int argc, char **argv)
{
size_t *auxv, aux[AUX_CNT] = {0};
}
app->name = argv[0];
app->global = 1;
+ app->constructed = 1;
app->dynv = (void *)(app->base + find_dyn(
(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
decode_dyn(app);
* error. If the dynamic loader (dlopen) will not be used, free
* 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();
+
+ do_init_fini(tail);
+
if (!rtld_used) {
free_all(head);
free(sys_path);
reclaim((void *)builtin_dsos, 0, sizeof builtin_dsos);
}
+ if (ssp_used) __pthread_self_init();
+
errno = 0;
return (void *)aux[AT_ENTRY];
}
{
struct dso *volatile p, *orig_tail = tail, *next;
size_t i;
+ int cs;
if (!file) return head;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
pthread_rwlock_wrlock(&lock);
if (setjmp(rtld_fail)) {
}
tail = orig_tail;
tail->next = 0;
- pthread_rwlock_unlock(&lock);
- return 0;
- }
+ p = 0;
+ errflag = 1;
+ goto end;
+ } else p = load_library(file);
- p = load_library(file);
- if (!p) goto end;
+ if (!p) {
+ snprintf(errbuf, sizeof errbuf,
+ "Error loading shared library %s: %m", file);
+ errflag = 1;
+ goto end;
+ }
/* First load handling */
if (!p->deps) {
p->global = 1;
}
+ _dl_debug_state();
+
+ do_init_fini(tail);
end:
pthread_rwlock_unlock(&lock);
+ pthread_setcancelstate(cs, 0);
return p;
}
if (!p) p=head;
p=p->next;
}
- if (p == head || p == RTLD_DEFAULT)
- return find_sym(head, s, 0);
+ if (p == head || p == RTLD_DEFAULT) {
+ void *res = find_sym(head, s, 0);
+ if (!res) errflag = 1;
+ return res;
+ }
h = hash(s);
sym = lookup(s, h, p->syms, p->hashtab, p->strings);
if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
return p->deps[i]->base + sym->st_value;
}
+ errflag = 1;
+ snprintf(errbuf, sizeof errbuf, "Symbol not found: %s", s);
return 0;
}
char *dlerror()
{
- return "unknown error";
+ if (!errflag) return 0;
+ errflag = 0;
+ return errbuf;
}
int dlclose(void *p)