projects
/
musl
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
PIE support for x86_64 (untested)
[musl]
/
src
/
ldso
/
dynlink.c
diff --git
a/src/ldso/dynlink.c
b/src/ldso/dynlink.c
index
ca49f43
..
3f3316a
100644
(file)
--- a/
src/ldso/dynlink.c
+++ b/
src/ldso/dynlink.c
@@
-1,4
+1,3
@@
-#ifdef __PIC__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@
-18,6
+17,11
@@
#include <ctype.h>
#include <dlfcn.h>
#include <ctype.h>
#include <dlfcn.h>
+static int errflag;
+static char errbuf[128];
+
+#ifdef __PIC__
+
#include "reloc.h"
#if ULONG_MAX == 0xffffffff
#include "reloc.h"
#if ULONG_MAX == 0xffffffff
@@
-34,33
+38,48
@@
typedef Elf64_Sym Sym;
#define R_SYM(x) ((x)>>32)
#endif
#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;
struct dso *next, *prev;
+
int refcnt;
int refcnt;
- size_t *dynv;
Sym *syms;
uint32_t *hashtab;
char *strings;
Sym *syms;
uint32_t *hashtab;
char *strings;
- unsigned char *base;
unsigned char *map;
size_t map_len;
dev_t dev;
ino_t ino;
unsigned char *map;
size_t map_len;
dev_t dev;
ino_t ino;
-
int
global;
-
int
relocated;
-
int
constructed;
+
char
global;
+
char
relocated;
+
char
constructed;
struct dso **deps;
struct dso **deps;
- char *name;
char buf[];
};
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 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 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
#define AUX_CNT 24
#define DYN_CNT 34
@@
-104,6
+123,7
@@
static void *find_sym(struct dso *dso, const char *s, int need_def)
void *def = 0;
if (h==0x6b366be && !strcmp(s, "dlopen")) rtld_used = 1;
if (h==0x6b3afd && !strcmp(s, "dlsym")) rtld_used = 1;
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;
for (; dso; dso=dso->next) {
Sym *sym;
if (!dso->global) continue;
@@
-139,8
+159,11
@@
static void do_relocs(unsigned char *base, size_t *rel, size_t rel_size, size_t
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) {
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);
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;
_exit(127);
}
sym_size = sym->st_size;
@@
-402,9
+425,11
@@
static void load_deps(struct dso *p)
if (p->dynv[i] != DT_NEEDED) continue;
dep = load_library(p->strings + p->dynv[i+1]);
if (!dep) {
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);
p->strings + p->dynv[i+1], p->name);
+ if (runtime) longjmp(rtld_fail, 1);
+ dprintf(2, "%s\n", errbuf);
_exit(127);
}
if (runtime) {
_exit(127);
}
if (runtime) {
@@
-486,6
+511,10
@@
static void do_init_fini(struct dso *p)
}
}
}
}
+void _dl_debug_state(void)
+{
+}
+
void *__dynlink(int argc, char **argv)
{
size_t *auxv, aux[AUX_CNT] = {0};
void *__dynlink(int argc, char **argv)
{
size_t *auxv, aux[AUX_CNT] = {0};
@@
-594,6
+623,16
@@
void *__dynlink(int argc, char **argv)
* all memory used by the dynamic linker. */
runtime = 1;
* 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) {
do_init_fini(tail);
if (!rtld_used) {
@@
-602,6
+641,8
@@
void *__dynlink(int argc, char **argv)
reclaim((void *)builtin_dsos, 0, sizeof builtin_dsos);
}
reclaim((void *)builtin_dsos, 0, sizeof builtin_dsos);
}
+ if (ssp_used) __pthread_self_init();
+
errno = 0;
return (void *)aux[AT_ENTRY];
}
errno = 0;
return (void *)aux[AT_ENTRY];
}
@@
-610,9
+651,11
@@
void *dlopen(const char *file, int mode)
{
struct dso *volatile p, *orig_tail = tail, *next;
size_t i;
{
struct dso *volatile p, *orig_tail = tail, *next;
size_t i;
+ int cs;
if (!file) return head;
if (!file) return head;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
pthread_rwlock_wrlock(&lock);
if (setjmp(rtld_fail)) {
pthread_rwlock_wrlock(&lock);
if (setjmp(rtld_fail)) {
@@
-628,12
+671,17
@@
void *dlopen(const char *file, int mode)
}
tail = orig_tail;
tail->next = 0;
}
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) {
/* First load handling */
if (!p->deps) {
@@
-655,8
+703,12
@@
void *dlopen(const char *file, int mode)
p->global = 1;
}
p->global = 1;
}
+ _dl_debug_state();
+
+ do_init_fini(tail);
end:
pthread_rwlock_unlock(&lock);
end:
pthread_rwlock_unlock(&lock);
+ pthread_setcancelstate(cs, 0);
return p;
}
return p;
}
@@
-670,8
+722,11
@@
static void *do_dlsym(struct dso *p, const char *s, void *ra)
if (!p) p=head;
p=p->next;
}
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))
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))
@@
-682,6
+737,8
@@
static void *do_dlsym(struct dso *p, const char *s, void *ra)
if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
return p->deps[i]->base + sym->st_value;
}
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;
}
return 0;
}
@@
-706,7
+763,9
@@
void *__dlsym(void *p, const char *s, void *ra)
char *dlerror()
{
char *dlerror()
{
- return "unknown error";
+ if (!errflag) return 0;
+ errflag = 0;
+ return errbuf;
}
int dlclose(void *p)
}
int dlclose(void *p)