xref: /onnv-gate/usr/src/uts/intel/amd64/krtld/doreloc.c (revision 1169:c1bfcc795896)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*1169Srie 
230Sstevel@tonic-gate /*
240Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #if	defined(_KERNEL)
310Sstevel@tonic-gate #include	<sys/types.h>
320Sstevel@tonic-gate #include	"reloc.h"
330Sstevel@tonic-gate #else
340Sstevel@tonic-gate #include	<stdio.h>
350Sstevel@tonic-gate #include	"sgs.h"
360Sstevel@tonic-gate #include	"machdep.h"
370Sstevel@tonic-gate #include	"libld.h"
380Sstevel@tonic-gate #include	"reloc.h"
390Sstevel@tonic-gate #include	"conv.h"
400Sstevel@tonic-gate #include	"msg.h"
410Sstevel@tonic-gate #endif
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
44*1169Srie  * This table represents the current relocations that do_reloc() is able to
45*1169Srie  * process.  The relocations below that are marked SPECIAL are relocations that
46*1169Srie  * take special processing and shouldn't actually ever be passed to do_reloc().
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate const Rel_entry	reloc_table[R_AMD64_NUM] = {
49*1169Srie /* R_AMD64_NONE */	{FLG_RE_NOTREL, 0},
500Sstevel@tonic-gate /* R_AMD64_64 */	{FLG_RE_NOTREL, 8},
510Sstevel@tonic-gate /* R_AMD64_PC32 */	{FLG_RE_PCREL, 4},
520Sstevel@tonic-gate /* R_AMD64_GOT32 */	{FLG_RE_NOTSUP, 0},
530Sstevel@tonic-gate /* R_AMD64_PLT32 */	{FLG_RE_PCREL | FLG_RE_PLTREL |
54*1169Srie 			    FLG_RE_VERIFY | FLG_RE_SIGN, 4},
55*1169Srie /* R_AMD64_COPY */	{FLG_RE_NOTSUP, 0},		/* SPECIAL */
560Sstevel@tonic-gate /* R_AMD64_GLOB_DAT */	{FLG_RE_NOTREL, 8},
57*1169Srie /* R_AMD64_JUMP_SLOT */	{FLG_RE_NOTSUP, 0},		/* SPECIAL */
580Sstevel@tonic-gate /* R_AMD64_RELATIVE */	{FLG_RE_NOTREL, 8},
590Sstevel@tonic-gate /* R_AMD64_GOTPCREL */	{FLG_RE_GOTPC | FLG_RE_GOTADD, 4},
600Sstevel@tonic-gate /* R_AMD64_32 */	{FLG_RE_NOTREL, 4},
610Sstevel@tonic-gate /* R_AMD64_32S */	{FLG_RE_NOTREL, 4},
62*1169Srie /* R_AMD64_16 */	{FLG_RE_NOTREL, 2},
63*1169Srie /* R_AMD64_PC16 */	{FLG_RE_PCREL, 2},
64*1169Srie /* R_AMD64_8 */		{FLG_RE_NOTREL, 1},
65*1169Srie /* R_AMD64_PC8 */	{FLG_RE_PCREL, 1},
660Sstevel@tonic-gate /* R_AMD64_DTPMOD64 */	{FLG_RE_NOTREL, 8},
670Sstevel@tonic-gate /* R_AMD64_DTPOFF64 */	{FLG_RE_NOTREL, 8},
680Sstevel@tonic-gate /* R_AMD64_TPOFF64 */	{FLG_RE_NOTREL, 8},
690Sstevel@tonic-gate /* R_AMD64_TLSGD */	{FLG_RE_GOTPC | FLG_RE_GOTADD |
700Sstevel@tonic-gate 			    FLG_RE_TLSINS | FLG_RE_TLSGD, 4},
710Sstevel@tonic-gate /* R_AMD64_TLSLD */	{FLG_RE_GOTPC | FLG_RE_GOTADD |
720Sstevel@tonic-gate 			    FLG_RE_TLSINS | FLG_RE_TLSLD, 4},
73*1169Srie /* R_AMD64_DTPOFF32 */	{FLG_RE_TLSINS | FLG_RE_TLSLD, 4},
740Sstevel@tonic-gate /* R_AMD64_GOTTPOFF */	{FLG_RE_GOTPC | FLG_RE_GOTADD |
750Sstevel@tonic-gate 			    FLG_RE_TLSINS | FLG_RE_TLSIE, 4},
76*1169Srie /* R_AMD64_TPOFF32 */	{FLG_RE_TLSINS | FLG_RE_TLSLE, 4},
770Sstevel@tonic-gate /* R_AMD64_PC64 */	{FLG_RE_PCREL, 8},
780Sstevel@tonic-gate /* R_AMD64_GOTOFF64 */	{FLG_RE_GOTREL, 8},
79*1169Srie /* R_AMD64_GOTPC32 */	{FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4},
80*1169Srie /* R_AMD64_GOT64 */	{FLG_RE_NOTSUP, 0},
81*1169Srie /* R_AMD64_GOTPCREL64 */	{FLG_RE_NOTSUP, 0},
82*1169Srie /* R_AMD64_GOTPC6 */	{FLG_RE_NOTSUP, 0},
83*1169Srie /* R_AMD64_GOTPLT64 */	{FLG_RE_NOTSUP, 0},
84*1169Srie /* R_AMD64_PLTOFF64 */	{FLG_RE_NOTSUP, 0}
85*1169Srie 
860Sstevel@tonic-gate };
87*1169Srie #if	(R_AMD64_NUM != (R_AMD64_PLTOFF64 + 1))
880Sstevel@tonic-gate #error	"R_AMD64_NUM has grown"
890Sstevel@tonic-gate #endif
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * Write a single relocated value to its reference location.
93*1169Srie  * We assume we wish to add the relocation amount, value, to the
940Sstevel@tonic-gate  * value of the address already present at the offset.
950Sstevel@tonic-gate  *
960Sstevel@tonic-gate  * NAME			VALUE	FIELD		CALCULATION
970Sstevel@tonic-gate  *
980Sstevel@tonic-gate  * R_AMD64_NONE		 0	none		none
990Sstevel@tonic-gate  * R_AMD64_64		 1	word64		S + A
1000Sstevel@tonic-gate  * R_AMD64_PC32		 2	word64		S + A
1010Sstevel@tonic-gate  * R_AMD64_GOT32	 3	word32		G + A
1020Sstevel@tonic-gate  * R_AMD64_PLT32	 4	word32		L + A - P
1030Sstevel@tonic-gate  * R_AMD64_COPY		 5	none		none
1040Sstevel@tonic-gate  * R_AMD64_GLOB_DAT	 6	word64		S
1050Sstevel@tonic-gate  * R_AMD64_JUMP_SLOT	 7	word64		S
1060Sstevel@tonic-gate  * R_AMD64_RELATIVE	 8	word64		B + A
1070Sstevel@tonic-gate  * R_AMD64_GOTPCREL	 9	word32		G + GOT + A - P
1080Sstevel@tonic-gate  * R_AMD64_32		10	word32		S + A
1090Sstevel@tonic-gate  * R_AMD64_32S		11	word32		S + A
1100Sstevel@tonic-gate  * R_AMD64_16		12	word16		S + A
1110Sstevel@tonic-gate  * R_AMD64_PC16		13	word16		S + A - P
1120Sstevel@tonic-gate  * R_AMD64_8		14	word8		S + A
1130Sstevel@tonic-gate  * R_AMD64_PC8		15	word8		S + A - P
1140Sstevel@tonic-gate  * R_AMD64_DTPMOD64	16	word64
1150Sstevel@tonic-gate  * R_AMD64_DTPOFF64	17	word64
1160Sstevel@tonic-gate  * R_AMD64_TPOFF64	18	word64
1170Sstevel@tonic-gate  * R_AMD64_TLSGD	19	word32
1180Sstevel@tonic-gate  * R_AMD64_TLSLD	20	word32
1190Sstevel@tonic-gate  * R_AMD64_DTPOFF32	21	word32
1200Sstevel@tonic-gate  * R_AMD64_GOTTPOFF	22	word32
1210Sstevel@tonic-gate  * R_AMD64_TPOFF32	23	word32
1220Sstevel@tonic-gate  * R_AMD64_PC64		24	word32		S + A - P
1230Sstevel@tonic-gate  * R_AMD64_GOTOFF64	25	word32		S + A - GOT
1240Sstevel@tonic-gate  * R_AMD64_GOTPC32	26	word32		GOT + A - P
125*1169Srie  * R_AMD64_GOT64	27			reserved for future expansion
126*1169Srie  * R_AMD64_GOTPCREL64	28			reserved for future expansion
127*1169Srie  * R_AMD64_GOTPC64	29			reserved for future expansion
128*1169Srie  * R_AMD64_GOTPLT64	30			reserved for future expansion
129*1169Srie  * R_AMD64_PLTOFF64	31			reserved for future expansion
1300Sstevel@tonic-gate  *
1310Sstevel@tonic-gate  * Relocation calculations:
1320Sstevel@tonic-gate  *	A	Represents the addend used to compute the value of the
1330Sstevel@tonic-gate  *		relocatable field.
1340Sstevel@tonic-gate  *
1350Sstevel@tonic-gate  *	B	Represents the base address at which a shared objects has
1360Sstevel@tonic-gate  *		been loaded into memory during executaion.  Generally, a
1370Sstevel@tonic-gate  *		shared objects is built with a 0 base virtual address,
1380Sstevel@tonic-gate  *		but the execution address will be different.
1390Sstevel@tonic-gate  *
1400Sstevel@tonic-gate  *	G	Represents the offset into the global offset table
1410Sstevel@tonic-gate  *		at which the relocation entry's symbol will reside
1420Sstevel@tonic-gate  *		during execution.
1430Sstevel@tonic-gate  *
1440Sstevel@tonic-gate  *	GOT	Rrepresents the address of the global offset table.
1450Sstevel@tonic-gate  *
1460Sstevel@tonic-gate  *	L	Represents the place (section offset or address) of
1470Sstevel@tonic-gate  *		the Procedure Linkage Table entry for a symbol.
1480Sstevel@tonic-gate  *
1490Sstevel@tonic-gate  *	P	Represents the place (section offset or address) of the
1500Sstevel@tonic-gate  *		storage unit being relocated (computed using r_offset).
1510Sstevel@tonic-gate  *
1520Sstevel@tonic-gate  *	S	Represents the value of the symbol whose index resides
1530Sstevel@tonic-gate  *		in the relocation entry.
1540Sstevel@tonic-gate  *
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate 
157238Sseizo #define	HIBITS	0xffffffff80000000ULL
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate int
160*1169Srie do_reloc(uchar_t rtype, uchar_t *off, Xword *value, const char *sym,
161*1169Srie     const char *file)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate 	const Rel_entry	*rep;
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	rep = &reloc_table[rtype];
1660Sstevel@tonic-gate 
167*1169Srie 	switch (rep->re_fsize) {
168*1169Srie 	case 1:
169*1169Srie 		/* LINTED */
170*1169Srie 		*((uchar_t *)off) = (uchar_t)(*value);
171*1169Srie 		break;
172*1169Srie 	case 2:
173*1169Srie 		/* LINTED */
174*1169Srie 		*((Half *)off) = (Half)(*value);
175*1169Srie 		break;
176*1169Srie 	case 4:
1770Sstevel@tonic-gate 		/*
178*1169Srie 		 * The amd64 psABI requires that we perform the following
179*1169Srie 		 * verifications:
1800Sstevel@tonic-gate 		 *
181*1169Srie 		 *    The R_AMD64_32 and R_AMD64_32S relocations truncate the
182*1169Srie 		 *    computed value to 32bits.  Verify that the generated value
183*1169Srie 		 *    for the R_AMD64_32/32S relocation zero-extends (sign
184*1169Srie 		 *    extends) to the original 64-bit value.
1850Sstevel@tonic-gate 		 *
186*1169Srie 		 * Also, the following relocations are all 32 bit PC relative
187*1169Srie 		 * references.  Validate that the value being written will fit
188*1169Srie 		 * in the field provided.
1890Sstevel@tonic-gate 		 *
190*1169Srie 		 *    R_AMD64_PC32, R_AMD64_GOTPC32, R_AMD64_GOTPCREL
1910Sstevel@tonic-gate 		 */
1920Sstevel@tonic-gate 		if (rtype == R_AMD64_32) {
1930Sstevel@tonic-gate 			/*
194*1169Srie 			 * Verify that this value will 'zero-extend', this
195*1169Srie 			 * requires that the upper 33bits all be 'zero'.
1960Sstevel@tonic-gate 			 */
1970Sstevel@tonic-gate 			if ((*value & HIBITS) != 0) {
1980Sstevel@tonic-gate 				/*
199*1169Srie 				 * To keep chkmsg() happy:
2000Sstevel@tonic-gate 				 *  MSG_INTL(MSG_REL_NOFIT)
2010Sstevel@tonic-gate 				 */
2020Sstevel@tonic-gate 				REL_ERR_NOFIT(file, sym, rtype, *value);
2030Sstevel@tonic-gate 				return (0);
2040Sstevel@tonic-gate 			}
205*1169Srie 		} else if ((rtype == R_AMD64_32S) || (rtype == R_AMD64_PC32) ||
206*1169Srie 		    (rtype == R_AMD64_GOTPCREL) || (rtype == R_AMD64_GOTPC32)) {
2070Sstevel@tonic-gate 			/*
208*1169Srie 			 * Verify that this value will properly sign extend.
209*1169Srie 			 * This is true of the upper 33bits are all either
210*1169Srie 			 * 'zero' or all 'one'.
2110Sstevel@tonic-gate 			 */
2120Sstevel@tonic-gate 			if (((*value & HIBITS) != HIBITS) &&
2130Sstevel@tonic-gate 			    ((*value & HIBITS) != 0)) {
2140Sstevel@tonic-gate 				/*
215*1169Srie 				 * To keep chkmsg() happy:
2160Sstevel@tonic-gate 				 *  MSG_INTL(MSG_REL_NOFIT)
2170Sstevel@tonic-gate 				 */
2180Sstevel@tonic-gate 				REL_ERR_NOFIT(file, sym, rtype, *value);
2190Sstevel@tonic-gate 				return (0);
2200Sstevel@tonic-gate 			}
2210Sstevel@tonic-gate 		}
2220Sstevel@tonic-gate 		/* LINTED */
2230Sstevel@tonic-gate 		*((Word *)off) += *value;
224*1169Srie 		break;
225*1169Srie 	case 8:
226*1169Srie 		/* LINTED */
2270Sstevel@tonic-gate 		*((Xword *)off) += *value;
228*1169Srie 		break;
229*1169Srie 	default:
230*1169Srie 		/*
231*1169Srie 		 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
232*1169Srie 		 */
233*1169Srie 		REL_ERR_UNSUPSZ(file, sym, rtype, rep->re_fsize);
2340Sstevel@tonic-gate 		return (0);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 	return (1);
2370Sstevel@tonic-gate }
238