xref: /illumos-gate/usr/src/uts/common/krtld/reloc.h (revision 7f7322febbcfe774b7270abc3b191c094bfcc517)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #ifndef	_RELOC_DOT_H
29 #define	_RELOC_DOT_H
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #if defined(_KERNEL)
34 #include <sys/machelf.h>
35 #include <sys/bootconf.h>
36 #include <sys/kobj.h>
37 #include <sys/kobj_impl.h>
38 #else
39 #include <machdep.h>
40 #include <conv.h>
41 #endif /* _KERNEL */
42 
43 #include <relmach.h>
44 
45 #ifdef	__cplusplus
46 extern "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  * Macros for testing relocation table flags
85  */
86 extern	const Rel_entry		reloc_table[];
87 
88 #define	IS_PLT(X)		((reloc_table[(X)].re_flags & \
89 					FLG_RE_PLTREL) != 0)
90 #define	IS_GOT_RELATIVE(X)	((reloc_table[(X)].re_flags & \
91 					FLG_RE_GOTADD) != 0)
92 #define	IS_GOT_PC(X)		((reloc_table[(X)].re_flags & \
93 					FLG_RE_GOTPC) != 0)
94 #define	IS_GOTPCREL(X)		((reloc_table[(X)].re_flags & \
95 					(FLG_RE_GOTPC | FLG_RE_GOTADD)) == \
96 					(FLG_RE_GOTPC | FLG_RE_GOTADD))
97 #define	IS_GOT_BASED(X)		((reloc_table[(X)].re_flags & \
98 					FLG_RE_GOTREL) != 0)
99 #define	IS_GOT_INS(X)		((reloc_table[(X)].re_flags & \
100 					FLG_RE_GOTOPINS) != 0)
101 #define	IS_GOT_REQUIRED(X)	((reloc_table[(X)].re_flags & \
102 					(FLG_RE_GOTADD | FLG_RE_GOTREL | \
103 					FLG_RE_GOTPC | FLG_RE_GOTOPINS)) != 0)
104 #define	IS_PC_RELATIVE(X)	((reloc_table[(X)].re_flags & \
105 					FLG_RE_PCREL) != 0)
106 #define	IS_ADD_RELATIVE(X)	((reloc_table[(X)].re_flags & \
107 					FLG_RE_ADDRELATIVE) != 0)
108 #define	IS_REGISTER(X)		((reloc_table[(X)].re_flags & \
109 					FLG_RE_REGISTER) != 0)
110 #define	IS_FORMOFF(X)		((reloc_table[(X)].re_flags &\
111 					FLG_RE_FRMOFF) != 0)
112 #define	IS_NOTSUP(X)		((reloc_table[(X)].re_flags &\
113 					FLG_RE_NOTSUP) != 0)
114 #define	IS_SEG_RELATIVE(X)	((reloc_table[(X)].re_flags &\
115 					FLG_RE_SEGREL) != 0)
116 #define	IS_EXTOFFSET(X)		((reloc_table[(X)].re_flags &\
117 					FLG_RE_EXTOFFSET) != 0)
118 #define	IS_SEC_RELATIVE(X)	((reloc_table[(X)].re_flags &\
119 					FLG_RE_SECREL) != 0)
120 #define	IS_TLS_INS(X)		((reloc_table[(X)].re_flags &\
121 					FLG_RE_TLSINS) != 0)
122 #define	IS_TLS_GD(X)		((reloc_table[(X)].re_flags &\
123 					FLG_RE_TLSGD) != 0)
124 #define	IS_TLS_LD(X)		((reloc_table[(X)].re_flags &\
125 					FLG_RE_TLSLD) != 0)
126 #define	IS_TLS_IE(X)		((reloc_table[(X)].re_flags &\
127 					FLG_RE_TLSIE) != 0)
128 #define	IS_TLS_LE(X)		((reloc_table[(X)].re_flags &\
129 					FLG_RE_TLSLE) != 0)
130 #define	IS_TLS(X)		((reloc_table[(X)].re_flags &\
131 					(FLG_RE_TLSINS|FLG_RE_TLSGD| \
132 					FLG_RE_TLSLD|FLG_RE_TLSIE| \
133 					FLG_RE_TLSLE)) != 0)
134 #define	IS_LOCALBND(X)		((reloc_table[(X)].re_flags &\
135 					FLG_RE_LOCLBND) != 0)
136 
137 /*
138  * Functions.
139  */
140 extern	int	do_reloc(uchar_t, uchar_t *, Xword *, const char *,
141 		    const char *);
142 
143 /*
144  * Provide a macro to select the appropriate convension routine for this
145  * architecture.
146  */
147 #if defined(__amd64)
148 #define	CONV_RELOC_TYPE		conv_reloc_amd64_type_str
149 #elif defined(__i386)
150 #define	CONV_RELOC_TYPE		conv_reloc_386_type_str
151 #elif defined(__sparc)
152 #define	CONV_RELOC_TYPE		conv_reloc_SPARC_type_str
153 #else
154 #error platform not defined!
155 #endif
156 
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 extern const char	 *conv_reloc_386_type_str(uint_t);
186 extern const char	 *conv_reloc_amd64_type_str(uint_t);
187 extern const char	 *conv_reloc_SPARC_type_str(uint_t);
188 
189 /*
190  * Note:  Related to bug 4128755, dlerror() only keeps track of a single error
191  * string, and therefore must have errors reported through a single eprintf()
192  * call.  The kernel's _kobj_printf is somewhat more limited, and must receive
193  * messages with only one arguement to the format string.  The following macros
194  * are to straighted all this out because krtld and rtld share do_reloc().
195  */
196 #define	REL_ERR_UNIMPL(file, sym, rtype) \
197 	_kobj_printf(ops, MSG_REL_PREFIL, (file)); \
198 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
199 	_kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
200 
201 #define	REL_ERR_UNSUPSZ(file, sym, rtype, size) \
202 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
203 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
204 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
205 	_kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
206 
207 #define	REL_ERR_NONALIGN(file, sym, rtype, off) \
208 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
209 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
210 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
211 	_kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
212 
213 #define	REL_ERR_UNNOBITS(file, sym, rtype, nbits) \
214 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
215 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
216 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
217 	_kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
218 
219 #define	REL_ERR_LOSEBITS(file, sym, rtype, uvalue, nbits, off) \
220 	_kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
221 	_kobj_printf(ops, MSG_REL_FILE, (file)); \
222 	_kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
223 	_kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
224 	_kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
225 	_kobj_printf(ops, MSG_REL_OFFSET, EC_ADDR((off)))
226 
227 #define	REL_ERR_NOFIT(file, sym, rtype, uvalue) \
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_NOFIT, EC_XWORD((uvalue)))
232 
233 
234 #else	/* !_KERNEL */
235 
236 extern	const char *demangle(const char *);
237 
238 #define	REL_ERR_UNIMPL(file, sym, rtype) \
239 	(eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
240 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
241 
242 #define	REL_ERR_UNSUPSZ(file, sym, rtype, size) \
243 	(eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
244 	    CONV_RELOC_TYPE((rtype)), (file), \
245 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
246 
247 #define	REL_ERR_NONALIGN(file, sym, rtype, off) \
248 	(eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
249 	    CONV_RELOC_TYPE((rtype)), (file), \
250 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
251 
252 #define	REL_ERR_UNNOBITS(file, sym, rtype, nbits) \
253 	(eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
254 	    CONV_RELOC_TYPE((rtype)), (file), \
255 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
256 
257 #define	REL_ERR_LOSEBITS(file, sym, rtype, uvalue, nbits, off) \
258 	(eprintf(ERR_FATAL,  MSG_INTL(MSG_REL_LOSEBITS), \
259 	    CONV_RELOC_TYPE((rtype)), (file), \
260 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
261 	    EC_XWORD((uvalue)), (nbits), EC_ADDR((off))))
262 
263 #define	REL_ERR_NOFIT(file, sym, rtype, uvalue) \
264 	(eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
265 	    CONV_RELOC_TYPE((rtype)), (file), \
266 	    ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
267 	    EC_XWORD((uvalue))))
268 
269 #endif	/* _KERNEL */
270 
271 #ifdef	__cplusplus
272 }
273 #endif
274 
275 #endif /* _RELOC_DOT_H */
276