xref: /titanic_53/usr/src/uts/common/krtld/reloc.h (revision ba2be53024c0b999e74ba9adcd7d80fec5df8c57)
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  */
21552ff457Srie 
227c478bd9Sstevel@tonic-gate /*
23*ba2be530Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #ifndef	_RELOC_DOT_H
287c478bd9Sstevel@tonic-gate #define	_RELOC_DOT_H
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
337c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
347c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
357c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h>
367c478bd9Sstevel@tonic-gate #else
375aefb655Srie #include <rtld.h>
38552ff457Srie #include <conv.h>
397c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
407c478bd9Sstevel@tonic-gate 
41*ba2be530Sab196087 #include "reloc_defs.h"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
447c478bd9Sstevel@tonic-gate extern "C" {
457c478bd9Sstevel@tonic-gate #endif
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * Global include file for relocation common code.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
525aefb655Srie  * In user land, redefine the relocation table and relocation engine to be
53*ba2be530Sab196087  * class/machine specific if necessary.  This allows multiple engines to
54*ba2be530Sab196087  * reside within a single instance of libld.
555aefb655Srie  */
565aefb655Srie #if	!defined(_KERNEL)
57*ba2be530Sab196087 
58*ba2be530Sab196087 #if defined(DO_RELOC_LIBLD)
59*ba2be530Sab196087 #undef DO_RELOC_LIBLD
60*ba2be530Sab196087 #endif
61*ba2be530Sab196087 
62*ba2be530Sab196087 #if	defined(DO_RELOC_LIBLD_X86)
63*ba2be530Sab196087 
64*ba2be530Sab196087 #define	DO_RELOC_LIBLD
655aefb655Srie #if	defined(_ELF64)
66*ba2be530Sab196087 #define	do_reloc_ld		do64_reloc_ld_x86
67*ba2be530Sab196087 #define	reloc_table		reloc64_table_x86
68*ba2be530Sab196087 #else
69*ba2be530Sab196087 #define	do_reloc_ld		do32_reloc_ld_x86
70*ba2be530Sab196087 #define	reloc_table		reloc32_table_x86
71*ba2be530Sab196087 #endif
72*ba2be530Sab196087 
73*ba2be530Sab196087 #elif	defined(DO_RELOC_LIBLD_SPARC)
74*ba2be530Sab196087 
75*ba2be530Sab196087 #define	DO_RELOC_LIBLD
76*ba2be530Sab196087 #if	defined(_ELF64)
77*ba2be530Sab196087 #define	do_reloc_ld		do64_reloc_ld_sparc
78*ba2be530Sab196087 #define	reloc_table		reloc64_table_sparc
79*ba2be530Sab196087 #else
80*ba2be530Sab196087 #define	do_reloc_ld		do32_reloc_ld_sparc
81*ba2be530Sab196087 #define	reloc_table		reloc32_table_sparc
82*ba2be530Sab196087 #endif
83*ba2be530Sab196087 
84*ba2be530Sab196087 #else				/* rtld */
85*ba2be530Sab196087 
86*ba2be530Sab196087 #if	defined(_ELF64)
87f3324781Sab196087 #define	do_reloc_rtld		do64_reloc_rtld
885aefb655Srie #define	reloc_table		reloc64_table
895aefb655Srie #else
90f3324781Sab196087 #define	do_reloc_rtld		do32_reloc_rtld
915aefb655Srie #define	reloc_table		reloc32_table
925aefb655Srie #endif
93*ba2be530Sab196087 
945aefb655Srie #endif
955aefb655Srie 
96*ba2be530Sab196087 #endif	/* !_KERNEL */
97*ba2be530Sab196087 
985aefb655Srie /*
995aefb655Srie  * Relocation table and macros for testing relocation table flags.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate extern	const Rel_entry	reloc_table[];
1027c478bd9Sstevel@tonic-gate 
103*ba2be530Sab196087 #define	IS_PLT(X)		RELTAB_IS_PLT(X, reloc_table)
104*ba2be530Sab196087 #define	IS_GOT_RELATIVE(X)	RELTAB_IS_GOT_RELATIVE(X, reloc_table)
105*ba2be530Sab196087 #define	IS_GOT_PC(X)		RELTAB_IS_GOT_PC(X, reloc_table)
106*ba2be530Sab196087 #define	IS_GOTPCREL(X)		RELTAB_IS_GOTPCREL(X, reloc_table)
107*ba2be530Sab196087 #define	IS_GOT_BASED(X)		RELTAB_IS_GOT_BASED(X, reloc_table)
108*ba2be530Sab196087 #define	IS_GOT_OPINS(X)		RELTAB_IS_GOT_OPINS(X, reloc_table)
109*ba2be530Sab196087 #define	IS_GOT_REQUIRED(X)	RELTAB_IS_GOT_REQUIRED(X, reloc_table)
110*ba2be530Sab196087 #define	IS_PC_RELATIVE(X)	RELTAB_IS_PC_RELATIVE(X, reloc_table)
111*ba2be530Sab196087 #define	IS_ADD_RELATIVE(X)	RELTAB_IS_ADD_RELATIVE(X, reloc_table)
112*ba2be530Sab196087 #define	IS_REGISTER(X)		RELTAB_IS_REGISTER(X, reloc_table)
113*ba2be530Sab196087 #define	IS_NOTSUP(X)		RELTAB_IS_NOTSUP(X, reloc_table)
114*ba2be530Sab196087 #define	IS_SEG_RELATIVE(X)	RELTAB_IS_SEG_RELATIVE(X, reloc_table)
115*ba2be530Sab196087 #define	IS_EXTOFFSET(X)		RELTAB_IS_EXTOFFSET(X, reloc_table)
116*ba2be530Sab196087 #define	IS_SEC_RELATIVE(X)	RELTAB_IS_SEC_RELATIVE(X, reloc_table)
117*ba2be530Sab196087 #define	IS_TLS_INS(X)		RELTAB_IS_TLS_INS(X, reloc_table)
118*ba2be530Sab196087 #define	IS_TLS_GD(X)		RELTAB_IS_TLS_GD(X, reloc_table)
119*ba2be530Sab196087 #define	IS_TLS_LD(X)		RELTAB_IS_TLS_LD(X, reloc_table)
120*ba2be530Sab196087 #define	IS_TLS_IE(X)		RELTAB_IS_TLS_IE(X, reloc_table)
121*ba2be530Sab196087 #define	IS_TLS_LE(X)		RELTAB_IS_TLS_LE(X, reloc_table)
122*ba2be530Sab196087 #define	IS_LOCALBND(X)		RELTAB_IS_LOCALBND(X, reloc_table)
123*ba2be530Sab196087 #define	IS_SIZE(X)		RELTAB_IS_SIZE(X, reloc_table)
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1265aefb655Srie  * Relocation engine.
127f3324781Sab196087  *
128f3324781Sab196087  * The do_reloc() code is used in three different places: The kernel,
129f3324781Sab196087  * the linker, and the runtime linker. All three use the same first
130f3324781Sab196087  * 5 arguments. In addition:
131f3324781Sab196087  *	- The linker and rtld want a link map pointer argument
132f3324781Sab196087  *	- The linker wants to pass a byte swap argument that tells
133f3324781Sab196087  *		the relocation engine that the data it is relocating
134f3324781Sab196087  *		has the opposite byte order of the system running the
135f3324781Sab196087  *		linker.
136*ba2be530Sab196087  *	- The linker is a cross-linker, meaning that it can examine
137*ba2be530Sab196087  *		relocation records for target hosts other than that of
138*ba2be530Sab196087  *		the currently running system. This means that multiple
139*ba2be530Sab196087  *		versions of the relocation code must be able to reside
140*ba2be530Sab196087  *		in a single program, without namespace clashes.
141f3324781Sab196087  *
142f3324781Sab196087  * To ensure that there is never any confusion about which version is
143f3324781Sab196087  * being linked to, we give each variant a different name, even though
144f3324781Sab196087  * each one is generated from the same source code.
145f3324781Sab196087  *
146f3324781Sab196087  *	do_reloc_krtld()
147f3324781Sab196087  *	The kernel version is provided if the _KERNEL macro is defined.
148f3324781Sab196087  *
149f3324781Sab196087  *	do_reloc_ld()
150*ba2be530Sab196087  *	The ld version is provided if the DO_RELOC_LIBLD_ macro is defined.
151f3324781Sab196087  *
152f3324781Sab196087  *	do_reloc_rtld()
153f3324781Sab196087  *	The rtld version is provided if neither _KERNEL or DO_RELOC_LIBLD
154f3324781Sab196087  *	are defined.
155f3324781Sab196087  *
156f3324781Sab196087  * Implementations of do_reloc() should use these same macros to
157f3324781Sab196087  * conditionalize any code not used by all three versions.
1587c478bd9Sstevel@tonic-gate  */
159f3324781Sab196087 #if defined(_KERNEL)
160f3324781Sab196087 extern	int	do_reloc_krtld(uchar_t, uchar_t *, Xword *, const char *,
161f3324781Sab196087 		    const char *);
162f3324781Sab196087 #elif defined(DO_RELOC_LIBLD)
163f3324781Sab196087 extern	int	do_reloc_ld(uchar_t, uchar_t *, Xword *, const char *,
164f3324781Sab196087 		    const char *, int, void *);
165f3324781Sab196087 #else
166f3324781Sab196087 extern	int	do_reloc_rtld(uchar_t, uchar_t *, Xword *, const char *,
1675aefb655Srie 		    const char *, void *);
168f3324781Sab196087 #endif
169552ff457Srie 
1707c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
1717c478bd9Sstevel@tonic-gate /*
172552ff457Srie  * These are macro's that are only needed for krtld.  Many of these are already
173552ff457Srie  * defined in the sgs/include files referenced by ld and rtld
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate #define	S_MASK(n)	((1l << (n)) - 1l)
1767c478bd9Sstevel@tonic-gate #define	S_INRANGE(v, n)	(((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate /*
179552ff457Srie  * Message strings used by doreloc().
1807c478bd9Sstevel@tonic-gate  */
1817c478bd9Sstevel@tonic-gate #define	MSG_STR_UNKNOWN		"(unknown)"
182552ff457Srie 
183552ff457Srie #define	MSG_REL_PREGEN		"relocation error: %s: "
184552ff457Srie #define	MSG_REL_PREFIL		"relocation error: file %s: "
185552ff457Srie #define	MSG_REL_FILE		"file %s: "
186552ff457Srie #define	MSG_REL_SYM		"symbol %s: "
187552ff457Srie #define	MSG_REL_VALUE		"value 0x%llx "
1887c478bd9Sstevel@tonic-gate #define	MSG_REL_LOSEBITS	"loses %d bits at "
1897c478bd9Sstevel@tonic-gate 
190552ff457Srie #define	MSG_REL_UNIMPL		"unimplemented relocation type: %d"
191552ff457Srie #define	MSG_REL_UNSUPSZ		"offset size (%d bytes) is not supported"
192552ff457Srie #define	MSG_REL_NONALIGN	"offset 0x%llx is non-aligned"
193552ff457Srie #define	MSG_REL_UNNOBITS	"unsupported number of bits: %d"
194552ff457Srie #define	MSG_REL_OFFSET		"offset 0x%llx"
195552ff457Srie #define	MSG_REL_NOFIT		"value 0x%llx does not fit"
196552ff457Srie 
1975aefb655Srie /*
1985aefb655Srie  * Provide a macro to select the appropriate conversion routine for this
1995aefb655Srie  * architecture.
2005aefb655Srie  */
2015aefb655Srie #if defined(__amd64)
2025aefb655Srie 
2035aefb655Srie extern const char	*conv_reloc_amd64_type(Word);
2045aefb655Srie #define	CONV_RELOC_TYPE	conv_reloc_amd64_type
2055aefb655Srie 
2065aefb655Srie #elif defined(__i386)
2075aefb655Srie 
2085aefb655Srie extern const char	*conv_reloc_386_type(Word);
2095aefb655Srie #define	CONV_RELOC_TYPE	conv_reloc_386_type
2105aefb655Srie 
2115aefb655Srie #elif defined(__sparc)
2125aefb655Srie 
2135aefb655Srie extern const char	*conv_reloc_SPARC_type(Word);
2145aefb655Srie #define	CONV_RELOC_TYPE	conv_reloc_SPARC_type
2155aefb655Srie 
2165aefb655Srie #else
2175aefb655Srie #error platform not defined!
2185aefb655Srie #endif
2197c478bd9Sstevel@tonic-gate 
220*ba2be530Sab196087 
2217c478bd9Sstevel@tonic-gate /*
2225aefb655Srie  * Note:  dlerror() only keeps track of a single error string, and therefore
2235aefb655Srie  * must have errors reported through a single eprintf() call.  The kernel's
2245aefb655Srie  * _kobj_printf is somewhat more limited, and must receive messages with only
2255aefb655Srie  * one argument to the format string.  The following macros account for these
226f3324781Sab196087  * differences, as krtld and rtld share the same do_reloc() source.
2277c478bd9Sstevel@tonic-gate  */
2285aefb655Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
229552ff457Srie 	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
230552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
231552ff457Srie 	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
232552ff457Srie 
2335aefb655Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
234552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
235552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
236552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
237552ff457Srie 	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
2387c478bd9Sstevel@tonic-gate 
2395aefb655Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
240552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
241552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
242552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
243552ff457Srie 	_kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
2447c478bd9Sstevel@tonic-gate 
2455aefb655Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
246552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
247552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
248552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
249552ff457Srie 	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
2507c478bd9Sstevel@tonic-gate 
2515aefb655Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
252552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
253552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
254552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
255552ff457Srie 	_kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
256552ff457Srie 	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
2575aefb655Srie 	_kobj_printf(ops, MSG_REL_OFFSET, EC_NATPTR((off)))
2587c478bd9Sstevel@tonic-gate 
2595aefb655Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
260552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
261552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
262552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
263552ff457Srie 	_kobj_printf(ops, MSG_REL_NOFIT, EC_XWORD((uvalue)))
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate #else	/* !_KERNEL */
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate extern	const char *demangle(const char *);
2697c478bd9Sstevel@tonic-gate 
2705aefb655Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
2715aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
272552ff457Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
273552ff457Srie 
2745aefb655Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
2755aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
276de777a60Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
277552ff457Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
2787c478bd9Sstevel@tonic-gate 
2795aefb655Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
2805aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
281de777a60Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
282552ff457Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
2837c478bd9Sstevel@tonic-gate 
2845aefb655Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
2855aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
286de777a60Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2877c478bd9Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
2887c478bd9Sstevel@tonic-gate 
2895aefb655Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
2905aefb655Srie 	(eprintf(lml, ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
291de777a60Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2927c478bd9Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
2935aefb655Srie 	    EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
2947c478bd9Sstevel@tonic-gate 
2955aefb655Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
2965aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
297de777a60Sab196087 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
2987c478bd9Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
2997c478bd9Sstevel@tonic-gate 	    EC_XWORD((uvalue))))
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate #endif
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate #endif /* _RELOC_DOT_H */
308