xref: /onnv-gate/usr/src/uts/common/krtld/reloc.h (revision 4734:a4708faa3e85)
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  */
211169Srie 
220Sstevel@tonic-gate /*
23*4734Sab196087  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #ifndef	_RELOC_DOT_H
280Sstevel@tonic-gate #define	_RELOC_DOT_H
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #if defined(_KERNEL)
330Sstevel@tonic-gate #include <sys/machelf.h>
340Sstevel@tonic-gate #include <sys/bootconf.h>
350Sstevel@tonic-gate #include <sys/kobj.h>
360Sstevel@tonic-gate #include <sys/kobj_impl.h>
370Sstevel@tonic-gate #else
380Sstevel@tonic-gate #include <machdep.h>
391618Srie #include <rtld.h>
401169Srie #include <conv.h>
410Sstevel@tonic-gate #endif /* _KERNEL */
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #include <relmach.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #ifdef	__cplusplus
460Sstevel@tonic-gate extern "C" {
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * Global include file for relocation common code.
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  * Flags for reloc_entry->re_flags
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate #define	FLG_RE_NOTREL		0x00000000
550Sstevel@tonic-gate #define	FLG_RE_GOTADD		0x00000001	/* create a GOT entry */
560Sstevel@tonic-gate #define	FLG_RE_GOTREL		0x00000002	/* GOT based */
570Sstevel@tonic-gate #define	FLG_RE_GOTPC		0x00000004	/* GOT - P */
580Sstevel@tonic-gate #define	FLG_RE_GOTOPINS		0x00000008	/* GOTOP instruction */
590Sstevel@tonic-gate #define	FLG_RE_PCREL		0x00000010
600Sstevel@tonic-gate #define	FLG_RE_PLTREL		0x00000020
610Sstevel@tonic-gate #define	FLG_RE_VERIFY		0x00000040	/* verify value fits */
620Sstevel@tonic-gate #define	FLG_RE_UNALIGN		0x00000080	/* offset is not aligned */
630Sstevel@tonic-gate #define	FLG_RE_WDISP16		0x00000100	/* funky sparc DISP16 rel */
640Sstevel@tonic-gate #define	FLG_RE_SIGN		0x00000200	/* value is signed */
650Sstevel@tonic-gate #define	FLG_RE_ADDRELATIVE	0x00000400	/* RELATIVE relocation */
662145Srie 						/*	required for non- */
672145Srie 						/*	fixed objects */
680Sstevel@tonic-gate #define	FLG_RE_EXTOFFSET	0x00000800	/* extra offset required */
690Sstevel@tonic-gate #define	FLG_RE_REGISTER		0x00001000	/* relocation initializes */
700Sstevel@tonic-gate 						/*    a REGISTER by OLO10 */
712850Srie #define	FLG_RE_SIZE		0x00002000	/* symbol size required */
722850Srie 
730Sstevel@tonic-gate #define	FLG_RE_NOTSUP		0x00010000	/* relocation not supported */
740Sstevel@tonic-gate 
751169Srie #define	FLG_RE_SEGREL		0x00040000	/* segment relative */
761169Srie #define	FLG_RE_SECREL		0x00080000	/* section relative */
772145Srie 
780Sstevel@tonic-gate #define	FLG_RE_TLSGD		0x00200000	/* TLS GD relocation */
790Sstevel@tonic-gate #define	FLG_RE_TLSLD		0x00400000	/* TLS LD relocation */
800Sstevel@tonic-gate #define	FLG_RE_TLSIE		0x00800000	/* TLS IE relocation */
810Sstevel@tonic-gate #define	FLG_RE_TLSLE		0x01000000	/* TLS LE relocation */
820Sstevel@tonic-gate #define	FLG_RE_LOCLBND		0x02000000	/* relocation must bind */
831169Srie 						/*    locally */
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
861618Srie  * In user land, redefine the relocation table and relocation engine to be
871618Srie  * class specific if necessary.  This allows both engines to reside in the
881618Srie  * intel/amd version of libld.
891618Srie  */
901618Srie #if	!defined(_KERNEL)
911618Srie #if	defined(_ELF64)
921618Srie #define	do_reloc		do64_reloc
931618Srie #define	reloc_table		reloc64_table
941618Srie #else
951618Srie #define	do_reloc		do32_reloc
961618Srie #define	reloc_table		reloc32_table
971618Srie #endif
981618Srie #endif
991618Srie 
1001618Srie /*
1011618Srie  * Relocation table and macros for testing relocation table flags.
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate extern	const Rel_entry		reloc_table[];
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate #define	IS_PLT(X)		((reloc_table[(X)].re_flags & \
1060Sstevel@tonic-gate 					FLG_RE_PLTREL) != 0)
1070Sstevel@tonic-gate #define	IS_GOT_RELATIVE(X)	((reloc_table[(X)].re_flags & \
1080Sstevel@tonic-gate 					FLG_RE_GOTADD) != 0)
1090Sstevel@tonic-gate #define	IS_GOT_PC(X)		((reloc_table[(X)].re_flags & \
1100Sstevel@tonic-gate 					FLG_RE_GOTPC) != 0)
1110Sstevel@tonic-gate #define	IS_GOTPCREL(X)		((reloc_table[(X)].re_flags & \
1120Sstevel@tonic-gate 					(FLG_RE_GOTPC | FLG_RE_GOTADD)) == \
1130Sstevel@tonic-gate 					(FLG_RE_GOTPC | FLG_RE_GOTADD))
1140Sstevel@tonic-gate #define	IS_GOT_BASED(X)		((reloc_table[(X)].re_flags & \
1150Sstevel@tonic-gate 					FLG_RE_GOTREL) != 0)
1163304Srie #define	IS_GOT_OPINS(X)		((reloc_table[(X)].re_flags & \
1170Sstevel@tonic-gate 					FLG_RE_GOTOPINS) != 0)
1181324Srie #define	IS_GOT_REQUIRED(X)	((reloc_table[(X)].re_flags & \
1191324Srie 					(FLG_RE_GOTADD | FLG_RE_GOTREL | \
1201324Srie 					FLG_RE_GOTPC | FLG_RE_GOTOPINS)) != 0)
1210Sstevel@tonic-gate #define	IS_PC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
1220Sstevel@tonic-gate 					FLG_RE_PCREL) != 0)
1230Sstevel@tonic-gate #define	IS_ADD_RELATIVE(X)	((reloc_table[(X)].re_flags & \
1240Sstevel@tonic-gate 					FLG_RE_ADDRELATIVE) != 0)
1250Sstevel@tonic-gate #define	IS_REGISTER(X)		((reloc_table[(X)].re_flags & \
1260Sstevel@tonic-gate 					FLG_RE_REGISTER) != 0)
1271618Srie #define	IS_NOTSUP(X)		((reloc_table[(X)].re_flags & \
1280Sstevel@tonic-gate 					FLG_RE_NOTSUP) != 0)
1291618Srie #define	IS_SEG_RELATIVE(X)	((reloc_table[(X)].re_flags & \
1300Sstevel@tonic-gate 					FLG_RE_SEGREL) != 0)
1311618Srie #define	IS_EXTOFFSET(X)		((reloc_table[(X)].re_flags & \
1320Sstevel@tonic-gate 					FLG_RE_EXTOFFSET) != 0)
1331618Srie #define	IS_SEC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
1340Sstevel@tonic-gate 					FLG_RE_SECREL) != 0)
1351618Srie #define	IS_TLS_INS(X)		((reloc_table[(X)].re_flags & \
1362145Srie 					(FLG_RE_TLSGD | FLG_RE_TLSLD | \
1372145Srie 					FLG_RE_TLSIE | FLG_RE_TLSLE)) != 0)
1381618Srie #define	IS_TLS_GD(X)		((reloc_table[(X)].re_flags & \
1390Sstevel@tonic-gate 					FLG_RE_TLSGD) != 0)
1401618Srie #define	IS_TLS_LD(X)		((reloc_table[(X)].re_flags & \
1410Sstevel@tonic-gate 					FLG_RE_TLSLD) != 0)
1421618Srie #define	IS_TLS_IE(X)		((reloc_table[(X)].re_flags & \
1430Sstevel@tonic-gate 					FLG_RE_TLSIE) != 0)
1441618Srie #define	IS_TLS_LE(X)		((reloc_table[(X)].re_flags & \
1450Sstevel@tonic-gate 					FLG_RE_TLSLE) != 0)
1461618Srie #define	IS_LOCALBND(X)		((reloc_table[(X)].re_flags & \
1470Sstevel@tonic-gate 					FLG_RE_LOCLBND) != 0)
1482850Srie #define	IS_SIZE(X)		((reloc_table[(X)].re_flags &\
1492850Srie 					FLG_RE_SIZE) != 0)
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate /*
1521618Srie  * Relocation engine.
1530Sstevel@tonic-gate  */
1541169Srie extern	int	do_reloc(uchar_t, uchar_t *, Xword *, const char *,
1551618Srie 		    const char *, void *);
1561169Srie 
1570Sstevel@tonic-gate #if defined(_KERNEL)
1580Sstevel@tonic-gate /*
1591169Srie  * These are macro's that are only needed for krtld.  Many of these are already
1601169Srie  * defined in the sgs/include files referenced by ld and rtld
1610Sstevel@tonic-gate  */
1620Sstevel@tonic-gate #define	S_MASK(n)	((1l << (n)) - 1l)
1630Sstevel@tonic-gate #define	S_INRANGE(v, n)	(((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate /*
1661169Srie  * Message strings used by doreloc().
1670Sstevel@tonic-gate  */
1681169Srie #define	MSG_STR_UNKNOWN		"(unknown)"
1691169Srie 
1701169Srie #define	MSG_REL_PREGEN		"relocation error: %s: "
1711169Srie #define	MSG_REL_PREFIL		"relocation error: file %s: "
1721169Srie #define	MSG_REL_FILE		"file %s: "
1731169Srie #define	MSG_REL_SYM		"symbol %s: "
1741169Srie #define	MSG_REL_VALUE		"value 0x%llx "
1751169Srie #define	MSG_REL_LOSEBITS	"loses %d bits at "
1761169Srie 
1771169Srie #define	MSG_REL_UNIMPL		"unimplemented relocation type: %d"
1781169Srie #define	MSG_REL_UNSUPSZ		"offset size (%d bytes) is not supported"
1791169Srie #define	MSG_REL_NONALIGN	"offset 0x%llx is non-aligned"
1801169Srie #define	MSG_REL_UNNOBITS	"unsupported number of bits: %d"
1811169Srie #define	MSG_REL_OFFSET		"offset 0x%llx"
1821169Srie #define	MSG_REL_NOFIT		"value 0x%llx does not fit"
1831169Srie 
1841618Srie /*
1851618Srie  * Provide a macro to select the appropriate conversion routine for this
1861618Srie  * architecture.
1871618Srie  */
1881618Srie #if defined(__amd64)
1891618Srie 
1901618Srie extern const char	*conv_reloc_amd64_type(Word);
1911618Srie #define	CONV_RELOC_TYPE	conv_reloc_amd64_type
1921618Srie 
1931618Srie #elif defined(__i386)
1941618Srie 
1951618Srie extern const char	*conv_reloc_386_type(Word);
1961618Srie #define	CONV_RELOC_TYPE	conv_reloc_386_type
1971618Srie 
1981618Srie #elif defined(__sparc)
1991618Srie 
2001618Srie extern const char	*conv_reloc_SPARC_type(Word);
2011618Srie #define	CONV_RELOC_TYPE	conv_reloc_SPARC_type
2021618Srie 
2031618Srie #else
2041618Srie #error platform not defined!
2051618Srie #endif
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate /*
2081618Srie  * Note:  dlerror() only keeps track of a single error string, and therefore
2091618Srie  * must have errors reported through a single eprintf() call.  The kernel's
2101618Srie  * _kobj_printf is somewhat more limited, and must receive messages with only
2111618Srie  * one argument to the format string.  The following macros account for these
2121618Srie  * differences, as krtld and rtld share do_reloc().
2130Sstevel@tonic-gate  */
2141618Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
2151169Srie 	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
2161169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2171169Srie 	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
2181169Srie 
2191618Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
2201169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2211169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2221169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2231169Srie 	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
2240Sstevel@tonic-gate 
2251618Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
2261169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2271169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2281169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2291169Srie 	_kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
2300Sstevel@tonic-gate 
2311618Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
2321169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2331169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2341169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2351169Srie 	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
2360Sstevel@tonic-gate 
2371618Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
2381169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2391169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2401169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2411169Srie 	_kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
2421169Srie 	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
2431618Srie 	_kobj_printf(ops, MSG_REL_OFFSET, EC_NATPTR((off)))
2440Sstevel@tonic-gate 
2451618Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
2461169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2471169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2481169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2491169Srie 	_kobj_printf(ops, MSG_REL_NOFIT, EC_XWORD((uvalue)))
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate #else	/* !_KERNEL */
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate extern	const char *demangle(const char *);
2550Sstevel@tonic-gate 
2561618Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
2571618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
2581169Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
2591169Srie 
2601618Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
2611618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
262*4734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2631169Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
2640Sstevel@tonic-gate 
2651618Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
2661618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
267*4734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2681169Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
2690Sstevel@tonic-gate 
2701618Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
2711618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
272*4734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2730Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
2740Sstevel@tonic-gate 
2751618Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
2761618Srie 	(eprintf(lml, ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
277*4734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2780Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
2791618Srie 	    EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
2800Sstevel@tonic-gate 
2811618Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
2821618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
283*4734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2840Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
2850Sstevel@tonic-gate 	    EC_XWORD((uvalue))))
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate #endif	/* _KERNEL */
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate #ifdef	__cplusplus
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate #endif
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate #endif /* _RELOC_DOT_H */
294