xref: /titanic_52/usr/src/uts/sparc/krtld/doreloc.c (revision ac88567a7a5bb7f01cf22cf366bc9d6203e24d7a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #if	defined(_KERNEL)
30 #include	<sys/types.h>
31 #include	"krtld/reloc.h"
32 #else
33 #define	ELF_TARGET_SPARC
34 #if defined(DO_RELOC_LIBLD)
35 #undef DO_RELOC_LIBLD
36 #define	DO_RELOC_LIBLD_SPARC
37 #endif
38 #include	<stdio.h>
39 #include	"sgs.h"
40 #include	"machdep.h"
41 #include	"libld.h"
42 #include	"reloc.h"
43 #include	"conv.h"
44 #include	"msg.h"
45 #endif
46 
47 /*
48  * We need to build this code differently when it is used for
49  * cross linking:
50  *	- Data alignment requirements can differ from those
51  *		of the running system, so we can't access data
52  *		in units larger than a byte
53  *	- We have to include code to do byte swapping when the
54  *		target and linker host use different byte ordering,
55  *		but such code is a waste when running natively.
56  */
57 #if !defined(DO_RELOC_LIBLD) || defined(__sparc)
58 #define	DORELOC_NATIVE
59 #endif
60 
61 /*
62  * This table represents the current relocations that do_reloc() is able to
63  * process.  The relocations below that are marked SPECIAL are relocations that
64  * take special processing and shouldn't actually ever be passed to do_reloc().
65  */
66 const Rel_entry reloc_table[R_SPARC_NUM] = {
67 /* R_SPARC_NONE */	{0x0, FLG_RE_NOTREL, 0, 0, 0},
68 /* R_SPARC_8 */		{0x0, FLG_RE_VERIFY, 1, 0, 0},
69 /* R_SPARC_16 */	{0x0, FLG_RE_VERIFY, 2, 0, 0},
70 /* R_SPARC_32 */	{0x0, FLG_RE_VERIFY, 4, 0, 0},
71 /* R_SPARC_DISP8 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
72 				1, 0, 0},
73 /* R_SPARC_DISP16 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
74 				2, 0, 0},
75 /* R_SPARC_DISP32 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
76 				4, 0, 0},
77 /* R_SPARC_WDISP30 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
78 				4, 2, 30},
79 /* R_SPARC_WDISP22 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
80 				4, 2, 22},
81 #if	defined(_ELF64)
82 /* R_SPARC_HI22 */	{0x0, FLG_RE_VERIFY, 4, 10, 22},
83 #else
84 /* R_SPARC_HI22 */	{0x0, FLG_RE_NOTREL, 4, 10, 22},
85 #endif
86 /* R_SPARC_22 */	{0x0, FLG_RE_VERIFY, 4, 0, 22},
87 /* R_SPARC_13 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 13},
88 /* R_SPARC_LO10 */	{0x3ff, FLG_RE_SIGN, 4, 0, 13},
89 /* R_SPARC_GOT10 */	{0x3ff, FLG_RE_GOTADD | FLG_RE_SIGN, 4, 0, 13},
90 /* R_SPARC_GOT13 */	{0x0, FLG_RE_GOTADD | FLG_RE_VERIFY | FLG_RE_SIGN,
91 				4, 0, 13},
92 /* R_SPARC_GOT22 */	{0x0, FLG_RE_GOTADD, 4, 10, 22},
93 /* R_SPARC_PC10 */	{0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_LOCLBND,
94 				4, 0, 13},
95 /* R_SPARC_PC22 */	{0x0, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_VERIFY |
96 				FLG_RE_LOCLBND, 4, 10, 22},
97 /* R_SPARC_WPLT30 */	{0x0, FLG_RE_PCREL | FLG_RE_PLTREL |
98 				FLG_RE_VERIFY | FLG_RE_SIGN,
99 				4, 2, 30},
100 /* R_SPARC_COPY */	{0x0, 0, 0, 0, 0},		/* SPECIAL */
101 #if	defined(_ELF64)
102 /* R_SPARC_GLOB_DAT */	{0x0, FLG_RE_NOTREL, 8, 0, 0},
103 #else
104 /* R_SPARC_GLOB_DAT */	{0x0, FLG_RE_NOTREL, 4, 0, 0},
105 #endif
106 /* R_SPARC_JMP_SLOT */	{0x0, 0, 0, 0, 0},		/* SPECIAL */
107 #if	defined(_ELF64)
108 /* R_SPARC_RELATIVE */	{0x0, FLG_RE_NOTREL, 8, 0, 0},
109 #else
110 /* R_SPARC_RELATIVE */	{0x0, FLG_RE_NOTREL, 4, 0, 0},
111 #endif
112 /* R_SPARC_UA32 */	{0x0, FLG_RE_UNALIGN, 4, 0, 0},
113 /* R_SPARC_PLT32 */	{0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
114 				FLG_RE_ADDRELATIVE, 4, 0, 0},
115 /* R_SPARC_HIPLT22 */	{0x0, FLG_RE_PLTREL, 4, 10, 22},
116 /* R_SPARC_LOPLT10 */	{0x3ff, FLG_RE_PLTREL, 4, 0, 13},
117 /* R_SPARC_PCPLT32 */	{0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
118 				4, 0, 0},
119 /* R_SPARC_PCPLT22 */	{0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
120 				4, 10, 22},
121 /* R_SPARC_PCPLT10 */	{0x3ff, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
122 				4, 0, 13},
123 /* R_SPARC_10 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 10},
124 /* R_SPARC_11 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 11},
125 /* R_SPARC_64 */	{0x0, FLG_RE_VERIFY, 8, 0, 0},		/* V9 */
126 /* R_SPARC_OLO10 */	{0x3ff, FLG_RE_EXTOFFSET | FLG_RE_SIGN,
127 				4, 0, 13},			/* V9 */
128 /* R_SPARC_HH22 */	{0x0, FLG_RE_VERIFY, 4, 42, 22},	/* V9 */
129 /* R_SPARC_HM10 */	{0x3ff, FLG_RE_SIGN, 4, 32, 13},	/* V9 */
130 /* R_SPARC_LM22 */	{0x0, FLG_RE_NOTREL, 4, 10, 22},	/* V9 */
131 /* R_SPARC_PC_HH22 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY,
132 				4, 42, 22},			/* V9 */
133 /* R_SPARC_PC_HM10 */	{0x3ff, FLG_RE_PCREL | FLG_RE_SIGN,
134 				4, 32, 13},			/* V9 */
135 /* R_SPARC_PC_LM22 */	{0x0, FLG_RE_PCREL,
136 				4, 10, 22},			/* V9 */
137 /* R_SPARC_WDISP16 */	{0x0, FLG_RE_PCREL | FLG_RE_WDISP16 |
138 				FLG_RE_VERIFY | FLG_RE_SIGN,
139 				4, 2, 16},
140 /* R_SPARC_WDISP19 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
141 				4, 2, 19},
142 /* R_SPARC_GLOB_JMP */	{0x0, 0, 0, 0, 0},	/* V9 - not implemented */
143 						/* removed from v9 ABI */
144 /* R_SPARC_7 */		{0x0, FLG_RE_NOTREL, 4, 0, 7},
145 /* R_SPARC_5 */		{0x0, FLG_RE_NOTREL, 4, 0, 5},
146 /* R_SPARC_6 */		{0x0, FLG_RE_NOTREL, 4, 0, 6},
147 /* R_SPARC_DISP64 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
148 				8, 0, 0},
149 /* R_SPARC_PLT64 */	{0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
150 				FLG_RE_ADDRELATIVE, 8, 0, 0},
151 /* R_SPARC_HIX22 */	{(Xword)(-1LL), FLG_RE_VERIFY,
152 				4, 10, 22},			/* V9 - HaL */
153 /* R_SPARC_LOX10 */	{0x3ff, FLG_RE_SIGN, 4, 0, 13},		/* V9 - HaL */
154 /* R_SPARC_H44 */	{0x0, FLG_RE_VERIFY, 4, 22, 22},	/* V9 */
155 /* R_SPARC_M44 */	{0x3ff, FLG_RE_NOTREL, 4, 12, 10},	/* V9 */
156 /* R_SPARC_L44 */	{0xfff, FLG_RE_NOTREL, 4, 0, 13},	/* V9 */
157 /* R_SPARC_REGISTER */	{0x0, FLG_RE_REGISTER, 0, 0, 0},	/* SPECIAL */
158 /* R_SPARC_UA64 */	{0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
159 				8, 0, 0},			/* V9 */
160 /* R_SPARC_UA16 */	{0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
161 				2, 0, 0},
162 /* R_SPARC_TLS_GD_HI22 */   {0x0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 10, 22},
163 /* R_SPARC_TLS_GD_LO10 */   {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSGD |
164 				FLG_RE_SIGN, 4, 0, 13},
165 /* R_SPARC_TLS_GD_ADD */    {0x0, FLG_RE_TLSGD, 0, 0, 0},
166 /* R_SPARC_TLS_GD_CALL */   {0x0, FLG_RE_TLSGD, 0, 0, 0},
167 /* R_SPARC_TLS_LDM_HI22 */  {0x0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 10, 22},
168 /* R_SPARC_TLS_LDM_LO10 */  {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSLD |
169 				FLG_RE_SIGN, 4, 0, 13},
170 /* R_SPARC_TLS_LDM_ADD */   {0x0, FLG_RE_TLSLD, 0, 0, 0},
171 /* R_SPARC_TLS_LDM_CALL */  {0x0, FLG_RE_TLSLD, 0, 0, 0},
172 /* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSLD, 4, 10, 22},
173 /* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLD, 4, 0, 13},
174 /* R_SPARC_TLS_LDO_ADD */   {0x0, FLG_RE_TLSLD, 0, 0, 0},
175 /* R_SPARC_TLS_IE_HI22 */   {0x0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 10, 22},
176 /* R_SPARC_TLS_IE_LO10 */   {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSIE |
177 				FLG_RE_SIGN, 4, 0, 13},
178 /* R_SPARC_TLS_IE_LD */	    {0x0, FLG_RE_TLSIE, 0, 0, 0},
179 /* R_SPARC_TLS_IE_LDX */    {0x0, FLG_RE_TLSIE, 0, 0, 0},
180 /* R_SPARC_TLS_IE_ADD */    {0x0, FLG_RE_TLSIE, 0, 0, 0},
181 /* R_SPARC_TLS_LE_HIX22 */  {(Xword)(-1LL),
182 				FLG_RE_VERIFY | FLG_RE_TLSLE, 4, 10, 22},
183 /* R_SPARC_TLS_LE_LOX10 */  {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLE, 4, 0, 13},
184 /* R_SPARC_TLS_DTPMOD32 */  {0x0, FLG_RE_NOTREL, 4, 0, 0},
185 /* R_SPARC_TLS_DTPMOD64 */  {0x0, FLG_RE_NOTREL, 8, 0, 0},
186 /* R_SPARC_TLS_DTPOFF32 */  {0x0, FLG_RE_NOTREL, 4, 0, 0},
187 /* R_SPARC_TLS_DTPOFF64 */  {0x0, FLG_RE_NOTREL, 8, 0, 0},
188 /* R_SPARC_TLS_TPOFF32 */   {0x0, FLG_RE_NOTREL, 4, 0, 0},
189 /* R_SPARC_TLS_TPOFF64 */   {0x0, FLG_RE_NOTREL, 8, 0, 0},
190 /* R_SPARC_GOTDATA_HIX22 */	{0, FLG_RE_SIGN | FLG_RE_GOTREL |
191 					FLG_RE_VERIFY, 4, 10, 22},
192 /* R_SPARC_GOTDATA_LOX10 */	{ 0x3ff, FLG_RE_GOTREL | FLG_RE_SIGN, 4, 0, 13},
193 /* R_SPARC_GOTDATA_OP_HIX22 */	{ 0x0, FLG_RE_GOTOPINS | FLG_RE_GOTADD,
194 					4, 10, 22},
195 /* R_SPARC_GOTDATA_OP_LOX10 */	{ 0x3ff, FLG_RE_SIGN | FLG_RE_GOTOPINS |
196 					FLG_RE_GOTADD, 4, 0, 13},
197 /* R_SPARC_GOTDATA_OP */	{ 0x0, FLG_RE_GOTOPINS, 0, 0, 0},
198 /* R_SPARC_H34 */	{0x0, FLG_RE_VERIFY, 4, 12, 22},	/* V9 */
199 /* R_SPARC_SIZE32 */	{0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0},
200 /* R_SPARC_SIZE64 */	{0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 8, 0, 0},
201 };
202 
203 
204 /*
205  * Write a single relocated value to its reference location.
206  * We assume we wish to add the relocation amount, value, to the
207  * value of the address already present in the instruction.
208  *
209  * NAME			 VALUE	FIELD		CALCULATION
210  *
211  * R_SPARC_NONE		     0	none		none
212  * R_SPARC_8		     1	V-byte8		S + A
213  * R_SPARC_16		     2	V-half16	S + A
214  * R_SPARC_32		     3	V-word32	S + A
215  * R_SPARC_DISP8	     4	V-byte8		S + A - P
216  * R_SPARC_DISP16	     5	V-half16	S + A - P
217  * R_SPARC_DISP32	     6	V-word32	S + A - P
218  * R_SPARC_WDISP30	     7	V-disp30	(S + A - P) >> 2
219  * R_SPARC_WDISP22	     8	V-disp22	(S + A - P) >> 2
220  * R_SPARC_HI22		     9	T-imm22		(S + A) >> 10
221  * R_SPARC_22		    10	V-imm22		S + A
222  * R_SPARC_13		    11	V-simm13	S + A
223  * R_SPARC_LO10		    12	T-simm13	(S + A) & 0x3ff
224  * R_SPARC_GOT10	    13	T-simm13	G & 0x3ff
225  * R_SPARC_GOT13	    14	V-simm13	G
226  * R_SPARC_GOT22	    15	T-imm22		G >> 10
227  * R_SPARC_PC10		    16	T-simm13	(S + A - P) & 0x3ff
228  * R_SPARC_PC22		    17	V-disp22	(S + A - P) >> 10
229  * R_SPARC_WPLT30	    18	V-disp30	(L + A - P) >> 2
230  * R_SPARC_COPY		    19	none		none
231  * R_SPARC_GLOB_DAT	    20	V-word32	S + A
232  * R_SPARC_JMP_SLOT	    21	V-plt22		S + A
233  * R_SPARC_RELATIVE	    22	V-word32	S + A
234  * R_SPARC_UA32		    23	V-word32	S + A
235  * R_SPARC_PLT32	    24	V-word32        L + A
236  * R_SPARC_HIPLT22	    25	T-imm22         (L + A) >> 10
237  * R_SPARC_LOPLT10	    26	T-simm13        (L + A) & 0x3ff
238  * R_SPARC_PCPLT32	    27	V-word32        L + A - P
239  * R_SPARC_PCPLT22	    28	V-disp22        (L + A - P) >> 10
240  * R_SPARC_PCPLT10	    29	V-simm13        (L + A - P) & 0x3ff
241  * R_SPARC_10		    30	V-simm10	S + A
242  * R_SPARC_11		    31	V-simm11	S + A
243  * R_SPARC_64		    32	V-xword64	S + A
244  * R_SPARC_OLO10	    33	V-simm13	((S + A) & 0x3ff) + O
245  * R_SPARC_HH22		    34	V-imm22		(S + A) >> 42
246  * R_SPARC_HM10		    35	T-simm13	((S + A) >> 32) & 0x3ff
247  * R_SPARC_LM22		    36	T-imm22		(S + A) >> 10
248  * R_SPARC_PC_HH22	    37	V-imm22		(S + A - P) >> 42
249  * R_SPARC_PC_HM10	    38	T-simm13	((S + A - P) >> 32) & 0x3ff
250  * R_SPARC_PC_LM22	    39	T-imm22		(S + A - P) >> 10
251  * R_SPARC_WDISP16	    40	V-d2/disp14	(S + A - P) >> 2
252  * R_SPARC_WDISP19	    41	V-disp19	(S + A - P) >> 2
253  * R_SPARC_GLOB_JMP	    42	V-xword64	S + A
254  * R_SPARC_7		    43	V-imm7		S + A
255  * R_SPARC_5		    44	V-imm5		S + A
256  * R_SPARC_6		    45	V-imm6		S + A
257  * R_SPARC_DISP64	    46	V-xword64	S + A - P
258  * R_SPARC_PLT64	    47	V-xword64	L + A
259  * R_SPARC_HIX22	    48	V-imm22		((S + A) ^
260  *						    0xffffffffffffffff) >> 10
261  * R_SPARC_LOX10	    49	T-simm13	((S + A) & 0x3ff) | 0x1c00
262  * R_SPARC_H44		    50	V-imm22		(S + A) >> 22
263  * R_SPARC_M44		    51	T-imm10		((S + A) >> 12) & 0x3ff
264  * R_SPARC_L44		    52	T-imm13		(S + A) & 0xfff
265  * R_SPARC_REGISTER	    53	V-xword64	S + A
266  * R_SPARC_UA64		    54	V-xword64	S + A
267  * R_SPARC_UA16		    55	V-half16	S + A
268  * R_SPARC_TLS_GD_HI22	    56	T-simm22	@dtlndx(S + A) >> 10
269  * R_SPARC_TLS_GD_LO10	    57	T-simm13	@dtlndx(S + A) & 0x3ff
270  * R_SPARC_TLS_GD_ADD	    58	none		SPECIAL
271  * R_SPARC_TLS_GD_CALL	    59	V-disp30	SPECIAL
272  * R_SPARC_TLS_LDM_HI22	    60	T-simm22	@tmndx(S + A) >> 10
273  * R_SPARC_TLS_LDM_LO10	    61	T-simm13	@tmndx(S + A) & 0x3ff
274  * R_SPARC_TLS_LDM_ADD	    62	none		SPECIAL
275  * R_SPARC_TLS_LDM_CALL	    63	V-disp30	SPECIAL
276  * R_SPARC_TLS_LDO_HIX22    64	V-simm22	@dtpoff(S + A) >> 10
277  * R_SPARC_TLS_LDO_LOX10    65	T-simm13	@dtpoff(S + A) & 0x3ff
278  * R_SPARC_TLS_LDO_ADD	    66	none		SPECIAL
279  * R_SPARC_TLS_IE_HI22	    67	T-simm22	@got(@tpoff(S + A)) >> 10
280  * R_SPARC_TLS_IE_LO10	    68	T-simm13	@got(@tpoff(S + A)) & 0x3ff
281  * R_SPARC_TLS_IE_LD	    69	none		SPECIAL
282  * R_SPARC_TLS_IE_LDX	    70	none		SPECIAL
283  * R_SPARC_TLS_IE_ADD	    71	none		SPECIAL
284  * R_SPARC_TLS_LE_HIX22	    72	V-simm22	(@tpoff(S + A) ^
285  *						    0xffffffff) >> 10
286  * R_SPARC_TLS_LE_LOX10	    73	T-simm13	(@tpoff(S + A) & 0x3ff) | 0x1c00
287  * R_SPARC_TLS_DTPMOD32	    74	V-word32	@dtmod(S + A)
288  * R_SPARC_TLS_DTPMOD64	    75	V-word64	@dtmod(S + A)
289  * R_SPARC_TLS_DTPOFF32	    76	V-word32	@dtpoff(S + A)
290  * R_SPARC_TLS_DTPOFF64	    77	V-word64	@dtpoff(S + A)
291  * R_SPARC_TLS_TPOFF32	    78	V-word32	@tpoff(S + A)
292  * R_SPARC_TLS_TPOFF64	    79	V-word64	@tpoff(S + A)
293  * R_SPARC_GOTDATA_HIX22    80	V-imm22		((S + A - GOT) >> 10) ^
294  *						  ((S + A - GOT) >> 31)
295  * R_SPARC_GOTDATA_LOX10    81	T-simm13	((S + A - GOT) & 0x3ff) |
296  *						  (((S + A - GOT) >> 31) &
297  *						  0x1c00)
298  * R_SPARC_GOTDATA_OP_HIX22 82	T-imm22		(G >> 10) & (G >> 31)
299  * R_SPARC_GOTDATA_OP_LOX10 83	T-simm13	(G & 0x3ff) |
300  *						  ((G >> 31) & 0x1c00)
301  * R_SPARC_GOTDATA_OP	    84  Word32		SPECIAL
302  * R_SPARC_H34		    85	V-imm22		(S + A) >> 12
303  * R_SPARC_SIZE32	    86	V-word32	Z + A
304  * R_SPARC_SIZE64	    87	V-xword64	Z + A
305  *
306  *	This is Figure 4-20: Relocation Types from the Draft Copy of
307  * the ABI, Printed on 11/29/88.
308  *
309  * NOTE1: relocations 24->45 are newly registered relocations to support
310  *	 C++ ABI & SPARC V8+ and SPARC V9 architectures (1/9/94), and
311  *	 64-bit relocations 46-55 were added for SPARC V9.
312  *
313  * NOTE2: relocations 56->79 are added to support Thread-Local storage
314  *	  as recorded in PSARC/2001/509
315  *
316  * NOTE3: The value to be passed for relocations R_SPARC_HIX22 and
317  *	  R_SPARC_TLS_HIX22 are negative values. So the upper 10 or 40 bits
318  *	  are 1. (So when the exclusive OR is applied, the upper bits
319  *	  will be 0.)
320  *
321  * Relocation calculations:
322  *
323  * The FIELD names indicate whether the relocation type checks for overflow.
324  * A calculated relocation value may be larger than the intended field, and
325  * the relocation type may verify (V) that the value fits, or truncate (T)
326  * the result.
327  *
328  * CALCULATION uses the following notation:
329  *      A       the addend used
330  *      B       the base address of the shared object in memory
331  *      G       the offset into the global offset table
332  *      L       the procedure linkage entry
333  *      P       the place of the storage unit being relocated
334  *      S       the value of the symbol
335  *	O	secondary addend (extra offset) in v9 r_info field
336  *	Z	the size of the symbol whose index resides in the relocation
337  *		entry
338  *
339  *	@dtlndx(x): Allocate two contiguous entries in the GOT table to hold
340  *	   a Tls_index structure (for passing to __tls_get_addr()). The
341  *	   instructions referencing this entry will be bound to the first
342  *	   of the two GOT entries.
343  *
344  *	@tmndx(x): Allocate two contiguous entries in the GOT table to hold
345  *	   a Tls_index structure (for passing to __tls_get_addr()). The
346  *	   ti_offset field of the Tls_index will be set to 0 (zero) and the
347  *	   ti_module will be filled in at run-time. The call to
348  *	   __tls_get_addr() will return the starting offset of the dynamic
349  *	   TLS block.
350  *
351  *	@dtpoff(x): calculate the tlsoffset relative to the TLS block.
352  *
353  *	@tpoff(x): calculate the negative tlsoffset relative to the static
354  *	   TLS block. This value can be added to the thread-pointer to
355  *	   calculate the tls address.
356  *
357  *	@dtpmod(x): calculate the module id of the object containing symbol x.
358  *
359  * The calculations in the CALCULATION column are assumed to have been performed
360  * before calling this function except for the addition of the addresses in the
361  * instructions.
362  *
363  * Upon successful completion of do_reloc() *value will be set to the
364  * 'bit-shifted' value that will be or'ed into memory.
365  */
366 #if defined(_KERNEL)
367 #define	lml	0		/* Needed by arglist of REL_ERR_* macros */
368 int
369 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
370     const char *file)
371 #elif defined(DO_RELOC_LIBLD)
372 /*ARGSUSED5*/
373 int
374 do_reloc_ld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
375     const char *file, int bswap, void *lml)
376 #else
377 int
378 do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
379     const char *file, void *lml)
380 #endif
381 {
382 	Xword	uvalue = 0;
383 	Xword	basevalue, sigbit_mask, sigfit_mask;
384 	Xword	corevalue = *value;
385 	uchar_t	bshift;
386 	int	field_size, re_flags;
387 	const	Rel_entry	*rep;
388 
389 	rep = &reloc_table[rtype];
390 	bshift = rep->re_bshift;
391 	field_size = rep->re_fsize;
392 	re_flags = rep->re_flags;
393 	sigbit_mask = S_MASK(rep->re_sigbits);
394 
395 	if ((re_flags & FLG_RE_SIGN) && sigbit_mask) {
396 		/*
397 		 * sigfit_mask takes into account that a value
398 		 * might be signed and discards the signbit for
399 		 * comparison.
400 		 */
401 		sigfit_mask = S_MASK(rep->re_sigbits - 1);
402 	} else
403 		sigfit_mask = sigbit_mask;
404 
405 	if (field_size == 0) {
406 		REL_ERR_UNIMPL(lml, file, sym, rtype);
407 		return (0);
408 	}
409 
410 	/*
411 	 * We have two ways to retrieve the base value, a general one
412 	 * that will work with data of any alignment, and another that is
413 	 * fast, but which requires the data to be aligned according to
414 	 * sparc alignment rules.
415 	 *
416 	 * For non-native linking, we always use the general path. For
417 	 * native linking, the FLG_RE_UNALIGN determines it.
418 	 */
419 #if defined(DORELOC_NATIVE)
420 	if (re_flags & FLG_RE_UNALIGN)
421 #endif
422 	{
423 		int	i;
424 		uchar_t	*dest = (uchar_t *)&basevalue;
425 
426 		basevalue = 0;
427 #if !defined(DORELOC_NATIVE)
428 		if (bswap) {
429 			int j = field_size - 1;
430 
431 			for (i = 0; i < field_size; i++, j--)
432 				dest[i] = off[j];
433 
434 		} else
435 #endif
436 		{
437 			/*
438 			 * Adjust the offset
439 			 */
440 			/* LINTED */
441 			i = (int)(sizeof (Xword) - field_size);
442 			if (i > 0)
443 				dest += i;
444 			for (i = field_size - 1; i >= 0; i--)
445 				dest[i] = off[i];
446 		}
447 	}
448 
449 	/*
450 	 * Non-native linker: We have already fetched the value above,
451 	 *	but if the relocation does not have the FLG_RE_UNALIGN
452 	 *	flag set, we still need to do the same error checking we
453 	 *	would do on a native linker.
454 	 * Native-linker: If this is an aligned relocation, we need to
455 	 *	fetch the value and also do the error checking.
456 	 *
457 	 * The FETCH macro is used to conditionalize the fetching so that
458 	 * it only happens in the native case.
459 	 */
460 #if defined(DORELOC_NATIVE)
461 #define	FETCH(_type) basevalue = (Xword)*((_type *)off);
462 #else
463 #define	FETCH(_type)
464 #endif
465 	if ((re_flags & FLG_RE_UNALIGN) == 0) {
466 		if (((field_size == 2) && ((uintptr_t)off & 0x1)) ||
467 		    ((field_size == 4) && ((uintptr_t)off & 0x3)) ||
468 		    ((field_size == 8) && ((uintptr_t)off & 0x7))) {
469 			REL_ERR_NONALIGN(lml, file, sym, rtype, (uintptr_t)off);
470 			return (0);
471 		}
472 		switch (field_size) {
473 		case 1:
474 			/* LINTED */
475 			FETCH(uchar_t);
476 			break;
477 		case 2:
478 			/* LINTED */
479 			FETCH(Half);
480 			break;
481 		case 4:
482 			/* LINTED */
483 			FETCH(Word);
484 			break;
485 		case 8:
486 			/* LINTED */
487 			FETCH(Xword);
488 			break;
489 		default:
490 			REL_ERR_UNNOBITS(lml, file, sym, rtype,
491 			    (rep->re_fsize * 8));
492 			return (0);
493 		}
494 	}
495 #undef FETCH
496 
497 	if (sigbit_mask) {
498 		/*
499 		 * The WDISP16 relocation is an unusual one in that it's bits
500 		 * are not all contiguous.  We have to selectivly pull them out.
501 		 */
502 		if (re_flags & FLG_RE_WDISP16) {
503 			uvalue = ((basevalue & 0x300000) >> 6) |
504 			    (basevalue & 0x3fff);
505 			basevalue &= ~0x303fff;
506 		} else {
507 			uvalue = sigbit_mask & basevalue;
508 			basevalue &= ~sigbit_mask;
509 		}
510 		/*
511 		 * If value is signed make sure that we signextend the uvalue.
512 		 */
513 		if (re_flags & FLG_RE_SIGN) {
514 			if (uvalue & (~sigbit_mask & sigfit_mask))
515 				uvalue |= ~sigbit_mask;
516 		}
517 	} else
518 		uvalue = basevalue;
519 
520 	if (bshift)
521 		uvalue <<= bshift;
522 
523 	uvalue += *value;
524 
525 	if (rep->re_mask &&
526 	    ((rtype == R_SPARC_HIX22) || (rtype == R_SPARC_TLS_LE_HIX22)))
527 		uvalue ^= rep->re_mask;
528 
529 	if (bshift) {
530 		/*
531 		 * This is to check that we are not attempting to
532 		 * jump to a non-4 byte aligned address.
533 		 */
534 		if ((bshift == 2) && (uvalue & 0x3)) {
535 			REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, 2, off);
536 			return (0);
537 		}
538 
539 		if (re_flags & FLG_RE_SIGN) {
540 			uvalue = (Sxword)uvalue >> bshift;
541 		} else {
542 			uvalue >>= bshift;
543 		}
544 		corevalue >>= bshift;
545 	}
546 
547 	if ((rtype == R_SPARC_GOTDATA_HIX22) ||
548 	    (rtype == R_SPARC_GOTDATA_OP_HIX22)) {
549 		uvalue ^= ((Sxword)(*value) >> 31);
550 		corevalue ^= ((Sxword)(*value) >> 31);
551 	}
552 
553 	if (rep->re_mask &&
554 	    (rtype != R_SPARC_HIX22) && (rtype != R_SPARC_TLS_LE_HIX22) &&
555 	    (rtype != R_SPARC_GOTDATA_HIX22))
556 		uvalue &= rep->re_mask;
557 
558 	if ((rtype == R_SPARC_LOX10) || (rtype == R_SPARC_TLS_LE_LOX10)) {
559 		uvalue |= 0x1c00;
560 		corevalue |= 0x1c00;
561 	}
562 
563 	if ((rtype == R_SPARC_GOTDATA_LOX10) ||
564 	    (rtype == R_SPARC_GOTDATA_OP_LOX10)) {
565 		uvalue |= ((Sxword)(*value) >> 31) & 0x1c00;
566 		corevalue |= ((Sxword)(*value) >> 31) & 0x1c00;
567 	}
568 
569 
570 	if ((re_flags & FLG_RE_VERIFY) && sigbit_mask) {
571 		if (((re_flags & FLG_RE_SIGN) &&
572 		    (S_INRANGE((Sxword)uvalue, rep->re_sigbits - 1) == 0)) ||
573 		    (!(re_flags & FLG_RE_SIGN) &&
574 		    ((sigbit_mask & uvalue) != uvalue))) {
575 			REL_ERR_NOFIT(lml, file, sym, rtype, uvalue);
576 			return (0);
577 		}
578 	}
579 
580 	if (sigbit_mask) {
581 		/*
582 		 * Again the R_SPARC_WDISP16 relocation takes special
583 		 * processing because of its non-continguous bits.
584 		 */
585 		if (re_flags & FLG_RE_WDISP16)
586 			uvalue = ((uvalue & 0xc000) << 6) |
587 			    (uvalue & 0x3fff);
588 		else
589 			uvalue &= sigbit_mask;
590 		/*
591 		 * Combine value back with original word
592 		 */
593 		uvalue |= basevalue;
594 	}
595 	*value = corevalue;
596 
597 	/*
598 	 * Now, we store uvalue back at the location given by off.
599 	 * This is similar to the fetch case above:
600 	 *	- We have general (unaligned) and fast (aligned) cases
601 	 *	- Cross linkers need to use the unaligned case even
602 	 *		when the relocation does not specify FLG_RE_UNALIGN.
603 	 *	- A cross linker that processes a relocation that does not
604 	 *		have FLG_RE_UNALIGN set has to do the same error
605 	 *		checking that a native linker would do, while avoiding
606 	 *		the aligned store (accomplished with the STORE macro).
607 	 */
608 #if defined(DORELOC_NATIVE)
609 	if (re_flags & FLG_RE_UNALIGN)
610 #endif
611 	{
612 		int	i;
613 		uchar_t	*src = (uchar_t *)&uvalue;
614 
615 #if !defined(DORELOC_NATIVE)
616 		if (bswap) {
617 			int j = field_size - 1;
618 
619 			for (i = 0; i < field_size; i++, j--)
620 				off[i] = src[j];
621 
622 		} else
623 #endif
624 		{
625 			/*
626 			 * Adjust the offset.
627 			 */
628 			/* LINTED */
629 			i = (int)(sizeof (Xword) - field_size);
630 			if (i > 0)
631 				src += i;
632 			for (i = field_size - 1; i >= 0; i--)
633 				off[i] = src[i];
634 		}
635 	}
636 
637 #if defined(DORELOC_NATIVE)
638 #define	STORE(_type) *((_type *)off) = (_type)uvalue
639 #else
640 #define	STORE(_type)
641 #endif
642 	if ((re_flags & FLG_RE_UNALIGN) == 0) {
643 		switch (rep->re_fsize) {
644 		case 1:
645 			/* LINTED */
646 			STORE(uchar_t);
647 			break;
648 		case 2:
649 			/* LINTED */
650 			STORE(Half);
651 			break;
652 		case 4:
653 			/* LINTED */
654 			STORE(Word);
655 			break;
656 		case 8:
657 			/* LINTED */
658 			STORE(Xword);
659 			break;
660 		default:
661 			/*
662 			 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
663 			 */
664 			REL_ERR_UNSUPSZ(lml, file, sym, rtype, rep->re_fsize);
665 			return (0);
666 		}
667 	}
668 #undef STORE
669 
670 	return (1);
671 }
672