reloc.c revision 331206
1/*	$NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $	*/
2
3/*-
4 * Copyright (c) 2000 Eduardo Horvath.
5 * Copyright (c) 1999 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Paul Kranenburg.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: stable/10/libexec/rtld-elf/sparc64/reloc.c 331206 2018-03-19 14:28:58Z marius $");
35
36#include <sys/param.h>
37#include <sys/mman.h>
38
39#include <errno.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45#include "debug.h"
46#include "rtld.h"
47
48/*
49 * The following table holds for each relocation type:
50 *	- the width in bits of the memory location the relocation
51 *	  applies to (not currently used)
52 *	- the number of bits the relocation value must be shifted to the
53 *	  right (i.e. discard least significant bits) to fit into
54 *	  the appropriate field in the instruction word.
55 *	- flags indicating whether
56 *		* the relocation involves a symbol
57 *		* the relocation is relative to the current position
58 *		* the relocation is for a GOT entry
59 *		* the relocation is relative to the load address
60 *
61 */
62#define	_RF_S		0x80000000		/* Resolve symbol */
63#define	_RF_A		0x40000000		/* Use addend */
64#define	_RF_P		0x20000000		/* Location relative */
65#define	_RF_G		0x10000000		/* GOT offset */
66#define	_RF_B		0x08000000		/* Load address relative */
67#define	_RF_U		0x04000000		/* Unaligned */
68#define	_RF_X		0x02000000		/* Bare symbols, needs proc */
69#define	_RF_D		0x01000000		/* Use dynamic TLS offset */
70#define	_RF_O		0x00800000		/* Use static TLS offset */
71#define	_RF_I		0x00400000		/* Use TLS object ID */
72#define	_RF_SZ(s)	(((s) & 0xff) << 8)	/* memory target size */
73#define	_RF_RS(s)	( (s) & 0xff)		/* right shift */
74static const int reloc_target_flags[] = {
75	0,							/* NONE */
76	_RF_S|_RF_A|		_RF_SZ(8)  | _RF_RS(0),		/* 8 */
77	_RF_S|_RF_A|		_RF_SZ(16) | _RF_RS(0),		/* 16 */
78	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* 32 */
79	_RF_S|_RF_A|_RF_P|	_RF_SZ(8)  | _RF_RS(0),		/* DISP_8 */
80	_RF_S|_RF_A|_RF_P|	_RF_SZ(16) | _RF_RS(0),		/* DISP_16 */
81	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* DISP_32 */
82	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP_30 */
83	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP_22 */
84	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(10),	/* HI22 */
85	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 22 */
86	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 13 */
87	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* LO10 */
88	_RF_G|			_RF_SZ(32) | _RF_RS(0),		/* GOT10 */
89	_RF_G|			_RF_SZ(32) | _RF_RS(0),		/* GOT13 */
90	_RF_G|			_RF_SZ(32) | _RF_RS(10),	/* GOT22 */
91	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PC10 */
92	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PC22 */
93	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WPLT30 */
94				_RF_SZ(32) | _RF_RS(0),		/* COPY */
95	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* GLOB_DAT */
96				_RF_SZ(32) | _RF_RS(0),		/* JMP_SLOT */
97	      _RF_A|	_RF_B|	_RF_SZ(64) | _RF_RS(0),		/* RELATIVE */
98	_RF_S|_RF_A|	_RF_U|	_RF_SZ(32) | _RF_RS(0),		/* UA_32 */
99
100	      _RF_A|		_RF_SZ(32) | _RF_RS(0),		/* PLT32 */
101	      _RF_A|		_RF_SZ(32) | _RF_RS(10),	/* HIPLT22 */
102	      _RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LOPLT10 */
103	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PCPLT32 */
104	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PCPLT22 */
105	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(0),		/* PCPLT10 */
106	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 10 */
107	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 11 */
108	_RF_S|_RF_A|_RF_X|	_RF_SZ(64) | _RF_RS(0),		/* 64 */
109	_RF_S|_RF_A|/*extra*/	_RF_SZ(32) | _RF_RS(0),		/* OLO10 */
110	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(42),	/* HH22 */
111	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(32),	/* HM10 */
112	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(10),	/* LM22 */
113	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(42),	/* PC_HH22 */
114	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(32),	/* PC_HM10 */
115	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(10),	/* PC_LM22 */
116	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP16 */
117	_RF_S|_RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* WDISP19 */
118	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* GLOB_JMP */
119	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 7 */
120	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 5 */
121	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* 6 */
122	_RF_S|_RF_A|_RF_P|	_RF_SZ(64) | _RF_RS(0),		/* DISP64 */
123	      _RF_A|		_RF_SZ(64) | _RF_RS(0),		/* PLT64 */
124	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(10),	/* HIX22 */
125	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* LOX10 */
126	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(22),	/* H44 */
127	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(12),	/* M44 */
128	_RF_S|_RF_A|_RF_X|	_RF_SZ(32) | _RF_RS(0),		/* L44 */
129	_RF_S|_RF_A|		_RF_SZ(64) | _RF_RS(0),		/* REGISTER */
130	_RF_S|_RF_A|	_RF_U|	_RF_SZ(64) | _RF_RS(0),		/* UA64 */
131	_RF_S|_RF_A|	_RF_U|	_RF_SZ(16) | _RF_RS(0),		/* UA16 */
132
133	/* TLS */
134	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* GD_HI22 */
135	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* GD_LO10 */
136	0,							/* GD_ADD */
137	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* GD_CALL */
138	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* LDM_HI22 */
139	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LDM_LO10 */
140	0,							/* LDM_ADD */
141	      _RF_A|_RF_P|	_RF_SZ(32) | _RF_RS(2),		/* LDM_CALL */
142	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* LDO_HIX22 */
143	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* LDO_LOX10 */
144	0,							/* LDO_ADD */
145	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(10),	/* IE_HI22 */
146	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* IE_LO10 */
147	0,							/* IE_LD */
148	0,							/* IE_LDX */
149	0,							/* IE_ADD */
150	_RF_S|_RF_A|	_RF_O|	_RF_SZ(32) | _RF_RS(10),	/* LE_HIX22 */
151	_RF_S|_RF_A|	_RF_O|	_RF_SZ(32) | _RF_RS(0),		/* LE_LOX10 */
152	_RF_S|		_RF_I|	_RF_SZ(32) | _RF_RS(0),		/* DTPMOD32 */
153	_RF_S|		_RF_I|	_RF_SZ(64) | _RF_RS(0),		/* DTPMOD64 */
154	_RF_S|_RF_A|	_RF_D|	_RF_SZ(32) | _RF_RS(0),		/* DTPOFF32 */
155	_RF_S|_RF_A|	_RF_D|	_RF_SZ(64) | _RF_RS(0),		/* DTPOFF64 */
156	_RF_S|_RF_A|	_RF_O|	_RF_SZ(32) | _RF_RS(0),		/* TPOFF32 */
157	_RF_S|_RF_A|	_RF_O|	_RF_SZ(64) | _RF_RS(0)		/* TPOFF64 */
158};
159
160#if 0
161static const char *const reloc_names[] = {
162	"NONE", "8", "16", "32", "DISP_8", "DISP_16", "DISP_32", "WDISP_30",
163	"WDISP_22", "HI22", "22", "13", "LO10", "GOT10", "GOT13", "GOT22",
164	"PC10", "PC22", "WPLT30", "COPY", "GLOB_DAT", "JMP_SLOT", "RELATIVE",
165	"UA_32", "PLT32", "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22",
166	"PCPLT32", "10", "11", "64", "OLO10", "HH22", "HM10", "LM22",
167	"PC_HH22", "PC_HM10", "PC_LM22", "WDISP16", "WDISP19", "GLOB_JMP",
168	"7", "5", "6", "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44",
169	"L44", "REGISTER", "UA64", "UA16", "GD_HI22", "GD_LO10", "GD_ADD",
170	"GD_CALL", "LDM_HI22", "LDMO10", "LDM_ADD", "LDM_CALL", "LDO_HIX22",
171	"LDO_LOX10", "LDO_ADD", "IE_HI22", "IE_LO10", "IE_LD", "IE_LDX",
172	"IE_ADD", "LE_HIX22", "LE_LOX10", "DTPMOD32", "DTPMOD64", "DTPOFF32",
173	"DTPOFF64", "TPOFF32", "TPOFF64"
174};
175#endif
176
177#define	RELOC_RESOLVE_SYMBOL(t)		((reloc_target_flags[t] & _RF_S) != 0)
178#define	RELOC_PC_RELATIVE(t)		((reloc_target_flags[t] & _RF_P) != 0)
179#define	RELOC_BASE_RELATIVE(t)		((reloc_target_flags[t] & _RF_B) != 0)
180#define	RELOC_UNALIGNED(t)		((reloc_target_flags[t] & _RF_U) != 0)
181#define	RELOC_USE_ADDEND(t)		((reloc_target_flags[t] & _RF_A) != 0)
182#define	RELOC_BARE_SYMBOL(t)		((reloc_target_flags[t] & _RF_X) != 0)
183#define	RELOC_USE_TLS_DOFF(t)		((reloc_target_flags[t] & _RF_D) != 0)
184#define	RELOC_USE_TLS_OFF(t)		((reloc_target_flags[t] & _RF_O) != 0)
185#define	RELOC_USE_TLS_ID(t)		((reloc_target_flags[t] & _RF_I) != 0)
186#define	RELOC_TARGET_SIZE(t)		((reloc_target_flags[t] >> 8) & 0xff)
187#define	RELOC_VALUE_RIGHTSHIFT(t)	(reloc_target_flags[t] & 0xff)
188
189static const long reloc_target_bitmask[] = {
190#define	_BM(x)	(~(-(1ULL << (x))))
191	0,				/* NONE */
192	_BM(8), _BM(16), _BM(32),	/* 8, 16, 32 */
193	_BM(8), _BM(16), _BM(32),	/* DISP8, DISP16, DISP32 */
194	_BM(30), _BM(22),		/* WDISP30, WDISP22 */
195	_BM(22), _BM(22),		/* HI22, 22 */
196	_BM(13), _BM(10),		/* 13, LO10 */
197	_BM(10), _BM(13), _BM(22),	/* GOT10, GOT13, GOT22 */
198	_BM(10), _BM(22),		/* PC10, PC22 */
199	_BM(30), 0,			/* WPLT30, COPY */
200	_BM(32), _BM(32), _BM(32),	/* GLOB_DAT, JMP_SLOT, RELATIVE */
201	_BM(32), _BM(32),		/* UA32, PLT32 */
202	_BM(22), _BM(10),		/* HIPLT22, LOPLT10 */
203	_BM(32), _BM(22), _BM(10),	/* PCPLT32, PCPLT22, PCPLT10 */
204	_BM(10), _BM(11), -1,		/* 10, 11, 64 */
205	_BM(13), _BM(22),		/* OLO10, HH22 */
206	_BM(10), _BM(22),		/* HM10, LM22 */
207	_BM(22), _BM(10), _BM(22),	/* PC_HH22, PC_HM10, PC_LM22 */
208	_BM(16), _BM(19),		/* WDISP16, WDISP19 */
209	-1,				/* GLOB_JMP */
210	_BM(7), _BM(5), _BM(6),		/* 7, 5, 6 */
211	-1, -1,				/* DISP64, PLT64 */
212	_BM(22), _BM(13),		/* HIX22, LOX10 */
213	_BM(22), _BM(10), _BM(13),	/* H44, M44, L44 */
214	-1, -1, _BM(16),		/* REGISTER, UA64, UA16 */
215	_BM(22), _BM(10), 0, _BM(30),	/* GD_HI22, GD_LO10, GD_ADD, GD_CALL */
216	_BM(22), _BM(10), 0,		/* LDM_HI22, LDMO10, LDM_ADD */
217	_BM(30),			/* LDM_CALL */
218	_BM(22), _BM(10), 0,		/* LDO_HIX22, LDO_LOX10, LDO_ADD */
219	_BM(22), _BM(10), 0, 0,		/* IE_HI22, IE_LO10, IE_LD, IE_LDX */
220	0,				/* IE_ADD */
221	_BM(22), _BM(13),		/* LE_HIX22, LE_LOX10 */
222	_BM(32), -1,			/* DTPMOD32, DTPMOD64 */
223	_BM(32), -1,			/* DTPOFF32, DTPOFF64 */
224	_BM(32), -1			/* TPOFF32, TPOFF64 */
225#undef _BM
226};
227#define	RELOC_VALUE_BITMASK(t)	(reloc_target_bitmask[t])
228
229#undef flush
230#define	flush(va, offs)							\
231	__asm __volatile("flush %0 + %1" : : "r" (va), "I" (offs));
232
233static int reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela,
234    SymCache *cache, int flags, RtldLockState *lockstate);
235static void install_plt(Elf_Word *pltgot, Elf_Addr proc);
236
237extern char _rtld_bind_start_0[];
238extern char _rtld_bind_start_1[];
239
240int
241do_copy_relocations(Obj_Entry *dstobj)
242{
243	const Elf_Rela *relalim;
244	const Elf_Rela *rela;
245	const Elf_Sym *dstsym;
246	const Elf_Sym *srcsym;
247	void *dstaddr;
248	const void *srcaddr;
249	const Obj_Entry *srcobj, *defobj;
250	SymLook req;
251	const char *name;
252	size_t size;
253	int res;
254
255	assert(dstobj->mainprog);   /* COPY relocations are invalid elsewhere */
256
257	relalim = (const Elf_Rela *)((caddr_t)dstobj->rela + dstobj->relasize);
258	for (rela = dstobj->rela; rela < relalim; rela++) {
259		if (ELF_R_TYPE(rela->r_info) == R_SPARC_COPY) {
260			dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
261			dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
262			name = dstobj->strtab + dstsym->st_name;
263			size = dstsym->st_size;
264			symlook_init(&req, name);
265			req.ventry = fetch_ventry(dstobj,
266			    ELF_R_SYM(rela->r_info));
267			req.flags = SYMLOOK_EARLY;
268
269			for (srcobj = globallist_next(dstobj); srcobj != NULL;
270			    srcobj = globallist_next(srcobj)) {
271				res = symlook_obj(&req, srcobj);
272				if (res == 0) {
273					srcsym = req.sym_out;
274					defobj = req.defobj_out;
275					break;
276				}
277			}
278			if (srcobj == NULL) {
279				_rtld_error("Undefined symbol \"%s\""
280					    "referenced from COPY relocation"
281					    "in %s", name, dstobj->path);
282				return (-1);
283			}
284
285			srcaddr = (const void *)(defobj->relocbase +
286			    srcsym->st_value);
287			memcpy(dstaddr, srcaddr, size);
288		}
289	}
290
291	return (0);
292}
293
294int
295reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
296    RtldLockState *lockstate)
297{
298	const Elf_Rela *relalim;
299	const Elf_Rela *rela;
300	SymCache *cache;
301	int r = -1;
302
303	if ((flags & SYMLOOK_IFUNC) != 0)
304		/* XXX not implemented */
305		return (0);
306
307	/*
308	 * The dynamic loader may be called from a thread, we have
309	 * limited amounts of stack available so we cannot use alloca().
310	 */
311	if (obj != obj_rtld) {
312		cache = calloc(obj->dynsymcount, sizeof(SymCache));
313		/* No need to check for NULL here */
314	} else
315		cache = NULL;
316
317	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
318	for (rela = obj->rela; rela < relalim; rela++) {
319		if (reloc_nonplt_object(obj, rela, cache, flags, lockstate) < 0)
320			goto done;
321	}
322	r = 0;
323done:
324	if (cache != NULL)
325		free(cache);
326	return (r);
327}
328
329static int
330reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, SymCache *cache,
331    int flags, RtldLockState *lockstate)
332{
333	const Obj_Entry *defobj;
334	const Elf_Sym *def;
335	Elf_Addr *where;
336	Elf_Word *where32;
337	Elf_Word type;
338	Elf_Addr value;
339	Elf_Addr mask;
340
341	where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
342	where32 = (Elf_Word *)where;
343	defobj = NULL;
344	def = NULL;
345
346	type = ELF64_R_TYPE_ID(rela->r_info);
347	if (type == R_SPARC_NONE)
348		return (0);
349
350	/* We do JMP_SLOTs below. */
351	if (type == R_SPARC_JMP_SLOT)
352		return (0);
353
354	/* COPY relocs are also handled elsewhere. */
355	if (type == R_SPARC_COPY)
356		return (0);
357
358	/* Ignore ADD and CALL relocations for dynamic TLS references. */
359	if (type == R_SPARC_TLS_GD_ADD || type == R_SPARC_TLS_GD_CALL ||
360	    type == R_SPARC_TLS_LDM_ADD || type == R_SPARC_TLS_LDM_CALL ||
361	    type == R_SPARC_TLS_LDO_ADD)
362		return (0);
363
364	/*
365	 * Note: R_SPARC_TLS_TPOFF64 must be the numerically largest
366	 * relocation type.
367	 */
368	if (type >= nitems(reloc_target_bitmask)) {
369		_rtld_error("%s: Unsupported relocation type %d in non-PLT "
370		    "object\n", obj->path, type);
371		return (-1);
372	}
373
374	value = rela->r_addend;
375
376	/*
377	 * Handle relative relocs here, because we might not be able to access
378	 * globals yet.
379	 */
380	if (type == R_SPARC_RELATIVE) {
381		/* XXXX -- apparently we ignore the preexisting value. */
382		*where = (Elf_Addr)(obj->relocbase + value);
383		return (0);
384	}
385
386	/*
387	 * If we get here while relocating rtld itself, we will crash because
388	 * a non-local variable is accessed.
389	 */
390	if (RELOC_RESOLVE_SYMBOL(type)) {
391		/* Find the symbol. */
392		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
393		    flags, cache, lockstate);
394		if (def == NULL)
395			return (-1);
396
397		if (RELOC_USE_TLS_ID(type))
398			value = (Elf_Addr)defobj->tlsindex;
399		else if (RELOC_USE_TLS_DOFF(type))
400			value += (Elf_Addr)def->st_value;
401		else if (RELOC_USE_TLS_OFF(type)) {
402			/*
403			 * We lazily allocate offsets for static TLS as we
404			 * see the first relocation that references the TLS
405			 * block.  This allows us to support (small amounts
406			 * of) static TLS in dynamically loaded modules.  If
407			 * we run out of space, we generate an error.
408			 */
409			if (!defobj->tls_done &&
410			    !allocate_tls_offset((Obj_Entry*)defobj)) {
411				_rtld_error("%s: No space available for "
412				    "static Thread Local Storage", obj->path);
413				return (-1);
414			}
415			value += (Elf_Addr)(def->st_value -
416			    defobj->tlsoffset);
417		} else {
418			/* Add in the symbol's absolute address. */
419			value += (Elf_Addr)(def->st_value +
420			    defobj->relocbase);
421		}
422	}
423
424	if (type == R_SPARC_OLO10)
425		value = (value & 0x3ff) + ELF64_R_TYPE_DATA(rela->r_info);
426
427	if (type == R_SPARC_HIX22 || type == R_SPARC_TLS_LE_HIX22)
428		value ^= 0xffffffffffffffff;
429
430	if (RELOC_PC_RELATIVE(type))
431		value -= (Elf_Addr)where;
432
433	if (RELOC_BASE_RELATIVE(type)) {
434		/*
435		 * Note that even though sparcs use `Elf_rela' exclusively
436		 * we still need the implicit memory addend in relocations
437		 * referring to GOT entries.  Undoubtedly, someone f*cked
438		 * this up in the distant past, and now we're stuck with
439		 * it in the name of compatibility for all eternity ...
440		 *
441		 * In any case, the implicit and explicit should be mutually
442		 * exclusive.  We provide a check for that here.
443		 */
444		/* XXXX -- apparently we ignore the preexisting value */
445		value += (Elf_Addr)(obj->relocbase);
446	}
447
448	mask = RELOC_VALUE_BITMASK(type);
449	value >>= RELOC_VALUE_RIGHTSHIFT(type);
450	value &= mask;
451
452	if (type == R_SPARC_LOX10 || type == R_SPARC_TLS_LE_LOX10)
453		value |= 0x1c00;
454
455	if (RELOC_UNALIGNED(type)) {
456		/* Handle unaligned relocations. */
457		Elf_Addr tmp;
458		char *ptr;
459		int size;
460		int i;
461
462		size = RELOC_TARGET_SIZE(type) / 8;
463		ptr = (char *)where;
464		tmp = 0;
465
466		/* Read it in one byte at a time. */
467		for (i = 0; i < size; i++)
468			tmp = (tmp << 8) | ptr[i];
469
470		tmp &= ~mask;
471		tmp |= value;
472
473		/* Write it back out. */
474		for (i = 0; i < size; i++)
475			ptr[i] = ((tmp >> ((size - i - 1) * 8)) & 0xff);
476	} else if (RELOC_TARGET_SIZE(type) > 32) {
477		*where &= ~mask;
478		*where |= value;
479	} else {
480		*where32 &= ~mask;
481		*where32 |= value;
482	}
483
484	return (0);
485}
486
487int
488reloc_plt(Obj_Entry *obj)
489{
490#if 0
491	const Obj_Entry *defobj;
492	const Elf_Rela *relalim;
493	const Elf_Rela *rela;
494	const Elf_Sym *def;
495	Elf_Addr *where;
496	Elf_Addr value;
497
498	relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
499	for (rela = obj->pltrela; rela < relalim; rela++) {
500		if (rela->r_addend == 0)
501			continue;
502		assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT);
503		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
504		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
505		    SYMLOOK_IN_PLT, NULL, lockstate);
506		value = (Elf_Addr)(defobj->relocbase + def->st_value);
507		*where = value;
508	}
509#endif
510	return (0);
511}
512
513/*
514 * Instruction templates:
515 */
516#define	BAA	0x10400000	/*	ba,a	%xcc, 0 */
517#define	SETHI	0x03000000	/*	sethi	%hi(0), %g1 */
518#define	JMP	0x81c06000	/*	jmpl	%g1+%lo(0), %g0 */
519#define	NOP	0x01000000	/*	sethi	%hi(0), %g0 */
520#define	OR	0x82806000	/*	or	%g1, 0, %g1 */
521#define	XOR	0x82c06000	/*	xor	%g1, 0, %g1 */
522#define	MOV71	0x8283a000	/*	or	%o7, 0, %g1 */
523#define	MOV17	0x9c806000	/*	or	%g1, 0, %o7 */
524#define	CALL	0x40000000	/*	call	0 */
525#define	SLLX	0x8b407000	/*	sllx	%g1, 0, %g1 */
526#define	SETHIG5	0x0b000000	/*	sethi	%hi(0), %g5 */
527#define	ORG5	0x82804005	/*	or	%g1, %g5, %g1 */
528
529/* %hi(v) with variable shift */
530#define	HIVAL(v, s)	(((v) >> (s)) &  0x003fffff)
531#define	LOVAL(v)	((v) & 0x000003ff)
532
533int
534reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
535{
536	const Obj_Entry *defobj;
537	const Elf_Rela *relalim;
538	const Elf_Rela *rela;
539	const Elf_Sym *def;
540	Elf_Addr *where;
541	Elf_Addr target;
542
543	relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
544	for (rela = obj->pltrela; rela < relalim; rela++) {
545		assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT);
546		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
547		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
548		    SYMLOOK_IN_PLT | flags, NULL, lockstate);
549		if (def == NULL)
550			return -1;
551		target = (Elf_Addr)(defobj->relocbase + def->st_value);
552		reloc_jmpslot(where, target, defobj, obj, (Elf_Rel *)rela);
553	}
554	obj->jmpslots_done = true;
555	return (0);
556}
557
558int
559reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
560{
561
562	/* XXX not implemented */
563	return (0);
564}
565
566int
567reloc_gnu_ifunc(Obj_Entry *obj, int flags,
568    struct Struct_RtldLockState *lockstate)
569{
570
571	/* XXX not implemented */
572	return (0);
573}
574
575Elf_Addr
576reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj,
577    const Obj_Entry *refobj, const Elf_Rel *rel)
578{
579	const Elf_Rela *rela = (const Elf_Rela *)rel;
580	Elf_Addr offset;
581	Elf_Word *where;
582
583	if (rela - refobj->pltrela < 32764) {
584		/*
585		 * At the PLT entry pointed at by `where', we now construct
586		 * a direct transfer to the now fully resolved function
587		 * address.
588		 *
589		 * A PLT entry is supposed to start by looking like this:
590		 *
591		 *	sethi	(. - .PLT0), %g1
592		 *	ba,a	%xcc, .PLT1
593		 *	nop
594		 *	nop
595		 *	nop
596		 *	nop
597		 *	nop
598		 *	nop
599		 *
600		 * When we replace these entries we start from the second
601		 * entry and do it in reverse order so the last thing we
602		 * do is replace the branch.  That allows us to change this
603		 * atomically.
604		 *
605		 * We now need to find out how far we need to jump.  We
606		 * have a choice of several different relocation techniques
607		 * which are increasingly expensive.
608		 */
609		where = (Elf_Word *)wherep;
610		offset = ((Elf_Addr)where) - target;
611		if (offset <= (1L<<20) && offset >= -(1L<<20)) {
612			/*
613			 * We're within 1MB -- we can use a direct branch
614			 * instruction.
615			 *
616			 * We can generate this pattern:
617			 *
618			 *	sethi	%hi(. - .PLT0), %g1
619			 *	ba,a	%xcc, addr
620			 *	nop
621			 *	nop
622			 *	nop
623			 *	nop
624			 *	nop
625			 *	nop
626			 *
627			 */
628			where[1] = BAA | ((offset >> 2) &0x3fffff);
629			flush(where, 4);
630		} else if (target >= 0 && target < (1L<<32)) {
631			/*
632			 * We're within 32-bits of address zero.
633			 *
634			 * The resulting code in the jump slot is:
635			 *
636			 *	sethi	%hi(. - .PLT0), %g1
637			 *	sethi	%hi(addr), %g1
638			 *	jmp	%g1+%lo(addr)
639			 *	nop
640			 *	nop
641			 *	nop
642			 *	nop
643			 *	nop
644			 *
645			 */
646			where[2] = JMP   | LOVAL(target);
647			flush(where, 8);
648			where[1] = SETHI | HIVAL(target, 10);
649			flush(where, 4);
650		} else if (target <= 0 && target > -(1L<<32)) {
651			/*
652			 * We're within 32-bits of address -1.
653			 *
654			 * The resulting code in the jump slot is:
655			 *
656			 *	sethi	%hi(. - .PLT0), %g1
657			 *	sethi	%hix(addr), %g1
658			 *	xor	%g1, %lox(addr), %g1
659			 *	jmp	%g1
660			 *	nop
661			 *	nop
662			 *	nop
663			 *	nop
664			 *
665			 */
666			where[3] = JMP;
667			flush(where, 12);
668			where[2] = XOR | ((~target) & 0x00001fff);
669			flush(where, 8);
670			where[1] = SETHI | HIVAL(~target, 10);
671			flush(where, 4);
672		} else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) {
673			/*
674			 * We're within 32-bits -- we can use a direct call
675			 * insn
676			 *
677			 * The resulting code in the jump slot is:
678			 *
679			 *	sethi	%hi(. - .PLT0), %g1
680			 *	mov	%o7, %g1
681			 *	call	(.+offset)
682			 *	 mov	%g1, %o7
683			 *	nop
684			 *	nop
685			 *	nop
686			 *	nop
687			 *
688			 */
689			where[3] = MOV17;
690			flush(where, 12);
691			where[2] = CALL	  | ((offset >> 4) & 0x3fffffff);
692			flush(where, 8);
693			where[1] = MOV71;
694			flush(where, 4);
695		} else if (offset >= 0 && offset < (1L<<44)) {
696			/*
697			 * We're within 44 bits.  We can generate this
698			 * pattern:
699			 *
700			 * The resulting code in the jump slot is:
701			 *
702			 *	sethi	%hi(. - .PLT0), %g1
703			 *	sethi	%h44(addr), %g1
704			 *	or	%g1, %m44(addr), %g1
705			 *	sllx	%g1, 12, %g1
706			 *	jmp	%g1+%l44(addr)
707			 *	nop
708			 *	nop
709			 *	nop
710			 *
711			 */
712			where[4] = JMP   | LOVAL(offset);
713			flush(where, 16);
714			where[3] = SLLX  | 12;
715			flush(where, 12);
716			where[2] = OR    | (((offset) >> 12) & 0x00001fff);
717			flush(where, 8);
718			where[1] = SETHI | HIVAL(offset, 22);
719			flush(where, 4);
720		} else if (offset < 0 && offset > -(1L<<44)) {
721			/*
722			 * We're within 44 bits.  We can generate this
723			 * pattern:
724			 *
725			 * The resulting code in the jump slot is:
726			 *
727			 *	sethi	%hi(. - .PLT0), %g1
728			 *	sethi	%h44(-addr), %g1
729			 *	xor	%g1, %m44(-addr), %g1
730			 *	sllx	%g1, 12, %g1
731			 *	jmp	%g1+%l44(addr)
732			 *	nop
733			 *	nop
734			 *	nop
735			 *
736			 */
737			where[4] = JMP   | LOVAL(offset);
738			flush(where, 16);
739			where[3] = SLLX  | 12;
740			flush(where, 12);
741			where[2] = XOR   | (((~offset) >> 12) & 0x00001fff);
742			flush(where, 8);
743			where[1] = SETHI | HIVAL(~offset, 22);
744			flush(where, 4);
745		} else {
746			/*
747			 * We need to load all 64-bits
748			 *
749			 * The resulting code in the jump slot is:
750			 *
751			 *	sethi	%hi(. - .PLT0), %g1
752			 *	sethi	%hh(addr), %g1
753			 *	sethi	%lm(addr), %g5
754			 *	or	%g1, %hm(addr), %g1
755			 *	sllx	%g1, 32, %g1
756			 *	or	%g1, %g5, %g1
757			 *	jmp	%g1+%lo(addr)
758			 *	nop
759			 *
760			 */
761			where[6] = JMP     | LOVAL(target);
762			flush(where, 24);
763			where[5] = ORG5;
764			flush(where, 20);
765			where[4] = SLLX    | 32;
766			flush(where, 16);
767			where[3] = OR      | LOVAL((target) >> 32);
768			flush(where, 12);
769			where[2] = SETHIG5 | HIVAL(target, 10);
770			flush(where, 8);
771			where[1] = SETHI   | HIVAL(target, 42);
772			flush(where, 4);
773		}
774	} else {
775		/*
776		 * This is a high PLT slot; the relocation offset specifies a
777		 * pointer that needs to be frobbed; no actual code needs to
778		 * be modified.  The pointer to be calculated needs the addend
779		 * added and the reference object relocation base subtraced.
780		 */
781		*wherep = target + rela->r_addend -
782		    (Elf_Addr)refobj->relocbase;
783	}
784
785	return (target);
786}
787
788void
789ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
790{
791
792}
793
794extern void __sparc_utrap_setup(void);
795
796void
797pre_init(void)
798{
799
800	__sparc_utrap_setup();
801}
802
803/*
804 * Install rtld function call into this PLT slot.
805 */
806#define	SAVE		0x9de3bf50
807#define	SETHI_l0	0x21000000
808#define	SETHI_l1	0x23000000
809#define	OR_l0_l0	0xa0142000
810#define	SLLX_l0_32_l0	0xa12c3020
811#define	OR_l0_l1_l0	0xa0140011
812#define	JMPL_l0_o1	0x93c42000
813#define	MOV_g1_o0	0x90100001
814
815void
816init_pltgot(Obj_Entry *obj)
817{
818	Elf_Word *entry;
819
820	if (obj->pltgot != NULL) {
821		entry = (Elf_Word *)obj->pltgot;
822		install_plt(&entry[0], (Elf_Addr)_rtld_bind_start_0);
823		install_plt(&entry[8], (Elf_Addr)_rtld_bind_start_1);
824		obj->pltgot[8] = (Elf_Addr)obj;
825	}
826}
827
828static void
829install_plt(Elf_Word *pltgot, Elf_Addr proc)
830{
831
832	pltgot[0] = SAVE;
833	flush(pltgot, 0);
834	pltgot[1] = SETHI_l0 | HIVAL(proc, 42);
835	flush(pltgot, 4);
836	pltgot[2] = SETHI_l1 | HIVAL(proc, 10);
837	flush(pltgot, 8);
838	pltgot[3] = OR_l0_l0 | LOVAL((proc) >> 32);
839	flush(pltgot, 12);
840	pltgot[4] = SLLX_l0_32_l0;
841	flush(pltgot, 16);
842	pltgot[5] = OR_l0_l1_l0;
843	flush(pltgot, 20);
844	pltgot[6] = JMPL_l0_o1 | LOVAL(proc);
845	flush(pltgot, 24);
846	pltgot[7] = MOV_g1_o0;
847	flush(pltgot, 28);
848}
849
850void
851allocate_initial_tls(Obj_Entry *objs)
852{
853	Elf_Addr* tpval;
854
855	/*
856	 * Fix the size of the static TLS block by using the maximum offset
857	 * allocated so far and adding a bit for dynamic modules to use.
858	 */
859	tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
860	tpval = allocate_tls(objs, NULL, 3 * sizeof(Elf_Addr),
861	     sizeof(Elf_Addr));
862	__asm __volatile("mov %0, %%g7" : : "r" (tpval));
863}
864
865void *__tls_get_addr(tls_index *ti)
866{
867	register Elf_Addr** tp __asm__("%g7");
868
869	return (tls_get_addr_common(tp, ti->ti_module, ti->ti_offset));
870}
871