xref: /illumos-gate/usr/src/uts/common/krtld/reloc.h (revision 4859da61)
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 /*
23bf994817SAli Bahrami  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
24c61137dfSJohn Levon  *
25c61137dfSJohn Levon  * Copyright 2020 Joyent, Inc.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #ifndef	_RELOC_DOT_H
297c478bd9Sstevel@tonic-gate #define	_RELOC_DOT_H
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
327c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
337c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
347c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h>
357c478bd9Sstevel@tonic-gate #else
365aefb655Srie #include <rtld.h>
37552ff457Srie #include <conv.h>
387c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
397c478bd9Sstevel@tonic-gate 
40ba2be530Sab #include "reloc_defs.h"
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
437c478bd9Sstevel@tonic-gate extern "C" {
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * Global include file for relocation common code.
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
515aefb655Srie  * In user land, redefine the relocation table and relocation engine to be
52ba2be530Sab  * class/machine specific if necessary.  This allows multiple engines to
53ba2be530Sab  * reside within a single instance of libld.
545aefb655Srie  */
555aefb655Srie #if	!defined(_KERNEL)
56ba2be530Sab 
57ba2be530Sab #if defined(DO_RELOC_LIBLD)
58ba2be530Sab #undef DO_RELOC_LIBLD
59ba2be530Sab #endif
60ba2be530Sab 
61ba2be530Sab #if	defined(DO_RELOC_LIBLD_X86)
62ba2be530Sab 
63ba2be530Sab #define	DO_RELOC_LIBLD
64ba2be530Sab #if	defined(_ELF64)
65ba2be530Sab #define	do_reloc_ld		do64_reloc_ld_x86
66ba2be530Sab #define	reloc_table		reloc64_table_x86
67ba2be530Sab #else
68ba2be530Sab #define	do_reloc_ld		do32_reloc_ld_x86
69ba2be530Sab #define	reloc_table		reloc32_table_x86
70ba2be530Sab #endif
71ba2be530Sab 
72ba2be530Sab #elif	defined(DO_RELOC_LIBLD_SPARC)
73ba2be530Sab 
74ba2be530Sab #define	DO_RELOC_LIBLD
75ba2be530Sab #if	defined(_ELF64)
76ba2be530Sab #define	do_reloc_ld		do64_reloc_ld_sparc
77ba2be530Sab #define	reloc_table		reloc64_table_sparc
78ba2be530Sab #else
79ba2be530Sab #define	do_reloc_ld		do32_reloc_ld_sparc
80ba2be530Sab #define	reloc_table		reloc32_table_sparc
81ba2be530Sab #endif
82ba2be530Sab 
83ba2be530Sab #else				/* rtld */
84ba2be530Sab 
855aefb655Srie #if	defined(_ELF64)
86f3324781Sab #define	do_reloc_rtld		do64_reloc_rtld
875aefb655Srie #define	reloc_table		reloc64_table
885aefb655Srie #else
89f3324781Sab #define	do_reloc_rtld		do32_reloc_rtld
905aefb655Srie #define	reloc_table		reloc32_table
915aefb655Srie #endif
92ba2be530Sab 
935aefb655Srie #endif
945aefb655Srie 
95ba2be530Sab #endif	/* !_KERNEL */
96ba2be530Sab 
975aefb655Srie /*
985aefb655Srie  * Relocation table and macros for testing relocation table flags.
997c478bd9Sstevel@tonic-gate  */
100ba2be530Sab extern	const Rel_entry	reloc_table[];
101ba2be530Sab 
102ba2be530Sab #define	IS_PLT(X)		RELTAB_IS_PLT(X, reloc_table)
103ba2be530Sab #define	IS_GOT_RELATIVE(X)	RELTAB_IS_GOT_RELATIVE(X, reloc_table)
104ba2be530Sab #define	IS_GOT_PC(X)		RELTAB_IS_GOT_PC(X, reloc_table)
105ba2be530Sab #define	IS_GOTPCREL(X)		RELTAB_IS_GOTPCREL(X, reloc_table)
106ba2be530Sab #define	IS_GOT_BASED(X)		RELTAB_IS_GOT_BASED(X, reloc_table)
107ba2be530Sab #define	IS_GOT_OPINS(X)		RELTAB_IS_GOT_OPINS(X, reloc_table)
108ba2be530Sab #define	IS_GOT_REQUIRED(X)	RELTAB_IS_GOT_REQUIRED(X, reloc_table)
109ba2be530Sab #define	IS_PC_RELATIVE(X)	RELTAB_IS_PC_RELATIVE(X, reloc_table)
110ba2be530Sab #define	IS_ADD_RELATIVE(X)	RELTAB_IS_ADD_RELATIVE(X, reloc_table)
111ba2be530Sab #define	IS_REGISTER(X)		RELTAB_IS_REGISTER(X, reloc_table)
112ba2be530Sab #define	IS_NOTSUP(X)		RELTAB_IS_NOTSUP(X, reloc_table)
113ba2be530Sab #define	IS_SEG_RELATIVE(X)	RELTAB_IS_SEG_RELATIVE(X, reloc_table)
114ba2be530Sab #define	IS_EXTOFFSET(X)		RELTAB_IS_EXTOFFSET(X, reloc_table)
115ba2be530Sab #define	IS_SEC_RELATIVE(X)	RELTAB_IS_SEC_RELATIVE(X, reloc_table)
116ba2be530Sab #define	IS_TLS_INS(X)		RELTAB_IS_TLS_INS(X, reloc_table)
117ba2be530Sab #define	IS_TLS_GD(X)		RELTAB_IS_TLS_GD(X, reloc_table)
118ba2be530Sab #define	IS_TLS_LD(X)		RELTAB_IS_TLS_LD(X, reloc_table)
119ba2be530Sab #define	IS_TLS_IE(X)		RELTAB_IS_TLS_IE(X, reloc_table)
120ba2be530Sab #define	IS_TLS_LE(X)		RELTAB_IS_TLS_LE(X, reloc_table)
121ba2be530Sab #define	IS_LOCALBND(X)		RELTAB_IS_LOCALBND(X, reloc_table)
122ba2be530Sab #define	IS_SIZE(X)		RELTAB_IS_SIZE(X, reloc_table)
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate /*
1255aefb655Srie  * Relocation engine.
126f3324781Sab  *
127f3324781Sab  * The do_reloc() code is used in three different places: The kernel,
128bf994817SAli Bahrami  * the link-editor, and the runtime linker. All three convey the same
129bf994817SAli Bahrami  * basic information with the first 5 arguments:
130bf994817SAli Bahrami  *
131bf994817SAli Bahrami  * 1)	Relocation type. The kernel and runtime linker pass this as
132bf994817SAli Bahrami  *	an integer value, while the link-editor passes it as a Rel_desc
133bf994817SAli Bahrami  *	descriptor. The relocation engine only looks at the rel_rtype
134bf994817SAli Bahrami  *	field of this descriptor, and does not examine the other fields,
135bf994817SAli Bahrami  *	which are explicitly allowed to contain garbage.
136bf994817SAli Bahrami  * 2)	Address of offset
137bf994817SAli Bahrami  * 3)	Address of value
138bf994817SAli Bahrami  * 4)	Name of symbol associated with the relocation, used if it is
139bf994817SAli Bahrami  *	necessary to report an error. The kernel and runtime linker pass
140bf994817SAli Bahrami  *	directly as a string pointer. The link-editor passes the address
141bf994817SAli Bahrami  *	of a rel_desc_sname_func_t function, which can be called by do_reloc(),
142bf994817SAli Bahrami  *	passing it the Rel_desc pointer (argument 1, above), to obtain the
143bf994817SAli Bahrami  *	string pointer.
144bf994817SAli Bahrami  * 5)	String giving the source file for the relocation.
145bf994817SAli Bahrami  *
146bf994817SAli Bahrami  * In addition:
147f3324781Sab  *	- The linker and rtld want a link map pointer argument
148f3324781Sab  *	- The linker wants to pass a byte swap argument that tells
149f3324781Sab  *		the relocation engine that the data it is relocating
150f3324781Sab  *		has the opposite byte order of the system running the
151f3324781Sab  *		linker.
152ba2be530Sab  *	- The linker is a cross-linker, meaning that it can examine
153ba2be530Sab  *		relocation records for target hosts other than that of
154ba2be530Sab  *		the currently running system. This means that multiple
155ba2be530Sab  *		versions of the relocation code must be able to reside
156ba2be530Sab  *		in a single program, without namespace clashes.
157f3324781Sab  *
158f3324781Sab  * To ensure that there is never any confusion about which version is
159f3324781Sab  * being linked to, we give each variant a different name, even though
160f3324781Sab  * each one is generated from the same source code.
161f3324781Sab  *
162f3324781Sab  *	do_reloc_krtld()
163f3324781Sab  *	The kernel version is provided if the _KERNEL macro is defined.
164f3324781Sab  *
165f3324781Sab  *	do_reloc_ld()
166ba2be530Sab  *	The ld version is provided if the DO_RELOC_LIBLD_ macro is defined.
167f3324781Sab  *
168f3324781Sab  *	do_reloc_rtld()
169f3324781Sab  *	The rtld version is provided if neither _KERNEL or DO_RELOC_LIBLD
170f3324781Sab  *	are defined.
171f3324781Sab  *
172f3324781Sab  * Implementations of do_reloc() should use these same macros to
173f3324781Sab  * conditionalize any code not used by all three versions.
1747c478bd9Sstevel@tonic-gate  */
175f3324781Sab #if defined(_KERNEL)
176f3324781Sab extern	int	do_reloc_krtld(uchar_t, uchar_t *, Xword *, const char *,
177f3324781Sab 		    const char *);
178f3324781Sab #elif defined(DO_RELOC_LIBLD)
179bf994817SAli Bahrami extern	int	do_reloc_ld(Rel_desc *, uchar_t *, Xword *,
180bf994817SAli Bahrami 		    rel_desc_sname_func_t, const char *, int, void *);
181f3324781Sab #else
182f3324781Sab extern	int	do_reloc_rtld(uchar_t, uchar_t *, Xword *, const char *,
1835aefb655Srie 		    const char *, void *);
184f3324781Sab #endif
185552ff457Srie 
1867c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
1877c478bd9Sstevel@tonic-gate /*
188552ff457Srie  * These are macro's that are only needed for krtld.  Many of these are already
189552ff457Srie  * defined in the sgs/include files referenced by ld and rtld
1907c478bd9Sstevel@tonic-gate  */
1917c478bd9Sstevel@tonic-gate #define	S_MASK(n)	((1l << (n)) - 1l)
1927c478bd9Sstevel@tonic-gate #define	S_INRANGE(v, n)	(((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
195552ff457Srie  * Message strings used by doreloc().
1967c478bd9Sstevel@tonic-gate  */
197552ff457Srie #define	MSG_STR_UNKNOWN		"(unknown)"
1987c478bd9Sstevel@tonic-gate 
199552ff457Srie #define	MSG_REL_PREGEN		"relocation error: %s: "
200552ff457Srie #define	MSG_REL_PREFIL		"relocation error: file %s: "
201552ff457Srie #define	MSG_REL_FILE		"file %s: "
202552ff457Srie #define	MSG_REL_SYM		"symbol %s: "
203552ff457Srie #define	MSG_REL_VALUE		"value 0x%llx "
204552ff457Srie #define	MSG_REL_LOSEBITS	"loses %d bits at "
2057c478bd9Sstevel@tonic-gate 
206552ff457Srie #define	MSG_REL_UNIMPL		"unimplemented relocation type: %d"
207552ff457Srie #define	MSG_REL_UNSUPSZ		"offset size (%d bytes) is not supported"
208552ff457Srie #define	MSG_REL_NONALIGN	"offset 0x%llx is non-aligned"
209552ff457Srie #define	MSG_REL_UNNOBITS	"unsupported number of bits: %d"
210552ff457Srie #define	MSG_REL_OFFSET		"offset 0x%llx"
211552ff457Srie #define	MSG_REL_NOFIT		"value 0x%llx does not fit"
212552ff457Srie 
2135aefb655Srie /*
2145aefb655Srie  * Provide a macro to select the appropriate conversion routine for this
2155aefb655Srie  * architecture.
2165aefb655Srie  */
2175aefb655Srie #if defined(__amd64)
2185aefb655Srie 
2195aefb655Srie extern const char	*conv_reloc_amd64_type(Word);
2205aefb655Srie #define	CONV_RELOC_TYPE	conv_reloc_amd64_type
2215aefb655Srie 
2225aefb655Srie #elif defined(__i386)
2235aefb655Srie 
2245aefb655Srie extern const char	*conv_reloc_386_type(Word);
2255aefb655Srie #define	CONV_RELOC_TYPE	conv_reloc_386_type
2265aefb655Srie 
2275aefb655Srie #elif defined(__sparc)
2285aefb655Srie 
2295aefb655Srie extern const char	*conv_reloc_SPARC_type(Word);
2305aefb655Srie #define	CONV_RELOC_TYPE	conv_reloc_SPARC_type
2315aefb655Srie 
2325aefb655Srie #else
2335aefb655Srie #error platform not defined!
2345aefb655Srie #endif
2357c478bd9Sstevel@tonic-gate 
236ba2be530Sab 
2377c478bd9Sstevel@tonic-gate /*
2385aefb655Srie  * Note:  dlerror() only keeps track of a single error string, and therefore
2395aefb655Srie  * must have errors reported through a single eprintf() call.  The kernel's
2405aefb655Srie  * _kobj_printf is somewhat more limited, and must receive messages with only
2415aefb655Srie  * one argument to the format string.  The following macros account for these
242f3324781Sab  * differences, as krtld and rtld share the same do_reloc() source.
2437c478bd9Sstevel@tonic-gate  */
2445aefb655Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
245552ff457Srie 	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
246552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
247552ff457Srie 	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
248552ff457Srie 
2495aefb655Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
250552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
251552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
252552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
253552ff457Srie 	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
2547c478bd9Sstevel@tonic-gate 
2555aefb655Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
256552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
257552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
258552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
259*4859da61SToomas Soome 	_kobj_printf(ops, MSG_REL_NONALIGN, (u_longlong_t)EC_OFF((off)))
2607c478bd9Sstevel@tonic-gate 
2615aefb655Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
262552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
263552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
264552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
265552ff457Srie 	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
2667c478bd9Sstevel@tonic-gate 
2675aefb655Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
268552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
269552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
270552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
271*4859da61SToomas Soome 	_kobj_printf(ops, MSG_REL_VALUE, (u_longlong_t)EC_XWORD((uvalue))); \
272552ff457Srie 	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
273*4859da61SToomas Soome 	_kobj_printf(ops, MSG_REL_OFFSET, (u_longlong_t)EC_NATPTR((off)))
2747c478bd9Sstevel@tonic-gate 
2755aefb655Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
276552ff457Srie 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
277552ff457Srie 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
278552ff457Srie 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
279c61137dfSJohn Levon 	_kobj_printf(ops, MSG_REL_NOFIT, (u_longlong_t)EC_XWORD((uvalue)))
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate #else	/* !_KERNEL */
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate extern	const char *demangle(const char *);
2857c478bd9Sstevel@tonic-gate 
2865aefb655Srie #define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
2875aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
288552ff457Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
289552ff457Srie 
2905aefb655Srie #define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
2915aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
292de777a60Sab 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
293552ff457Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
2947c478bd9Sstevel@tonic-gate 
2955aefb655Srie #define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
2965aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
297de777a60Sab 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
298552ff457Srie 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
2997c478bd9Sstevel@tonic-gate 
3005aefb655Srie #define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
3015aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
302de777a60Sab 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
3037c478bd9Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
3047c478bd9Sstevel@tonic-gate 
3055aefb655Srie #define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
3065aefb655Srie 	(eprintf(lml, ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
307de777a60Sab 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
3087c478bd9Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
3095aefb655Srie 	    EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
3107c478bd9Sstevel@tonic-gate 
3115aefb655Srie #define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
3125aefb655Srie 	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
313de777a60Sab 	    conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
3147c478bd9Sstevel@tonic-gate 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
3157c478bd9Sstevel@tonic-gate 	    EC_XWORD((uvalue))))
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate #endif
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate #endif /* _RELOC_DOT_H */
324