xref: /illumos-gate/usr/src/uts/sparc/krtld/doreloc.c (revision bf994817)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2175521904Sraf 
227c478bd9Sstevel@tonic-gate /*
23*bf994817SAli Bahrami  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
2575521904Sraf 
267c478bd9Sstevel@tonic-gate #if	defined(_KERNEL)
277c478bd9Sstevel@tonic-gate #include	<sys/types.h>
28986fd29aSsetje #include	"krtld/reloc.h"
297c478bd9Sstevel@tonic-gate #else
30ba2be530Sab #define	ELF_TARGET_SPARC
31ba2be530Sab #if defined(DO_RELOC_LIBLD)
32ba2be530Sab #undef DO_RELOC_LIBLD
33ba2be530Sab #define	DO_RELOC_LIBLD_SPARC
34ba2be530Sab #endif
357c478bd9Sstevel@tonic-gate #include	<stdio.h>
367c478bd9Sstevel@tonic-gate #include	"sgs.h"
377c478bd9Sstevel@tonic-gate #include	"machdep.h"
387c478bd9Sstevel@tonic-gate #include	"libld.h"
397c478bd9Sstevel@tonic-gate #include	"reloc.h"
407c478bd9Sstevel@tonic-gate #include	"conv.h"
417c478bd9Sstevel@tonic-gate #include	"msg.h"
427c478bd9Sstevel@tonic-gate #endif
437c478bd9Sstevel@tonic-gate 
44ba2be530Sab /*
45ba2be530Sab  * We need to build this code differently when it is used for
46ba2be530Sab  * cross linking:
47ba2be530Sab  *	- Data alignment requirements can differ from those
48ba2be530Sab  *		of the running system, so we can't access data
49ba2be530Sab  *		in units larger than a byte
50ba2be530Sab  *	- We have to include code to do byte swapping when the
51ba2be530Sab  *		target and linker host use different byte ordering,
52ba2be530Sab  *		but such code is a waste when running natively.
53ba2be530Sab  */
54ba2be530Sab #if !defined(DO_RELOC_LIBLD) || defined(__sparc)
55ba2be530Sab #define	DORELOC_NATIVE
56ba2be530Sab #endif
57ba2be530Sab 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * This table represents the current relocations that do_reloc() is able to
607c478bd9Sstevel@tonic-gate  * process.  The relocations below that are marked SPECIAL are relocations that
617c478bd9Sstevel@tonic-gate  * take special processing and shouldn't actually ever be passed to do_reloc().
627c478bd9Sstevel@tonic-gate  */
63ba2be530Sab const Rel_entry reloc_table[R_SPARC_NUM] = {
64552ff457Srie /* R_SPARC_NONE */	{0x0, FLG_RE_NOTREL, 0, 0, 0},
65552ff457Srie /* R_SPARC_8 */		{0x0, FLG_RE_VERIFY, 1, 0, 0},
66552ff457Srie /* R_SPARC_16 */	{0x0, FLG_RE_VERIFY, 2, 0, 0},
67552ff457Srie /* R_SPARC_32 */	{0x0, FLG_RE_VERIFY, 4, 0, 0},
687c478bd9Sstevel@tonic-gate /* R_SPARC_DISP8 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
697c478bd9Sstevel@tonic-gate 				1, 0, 0},
707c478bd9Sstevel@tonic-gate /* R_SPARC_DISP16 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
717c478bd9Sstevel@tonic-gate 				2, 0, 0},
727c478bd9Sstevel@tonic-gate /* R_SPARC_DISP32 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
737c478bd9Sstevel@tonic-gate 				4, 0, 0},
747c478bd9Sstevel@tonic-gate /* R_SPARC_WDISP30 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
757c478bd9Sstevel@tonic-gate 				4, 2, 30},
767c478bd9Sstevel@tonic-gate /* R_SPARC_WDISP22 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
777c478bd9Sstevel@tonic-gate 				4, 2, 22},
787c478bd9Sstevel@tonic-gate #if	defined(_ELF64)
79552ff457Srie /* R_SPARC_HI22 */	{0x0, FLG_RE_VERIFY, 4, 10, 22},
807c478bd9Sstevel@tonic-gate #else
817c478bd9Sstevel@tonic-gate /* R_SPARC_HI22 */	{0x0, FLG_RE_NOTREL, 4, 10, 22},
827c478bd9Sstevel@tonic-gate #endif
83552ff457Srie /* R_SPARC_22 */	{0x0, FLG_RE_VERIFY, 4, 0, 22},
84552ff457Srie /* R_SPARC_13 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 13},
85552ff457Srie /* R_SPARC_LO10 */	{0x3ff, FLG_RE_SIGN, 4, 0, 13},
867c478bd9Sstevel@tonic-gate /* R_SPARC_GOT10 */	{0x3ff, FLG_RE_GOTADD | FLG_RE_SIGN, 4, 0, 13},
877c478bd9Sstevel@tonic-gate /* R_SPARC_GOT13 */	{0x0, FLG_RE_GOTADD | FLG_RE_VERIFY | FLG_RE_SIGN,
887c478bd9Sstevel@tonic-gate 				4, 0, 13},
897c478bd9Sstevel@tonic-gate /* R_SPARC_GOT22 */	{0x0, FLG_RE_GOTADD, 4, 10, 22},
90141040e8Srie /* R_SPARC_PC10 */	{0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_LOCLBND,
91141040e8Srie 				4, 0, 13},
92141040e8Srie /* R_SPARC_PC22 */	{0x0, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_VERIFY |
93141040e8Srie 				FLG_RE_LOCLBND, 4, 10, 22},
947c478bd9Sstevel@tonic-gate /* R_SPARC_WPLT30 */	{0x0, FLG_RE_PCREL | FLG_RE_PLTREL |
957c478bd9Sstevel@tonic-gate 				FLG_RE_VERIFY | FLG_RE_SIGN,
967c478bd9Sstevel@tonic-gate 				4, 2, 30},
977c478bd9Sstevel@tonic-gate /* R_SPARC_COPY */	{0x0, 0, 0, 0, 0},		/* SPECIAL */
987c478bd9Sstevel@tonic-gate #if	defined(_ELF64)
997c478bd9Sstevel@tonic-gate /* R_SPARC_GLOB_DAT */	{0x0, FLG_RE_NOTREL, 8, 0, 0},
1007c478bd9Sstevel@tonic-gate #else
1017c478bd9Sstevel@tonic-gate /* R_SPARC_GLOB_DAT */	{0x0, FLG_RE_NOTREL, 4, 0, 0},
1027c478bd9Sstevel@tonic-gate #endif
1037c478bd9Sstevel@tonic-gate /* R_SPARC_JMP_SLOT */	{0x0, 0, 0, 0, 0},		/* SPECIAL */
1047c478bd9Sstevel@tonic-gate #if	defined(_ELF64)
1057c478bd9Sstevel@tonic-gate /* R_SPARC_RELATIVE */	{0x0, FLG_RE_NOTREL, 8, 0, 0},
1067c478bd9Sstevel@tonic-gate #else
1077c478bd9Sstevel@tonic-gate /* R_SPARC_RELATIVE */	{0x0, FLG_RE_NOTREL, 4, 0, 0},
1087c478bd9Sstevel@tonic-gate #endif
109552ff457Srie /* R_SPARC_UA32 */	{0x0, FLG_RE_UNALIGN, 4, 0, 0},
1107c478bd9Sstevel@tonic-gate /* R_SPARC_PLT32 */	{0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
1117c478bd9Sstevel@tonic-gate 				FLG_RE_ADDRELATIVE, 4, 0, 0},
1127c478bd9Sstevel@tonic-gate /* R_SPARC_HIPLT22 */	{0x0, FLG_RE_PLTREL, 4, 10, 22},
1137c478bd9Sstevel@tonic-gate /* R_SPARC_LOPLT10 */	{0x3ff, FLG_RE_PLTREL, 4, 0, 13},
1147c478bd9Sstevel@tonic-gate /* R_SPARC_PCPLT32 */	{0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
1157c478bd9Sstevel@tonic-gate 				4, 0, 0},
116552ff457Srie /* R_SPARC_PCPLT22 */	{0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
1177c478bd9Sstevel@tonic-gate 				4, 10, 22},
118552ff457Srie /* R_SPARC_PCPLT10 */	{0x3ff, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
1197c478bd9Sstevel@tonic-gate 				4, 0, 13},
120552ff457Srie /* R_SPARC_10 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 10},
121552ff457Srie /* R_SPARC_11 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 11},
122552ff457Srie /* R_SPARC_64 */	{0x0, FLG_RE_VERIFY, 8, 0, 0},		/* V9 */
123552ff457Srie /* R_SPARC_OLO10 */	{0x3ff, FLG_RE_EXTOFFSET | FLG_RE_SIGN,
124552ff457Srie 				4, 0, 13},			/* V9 */
125552ff457Srie /* R_SPARC_HH22 */	{0x0, FLG_RE_VERIFY, 4, 42, 22},	/* V9 */
126552ff457Srie /* R_SPARC_HM10 */	{0x3ff, FLG_RE_SIGN, 4, 32, 13},	/* V9 */
127552ff457Srie /* R_SPARC_LM22 */	{0x0, FLG_RE_NOTREL, 4, 10, 22},	/* V9 */
128141040e8Srie /* R_SPARC_PC_HH22 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY,
129552ff457Srie 				4, 42, 22},			/* V9 */
130141040e8Srie /* R_SPARC_PC_HM10 */	{0x3ff, FLG_RE_PCREL | FLG_RE_SIGN,
131552ff457Srie 				4, 32, 13},			/* V9 */
132141040e8Srie /* R_SPARC_PC_LM22 */	{0x0, FLG_RE_PCREL,
133552ff457Srie 				4, 10, 22},			/* V9 */
1347c478bd9Sstevel@tonic-gate /* R_SPARC_WDISP16 */	{0x0, FLG_RE_PCREL | FLG_RE_WDISP16 |
1357c478bd9Sstevel@tonic-gate 				FLG_RE_VERIFY | FLG_RE_SIGN,
1367c478bd9Sstevel@tonic-gate 				4, 2, 16},
1377c478bd9Sstevel@tonic-gate /* R_SPARC_WDISP19 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
1387c478bd9Sstevel@tonic-gate 				4, 2, 19},
1397c478bd9Sstevel@tonic-gate /* R_SPARC_GLOB_JMP */	{0x0, 0, 0, 0, 0},	/* V9 - not implemented */
1407c478bd9Sstevel@tonic-gate 						/* removed from v9 ABI */
1417c478bd9Sstevel@tonic-gate /* R_SPARC_7 */		{0x0, FLG_RE_NOTREL, 4, 0, 7},
1427c478bd9Sstevel@tonic-gate /* R_SPARC_5 */		{0x0, FLG_RE_NOTREL, 4, 0, 5},
1437c478bd9Sstevel@tonic-gate /* R_SPARC_6 */		{0x0, FLG_RE_NOTREL, 4, 0, 6},
1447c478bd9Sstevel@tonic-gate /* R_SPARC_DISP64 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
1457c478bd9Sstevel@tonic-gate 				8, 0, 0},
1467c478bd9Sstevel@tonic-gate /* R_SPARC_PLT64 */	{0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
1477c478bd9Sstevel@tonic-gate 				FLG_RE_ADDRELATIVE, 8, 0, 0},
1485aefb655Srie /* R_SPARC_HIX22 */	{(Xword)(-1LL), FLG_RE_VERIFY,
1495aefb655Srie 				4, 10, 22},			/* V9 - HaL */
150552ff457Srie /* R_SPARC_LOX10 */	{0x3ff, FLG_RE_SIGN, 4, 0, 13},		/* V9 - HaL */
151552ff457Srie /* R_SPARC_H44 */	{0x0, FLG_RE_VERIFY, 4, 22, 22},	/* V9 */
1527c478bd9Sstevel@tonic-gate /* R_SPARC_M44 */	{0x3ff, FLG_RE_NOTREL, 4, 12, 10},	/* V9 */
1537c478bd9Sstevel@tonic-gate /* R_SPARC_L44 */	{0xfff, FLG_RE_NOTREL, 4, 0, 13},	/* V9 */
154552ff457Srie /* R_SPARC_REGISTER */	{0x0, FLG_RE_REGISTER, 0, 0, 0},	/* SPECIAL */
155552ff457Srie /* R_SPARC_UA64 */	{0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
156552ff457Srie 				8, 0, 0},			/* V9 */
157552ff457Srie /* R_SPARC_UA16 */	{0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
1587c478bd9Sstevel@tonic-gate 				2, 0, 0},
159d326b23bSrie /* R_SPARC_TLS_GD_HI22 */   {0x0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 10, 22},
160d326b23bSrie /* R_SPARC_TLS_GD_LO10 */   {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSGD |
161d326b23bSrie 				FLG_RE_SIGN, 4, 0, 13},
162d326b23bSrie /* R_SPARC_TLS_GD_ADD */    {0x0, FLG_RE_TLSGD, 0, 0, 0},
163d326b23bSrie /* R_SPARC_TLS_GD_CALL */   {0x0, FLG_RE_TLSGD, 0, 0, 0},
164d326b23bSrie /* R_SPARC_TLS_LDM_HI22 */  {0x0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 10, 22},
165d326b23bSrie /* R_SPARC_TLS_LDM_LO10 */  {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSLD |
166d326b23bSrie 				FLG_RE_SIGN, 4, 0, 13},
167d326b23bSrie /* R_SPARC_TLS_LDM_ADD */   {0x0, FLG_RE_TLSLD, 0, 0, 0},
168d326b23bSrie /* R_SPARC_TLS_LDM_CALL */  {0x0, FLG_RE_TLSLD, 0, 0, 0},
169d326b23bSrie /* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSLD, 4, 10, 22},
170d326b23bSrie /* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLD, 4, 0, 13},
171d326b23bSrie /* R_SPARC_TLS_LDO_ADD */   {0x0, FLG_RE_TLSLD, 0, 0, 0},
172d326b23bSrie /* R_SPARC_TLS_IE_HI22 */   {0x0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 10, 22},
173d326b23bSrie /* R_SPARC_TLS_IE_LO10 */   {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSIE |
174d326b23bSrie 				FLG_RE_SIGN, 4, 0, 13},
175d326b23bSrie /* R_SPARC_TLS_IE_LD */	    {0x0, FLG_RE_TLSIE, 0, 0, 0},
176d326b23bSrie /* R_SPARC_TLS_IE_LDX */    {0x0, FLG_RE_TLSIE, 0, 0, 0},
177d326b23bSrie /* R_SPARC_TLS_IE_ADD */    {0x0, FLG_RE_TLSIE, 0, 0, 0},
178552ff457Srie /* R_SPARC_TLS_LE_HIX22 */  {(Xword)(-1LL),
179d326b23bSrie 				FLG_RE_VERIFY | FLG_RE_TLSLE, 4, 10, 22},
180d326b23bSrie /* R_SPARC_TLS_LE_LOX10 */  {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLE, 4, 0, 13},
1817c478bd9Sstevel@tonic-gate /* R_SPARC_TLS_DTPMOD32 */  {0x0, FLG_RE_NOTREL, 4, 0, 0},
1827c478bd9Sstevel@tonic-gate /* R_SPARC_TLS_DTPMOD64 */  {0x0, FLG_RE_NOTREL, 8, 0, 0},
1837c478bd9Sstevel@tonic-gate /* R_SPARC_TLS_DTPOFF32 */  {0x0, FLG_RE_NOTREL, 4, 0, 0},
1847c478bd9Sstevel@tonic-gate /* R_SPARC_TLS_DTPOFF64 */  {0x0, FLG_RE_NOTREL, 8, 0, 0},
1857c478bd9Sstevel@tonic-gate /* R_SPARC_TLS_TPOFF32 */   {0x0, FLG_RE_NOTREL, 4, 0, 0},
1867c478bd9Sstevel@tonic-gate /* R_SPARC_TLS_TPOFF64 */   {0x0, FLG_RE_NOTREL, 8, 0, 0},
187051d39bbSrie /* R_SPARC_GOTDATA_HIX22 */	{0, FLG_RE_SIGN | FLG_RE_GOTREL |
188051d39bbSrie 					FLG_RE_VERIFY, 4, 10, 22},
1897c478bd9Sstevel@tonic-gate /* R_SPARC_GOTDATA_LOX10 */	{ 0x3ff, FLG_RE_GOTREL | FLG_RE_SIGN, 4, 0, 13},
1907c478bd9Sstevel@tonic-gate /* R_SPARC_GOTDATA_OP_HIX22 */	{ 0x0, FLG_RE_GOTOPINS | FLG_RE_GOTADD,
1917c478bd9Sstevel@tonic-gate 					4, 10, 22},
1927c478bd9Sstevel@tonic-gate /* R_SPARC_GOTDATA_OP_LOX10 */	{ 0x3ff, FLG_RE_SIGN | FLG_RE_GOTOPINS |
1937c478bd9Sstevel@tonic-gate 					FLG_RE_GOTADD, 4, 0, 13},
1947c478bd9Sstevel@tonic-gate /* R_SPARC_GOTDATA_OP */	{ 0x0, FLG_RE_GOTOPINS, 0, 0, 0},
1952926dd2eSrie /* R_SPARC_H34 */	{0x0, FLG_RE_VERIFY, 4, 12, 22},	/* V9 */
1962926dd2eSrie /* R_SPARC_SIZE32 */	{0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0},
1972926dd2eSrie /* R_SPARC_SIZE64 */	{0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 8, 0, 0},
1987c478bd9Sstevel@tonic-gate };
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate  * Write a single relocated value to its reference location.
2037c478bd9Sstevel@tonic-gate  * We assume we wish to add the relocation amount, value, to the
204552ff457Srie  * value of the address already present in the instruction.
2057c478bd9Sstevel@tonic-gate  *
206552ff457Srie  * NAME			 VALUE	FIELD		CALCULATION
2077c478bd9Sstevel@tonic-gate  *
208552ff457Srie  * R_SPARC_NONE		     0	none		none
209552ff457Srie  * R_SPARC_8		     1	V-byte8		S + A
210552ff457Srie  * R_SPARC_16		     2	V-half16	S + A
211552ff457Srie  * R_SPARC_32		     3	V-word32	S + A
212552ff457Srie  * R_SPARC_DISP8	     4	V-byte8		S + A - P
213552ff457Srie  * R_SPARC_DISP16	     5	V-half16	S + A - P
214552ff457Srie  * R_SPARC_DISP32	     6	V-word32	S + A - P
215552ff457Srie  * R_SPARC_WDISP30	     7	V-disp30	(S + A - P) >> 2
216552ff457Srie  * R_SPARC_WDISP22	     8	V-disp22	(S + A - P) >> 2
217552ff457Srie  * R_SPARC_HI22		     9	T-imm22		(S + A) >> 10
218552ff457Srie  * R_SPARC_22		    10	V-imm22		S + A
219552ff457Srie  * R_SPARC_13		    11	V-simm13	S + A
220552ff457Srie  * R_SPARC_LO10		    12	T-simm13	(S + A) & 0x3ff
221552ff457Srie  * R_SPARC_GOT10	    13	T-simm13	G & 0x3ff
222552ff457Srie  * R_SPARC_GOT13	    14	V-simm13	G
223552ff457Srie  * R_SPARC_GOT22	    15	T-imm22		G >> 10
224552ff457Srie  * R_SPARC_PC10		    16	T-simm13	(S + A - P) & 0x3ff
225552ff457Srie  * R_SPARC_PC22		    17	V-disp22	(S + A - P) >> 10
226552ff457Srie  * R_SPARC_WPLT30	    18	V-disp30	(L + A - P) >> 2
227552ff457Srie  * R_SPARC_COPY		    19	none		none
228552ff457Srie  * R_SPARC_GLOB_DAT	    20	V-word32	S + A
229552ff457Srie  * R_SPARC_JMP_SLOT	    21	V-plt22		S + A
230552ff457Srie  * R_SPARC_RELATIVE	    22	V-word32	S + A
231552ff457Srie  * R_SPARC_UA32		    23	V-word32	S + A
232552ff457Srie  * R_SPARC_PLT32	    24	V-word32        L + A
233552ff457Srie  * R_SPARC_HIPLT22	    25	T-imm22         (L + A) >> 10
234552ff457Srie  * R_SPARC_LOPLT10	    26	T-simm13        (L + A) & 0x3ff
235552ff457Srie  * R_SPARC_PCPLT32	    27	V-word32        L + A - P
236552ff457Srie  * R_SPARC_PCPLT22	    28	V-disp22        (L + A - P) >> 10
237552ff457Srie  * R_SPARC_PCPLT10	    29	V-simm13        (L + A - P) & 0x3ff
238552ff457Srie  * R_SPARC_10		    30	V-simm10	S + A
239552ff457Srie  * R_SPARC_11		    31	V-simm11	S + A
240552ff457Srie  * R_SPARC_64		    32	V-xword64	S + A
241552ff457Srie  * R_SPARC_OLO10	    33	V-simm13	((S + A) & 0x3ff) + O
242552ff457Srie  * R_SPARC_HH22		    34	V-imm22		(S + A) >> 42
243552ff457Srie  * R_SPARC_HM10		    35	T-simm13	((S + A) >> 32) & 0x3ff
244552ff457Srie  * R_SPARC_LM22		    36	T-imm22		(S + A) >> 10
245552ff457Srie  * R_SPARC_PC_HH22	    37	V-imm22		(S + A - P) >> 42
246552ff457Srie  * R_SPARC_PC_HM10	    38	T-simm13	((S + A - P) >> 32) & 0x3ff
247552ff457Srie  * R_SPARC_PC_LM22	    39	T-imm22		(S + A - P) >> 10
248552ff457Srie  * R_SPARC_WDISP16	    40	V-d2/disp14	(S + A - P) >> 2
249552ff457Srie  * R_SPARC_WDISP19	    41	V-disp19	(S + A - P) >> 2
250552ff457Srie  * R_SPARC_GLOB_JMP	    42	V-xword64	S + A
251552ff457Srie  * R_SPARC_7		    43	V-imm7		S + A
252552ff457Srie  * R_SPARC_5		    44	V-imm5		S + A
253552ff457Srie  * R_SPARC_6		    45	V-imm6		S + A
254552ff457Srie  * R_SPARC_DISP64	    46	V-xword64	S + A - P
255552ff457Srie  * R_SPARC_PLT64	    47	V-xword64	L + A
256552ff457Srie  * R_SPARC_HIX22	    48	V-imm22		((S + A) ^
257552ff457Srie  *						    0xffffffffffffffff) >> 10
258552ff457Srie  * R_SPARC_LOX10	    49	T-simm13	((S + A) & 0x3ff) | 0x1c00
259552ff457Srie  * R_SPARC_H44		    50	V-imm22		(S + A) >> 22
260552ff457Srie  * R_SPARC_M44		    51	T-imm10		((S + A) >> 12) & 0x3ff
261552ff457Srie  * R_SPARC_L44		    52	T-imm13		(S + A) & 0xfff
262552ff457Srie  * R_SPARC_REGISTER	    53	V-xword64	S + A
263552ff457Srie  * R_SPARC_UA64		    54	V-xword64	S + A
264552ff457Srie  * R_SPARC_UA16		    55	V-half16	S + A
265552ff457Srie  * R_SPARC_TLS_GD_HI22	    56	T-simm22	@dtlndx(S + A) >> 10
266552ff457Srie  * R_SPARC_TLS_GD_LO10	    57	T-simm13	@dtlndx(S + A) & 0x3ff
267552ff457Srie  * R_SPARC_TLS_GD_ADD	    58	none		SPECIAL
268552ff457Srie  * R_SPARC_TLS_GD_CALL	    59	V-disp30	SPECIAL
269552ff457Srie  * R_SPARC_TLS_LDM_HI22	    60	T-simm22	@tmndx(S + A) >> 10
270552ff457Srie  * R_SPARC_TLS_LDM_LO10	    61	T-simm13	@tmndx(S + A) & 0x3ff
271552ff457Srie  * R_SPARC_TLS_LDM_ADD	    62	none		SPECIAL
272552ff457Srie  * R_SPARC_TLS_LDM_CALL	    63	V-disp30	SPECIAL
273552ff457Srie  * R_SPARC_TLS_LDO_HIX22    64	V-simm22	@dtpoff(S + A) >> 10
274552ff457Srie  * R_SPARC_TLS_LDO_LOX10    65	T-simm13	@dtpoff(S + A) & 0x3ff
275552ff457Srie  * R_SPARC_TLS_LDO_ADD	    66	none		SPECIAL
276552ff457Srie  * R_SPARC_TLS_IE_HI22	    67	T-simm22	@got(@tpoff(S + A)) >> 10
277552ff457Srie  * R_SPARC_TLS_IE_LO10	    68	T-simm13	@got(@tpoff(S + A)) & 0x3ff
278552ff457Srie  * R_SPARC_TLS_IE_LD	    69	none		SPECIAL
279552ff457Srie  * R_SPARC_TLS_IE_LDX	    70	none		SPECIAL
280552ff457Srie  * R_SPARC_TLS_IE_ADD	    71	none		SPECIAL
281552ff457Srie  * R_SPARC_TLS_LE_HIX22	    72	V-simm22	(@tpoff(S + A) ^
282552ff457Srie  *						    0xffffffff) >> 10
283552ff457Srie  * R_SPARC_TLS_LE_LOX10	    73	T-simm13	(@tpoff(S + A) & 0x3ff) | 0x1c00
284552ff457Srie  * R_SPARC_TLS_DTPMOD32	    74	V-word32	@dtmod(S + A)
285552ff457Srie  * R_SPARC_TLS_DTPMOD64	    75	V-word64	@dtmod(S + A)
286552ff457Srie  * R_SPARC_TLS_DTPOFF32	    76	V-word32	@dtpoff(S + A)
287552ff457Srie  * R_SPARC_TLS_DTPOFF64	    77	V-word64	@dtpoff(S + A)
288552ff457Srie  * R_SPARC_TLS_TPOFF32	    78	V-word32	@tpoff(S + A)
289552ff457Srie  * R_SPARC_TLS_TPOFF64	    79	V-word64	@tpoff(S + A)
290051d39bbSrie  * R_SPARC_GOTDATA_HIX22    80	V-imm22		((S + A - GOT) >> 10) ^
291552ff457Srie  *						  ((S + A - GOT) >> 31)
292552ff457Srie  * R_SPARC_GOTDATA_LOX10    81	T-simm13	((S + A - GOT) & 0x3ff) |
293552ff457Srie  *						  (((S + A - GOT) >> 31) &
294552ff457Srie  *						  0x1c00)
295552ff457Srie  * R_SPARC_GOTDATA_OP_HIX22 82	T-imm22		(G >> 10) & (G >> 31)
296552ff457Srie  * R_SPARC_GOTDATA_OP_LOX10 83	T-simm13	(G & 0x3ff) |
297552ff457Srie  *						  ((G >> 31) & 0x1c00)
2982926dd2eSrie  * R_SPARC_GOTDATA_OP	    84  Word32		SPECIAL
2992926dd2eSrie  * R_SPARC_H34		    85	V-imm22		(S + A) >> 12
3002926dd2eSrie  * R_SPARC_SIZE32	    86	V-word32	Z + A
3012926dd2eSrie  * R_SPARC_SIZE64	    87	V-xword64	Z + A
3027c478bd9Sstevel@tonic-gate  *
3037c478bd9Sstevel@tonic-gate  *	This is Figure 4-20: Relocation Types from the Draft Copy of
3047c478bd9Sstevel@tonic-gate  * the ABI, Printed on 11/29/88.
3057c478bd9Sstevel@tonic-gate  *
3067c478bd9Sstevel@tonic-gate  * NOTE1: relocations 24->45 are newly registered relocations to support
3077c478bd9Sstevel@tonic-gate  *	 C++ ABI & SPARC V8+ and SPARC V9 architectures (1/9/94), and
3087c478bd9Sstevel@tonic-gate  *	 64-bit relocations 46-55 were added for SPARC V9.
3097c478bd9Sstevel@tonic-gate  *
3107c478bd9Sstevel@tonic-gate  * NOTE2: relocations 56->79 are added to support Thread-Local storage
3117c478bd9Sstevel@tonic-gate  *	  as recorded in PSARC/2001/509
3127c478bd9Sstevel@tonic-gate  *
3137c478bd9Sstevel@tonic-gate  * NOTE3: The value to be passed for relocations R_SPARC_HIX22 and
3147c478bd9Sstevel@tonic-gate  *	  R_SPARC_TLS_HIX22 are negative values. So the upper 10 or 40 bits
3157c478bd9Sstevel@tonic-gate  *	  are 1. (So when the exclusive OR is applied, the upper bits
3167c478bd9Sstevel@tonic-gate  *	  will be 0.)
3177c478bd9Sstevel@tonic-gate  *
3187c478bd9Sstevel@tonic-gate  * Relocation calculations:
3197c478bd9Sstevel@tonic-gate  *
3207c478bd9Sstevel@tonic-gate  * The FIELD names indicate whether the relocation type checks for overflow.
3217c478bd9Sstevel@tonic-gate  * A calculated relocation value may be larger than the intended field, and
3227c478bd9Sstevel@tonic-gate  * the relocation type may verify (V) that the value fits, or truncate (T)
3237c478bd9Sstevel@tonic-gate  * the result.
3247c478bd9Sstevel@tonic-gate  *
3257c478bd9Sstevel@tonic-gate  * CALCULATION uses the following notation:
3267c478bd9Sstevel@tonic-gate  *      A       the addend used
3277c478bd9Sstevel@tonic-gate  *      B       the base address of the shared object in memory
3287c478bd9Sstevel@tonic-gate  *      G       the offset into the global offset table
3297c478bd9Sstevel@tonic-gate  *      L       the procedure linkage entry
3307c478bd9Sstevel@tonic-gate  *      P       the place of the storage unit being relocated
3317c478bd9Sstevel@tonic-gate  *      S       the value of the symbol
3327c478bd9Sstevel@tonic-gate  *	O	secondary addend (extra offset) in v9 r_info field
3332926dd2eSrie  *	Z	the size of the symbol whose index resides in the relocation
3342926dd2eSrie  *		entry
3357c478bd9Sstevel@tonic-gate  *
3367c478bd9Sstevel@tonic-gate  *	@dtlndx(x): Allocate two contiguous entries in the GOT table to hold
3377c478bd9Sstevel@tonic-gate  *	   a Tls_index structure (for passing to __tls_get_addr()). The
3387c478bd9Sstevel@tonic-gate  *	   instructions referencing this entry will be bound to the first
3397c478bd9Sstevel@tonic-gate  *	   of the two GOT entries.
3407c478bd9Sstevel@tonic-gate  *
3417c478bd9Sstevel@tonic-gate  *	@tmndx(x): Allocate two contiguous entries in the GOT table to hold
3427c478bd9Sstevel@tonic-gate  *	   a Tls_index structure (for passing to __tls_get_addr()). The
3437c478bd9Sstevel@tonic-gate  *	   ti_offset field of the Tls_index will be set to 0 (zero) and the
3447c478bd9Sstevel@tonic-gate  *	   ti_module will be filled in at run-time. The call to
3457c478bd9Sstevel@tonic-gate  *	   __tls_get_addr() will return the starting offset of the dynamic
3467c478bd9Sstevel@tonic-gate  *	   TLS block.
3477c478bd9Sstevel@tonic-gate  *
3487c478bd9Sstevel@tonic-gate  *	@dtpoff(x): calculate the tlsoffset relative to the TLS block.
3497c478bd9Sstevel@tonic-gate  *
3507c478bd9Sstevel@tonic-gate  *	@tpoff(x): calculate the negative tlsoffset relative to the static
3517c478bd9Sstevel@tonic-gate  *	   TLS block. This value can be added to the thread-pointer to
3527c478bd9Sstevel@tonic-gate  *	   calculate the tls address.
3537c478bd9Sstevel@tonic-gate  *
3547c478bd9Sstevel@tonic-gate  *	@dtpmod(x): calculate the module id of the object containing symbol x.
3557c478bd9Sstevel@tonic-gate  *
3567c478bd9Sstevel@tonic-gate  * The calculations in the CALCULATION column are assumed to have been performed
3577c478bd9Sstevel@tonic-gate  * before calling this function except for the addition of the addresses in the
3587c478bd9Sstevel@tonic-gate  * instructions.
3597c478bd9Sstevel@tonic-gate  *
3607c478bd9Sstevel@tonic-gate  * Upon successful completion of do_reloc() *value will be set to the
3617c478bd9Sstevel@tonic-gate  * 'bit-shifted' value that will be or'ed into memory.
3627c478bd9Sstevel@tonic-gate  */
363f3324781Sab #if defined(_KERNEL)
364f3324781Sab #define	lml	0		/* Needed by arglist of REL_ERR_* macros */
3657c478bd9Sstevel@tonic-gate int
do_reloc_krtld(uchar_t rtype,uchar_t * off,Xword * value,const char * sym,const char * file)366f3324781Sab do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
367f3324781Sab     const char *file)
368f3324781Sab #elif defined(DO_RELOC_LIBLD)
369ba2be530Sab /*ARGSUSED5*/
370f3324781Sab int
371*bf994817SAli Bahrami do_reloc_ld(Rel_desc *rdesc, uchar_t *off, Xword *value,
372*bf994817SAli Bahrami     rel_desc_sname_func_t rel_desc_sname_func,
373f3324781Sab     const char *file, int bswap, void *lml)
374f3324781Sab #else
375f3324781Sab int
376f3324781Sab do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
3775aefb655Srie     const char *file, void *lml)
378f3324781Sab #endif
3797c478bd9Sstevel@tonic-gate {
380*bf994817SAli Bahrami #ifdef DO_RELOC_LIBLD
381*bf994817SAli Bahrami #define	sym (* rel_desc_sname_func)(rdesc)
382*bf994817SAli Bahrami 	uchar_t	rtype = rdesc->rel_rtype;
383*bf994817SAli Bahrami #endif
384ba2be530Sab 	Xword	uvalue = 0;
385ba2be530Sab 	Xword	basevalue, sigbit_mask, sigfit_mask;
386ba2be530Sab 	Xword	corevalue = *value;
387ba2be530Sab 	uchar_t	bshift;
388ba2be530Sab 	int	field_size, re_flags;
389ba2be530Sab 	const	Rel_entry	*rep;
390f3324781Sab 
3917c478bd9Sstevel@tonic-gate 	rep = &reloc_table[rtype];
3927c478bd9Sstevel@tonic-gate 	bshift = rep->re_bshift;
3937c478bd9Sstevel@tonic-gate 	field_size = rep->re_fsize;
3947c478bd9Sstevel@tonic-gate 	re_flags = rep->re_flags;
3957c478bd9Sstevel@tonic-gate 	sigbit_mask = S_MASK(rep->re_sigbits);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if ((re_flags & FLG_RE_SIGN) && sigbit_mask) {
3987c478bd9Sstevel@tonic-gate 		/*
3997c478bd9Sstevel@tonic-gate 		 * sigfit_mask takes into account that a value
4007c478bd9Sstevel@tonic-gate 		 * might be signed and discards the signbit for
4017c478bd9Sstevel@tonic-gate 		 * comparison.
4027c478bd9Sstevel@tonic-gate 		 */
4037c478bd9Sstevel@tonic-gate 		sigfit_mask = S_MASK(rep->re_sigbits - 1);
4047c478bd9Sstevel@tonic-gate 	} else
4057c478bd9Sstevel@tonic-gate 		sigfit_mask = sigbit_mask;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	if (field_size == 0) {
4085aefb655Srie 		REL_ERR_UNIMPL(lml, file, sym, rtype);
4097c478bd9Sstevel@tonic-gate 		return (0);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 
412ba2be530Sab 	/*
413ba2be530Sab 	 * We have two ways to retrieve the base value, a general one
414ba2be530Sab 	 * that will work with data of any alignment, and another that is
415ba2be530Sab 	 * fast, but which requires the data to be aligned according to
416ba2be530Sab 	 * sparc alignment rules.
417ba2be530Sab 	 *
418ba2be530Sab 	 * For non-native linking, we always use the general path. For
419ba2be530Sab 	 * native linking, the FLG_RE_UNALIGN determines it.
420ba2be530Sab 	 */
421ba2be530Sab #if defined(DORELOC_NATIVE)
422ba2be530Sab 	if (re_flags & FLG_RE_UNALIGN)
423ba2be530Sab #endif
424ba2be530Sab 	{
425552ff457Srie 		int	i;
426552ff457Srie 		uchar_t	*dest = (uchar_t *)&basevalue;
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 		basevalue = 0;
429ba2be530Sab #if !defined(DORELOC_NATIVE)
430ba2be530Sab 		if (bswap) {
431ba2be530Sab 			int j = field_size - 1;
432ba2be530Sab 
433ba2be530Sab 			for (i = 0; i < field_size; i++, j--)
434ba2be530Sab 				dest[i] = off[j];
435ba2be530Sab 
436ba2be530Sab 		} else
437ba2be530Sab #endif
438ba2be530Sab 		{
439ba2be530Sab 			/*
440ba2be530Sab 			 * Adjust the offset
441ba2be530Sab 			 */
442ba2be530Sab 			/* LINTED */
443ba2be530Sab 			i = (int)(sizeof (Xword) - field_size);
444ba2be530Sab 			if (i > 0)
445ba2be530Sab 				dest += i;
446ba2be530Sab 			for (i = field_size - 1; i >= 0; i--)
447ba2be530Sab 				dest[i] = off[i];
448ba2be530Sab 		}
449ba2be530Sab 	}
450ba2be530Sab 
451ba2be530Sab 	/*
452ba2be530Sab 	 * Non-native linker: We have already fetched the value above,
453ba2be530Sab 	 *	but if the relocation does not have the FLG_RE_UNALIGN
454ba2be530Sab 	 *	flag set, we still need to do the same error checking we
455ba2be530Sab 	 *	would do on a native linker.
456ba2be530Sab 	 * Native-linker: If this is an aligned relocation, we need to
457ba2be530Sab 	 *	fetch the value and also do the error checking.
458ba2be530Sab 	 *
459ba2be530Sab 	 * The FETCH macro is used to conditionalize the fetching so that
460ba2be530Sab 	 * it only happens in the native case.
461ba2be530Sab 	 */
462ba2be530Sab #if defined(DORELOC_NATIVE)
463ba2be530Sab #define	FETCH(_type) basevalue = (Xword)*((_type *)off);
464ba2be530Sab #else
465ba2be530Sab #define	FETCH(_type)
466ba2be530Sab #endif
467ba2be530Sab 	if ((re_flags & FLG_RE_UNALIGN) == 0) {
46875521904Sraf 		if (((field_size == 2) && ((uintptr_t)off & 0x1)) ||
46975521904Sraf 		    ((field_size == 4) && ((uintptr_t)off & 0x3)) ||
47075521904Sraf 		    ((field_size == 8) && ((uintptr_t)off & 0x7))) {
4715aefb655Srie 			REL_ERR_NONALIGN(lml, file, sym, rtype, (uintptr_t)off);
4727c478bd9Sstevel@tonic-gate 			return (0);
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 		switch (field_size) {
4757c478bd9Sstevel@tonic-gate 		case 1:
476ba2be530Sab 			/* LINTED */
477ba2be530Sab 			FETCH(uchar_t);
4787c478bd9Sstevel@tonic-gate 			break;
4797c478bd9Sstevel@tonic-gate 		case 2:
4807c478bd9Sstevel@tonic-gate 			/* LINTED */
481ba2be530Sab 			FETCH(Half);
4827c478bd9Sstevel@tonic-gate 			break;
4837c478bd9Sstevel@tonic-gate 		case 4:
4847c478bd9Sstevel@tonic-gate 			/* LINTED */
485ba2be530Sab 			FETCH(Word);
4867c478bd9Sstevel@tonic-gate 			break;
4877c478bd9Sstevel@tonic-gate 		case 8:
4887c478bd9Sstevel@tonic-gate 			/* LINTED */
489ba2be530Sab 			FETCH(Xword);
4907c478bd9Sstevel@tonic-gate 			break;
4917c478bd9Sstevel@tonic-gate 		default:
4925aefb655Srie 			REL_ERR_UNNOBITS(lml, file, sym, rtype,
4935aefb655Srie 			    (rep->re_fsize * 8));
4947c478bd9Sstevel@tonic-gate 			return (0);
4957c478bd9Sstevel@tonic-gate 		}
4967c478bd9Sstevel@tonic-gate 	}
497ba2be530Sab #undef FETCH
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	if (sigbit_mask) {
5007c478bd9Sstevel@tonic-gate 		/*
5017c478bd9Sstevel@tonic-gate 		 * The WDISP16 relocation is an unusual one in that it's bits
5027c478bd9Sstevel@tonic-gate 		 * are not all contiguous.  We have to selectivly pull them out.
5037c478bd9Sstevel@tonic-gate 		 */
5047c478bd9Sstevel@tonic-gate 		if (re_flags & FLG_RE_WDISP16) {
5057c478bd9Sstevel@tonic-gate 			uvalue = ((basevalue & 0x300000) >> 6) |
506986fd29aSsetje 			    (basevalue & 0x3fff);
5077c478bd9Sstevel@tonic-gate 			basevalue &= ~0x303fff;
5087c478bd9Sstevel@tonic-gate 		} else {
5097c478bd9Sstevel@tonic-gate 			uvalue = sigbit_mask & basevalue;
5107c478bd9Sstevel@tonic-gate 			basevalue &= ~sigbit_mask;
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 		/*
5137c478bd9Sstevel@tonic-gate 		 * If value is signed make sure that we signextend the uvalue.
5147c478bd9Sstevel@tonic-gate 		 */
5157c478bd9Sstevel@tonic-gate 		if (re_flags & FLG_RE_SIGN) {
5167c478bd9Sstevel@tonic-gate 			if (uvalue & (~sigbit_mask & sigfit_mask))
5177c478bd9Sstevel@tonic-gate 				uvalue |= ~sigbit_mask;
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 	} else
5207c478bd9Sstevel@tonic-gate 		uvalue = basevalue;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (bshift)
5237c478bd9Sstevel@tonic-gate 		uvalue <<= bshift;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	uvalue += *value;
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	if (rep->re_mask &&
5287c478bd9Sstevel@tonic-gate 	    ((rtype == R_SPARC_HIX22) || (rtype == R_SPARC_TLS_LE_HIX22)))
5297c478bd9Sstevel@tonic-gate 		uvalue ^= rep->re_mask;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	if (bshift) {
5327c478bd9Sstevel@tonic-gate 		/*
5337c478bd9Sstevel@tonic-gate 		 * This is to check that we are not attempting to
5347c478bd9Sstevel@tonic-gate 		 * jump to a non-4 byte aligned address.
5357c478bd9Sstevel@tonic-gate 		 */
5367c478bd9Sstevel@tonic-gate 		if ((bshift == 2) && (uvalue & 0x3)) {
5375aefb655Srie 			REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, 2, off);
5387c478bd9Sstevel@tonic-gate 			return (0);
5397c478bd9Sstevel@tonic-gate 		}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		if (re_flags & FLG_RE_SIGN) {
5427c478bd9Sstevel@tonic-gate 			uvalue = (Sxword)uvalue >> bshift;
5437c478bd9Sstevel@tonic-gate 		} else {
5447c478bd9Sstevel@tonic-gate 			uvalue >>= bshift;
5457c478bd9Sstevel@tonic-gate 		}
5467c478bd9Sstevel@tonic-gate 		corevalue >>= bshift;
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	if ((rtype == R_SPARC_GOTDATA_HIX22) ||
5507c478bd9Sstevel@tonic-gate 	    (rtype == R_SPARC_GOTDATA_OP_HIX22)) {
5517c478bd9Sstevel@tonic-gate 		uvalue ^= ((Sxword)(*value) >> 31);
5527c478bd9Sstevel@tonic-gate 		corevalue ^= ((Sxword)(*value) >> 31);
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	if (rep->re_mask &&
5567c478bd9Sstevel@tonic-gate 	    (rtype != R_SPARC_HIX22) && (rtype != R_SPARC_TLS_LE_HIX22) &&
5577c478bd9Sstevel@tonic-gate 	    (rtype != R_SPARC_GOTDATA_HIX22))
5587c478bd9Sstevel@tonic-gate 		uvalue &= rep->re_mask;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	if ((rtype == R_SPARC_LOX10) || (rtype == R_SPARC_TLS_LE_LOX10)) {
5617c478bd9Sstevel@tonic-gate 		uvalue |= 0x1c00;
5627c478bd9Sstevel@tonic-gate 		corevalue |= 0x1c00;
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	if ((rtype == R_SPARC_GOTDATA_LOX10) ||
5667c478bd9Sstevel@tonic-gate 	    (rtype == R_SPARC_GOTDATA_OP_LOX10)) {
5677c478bd9Sstevel@tonic-gate 		uvalue |= ((Sxword)(*value) >> 31) & 0x1c00;
5687c478bd9Sstevel@tonic-gate 		corevalue |= ((Sxword)(*value) >> 31) & 0x1c00;
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	if ((re_flags & FLG_RE_VERIFY) && sigbit_mask) {
5737c478bd9Sstevel@tonic-gate 		if (((re_flags & FLG_RE_SIGN) &&
5747c478bd9Sstevel@tonic-gate 		    (S_INRANGE((Sxword)uvalue, rep->re_sigbits - 1) == 0)) ||
5757c478bd9Sstevel@tonic-gate 		    (!(re_flags & FLG_RE_SIGN) &&
5767c478bd9Sstevel@tonic-gate 		    ((sigbit_mask & uvalue) != uvalue))) {
5775aefb655Srie 			REL_ERR_NOFIT(lml, file, sym, rtype, uvalue);
5787c478bd9Sstevel@tonic-gate 			return (0);
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	if (sigbit_mask) {
5837c478bd9Sstevel@tonic-gate 		/*
5847c478bd9Sstevel@tonic-gate 		 * Again the R_SPARC_WDISP16 relocation takes special
5857c478bd9Sstevel@tonic-gate 		 * processing because of its non-continguous bits.
5867c478bd9Sstevel@tonic-gate 		 */
5877c478bd9Sstevel@tonic-gate 		if (re_flags & FLG_RE_WDISP16)
5887c478bd9Sstevel@tonic-gate 			uvalue = ((uvalue & 0xc000) << 6) |
589986fd29aSsetje 			    (uvalue & 0x3fff);
5907c478bd9Sstevel@tonic-gate 		else
5917c478bd9Sstevel@tonic-gate 			uvalue &= sigbit_mask;
5927c478bd9Sstevel@tonic-gate 		/*
5937c478bd9Sstevel@tonic-gate 		 * Combine value back with original word
5947c478bd9Sstevel@tonic-gate 		 */
5957c478bd9Sstevel@tonic-gate 		uvalue |= basevalue;
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 	*value = corevalue;
5987c478bd9Sstevel@tonic-gate 
599ba2be530Sab 	/*
600ba2be530Sab 	 * Now, we store uvalue back at the location given by off.
601ba2be530Sab 	 * This is similar to the fetch case above:
602ba2be530Sab 	 *	- We have general (unaligned) and fast (aligned) cases
603ba2be530Sab 	 *	- Cross linkers need to use the unaligned case even
604ba2be530Sab 	 *		when the relocation does not specify FLG_RE_UNALIGN.
605ba2be530Sab 	 *	- A cross linker that processes a relocation that does not
606ba2be530Sab 	 *		have FLG_RE_UNALIGN set has to do the same error
607ba2be530Sab 	 *		checking that a native linker would do, while avoiding
608ba2be530Sab 	 *		the aligned store (accomplished with the STORE macro).
609ba2be530Sab 	 */
610ba2be530Sab #if defined(DORELOC_NATIVE)
611ba2be530Sab 	if (re_flags & FLG_RE_UNALIGN)
612ba2be530Sab #endif
613ba2be530Sab 	{
614552ff457Srie 		int	i;
615552ff457Srie 		uchar_t	*src = (uchar_t *)&uvalue;
6167c478bd9Sstevel@tonic-gate 
617ba2be530Sab #if !defined(DORELOC_NATIVE)
618ba2be530Sab 		if (bswap) {
619ba2be530Sab 			int j = field_size - 1;
620ba2be530Sab 
621ba2be530Sab 			for (i = 0; i < field_size; i++, j--)
622ba2be530Sab 				off[i] = src[j];
623ba2be530Sab 
624ba2be530Sab 		} else
625ba2be530Sab #endif
626ba2be530Sab 		{
627ba2be530Sab 			/*
628ba2be530Sab 			 * Adjust the offset.
629ba2be530Sab 			 */
630ba2be530Sab 			/* LINTED */
631ba2be530Sab 			i = (int)(sizeof (Xword) - field_size);
632ba2be530Sab 			if (i > 0)
633ba2be530Sab 				src += i;
634ba2be530Sab 			for (i = field_size - 1; i >= 0; i--)
635ba2be530Sab 				off[i] = src[i];
636ba2be530Sab 		}
637ba2be530Sab 	}
638ba2be530Sab 
639ba2be530Sab #if defined(DORELOC_NATIVE)
640ba2be530Sab #define	STORE(_type) *((_type *)off) = (_type)uvalue
641ba2be530Sab #else
642ba2be530Sab #define	STORE(_type)
643ba2be530Sab #endif
644ba2be530Sab 	if ((re_flags & FLG_RE_UNALIGN) == 0) {
6457c478bd9Sstevel@tonic-gate 		switch (rep->re_fsize) {
6467c478bd9Sstevel@tonic-gate 		case 1:
647552ff457Srie 			/* LINTED */
648ba2be530Sab 			STORE(uchar_t);
6497c478bd9Sstevel@tonic-gate 			break;
6507c478bd9Sstevel@tonic-gate 		case 2:
6517c478bd9Sstevel@tonic-gate 			/* LINTED */
652ba2be530Sab 			STORE(Half);
6537c478bd9Sstevel@tonic-gate 			break;
6547c478bd9Sstevel@tonic-gate 		case 4:
6557c478bd9Sstevel@tonic-gate 			/* LINTED */
656ba2be530Sab 			STORE(Word);
6577c478bd9Sstevel@tonic-gate 			break;
6587c478bd9Sstevel@tonic-gate 		case 8:
6597c478bd9Sstevel@tonic-gate 			/* LINTED */
660ba2be530Sab 			STORE(Xword);
6617c478bd9Sstevel@tonic-gate 			break;
662552ff457Srie 		default:
663552ff457Srie 			/*
664552ff457Srie 			 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
665552ff457Srie 			 */
6665aefb655Srie 			REL_ERR_UNSUPSZ(lml, file, sym, rtype, rep->re_fsize);
667552ff457Srie 			return (0);
6687c478bd9Sstevel@tonic-gate 		}
6697c478bd9Sstevel@tonic-gate 	}
670ba2be530Sab #undef STORE
671ba2be530Sab 
6727c478bd9Sstevel@tonic-gate 	return (1);
673*bf994817SAli Bahrami 
674*bf994817SAli Bahrami #ifdef DO_RELOC_LIBLD
675*bf994817SAli Bahrami #undef sym
676*bf994817SAli Bahrami #endif
6777c478bd9Sstevel@tonic-gate }
678