reloc.h revision 1976:f0691a145b7e
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef	_RELOC_DOT_H
28#define	_RELOC_DOT_H
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32#if defined(_KERNEL)
33#include <sys/machelf.h>
34#include <sys/bootconf.h>
35#include <sys/kobj.h>
36#include <sys/kobj_impl.h>
37#else
38#include <machdep.h>
39#include <rtld.h>
40#include <conv.h>
41#endif /* _KERNEL */
42
43#include <relmach.h>
44
45#ifdef	__cplusplus
46extern "C" {
47#endif
48
49/*
50 * Global include file for relocation common code.
51 *
52 * Flags for reloc_entry->re_flags
53 */
54#define	FLG_RE_NOTREL		0x00000000
55#define	FLG_RE_GOTADD		0x00000001	/* create a GOT entry */
56#define	FLG_RE_GOTREL		0x00000002	/* GOT based */
57#define	FLG_RE_GOTPC		0x00000004	/* GOT - P */
58#define	FLG_RE_GOTOPINS		0x00000008	/* GOTOP instruction */
59#define	FLG_RE_PCREL		0x00000010
60#define	FLG_RE_PLTREL		0x00000020
61#define	FLG_RE_VERIFY		0x00000040	/* verify value fits */
62#define	FLG_RE_UNALIGN		0x00000080	/* offset is not aligned */
63#define	FLG_RE_WDISP16		0x00000100	/* funky sparc DISP16 rel */
64#define	FLG_RE_SIGN		0x00000200	/* value is signed */
65#define	FLG_RE_ADDRELATIVE	0x00000400	/* RELATIVE relocation */
66						/* required for non-fixed */
67						/* objects */
68#define	FLG_RE_EXTOFFSET	0x00000800	/* extra offset required */
69#define	FLG_RE_REGISTER		0x00001000	/* relocation initializes */
70						/*    a REGISTER by OLO10 */
71#define	FLG_RE_NOTSUP		0x00010000	/* relocation not supported */
72
73#define	FLG_RE_SEGREL		0x00040000	/* segment relative */
74#define	FLG_RE_SECREL		0x00080000	/* section relative */
75#define	FLG_RE_TLSINS		0x00100000	/* TLS instructino rel */
76#define	FLG_RE_TLSGD		0x00200000	/* TLS GD relocation */
77#define	FLG_RE_TLSLD		0x00400000	/* TLS LD relocation */
78#define	FLG_RE_TLSIE		0x00800000	/* TLS IE relocation */
79#define	FLG_RE_TLSLE		0x01000000	/* TLS LE relocation */
80#define	FLG_RE_LOCLBND		0x02000000	/* relocation must bind */
81						/*    locally */
82
83/*
84 * In user land, redefine the relocation table and relocation engine to be
85 * class specific if necessary.  This allows both engines to reside in the
86 * intel/amd version of libld.
87 */
88#if	!defined(_KERNEL)
89#if	defined(_ELF64)
90#define	do_reloc		do64_reloc
91#define	reloc_table		reloc64_table
92#else
93#define	do_reloc		do32_reloc
94#define	reloc_table		reloc32_table
95#endif
96#endif
97
98/*
99 * Relocation table and macros for testing relocation table flags.
100 */
101extern	const Rel_entry		reloc_table[];
102
103#define	IS_PLT(X)		((reloc_table[(X)].re_flags & \
104					FLG_RE_PLTREL) != 0)
105#define	IS_GOT_RELATIVE(X)	((reloc_table[(X)].re_flags & \
106					FLG_RE_GOTADD) != 0)
107#define	IS_GOT_PC(X)		((reloc_table[(X)].re_flags & \
108					FLG_RE_GOTPC) != 0)
109#define	IS_GOTPCREL(X)		((reloc_table[(X)].re_flags & \
110					(FLG_RE_GOTPC | FLG_RE_GOTADD)) == \
111					(FLG_RE_GOTPC | FLG_RE_GOTADD))
112#define	IS_GOT_BASED(X)		((reloc_table[(X)].re_flags & \
113					FLG_RE_GOTREL) != 0)
114#define	IS_GOT_INS(X)		((reloc_table[(X)].re_flags & \
115					FLG_RE_GOTOPINS) != 0)
116#define	IS_GOT_REQUIRED(X)	((reloc_table[(X)].re_flags & \
117					(FLG_RE_GOTADD | FLG_RE_GOTREL | \
118					FLG_RE_GOTPC | FLG_RE_GOTOPINS)) != 0)
119#define	IS_PC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
120					FLG_RE_PCREL) != 0)
121#define	IS_ADD_RELATIVE(X)	((reloc_table[(X)].re_flags & \
122					FLG_RE_ADDRELATIVE) != 0)
123#define	IS_REGISTER(X)		((reloc_table[(X)].re_flags & \
124					FLG_RE_REGISTER) != 0)
125#define	IS_FORMOFF(X)		((reloc_table[(X)].re_flags & \
126					FLG_RE_FRMOFF) != 0)
127#define	IS_NOTSUP(X)		((reloc_table[(X)].re_flags & \
128					FLG_RE_NOTSUP) != 0)
129#define	IS_SEG_RELATIVE(X)	((reloc_table[(X)].re_flags & \
130					FLG_RE_SEGREL) != 0)
131#define	IS_EXTOFFSET(X)		((reloc_table[(X)].re_flags & \
132					FLG_RE_EXTOFFSET) != 0)
133#define	IS_SEC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
134					FLG_RE_SECREL) != 0)
135#define	IS_TLS_INS(X)		((reloc_table[(X)].re_flags & \
136					FLG_RE_TLSINS) != 0)
137#define	IS_TLS_GD(X)		((reloc_table[(X)].re_flags & \
138					FLG_RE_TLSGD) != 0)
139#define	IS_TLS_LD(X)		((reloc_table[(X)].re_flags & \
140					FLG_RE_TLSLD) != 0)
141#define	IS_TLS_IE(X)		((reloc_table[(X)].re_flags & \
142					FLG_RE_TLSIE) != 0)
143#define	IS_TLS_LE(X)		((reloc_table[(X)].re_flags & \
144					FLG_RE_TLSLE) != 0)
145#define	IS_TLS(X)		((reloc_table[(X)].re_flags & \
146					(FLG_RE_TLSINS|FLG_RE_TLSGD| \
147					FLG_RE_TLSLD|FLG_RE_TLSIE| \
148					FLG_RE_TLSLE)) != 0)
149#define	IS_LOCALBND(X)		((reloc_table[(X)].re_flags & \
150					FLG_RE_LOCLBND) != 0)
151
152/*
153 * Relocation engine.
154 */
155extern	int	do_reloc(uchar_t, uchar_t *, Xword *, const char *,
156		    const char *, void *);
157
158#if defined(_KERNEL)
159/*
160 * These are macro's that are only needed for krtld.  Many of these are already
161 * defined in the sgs/include files referenced by ld and rtld
162 */
163#define	S_MASK(n)	((1l << (n)) - 1l)
164#define	S_INRANGE(v, n)	(((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
165
166/*
167 * Message strings used by doreloc().
168 */
169#define	MSG_STR_UNKNOWN		"(unknown)"
170
171#define	MSG_REL_PREGEN		"relocation error: %s: "
172#define	MSG_REL_PREFIL		"relocation error: file %s: "
173#define	MSG_REL_FILE		"file %s: "
174#define	MSG_REL_SYM		"symbol %s: "
175#define	MSG_REL_VALUE		"value 0x%llx "
176#define	MSG_REL_LOSEBITS	"loses %d bits at "
177
178#define	MSG_REL_UNIMPL		"unimplemented relocation type: %d"
179#define	MSG_REL_UNSUPSZ		"offset size (%d bytes) is not supported"
180#define	MSG_REL_NONALIGN	"offset 0x%llx is non-aligned"
181#define	MSG_REL_UNNOBITS	"unsupported number of bits: %d"
182#define	MSG_REL_OFFSET		"offset 0x%llx"
183#define	MSG_REL_NOFIT		"value 0x%llx does not fit"
184
185/*
186 * Provide a macro to select the appropriate conversion routine for this
187 * architecture.
188 */
189#if defined(__amd64)
190
191extern const char	*conv_reloc_amd64_type(Word);
192#define	CONV_RELOC_TYPE	conv_reloc_amd64_type
193
194#elif defined(__i386)
195
196extern const char	*conv_reloc_386_type(Word);
197#define	CONV_RELOC_TYPE	conv_reloc_386_type
198
199#elif defined(__sparc)
200
201extern const char	*conv_reloc_SPARC_type(Word);
202#define	CONV_RELOC_TYPE	conv_reloc_SPARC_type
203
204#else
205#error platform not defined!
206#endif
207
208/*
209 * Note:  dlerror() only keeps track of a single error string, and therefore
210 * must have errors reported through a single eprintf() call.  The kernel's
211 * _kobj_printf is somewhat more limited, and must receive messages with only
212 * one argument to the format string.  The following macros account for these
213 * differences, as krtld and rtld share do_reloc().
214 */
215#define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
216	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
217	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
218	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
219
220#define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
221	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
222	_kobj_printf(ops, MSG_REL_FILE, (file)); \
223	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
224	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
225
226#define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
227	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
228	_kobj_printf(ops, MSG_REL_FILE, (file)); \
229	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
230	_kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
231
232#define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
233	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
234	_kobj_printf(ops, MSG_REL_FILE, (file)); \
235	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
236	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
237
238#define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
239	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
240	_kobj_printf(ops, MSG_REL_FILE, (file)); \
241	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
242	_kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
243	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
244	_kobj_printf(ops, MSG_REL_OFFSET, EC_NATPTR((off)))
245
246#define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
247	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
248	_kobj_printf(ops, MSG_REL_FILE, (file)); \
249	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
250	_kobj_printf(ops, MSG_REL_NOFIT, EC_XWORD((uvalue)))
251
252
253#else	/* !_KERNEL */
254
255extern	const char *demangle(const char *);
256
257#define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
258	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
259	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
260
261#define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
262	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
263	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
264	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
265
266#define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
267	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
268	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
269	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
270
271#define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
272	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
273	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
274	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
275
276#define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
277	(eprintf(lml, ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
278	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
279	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
280	    EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
281
282#define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
283	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
284	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
285	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
286	    EC_XWORD((uvalue))))
287
288#endif	/* _KERNEL */
289
290#ifdef	__cplusplus
291}
292#endif
293
294#endif /* _RELOC_DOT_H */
295