xref: /onnv-gate/usr/src/uts/sparc/krtld/doreloc.c (revision 12155:50d9d4aeb501)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51618Srie  * Common Development and Distribution License (the "License").
61618Srie  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211048Sraf 
220Sstevel@tonic-gate /*
23*12155SAli.Bahrami@Sun.COM  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
251048Sraf 
260Sstevel@tonic-gate #if	defined(_KERNEL)
270Sstevel@tonic-gate #include	<sys/types.h>
285648Ssetje #include	"krtld/reloc.h"
290Sstevel@tonic-gate #else
306206Sab196087 #define	ELF_TARGET_SPARC
316206Sab196087 #if defined(DO_RELOC_LIBLD)
326206Sab196087 #undef DO_RELOC_LIBLD
336206Sab196087 #define	DO_RELOC_LIBLD_SPARC
346206Sab196087 #endif
350Sstevel@tonic-gate #include	<stdio.h>
360Sstevel@tonic-gate #include	"sgs.h"
370Sstevel@tonic-gate #include	"machdep.h"
380Sstevel@tonic-gate #include	"libld.h"
390Sstevel@tonic-gate #include	"reloc.h"
400Sstevel@tonic-gate #include	"conv.h"
410Sstevel@tonic-gate #include	"msg.h"
420Sstevel@tonic-gate #endif
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
456206Sab196087  * We need to build this code differently when it is used for
466206Sab196087  * cross linking:
476206Sab196087  *	- Data alignment requirements can differ from those
486206Sab196087  *		of the running system, so we can't access data
496206Sab196087  *		in units larger than a byte
506206Sab196087  *	- We have to include code to do byte swapping when the
516206Sab196087  *		target and linker host use different byte ordering,
526206Sab196087  *		but such code is a waste when running natively.
536206Sab196087  */
546206Sab196087 #if !defined(DO_RELOC_LIBLD) || defined(__sparc)
556206Sab196087 #define	DORELOC_NATIVE
566206Sab196087 #endif
576206Sab196087 
586206Sab196087 /*
590Sstevel@tonic-gate  * This table represents the current relocations that do_reloc() is able to
600Sstevel@tonic-gate  * process.  The relocations below that are marked SPECIAL are relocations that
610Sstevel@tonic-gate  * take special processing and shouldn't actually ever be passed to do_reloc().
620Sstevel@tonic-gate  */
636206Sab196087 const Rel_entry reloc_table[R_SPARC_NUM] = {
641169Srie /* R_SPARC_NONE */	{0x0, FLG_RE_NOTREL, 0, 0, 0},
651169Srie /* R_SPARC_8 */		{0x0, FLG_RE_VERIFY, 1, 0, 0},
661169Srie /* R_SPARC_16 */	{0x0, FLG_RE_VERIFY, 2, 0, 0},
671169Srie /* R_SPARC_32 */	{0x0, FLG_RE_VERIFY, 4, 0, 0},
680Sstevel@tonic-gate /* R_SPARC_DISP8 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
690Sstevel@tonic-gate 				1, 0, 0},
700Sstevel@tonic-gate /* R_SPARC_DISP16 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
710Sstevel@tonic-gate 				2, 0, 0},
720Sstevel@tonic-gate /* R_SPARC_DISP32 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
730Sstevel@tonic-gate 				4, 0, 0},
740Sstevel@tonic-gate /* R_SPARC_WDISP30 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
750Sstevel@tonic-gate 				4, 2, 30},
760Sstevel@tonic-gate /* R_SPARC_WDISP22 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
770Sstevel@tonic-gate 				4, 2, 22},
780Sstevel@tonic-gate #if	defined(_ELF64)
791169Srie /* R_SPARC_HI22 */	{0x0, FLG_RE_VERIFY, 4, 10, 22},
800Sstevel@tonic-gate #else
810Sstevel@tonic-gate /* R_SPARC_HI22 */	{0x0, FLG_RE_NOTREL, 4, 10, 22},
820Sstevel@tonic-gate #endif
831169Srie /* R_SPARC_22 */	{0x0, FLG_RE_VERIFY, 4, 0, 22},
841169Srie /* R_SPARC_13 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 13},
851169Srie /* R_SPARC_LO10 */	{0x3ff, FLG_RE_SIGN, 4, 0, 13},
860Sstevel@tonic-gate /* R_SPARC_GOT10 */	{0x3ff, FLG_RE_GOTADD | FLG_RE_SIGN, 4, 0, 13},
870Sstevel@tonic-gate /* R_SPARC_GOT13 */	{0x0, FLG_RE_GOTADD | FLG_RE_VERIFY | FLG_RE_SIGN,
880Sstevel@tonic-gate 				4, 0, 13},
890Sstevel@tonic-gate /* R_SPARC_GOT22 */	{0x0, FLG_RE_GOTADD, 4, 10, 22},
901324Srie /* R_SPARC_PC10 */	{0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_LOCLBND,
911324Srie 				4, 0, 13},
921324Srie /* R_SPARC_PC22 */	{0x0, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_VERIFY |
931324Srie 				FLG_RE_LOCLBND, 4, 10, 22},
940Sstevel@tonic-gate /* R_SPARC_WPLT30 */	{0x0, FLG_RE_PCREL | FLG_RE_PLTREL |
950Sstevel@tonic-gate 				FLG_RE_VERIFY | FLG_RE_SIGN,
960Sstevel@tonic-gate 				4, 2, 30},
970Sstevel@tonic-gate /* R_SPARC_COPY */	{0x0, 0, 0, 0, 0},		/* SPECIAL */
980Sstevel@tonic-gate #if	defined(_ELF64)
990Sstevel@tonic-gate /* R_SPARC_GLOB_DAT */	{0x0, FLG_RE_NOTREL, 8, 0, 0},
1000Sstevel@tonic-gate #else
1010Sstevel@tonic-gate /* R_SPARC_GLOB_DAT */	{0x0, FLG_RE_NOTREL, 4, 0, 0},
1020Sstevel@tonic-gate #endif
1030Sstevel@tonic-gate /* R_SPARC_JMP_SLOT */	{0x0, 0, 0, 0, 0},		/* SPECIAL */
1040Sstevel@tonic-gate #if	defined(_ELF64)
1050Sstevel@tonic-gate /* R_SPARC_RELATIVE */	{0x0, FLG_RE_NOTREL, 8, 0, 0},
1060Sstevel@tonic-gate #else
1070Sstevel@tonic-gate /* R_SPARC_RELATIVE */	{0x0, FLG_RE_NOTREL, 4, 0, 0},
1080Sstevel@tonic-gate #endif
1091169Srie /* R_SPARC_UA32 */	{0x0, FLG_RE_UNALIGN, 4, 0, 0},
1100Sstevel@tonic-gate /* R_SPARC_PLT32 */	{0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
1110Sstevel@tonic-gate 				FLG_RE_ADDRELATIVE, 4, 0, 0},
1120Sstevel@tonic-gate /* R_SPARC_HIPLT22 */	{0x0, FLG_RE_PLTREL, 4, 10, 22},
1130Sstevel@tonic-gate /* R_SPARC_LOPLT10 */	{0x3ff, FLG_RE_PLTREL, 4, 0, 13},
1140Sstevel@tonic-gate /* R_SPARC_PCPLT32 */	{0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
1150Sstevel@tonic-gate 				4, 0, 0},
1161169Srie /* R_SPARC_PCPLT22 */	{0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
1170Sstevel@tonic-gate 				4, 10, 22},
1181169Srie /* R_SPARC_PCPLT10 */	{0x3ff, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY,
1190Sstevel@tonic-gate 				4, 0, 13},
1201169Srie /* R_SPARC_10 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 10},
1211169Srie /* R_SPARC_11 */	{0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 11},
1221169Srie /* R_SPARC_64 */	{0x0, FLG_RE_VERIFY, 8, 0, 0},		/* V9 */
1231169Srie /* R_SPARC_OLO10 */	{0x3ff, FLG_RE_EXTOFFSET | FLG_RE_SIGN,
1241169Srie 				4, 0, 13},			/* V9 */
1251169Srie /* R_SPARC_HH22 */	{0x0, FLG_RE_VERIFY, 4, 42, 22},	/* V9 */
1261169Srie /* R_SPARC_HM10 */	{0x3ff, FLG_RE_SIGN, 4, 32, 13},	/* V9 */
1271169Srie /* R_SPARC_LM22 */	{0x0, FLG_RE_NOTREL, 4, 10, 22},	/* V9 */
1281324Srie /* R_SPARC_PC_HH22 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY,
1291169Srie 				4, 42, 22},			/* V9 */
1301324Srie /* R_SPARC_PC_HM10 */	{0x3ff, FLG_RE_PCREL | FLG_RE_SIGN,
1311169Srie 				4, 32, 13},			/* V9 */
1321324Srie /* R_SPARC_PC_LM22 */	{0x0, FLG_RE_PCREL,
1331169Srie 				4, 10, 22},			/* V9 */
1340Sstevel@tonic-gate /* R_SPARC_WDISP16 */	{0x0, FLG_RE_PCREL | FLG_RE_WDISP16 |
1350Sstevel@tonic-gate 				FLG_RE_VERIFY | FLG_RE_SIGN,
1360Sstevel@tonic-gate 				4, 2, 16},
1370Sstevel@tonic-gate /* R_SPARC_WDISP19 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
1380Sstevel@tonic-gate 				4, 2, 19},
1390Sstevel@tonic-gate /* R_SPARC_GLOB_JMP */	{0x0, 0, 0, 0, 0},	/* V9 - not implemented */
1400Sstevel@tonic-gate 						/* removed from v9 ABI */
1410Sstevel@tonic-gate /* R_SPARC_7 */		{0x0, FLG_RE_NOTREL, 4, 0, 7},
1420Sstevel@tonic-gate /* R_SPARC_5 */		{0x0, FLG_RE_NOTREL, 4, 0, 5},
1430Sstevel@tonic-gate /* R_SPARC_6 */		{0x0, FLG_RE_NOTREL, 4, 0, 6},
1440Sstevel@tonic-gate /* R_SPARC_DISP64 */	{0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN,
1450Sstevel@tonic-gate 				8, 0, 0},
1460Sstevel@tonic-gate /* R_SPARC_PLT64 */	{0x0, FLG_RE_PLTREL | FLG_RE_VERIFY |
1470Sstevel@tonic-gate 				FLG_RE_ADDRELATIVE, 8, 0, 0},
1481618Srie /* R_SPARC_HIX22 */	{(Xword)(-1LL), FLG_RE_VERIFY,
1491618Srie 				4, 10, 22},			/* V9 - HaL */
1501169Srie /* R_SPARC_LOX10 */	{0x3ff, FLG_RE_SIGN, 4, 0, 13},		/* V9 - HaL */
1511169Srie /* R_SPARC_H44 */	{0x0, FLG_RE_VERIFY, 4, 22, 22},	/* V9 */
1520Sstevel@tonic-gate /* R_SPARC_M44 */	{0x3ff, FLG_RE_NOTREL, 4, 12, 10},	/* V9 */
1530Sstevel@tonic-gate /* R_SPARC_L44 */	{0xfff, FLG_RE_NOTREL, 4, 0, 13},	/* V9 */
1541169Srie /* R_SPARC_REGISTER */	{0x0, FLG_RE_REGISTER, 0, 0, 0},	/* SPECIAL */
1551169Srie /* R_SPARC_UA64 */	{0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
1561169Srie 				8, 0, 0},			/* V9 */
1571169Srie /* R_SPARC_UA16 */	{0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN,
1580Sstevel@tonic-gate 				2, 0, 0},
1592145Srie /* R_SPARC_TLS_GD_HI22 */   {0x0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 10, 22},
1602145Srie /* R_SPARC_TLS_GD_LO10 */   {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSGD |
1612145Srie 				FLG_RE_SIGN, 4, 0, 13},
1622145Srie /* R_SPARC_TLS_GD_ADD */    {0x0, FLG_RE_TLSGD, 0, 0, 0},
1632145Srie /* R_SPARC_TLS_GD_CALL */   {0x0, FLG_RE_TLSGD, 0, 0, 0},
1642145Srie /* R_SPARC_TLS_LDM_HI22 */  {0x0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 10, 22},
1652145Srie /* R_SPARC_TLS_LDM_LO10 */  {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSLD |
1662145Srie 				FLG_RE_SIGN, 4, 0, 13},
1672145Srie /* R_SPARC_TLS_LDM_ADD */   {0x0, FLG_RE_TLSLD, 0, 0, 0},
1682145Srie /* R_SPARC_TLS_LDM_CALL */  {0x0, FLG_RE_TLSLD, 0, 0, 0},
1692145Srie /* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSLD, 4, 10, 22},
1702145Srie /* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLD, 4, 0, 13},
1712145Srie /* R_SPARC_TLS_LDO_ADD */   {0x0, FLG_RE_TLSLD, 0, 0, 0},
1722145Srie /* R_SPARC_TLS_IE_HI22 */   {0x0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 10, 22},
1732145Srie /* R_SPARC_TLS_IE_LO10 */   {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSIE |
1742145Srie 				FLG_RE_SIGN, 4, 0, 13},
1752145Srie /* R_SPARC_TLS_IE_LD */	    {0x0, FLG_RE_TLSIE, 0, 0, 0},
1762145Srie /* R_SPARC_TLS_IE_LDX */    {0x0, FLG_RE_TLSIE, 0, 0, 0},
1772145Srie /* R_SPARC_TLS_IE_ADD */    {0x0, FLG_RE_TLSIE, 0, 0, 0},
1781169Srie /* R_SPARC_TLS_LE_HIX22 */  {(Xword)(-1LL),
1792145Srie 				FLG_RE_VERIFY | FLG_RE_TLSLE, 4, 10, 22},
1802145Srie /* R_SPARC_TLS_LE_LOX10 */  {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLE, 4, 0, 13},
1810Sstevel@tonic-gate /* R_SPARC_TLS_DTPMOD32 */  {0x0, FLG_RE_NOTREL, 4, 0, 0},
1820Sstevel@tonic-gate /* R_SPARC_TLS_DTPMOD64 */  {0x0, FLG_RE_NOTREL, 8, 0, 0},
1830Sstevel@tonic-gate /* R_SPARC_TLS_DTPOFF32 */  {0x0, FLG_RE_NOTREL, 4, 0, 0},
1840Sstevel@tonic-gate /* R_SPARC_TLS_DTPOFF64 */  {0x0, FLG_RE_NOTREL, 8, 0, 0},
1850Sstevel@tonic-gate /* R_SPARC_TLS_TPOFF32 */   {0x0, FLG_RE_NOTREL, 4, 0, 0},
1860Sstevel@tonic-gate /* R_SPARC_TLS_TPOFF64 */   {0x0, FLG_RE_NOTREL, 8, 0, 0},
1873304Srie /* R_SPARC_GOTDATA_HIX22 */	{0, FLG_RE_SIGN | FLG_RE_GOTREL |
1883304Srie 					FLG_RE_VERIFY, 4, 10, 22},
1890Sstevel@tonic-gate /* R_SPARC_GOTDATA_LOX10 */	{ 0x3ff, FLG_RE_GOTREL | FLG_RE_SIGN, 4, 0, 13},
1900Sstevel@tonic-gate /* R_SPARC_GOTDATA_OP_HIX22 */	{ 0x0, FLG_RE_GOTOPINS | FLG_RE_GOTADD,
1910Sstevel@tonic-gate 					4, 10, 22},
1920Sstevel@tonic-gate /* R_SPARC_GOTDATA_OP_LOX10 */	{ 0x3ff, FLG_RE_SIGN | FLG_RE_GOTOPINS |
1930Sstevel@tonic-gate 					FLG_RE_GOTADD, 4, 0, 13},
1940Sstevel@tonic-gate /* R_SPARC_GOTDATA_OP */	{ 0x0, FLG_RE_GOTOPINS, 0, 0, 0},
1952850Srie /* R_SPARC_H34 */	{0x0, FLG_RE_VERIFY, 4, 12, 22},	/* V9 */
1962850Srie /* R_SPARC_SIZE32 */	{0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0},
1972850Srie /* R_SPARC_SIZE64 */	{0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 8, 0, 0},
1980Sstevel@tonic-gate };
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate  * Write a single relocated value to its reference location.
2030Sstevel@tonic-gate  * We assume we wish to add the relocation amount, value, to the
2041169Srie  * value of the address already present in the instruction.
2050Sstevel@tonic-gate  *
2061169Srie  * NAME			 VALUE	FIELD		CALCULATION
2070Sstevel@tonic-gate  *
2081169Srie  * R_SPARC_NONE		     0	none		none
2091169Srie  * R_SPARC_8		     1	V-byte8		S + A
2101169Srie  * R_SPARC_16		     2	V-half16	S + A
2111169Srie  * R_SPARC_32		     3	V-word32	S + A
2121169Srie  * R_SPARC_DISP8	     4	V-byte8		S + A - P
2131169Srie  * R_SPARC_DISP16	     5	V-half16	S + A - P
2141169Srie  * R_SPARC_DISP32	     6	V-word32	S + A - P
2151169Srie  * R_SPARC_WDISP30	     7	V-disp30	(S + A - P) >> 2
2161169Srie  * R_SPARC_WDISP22	     8	V-disp22	(S + A - P) >> 2
2171169Srie  * R_SPARC_HI22		     9	T-imm22		(S + A) >> 10
2181169Srie  * R_SPARC_22		    10	V-imm22		S + A
2191169Srie  * R_SPARC_13		    11	V-simm13	S + A
2201169Srie  * R_SPARC_LO10		    12	T-simm13	(S + A) & 0x3ff
2211169Srie  * R_SPARC_GOT10	    13	T-simm13	G & 0x3ff
2221169Srie  * R_SPARC_GOT13	    14	V-simm13	G
2231169Srie  * R_SPARC_GOT22	    15	T-imm22		G >> 10
2241169Srie  * R_SPARC_PC10		    16	T-simm13	(S + A - P) & 0x3ff
2251169Srie  * R_SPARC_PC22		    17	V-disp22	(S + A - P) >> 10
2261169Srie  * R_SPARC_WPLT30	    18	V-disp30	(L + A - P) >> 2
2271169Srie  * R_SPARC_COPY		    19	none		none
2281169Srie  * R_SPARC_GLOB_DAT	    20	V-word32	S + A
2291169Srie  * R_SPARC_JMP_SLOT	    21	V-plt22		S + A
2301169Srie  * R_SPARC_RELATIVE	    22	V-word32	S + A
2311169Srie  * R_SPARC_UA32		    23	V-word32	S + A
2321169Srie  * R_SPARC_PLT32	    24	V-word32        L + A
2331169Srie  * R_SPARC_HIPLT22	    25	T-imm22         (L + A) >> 10
2341169Srie  * R_SPARC_LOPLT10	    26	T-simm13        (L + A) & 0x3ff
2351169Srie  * R_SPARC_PCPLT32	    27	V-word32        L + A - P
2361169Srie  * R_SPARC_PCPLT22	    28	V-disp22        (L + A - P) >> 10
2371169Srie  * R_SPARC_PCPLT10	    29	V-simm13        (L + A - P) & 0x3ff
2381169Srie  * R_SPARC_10		    30	V-simm10	S + A
2391169Srie  * R_SPARC_11		    31	V-simm11	S + A
2401169Srie  * R_SPARC_64		    32	V-xword64	S + A
2411169Srie  * R_SPARC_OLO10	    33	V-simm13	((S + A) & 0x3ff) + O
2421169Srie  * R_SPARC_HH22		    34	V-imm22		(S + A) >> 42
2431169Srie  * R_SPARC_HM10		    35	T-simm13	((S + A) >> 32) & 0x3ff
2441169Srie  * R_SPARC_LM22		    36	T-imm22		(S + A) >> 10
2451169Srie  * R_SPARC_PC_HH22	    37	V-imm22		(S + A - P) >> 42
2461169Srie  * R_SPARC_PC_HM10	    38	T-simm13	((S + A - P) >> 32) & 0x3ff
2471169Srie  * R_SPARC_PC_LM22	    39	T-imm22		(S + A - P) >> 10
2481169Srie  * R_SPARC_WDISP16	    40	V-d2/disp14	(S + A - P) >> 2
2491169Srie  * R_SPARC_WDISP19	    41	V-disp19	(S + A - P) >> 2
2501169Srie  * R_SPARC_GLOB_JMP	    42	V-xword64	S + A
2511169Srie  * R_SPARC_7		    43	V-imm7		S + A
2521169Srie  * R_SPARC_5		    44	V-imm5		S + A
2531169Srie  * R_SPARC_6		    45	V-imm6		S + A
2541169Srie  * R_SPARC_DISP64	    46	V-xword64	S + A - P
2551169Srie  * R_SPARC_PLT64	    47	V-xword64	L + A
2561169Srie  * R_SPARC_HIX22	    48	V-imm22		((S + A) ^
2571169Srie  *						    0xffffffffffffffff) >> 10
2581169Srie  * R_SPARC_LOX10	    49	T-simm13	((S + A) & 0x3ff) | 0x1c00
2591169Srie  * R_SPARC_H44		    50	V-imm22		(S + A) >> 22
2601169Srie  * R_SPARC_M44		    51	T-imm10		((S + A) >> 12) & 0x3ff
2611169Srie  * R_SPARC_L44		    52	T-imm13		(S + A) & 0xfff
2621169Srie  * R_SPARC_REGISTER	    53	V-xword64	S + A
2631169Srie  * R_SPARC_UA64		    54	V-xword64	S + A
2641169Srie  * R_SPARC_UA16		    55	V-half16	S + A
2651169Srie  * R_SPARC_TLS_GD_HI22	    56	T-simm22	@dtlndx(S + A) >> 10
2661169Srie  * R_SPARC_TLS_GD_LO10	    57	T-simm13	@dtlndx(S + A) & 0x3ff
2671169Srie  * R_SPARC_TLS_GD_ADD	    58	none		SPECIAL
2681169Srie  * R_SPARC_TLS_GD_CALL	    59	V-disp30	SPECIAL
2691169Srie  * R_SPARC_TLS_LDM_HI22	    60	T-simm22	@tmndx(S + A) >> 10
2701169Srie  * R_SPARC_TLS_LDM_LO10	    61	T-simm13	@tmndx(S + A) & 0x3ff
2711169Srie  * R_SPARC_TLS_LDM_ADD	    62	none		SPECIAL
2721169Srie  * R_SPARC_TLS_LDM_CALL	    63	V-disp30	SPECIAL
2731169Srie  * R_SPARC_TLS_LDO_HIX22    64	V-simm22	@dtpoff(S + A) >> 10
2741169Srie  * R_SPARC_TLS_LDO_LOX10    65	T-simm13	@dtpoff(S + A) & 0x3ff
2751169Srie  * R_SPARC_TLS_LDO_ADD	    66	none		SPECIAL
2761169Srie  * R_SPARC_TLS_IE_HI22	    67	T-simm22	@got(@tpoff(S + A)) >> 10
2771169Srie  * R_SPARC_TLS_IE_LO10	    68	T-simm13	@got(@tpoff(S + A)) & 0x3ff
2781169Srie  * R_SPARC_TLS_IE_LD	    69	none		SPECIAL
2791169Srie  * R_SPARC_TLS_IE_LDX	    70	none		SPECIAL
2801169Srie  * R_SPARC_TLS_IE_ADD	    71	none		SPECIAL
2811169Srie  * R_SPARC_TLS_LE_HIX22	    72	V-simm22	(@tpoff(S + A) ^
2821169Srie  *						    0xffffffff) >> 10
2831169Srie  * R_SPARC_TLS_LE_LOX10	    73	T-simm13	(@tpoff(S + A) & 0x3ff) | 0x1c00
2841169Srie  * R_SPARC_TLS_DTPMOD32	    74	V-word32	@dtmod(S + A)
2851169Srie  * R_SPARC_TLS_DTPMOD64	    75	V-word64	@dtmod(S + A)
2861169Srie  * R_SPARC_TLS_DTPOFF32	    76	V-word32	@dtpoff(S + A)
2871169Srie  * R_SPARC_TLS_DTPOFF64	    77	V-word64	@dtpoff(S + A)
2881169Srie  * R_SPARC_TLS_TPOFF32	    78	V-word32	@tpoff(S + A)
2891169Srie  * R_SPARC_TLS_TPOFF64	    79	V-word64	@tpoff(S + A)
2903304Srie  * R_SPARC_GOTDATA_HIX22    80	V-imm22		((S + A - GOT) >> 10) ^
2911169Srie  *						  ((S + A - GOT) >> 31)
2921169Srie  * R_SPARC_GOTDATA_LOX10    81	T-simm13	((S + A - GOT) & 0x3ff) |
2931169Srie  *						  (((S + A - GOT) >> 31) &
2941169Srie  *						  0x1c00)
2951169Srie  * R_SPARC_GOTDATA_OP_HIX22 82	T-imm22		(G >> 10) & (G >> 31)
2961169Srie  * R_SPARC_GOTDATA_OP_LOX10 83	T-simm13	(G & 0x3ff) |
2971169Srie  *						  ((G >> 31) & 0x1c00)
2982850Srie  * R_SPARC_GOTDATA_OP	    84  Word32		SPECIAL
2992850Srie  * R_SPARC_H34		    85	V-imm22		(S + A) >> 12
3002850Srie  * R_SPARC_SIZE32	    86	V-word32	Z + A
3012850Srie  * R_SPARC_SIZE64	    87	V-xword64	Z + A
3020Sstevel@tonic-gate  *
3030Sstevel@tonic-gate  *	This is Figure 4-20: Relocation Types from the Draft Copy of
3040Sstevel@tonic-gate  * the ABI, Printed on 11/29/88.
3050Sstevel@tonic-gate  *
3060Sstevel@tonic-gate  * NOTE1: relocations 24->45 are newly registered relocations to support
3070Sstevel@tonic-gate  *	 C++ ABI & SPARC V8+ and SPARC V9 architectures (1/9/94), and
3080Sstevel@tonic-gate  *	 64-bit relocations 46-55 were added for SPARC V9.
3090Sstevel@tonic-gate  *
3100Sstevel@tonic-gate  * NOTE2: relocations 56->79 are added to support Thread-Local storage
3110Sstevel@tonic-gate  *	  as recorded in PSARC/2001/509
3120Sstevel@tonic-gate  *
3130Sstevel@tonic-gate  * NOTE3: The value to be passed for relocations R_SPARC_HIX22 and
3140Sstevel@tonic-gate  *	  R_SPARC_TLS_HIX22 are negative values. So the upper 10 or 40 bits
3150Sstevel@tonic-gate  *	  are 1. (So when the exclusive OR is applied, the upper bits
3160Sstevel@tonic-gate  *	  will be 0.)
3170Sstevel@tonic-gate  *
3180Sstevel@tonic-gate  * Relocation calculations:
3190Sstevel@tonic-gate  *
3200Sstevel@tonic-gate  * The FIELD names indicate whether the relocation type checks for overflow.
3210Sstevel@tonic-gate  * A calculated relocation value may be larger than the intended field, and
3220Sstevel@tonic-gate  * the relocation type may verify (V) that the value fits, or truncate (T)
3230Sstevel@tonic-gate  * the result.
3240Sstevel@tonic-gate  *
3250Sstevel@tonic-gate  * CALCULATION uses the following notation:
3260Sstevel@tonic-gate  *      A       the addend used
3270Sstevel@tonic-gate  *      B       the base address of the shared object in memory
3280Sstevel@tonic-gate  *      G       the offset into the global offset table
3290Sstevel@tonic-gate  *      L       the procedure linkage entry
3300Sstevel@tonic-gate  *      P       the place of the storage unit being relocated
3310Sstevel@tonic-gate  *      S       the value of the symbol
3320Sstevel@tonic-gate  *	O	secondary addend (extra offset) in v9 r_info field
3332850Srie  *	Z	the size of the symbol whose index resides in the relocation
3342850Srie  *		entry
3350Sstevel@tonic-gate  *
3360Sstevel@tonic-gate  *	@dtlndx(x): Allocate two contiguous entries in the GOT table to hold
3370Sstevel@tonic-gate  *	   a Tls_index structure (for passing to __tls_get_addr()). The
3380Sstevel@tonic-gate  *	   instructions referencing this entry will be bound to the first
3390Sstevel@tonic-gate  *	   of the two GOT entries.
3400Sstevel@tonic-gate  *
3410Sstevel@tonic-gate  *	@tmndx(x): Allocate two contiguous entries in the GOT table to hold
3420Sstevel@tonic-gate  *	   a Tls_index structure (for passing to __tls_get_addr()). The
3430Sstevel@tonic-gate  *	   ti_offset field of the Tls_index will be set to 0 (zero) and the
3440Sstevel@tonic-gate  *	   ti_module will be filled in at run-time. The call to
3450Sstevel@tonic-gate  *	   __tls_get_addr() will return the starting offset of the dynamic
3460Sstevel@tonic-gate  *	   TLS block.
3470Sstevel@tonic-gate  *
3480Sstevel@tonic-gate  *	@dtpoff(x): calculate the tlsoffset relative to the TLS block.
3490Sstevel@tonic-gate  *
3500Sstevel@tonic-gate  *	@tpoff(x): calculate the negative tlsoffset relative to the static
3510Sstevel@tonic-gate  *	   TLS block. This value can be added to the thread-pointer to
3520Sstevel@tonic-gate  *	   calculate the tls address.
3530Sstevel@tonic-gate  *
3540Sstevel@tonic-gate  *	@dtpmod(x): calculate the module id of the object containing symbol x.
3550Sstevel@tonic-gate  *
3560Sstevel@tonic-gate  * The calculations in the CALCULATION column are assumed to have been performed
3570Sstevel@tonic-gate  * before calling this function except for the addition of the addresses in the
3580Sstevel@tonic-gate  * instructions.
3590Sstevel@tonic-gate  *
3600Sstevel@tonic-gate  * Upon successful completion of do_reloc() *value will be set to the
3610Sstevel@tonic-gate  * 'bit-shifted' value that will be or'ed into memory.
3620Sstevel@tonic-gate  */
3635189Sab196087 #if defined(_KERNEL)
3645189Sab196087 #define	lml	0		/* Needed by arglist of REL_ERR_* macros */
3655189Sab196087 int
do_reloc_krtld(uchar_t rtype,uchar_t * off,Xword * value,const char * sym,const char * file)3665189Sab196087 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
3675189Sab196087     const char *file)
3685189Sab196087 #elif defined(DO_RELOC_LIBLD)
3696206Sab196087 /*ARGSUSED5*/
3700Sstevel@tonic-gate int
371*12155SAli.Bahrami@Sun.COM do_reloc_ld(Rel_desc *rdesc, uchar_t *off, Xword *value,
372*12155SAli.Bahrami@Sun.COM     rel_desc_sname_func_t rel_desc_sname_func,
3735189Sab196087     const char *file, int bswap, void *lml)
3745189Sab196087 #else
3755189Sab196087 int
3765189Sab196087 do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
3771618Srie     const char *file, void *lml)
3785189Sab196087 #endif
3790Sstevel@tonic-gate {
380*12155SAli.Bahrami@Sun.COM #ifdef DO_RELOC_LIBLD
381*12155SAli.Bahrami@Sun.COM #define	sym (* rel_desc_sname_func)(rdesc)
382*12155SAli.Bahrami@Sun.COM 	uchar_t	rtype = rdesc->rel_rtype;
383*12155SAli.Bahrami@Sun.COM #endif
3846206Sab196087 	Xword	uvalue = 0;
3856206Sab196087 	Xword	basevalue, sigbit_mask, sigfit_mask;
3866206Sab196087 	Xword	corevalue = *value;
3876206Sab196087 	uchar_t	bshift;
3886206Sab196087 	int	field_size, re_flags;
3896206Sab196087 	const	Rel_entry	*rep;
3905189Sab196087 
3910Sstevel@tonic-gate 	rep = &reloc_table[rtype];
3920Sstevel@tonic-gate 	bshift = rep->re_bshift;
3930Sstevel@tonic-gate 	field_size = rep->re_fsize;
3940Sstevel@tonic-gate 	re_flags = rep->re_flags;
3950Sstevel@tonic-gate 	sigbit_mask = S_MASK(rep->re_sigbits);
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	if ((re_flags & FLG_RE_SIGN) && sigbit_mask) {
3980Sstevel@tonic-gate 		/*
3990Sstevel@tonic-gate 		 * sigfit_mask takes into account that a value
4000Sstevel@tonic-gate 		 * might be signed and discards the signbit for
4010Sstevel@tonic-gate 		 * comparison.
4020Sstevel@tonic-gate 		 */
4030Sstevel@tonic-gate 		sigfit_mask = S_MASK(rep->re_sigbits - 1);
4040Sstevel@tonic-gate 	} else
4050Sstevel@tonic-gate 		sigfit_mask = sigbit_mask;
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	if (field_size == 0) {
4081618Srie 		REL_ERR_UNIMPL(lml, file, sym, rtype);
4090Sstevel@tonic-gate 		return (0);
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 
4126206Sab196087 	/*
4136206Sab196087 	 * We have two ways to retrieve the base value, a general one
4146206Sab196087 	 * that will work with data of any alignment, and another that is
4156206Sab196087 	 * fast, but which requires the data to be aligned according to
4166206Sab196087 	 * sparc alignment rules.
4176206Sab196087 	 *
4186206Sab196087 	 * For non-native linking, we always use the general path. For
4196206Sab196087 	 * native linking, the FLG_RE_UNALIGN determines it.
4206206Sab196087 	 */
4216206Sab196087 #if defined(DORELOC_NATIVE)
4226206Sab196087 	if (re_flags & FLG_RE_UNALIGN)
4236206Sab196087 #endif
4246206Sab196087 	{
4251169Srie 		int	i;
4261169Srie 		uchar_t	*dest = (uchar_t *)&basevalue;
4270Sstevel@tonic-gate 
4286206Sab196087 		basevalue = 0;
4296206Sab196087 #if !defined(DORELOC_NATIVE)
4306206Sab196087 		if (bswap) {
4316206Sab196087 			int j = field_size - 1;
4326206Sab196087 
4336206Sab196087 			for (i = 0; i < field_size; i++, j--)
4346206Sab196087 				dest[i] = off[j];
4350Sstevel@tonic-gate 
4366206Sab196087 		} else
4376206Sab196087 #endif
4386206Sab196087 		{
4396206Sab196087 			/*
4406206Sab196087 			 * Adjust the offset
4416206Sab196087 			 */
4426206Sab196087 			/* LINTED */
4436206Sab196087 			i = (int)(sizeof (Xword) - field_size);
4446206Sab196087 			if (i > 0)
4456206Sab196087 				dest += i;
4466206Sab196087 			for (i = field_size - 1; i >= 0; i--)
4476206Sab196087 				dest[i] = off[i];
4486206Sab196087 		}
4496206Sab196087 	}
4506206Sab196087 
4516206Sab196087 	/*
4526206Sab196087 	 * Non-native linker: We have already fetched the value above,
4536206Sab196087 	 *	but if the relocation does not have the FLG_RE_UNALIGN
4546206Sab196087 	 *	flag set, we still need to do the same error checking we
4556206Sab196087 	 *	would do on a native linker.
4566206Sab196087 	 * Native-linker: If this is an aligned relocation, we need to
4576206Sab196087 	 *	fetch the value and also do the error checking.
4586206Sab196087 	 *
4596206Sab196087 	 * The FETCH macro is used to conditionalize the fetching so that
4606206Sab196087 	 * it only happens in the native case.
4616206Sab196087 	 */
4626206Sab196087 #if defined(DORELOC_NATIVE)
4636206Sab196087 #define	FETCH(_type) basevalue = (Xword)*((_type *)off);
4646206Sab196087 #else
4656206Sab196087 #define	FETCH(_type)
4666206Sab196087 #endif
4676206Sab196087 	if ((re_flags & FLG_RE_UNALIGN) == 0) {
4681048Sraf 		if (((field_size == 2) && ((uintptr_t)off & 0x1)) ||
4691048Sraf 		    ((field_size == 4) && ((uintptr_t)off & 0x3)) ||
4701048Sraf 		    ((field_size == 8) && ((uintptr_t)off & 0x7))) {
4711618Srie 			REL_ERR_NONALIGN(lml, file, sym, rtype, (uintptr_t)off);
4720Sstevel@tonic-gate 			return (0);
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate 		switch (field_size) {
4750Sstevel@tonic-gate 		case 1:
4766206Sab196087 			/* LINTED */
4776206Sab196087 			FETCH(uchar_t);
4780Sstevel@tonic-gate 			break;
4790Sstevel@tonic-gate 		case 2:
4800Sstevel@tonic-gate 			/* LINTED */
4816206Sab196087 			FETCH(Half);
4820Sstevel@tonic-gate 			break;
4830Sstevel@tonic-gate 		case 4:
4840Sstevel@tonic-gate 			/* LINTED */
4856206Sab196087 			FETCH(Word);
4860Sstevel@tonic-gate 			break;
4870Sstevel@tonic-gate 		case 8:
4880Sstevel@tonic-gate 			/* LINTED */
4896206Sab196087 			FETCH(Xword);
4900Sstevel@tonic-gate 			break;
4910Sstevel@tonic-gate 		default:
4921618Srie 			REL_ERR_UNNOBITS(lml, file, sym, rtype,
4931618Srie 			    (rep->re_fsize * 8));
4940Sstevel@tonic-gate 			return (0);
4950Sstevel@tonic-gate 		}
4960Sstevel@tonic-gate 	}
4976206Sab196087 #undef FETCH
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	if (sigbit_mask) {
5000Sstevel@tonic-gate 		/*
5010Sstevel@tonic-gate 		 * The WDISP16 relocation is an unusual one in that it's bits
5020Sstevel@tonic-gate 		 * are not all contiguous.  We have to selectivly pull them out.
5030Sstevel@tonic-gate 		 */
5040Sstevel@tonic-gate 		if (re_flags & FLG_RE_WDISP16) {
5050Sstevel@tonic-gate 			uvalue = ((basevalue & 0x300000) >> 6) |
5065648Ssetje 			    (basevalue & 0x3fff);
5070Sstevel@tonic-gate 			basevalue &= ~0x303fff;
5080Sstevel@tonic-gate 		} else {
5090Sstevel@tonic-gate 			uvalue = sigbit_mask & basevalue;
5100Sstevel@tonic-gate 			basevalue &= ~sigbit_mask;
5110Sstevel@tonic-gate 		}
5120Sstevel@tonic-gate 		/*
5130Sstevel@tonic-gate 		 * If value is signed make sure that we signextend the uvalue.
5140Sstevel@tonic-gate 		 */
5150Sstevel@tonic-gate 		if (re_flags & FLG_RE_SIGN) {
5160Sstevel@tonic-gate 			if (uvalue & (~sigbit_mask & sigfit_mask))
5170Sstevel@tonic-gate 				uvalue |= ~sigbit_mask;
5180Sstevel@tonic-gate 		}
5190Sstevel@tonic-gate 	} else
5200Sstevel@tonic-gate 		uvalue = basevalue;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	if (bshift)
5230Sstevel@tonic-gate 		uvalue <<= bshift;
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 	uvalue += *value;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	if (rep->re_mask &&
5280Sstevel@tonic-gate 	    ((rtype == R_SPARC_HIX22) || (rtype == R_SPARC_TLS_LE_HIX22)))
5290Sstevel@tonic-gate 		uvalue ^= rep->re_mask;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	if (bshift) {
5320Sstevel@tonic-gate 		/*
5330Sstevel@tonic-gate 		 * This is to check that we are not attempting to
5340Sstevel@tonic-gate 		 * jump to a non-4 byte aligned address.
5350Sstevel@tonic-gate 		 */
5360Sstevel@tonic-gate 		if ((bshift == 2) && (uvalue & 0x3)) {
5371618Srie 			REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, 2, off);
5380Sstevel@tonic-gate 			return (0);
5390Sstevel@tonic-gate 		}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 		if (re_flags & FLG_RE_SIGN) {
5420Sstevel@tonic-gate 			uvalue = (Sxword)uvalue >> bshift;
5430Sstevel@tonic-gate 		} else {
5440Sstevel@tonic-gate 			uvalue >>= bshift;
5450Sstevel@tonic-gate 		}
5460Sstevel@tonic-gate 		corevalue >>= bshift;
5470Sstevel@tonic-gate 	}
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	if ((rtype == R_SPARC_GOTDATA_HIX22) ||
5500Sstevel@tonic-gate 	    (rtype == R_SPARC_GOTDATA_OP_HIX22)) {
5510Sstevel@tonic-gate 		uvalue ^= ((Sxword)(*value) >> 31);
5520Sstevel@tonic-gate 		corevalue ^= ((Sxword)(*value) >> 31);
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	if (rep->re_mask &&
5560Sstevel@tonic-gate 	    (rtype != R_SPARC_HIX22) && (rtype != R_SPARC_TLS_LE_HIX22) &&
5570Sstevel@tonic-gate 	    (rtype != R_SPARC_GOTDATA_HIX22))
5580Sstevel@tonic-gate 		uvalue &= rep->re_mask;
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	if ((rtype == R_SPARC_LOX10) || (rtype == R_SPARC_TLS_LE_LOX10)) {
5610Sstevel@tonic-gate 		uvalue |= 0x1c00;
5620Sstevel@tonic-gate 		corevalue |= 0x1c00;
5630Sstevel@tonic-gate 	}
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if ((rtype == R_SPARC_GOTDATA_LOX10) ||
5660Sstevel@tonic-gate 	    (rtype == R_SPARC_GOTDATA_OP_LOX10)) {
5670Sstevel@tonic-gate 		uvalue |= ((Sxword)(*value) >> 31) & 0x1c00;
5680Sstevel@tonic-gate 		corevalue |= ((Sxword)(*value) >> 31) & 0x1c00;
5690Sstevel@tonic-gate 	}
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	if ((re_flags & FLG_RE_VERIFY) && sigbit_mask) {
5730Sstevel@tonic-gate 		if (((re_flags & FLG_RE_SIGN) &&
5740Sstevel@tonic-gate 		    (S_INRANGE((Sxword)uvalue, rep->re_sigbits - 1) == 0)) ||
5750Sstevel@tonic-gate 		    (!(re_flags & FLG_RE_SIGN) &&
5760Sstevel@tonic-gate 		    ((sigbit_mask & uvalue) != uvalue))) {
5771618Srie 			REL_ERR_NOFIT(lml, file, sym, rtype, uvalue);
5780Sstevel@tonic-gate 			return (0);
5790Sstevel@tonic-gate 		}
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	if (sigbit_mask) {
5830Sstevel@tonic-gate 		/*
5840Sstevel@tonic-gate 		 * Again the R_SPARC_WDISP16 relocation takes special
5850Sstevel@tonic-gate 		 * processing because of its non-continguous bits.
5860Sstevel@tonic-gate 		 */
5870Sstevel@tonic-gate 		if (re_flags & FLG_RE_WDISP16)
5880Sstevel@tonic-gate 			uvalue = ((uvalue & 0xc000) << 6) |
5895648Ssetje 			    (uvalue & 0x3fff);
5900Sstevel@tonic-gate 		else
5910Sstevel@tonic-gate 			uvalue &= sigbit_mask;
5920Sstevel@tonic-gate 		/*
5930Sstevel@tonic-gate 		 * Combine value back with original word
5940Sstevel@tonic-gate 		 */
5950Sstevel@tonic-gate 		uvalue |= basevalue;
5960Sstevel@tonic-gate 	}
5970Sstevel@tonic-gate 	*value = corevalue;
5980Sstevel@tonic-gate 
5996206Sab196087 	/*
6006206Sab196087 	 * Now, we store uvalue back at the location given by off.
6016206Sab196087 	 * This is similar to the fetch case above:
6026206Sab196087 	 *	- We have general (unaligned) and fast (aligned) cases
6036206Sab196087 	 *	- Cross linkers need to use the unaligned case even
6046206Sab196087 	 *		when the relocation does not specify FLG_RE_UNALIGN.
6056206Sab196087 	 *	- A cross linker that processes a relocation that does not
6066206Sab196087 	 *		have FLG_RE_UNALIGN set has to do the same error
6076206Sab196087 	 *		checking that a native linker would do, while avoiding
6086206Sab196087 	 *		the aligned store (accomplished with the STORE macro).
6096206Sab196087 	 */
6106206Sab196087 #if defined(DORELOC_NATIVE)
6116206Sab196087 	if (re_flags & FLG_RE_UNALIGN)
6126206Sab196087 #endif
6136206Sab196087 	{
6141169Srie 		int	i;
6151169Srie 		uchar_t	*src = (uchar_t *)&uvalue;
6160Sstevel@tonic-gate 
6176206Sab196087 #if !defined(DORELOC_NATIVE)
6186206Sab196087 		if (bswap) {
6196206Sab196087 			int j = field_size - 1;
6206206Sab196087 
6216206Sab196087 			for (i = 0; i < field_size; i++, j--)
6226206Sab196087 				off[i] = src[j];
6230Sstevel@tonic-gate 
6246206Sab196087 		} else
6256206Sab196087 #endif
6266206Sab196087 		{
6276206Sab196087 			/*
6286206Sab196087 			 * Adjust the offset.
6296206Sab196087 			 */
6306206Sab196087 			/* LINTED */
6316206Sab196087 			i = (int)(sizeof (Xword) - field_size);
6326206Sab196087 			if (i > 0)
6336206Sab196087 				src += i;
6346206Sab196087 			for (i = field_size - 1; i >= 0; i--)
6356206Sab196087 				off[i] = src[i];
6366206Sab196087 		}
6376206Sab196087 	}
6386206Sab196087 
6396206Sab196087 #if defined(DORELOC_NATIVE)
6406206Sab196087 #define	STORE(_type) *((_type *)off) = (_type)uvalue
6416206Sab196087 #else
6426206Sab196087 #define	STORE(_type)
6436206Sab196087 #endif
6446206Sab196087 	if ((re_flags & FLG_RE_UNALIGN) == 0) {
6450Sstevel@tonic-gate 		switch (rep->re_fsize) {
6460Sstevel@tonic-gate 		case 1:
6471169Srie 			/* LINTED */
6486206Sab196087 			STORE(uchar_t);
6490Sstevel@tonic-gate 			break;
6500Sstevel@tonic-gate 		case 2:
6510Sstevel@tonic-gate 			/* LINTED */
6526206Sab196087 			STORE(Half);
6530Sstevel@tonic-gate 			break;
6540Sstevel@tonic-gate 		case 4:
6550Sstevel@tonic-gate 			/* LINTED */
6566206Sab196087 			STORE(Word);
6570Sstevel@tonic-gate 			break;
6580Sstevel@tonic-gate 		case 8:
6590Sstevel@tonic-gate 			/* LINTED */
6606206Sab196087 			STORE(Xword);
6610Sstevel@tonic-gate 			break;
6621169Srie 		default:
6631169Srie 			/*
6641169Srie 			 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
6651169Srie 			 */
6661618Srie 			REL_ERR_UNSUPSZ(lml, file, sym, rtype, rep->re_fsize);
6671169Srie 			return (0);
6680Sstevel@tonic-gate 		}
6690Sstevel@tonic-gate 	}
6706206Sab196087 #undef STORE
6716206Sab196087 
6720Sstevel@tonic-gate 	return (1);
673*12155SAli.Bahrami@Sun.COM 
674*12155SAli.Bahrami@Sun.COM #ifdef DO_RELOC_LIBLD
675*12155SAli.Bahrami@Sun.COM #undef sym
676*12155SAli.Bahrami@Sun.COM #endif
6770Sstevel@tonic-gate }
678