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