1/*-
2 * Copyright (c) 2014-2015 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * Portions of this software were developed by Andrew Turner
6 * under sponsorship from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/types.h>
31
32#include <machine/sysarch.h>
33
34#include <stdlib.h>
35
36#include "debug.h"
37#include "rtld.h"
38#include "rtld_printf.h"
39
40/*
41 * It is possible for the compiler to emit relocations for unaligned data.
42 * We handle this situation with these inlines.
43 */
44#define	RELOC_ALIGNED_P(x) \
45	(((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
46
47/*
48 * This is not the correct prototype, but we only need it for
49 * a function pointer to a simple asm function.
50 */
51void *_rtld_tlsdesc_static(void *);
52void *_rtld_tlsdesc_undef(void *);
53void *_rtld_tlsdesc_dynamic(void *);
54
55void _exit(int);
56
57bool
58arch_digest_dynamic(struct Struct_Obj_Entry *obj, const Elf_Dyn *dynp)
59{
60	if (dynp->d_tag == DT_AARCH64_VARIANT_PCS) {
61		obj->variant_pcs = true;
62		return (true);
63	}
64
65	return (false);
66}
67
68bool
69arch_digest_note(struct Struct_Obj_Entry *obj __unused, const Elf_Note *note)
70{
71	const char *note_name;
72	const uint32_t *note_data;
73
74	note_name = (const char *)(note + 1);
75	/* Only handle GNU notes */
76	if (note->n_namesz != sizeof(ELF_NOTE_GNU) ||
77	    strncmp(note_name, ELF_NOTE_GNU, sizeof(ELF_NOTE_GNU)) != 0)
78		return (false);
79
80	/* Only handle GNU property notes */
81	if (note->n_type != NT_GNU_PROPERTY_TYPE_0)
82		return (false);
83
84	/*
85	 * note_data[0] - Type
86	 * note_data[1] - Length
87	 * note_data[2] - Data
88	 * note_data[3] - Padding?
89	 */
90	note_data = (const uint32_t *)(note_name + note->n_namesz);
91
92	/* Only handle AArch64 feature notes */
93	if (note_data[0] != GNU_PROPERTY_AARCH64_FEATURE_1_AND)
94		return (false);
95
96	/* We expect at least 4 bytes of data */
97	if (note_data[1] < 4)
98		return (false);
99
100	/* TODO: Only guard if HWCAP2_BTI is set */
101	if ((note_data[2] & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0) {
102		struct arm64_guard_page_args guard;
103
104		guard.addr = (uintptr_t)obj->mapbase;
105		guard.len = obj->mapsize;
106
107		sysarch(ARM64_GUARD_PAGE, &guard);
108	}
109
110	return (true);
111}
112
113void
114init_pltgot(Obj_Entry *obj)
115{
116
117	if (obj->pltgot != NULL) {
118		obj->pltgot[1] = (Elf_Addr) obj;
119		obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
120	}
121}
122
123int
124do_copy_relocations(Obj_Entry *dstobj)
125{
126	const Obj_Entry *srcobj, *defobj;
127	const Elf_Rela *relalim;
128	const Elf_Rela *rela;
129	const Elf_Sym *srcsym;
130	const Elf_Sym *dstsym;
131	const void *srcaddr;
132	const char *name;
133	void *dstaddr;
134	SymLook req;
135	size_t size;
136	int res;
137
138	/*
139	 * COPY relocs are invalid outside of the main program
140	 */
141	assert(dstobj->mainprog);
142
143	relalim = (const Elf_Rela *)((const char *)dstobj->rela +
144	    dstobj->relasize);
145	for (rela = dstobj->rela; rela < relalim; rela++) {
146		if (ELF_R_TYPE(rela->r_info) != R_AARCH64_COPY)
147			continue;
148
149		dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
150		dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
151		name = dstobj->strtab + dstsym->st_name;
152		size = dstsym->st_size;
153
154		symlook_init(&req, name);
155		req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
156		req.flags = SYMLOOK_EARLY;
157
158		for (srcobj = globallist_next(dstobj); srcobj != NULL;
159		     srcobj = globallist_next(srcobj)) {
160			res = symlook_obj(&req, srcobj);
161			if (res == 0) {
162				srcsym = req.sym_out;
163				defobj = req.defobj_out;
164				break;
165			}
166		}
167		if (srcobj == NULL) {
168			_rtld_error("Undefined symbol \"%s\" referenced from "
169			    "COPY relocation in %s", name, dstobj->path);
170			return (-1);
171		}
172
173		srcaddr = (const void *)(defobj->relocbase + srcsym->st_value);
174		memcpy(dstaddr, srcaddr, size);
175	}
176
177	return (0);
178}
179
180struct tls_data {
181	Elf_Addr	dtv_gen;
182	int		tls_index;
183	Elf_Addr	tls_offs;
184};
185
186static struct tls_data *
187reloc_tlsdesc_alloc(int tlsindex, Elf_Addr tlsoffs)
188{
189	struct tls_data *tlsdesc;
190
191	tlsdesc = xmalloc(sizeof(struct tls_data));
192	tlsdesc->dtv_gen = tls_dtv_generation;
193	tlsdesc->tls_index = tlsindex;
194	tlsdesc->tls_offs = tlsoffs;
195
196	return (tlsdesc);
197}
198
199struct tlsdesc_entry {
200	void	*(*func)(void *);
201	union {
202		Elf_Ssize	addend;
203		Elf_Size	offset;
204		struct tls_data	*data;
205	};
206};
207
208static void
209reloc_tlsdesc(const Obj_Entry *obj, const Elf_Rela *rela,
210    struct tlsdesc_entry *where, int flags, RtldLockState *lockstate)
211{
212	const Elf_Sym *def;
213	const Obj_Entry *defobj;
214	Elf_Addr offs;
215
216	offs = 0;
217	if (ELF_R_SYM(rela->r_info) != 0) {
218		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, flags,
219			    NULL, lockstate);
220		if (def == NULL)
221			rtld_die();
222		offs = def->st_value;
223		obj = defobj;
224		if (def->st_shndx == SHN_UNDEF) {
225			/* Weak undefined thread variable */
226			where->func = _rtld_tlsdesc_undef;
227			where->addend = rela->r_addend;
228			return;
229		}
230	}
231	offs += rela->r_addend;
232
233	if (obj->tlsoffset != 0) {
234		/* Variable is in initialy allocated TLS segment */
235		where->func = _rtld_tlsdesc_static;
236		where->offset = obj->tlsoffset + offs;
237	} else {
238		/* TLS offest is unknown at load time, use dynamic resolving */
239		where->func = _rtld_tlsdesc_dynamic;
240		where->data = reloc_tlsdesc_alloc(obj->tlsindex, offs);
241	}
242}
243
244/*
245 * Process the PLT relocations.
246 */
247int
248reloc_plt(Obj_Entry *obj, int flags, RtldLockState *lockstate)
249{
250	const Obj_Entry *defobj;
251	const Elf_Rela *relalim;
252	const Elf_Rela *rela;
253	const Elf_Sym *def, *sym;
254	bool lazy;
255
256	relalim = (const Elf_Rela *)((const char *)obj->pltrela +
257	    obj->pltrelasize);
258	for (rela = obj->pltrela; rela < relalim; rela++) {
259		Elf_Addr *where, target;
260
261		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
262
263		switch(ELF_R_TYPE(rela->r_info)) {
264		case R_AARCH64_JUMP_SLOT:
265			lazy = true;
266			if (obj->variant_pcs) {
267				sym = &obj->symtab[ELF_R_SYM(rela->r_info)];
268				/*
269				 * Variant PCS functions don't follow the
270				 * standard register convention. Because of
271				 * this we can't use lazy relocation and
272				 * need to set the target address.
273				 */
274				if ((sym->st_other & STO_AARCH64_VARIANT_PCS) !=
275				    0)
276					lazy = false;
277			}
278			if (lazy) {
279				*where += (Elf_Addr)obj->relocbase;
280			} else {
281				def = find_symdef(ELF_R_SYM(rela->r_info), obj,
282				    &defobj, SYMLOOK_IN_PLT | flags, NULL,
283				    lockstate);
284				if (def == NULL)
285					return (-1);
286				if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC){
287					obj->gnu_ifunc = true;
288					continue;
289				}
290				target = (Elf_Addr)(defobj->relocbase +
291				    def->st_value);
292				/*
293				 * Ignore ld_bind_not as it requires lazy
294				 * binding
295				 */
296				*where = target;
297			}
298			break;
299		case R_AARCH64_TLSDESC:
300			reloc_tlsdesc(obj, rela, (struct tlsdesc_entry *)where,
301			    SYMLOOK_IN_PLT | flags, lockstate);
302			break;
303		case R_AARCH64_IRELATIVE:
304			obj->irelative = true;
305			break;
306		case R_AARCH64_NONE:
307			break;
308		default:
309			_rtld_error("Unknown relocation type %u in PLT",
310			    (unsigned int)ELF_R_TYPE(rela->r_info));
311			return (-1);
312		}
313	}
314
315	return (0);
316}
317
318/*
319 * LD_BIND_NOW was set - force relocation for all jump slots
320 */
321int
322reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
323{
324	const Obj_Entry *defobj;
325	const Elf_Rela *relalim;
326	const Elf_Rela *rela;
327	const Elf_Sym *def;
328
329	if (obj->jmpslots_done)
330		return (0);
331
332	relalim = (const Elf_Rela *)((const char *)obj->pltrela +
333	    obj->pltrelasize);
334	for (rela = obj->pltrela; rela < relalim; rela++) {
335		Elf_Addr *where, target;
336
337		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
338		switch(ELF_R_TYPE(rela->r_info)) {
339		case R_AARCH64_JUMP_SLOT:
340			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
341			    &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate);
342			if (def == NULL)
343				return (-1);
344			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
345				obj->gnu_ifunc = true;
346				continue;
347			}
348			target = (Elf_Addr)(defobj->relocbase + def->st_value);
349			reloc_jmpslot(where, target, defobj, obj,
350			    (const Elf_Rel *)rela);
351			break;
352		}
353	}
354	obj->jmpslots_done = true;
355
356	return (0);
357}
358
359static void
360reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela,
361    RtldLockState *lockstate)
362{
363	Elf_Addr *where, target, *ptr;
364
365	ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
366	where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
367	lock_release(rtld_bind_lock, lockstate);
368	target = call_ifunc_resolver(ptr);
369	wlock_acquire(rtld_bind_lock, lockstate);
370	*where = target;
371}
372
373int
374reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
375{
376	const Elf_Rela *relalim;
377	const Elf_Rela *rela;
378
379	if (!obj->irelative)
380		return (0);
381	obj->irelative = false;
382	relalim = (const Elf_Rela *)((const char *)obj->pltrela +
383	    obj->pltrelasize);
384	for (rela = obj->pltrela;  rela < relalim;  rela++) {
385		if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE)
386			reloc_iresolve_one(obj, rela, lockstate);
387	}
388	return (0);
389}
390
391int
392reloc_iresolve_nonplt(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
393{
394	const Elf_Rela *relalim;
395	const Elf_Rela *rela;
396
397	if (!obj->irelative_nonplt)
398		return (0);
399	obj->irelative_nonplt = false;
400	relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize);
401	for (rela = obj->rela;  rela < relalim;  rela++) {
402		if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE)
403			reloc_iresolve_one(obj, rela, lockstate);
404	}
405	return (0);
406}
407
408int
409reloc_gnu_ifunc(Obj_Entry *obj, int flags,
410   struct Struct_RtldLockState *lockstate)
411{
412	const Elf_Rela *relalim;
413	const Elf_Rela *rela;
414	Elf_Addr *where, target;
415	const Elf_Sym *def;
416	const Obj_Entry *defobj;
417
418	if (!obj->gnu_ifunc)
419		return (0);
420	relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize);
421	for (rela = obj->pltrela;  rela < relalim;  rela++) {
422		if (ELF_R_TYPE(rela->r_info) == R_AARCH64_JUMP_SLOT) {
423			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
424			def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
425			    SYMLOOK_IN_PLT | flags, NULL, lockstate);
426			if (def == NULL)
427				return (-1);
428			if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
429				continue;
430			lock_release(rtld_bind_lock, lockstate);
431			target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
432			wlock_acquire(rtld_bind_lock, lockstate);
433			reloc_jmpslot(where, target, defobj, obj,
434			    (const Elf_Rel *)rela);
435		}
436	}
437	obj->gnu_ifunc = false;
438	return (0);
439}
440
441Elf_Addr
442reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
443    const Obj_Entry *defobj __unused, const Obj_Entry *obj __unused,
444    const Elf_Rel *rel)
445{
446
447	assert(ELF_R_TYPE(rel->r_info) == R_AARCH64_JUMP_SLOT ||
448	    ELF_R_TYPE(rel->r_info) == R_AARCH64_IRELATIVE);
449
450	if (*where != target && !ld_bind_not)
451		*where = target;
452	return (target);
453}
454
455void
456ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
457{
458
459}
460
461/*
462 * Process non-PLT relocations
463 */
464int
465reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
466    RtldLockState *lockstate)
467{
468	const Obj_Entry *defobj;
469	const Elf_Rela *relalim;
470	const Elf_Rela *rela;
471	const Elf_Sym *def;
472	SymCache *cache;
473	Elf_Addr *where, symval;
474
475	/*
476	 * The dynamic loader may be called from a thread, we have
477	 * limited amounts of stack available so we cannot use alloca().
478	 */
479	if (obj == obj_rtld)
480		cache = NULL;
481	else
482		cache = calloc(obj->dynsymcount, sizeof(SymCache));
483		/* No need to check for NULL here */
484
485	relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize);
486	for (rela = obj->rela; rela < relalim; rela++) {
487		/*
488		 * First, resolve symbol for relocations which
489		 * reference symbols.
490		 */
491		switch (ELF_R_TYPE(rela->r_info)) {
492		case R_AARCH64_ABS64:
493		case R_AARCH64_GLOB_DAT:
494		case R_AARCH64_TLS_TPREL64:
495		case R_AARCH64_TLS_DTPREL64:
496		case R_AARCH64_TLS_DTPMOD64:
497			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
498			    &defobj, flags, cache, lockstate);
499			if (def == NULL)
500				return (-1);
501			/*
502			 * If symbol is IFUNC, only perform relocation
503			 * when caller allowed it by passing
504			 * SYMLOOK_IFUNC flag.  Skip the relocations
505			 * otherwise.
506			 *
507			 * Also error out in case IFUNC relocations
508			 * are specified for TLS, which cannot be
509			 * usefully interpreted.
510			 */
511			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
512				switch (ELF_R_TYPE(rela->r_info)) {
513				case R_AARCH64_ABS64:
514				case R_AARCH64_GLOB_DAT:
515					if ((flags & SYMLOOK_IFUNC) == 0) {
516						obj->non_plt_gnu_ifunc = true;
517						continue;
518					}
519					symval = (Elf_Addr)rtld_resolve_ifunc(
520					    defobj, def);
521					break;
522				default:
523					_rtld_error("%s: IFUNC for TLS reloc",
524					    obj->path);
525					return (-1);
526				}
527			} else {
528				if ((flags & SYMLOOK_IFUNC) != 0)
529					continue;
530				symval = (Elf_Addr)defobj->relocbase +
531				    def->st_value;
532			}
533			break;
534		default:
535			if ((flags & SYMLOOK_IFUNC) != 0)
536				continue;
537		}
538
539		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
540
541		switch (ELF_R_TYPE(rela->r_info)) {
542		case R_AARCH64_ABS64:
543		case R_AARCH64_GLOB_DAT:
544			*where = symval + rela->r_addend;
545			break;
546		case R_AARCH64_COPY:
547			/*
548			 * These are deferred until all other relocations have
549			 * been done. All we do here is make sure that the
550			 * COPY relocation is not in a shared library. They
551			 * are allowed only in executable files.
552			 */
553			if (!obj->mainprog) {
554				_rtld_error("%s: Unexpected R_AARCH64_COPY "
555				    "relocation in shared library", obj->path);
556				return (-1);
557			}
558			break;
559		case R_AARCH64_TLSDESC:
560			reloc_tlsdesc(obj, rela, (struct tlsdesc_entry *)where,
561			    flags, lockstate);
562			break;
563		case R_AARCH64_TLS_TPREL64:
564			/*
565			 * We lazily allocate offsets for static TLS as we
566			 * see the first relocation that references the
567			 * TLS block. This allows us to support (small
568			 * amounts of) static TLS in dynamically loaded
569			 * modules. If we run out of space, we generate an
570			 * error.
571			 */
572			if (!defobj->tls_static) {
573				if (!allocate_tls_offset(
574				    __DECONST(Obj_Entry *, defobj))) {
575					_rtld_error(
576					    "%s: No space available for static "
577					    "Thread Local Storage", obj->path);
578					return (-1);
579				}
580			}
581			*where = def->st_value + rela->r_addend +
582			    defobj->tlsoffset;
583			break;
584
585		/*
586		 * !!! BEWARE !!!
587		 * ARM ELF ABI defines TLS_DTPMOD64 as 1029, and TLS_DTPREL64
588		 * as 1028. But actual bfd linker and the glibc RTLD linker
589		 * treats TLS_DTPMOD64 as 1028 and TLS_DTPREL64 1029.
590		 */
591		case R_AARCH64_TLS_DTPREL64: /* efectively is TLS_DTPMOD64 */
592			*where += (Elf_Addr)defobj->tlsindex;
593			break;
594		case R_AARCH64_TLS_DTPMOD64: /* efectively is TLS_DTPREL64 */
595			*where += (Elf_Addr)(def->st_value + rela->r_addend);
596			break;
597		case R_AARCH64_RELATIVE:
598			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
599			break;
600		case R_AARCH64_NONE:
601			break;
602		case R_AARCH64_IRELATIVE:
603			obj->irelative_nonplt = true;
604			break;
605		default:
606			rtld_printf("%s: Unhandled relocation %lu\n",
607			    obj->path, ELF_R_TYPE(rela->r_info));
608			return (-1);
609		}
610	}
611
612	return (0);
613}
614
615void
616allocate_initial_tls(Obj_Entry *objs)
617{
618
619	/*
620	* Fix the size of the static TLS block by using the maximum
621	* offset allocated so far and adding a bit for dynamic modules to
622	* use.
623	*/
624	tls_static_space = tls_last_offset + tls_last_size +
625	    ld_static_tls_extra;
626
627	_tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
628}
629
630void *
631__tls_get_addr(tls_index* ti)
632{
633	uintptr_t **dtvp;
634
635	dtvp = &_tcb_get()->tcb_dtv;
636	return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset));
637}
638