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