reloc.h revision 2647:e440e3da2a6f
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- */
67						/*	fixed 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
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_NOTSUP(X)		((reloc_table[(X)].re_flags & \
126					FLG_RE_NOTSUP) != 0)
127#define	IS_SEG_RELATIVE(X)	((reloc_table[(X)].re_flags & \
128					FLG_RE_SEGREL) != 0)
129#define	IS_EXTOFFSET(X)		((reloc_table[(X)].re_flags & \
130					FLG_RE_EXTOFFSET) != 0)
131#define	IS_SEC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
132					FLG_RE_SECREL) != 0)
133#define	IS_TLS_INS(X)		((reloc_table[(X)].re_flags & \
134					(FLG_RE_TLSGD | FLG_RE_TLSLD | \
135					FLG_RE_TLSIE | FLG_RE_TLSLE)) != 0)
136#define	IS_TLS_GD(X)		((reloc_table[(X)].re_flags & \
137					FLG_RE_TLSGD) != 0)
138#define	IS_TLS_LD(X)		((reloc_table[(X)].re_flags & \
139					FLG_RE_TLSLD) != 0)
140#define	IS_TLS_IE(X)		((reloc_table[(X)].re_flags & \
141					FLG_RE_TLSIE) != 0)
142#define	IS_TLS_LE(X)		((reloc_table[(X)].re_flags & \
143					FLG_RE_TLSLE) != 0)
144#define	IS_LOCALBND(X)		((reloc_table[(X)].re_flags & \
145					FLG_RE_LOCLBND) != 0)
146
147/*
148 * Relocation engine.
149 */
150extern	int	do_reloc(uchar_t, uchar_t *, Xword *, const char *,
151		    const char *, void *);
152
153#if defined(_KERNEL)
154/*
155 * These are macro's that are only needed for krtld.  Many of these are already
156 * defined in the sgs/include files referenced by ld and rtld
157 */
158#define	S_MASK(n)	((1l << (n)) - 1l)
159#define	S_INRANGE(v, n)	(((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
160
161/*
162 * Message strings used by doreloc().
163 */
164#define	MSG_STR_UNKNOWN		"(unknown)"
165
166#define	MSG_REL_PREGEN		"relocation error: %s: "
167#define	MSG_REL_PREFIL		"relocation error: file %s: "
168#define	MSG_REL_FILE		"file %s: "
169#define	MSG_REL_SYM		"symbol %s: "
170#define	MSG_REL_VALUE		"value 0x%llx "
171#define	MSG_REL_LOSEBITS	"loses %d bits at "
172
173#define	MSG_REL_UNIMPL		"unimplemented relocation type: %d"
174#define	MSG_REL_UNSUPSZ		"offset size (%d bytes) is not supported"
175#define	MSG_REL_NONALIGN	"offset 0x%llx is non-aligned"
176#define	MSG_REL_UNNOBITS	"unsupported number of bits: %d"
177#define	MSG_REL_OFFSET		"offset 0x%llx"
178#define	MSG_REL_NOFIT		"value 0x%llx does not fit"
179
180/*
181 * Provide a macro to select the appropriate conversion routine for this
182 * architecture.
183 */
184#if defined(__amd64)
185
186extern const char	*conv_reloc_amd64_type(Word);
187#define	CONV_RELOC_TYPE	conv_reloc_amd64_type
188
189#elif defined(__i386)
190
191extern const char	*conv_reloc_386_type(Word);
192#define	CONV_RELOC_TYPE	conv_reloc_386_type
193
194#elif defined(__sparc)
195
196extern const char	*conv_reloc_SPARC_type(Word);
197#define	CONV_RELOC_TYPE	conv_reloc_SPARC_type
198
199#else
200#error platform not defined!
201#endif
202
203/*
204 * Note:  dlerror() only keeps track of a single error string, and therefore
205 * must have errors reported through a single eprintf() call.  The kernel's
206 * _kobj_printf is somewhat more limited, and must receive messages with only
207 * one argument to the format string.  The following macros account for these
208 * differences, as krtld and rtld share do_reloc().
209 */
210#define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
211	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
212	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
213	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
214
215#define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
216	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
217	_kobj_printf(ops, MSG_REL_FILE, (file)); \
218	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
219	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
220
221#define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
222	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
223	_kobj_printf(ops, MSG_REL_FILE, (file)); \
224	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
225	_kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
226
227#define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
228	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
229	_kobj_printf(ops, MSG_REL_FILE, (file)); \
230	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
231	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
232
233#define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
234	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
235	_kobj_printf(ops, MSG_REL_FILE, (file)); \
236	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
237	_kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
238	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
239	_kobj_printf(ops, MSG_REL_OFFSET, EC_NATPTR((off)))
240
241#define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
242	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
243	_kobj_printf(ops, MSG_REL_FILE, (file)); \
244	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
245	_kobj_printf(ops, MSG_REL_NOFIT, EC_XWORD((uvalue)))
246
247
248#else	/* !_KERNEL */
249
250extern	const char *demangle(const char *);
251
252#define	REL_ERR_UNIMPL(lml, file, sym, rtype) \
253	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
254	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
255
256#define	REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
257	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
258	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
259	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
260
261#define	REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
262	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
263	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
264	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
265
266#define	REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
267	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
268	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
269	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
270
271#define	REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
272	(eprintf(lml, ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
273	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
274	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
275	    EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
276
277#define	REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
278	(eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
279	    conv_reloc_type(M_MACH, (rtype), 0), (file), \
280	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
281	    EC_XWORD((uvalue))))
282
283#endif	/* _KERNEL */
284
285#ifdef	__cplusplus
286}
287#endif
288
289#endif /* _RELOC_DOT_H */
290