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