dynlink.c 42.4 KB
Newer Older
1
#define _GNU_SOURCE
R
Rich Felker 已提交
2 3
#include <stdio.h>
#include <stdlib.h>
4
#include <stdarg.h>
5
#include <stddef.h>
R
Rich Felker 已提交
6 7 8 9 10 11 12 13 14
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <elf.h>
#include <sys/mman.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
R
Rich Felker 已提交
15
#include <link.h>
R
Rich Felker 已提交
16
#include <setjmp.h>
17
#include <pthread.h>
R
Rich Felker 已提交
18
#include <ctype.h>
19
#include <dlfcn.h>
20 21
#include "pthread_impl.h"
#include "libc.h"
R
Rich Felker 已提交
22

R
Rich Felker 已提交
23
static int errflag;
24
static char errbuf[128];
R
Rich Felker 已提交
25

26
#ifdef SHARED
R
Rich Felker 已提交
27

R
Rich Felker 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41
#if ULONG_MAX == 0xffffffff
typedef Elf32_Ehdr Ehdr;
typedef Elf32_Phdr Phdr;
typedef Elf32_Sym Sym;
#define R_TYPE(x) ((x)&255)
#define R_SYM(x) ((x)>>8)
#else
typedef Elf64_Ehdr Ehdr;
typedef Elf64_Phdr Phdr;
typedef Elf64_Sym Sym;
#define R_TYPE(x) ((x)&0xffffffff)
#define R_SYM(x) ((x)>>32)
#endif

R
Rich Felker 已提交
42 43 44
#define MAXP2(a,b) (-(-(a)&-(b)))
#define ALIGN(x,y) ((x)+(y)-1 & -(y))

45 46 47 48 49 50 51 52
struct debug {
	int ver;
	void *head;
	void (*bp)(void);
	int state;
	void *base;
};

53 54 55 56 57
struct td_index {
	size_t args[2];
	struct td_index *next;
};

58 59 60 61
struct dso {
	unsigned char *base;
	char *name;
	size_t *dynv;
R
Rich Felker 已提交
62
	struct dso *next, *prev;
63

R
Rich Felker 已提交
64 65
	Phdr *phdr;
	int phnum;
66
	size_t phentsize;
R
Rich Felker 已提交
67 68
	int refcnt;
	Sym *syms;
69
	uint32_t *hashtab;
70
	uint32_t *ghashtab;
71
	int16_t *versym;
R
Rich Felker 已提交
72 73 74 75 76
	char *strings;
	unsigned char *map;
	size_t map_len;
	dev_t dev;
	ino_t ino;
77
	signed char global;
78 79
	char relocated;
	char constructed;
80
	char kernel_mapped;
81
	struct dso **deps, *needed_by;
82
	char *rpath_orig, *rpath;
83
	void *tls_image;
84
	size_t tls_len, tls_size, tls_align, tls_id, tls_offset;
T
Timo Teräs 已提交
85
	size_t relro_start, relro_end;
86 87
	void **new_dtv;
	unsigned char *new_tls;
88
	volatile int new_dtv_idx, new_tls_idx;
89
	struct td_index *td_index;
90
	struct dso *fini_next;
91
	char *shortname;
R
Rich Felker 已提交
92
	char buf[];
R
Rich Felker 已提交
93 94
};

95 96 97 98 99
struct symdef {
	Sym *sym;
	struct dso *dso;
};

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
enum {
	REL_ERR,
	REL_SYMBOLIC,
	REL_GOT,
	REL_PLT,
	REL_RELATIVE,
	REL_OFFSET,
	REL_OFFSET32,
	REL_COPY,
	REL_SYM_OR_REL,
	REL_TLS, /* everything past here is TLS */
	REL_DTPMOD,
	REL_DTPOFF,
	REL_TPOFF,
	REL_TPOFF_NEG,
115
	REL_TLSDESC,
116 117
};

118 119
#include "reloc.h"

120
int __init_tp(void *);
121
void __init_libc(char **, char *);
122

123 124
const char *__libc_get_version(void);

125 126 127 128 129 130 131
static struct builtin_tls {
	char c;
	struct pthread pt;
	void *space[16];
} builtin_tls[1];
#define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt)

132
static struct dso *head, *tail, *ldso, *fini_head;
133
static char *env_path, *sys_path;
R
Rich Felker 已提交
134
static unsigned long long gencnt;
R
Rich Felker 已提交
135
static int runtime;
136
static int ldd_mode;
137
static int ldso_fail;
138
static int noload;
139
static jmp_buf *rtld_fail;
140
static pthread_rwlock_t lock;
141
static struct debug debug;
142
static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN;
143
static size_t static_tls_cnt;
144
static pthread_mutex_t init_fini_lock = { ._m_type = PTHREAD_MUTEX_RECURSIVE };
145 146

struct debug *_dl_debug_addr = &debug;
R
Rich Felker 已提交
147

148
#define AUX_CNT 38
R
Rich Felker 已提交
149 150 151 152 153 154 155 156 157 158 159
#define DYN_CNT 34

static void decode_vec(size_t *v, size_t *a, size_t cnt)
{
	memset(a, 0, cnt*sizeof(size_t));
	for (; v[0]; v+=2) if (v[0]<cnt) {
		a[0] |= 1ULL<<v[0];
		a[v[0]] = v[1];
	}
}

160 161 162 163 164 165 166 167
static int search_vec(size_t *v, size_t *r, size_t key)
{
	for (; v[0]!=key; v+=2)
		if (!v[0]) return 0;
	*r = v[1];
	return 1;
}

168 169 170 171 172 173 174 175 176 177 178
static void error(const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	vsnprintf(errbuf, sizeof errbuf, fmt, ap);
	va_end(ap);
	if (runtime) longjmp(*rtld_fail, 1);
	dprintf(2, "%s\n", errbuf);
	ldso_fail = 1;
}

179
static uint32_t sysv_hash(const char *s0)
R
Rich Felker 已提交
180
{
181
	const unsigned char *s = (void *)s0;
R
Rich Felker 已提交
182 183 184 185 186 187 188 189
	uint_fast32_t h = 0;
	while (*s) {
		h = 16*h + *s++;
		h ^= h>>24 & 0xf0;
	}
	return h & 0xfffffff;
}

190 191 192 193 194 195 196 197 198 199
static uint32_t gnu_hash(const char *s0)
{
	const unsigned char *s = (void *)s0;
	uint_fast32_t h = 5381;
	for (; *s; s++)
		h = h*33 + *s;
	return h;
}

static Sym *sysv_lookup(const char *s, uint32_t h, struct dso *dso)
R
Rich Felker 已提交
200 201
{
	size_t i;
R
Rich Felker 已提交
202 203 204
	Sym *syms = dso->syms;
	uint32_t *hashtab = dso->hashtab;
	char *strings = dso->strings;
R
Rich Felker 已提交
205
	for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) {
206 207
		if ((!dso->versym || dso->versym[i] >= 0)
		    && (!strcmp(s, strings+syms[i].st_name)))
R
Rich Felker 已提交
208 209 210 211 212
			return syms+i;
	}
	return 0;
}

213 214
static Sym *gnu_lookup(const char *s, uint32_t h1, struct dso *dso)
{
215 216
	Sym *syms = dso->syms;
	char *strings = dso->strings;
217 218 219 220 221
	uint32_t *hashtab = dso->ghashtab;
	uint32_t nbuckets = hashtab[0];
	uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4);
	uint32_t h2;
	uint32_t *hashval;
222
	uint32_t i = buckets[h1 % nbuckets];
223

224
	if (!i) return 0;
225

226
	hashval = buckets + nbuckets + (i - hashtab[1]);
227

228
	for (h1 |= 1; ; i++) {
229
		h2 = *hashval++;
230 231 232
		if ((!dso->versym || dso->versym[i] >= 0)
		    && (h1 == (h2|1)) && !strcmp(s, strings + syms[i].st_name))
			return syms+i;
233 234 235 236 237 238
		if (h2 & 1) break;
	}

	return 0;
}

239
#define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS)
240
#define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
R
Rich Felker 已提交
241

242 243 244 245
#ifndef ARCH_SYM_REJECT_UND
#define ARCH_SYM_REJECT_UND(s) 0
#endif

246
static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
R
Rich Felker 已提交
247
{
248
	uint32_t h = 0, gh = 0;
249
	struct symdef def = {0};
R
Rich Felker 已提交
250
	for (; dso; dso=dso->next) {
251 252
		Sym *sym;
		if (!dso->global) continue;
253 254 255 256 257 258 259
		if (dso->ghashtab) {
			if (!gh) gh = gnu_hash(s);
			sym = gnu_lookup(s, gh, dso);
		} else {
			if (!h) h = sysv_hash(s);
			sym = sysv_lookup(s, h, dso);
		}
260 261
		if (!sym) continue;
		if (!sym->st_shndx)
262 263
			if (need_def || (sym->st_info&0xf) == STT_TLS
			    || ARCH_SYM_REJECT_UND(sym))
264 265 266 267 268 269 270 271 272 273 274
				continue;
		if (!sym->st_value)
			if ((sym->st_info&0xf) != STT_TLS)
				continue;
		if (!(1<<(sym->st_info&0xf) & OK_TYPES)) continue;
		if (!(1<<(sym->st_info>>4) & OK_BINDS)) continue;

		if (def.sym && sym->st_info>>4 == STB_WEAK) continue;
		def.sym = sym;
		def.dso = dso;
		if (sym->st_info>>4 == STB_GLOBAL) break;
R
Rich Felker 已提交
275
	}
276
	return def;
R
Rich Felker 已提交
277 278
}

279 280
#define NO_INLINE_ADDEND (1<<REL_COPY | 1<<REL_GOT | 1<<REL_PLT)

281 282
ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic();

283
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
R
Rich Felker 已提交
284
{
285 286 287
	unsigned char *base = dso->base;
	Sym *syms = dso->syms;
	char *strings = dso->strings;
R
Rich Felker 已提交
288 289 290
	Sym *sym;
	const char *name;
	void *ctx;
291
	int astype, type;
R
Rich Felker 已提交
292
	int sym_index;
293
	struct symdef def;
294 295 296 297
	size_t *reloc_addr;
	size_t sym_val;
	size_t tls_val;
	size_t addend;
R
Rich Felker 已提交
298 299

	for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
300 301 302 303
		astype = R_TYPE(rel[1]);
		if (!astype) continue;
		type = remap_rel(astype);
		if (!type) {
304
			error("Error relocating %s: unsupported relocation type %d",
305 306 307
				dso->name, astype);
			continue;
		}
R
Rich Felker 已提交
308
		sym_index = R_SYM(rel[1]);
309
		reloc_addr = (void *)(base + rel[0]);
R
Rich Felker 已提交
310 311 312
		if (sym_index) {
			sym = syms + sym_index;
			name = strings + sym->st_name;
313 314
			ctx = type==REL_COPY ? head->next : head;
			def = find_sym(ctx, name, type==REL_PLT);
315 316
			if (!def.sym && (sym->st_shndx != SHN_UNDEF
			    || sym->st_info>>4 != STB_WEAK)) {
317
				error("Error relocating %s: %s: symbol not found",
318
					dso->name, name);
319
				continue;
R
Rich Felker 已提交
320
			}
321
		} else {
322 323
			sym = 0;
			def.sym = 0;
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
			def.dso = dso;
		}

		addend = stride>2 ? rel[2]
			: (1<<type & NO_INLINE_ADDEND) ? 0
			: *reloc_addr;

		sym_val = def.sym ? (size_t)def.dso->base+def.sym->st_value : 0;
		tls_val = def.sym ? def.sym->st_value : 0;

		switch(type) {
		case REL_OFFSET:
			addend -= (size_t)reloc_addr;
		case REL_SYMBOLIC:
		case REL_GOT:
		case REL_PLT:
			*reloc_addr = sym_val + addend;
			break;
		case REL_RELATIVE:
			*reloc_addr = (size_t)base + addend;
			break;
		case REL_SYM_OR_REL:
			if (sym) *reloc_addr = sym_val + addend;
			else *reloc_addr = (size_t)base + addend;
			break;
		case REL_COPY:
			memcpy(reloc_addr, (void *)sym_val, sym->st_size);
			break;
		case REL_OFFSET32:
			*(uint32_t *)reloc_addr = sym_val + addend
				- (size_t)reloc_addr;
			break;
		case REL_DTPMOD:
			*reloc_addr = def.dso->tls_id;
			break;
		case REL_DTPOFF:
			*reloc_addr = tls_val + addend;
			break;
#ifdef TLS_ABOVE_TP
		case REL_TPOFF:
			*reloc_addr = tls_val + def.dso->tls_offset + TPOFF_K + addend;
			break;
#else
		case REL_TPOFF:
			*reloc_addr = tls_val - def.dso->tls_offset + addend;
			break;
		case REL_TPOFF_NEG:
			*reloc_addr = def.dso->tls_offset - tls_val + addend;
			break;
#endif
374 375 376 377
		case REL_TLSDESC:
			if (stride<3) addend = reloc_addr[1];
			if (runtime && def.dso->tls_id >= static_tls_cnt) {
				struct td_index *new = malloc(sizeof *new);
378
				if (!new) error(
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
					"Error relocating %s: cannot allocate TLSDESC for %s",
					dso->name, sym ? name : "(local)" );
				new->next = dso->td_index;
				dso->td_index = new;
				new->args[0] = def.dso->tls_id;
				new->args[1] = tls_val + addend;
				reloc_addr[0] = (size_t)__tlsdesc_dynamic;
				reloc_addr[1] = (size_t)new;
			} else {
				reloc_addr[0] = (size_t)__tlsdesc_static;
#ifdef TLS_ABOVE_TP
				reloc_addr[1] = tls_val + def.dso->tls_offset
					+ TPOFF_K + addend;
#else
				reloc_addr[1] = tls_val - def.dso->tls_offset
					+ addend;
#endif
			}
			break;
R
Rich Felker 已提交
398 399 400 401
		}
	}
}

402 403 404 405 406 407
/* A huge hack: to make up for the wastefulness of shared libraries
 * needing at least a page of dirty memory even if they have no global
 * data, we reclaim the gaps at the beginning and end of writable maps
 * and "donate" them to the heap by setting up minimal malloc
 * structures and then freeing them. */

T
Timo Teräs 已提交
408
static void reclaim(struct dso *dso, size_t start, size_t end)
409 410
{
	size_t *a, *z;
T
Timo Teräs 已提交
411 412
	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;
413 414 415
	start = start + 6*sizeof(size_t)-1 & -4*sizeof(size_t);
	end = (end & -4*sizeof(size_t)) - 2*sizeof(size_t);
	if (start>end || end-start < 4*sizeof(size_t)) return;
T
Timo Teräs 已提交
416 417
	a = (size_t *)(dso->base + start);
	z = (size_t *)(dso->base + end);
418 419 420 421 422 423
	a[-2] = 1;
	a[-1] = z[0] = end-start + 2*sizeof(size_t) | 1;
	z[1] = 1;
	free(a);
}

424
static void reclaim_gaps(struct dso *dso)
425
{
426 427
	Phdr *ph = dso->phdr;
	size_t phcnt = dso->phnum;
428

429
	for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
430 431
		if (ph->p_type!=PT_LOAD) continue;
		if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
T
Timo Teräs 已提交
432 433
		reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
		reclaim(dso, ph->p_vaddr+ph->p_memsz,
434 435 436 437
			ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE);
	}
}

438
static void *map_library(int fd, struct dso *dso)
R
Rich Felker 已提交
439
{
440
	Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
441
	void *allocated_buf=0;
R
Rich Felker 已提交
442 443 444 445 446
	size_t phsize;
	size_t addr_min=SIZE_MAX, addr_max=0, map_len;
	size_t this_min, this_max;
	off_t off_start;
	Ehdr *eh;
447
	Phdr *ph, *ph0;
R
Rich Felker 已提交
448
	unsigned prot;
449
	unsigned char *map=MAP_FAILED, *base;
450
	size_t dyn=0;
451
	size_t tls_image=0;
R
Rich Felker 已提交
452 453 454
	size_t i;

	ssize_t l = read(fd, buf, sizeof buf);
455
	eh = buf;
456 457 458
	if (l<0) return 0;
	if (l<sizeof *eh || (eh->e_type != ET_DYN && eh->e_type != ET_EXEC))
		goto noexec;
R
Rich Felker 已提交
459
	phsize = eh->e_phentsize * eh->e_phnum;
460 461 462 463 464 465 466 467
	if (phsize > sizeof buf - sizeof *eh) {
		allocated_buf = malloc(phsize);
		if (!allocated_buf) return 0;
		l = pread(fd, allocated_buf, phsize, eh->e_phoff);
		if (l < 0) goto error;
		if (l != phsize) goto noexec;
		ph = ph0 = allocated_buf;
	} else if (eh->e_phoff + phsize > l) {
468
		l = pread(fd, buf+1, phsize, eh->e_phoff);
469 470
		if (l < 0) goto error;
		if (l != phsize) goto noexec;
471 472 473
		ph = ph0 = (void *)(buf + 1);
	} else {
		ph = ph0 = (void *)((char *)buf + eh->e_phoff);
R
Rich Felker 已提交
474 475
	}
	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
476
		if (ph->p_type == PT_DYNAMIC) {
R
Rich Felker 已提交
477
			dyn = ph->p_vaddr;
478
		} else if (ph->p_type == PT_TLS) {
479 480 481 482
			tls_image = ph->p_vaddr;
			dso->tls_align = ph->p_align;
			dso->tls_len = ph->p_filesz;
			dso->tls_size = ph->p_memsz;
T
Timo Teräs 已提交
483 484 485
		} else if (ph->p_type == PT_GNU_RELRO) {
			dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
			dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
486
		}
R
Rich Felker 已提交
487 488 489 490 491 492 493 494 495 496 497 498
		if (ph->p_type != PT_LOAD) continue;
		if (ph->p_vaddr < addr_min) {
			addr_min = ph->p_vaddr;
			off_start = ph->p_offset;
			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
		}
		if (ph->p_vaddr+ph->p_memsz > addr_max) {
			addr_max = ph->p_vaddr+ph->p_memsz;
		}
	}
499
	if (!dyn) goto noexec;
R
Rich Felker 已提交
500 501 502 503 504 505 506 507 508
	addr_max += PAGE_SIZE-1;
	addr_max &= -PAGE_SIZE;
	addr_min &= -PAGE_SIZE;
	off_start &= -PAGE_SIZE;
	map_len = addr_max - addr_min + off_start;
	/* The first time, we map too much, possibly even more than
	 * the length of the file. This is okay because we will not
	 * use the invalid part; we just need to reserve the right
	 * amount of virtual address space to map over later. */
509
	map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
510
	if (map==MAP_FAILED) goto error;
511 512 513 514 515 516
	/* If the loaded file is not relocatable and the requested address is
	 * not available, then the load operation must fail. */
	if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
		errno = EBUSY;
		goto error;
	}
R
Rich Felker 已提交
517
	base = map - addr_min;
518 519 520
	dso->phdr = 0;
	dso->phnum = 0;
	for (ph=ph0, i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
R
Rich Felker 已提交
521
		if (ph->p_type != PT_LOAD) continue;
522 523 524 525 526 527 528
		/* Check if the programs headers are in this load segment, and
		 * if so, record the address for use by dl_iterate_phdr. */
		if (!dso->phdr && eh->e_phoff >= ph->p_offset
		    && eh->e_phoff+phsize <= ph->p_offset+ph->p_filesz) {
			dso->phdr = (void *)(base + ph->p_vaddr
				+ (eh->e_phoff-ph->p_offset));
			dso->phnum = eh->e_phnum;
529
			dso->phentsize = eh->e_phentsize;
530
		}
R
Rich Felker 已提交
531 532 533 534 535 536 537 538
		/* Reuse the existing mapping for the lowest-address LOAD */
		if ((ph->p_vaddr & -PAGE_SIZE) == addr_min) continue;
		this_min = ph->p_vaddr & -PAGE_SIZE;
		this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE;
		off_start = ph->p_offset & -PAGE_SIZE;
		prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
			((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
			((ph->p_flags&PF_X) ? PROT_EXEC : 0));
539 540
		if (mmap(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
			goto error;
R
Rich Felker 已提交
541 542 543 544
		if (ph->p_memsz > ph->p_filesz) {
			size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
			size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
			memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
545 546
			if (pgbrk-(size_t)base < this_max && mmap((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
				goto error;
R
Rich Felker 已提交
547 548
		}
	}
R
Rich Felker 已提交
549 550
	for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
		if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
551 552
			if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
				goto error;
R
Rich Felker 已提交
553 554
			break;
		}
555 556 557 558 559
	dso->map = map;
	dso->map_len = map_len;
	dso->base = base;
	dso->dynv = (void *)(base+dyn);
	if (dso->tls_size) dso->tls_image = (void *)(base+tls_image);
560
	if (!runtime) reclaim_gaps(dso);
561
	free(allocated_buf);
R
Rich Felker 已提交
562
	return map;
563 564
noexec:
	errno = ENOEXEC;
565
error:
566 567
	if (map!=MAP_FAILED) munmap(map, map_len);
	free(allocated_buf);
568
	return 0;
R
Rich Felker 已提交
569 570
}

571
static int path_open(const char *name, const char *s, char *buf, size_t buf_size)
572
{
573 574
	size_t l;
	int fd;
575
	for (;;) {
576 577 578
		s += strspn(s, ":\n");
		l = strcspn(s, ":\n");
		if (l-1 >= INT_MAX) return -1;
579 580 581 582 583 584 585 586 587 588 589 590 591 592
		if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) {
			if ((fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) return fd;
			switch (errno) {
			case ENOENT:
			case ENOTDIR:
			case EACCES:
			case ENAMETOOLONG:
				break;
			default:
				/* Any negative value but -1 will inhibit
				 * futher path search. */
				return -2;
			}
		}
593
		s += l;
594 595 596
	}
}

597 598 599 600 601 602 603 604 605 606 607 608 609
static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
{
	size_t n, l;
	const char *s, *t, *origin;
	char *d;
	if (p->rpath) return 0;
	if (!p->rpath_orig) return -1;
	if (!strchr(p->rpath_orig, '$')) {
		p->rpath = p->rpath_orig;
		return 0;
	}
	n = 0;
	s = p->rpath_orig;
R
Rich Felker 已提交
610 611 612
	while ((t=strchr(s, '$'))) {
		if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9))
			return -1;
613 614 615 616 617 618 619 620 621 622 623 624 625 626
		s = t+1;
		n++;
	}
	if (n > SSIZE_MAX/PATH_MAX) return -1;

	if (p->kernel_mapped) {
		/* $ORIGIN searches cannot be performed for the main program
		 * when it is suid/sgid/AT_SECURE. This is because the
		 * pathname is under the control of the caller of execve.
		 * For libraries, however, $ORIGIN can be processed safely
		 * since the library's pathname came from a trusted source
		 * (either system paths or a call to dlopen). */
		if (libc.secure)
			return -1;
R
Rich Felker 已提交
627 628
		l = readlink("/proc/self/exe", buf, buf_size);
		if (l >= buf_size)
629
			return -1;
R
Rich Felker 已提交
630
		buf[l] = 0;
631 632 633 634 635 636 637 638 639 640 641
		origin = buf;
	} else {
		origin = p->name;
	}
	t = strrchr(origin, '/');
	l = t ? t-origin : 0;
	p->rpath = malloc(strlen(p->rpath_orig) + n*l + 1);
	if (!p->rpath) return -1;

	d = p->rpath;
	s = p->rpath_orig;
R
Rich Felker 已提交
642
	while ((t=strchr(s, '$'))) {
643 644 645 646
		memcpy(d, s, t-s);
		d += t-s;
		memcpy(d, origin, l);
		d += l;
R
Rich Felker 已提交
647 648
		/* It was determined previously that the '$' is followed
		 * either by "ORIGIN" or "{ORIGIN}". */
649 650 651 652 653 654
		s = t + 7 + 2*(t[1]=='{');
	}
	strcpy(d, s);
	return 0;
}

655 656 657 658 659 660
static void decode_dyn(struct dso *p)
{
	size_t dyn[DYN_CNT] = {0};
	decode_vec(p->dynv, dyn, DYN_CNT);
	p->syms = (void *)(p->base + dyn[DT_SYMTAB]);
	p->strings = (void *)(p->base + dyn[DT_STRTAB]);
661 662
	if (dyn[0]&(1<<DT_HASH))
		p->hashtab = (void *)(p->base + dyn[DT_HASH]);
663
	if (dyn[0]&(1<<DT_RPATH))
664
		p->rpath_orig = (void *)(p->strings + dyn[DT_RPATH]);
665 666
	if (dyn[0]&(1<<DT_RUNPATH))
		p->rpath_orig = (void *)(p->strings + dyn[DT_RUNPATH]);
667 668
	if (search_vec(p->dynv, dyn, DT_GNU_HASH))
		p->ghashtab = (void *)(p->base + *dyn);
669 670
	if (search_vec(p->dynv, dyn, DT_VERSYM))
		p->versym = (void *)(p->base + *dyn);
671 672
}

673
static struct dso *load_library(const char *name, struct dso *needed_by)
R
Rich Felker 已提交
674
{
675
	char buf[2*NAME_MAX+2];
676
	const char *pathname;
677
	unsigned char *map;
678
	struct dso *p, temp_dso = {0};
R
Rich Felker 已提交
679 680
	int fd;
	struct stat st;
681 682
	size_t alloc_size;
	int n_th = 0;
683
	int is_self = 0;
R
Rich Felker 已提交
684

685 686 687 688 689
	if (!*name) {
		errno = EINVAL;
		return 0;
	}

R
Rich Felker 已提交
690 691 692 693 694 695 696
	/* Catch and block attempts to reload the implementation itself */
	if (name[0]=='l' && name[1]=='i' && name[2]=='b') {
		static const char *rp, reserved[] =
			"c\0pthread\0rt\0m\0dl\0util\0xnet\0";
		char *z = strchr(name, '.');
		if (z) {
			size_t l = z-name;
697
			for (rp=reserved; *rp && strncmp(name+3, rp, l-3); rp+=strlen(rp)+1);
R
Rich Felker 已提交
698
			if (*rp) {
699 700 701 702 703 704 705 706 707 708 709 710
				if (ldd_mode) {
					/* Track which names have been resolved
					 * and only report each one once. */
					static unsigned reported;
					unsigned mask = 1U<<(rp-reserved);
					if (!(reported & mask)) {
						reported |= mask;
						dprintf(1, "\t%s => %s (%p)\n",
							name, ldso->name,
							ldso->base);
					}
				}
711
				is_self = 1;
R
Rich Felker 已提交
712 713 714
			}
		}
	}
715 716 717 718 719 720 721 722 723
	if (!strcmp(name, ldso->name)) is_self = 1;
	if (is_self) {
		if (!ldso->prev) {
			tail->next = ldso;
			ldso->prev = tail;
			tail = ldso->next ? ldso->next : ldso;
		}
		return ldso;
	}
724
	if (strchr(name, '/')) {
725
		pathname = name;
726
		fd = open(name, O_RDONLY|O_CLOEXEC);
R
Rich Felker 已提交
727
	} else {
728 729 730 731 732 733 734
		/* Search for the name to see if it's already loaded */
		for (p=head->next; p; p=p->next) {
			if (p->shortname && !strcmp(p->shortname, name)) {
				p->refcnt++;
				return p;
			}
		}
735
		if (strlen(name) > NAME_MAX) return 0;
736
		fd = -1;
737
		if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
738
		for (p=needed_by; fd == -1 && p; p=p->needed_by)
739
			if (!fixup_rpath(p, buf, sizeof buf))
740
				fd = path_open(name, p->rpath, buf, sizeof buf);
741
		if (fd == -1) {
742
			if (!sys_path) {
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
				char *prefix = 0;
				size_t prefix_len;
				if (ldso->name[0]=='/') {
					char *s, *t, *z;
					for (s=t=z=ldso->name; *s; s++)
						if (*s=='/') z=t, t=s;
					prefix_len = z-ldso->name;
					if (prefix_len < PATH_MAX)
						prefix = ldso->name;
				}
				if (!prefix) {
					prefix = "";
					prefix_len = 0;
				}
				char etc_ldso_path[prefix_len + 1
					+ sizeof "/etc/ld-musl-" LDSO_ARCH ".path"];
				snprintf(etc_ldso_path, sizeof etc_ldso_path,
					"%.*s/etc/ld-musl-" LDSO_ARCH ".path",
					(int)prefix_len, prefix);
				FILE *f = fopen(etc_ldso_path, "rbe");
763
				if (f) {
764
					if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) {
765
						free(sys_path);
766
						sys_path = "";
767
					}
768
					fclose(f);
769 770
				} else if (errno != ENOENT) {
					sys_path = "";
771 772
				}
			}
773 774
			if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib";
			fd = path_open(name, sys_path, buf, sizeof buf);
R
Rich Felker 已提交
775
		}
776
		pathname = buf;
R
Rich Felker 已提交
777 778 779 780 781 782 783 784
	}
	if (fd < 0) return 0;
	if (fstat(fd, &st) < 0) {
		close(fd);
		return 0;
	}
	for (p=head->next; p; p=p->next) {
		if (p->dev == st.st_dev && p->ino == st.st_ino) {
785 786 787
			/* If this library was previously loaded with a
			 * pathname but a search found the same inode,
			 * setup its shortname so it can be found by name. */
788 789
			if (!p->shortname && pathname != name)
				p->shortname = strrchr(p->name, '/')+1;
R
Rich Felker 已提交
790 791 792 793 794
			close(fd);
			p->refcnt++;
			return p;
		}
	}
795
	map = noload ? 0 : map_library(fd, &temp_dso);
R
Rich Felker 已提交
796 797
	close(fd);
	if (!map) return 0;
798 799 800 801 802 803 804 805 806 807

	/* Allocate storage for the new DSO. When there is TLS, this
	 * storage must include a reservation for all pre-existing
	 * threads to obtain copies of both the new TLS, and an
	 * extended DTV capable of storing an additional slot for
	 * the newly-loaded DSO. */
	alloc_size = sizeof *p + strlen(pathname) + 1;
	if (runtime && temp_dso.tls_image) {
		size_t per_th = temp_dso.tls_size + temp_dso.tls_align
			+ sizeof(void *) * (tls_cnt+3);
808
		n_th = libc.threads_minus_1 + 1;
809 810 811 812
		if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX;
		else alloc_size += n_th * per_th;
	}
	p = calloc(1, alloc_size);
R
Rich Felker 已提交
813
	if (!p) {
814
		munmap(map, temp_dso.map_len);
R
Rich Felker 已提交
815 816
		return 0;
	}
817
	memcpy(p, &temp_dso, sizeof temp_dso);
818
	decode_dyn(p);
R
Rich Felker 已提交
819 820 821
	p->dev = st.st_dev;
	p->ino = st.st_ino;
	p->refcnt = 1;
822
	p->needed_by = needed_by;
R
Rich Felker 已提交
823
	p->name = p->buf;
824 825 826
	strcpy(p->name, pathname);
	/* Add a shortname only if name arg was not an explicit pathname. */
	if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
827
	if (p->tls_image) {
828
		if (runtime && !libc.has_thread_pointer) {
829
			munmap(map, p->map_len);
830
			free(p);
831
			errno = ENOSYS;
832 833
			return 0;
		}
834
		p->tls_id = ++tls_cnt;
R
Rich Felker 已提交
835
		tls_align = MAXP2(tls_align, p->tls_align);
836 837 838 839 840
#ifdef TLS_ABOVE_TP
		p->tls_offset = tls_offset + ( (tls_align-1) &
			-(tls_offset + (uintptr_t)p->tls_image) );
		tls_offset += p->tls_size;
#else
R
Rich Felker 已提交
841 842 843 844
		tls_offset += p->tls_size + p->tls_align - 1;
		tls_offset -= (tls_offset + (uintptr_t)p->tls_image)
			& (p->tls_align-1);
		p->tls_offset = tls_offset;
845
#endif
846 847 848 849
		p->new_dtv = (void *)(-sizeof(size_t) &
			(uintptr_t)(p->name+strlen(p->name)+sizeof(size_t)));
		p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1));
	}
R
Rich Felker 已提交
850 851 852 853 854

	tail->next = p;
	p->prev = tail;
	tail = p;

855
	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
856

R
Rich Felker 已提交
857 858 859 860 861
	return p;
}

static void load_deps(struct dso *p)
{
862 863
	size_t i, ndeps=0;
	struct dso ***deps = &p->deps, **tmp, *dep;
R
Rich Felker 已提交
864 865 866
	for (; p; p=p->next) {
		for (i=0; p->dynv[i]; i+=2) {
			if (p->dynv[i] != DT_NEEDED) continue;
867
			dep = load_library(p->strings + p->dynv[i+1], p);
868
			if (!dep) {
869
				error("Error loading shared library %s: %m (needed by %s)",
R
Rich Felker 已提交
870
					p->strings + p->dynv[i+1], p->name);
871
				continue;
R
Rich Felker 已提交
872
			}
873 874
			if (runtime) {
				tmp = realloc(*deps, sizeof(*tmp)*(ndeps+2));
875
				if (!tmp) longjmp(*rtld_fail, 1);
876 877 878 879
				tmp[ndeps++] = dep;
				tmp[ndeps] = 0;
				*deps = tmp;
			}
R
Rich Felker 已提交
880 881 882 883
		}
	}
}

R
Rich Felker 已提交
884 885 886 887 888
static void load_preload(char *s)
{
	int tmp;
	char *z;
	for (z=s; *z; s=z) {
889 890
		for (   ; *s && (isspace(*s) || *s==':'); s++);
		for (z=s; *z && !isspace(*z) && *z!=':'; z++);
R
Rich Felker 已提交
891 892
		tmp = *z;
		*z = 0;
893
		load_library(s, 0);
R
Rich Felker 已提交
894 895 896 897
		*z = tmp;
	}
}

898 899 900 901 902
static void make_global(struct dso *p)
{
	for (; p; p=p->next) p->global = 1;
}

R
Rich Felker 已提交
903 904 905 906 907 908
static void reloc_all(struct dso *p)
{
	size_t dyn[DYN_CNT] = {0};
	for (; p; p=p->next) {
		if (p->relocated) continue;
		decode_vec(p->dynv, dyn, DYN_CNT);
R
Rich Felker 已提交
909 910 911
#ifdef NEED_ARCH_RELOCS
		do_arch_relocs(p, head);
#endif
912 913 914 915
		do_relocs(p, (void *)(p->base+dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
			2+(dyn[DT_PLTREL]==DT_RELA));
		do_relocs(p, (void *)(p->base+dyn[DT_REL]), dyn[DT_RELSZ], 2);
		do_relocs(p, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ], 3);
T
Timo Teräs 已提交
916 917 918

		if (p->relro_start != p->relro_end &&
		    mprotect(p->base+p->relro_start, p->relro_end-p->relro_start, PROT_READ) < 0) {
919
			error("Error relocating %s: RELRO protection failed: %m",
T
Timo Teräs 已提交
920 921 922
				p->name);
		}

923
		p->relocated = 1;
R
Rich Felker 已提交
924 925 926
	}
}

927
static void kernel_mapped_dso(struct dso *p)
928
{
929 930 931 932 933 934
	size_t min_addr = -1, max_addr = 0, cnt;
	Phdr *ph = p->phdr;
	for (cnt = p->phnum; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
		if (ph->p_type == PT_DYNAMIC) {
			p->dynv = (void *)(p->base + ph->p_vaddr);
		} else if (ph->p_type == PT_GNU_RELRO) {
T
Timo Teräs 已提交
935 936 937
			p->relro_start = ph->p_vaddr & -PAGE_SIZE;
			p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
		}
938 939 940 941 942 943 944 945 946 947
		if (ph->p_type != PT_LOAD) continue;
		if (ph->p_vaddr < min_addr)
			min_addr = ph->p_vaddr;
		if (ph->p_vaddr+ph->p_memsz > max_addr)
			max_addr = ph->p_vaddr+ph->p_memsz;
	}
	min_addr &= -PAGE_SIZE;
	max_addr = (max_addr + PAGE_SIZE-1) & -PAGE_SIZE;
	p->map = p->base + min_addr;
	p->map_len = max_addr - min_addr;
948
	p->kernel_mapped = 1;
949 950
}

951 952 953 954 955 956 957
static void do_fini()
{
	struct dso *p;
	size_t dyn[DYN_CNT] = {0};
	for (p=fini_head; p; p=p->fini_next) {
		if (!p->constructed) continue;
		decode_vec(p->dynv, dyn, DYN_CNT);
958 959
		if (dyn[0] & (1<<DT_FINI_ARRAY)) {
			size_t n = dyn[DT_FINI_ARRAYSZ]/sizeof(size_t);
960 961
			size_t *fn = (size_t *)(p->base + dyn[DT_FINI_ARRAY])+n;
			while (n--) ((void (*)(void))*--fn)();
962
		}
963
#ifndef NO_LEGACY_INITFINI
964
		if ((dyn[0] & (1<<DT_FINI)) && dyn[DT_FINI])
965
			((void (*)(void))(p->base + dyn[DT_FINI]))();
966
#endif
967 968 969
	}
}

970 971 972
static void do_init_fini(struct dso *p)
{
	size_t dyn[DYN_CNT] = {0};
973
	int need_locking = libc.threads_minus_1;
974 975 976 977
	/* Allow recursive calls that arise when a library calls
	 * dlopen from one of its constructors, but block any
	 * other threads until all ctors have finished. */
	if (need_locking) pthread_mutex_lock(&init_fini_lock);
978
	for (; p; p=p->prev) {
979 980
		if (p->constructed) continue;
		p->constructed = 1;
981
		decode_vec(p->dynv, dyn, DYN_CNT);
982
		if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) {
983 984 985
			p->fini_next = fini_head;
			fini_head = p;
		}
986
#ifndef NO_LEGACY_INITFINI
987
		if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT])
988
			((void (*)(void))(p->base + dyn[DT_INIT]))();
989
#endif
990 991 992 993 994
		if (dyn[0] & (1<<DT_INIT_ARRAY)) {
			size_t n = dyn[DT_INIT_ARRAYSZ]/sizeof(size_t);
			size_t *fn = (void *)(p->base + dyn[DT_INIT_ARRAY]);
			while (n--) ((void (*)(void))*fn++)();
		}
995 996 997 998
		if (!need_locking && libc.threads_minus_1) {
			need_locking = 1;
			pthread_mutex_lock(&init_fini_lock);
		}
999
	}
1000
	if (need_locking) pthread_mutex_unlock(&init_fini_lock);
1001 1002
}

1003 1004 1005 1006
void _dl_debug_state(void)
{
}

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
void __reset_tls()
{
	pthread_t self = __pthread_self();
	struct dso *p;
	for (p=head; p; p=p->next) {
		if (!p->tls_id || !self->dtv[p->tls_id]) continue;
		memcpy(self->dtv[p->tls_id], p->tls_image, p->tls_len);
		memset((char *)self->dtv[p->tls_id]+p->tls_len, 0,
			p->tls_size - p->tls_len);
		if (p->tls_id == (size_t)self->dtv[0]) break;
	}
}

1020
void *__copy_tls(unsigned char *mem)
1021
{
R
Rich Felker 已提交
1022
	pthread_t td;
1023
	struct dso *p;
R
Rich Felker 已提交
1024

1025
	void **dtv = (void *)mem;
1026
	dtv[0] = (void *)tls_cnt;
1027 1028
	if (!tls_cnt) {
		td = (void *)(dtv+1);
1029
		td->dtv = td->dtv_copy = dtv;
1030 1031
		return td;
	}
R
Rich Felker 已提交
1032

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
#ifdef TLS_ABOVE_TP
	mem += sizeof(void *) * (tls_cnt+1);
	mem += -((uintptr_t)mem + sizeof(struct pthread)) & (tls_align-1);
	td = (pthread_t)mem;
	mem += sizeof(struct pthread);

	for (p=head; p; p=p->next) {
		if (!p->tls_id) continue;
		dtv[p->tls_id] = mem + p->tls_offset;
		memcpy(dtv[p->tls_id], p->tls_image, p->tls_len);
	}
#else
1045
	mem += libc.tls_size - sizeof(struct pthread);
R
Rich Felker 已提交
1046 1047 1048 1049
	mem -= (uintptr_t)mem & (tls_align-1);
	td = (pthread_t)mem;

	for (p=head; p; p=p->next) {
1050
		if (!p->tls_id) continue;
R
Rich Felker 已提交
1051 1052
		dtv[p->tls_id] = mem - p->tls_offset;
		memcpy(dtv[p->tls_id], p->tls_image, p->tls_len);
1053
	}
1054
#endif
1055
	td->dtv = td->dtv_copy = dtv;
R
Rich Felker 已提交
1056
	return td;
1057 1058
}

1059
void *__tls_get_new(size_t *v)
1060 1061
{
	pthread_t self = __pthread_self();
1062 1063 1064

	/* Block signals to make accessing new TLS async-signal-safe */
	sigset_t set;
1065
	__block_all_sigs(&set);
1066
	if (v[0]<=(size_t)self->dtv[0]) {
1067
		__restore_sigs(&set);
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
		return (char *)self->dtv[v[0]]+v[1];
	}

	/* This is safe without any locks held because, if the caller
	 * is able to request the Nth entry of the DTV, the DSO list
	 * must be valid at least that far out and it was synchronized
	 * at program startup or by an already-completed call to dlopen. */
	struct dso *p;
	for (p=head; p->tls_id != v[0]; p=p->next);

	/* Get new DTV space from new DSO if needed */
1079
	if (v[0] > (size_t)self->dtv[0]) {
1080 1081
		void **newdtv = p->new_dtv +
			(v[0]+1)*sizeof(void *)*a_fetch_add(&p->new_dtv_idx,1);
1082
		memcpy(newdtv, self->dtv,
1083 1084
			((size_t)self->dtv[0]+1) * sizeof(void *));
		newdtv[0] = (void *)v[0];
1085
		self->dtv = self->dtv_copy = newdtv;
1086
	}
1087

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
	/* Get new TLS memory from all new DSOs up to the requested one */
	unsigned char *mem;
	for (p=head; ; p=p->next) {
		if (!p->tls_id || self->dtv[p->tls_id]) continue;
		mem = p->new_tls + (p->tls_size + p->tls_align)
			* a_fetch_add(&p->new_tls_idx,1);
		mem += ((uintptr_t)p->tls_image - (uintptr_t)mem)
			& (p->tls_align-1);
		self->dtv[p->tls_id] = mem;
		memcpy(mem, p->tls_image, p->tls_len);
		if (p->tls_id == v[0]) break;
	}
1100
	__restore_sigs(&set);
1101
	return mem + v[1];
1102 1103
}

R
Rich Felker 已提交
1104 1105
static void update_tls_size()
{
1106 1107 1108 1109 1110 1111
	libc.tls_size = ALIGN(
		(1+tls_cnt) * sizeof(void *) +
		tls_offset +
		sizeof(struct pthread) +
		tls_align * 2,
	tls_align);
R
Rich Felker 已提交
1112 1113
}

1114
void *__dynlink(int argc, char **argv)
R
Rich Felker 已提交
1115
{
1116
	size_t aux[AUX_CNT] = {0};
R
Rich Felker 已提交
1117 1118
	size_t i;
	Phdr *phdr;
1119
	Ehdr *ehdr;
1120
	static struct dso builtin_dsos[3];
R
Rich Felker 已提交
1121 1122
	struct dso *const app = builtin_dsos+0;
	struct dso *const lib = builtin_dsos+1;
1123
	struct dso *const vdso = builtin_dsos+2;
R
Rich Felker 已提交
1124
	char *env_preload=0;
R
Rich Felker 已提交
1125
	size_t vdso_base;
1126
	size_t *auxv;
1127
	char **envp = argv+argc+1;
1128
	void *initial_tls;
R
Rich Felker 已提交
1129 1130

	/* Find aux vector just past environ[] */
1131 1132 1133
	for (i=argc+1; argv[i]; i++)
		if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16))
			env_path = argv[i]+16;
R
Rich Felker 已提交
1134 1135
		else if (!memcmp(argv[i], "LD_PRELOAD=", 11))
			env_preload = argv[i]+11;
R
Rich Felker 已提交
1136 1137 1138 1139
	auxv = (void *)(argv+i+1);

	decode_vec(auxv, aux, AUX_CNT);

1140 1141
	/* Only trust user/env if kernel says we're not suid/sgid */
	if ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
R
Rich Felker 已提交
1142
	  || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]) {
1143
		env_path = 0;
R
Rich Felker 已提交
1144
		env_preload = 0;
1145
		libc.secure = 1;
1146
	}
1147
	libc.page_size = aux[AT_PAGESZ];
1148
	libc.auxv = auxv;
1149

1150 1151 1152 1153 1154 1155 1156 1157 1158
	/* If the dynamic linker was invoked as a program itself, AT_BASE
	 * will not be set. In that case, we assume the base address is
	 * the start of the page containing the PHDRs; I don't know any
	 * better approach... */
	if (!aux[AT_BASE]) {
		aux[AT_BASE] = aux[AT_PHDR] & -PAGE_SIZE;
		aux[AT_PHDR] = aux[AT_PHENT] = aux[AT_PHNUM] = 0;
	}

1159 1160 1161
	/* The dynamic linker load address is passed by the kernel
	 * in the AUX vector, so this is easy. */
	lib->base = (void *)aux[AT_BASE];
1162
	lib->name = lib->shortname = "libc.so";
1163 1164
	lib->global = 1;
	ehdr = (void *)lib->base;
R
Rich Felker 已提交
1165 1166
	lib->phnum = ehdr->e_phnum;
	lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff);
1167 1168
	lib->phentsize = ehdr->e_phentsize;
	kernel_mapped_dso(lib);
1169 1170
	decode_dyn(lib);

1171
	if (aux[AT_PHDR]) {
1172
		size_t interp_off = 0;
1173
		size_t tls_image = 0;
1174
		/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
R
Rich Felker 已提交
1175 1176
		app->phdr = phdr = (void *)aux[AT_PHDR];
		app->phnum = aux[AT_PHNUM];
1177
		app->phentsize = aux[AT_PHENT];
1178 1179 1180
		for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
			if (phdr->p_type == PT_PHDR)
				app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
1181 1182
			else if (phdr->p_type == PT_INTERP)
				interp_off = (size_t)phdr->p_vaddr;
1183 1184 1185 1186 1187 1188
			else if (phdr->p_type == PT_TLS) {
				tls_image = phdr->p_vaddr;
				app->tls_len = phdr->p_filesz;
				app->tls_size = phdr->p_memsz;
				app->tls_align = phdr->p_align;
			}
1189
		}
1190
		if (app->tls_size) app->tls_image = (char *)app->base + tls_image;
1191
		if (interp_off) lib->name = (char *)app->base + interp_off;
1192 1193 1194 1195 1196
		if ((aux[0] & (1UL<<AT_EXECFN))
		    && strncmp((char *)aux[AT_EXECFN], "/proc/", 6))
			app->name = (char *)aux[AT_EXECFN];
		else
			app->name = argv[0];
1197
		kernel_mapped_dso(app);
1198 1199 1200
	} else {
		int fd;
		char *ldname = argv[0];
R
Rich Felker 已提交
1201
		size_t l = strlen(ldname);
1202 1203
		if (l >= 3 && !strcmp(ldname+l-3, "ldd")) ldd_mode = 1;
		*argv++ = (void *)-1;
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
		while (argv[0] && argv[0][0]=='-' && argv[0][1]=='-') {
			char *opt = argv[0]+2;
			*argv++ = (void *)-1;
			if (!*opt) {
				break;
			} else if (!memcmp(opt, "list", 5)) {
				ldd_mode = 1;
			} else if (!memcmp(opt, "library-path", 12)) {
				if (opt[12]=='=') env_path = opt+13;
				else if (opt[12]) *argv = 0;
				else if (*argv) env_path = *argv++;
			} else if (!memcmp(opt, "preload", 7)) {
				if (opt[7]=='=') env_preload = opt+8;
				else if (opt[7]) *argv = 0;
				else if (*argv) env_preload = *argv++;
			} else {
				argv[0] = 0;
			}
			argv[-1] = (void *)-1;
		}
1224
		if (!argv[0]) {
1225 1226 1227
			dprintf(2, "musl libc\n"
				"Version %s\n"
				"Dynamic Program Loader\n"
1228
				"Usage: %s [options] [--] pathname%s\n",
1229
				__libc_get_version(), ldname,
1230 1231 1232 1233 1234 1235 1236 1237 1238
				ldd_mode ? "" : " [args]");
			_exit(1);
		}
		fd = open(argv[0], O_RDONLY);
		if (fd < 0) {
			dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
			_exit(1);
		}
		runtime = 1;
1239
		ehdr = (void *)map_library(fd, app);
1240 1241 1242 1243 1244 1245
		if (!ehdr) {
			dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
			_exit(1);
		}
		runtime = 0;
		close(fd);
1246
		lib->name = ldname;
1247
		app->name = argv[0];
1248
		aux[AT_ENTRY] = (size_t)app->base + ehdr->e_entry;
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
		/* Find the name that would have been used for the dynamic
		 * linker had ldd not taken its place. */
		if (ldd_mode) {
			for (i=0; i<app->phnum; i++) {
				if (app->phdr[i].p_type == PT_INTERP)
					lib->name = (void *)(app->base
						+ app->phdr[i].p_vaddr);
			}
			dprintf(1, "\t%s (%p)\n", lib->name, lib->base);
		}
1259
	}
1260
	if (app->tls_size) {
R
Rich Felker 已提交
1261
		app->tls_id = tls_cnt = 1;
1262 1263 1264 1265 1266 1267
#ifdef TLS_ABOVE_TP
		app->tls_offset = 0;
		tls_offset = app->tls_size
			+ ( -((uintptr_t)app->tls_image + app->tls_size)
			& (app->tls_align-1) );
#else
1268 1269 1270
		tls_offset = app->tls_offset = app->tls_size
			+ ( -((uintptr_t)app->tls_image + app->tls_size)
			& (app->tls_align-1) );
1271
#endif
R
Rich Felker 已提交
1272
		tls_align = MAXP2(tls_align, app->tls_align);
1273
	}
1274 1275 1276 1277
	app->global = 1;
	decode_dyn(app);

	/* Attach to vdso, if provided by the kernel */
R
Rich Felker 已提交
1278
	if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR)) {
1279
		ehdr = (void *)vdso_base;
R
Rich Felker 已提交
1280 1281
		vdso->phdr = phdr = (void *)(vdso_base + ehdr->e_phoff);
		vdso->phnum = ehdr->e_phnum;
1282
		vdso->phentsize = ehdr->e_phentsize;
1283 1284 1285 1286 1287 1288
		for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
			if (phdr->p_type == PT_DYNAMIC)
				vdso->dynv = (void *)(vdso_base + phdr->p_offset);
			if (phdr->p_type == PT_LOAD)
				vdso->base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset);
		}
1289 1290
		vdso->name = "";
		vdso->shortname = "linux-gate.so.1";
1291
		vdso->global = 1;
1292
		decode_dyn(vdso);
1293 1294 1295 1296
		vdso->prev = lib;
		lib->next = vdso;
	}

1297 1298 1299 1300 1301
	/* Initial dso chain consists only of the app. We temporarily
	 * append the dynamic linker/libc so we can relocate it, then
	 * restore the initial chain in preparation for loading third
	 * party libraries (preload/needed). */
	head = tail = app;
1302
	ldso = lib;
1303 1304 1305
	app->next = lib;
	reloc_all(lib);
	app->next = 0;
R
Rich Felker 已提交
1306

1307
	/* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */
R
Rich Felker 已提交
1308

1309
	/* Donate unused parts of app and library mapping to malloc */
1310 1311
	reclaim_gaps(app);
	reclaim_gaps(lib);
1312

1313
	/* Load preload/needed libraries, add their symbols to the global
1314 1315 1316
	 * namespace, and perform all remaining relocations. The main
	 * program must be relocated LAST since it may contain copy
	 * relocations which depend on libraries' relocations. */
R
Rich Felker 已提交
1317
	if (env_preload) load_preload(env_preload);
1318 1319
	load_deps(app);
	make_global(app);
1320

T
Timo Teräs 已提交
1321 1322 1323 1324 1325 1326
#ifndef DYNAMIC_IS_RO
	for (i=0; app->dynv[i]; i+=2)
		if (app->dynv[i]==DT_DEBUG)
			app->dynv[i+1] = (size_t)&debug;
#endif

R
Rich Felker 已提交
1327 1328 1329 1330
	reloc_all(app->next);
	reloc_all(app);

	update_tls_size();
1331 1332 1333
	if (libc.tls_size > sizeof builtin_tls) {
		initial_tls = calloc(libc.tls_size, 1);
		if (!initial_tls) {
1334
			dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
1335
				argv[0], libc.tls_size);
1336 1337
			_exit(127);
		}
1338 1339 1340 1341 1342 1343
	} else {
		initial_tls = builtin_tls;
	}
	if (__init_tp(__copy_tls(initial_tls)) < 0 && tls_cnt) {
		dprintf(2, "%s: Thread-local storage not supported by kernel.\n", argv[0]);
		_exit(127);
1344
	}
1345
	static_tls_cnt = tls_cnt;
1346

1347
	if (ldso_fail) _exit(127);
1348 1349
	if (ldd_mode) _exit(0);

1350 1351 1352 1353
	/* Switch to runtime mode: any further failures in the dynamic
	 * linker are a reportable failure rather than a fatal startup
	 * error. If the dynamic loader (dlopen) will not be used, free
	 * all memory used by the dynamic linker. */
R
Rich Felker 已提交
1354
	runtime = 1;
1355

1356 1357 1358 1359 1360 1361 1362
	debug.ver = 1;
	debug.bp = _dl_debug_state;
	debug.head = head;
	debug.base = lib->base;
	debug.state = 0;
	_dl_debug_state();

1363
	__init_libc(envp, argv[0]);
1364
	atexit(do_fini);
1365
	errno = 0;
1366
	do_init_fini(tail);
1367 1368

	return (void *)aux[AT_ENTRY];
1369 1370
}

1371 1372
void *dlopen(const char *file, int mode)
{
R
Rich Felker 已提交
1373
	struct dso *volatile p, *orig_tail, *next;
R
Rich Felker 已提交
1374
	size_t orig_tls_cnt, orig_tls_offset, orig_tls_align;
1375
	size_t i;
1376
	int cs;
1377
	jmp_buf jb;
1378 1379 1380

	if (!file) return head;

1381
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
1382
	pthread_rwlock_wrlock(&lock);
1383
	__inhibit_ptc();
1384

1385 1386
	p = 0;
	orig_tls_cnt = tls_cnt;
R
Rich Felker 已提交
1387 1388
	orig_tls_offset = tls_offset;
	orig_tls_align = tls_align;
R
Rich Felker 已提交
1389
	orig_tail = tail;
1390
	noload = mode & RTLD_NOLOAD;
R
Rich Felker 已提交
1391

1392 1393
	rtld_fail = &jb;
	if (setjmp(*rtld_fail)) {
1394
		/* Clean up anything new that was (partially) loaded */
1395
		if (p && p->deps) for (i=0; p->deps[i]; i++)
1396 1397
			if (p->deps[i]->global < 0)
				p->deps[i]->global = 0;
1398 1399 1400
		for (p=orig_tail->next; p; p=next) {
			next = p->next;
			munmap(p->map, p->map_len);
1401 1402 1403 1404 1405
			while (p->td_index) {
				void *tmp = p->td_index->next;
				free(p->td_index);
				p->td_index = tmp;
			}
1406 1407 1408
			free(p->deps);
			free(p);
		}
1409
		tls_cnt = orig_tls_cnt;
R
Rich Felker 已提交
1410 1411
		tls_offset = orig_tls_offset;
		tls_align = orig_tls_align;
1412 1413
		tail = orig_tail;
		tail->next = 0;
1414
		p = 0;
1415 1416
		errflag = 1;
		goto end;
1417
	} else p = load_library(file, head);
R
Rich Felker 已提交
1418 1419

	if (!p) {
1420 1421 1422 1423
		snprintf(errbuf, sizeof errbuf, noload ?
			"Library %s is not already loaded" :
			"Error loading shared library %s: %m",
			file);
R
Rich Felker 已提交
1424
		errflag = 1;
1425
		goto end;
1426 1427 1428 1429 1430
	}

	/* First load handling */
	if (!p->deps) {
		load_deps(p);
R
Rich Felker 已提交
1431
		if (p->deps) for (i=0; p->deps[i]; i++)
1432 1433 1434
			if (!p->deps[i]->global)
				p->deps[i]->global = -1;
		if (!p->global) p->global = -1;
1435
		reloc_all(p);
R
Rich Felker 已提交
1436
		if (p->deps) for (i=0; p->deps[i]; i++)
1437 1438 1439
			if (p->deps[i]->global < 0)
				p->deps[i]->global = 0;
		if (p->global < 0) p->global = 0;
1440 1441 1442
	}

	if (mode & RTLD_GLOBAL) {
R
Rich Felker 已提交
1443
		if (p->deps) for (i=0; p->deps[i]; i++)
1444 1445 1446 1447
			p->deps[i]->global = 1;
		p->global = 1;
	}

R
Rich Felker 已提交
1448
	update_tls_size();
1449
	_dl_debug_state();
1450
	orig_tail = tail;
1451
end:
1452
	__release_ptc();
R
Rich Felker 已提交
1453
	if (p) gencnt++;
1454
	pthread_rwlock_unlock(&lock);
1455
	if (p) do_init_fini(orig_tail);
1456
	pthread_setcancelstate(cs, 0);
1457 1458 1459
	return p;
}

1460
static int invalid_dso_handle(void *h)
1461 1462 1463 1464 1465 1466 1467 1468
{
	struct dso *p;
	for (p=head; p; p=p->next) if (h==p) return 0;
	snprintf(errbuf, sizeof errbuf, "Invalid library handle %p", (void *)h);
	errflag = 1;
	return 1;
}

1469 1470
void *__tls_get_addr(size_t *);

R
Rich Felker 已提交
1471
static void *do_dlsym(struct dso *p, const char *s, void *ra)
1472 1473
{
	size_t i;
1474
	uint32_t h = 0, gh = 0;
1475
	Sym *sym;
1476
	if (p == head || p == RTLD_DEFAULT || p == RTLD_NEXT) {
1477 1478 1479
		if (p == RTLD_DEFAULT) {
			p = head;
		} else if (p == RTLD_NEXT) {
1480 1481
			for (p=head; p && (unsigned char *)ra-p->map>p->map_len; p=p->next);
			if (!p) p=head;
1482
			p = p->next;
1483
		}
1484
		struct symdef def = find_sym(p, s, 0);
1485
		if (!def.sym) goto failed;
1486 1487
		if ((def.sym->st_info&0xf) == STT_TLS)
			return __tls_get_addr((size_t []){def.dso->tls_id, def.sym->st_value});
1488
		return def.dso->base + def.sym->st_value;
R
Rich Felker 已提交
1489
	}
1490 1491
	if (p != RTLD_DEFAULT && p != RTLD_NEXT && invalid_dso_handle(p))
		return 0;
1492 1493 1494 1495 1496 1497 1498
	if (p->ghashtab) {
		gh = gnu_hash(s);
		sym = gnu_lookup(s, gh, p);
	} else {
		h = sysv_hash(s);
		sym = sysv_lookup(s, h, p);
	}
1499 1500
	if (sym && (sym->st_info&0xf) == STT_TLS)
		return __tls_get_addr((size_t []){p->tls_id, sym->st_value});
1501 1502 1503
	if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
		return p->base + sym->st_value;
	if (p->deps) for (i=0; p->deps[i]; i++) {
1504 1505
		if (p->deps[i]->ghashtab) {
			if (!gh) gh = gnu_hash(s);
1506
			sym = gnu_lookup(s, gh, p->deps[i]);
1507 1508 1509 1510
		} else {
			if (!h) h = sysv_hash(s);
			sym = sysv_lookup(s, h, p->deps[i]);
		}
1511 1512
		if (sym && (sym->st_info&0xf) == STT_TLS)
			return __tls_get_addr((size_t []){p->deps[i]->tls_id, sym->st_value});
1513 1514 1515
		if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
			return p->deps[i]->base + sym->st_value;
	}
1516
failed:
R
Rich Felker 已提交
1517
	errflag = 1;
1518
	snprintf(errbuf, sizeof errbuf, "Symbol not found: %s", s);
1519 1520 1521
	return 0;
}

1522
int __dladdr(const void *addr, Dl_info *info)
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
{
	struct dso *p;
	Sym *sym;
	uint32_t nsym;
	char *strings;
	size_t i;
	void *best = 0;
	char *bestname;

	pthread_rwlock_rdlock(&lock);
	for (p=head; p && (unsigned char *)addr-p->map>p->map_len; p=p->next);
	pthread_rwlock_unlock(&lock);

	if (!p) return 0;

	sym = p->syms;
	strings = p->strings;
	if (p->hashtab) {
		nsym = p->hashtab[1];
	} else {
		uint32_t *buckets;
		uint32_t *hashval;
		buckets = p->ghashtab + 4 + (p->ghashtab[2]*sizeof(size_t)/4);
		sym += p->ghashtab[1];
R
Rich Felker 已提交
1547
		for (i = nsym = 0; i < p->ghashtab[0]; i++) {
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
			if (buckets[i] > nsym)
				nsym = buckets[i];
		}
		if (nsym) {
			nsym -= p->ghashtab[1];
			hashval = buckets + p->ghashtab[0] + nsym;
			do nsym++;
			while (!(*hashval++ & 1));
		}
	}

	for (; nsym; nsym--, sym++) {
1560
		if (sym->st_value
1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
		 && (1<<(sym->st_info&0xf) & OK_TYPES)
		 && (1<<(sym->st_info>>4) & OK_BINDS)) {
			void *symaddr = p->base + sym->st_value;
			if (symaddr > addr || symaddr < best)
				continue;
			best = symaddr;
			bestname = strings + sym->st_name;
			if (addr == symaddr)
				break;
		}
	}

	if (!best) return 0;

	info->dli_fname = p->name;
	info->dli_fbase = p->base;
	info->dli_sname = bestname;
	info->dli_saddr = best;

	return 1;
}

1583
void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
1584 1585 1586
{
	void *res;
	pthread_rwlock_rdlock(&lock);
R
Rich Felker 已提交
1587
	res = do_dlsym(p, s, ra);
1588 1589 1590
	pthread_rwlock_unlock(&lock);
	return res;
}
R
Rich Felker 已提交
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616

int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
{
	struct dso *current;
	struct dl_phdr_info info;
	int ret = 0;
	for(current = head; current;) {
		info.dlpi_addr      = (uintptr_t)current->base;
		info.dlpi_name      = current->name;
		info.dlpi_phdr      = current->phdr;
		info.dlpi_phnum     = current->phnum;
		info.dlpi_adds      = gencnt;
		info.dlpi_subs      = 0;
		info.dlpi_tls_modid = current->tls_id;
		info.dlpi_tls_data  = current->tls_image;

		ret = (callback)(&info, sizeof (info), data);

		if (ret != 0) break;

		pthread_rwlock_rdlock(&lock);
		current = current->next;
		pthread_rwlock_unlock(&lock);
	}
	return ret;
}
1617
#else
1618
static int invalid_dso_handle(void *h)
1619 1620 1621 1622 1623
{
	snprintf(errbuf, sizeof errbuf, "Invalid library handle %p", (void *)h);
	errflag = 1;
	return 1;
}
1624 1625
void *dlopen(const char *file, int mode)
{
1626 1627
	strcpy(errbuf, "Dynamic loading not supported");
	errflag = 1;
1628 1629
	return 0;
}
1630
void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
1631
{
1632 1633
	errflag = 1;
	snprintf(errbuf, sizeof errbuf, "Symbol not found: %s", s);
1634 1635
	return 0;
}
1636
int __dladdr (const void *addr, Dl_info *info)
1637 1638 1639
{
	return 0;
}
1640
#endif
1641

R
Rich Felker 已提交
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653
int __dlinfo(void *dso, int req, void *res)
{
	if (invalid_dso_handle(dso)) return -1;
	if (req != RTLD_DI_LINKMAP) {
		snprintf(errbuf, sizeof errbuf, "Unsupported request %d", req);
		errflag = 1;
		return -1;
	}
	*(struct link_map **)res = dso;
	return 0;
}

1654 1655
char *dlerror()
{
R
Rich Felker 已提交
1656 1657
	if (!errflag) return 0;
	errflag = 0;
1658
	return errbuf;
1659 1660 1661 1662
}

int dlclose(void *p)
{
1663
	return invalid_dso_handle(p);
1664
}