dynlink.c 51.0 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
#include "dynlink.h"
R
Rich Felker 已提交
23

24
static void error(const char *, ...);
R
Rich Felker 已提交
25

26
#ifdef SHARED
R
Rich Felker 已提交
27

R
Rich Felker 已提交
28 29 30
#define MAXP2(a,b) (-(-(a)&-(b)))
#define ALIGN(x,y) ((x)+(y)-1 & -(y))

31 32 33 34 35 36 37 38
struct debug {
	int ver;
	void *head;
	void (*bp)(void);
	int state;
	void *base;
};

39 40 41 42 43
struct td_index {
	size_t args[2];
	struct td_index *next;
};

44
struct dso {
45 46 47
#if DL_FDPIC
	struct fdpic_loadmap *loadmap;
#else
48
	unsigned char *base;
49
#endif
50 51
	char *name;
	size_t *dynv;
R
Rich Felker 已提交
52
	struct dso *next, *prev;
53

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

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

100
int __init_tp(void *);
101
void __init_libc(char **, char *);
102

103 104
const char *__libc_get_version(void);

105 106 107 108 109 110 111
static struct builtin_tls {
	char c;
	struct pthread pt;
	void *space[16];
} builtin_tls[1];
#define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt)

112 113 114
#define ADDEND_LIMIT 4096
static size_t *saved_addends, *apply_addends_to;

R
Rich Felker 已提交
115 116
static struct dso ldso;
static struct dso *head, *tail, *fini_head;
117
static char *env_path, *sys_path;
R
Rich Felker 已提交
118
static unsigned long long gencnt;
R
Rich Felker 已提交
119
static int runtime;
120
static int ldd_mode;
121
static int ldso_fail;
122
static int noload;
123
static jmp_buf *rtld_fail;
124
static pthread_rwlock_t lock;
125
static struct debug debug;
126
static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN;
127
static size_t static_tls_cnt;
128
static pthread_mutex_t init_fini_lock = { ._m_type = PTHREAD_MUTEX_RECURSIVE };
129 130
static struct fdpic_loadmap *app_loadmap;
static struct fdpic_dummy_loadmap app_dummy_loadmap;
131 132

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

R
Rich Felker 已提交
134 135 136 137 138 139
static int dl_strcmp(const char *l, const char *r)
{
	for (; *l==*r && *l; l++, r++);
	return *(unsigned char *)l - *(unsigned char *)r;
}
#define strcmp(l,r) dl_strcmp(l,r)
R
Rich Felker 已提交
140

141
/* Compute load address for a virtual address in a given dso. */
142 143 144 145 146 147 148 149 150 151 152
#ifdef DL_FDPIC
static void *laddr(const struct dso *p, size_t v)
{
	size_t j=0;
	if (!p->loadmap) return p->base + v;
	for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
}
#define fpaddr(p, v) ((void (*)())&(struct funcdesc){ \
	laddr(p, v), (p)->got })
#else
153
#define laddr(p, v) (void *)((p)->base + (v))
154 155
#define fpaddr(p, v) ((void (*)())laddr(p, v))
#endif
156

R
Rich Felker 已提交
157 158
static void decode_vec(size_t *v, size_t *a, size_t cnt)
{
R
Rich Felker 已提交
159 160 161 162
	size_t i;
	for (i=0; i<cnt; i++) a[i] = 0;
	for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
		a[0] |= 1UL<<v[0];
R
Rich Felker 已提交
163 164 165 166
		a[v[0]] = v[1];
	}
}

167 168 169 170 171 172 173 174 175
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;
}

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

186 187 188 189 190
static uint32_t gnu_hash(const char *s0)
{
	const unsigned char *s = (void *)s0;
	uint_fast32_t h = 5381;
	for (; *s; s++)
191
		h += h*32 + *s;
192 193 194 195
	return h;
}

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

209
static Sym *gnu_lookup(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s)
210 211 212
{
	uint32_t nbuckets = hashtab[0];
	uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4);
213
	uint32_t i = buckets[h1 % nbuckets];
214

215
	if (!i) return 0;
216

217
	uint32_t *hashval = buckets + nbuckets + (i - hashtab[1]);
218

219
	for (h1 |= 1; ; i++) {
220 221 222 223
		uint32_t h2 = *hashval++;
		if ((h1 == (h2|1)) && (!dso->versym || dso->versym[i] >= 0)
		    && !strcmp(s, dso->strings + dso->syms[i].st_name))
			return dso->syms+i;
224 225 226 227 228 229
		if (h2 & 1) break;
	}

	return 0;
}

230
static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s, uint32_t fofs, size_t fmask)
231 232 233 234 235 236 237 238
{
	const size_t *bloomwords = (const void *)(hashtab+4);
	size_t f = bloomwords[fofs & (hashtab[2]-1)];
	if (!(f & fmask)) return 0;

	f >>= (h1 >> hashtab[3]) % (8 * sizeof f);
	if (!(f & 1)) return 0;

239
	return gnu_lookup(h1, hashtab, dso, s);
240 241
}

242
#define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS)
243
#define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
R
Rich Felker 已提交
244

245 246 247 248
#ifndef ARCH_SYM_REJECT_UND
#define ARCH_SYM_REJECT_UND(s) 0
#endif

249
static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
R
Rich Felker 已提交
250
{
251
	uint32_t h = 0, gh, gho, *ght;
252
	size_t ghm = 0;
253
	struct symdef def = {0};
R
Rich Felker 已提交
254
	for (; dso; dso=dso->next) {
255 256
		Sym *sym;
		if (!dso->global) continue;
257
		if ((ght = dso->ghashtab)) {
258 259 260 261 262 263
			if (!ghm) {
				gh = gnu_hash(s);
				int maskbits = 8 * sizeof ghm;
				gho = gh / maskbits;
				ghm = 1ul << gh % maskbits;
			}
264
			sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm);
265 266 267 268
		} else {
			if (!h) h = sysv_hash(s);
			sym = sysv_lookup(s, h, dso);
		}
269 270
		if (!sym) continue;
		if (!sym->st_shndx)
271 272
			if (need_def || (sym->st_info&0xf) == STT_TLS
			    || ARCH_SYM_REJECT_UND(sym))
273 274 275 276 277 278 279 280 281 282 283
				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 已提交
284
	}
285
	return def;
R
Rich Felker 已提交
286 287
}

288
__attribute__((__visibility__("hidden")))
289 290
ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic();

291
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
R
Rich Felker 已提交
292
{
293 294 295
	unsigned char *base = dso->base;
	Sym *syms = dso->syms;
	char *strings = dso->strings;
R
Rich Felker 已提交
296 297 298
	Sym *sym;
	const char *name;
	void *ctx;
R
Rich Felker 已提交
299
	int type;
R
Rich Felker 已提交
300
	int sym_index;
301
	struct symdef def;
302 303 304 305
	size_t *reloc_addr;
	size_t sym_val;
	size_t tls_val;
	size_t addend;
306 307 308 309 310 311 312 313
	int skip_relative = 0, reuse_addends = 0, save_slot = 0;

	if (dso == &ldso) {
		/* Only ldso's REL table needs addend saving/reuse. */
		if (rel == apply_addends_to)
			reuse_addends = 1;
		skip_relative = 1;
	}
R
Rich Felker 已提交
314 315

	for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
316
		if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue;
R
Rich Felker 已提交
317
		type = R_TYPE(rel[1]);
318
		if (type == REL_NONE) continue;
R
Rich Felker 已提交
319
		sym_index = R_SYM(rel[1]);
320
		reloc_addr = laddr(dso, rel[0]);
R
Rich Felker 已提交
321 322 323
		if (sym_index) {
			sym = syms + sym_index;
			name = strings + sym->st_name;
324
			ctx = type==REL_COPY ? head->next : head;
325 326 327
			def = (sym->st_info&0xf) == STT_SECTION
				? (struct symdef){ .dso = dso, .sym = sym }
				: find_sym(ctx, name, type==REL_PLT);
328 329
			if (!def.sym && (sym->st_shndx != SHN_UNDEF
			    || sym->st_info>>4 != STB_WEAK)) {
330
				error("Error relocating %s: %s: symbol not found",
331
					dso->name, name);
332
				if (runtime) longjmp(*rtld_fail, 1);
333
				continue;
R
Rich Felker 已提交
334
			}
335
		} else {
336 337
			sym = 0;
			def.sym = 0;
338 339 340
			def.dso = dso;
		}

341 342 343 344 345 346 347 348 349 350 351 352 353 354
		if (stride > 2) {
			addend = rel[2];
		} else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) {
			addend = 0;
		} else if (reuse_addends) {
			/* Save original addend in stage 2 where the dso
			 * chain consists of just ldso; otherwise read back
			 * saved addend since the inline one was clobbered. */
			if (head==&ldso)
				saved_addends[save_slot] = *reloc_addr;
			addend = saved_addends[save_slot++];
		} else {
			addend = *reloc_addr;
		}
355

356
		sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
357 358 359
		tls_val = def.sym ? def.sym->st_value : 0;

		switch(type) {
R
Rich Felker 已提交
360 361
		case REL_NONE:
			break;
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
		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;
383 384 385 386 387 388 389 390 391
		case REL_FUNCDESC:
			*reloc_addr = def.sym ? (size_t)(def.dso->funcdescs
				+ (def.sym - def.dso->syms)) : 0;
			break;
		case REL_FUNCDESC_VAL:
			if ((sym->st_info&0xf) == STT_SECTION) *reloc_addr += sym_val;
			else *reloc_addr = sym_val;
			reloc_addr[1] = def.sym ? (size_t)def.dso->got : 0;
			break;
392 393 394 395
		case REL_DTPMOD:
			*reloc_addr = def.dso->tls_id;
			break;
		case REL_DTPOFF:
396
			*reloc_addr = tls_val + addend - DTP_OFFSET;
397 398 399 400 401 402 403 404 405 406 407 408 409
			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
410 411 412 413
		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);
414 415
				if (!new) {
					error(
416 417
					"Error relocating %s: cannot allocate TLSDESC for %s",
					dso->name, sym ? name : "(local)" );
418
					longjmp(*rtld_fail, 1);
419
				}
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
				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 已提交
437 438 439
		default:
			error("Error relocating %s: unsupported relocation type %d",
				dso->name, type);
440
			if (runtime) longjmp(*rtld_fail, 1);
R
Rich Felker 已提交
441
			continue;
R
Rich Felker 已提交
442 443 444 445
		}
	}
}

446 447 448 449 450 451
/* 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 已提交
452
static void reclaim(struct dso *dso, size_t start, size_t end)
453 454
{
	size_t *a, *z;
T
Timo Teräs 已提交
455 456
	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;
457 458 459
	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;
460 461
	a = laddr(dso, start);
	z = laddr(dso, end);
462 463 464 465 466 467
	a[-2] = 1;
	a[-1] = z[0] = end-start + 2*sizeof(size_t) | 1;
	z[1] = 1;
	free(a);
}

468
static void reclaim_gaps(struct dso *dso)
469
{
470 471
	Phdr *ph = dso->phdr;
	size_t phcnt = dso->phnum;
472

473
	if (DL_FDPIC) return; // FIXME
474
	for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
475 476
		if (ph->p_type!=PT_LOAD) continue;
		if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
T
Timo Teräs 已提交
477 478
		reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
		reclaim(dso, ph->p_vaddr+ph->p_memsz,
479 480 481 482
			ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE);
	}
}

483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
{
	char *q = mmap(p, n, prot, flags, fd, off);
	if (q != MAP_FAILED || errno != EINVAL) return q;
	/* Fallbacks for MAP_FIXED failure on NOMMU kernels. */
	if (flags & MAP_ANONYMOUS) {
		memset(p, 0, n);
		return p;
	}
	ssize_t r;
	if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED;
	for (q=p; n; q+=r, off+=r, n-=r) {
		r = read(fd, q, n);
		if (r < 0 && errno != EINTR) return MAP_FAILED;
		if (!r) {
			memset(q, 0, n);
			break;
		}
	}
	return p;
}

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
static void unmap_library(struct dso *dso)
{
	if (dso->loadmap) {
		size_t i;
		for (i=0; i<dso->loadmap->nsegs; i++) {
			if (!dso->loadmap->segs[i].p_memsz)
				continue;
			munmap((void *)dso->loadmap->segs[i].addr,
				dso->loadmap->segs[i].p_memsz);
		}
		free(dso->loadmap);
	} else if (dso->map && dso->map_len) {
		munmap(dso->map, dso->map_len);
	}
}

521
static void *map_library(int fd, struct dso *dso)
R
Rich Felker 已提交
522
{
523
	Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
524
	void *allocated_buf=0;
R
Rich Felker 已提交
525 526 527
	size_t phsize;
	size_t addr_min=SIZE_MAX, addr_max=0, map_len;
	size_t this_min, this_max;
528
	size_t nsegs = 0;
R
Rich Felker 已提交
529 530
	off_t off_start;
	Ehdr *eh;
531
	Phdr *ph, *ph0;
R
Rich Felker 已提交
532
	unsigned prot;
533
	unsigned char *map=MAP_FAILED, *base;
534
	size_t dyn=0;
535
	size_t tls_image=0;
R
Rich Felker 已提交
536 537 538
	size_t i;

	ssize_t l = read(fd, buf, sizeof buf);
539
	eh = buf;
540 541 542
	if (l<0) return 0;
	if (l<sizeof *eh || (eh->e_type != ET_DYN && eh->e_type != ET_EXEC))
		goto noexec;
R
Rich Felker 已提交
543
	phsize = eh->e_phentsize * eh->e_phnum;
544 545 546 547 548 549 550 551
	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) {
552
		l = pread(fd, buf+1, phsize, eh->e_phoff);
553 554
		if (l < 0) goto error;
		if (l != phsize) goto noexec;
555 556 557
		ph = ph0 = (void *)(buf + 1);
	} else {
		ph = ph0 = (void *)((char *)buf + eh->e_phoff);
R
Rich Felker 已提交
558 559
	}
	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
560
		if (ph->p_type == PT_DYNAMIC) {
R
Rich Felker 已提交
561
			dyn = ph->p_vaddr;
562
		} else if (ph->p_type == PT_TLS) {
563 564 565 566
			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 已提交
567 568 569
		} 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;
570
		}
R
Rich Felker 已提交
571
		if (ph->p_type != PT_LOAD) continue;
572
		nsegs++;
R
Rich Felker 已提交
573 574 575 576 577 578 579 580 581 582 583
		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;
		}
	}
584
	if (!dyn) goto noexec;
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
	if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
		dso->loadmap = calloc(1, sizeof *dso->loadmap
			+ nsegs * sizeof *dso->loadmap->segs);
		if (!dso->loadmap) goto error;
		dso->loadmap->nsegs = nsegs;
		for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
			if (ph->p_type != PT_LOAD) continue;
			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));
			map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
				prot, (prot&PROT_WRITE) ? MAP_PRIVATE : MAP_SHARED,
				fd, ph->p_offset & -PAGE_SIZE);
			if (map == MAP_FAILED) {
				unmap_library(dso);
				goto error;
			}
			dso->loadmap->segs[i].addr = (size_t)map +
				(ph->p_vaddr & PAGE_SIZE-1);
			dso->loadmap->segs[i].p_vaddr = ph->p_vaddr;
			dso->loadmap->segs[i].p_memsz = ph->p_memsz;
			i++;
		}
		map = (void *)dso->loadmap->segs[0].addr;
		map_len = 0;
		goto done_mapping;
	}
R
Rich Felker 已提交
612 613 614 615 616 617 618 619 620
	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. */
621
	map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
622
	if (map==MAP_FAILED) goto error;
623 624
	dso->map = map;
	dso->map_len = map_len;
625 626 627 628 629 630
	/* 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 已提交
631
	base = map - addr_min;
632 633 634
	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 已提交
635
		if (ph->p_type != PT_LOAD) continue;
636 637 638 639 640 641 642
		/* 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;
643
			dso->phentsize = eh->e_phentsize;
644
		}
R
Rich Felker 已提交
645 646 647 648 649 650 651 652
		/* 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));
653
		if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
654
			goto error;
R
Rich Felker 已提交
655 656 657 658
		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);
659
			if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
660
				goto error;
R
Rich Felker 已提交
661 662
		}
	}
R
Rich Felker 已提交
663 664
	for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
		if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
665 666
			if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC)
			    && errno != ENOSYS)
667
				goto error;
R
Rich Felker 已提交
668 669
			break;
		}
670
done_mapping:
671
	dso->base = base;
672 673
	dso->dynv = laddr(dso, dyn);
	if (dso->tls_size) dso->tls_image = laddr(dso, tls_image);
674
	if (!runtime) reclaim_gaps(dso);
675
	free(allocated_buf);
R
Rich Felker 已提交
676
	return map;
677 678
noexec:
	errno = ENOEXEC;
679
error:
680
	if (map!=MAP_FAILED) unmap_library(dso);
681
	free(allocated_buf);
682
	return 0;
R
Rich Felker 已提交
683 684
}

685
static int path_open(const char *name, const char *s, char *buf, size_t buf_size)
686
{
687 688
	size_t l;
	int fd;
689
	for (;;) {
690 691 692
		s += strspn(s, ":\n");
		l = strcspn(s, ":\n");
		if (l-1 >= INT_MAX) return -1;
693 694 695 696 697 698 699 700 701 702 703 704 705 706
		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;
			}
		}
707
		s += l;
708 709 710
	}
}

711 712 713 714 715
static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
{
	size_t n, l;
	const char *s, *t, *origin;
	char *d;
716
	if (p->rpath || !p->rpath_orig) return 0;
717 718 719 720 721 722
	if (!strchr(p->rpath_orig, '$')) {
		p->rpath = p->rpath_orig;
		return 0;
	}
	n = 0;
	s = p->rpath_orig;
R
Rich Felker 已提交
723 724
	while ((t=strchr(s, '$'))) {
		if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9))
725
			return 0;
726 727 728
		s = t+1;
		n++;
	}
729
	if (n > SSIZE_MAX/PATH_MAX) return 0;
730 731 732 733 734 735 736 737 738

	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)
739
			return 0;
R
Rich Felker 已提交
740
		l = readlink("/proc/self/exe", buf, buf_size);
741 742 743 744 745 746
		if (l == -1) switch (errno) {
		case ENOENT:
		case ENOTDIR:
		case EACCES:
			break;
		default:
747
			return -1;
748 749 750
		}
		if (l >= buf_size)
			return 0;
R
Rich Felker 已提交
751
		buf[l] = 0;
752 753 754 755 756 757 758 759 760 761 762
		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 已提交
763
	while ((t=strchr(s, '$'))) {
764 765 766 767
		memcpy(d, s, t-s);
		d += t-s;
		memcpy(d, origin, l);
		d += l;
R
Rich Felker 已提交
768 769
		/* It was determined previously that the '$' is followed
		 * either by "ORIGIN" or "{ORIGIN}". */
770 771 772 773 774 775
		s = t + 7 + 2*(t[1]=='{');
	}
	strcpy(d, s);
	return 0;
}

776 777
static void decode_dyn(struct dso *p)
{
778
	size_t dyn[DYN_CNT];
779
	decode_vec(p->dynv, dyn, DYN_CNT);
780 781
	p->syms = laddr(p, dyn[DT_SYMTAB]);
	p->strings = laddr(p, dyn[DT_STRTAB]);
782
	if (dyn[0]&(1<<DT_HASH))
783
		p->hashtab = laddr(p, dyn[DT_HASH]);
784
	if (dyn[0]&(1<<DT_RPATH))
785
		p->rpath_orig = p->strings + dyn[DT_RPATH];
786
	if (dyn[0]&(1<<DT_RUNPATH))
787
		p->rpath_orig = p->strings + dyn[DT_RUNPATH];
788 789
	if (dyn[0]&(1<<DT_PLTGOT))
		p->got = laddr(p, dyn[DT_PLTGOT]);
790
	if (search_vec(p->dynv, dyn, DT_GNU_HASH))
791
		p->ghashtab = laddr(p, *dyn);
792
	if (search_vec(p->dynv, dyn, DT_VERSYM))
793
		p->versym = laddr(p, *dyn);
794 795
}

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
static size_t count_syms(struct dso *p)
{
	if (p->hashtab) return p->hashtab[1];

	size_t nsym, i;
	uint32_t *buckets = p->ghashtab + 4 + (p->ghashtab[2]*sizeof(size_t)/4);
	uint32_t *hashval;
	for (i = nsym = 0; i < p->ghashtab[0]; i++) {
		if (buckets[i] > nsym)
			nsym = buckets[i];
	}
	if (nsym) {
		hashval = buckets + p->ghashtab[0] + (nsym - p->ghashtab[1]);
		do nsym++;
		while (!(*hashval++ & 1));
	}
	return nsym;
}

815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
static void *dl_mmap(size_t n)
{
	void *p;
	int prot = PROT_READ|PROT_WRITE, flags = MAP_ANONYMOUS|MAP_PRIVATE;
#ifdef SYS_mmap2
	p = (void *)__syscall(SYS_mmap2, 0, n, prot, flags, -1, 0);
#else
	p = (void *)__syscall(SYS_mmap, 0, n, prot, flags, -1, 0);
#endif
	return p == MAP_FAILED ? 0 : p;
}

static void makefuncdescs(struct dso *p)
{
	static int self_done;
	size_t nsym = count_syms(p);
	size_t i, size = nsym * sizeof(*p->funcdescs);

	if (!self_done) {
		p->funcdescs = dl_mmap(size);
		self_done = 1;
	} else {
		p->funcdescs = malloc(size);
	}
	if (!p->funcdescs) {
		if (!runtime) a_crash();
		error("Error allocating function descriptors for %s", p->name);
		longjmp(*rtld_fail, 1);
	}
	for (i=0; i<nsym; i++) {
		if ((p->syms[i].st_info&0xf)==STT_FUNC && p->syms[i].st_shndx) {
			p->funcdescs[i].addr = laddr(p, p->syms[i].st_value);
			p->funcdescs[i].got = p->got;
		} else {
			p->funcdescs[i].addr = 0;
			p->funcdescs[i].got = 0;
		}
	}
}

855
static struct dso *load_library(const char *name, struct dso *needed_by)
R
Rich Felker 已提交
856
{
857
	char buf[2*NAME_MAX+2];
858
	const char *pathname;
859
	unsigned char *map;
860
	struct dso *p, temp_dso = {0};
R
Rich Felker 已提交
861 862
	int fd;
	struct stat st;
863 864
	size_t alloc_size;
	int n_th = 0;
865
	int is_self = 0;
R
Rich Felker 已提交
866

867 868 869 870 871
	if (!*name) {
		errno = EINVAL;
		return 0;
	}

R
Rich Felker 已提交
872 873 874 875 876 877 878
	/* 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;
879
			for (rp=reserved; *rp && strncmp(name+3, rp, l-3); rp+=strlen(rp)+1);
R
Rich Felker 已提交
880
			if (*rp) {
881 882 883 884 885 886 887 888
				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",
R
Rich Felker 已提交
889 890
							name, ldso.name,
							ldso.base);
891 892
					}
				}
893
				is_self = 1;
R
Rich Felker 已提交
894 895 896
			}
		}
	}
R
Rich Felker 已提交
897
	if (!strcmp(name, ldso.name)) is_self = 1;
898
	if (is_self) {
R
Rich Felker 已提交
899 900 901 902
		if (!ldso.prev) {
			tail->next = &ldso;
			ldso.prev = tail;
			tail = ldso.next ? ldso.next : &ldso;
903
		}
R
Rich Felker 已提交
904
		return &ldso;
905
	}
906
	if (strchr(name, '/')) {
907
		pathname = name;
908
		fd = open(name, O_RDONLY|O_CLOEXEC);
R
Rich Felker 已提交
909
	} else {
910 911 912 913 914 915 916
		/* 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;
			}
		}
917
		if (strlen(name) > NAME_MAX) return 0;
918
		fd = -1;
919
		if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
920 921 922 923
		for (p=needed_by; fd == -1 && p; p=p->needed_by) {
			if (fixup_rpath(p, buf, sizeof buf) < 0)
				fd = -2; /* Inhibit further search. */
			if (p->rpath)
924
				fd = path_open(name, p->rpath, buf, sizeof buf);
925
		}
926
		if (fd == -1) {
927
			if (!sys_path) {
928 929
				char *prefix = 0;
				size_t prefix_len;
R
Rich Felker 已提交
930
				if (ldso.name[0]=='/') {
931
					char *s, *t, *z;
R
Rich Felker 已提交
932
					for (s=t=z=ldso.name; *s; s++)
933
						if (*s=='/') z=t, t=s;
R
Rich Felker 已提交
934
					prefix_len = z-ldso.name;
935
					if (prefix_len < PATH_MAX)
R
Rich Felker 已提交
936
						prefix = ldso.name;
937 938 939 940 941 942 943 944 945 946 947
				}
				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");
948
				if (f) {
949
					if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) {
950
						free(sys_path);
951
						sys_path = "";
952
					}
953
					fclose(f);
954 955
				} else if (errno != ENOENT) {
					sys_path = "";
956 957
				}
			}
958 959
			if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib";
			fd = path_open(name, sys_path, buf, sizeof buf);
R
Rich Felker 已提交
960
		}
961
		pathname = buf;
R
Rich Felker 已提交
962 963 964 965 966 967 968 969
	}
	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) {
970 971 972
			/* 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. */
973 974
			if (!p->shortname && pathname != name)
				p->shortname = strrchr(p->name, '/')+1;
R
Rich Felker 已提交
975 976 977 978 979
			close(fd);
			p->refcnt++;
			return p;
		}
	}
980
	map = noload ? 0 : map_library(fd, &temp_dso);
R
Rich Felker 已提交
981 982
	close(fd);
	if (!map) return 0;
983 984 985 986 987 988 989 990 991 992

	/* 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);
993
		n_th = libc.threads_minus_1 + 1;
994 995 996 997
		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 已提交
998
	if (!p) {
999
		unmap_library(&temp_dso);
R
Rich Felker 已提交
1000 1001
		return 0;
	}
1002
	memcpy(p, &temp_dso, sizeof temp_dso);
1003
	decode_dyn(p);
R
Rich Felker 已提交
1004 1005 1006
	p->dev = st.st_dev;
	p->ino = st.st_ino;
	p->refcnt = 1;
1007
	p->needed_by = needed_by;
R
Rich Felker 已提交
1008
	p->name = p->buf;
1009 1010 1011
	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;
1012 1013
	if (p->tls_image) {
		p->tls_id = ++tls_cnt;
R
Rich Felker 已提交
1014
		tls_align = MAXP2(tls_align, p->tls_align);
1015 1016 1017 1018 1019
#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 已提交
1020 1021 1022 1023
		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;
1024
#endif
1025 1026 1027 1028
		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 已提交
1029 1030 1031 1032 1033

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

1034 1035
	if (DL_FDPIC) makefuncdescs(p);

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

R
Rich Felker 已提交
1038 1039 1040 1041 1042
	return p;
}

static void load_deps(struct dso *p)
{
1043 1044
	size_t i, ndeps=0;
	struct dso ***deps = &p->deps, **tmp, *dep;
R
Rich Felker 已提交
1045 1046 1047
	for (; p; p=p->next) {
		for (i=0; p->dynv[i]; i+=2) {
			if (p->dynv[i] != DT_NEEDED) continue;
1048
			dep = load_library(p->strings + p->dynv[i+1], p);
1049
			if (!dep) {
1050
				error("Error loading shared library %s: %m (needed by %s)",
R
Rich Felker 已提交
1051
					p->strings + p->dynv[i+1], p->name);
1052
				if (runtime) longjmp(*rtld_fail, 1);
1053
				continue;
R
Rich Felker 已提交
1054
			}
1055 1056
			if (runtime) {
				tmp = realloc(*deps, sizeof(*tmp)*(ndeps+2));
1057
				if (!tmp) longjmp(*rtld_fail, 1);
1058 1059 1060 1061
				tmp[ndeps++] = dep;
				tmp[ndeps] = 0;
				*deps = tmp;
			}
R
Rich Felker 已提交
1062 1063 1064 1065
		}
	}
}

R
Rich Felker 已提交
1066 1067 1068 1069 1070
static void load_preload(char *s)
{
	int tmp;
	char *z;
	for (z=s; *z; s=z) {
1071 1072
		for (   ; *s && (isspace(*s) || *s==':'); s++);
		for (z=s; *z && !isspace(*z) && *z!=':'; z++);
R
Rich Felker 已提交
1073 1074
		tmp = *z;
		*z = 0;
1075
		load_library(s, 0);
R
Rich Felker 已提交
1076 1077 1078 1079
		*z = tmp;
	}
}

1080 1081 1082 1083 1084
static void make_global(struct dso *p)
{
	for (; p; p=p->next) p->global = 1;
}

R
Rich Felker 已提交
1085 1086 1087 1088 1089
static void do_mips_relocs(struct dso *p, size_t *got)
{
	size_t i, j, rel[2];
	unsigned char *base = p->base;
	i=0; search_vec(p->dynv, &i, DT_MIPS_LOCAL_GOTNO);
1090
	if (p==&ldso) {
R
Rich Felker 已提交
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
		got += i;
	} else {
		while (i--) *got++ += (size_t)base;
	}
	j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM);
	i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO);
	Sym *sym = p->syms + j;
	rel[0] = (unsigned char *)got - base;
	for (i-=j; i; i--, sym++, rel[0]+=sizeof(size_t)) {
		rel[1] = sym-p->syms << 8 | R_MIPS_JUMP_SLOT;
		do_relocs(p, rel, sizeof rel, 2);
	}
}

R
Rich Felker 已提交
1105 1106
static void reloc_all(struct dso *p)
{
1107
	size_t dyn[DYN_CNT];
R
Rich Felker 已提交
1108 1109 1110
	for (; p; p=p->next) {
		if (p->relocated) continue;
		decode_vec(p->dynv, dyn, DYN_CNT);
R
Rich Felker 已提交
1111
		if (NEED_MIPS_GOT_RELOCS)
1112 1113
			do_mips_relocs(p, laddr(p, dyn[DT_PLTGOT]));
		do_relocs(p, laddr(p, dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
1114
			2+(dyn[DT_PLTREL]==DT_RELA));
1115 1116
		do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2);
		do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3);
T
Timo Teräs 已提交
1117

R
Rich Felker 已提交
1118
		if (head != &ldso && p->relro_start != p->relro_end &&
1119
		    mprotect(laddr(p, p->relro_start), p->relro_end-p->relro_start, PROT_READ)
1120
		    && errno != ENOSYS) {
1121
			error("Error relocating %s: RELRO protection failed: %m",
T
Timo Teräs 已提交
1122
				p->name);
1123
			if (runtime) longjmp(*rtld_fail, 1);
T
Timo Teräs 已提交
1124 1125
		}

1126
		p->relocated = 1;
R
Rich Felker 已提交
1127 1128 1129
	}
}

1130
static void kernel_mapped_dso(struct dso *p)
1131
{
1132 1133 1134 1135
	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) {
1136
			p->dynv = laddr(p, ph->p_vaddr);
1137
		} else if (ph->p_type == PT_GNU_RELRO) {
T
Timo Teräs 已提交
1138 1139 1140
			p->relro_start = ph->p_vaddr & -PAGE_SIZE;
			p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
		}
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
		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;
1151
	p->kernel_mapped = 1;
1152 1153
}

1154 1155 1156
static void do_fini()
{
	struct dso *p;
1157
	size_t dyn[DYN_CNT];
1158 1159 1160
	for (p=fini_head; p; p=p->fini_next) {
		if (!p->constructed) continue;
		decode_vec(p->dynv, dyn, DYN_CNT);
1161 1162
		if (dyn[0] & (1<<DT_FINI_ARRAY)) {
			size_t n = dyn[DT_FINI_ARRAYSZ]/sizeof(size_t);
1163
			size_t *fn = (size_t *)laddr(p, dyn[DT_FINI_ARRAY])+n;
1164
			while (n--) ((void (*)(void))*--fn)();
1165
		}
1166
#ifndef NO_LEGACY_INITFINI
1167
		if ((dyn[0] & (1<<DT_FINI)) && dyn[DT_FINI])
1168
			fpaddr(p, dyn[DT_FINI])();
1169
#endif
1170 1171 1172
	}
}

1173 1174
static void do_init_fini(struct dso *p)
{
1175
	size_t dyn[DYN_CNT];
1176
	int need_locking = libc.threads_minus_1;
1177 1178 1179 1180
	/* 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);
1181
	for (; p; p=p->prev) {
1182 1183
		if (p->constructed) continue;
		p->constructed = 1;
1184
		decode_vec(p->dynv, dyn, DYN_CNT);
1185
		if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) {
1186 1187 1188
			p->fini_next = fini_head;
			fini_head = p;
		}
1189
#ifndef NO_LEGACY_INITFINI
1190
		if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT])
1191
			fpaddr(p, dyn[DT_INIT])();
1192
#endif
1193 1194
		if (dyn[0] & (1<<DT_INIT_ARRAY)) {
			size_t n = dyn[DT_INIT_ARRAYSZ]/sizeof(size_t);
1195
			size_t *fn = laddr(p, dyn[DT_INIT_ARRAY]);
1196 1197
			while (n--) ((void (*)(void))*fn++)();
		}
1198 1199 1200 1201
		if (!need_locking && libc.threads_minus_1) {
			need_locking = 1;
			pthread_mutex_lock(&init_fini_lock);
		}
1202
	}
1203
	if (need_locking) pthread_mutex_unlock(&init_fini_lock);
1204 1205
}

1206
static void dl_debug_state(void)
1207 1208 1209
{
}

1210 1211
weak_alias(dl_debug_state, _dl_debug_state);

1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
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;
	}
}

1225
void *__copy_tls(unsigned char *mem)
1226
{
R
Rich Felker 已提交
1227
	pthread_t td;
1228
	struct dso *p;
1229
	void **dtv;
R
Rich Felker 已提交
1230

1231
#ifdef TLS_ABOVE_TP
1232 1233
	dtv = (void **)(mem + libc.tls_size) - (tls_cnt + 1);

1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
	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
1244 1245
	dtv = (void **)mem;

1246
	mem += libc.tls_size - sizeof(struct pthread);
R
Rich Felker 已提交
1247 1248 1249 1250
	mem -= (uintptr_t)mem & (tls_align-1);
	td = (pthread_t)mem;

	for (p=head; p; p=p->next) {
1251
		if (!p->tls_id) continue;
R
Rich Felker 已提交
1252 1253
		dtv[p->tls_id] = mem - p->tls_offset;
		memcpy(dtv[p->tls_id], p->tls_image, p->tls_len);
1254
	}
1255
#endif
1256
	dtv[0] = (void *)tls_cnt;
1257
	td->dtv = td->dtv_copy = dtv;
R
Rich Felker 已提交
1258
	return td;
1259 1260
}

1261
__attribute__((__visibility__("hidden")))
1262
void *__tls_get_new(size_t *v)
1263 1264
{
	pthread_t self = __pthread_self();
1265 1266 1267

	/* Block signals to make accessing new TLS async-signal-safe */
	sigset_t set;
1268
	__block_all_sigs(&set);
1269
	if (v[0]<=(size_t)self->dtv[0]) {
1270
		__restore_sigs(&set);
1271
		return (char *)self->dtv[v[0]]+v[1]+DTP_OFFSET;
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
	}

	/* 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 */
1282
	if (v[0] > (size_t)self->dtv[0]) {
1283 1284
		void **newdtv = p->new_dtv +
			(v[0]+1)*sizeof(void *)*a_fetch_add(&p->new_dtv_idx,1);
1285
		memcpy(newdtv, self->dtv,
1286 1287
			((size_t)self->dtv[0]+1) * sizeof(void *));
		newdtv[0] = (void *)v[0];
1288
		self->dtv = self->dtv_copy = newdtv;
1289
	}
1290

1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
	/* 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;
	}
1303
	__restore_sigs(&set);
1304
	return mem + v[1] + DTP_OFFSET;
1305 1306
}

R
Rich Felker 已提交
1307 1308
static void update_tls_size()
{
1309 1310 1311 1312 1313 1314
	libc.tls_size = ALIGN(
		(1+tls_cnt) * sizeof(void *) +
		tls_offset +
		sizeof(struct pthread) +
		tls_align * 2,
	tls_align);
R
Rich Felker 已提交
1315 1316
}

R
Rich Felker 已提交
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
/* Stage 1 of the dynamic linker is defined in dlstart.c. It calls the
 * following stage 2 and stage 3 functions via primitive symbolic lookup
 * since it does not have access to their addresses to begin with. */

/* Stage 2 of the dynamic linker is called after relative relocations 
 * have been processed. It can make function calls to static functions
 * and access string literals and static data, but cannot use extern
 * symbols. Its job is to perform symbolic relocations on the dynamic
 * linker itself, but some of the relocations performed may need to be
 * replaced later due to copy relocations in the main program. */

1328
void __dls2(unsigned char *base, size_t *sp)
R
Rich Felker 已提交
1329
{
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
	if (DL_FDPIC) {
		void *p1 = (void *)sp[-2];
		void *p2 = (void *)sp[-1];
		if (!p1) {
			size_t *auxv, aux[AUX_CNT];
			for (auxv=sp+1+*sp+1; *auxv; auxv++); auxv++;
			decode_vec(auxv, aux, AUX_CNT);
			if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE];
			else ldso.base = (void *)(aux[AT_PHDR] & -4096);
		}
		app_loadmap = p2 ? p1 : 0;
		ldso.loadmap = p2 ? p2 : p1;
		ldso.base = laddr(&ldso, 0);
	} else {
		ldso.base = base;
	}
	Ehdr *ehdr = (void *)ldso.base;
R
Rich Felker 已提交
1347 1348 1349
	ldso.name = ldso.shortname = "libc.so";
	ldso.global = 1;
	ldso.phnum = ehdr->e_phnum;
1350
	ldso.phdr = laddr(&ldso, ehdr->e_phoff);
R
Rich Felker 已提交
1351 1352 1353 1354
	ldso.phentsize = ehdr->e_phentsize;
	kernel_mapped_dso(&ldso);
	decode_dyn(&ldso);

1355 1356
	if (DL_FDPIC) makefuncdescs(&ldso);

1357 1358 1359 1360 1361 1362
	/* Prepare storage for to save clobbered REL addends so they
	 * can be reused in stage 3. There should be very few. If
	 * something goes wrong and there are a huge number, abort
	 * instead of risking stack overflow. */
	size_t dyn[DYN_CNT];
	decode_vec(ldso.dynv, dyn, DYN_CNT);
1363
	size_t *rel = laddr(&ldso, dyn[DT_REL]);
1364 1365 1366 1367
	size_t rel_size = dyn[DT_RELSZ];
	size_t symbolic_rel_cnt = 0;
	apply_addends_to = rel;
	for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t))
1368
		if (!IS_RELATIVE(rel[1], ldso.syms)) symbolic_rel_cnt++;
1369 1370 1371 1372
	if (symbolic_rel_cnt >= ADDEND_LIMIT) a_crash();
	size_t addends[symbolic_rel_cnt+1];
	saved_addends = addends;

R
Rich Felker 已提交
1373 1374 1375 1376
	head = &ldso;
	reloc_all(&ldso);

	ldso.relocated = 0;
1377 1378 1379 1380 1381

	/* Call dynamic linker stage-3, __dls3, looking it up
	 * symbolically as a barrier against moving the address
	 * load across the above relocation processing. */
	struct symdef dls3_def = find_sym(&ldso, "__dls3", 0);
1382 1383
	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls3_def.sym-ldso.syms])(sp);
	else ((stage3_func)laddr(&ldso, dls3_def.sym->st_value))(sp);
R
Rich Felker 已提交
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
}

/* Stage 3 of the dynamic linker is called with the dynamic linker/libc
 * fully functional. Its job is to load (if not already loaded) and
 * process dependencies and relocations for the main application and
 * transfer control to its entry point. */

_Noreturn void __dls3(size_t *sp)
{
	static struct dso app, vdso;
1394
	size_t aux[AUX_CNT], *auxv;
R
Rich Felker 已提交
1395
	size_t i;
R
Rich Felker 已提交
1396
	char *env_preload=0;
R
Rich Felker 已提交
1397
	size_t vdso_base;
R
Rich Felker 已提交
1398 1399 1400
	int argc = *sp;
	char **argv = (void *)(sp+1);
	char **argv_orig = argv;
1401
	char **envp = argv+argc+1;
1402

1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
	/* Find aux vector just past environ[] and use it to initialize
	 * global data that may be needed before we can make syscalls. */
	__environ = envp;
	for (i=argc+1; argv[i]; i++);
	libc.auxv = auxv = (void *)(argv+i+1);
	decode_vec(auxv, aux, AUX_CNT);
	__hwcap = aux[AT_HWCAP];
	libc.page_size = aux[AT_PAGESZ];
	libc.secure = ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
		|| aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]);

1414 1415 1416 1417 1418
	/* Setup early thread pointer in builtin_tls for ldso/libc itself to
	 * use during dynamic linking. If possible it will also serve as the
	 * thread pointer at runtime. */
	libc.tls_size = sizeof builtin_tls;
	if (__init_tp(__copy_tls((void *)builtin_tls)) < 0) {
1419
		a_crash();
1420
	}
R
Rich Felker 已提交
1421

1422
	/* Only trust user/env if kernel says we're not suid/sgid */
1423 1424 1425
	if (!libc.secure) {
		env_path = getenv("LD_LIBRARY_PATH");
		env_preload = getenv("LD_PRELOAD");
1426 1427
	}

R
Rich Felker 已提交
1428 1429 1430 1431
	/* If the main program was already loaded by the kernel,
	 * AT_PHDR will point to some location other than the dynamic
	 * linker's program headers. */
	if (aux[AT_PHDR] != (size_t)ldso.phdr) {
1432
		size_t interp_off = 0;
1433
		size_t tls_image = 0;
1434
		/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
R
Rich Felker 已提交
1435 1436 1437
		Phdr *phdr = app.phdr = (void *)aux[AT_PHDR];
		app.phnum = aux[AT_PHNUM];
		app.phentsize = aux[AT_PHENT];
1438 1439
		for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
			if (phdr->p_type == PT_PHDR)
R
Rich Felker 已提交
1440
				app.base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
1441 1442
			else if (phdr->p_type == PT_INTERP)
				interp_off = (size_t)phdr->p_vaddr;
1443 1444
			else if (phdr->p_type == PT_TLS) {
				tls_image = phdr->p_vaddr;
R
Rich Felker 已提交
1445 1446 1447
				app.tls_len = phdr->p_filesz;
				app.tls_size = phdr->p_memsz;
				app.tls_align = phdr->p_align;
1448
			}
1449
		}
1450
		if (DL_FDPIC) app.loadmap = app_loadmap;
1451 1452
		if (app.tls_size) app.tls_image = laddr(&app, tls_image);
		if (interp_off) ldso.name = laddr(&app, interp_off);
1453 1454
		if ((aux[0] & (1UL<<AT_EXECFN))
		    && strncmp((char *)aux[AT_EXECFN], "/proc/", 6))
R
Rich Felker 已提交
1455
			app.name = (char *)aux[AT_EXECFN];
1456
		else
R
Rich Felker 已提交
1457 1458
			app.name = argv[0];
		kernel_mapped_dso(&app);
1459 1460 1461
	} else {
		int fd;
		char *ldname = argv[0];
R
Rich Felker 已提交
1462
		size_t l = strlen(ldname);
1463
		if (l >= 3 && !strcmp(ldname+l-3, "ldd")) ldd_mode = 1;
R
Rich Felker 已提交
1464
		argv++;
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
		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;
			}
		}
R
Rich Felker 已提交
1484
		argv[-1] = (void *)(argc - (argv-argv_orig));
1485
		if (!argv[0]) {
1486 1487 1488
			dprintf(2, "musl libc\n"
				"Version %s\n"
				"Dynamic Program Loader\n"
1489
				"Usage: %s [options] [--] pathname%s\n",
1490
				__libc_get_version(), ldname,
1491 1492 1493 1494 1495 1496 1497 1498 1499
				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;
R
Rich Felker 已提交
1500
		Ehdr *ehdr = (void *)map_library(fd, &app);
1501 1502 1503 1504 1505 1506
		if (!ehdr) {
			dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
			_exit(1);
		}
		runtime = 0;
		close(fd);
R
Rich Felker 已提交
1507 1508
		ldso.name = ldname;
		app.name = argv[0];
1509
		aux[AT_ENTRY] = (size_t)laddr(&app, ehdr->e_entry);
1510 1511 1512
		/* Find the name that would have been used for the dynamic
		 * linker had ldd not taken its place. */
		if (ldd_mode) {
R
Rich Felker 已提交
1513 1514 1515 1516
			for (i=0; i<app.phnum; i++) {
				if (app.phdr[i].p_type == PT_INTERP)
					ldso.name = (void *)(app.base
						+ app.phdr[i].p_vaddr);
1517
			}
R
Rich Felker 已提交
1518
			dprintf(1, "\t%s (%p)\n", ldso.name, ldso.base);
1519
		}
1520
	}
R
Rich Felker 已提交
1521 1522
	if (app.tls_size) {
		app.tls_id = tls_cnt = 1;
1523
#ifdef TLS_ABOVE_TP
R
Rich Felker 已提交
1524 1525 1526 1527
		app.tls_offset = 0;
		tls_offset = app.tls_size
			+ ( -((uintptr_t)app.tls_image + app.tls_size)
			& (app.tls_align-1) );
1528
#else
R
Rich Felker 已提交
1529 1530 1531
		tls_offset = app.tls_offset = app.tls_size
			+ ( -((uintptr_t)app.tls_image + app.tls_size)
			& (app.tls_align-1) );
1532
#endif
R
Rich Felker 已提交
1533
		tls_align = MAXP2(tls_align, app.tls_align);
1534
	}
R
Rich Felker 已提交
1535 1536
	app.global = 1;
	decode_dyn(&app);
1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
	if (DL_FDPIC) {
		makefuncdescs(&app);
		if (!app.loadmap) {
			app.loadmap = (void *)&app_dummy_loadmap;
			app.loadmap->nsegs = 1;
			app.loadmap->segs[0].addr = (size_t)app.base;
			app.loadmap->segs[0].p_memsz = -1;
		}
		argv[-3] = (void *)app.loadmap;
	}
1547 1548

	/* Attach to vdso, if provided by the kernel */
R
Rich Felker 已提交
1549
	if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR)) {
R
Rich Felker 已提交
1550 1551 1552 1553
		Ehdr *ehdr = (void *)vdso_base;
		Phdr *phdr = vdso.phdr = (void *)(vdso_base + ehdr->e_phoff);
		vdso.phnum = ehdr->e_phnum;
		vdso.phentsize = ehdr->e_phentsize;
1554 1555
		for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
			if (phdr->p_type == PT_DYNAMIC)
R
Rich Felker 已提交
1556
				vdso.dynv = (void *)(vdso_base + phdr->p_offset);
1557
			if (phdr->p_type == PT_LOAD)
R
Rich Felker 已提交
1558
				vdso.base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset);
1559
		}
R
Rich Felker 已提交
1560 1561 1562 1563 1564 1565 1566
		vdso.name = "";
		vdso.shortname = "linux-gate.so.1";
		vdso.global = 1;
		vdso.relocated = 1;
		decode_dyn(&vdso);
		vdso.prev = &ldso;
		ldso.next = &vdso;
1567 1568
	}

R
Rich Felker 已提交
1569 1570
	/* Initial dso chain consists only of the app. */
	head = tail = &app;
R
Rich Felker 已提交
1571

1572
	/* Donate unused parts of app and library mapping to malloc */
R
Rich Felker 已提交
1573 1574
	reclaim_gaps(&app);
	reclaim_gaps(&ldso);
1575

1576
	/* Load preload/needed libraries, add their symbols to the global
R
Rich Felker 已提交
1577
	 * namespace, and perform all remaining relocations. */
R
Rich Felker 已提交
1578
	if (env_preload) load_preload(env_preload);
R
Rich Felker 已提交
1579 1580
	load_deps(&app);
	make_global(&app);
1581

T
Timo Teräs 已提交
1582
#ifndef DYNAMIC_IS_RO
R
Rich Felker 已提交
1583 1584 1585
	for (i=0; app.dynv[i]; i+=2)
		if (app.dynv[i]==DT_DEBUG)
			app.dynv[i+1] = (size_t)&debug;
T
Timo Teräs 已提交
1586 1587
#endif

R
Rich Felker 已提交
1588 1589 1590 1591
	/* The main program must be relocated LAST since it may contin
	 * copy relocations which depend on libraries' relocations. */
	reloc_all(app.next);
	reloc_all(&app);
R
Rich Felker 已提交
1592 1593

	update_tls_size();
1594 1595
	if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) {
		void *initial_tls = calloc(libc.tls_size, 1);
1596
		if (!initial_tls) {
1597
			dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
1598
				argv[0], libc.tls_size);
1599 1600
			_exit(127);
		}
1601
		if (__init_tp(__copy_tls(initial_tls)) < 0) {
1602
			a_crash();
1603
		}
1604
	} else {
1605 1606 1607 1608 1609 1610 1611 1612
		size_t tmp_tls_size = libc.tls_size;
		pthread_t self = __pthread_self();
		/* Temporarily set the tls size to the full size of
		 * builtin_tls so that __copy_tls will use the same layout
		 * as it did for before. Then check, just to be safe. */
		libc.tls_size = sizeof builtin_tls;
		if (__copy_tls((void*)builtin_tls) != self) a_crash();
		libc.tls_size = tmp_tls_size;
1613
	}
1614
	static_tls_cnt = tls_cnt;
1615

1616
	if (ldso_fail) _exit(127);
1617 1618
	if (ldd_mode) _exit(0);

1619 1620
	/* Switch to runtime mode: any further failures in the dynamic
	 * linker are a reportable failure rather than a fatal startup
R
Rich Felker 已提交
1621
	 * error. */
R
Rich Felker 已提交
1622
	runtime = 1;
1623

1624
	debug.ver = 1;
1625
	debug.bp = dl_debug_state;
1626
	debug.head = head;
R
Rich Felker 已提交
1627
	debug.base = ldso.base;
1628 1629 1630
	debug.state = 0;
	_dl_debug_state();

1631
	__init_libc(envp, argv[0]);
1632
	atexit(do_fini);
1633
	errno = 0;
1634
	do_init_fini(tail);
1635

R
Rich Felker 已提交
1636 1637
	CRTJMP((void *)aux[AT_ENTRY], argv-1);
	for(;;);
1638 1639
}

1640 1641
void *dlopen(const char *file, int mode)
{
R
Rich Felker 已提交
1642
	struct dso *volatile p, *orig_tail, *next;
R
Rich Felker 已提交
1643
	size_t orig_tls_cnt, orig_tls_offset, orig_tls_align;
1644
	size_t i;
1645
	int cs;
1646
	jmp_buf jb;
1647 1648 1649

	if (!file) return head;

1650
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
1651
	pthread_rwlock_wrlock(&lock);
1652
	__inhibit_ptc();
1653

1654 1655
	p = 0;
	orig_tls_cnt = tls_cnt;
R
Rich Felker 已提交
1656 1657
	orig_tls_offset = tls_offset;
	orig_tls_align = tls_align;
R
Rich Felker 已提交
1658
	orig_tail = tail;
1659
	noload = mode & RTLD_NOLOAD;
R
Rich Felker 已提交
1660

1661 1662
	rtld_fail = &jb;
	if (setjmp(*rtld_fail)) {
1663
		/* Clean up anything new that was (partially) loaded */
1664
		if (p && p->deps) for (i=0; p->deps[i]; i++)
1665 1666
			if (p->deps[i]->global < 0)
				p->deps[i]->global = 0;
1667 1668
		for (p=orig_tail->next; p; p=next) {
			next = p->next;
1669 1670 1671 1672 1673
			while (p->td_index) {
				void *tmp = p->td_index->next;
				free(p->td_index);
				p->td_index = tmp;
			}
1674
			free(p->funcdescs);
1675 1676
			if (p->rpath != p->rpath_orig)
				free(p->rpath);
1677
			free(p->deps);
1678
			unmap_library(p);
1679 1680
			free(p);
		}
1681
		tls_cnt = orig_tls_cnt;
R
Rich Felker 已提交
1682 1683
		tls_offset = orig_tls_offset;
		tls_align = orig_tls_align;
1684 1685
		tail = orig_tail;
		tail->next = 0;
1686
		p = 0;
1687
		goto end;
1688
	} else p = load_library(file, head);
R
Rich Felker 已提交
1689 1690

	if (!p) {
1691
		error(noload ?
1692 1693 1694
			"Library %s is not already loaded" :
			"Error loading shared library %s: %m",
			file);
1695
		goto end;
1696 1697 1698 1699 1700
	}

	/* First load handling */
	if (!p->deps) {
		load_deps(p);
R
Rich Felker 已提交
1701
		if (p->deps) for (i=0; p->deps[i]; i++)
1702 1703 1704
			if (!p->deps[i]->global)
				p->deps[i]->global = -1;
		if (!p->global) p->global = -1;
1705
		reloc_all(p);
R
Rich Felker 已提交
1706
		if (p->deps) for (i=0; p->deps[i]; i++)
1707 1708 1709
			if (p->deps[i]->global < 0)
				p->deps[i]->global = 0;
		if (p->global < 0) p->global = 0;
1710 1711 1712
	}

	if (mode & RTLD_GLOBAL) {
R
Rich Felker 已提交
1713
		if (p->deps) for (i=0; p->deps[i]; i++)
1714 1715 1716 1717
			p->deps[i]->global = 1;
		p->global = 1;
	}

R
Rich Felker 已提交
1718
	update_tls_size();
1719
	_dl_debug_state();
1720
	orig_tail = tail;
1721
end:
1722
	__release_ptc();
R
Rich Felker 已提交
1723
	if (p) gencnt++;
1724
	pthread_rwlock_unlock(&lock);
1725
	if (p) do_init_fini(orig_tail);
1726
	pthread_setcancelstate(cs, 0);
1727 1728 1729
	return p;
}

1730
static int invalid_dso_handle(void *h)
1731 1732 1733
{
	struct dso *p;
	for (p=head; p; p=p->next) if (h==p) return 0;
1734
	error("Invalid library handle %p", (void *)h);
1735 1736 1737
	return 1;
}

1738 1739
void *__tls_get_addr(size_t *);

R
Rich Felker 已提交
1740
static void *do_dlsym(struct dso *p, const char *s, void *ra)
1741 1742
{
	size_t i;
1743
	uint32_t h = 0, gh = 0, *ght;
1744
	Sym *sym;
1745
	if (p == head || p == RTLD_DEFAULT || p == RTLD_NEXT) {
1746 1747 1748
		if (p == RTLD_DEFAULT) {
			p = head;
		} else if (p == RTLD_NEXT) {
1749 1750
			for (p=head; p && (unsigned char *)ra-p->map>p->map_len; p=p->next);
			if (!p) p=head;
1751
			p = p->next;
1752
		}
1753
		struct symdef def = find_sym(p, s, 0);
1754
		if (!def.sym) goto failed;
1755 1756
		if ((def.sym->st_info&0xf) == STT_TLS)
			return __tls_get_addr((size_t []){def.dso->tls_id, def.sym->st_value});
1757
		return laddr(def.dso, def.sym->st_value);
R
Rich Felker 已提交
1758
	}
1759
	if (invalid_dso_handle(p))
1760
		return 0;
1761
	if ((ght = p->ghashtab)) {
1762
		gh = gnu_hash(s);
1763
		sym = gnu_lookup(gh, ght, p, s);
1764 1765 1766 1767
	} else {
		h = sysv_hash(s);
		sym = sysv_lookup(s, h, p);
	}
1768 1769
	if (sym && (sym->st_info&0xf) == STT_TLS)
		return __tls_get_addr((size_t []){p->tls_id, sym->st_value});
1770
	if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
1771
		return laddr(p, sym->st_value);
1772
	if (p->deps) for (i=0; p->deps[i]; i++) {
1773
		if ((ght = p->deps[i]->ghashtab)) {
1774
			if (!gh) gh = gnu_hash(s);
1775
			sym = gnu_lookup(gh, ght, p->deps[i], s);
1776 1777 1778 1779
		} else {
			if (!h) h = sysv_hash(s);
			sym = sysv_lookup(s, h, p->deps[i]);
		}
1780 1781
		if (sym && (sym->st_info&0xf) == STT_TLS)
			return __tls_get_addr((size_t []){p->deps[i]->tls_id, sym->st_value});
1782
		if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
1783
			return laddr(p->deps[i], sym->st_value);
1784
	}
1785
failed:
1786
	error("Symbol not found: %s", s);
1787 1788 1789
	return 0;
}

1790
int __dladdr(const void *addr, Dl_info *info)
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
{
	struct dso *p;
	Sym *sym;
	uint32_t nsym;
	char *strings;
	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;
1807
	nsym = count_syms(p);
1808 1809

	for (; nsym; nsym--, sym++) {
1810
		if (sym->st_value
1811 1812
		 && (1<<(sym->st_info&0xf) & OK_TYPES)
		 && (1<<(sym->st_info>>4) & OK_BINDS)) {
1813
			void *symaddr = laddr(p, sym->st_value);
1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
			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;
}

1833
__attribute__((__visibility__("hidden")))
1834
void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
1835 1836 1837
{
	void *res;
	pthread_rwlock_rdlock(&lock);
R
Rich Felker 已提交
1838
	res = do_dlsym(p, s, ra);
1839 1840 1841
	pthread_rwlock_unlock(&lock);
	return res;
}
R
Rich Felker 已提交
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867

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;
}
1868
#else
1869
static int invalid_dso_handle(void *h)
1870
{
1871
	error("Invalid library handle %p", (void *)h);
1872 1873
	return 1;
}
1874 1875
void *dlopen(const char *file, int mode)
{
1876
	error("Dynamic loading not supported");
1877 1878
	return 0;
}
1879
void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
1880
{
1881
	error("Symbol not found: %s", s);
1882 1883
	return 0;
}
1884
int __dladdr (const void *addr, Dl_info *info)
1885 1886 1887
{
	return 0;
}
1888
#endif
1889

R
Rich Felker 已提交
1890 1891 1892 1893
int __dlinfo(void *dso, int req, void *res)
{
	if (invalid_dso_handle(dso)) return -1;
	if (req != RTLD_DI_LINKMAP) {
1894
		error("Unsupported request %d", req);
R
Rich Felker 已提交
1895 1896 1897 1898 1899 1900
		return -1;
	}
	*(struct link_map **)res = dso;
	return 0;
}

1901 1902
char *dlerror()
{
1903 1904 1905 1906 1907 1908 1909 1910
	pthread_t self = __pthread_self();
	if (!self->dlerror_flag) return 0;
	self->dlerror_flag = 0;
	char *s = self->dlerror_buf;
	if (s == (void *)-1)
		return "Dynamic linker failed to allocate memory for error message";
	else
		return s;
1911 1912 1913 1914
}

int dlclose(void *p)
{
1915
	return invalid_dso_handle(p);
1916
}
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953

void __dl_thread_cleanup(void)
{
	pthread_t self = __pthread_self();
	if (self->dlerror_buf != (void *)-1)
		free(self->dlerror_buf);
}

static void error(const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
#ifdef SHARED
	if (!runtime) {
		vdprintf(2, fmt, ap);
		dprintf(2, "\n");
		ldso_fail = 1;
		va_end(ap);
		return;
	}
#endif
	pthread_t self = __pthread_self();
	if (self->dlerror_buf != (void *)-1)
		free(self->dlerror_buf);
	size_t len = vsnprintf(0, 0, fmt, ap);
	va_end(ap);
	char *buf = malloc(len+1);
	if (buf) {
		va_start(ap, fmt);
		vsnprintf(buf, len+1, fmt, ap);
		va_end(ap);
	} else {
		buf = (void *)-1;	
	}
	self->dlerror_buf = buf;
	self->dlerror_flag = 1;
}