xref: /onnv-gate/usr/src/uts/common/krtld/reloc.h (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  */
211169Srie 
220Sstevel@tonic-gate /*
23*12155SAli.Bahrami@Sun.COM  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #ifndef	_RELOC_DOT_H
270Sstevel@tonic-gate #define	_RELOC_DOT_H
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #if defined(_KERNEL)
300Sstevel@tonic-gate #include <sys/bootconf.h>
310Sstevel@tonic-gate #include <sys/kobj.h>
320Sstevel@tonic-gate #include <sys/kobj_impl.h>
330Sstevel@tonic-gate #else
341618Srie #include <rtld.h>
351169Srie #include <conv.h>
360Sstevel@tonic-gate #endif /* _KERNEL */
370Sstevel@tonic-gate 
386206Sab196087 #include "reloc_defs.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #ifdef	__cplusplus
410Sstevel@tonic-gate extern "C" {
420Sstevel@tonic-gate #endif
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  * Global include file for relocation common code.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /*
491618Srie  * In user land, redefine the relocation table and relocation engine to be
506206Sab196087  * class/machine specific if necessary.  This allows multiple engines to
516206Sab196087  * reside within a single instance of libld.
521618Srie  */
531618Srie #if	!defined(_KERNEL)
546206Sab196087 
556206Sab196087 #if defined(DO_RELOC_LIBLD)
566206Sab196087 #undef DO_RELOC_LIBLD
576206Sab196087 #endif
586206Sab196087 
596206Sab196087 #if	defined(DO_RELOC_LIBLD_X86)
606206Sab196087 
616206Sab196087 #define	DO_RELOC_LIBLD
621618Srie #if	defined(_ELF64)
636206Sab196087 #define	do_reloc_ld		do64_reloc_ld_x86
646206Sab196087 #define	reloc_table		reloc64_table_x86
656206Sab196087 #else
666206Sab196087 #define	do_reloc_ld		do32_reloc_ld_x86
676206Sab196087 #define	reloc_table		reloc32_table_x86
686206Sab196087 #endif
696206Sab196087 
706206Sab196087 #elif	defined(DO_RELOC_LIBLD_SPARC)
716206Sab196087 
726206Sab196087 #define	DO_RELOC_LIBLD
736206Sab196087 #if	defined(_ELF64)
746206Sab196087 #define	do_reloc_ld		do64_reloc_ld_sparc
756206Sab196087 #define	reloc_table		reloc64_table_sparc
766206Sab196087 #else
776206Sab196087 #define	do_reloc_ld		do32_reloc_ld_sparc
786206Sab196087 #define	reloc_table		reloc32_table_sparc
796206Sab196087 #endif
806206Sab196087 
816206Sab196087 #else				/* rtld */
826206Sab196087 
836206Sab196087 #if	defined(_ELF64)
845189Sab196087 #define	do_reloc_rtld		do64_reloc_rtld
851618Srie #define	reloc_table		reloc64_table
861618Srie #else
875189Sab196087 #define	do_reloc_rtld		do32_reloc_rtld
881618Srie #define	reloc_table		reloc32_table
891618Srie #endif
906206Sab196087 
911618Srie #endif
921618Srie 
936206Sab196087 #endif	/* !_KERNEL */
946206Sab196087 
951618Srie /*
961618Srie  * Relocation table and macros for testing relocation table flags.
970Sstevel@tonic-gate  */
986206Sab196087 extern	const Rel_entry	reloc_table[];
990Sstevel@tonic-gate 
1006206Sab196087 #define	IS_PLT(X)		RELTAB_IS_PLT(X, reloc_table)
1016206Sab196087 #define	IS_GOT_RELATIVE(X)	RELTAB_IS_GOT_RELATIVE(X, reloc_table)
1026206Sab196087 #define	IS_GOT_PC(X)		RELTAB_IS_GOT_PC(X, reloc_table)
1036206Sab196087 #define	IS_GOTPCREL(X)		RELTAB_IS_GOTPCREL(X, reloc_table)
1046206Sab196087 #define	IS_GOT_BASED(X)		RELTAB_IS_GOT_BASED(X, reloc_table)
1056206Sab196087 #define	IS_GOT_OPINS(X)		RELTAB_IS_GOT_OPINS(X, reloc_table)
1066206Sab196087 #define	IS_GOT_REQUIRED(X)	RELTAB_IS_GOT_REQUIRED(X, reloc_table)
1076206Sab196087 #define	IS_PC_RELATIVE(X)	RELTAB_IS_PC_RELATIVE(X, reloc_table)
1086206Sab196087 #define	IS_ADD_RELATIVE(X)	RELTAB_IS_ADD_RELATIVE(X, reloc_table)
1096206Sab196087 #define	IS_REGISTER(X)		RELTAB_IS_REGISTER(X, reloc_table)
1106206Sab196087 #define	IS_NOTSUP(X)		RELTAB_IS_NOTSUP(X, reloc_table)
1116206Sab196087 #define	IS_SEG_RELATIVE(X)	RELTAB_IS_SEG_RELATIVE(X, reloc_table)
1126206Sab196087 #define	IS_EXTOFFSET(X)		RELTAB_IS_EXTOFFSET(X, reloc_table)
1136206Sab196087 #define	IS_SEC_RELATIVE(X)	RELTAB_IS_SEC_RELATIVE(X, reloc_table)
1146206Sab196087 #define	IS_TLS_INS(X)		RELTAB_IS_TLS_INS(X, reloc_table)
1156206Sab196087 #define	IS_TLS_GD(X)		RELTAB_IS_TLS_GD(X, reloc_table)
1166206Sab196087 #define	IS_TLS_LD(X)		RELTAB_IS_TLS_LD(X, reloc_table)
1176206Sab196087 #define	IS_TLS_IE(X)		RELTAB_IS_TLS_IE(X, reloc_table)
1186206Sab196087 #define	IS_TLS_LE(X)		RELTAB_IS_TLS_LE(X, reloc_table)
1196206Sab196087 #define	IS_LOCALBND(X)		RELTAB_IS_LOCALBND(X, reloc_table)
1206206Sab196087 #define	IS_SIZE(X)		RELTAB_IS_SIZE(X, reloc_table)
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate /*
1231618Srie  * Relocation engine.
1245189Sab196087  *
1255189Sab196087  * The do_reloc() code is used in three different places: The kernel,
126*12155SAli.Bahrami@Sun.COM  * the link-editor, and the runtime linker. All three convey the same
127*12155SAli.Bahrami@Sun.COM  * basic information with the first 5 arguments:
128*12155SAli.Bahrami@Sun.COM  *
129*12155SAli.Bahrami@Sun.COM  * 1)	Relocation type. The kernel and runtime linker pass this as
130*12155SAli.Bahrami@Sun.COM  *	an integer value, while the link-editor passes it as a Rel_desc
131*12155SAli.Bahrami@Sun.COM  *	descriptor. The relocation engine only looks at the rel_rtype
132*12155SAli.Bahrami@Sun.COM  *	field of this descriptor, and does not examine the other fields,
133*12155SAli.Bahrami@Sun.COM  *	which are explicitly allowed to contain garbage.
134*12155SAli.Bahrami@Sun.COM  * 2)	Address of offset
135*12155SAli.Bahrami@Sun.COM  * 3)	Address of value
136*12155SAli.Bahrami@Sun.COM  * 4)	Name of symbol associated with the relocation, used if it is
137*12155SAli.Bahrami@Sun.COM  *	necessary to report an error. The kernel and runtime linker pass
138*12155SAli.Bahrami@Sun.COM  *	directly as a string pointer. The link-editor passes the address
139*12155SAli.Bahrami@Sun.COM  *	of a rel_desc_sname_func_t function, which can be called by do_reloc(),
140*12155SAli.Bahrami@Sun.COM  *	passing it the Rel_desc pointer (argument 1, above), to obtain the
141*12155SAli.Bahrami@Sun.COM  *	string pointer.
142*12155SAli.Bahrami@Sun.COM  * 5)	String giving the source file for the relocation.
143*12155SAli.Bahrami@Sun.COM  *
144*12155SAli.Bahrami@Sun.COM  * In addition:
1455189Sab196087  *	- The linker and rtld want a link map pointer argument
1465189Sab196087  *	- The linker wants to pass a byte swap argument that tells
1475189Sab196087  *		the relocation engine that the data it is relocating
1485189Sab196087  *		has the opposite byte order of the system running the
1495189Sab196087  *		linker.
1506206Sab196087  *	- The linker is a cross-linker, meaning that it can examine
1516206Sab196087  *		relocation records for target hosts other than that of
1526206Sab196087  *		the currently running system. This means that multiple
1536206Sab196087  *		versions of the relocation code must be able to reside
1546206Sab196087  *		in a single program, without namespace clashes.
1555189Sab196087  *
1565189Sab196087  * To ensure that there is never any confusion about which version is
1575189Sab196087  * being linked to, we give each variant a different name, even though
1585189Sab196087  * each one is generated from the same source code.
1595189Sab196087  *
1605189Sab196087  *	do_reloc_krtld()
1615189Sab196087  *	The kernel version is provided if the _KERNEL macro is defined.
1625189Sab196087  *
1635189Sab196087  *	do_reloc_ld()
1646206Sab196087  *	The ld version is provided if the DO_RELOC_LIBLD_ macro is defined.
1655189Sab196087  *
1665189Sab196087  *	do_reloc_rtld()
1675189Sab196087  *	The rtld version is provided if neither _KERNEL or DO_RELOC_LIBLD
1685189Sab196087  *	are defined.
1695189Sab196087  *
1705189Sab196087  * Implementations of do_reloc() should use these same macros to
1715189Sab196087  * conditionalize any code not used by all three versions.
1720Sstevel@tonic-gate  */
1735189Sab196087 #if defined(_KERNEL)
1745189Sab196087 extern	int	do_reloc_krtld(uchar_t, uchar_t *, Xword *, const char *,
1755189Sab196087 		    const char *);
1765189Sab196087 #elif defined(DO_RELOC_LIBLD)
177*12155SAli.Bahrami@Sun.COM extern	int	do_reloc_ld(Rel_desc *, uchar_t *, Xword *,
178*12155SAli.Bahrami@Sun.COM 		    rel_desc_sname_func_t, const char *, int, void *);
1795189Sab196087 #else
1805189Sab196087 extern	int	do_reloc_rtld(uchar_t, uchar_t *, Xword *, const char *,
1811618Srie 		    const char *, void *);
1825189Sab196087 #endif
1831169Srie 
1840Sstevel@tonic-gate #if defined(_KERNEL)
1850Sstevel@tonic-gate /*
1861169Srie  * These are macro's that are only needed for krtld.  Many of these are already
1871169Srie  * defined in the sgs/include files referenced by ld and rtld
1880Sstevel@tonic-gate  */
1890Sstevel@tonic-gate #define	S_MASK(n)	((1l << (n)) - 1l)
1900Sstevel@tonic-gate #define	S_INRANGE(v, n)	(((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate /*
1931169Srie  * Message strings used by doreloc().
1940Sstevel@tonic-gate  */
1951169Srie #define	MSG_STR_UNKNOWN		"(unknown)"
1961169Srie 
1971169Srie #define	MSG_REL_PREGEN		"relocation error: %s: "
1981169Srie #define	MSG_REL_PREFIL		"relocation error: file %s: "
1991169Srie #define	MSG_REL_FILE		"file %s: "
2001169Srie #define	MSG_REL_SYM		"symbol %s: "
2011169Srie #define	MSG_REL_VALUE		"value 0x%llx "
2021169Srie #define	MSG_REL_LOSEBITS	"loses %d bits at "
2031169Srie 
2041169Srie #define	MSG_REL_UNIMPL		"unimplemented relocation type: %d"
2051169Srie #define	MSG_REL_UNSUPSZ		"offset size (%d bytes) is not supported"
2061169Srie #define	MSG_REL_NONALIGN	"offset 0x%llx is non-aligned"
2071169Srie #define	MSG_REL_UNNOBITS	"unsupported number of bits: %d"
2081169Srie #define	MSG_REL_OFFSET		"offset 0x%llx"
2091169Srie #define	MSG_REL_NOFIT		"value 0x%llx does not fit"
2101169Srie 
2111618Srie /*
2121618Srie  * Provide a macro to select the appropriate conversion routine for this
2131618Srie  * architecture.
2141618Srie  */
2151618Srie #if defined(__amd64)
2161618Srie 
2171618Srie extern const char	*conv_reloc_amd64_type(Word);
2181618Srie #define	CONV_RELOC_TYPE	conv_reloc_amd64_type
2191618Srie 
2201618Srie #elif defined(__i386)
2211618Srie 
2221618Srie extern const char	*conv_reloc_386_type(Word);
2231618Srie #define	CONV_RELOC_TYPE	conv_reloc_386_type
2241618Srie 
2251618Srie #elif defined(__sparc)
2261618Srie 
2271618Srie extern const char	*conv_reloc_SPARC_type(Word);
2281618Srie #define	CONV_RELOC_TYPE	conv_reloc_SPARC_type
2291618Srie 
2301618Srie #else
2311618Srie #error platform not defined!
2321618Srie #endif
2330Sstevel@tonic-gate 
2346206Sab196087 
2350Sstevel@tonic-gate /*
2361618Srie  * Note:  dlerror() only keeps track of a single error string, and therefore
2371618Srie  * must have errors reported through a single eprintf() call.  The kernel's
2381618Srie  * _kobj_printf is somewhat more limited, and must receive messages with only
2391618Srie  * one argument to the format string.  The following macros account for these
2405189Sab196087  * differences, as krtld and rtld share the same do_reloc() source.
2410Sstevel@tonic-gate  */
2421618Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
2431169Srie 	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
2441169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2451169Srie 	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
2461169Srie 
2471618Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
2481169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2491169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2501169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2511169Srie 	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
2520Sstevel@tonic-gate 
2531618Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
2541169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2551169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2561169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2571169Srie 	_kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
2580Sstevel@tonic-gate 
2591618Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
2601169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2611169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2621169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2631169Srie 	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
2640Sstevel@tonic-gate 
2651618Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
2661169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2671169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2681169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2691169Srie 	_kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
2701169Srie 	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
2711618Srie 	_kobj_printf(ops, MSG_REL_OFFSET, EC_NATPTR((off)))
2720Sstevel@tonic-gate 
2731618Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
2741169Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
2751169Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
2761169Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
2771169Srie 	_kobj_printf(ops, MSG_REL_NOFIT, EC_XWORD((uvalue)))
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate #else	/* !_KERNEL */
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate extern	const char *demangle(const char *);
2830Sstevel@tonic-gate 
2841618Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
2851618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
2861169Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
2871169Srie 
2881618Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
2891618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
2904734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2911169Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
2920Sstevel@tonic-gate 
2931618Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
2941618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
2954734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2961169Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
2970Sstevel@tonic-gate 
2981618Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
2991618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
3004734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
3010Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
3020Sstevel@tonic-gate 
3031618Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
3041618Srie 	(eprintf(lml, ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
3054734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
3060Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
3071618Srie 	    EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
3080Sstevel@tonic-gate 
3091618Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
3101618Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
3114734Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
3120Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
3130Sstevel@tonic-gate 	    EC_XWORD((uvalue))))
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate #endif	/* _KERNEL */
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate #ifdef	__cplusplus
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate #endif
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate #endif /* _RELOC_DOT_H */
322