Merge illumos-gate
[unleashed.git] / include / krtld / reloc.h
blobf38806de5015e1608ea52334f05327226da7f31b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
26 #ifndef _RELOC_DOT_H
27 #define _RELOC_DOT_H
29 #if defined(_KERNEL)
30 #include <sys/bootconf.h>
31 #include <sys/kobj.h>
32 #include <sys/kobj_impl.h>
33 #else
34 #include <rtld.h>
35 #include <conv.h>
36 #endif /* _KERNEL */
38 #include <krtld/reloc_defs.h>
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
45 * Global include file for relocation common code.
49 * In user land, redefine the relocation table and relocation engine to be
50 * class/machine specific if necessary. This allows multiple engines to
51 * reside within a single instance of libld.
53 #if !defined(_KERNEL)
55 #if defined(DO_RELOC_LIBLD)
56 #undef DO_RELOC_LIBLD
57 #endif
59 #if defined(DO_RELOC_LIBLD_X86)
61 #define DO_RELOC_LIBLD
62 #if defined(_ELF64)
63 #define do_reloc_ld do64_reloc_ld_x86
64 #define reloc_table reloc64_table_x86
65 #else
66 #define do_reloc_ld do32_reloc_ld_x86
67 #define reloc_table reloc32_table_x86
68 #endif
70 #elif defined(DO_RELOC_LIBLD_SPARC)
72 #define DO_RELOC_LIBLD
73 #if defined(_ELF64)
74 #define do_reloc_ld do64_reloc_ld_sparc
75 #define reloc_table reloc64_table_sparc
76 #else
77 #define do_reloc_ld do32_reloc_ld_sparc
78 #define reloc_table reloc32_table_sparc
79 #endif
81 #else /* rtld */
83 #if defined(_ELF64)
84 #define do_reloc_rtld do64_reloc_rtld
85 #define reloc_table reloc64_table
86 #else
87 #define do_reloc_rtld do32_reloc_rtld
88 #define reloc_table reloc32_table
89 #endif
91 #endif
93 #endif /* !_KERNEL */
96 * Relocation table and macros for testing relocation table flags.
98 extern const Rel_entry reloc_table[];
100 #define IS_PLT(X) RELTAB_IS_PLT(X, reloc_table)
101 #define IS_GOT_RELATIVE(X) RELTAB_IS_GOT_RELATIVE(X, reloc_table)
102 #define IS_GOT_PC(X) RELTAB_IS_GOT_PC(X, reloc_table)
103 #define IS_GOTPCREL(X) RELTAB_IS_GOTPCREL(X, reloc_table)
104 #define IS_GOT_BASED(X) RELTAB_IS_GOT_BASED(X, reloc_table)
105 #define IS_GOT_OPINS(X) RELTAB_IS_GOT_OPINS(X, reloc_table)
106 #define IS_GOT_REQUIRED(X) RELTAB_IS_GOT_REQUIRED(X, reloc_table)
107 #define IS_PC_RELATIVE(X) RELTAB_IS_PC_RELATIVE(X, reloc_table)
108 #define IS_ADD_RELATIVE(X) RELTAB_IS_ADD_RELATIVE(X, reloc_table)
109 #define IS_REGISTER(X) RELTAB_IS_REGISTER(X, reloc_table)
110 #define IS_NOTSUP(X) RELTAB_IS_NOTSUP(X, reloc_table)
111 #define IS_SEG_RELATIVE(X) RELTAB_IS_SEG_RELATIVE(X, reloc_table)
112 #define IS_EXTOFFSET(X) RELTAB_IS_EXTOFFSET(X, reloc_table)
113 #define IS_SEC_RELATIVE(X) RELTAB_IS_SEC_RELATIVE(X, reloc_table)
114 #define IS_TLS_INS(X) RELTAB_IS_TLS_INS(X, reloc_table)
115 #define IS_TLS_GD(X) RELTAB_IS_TLS_GD(X, reloc_table)
116 #define IS_TLS_LD(X) RELTAB_IS_TLS_LD(X, reloc_table)
117 #define IS_TLS_IE(X) RELTAB_IS_TLS_IE(X, reloc_table)
118 #define IS_TLS_LE(X) RELTAB_IS_TLS_LE(X, reloc_table)
119 #define IS_LOCALBND(X) RELTAB_IS_LOCALBND(X, reloc_table)
120 #define IS_SIZE(X) RELTAB_IS_SIZE(X, reloc_table)
123 * Relocation engine.
125 * The do_reloc() code is used in three different places: The kernel,
126 * the link-editor, and the runtime linker. All three convey the same
127 * basic information with the first 5 arguments:
129 * 1) Relocation type. The kernel and runtime linker pass this as
130 * an integer value, while the link-editor passes it as a Rel_desc
131 * descriptor. The relocation engine only looks at the rel_rtype
132 * field of this descriptor, and does not examine the other fields,
133 * which are explicitly allowed to contain garbage.
134 * 2) Address of offset
135 * 3) Address of value
136 * 4) Name of symbol associated with the relocation, used if it is
137 * necessary to report an error. The kernel and runtime linker pass
138 * directly as a string pointer. The link-editor passes the address
139 * of a rel_desc_sname_func_t function, which can be called by do_reloc(),
140 * passing it the Rel_desc pointer (argument 1, above), to obtain the
141 * string pointer.
142 * 5) String giving the source file for the relocation.
144 * In addition:
145 * - The linker and rtld want a link map pointer argument
146 * - The linker wants to pass a byte swap argument that tells
147 * the relocation engine that the data it is relocating
148 * has the opposite byte order of the system running the
149 * linker.
150 * - The linker is a cross-linker, meaning that it can examine
151 * relocation records for target hosts other than that of
152 * the currently running system. This means that multiple
153 * versions of the relocation code must be able to reside
154 * in a single program, without namespace clashes.
156 * To ensure that there is never any confusion about which version is
157 * being linked to, we give each variant a different name, even though
158 * each one is generated from the same source code.
160 * do_reloc_krtld()
161 * The kernel version is provided if the _KERNEL macro is defined.
163 * do_reloc_ld()
164 * The ld version is provided if the DO_RELOC_LIBLD_ macro is defined.
166 * do_reloc_rtld()
167 * The rtld version is provided if neither _KERNEL or DO_RELOC_LIBLD
168 * are defined.
170 * Implementations of do_reloc() should use these same macros to
171 * conditionalize any code not used by all three versions.
173 #if defined(_KERNEL)
174 extern int do_reloc_krtld(uchar_t, uchar_t *, Xword *, const char *,
175 const char *);
176 #elif defined(DO_RELOC_LIBLD)
177 extern int do_reloc_ld(Rel_desc *, uchar_t *, Xword *,
178 rel_desc_sname_func_t, const char *, int, void *);
179 #else
180 extern int do_reloc_rtld(uchar_t, uchar_t *, Xword *, const char *,
181 const char *, void *);
182 #endif
184 #if defined(_KERNEL)
186 * These are macro's that are only needed for krtld. Many of these are already
187 * defined in the sgs/include files referenced by ld and rtld
189 #define S_MASK(n) ((1l << (n)) - 1l)
190 #define S_INRANGE(v, n) (((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n))))
193 * Message strings used by doreloc().
195 #define MSG_STR_UNKNOWN "(unknown)"
197 #define MSG_REL_PREGEN "relocation error: %s: "
198 #define MSG_REL_PREFIL "relocation error: file %s: "
199 #define MSG_REL_FILE "file %s: "
200 #define MSG_REL_SYM "symbol %s: "
201 #define MSG_REL_VALUE "value 0x%llx "
202 #define MSG_REL_LOSEBITS "loses %d bits at "
204 #define MSG_REL_UNIMPL "unimplemented relocation type: %d"
205 #define MSG_REL_UNSUPSZ "offset size (%d bytes) is not supported"
206 #define MSG_REL_NONALIGN "offset 0x%llx is non-aligned"
207 #define MSG_REL_UNNOBITS "unsupported number of bits: %d"
208 #define MSG_REL_OFFSET "offset 0x%llx"
209 #define MSG_REL_NOFIT "value 0x%llx does not fit"
212 * Provide a macro to select the appropriate conversion routine for this
213 * architecture.
215 #if defined(__amd64)
217 extern const char *conv_reloc_amd64_type(Word);
218 #define CONV_RELOC_TYPE conv_reloc_amd64_type
220 #elif defined(__i386)
222 extern const char *conv_reloc_386_type(Word);
223 #define CONV_RELOC_TYPE conv_reloc_386_type
225 #elif defined(__sparc)
227 extern const char *conv_reloc_SPARC_type(Word);
228 #define CONV_RELOC_TYPE conv_reloc_SPARC_type
230 #else
231 #error platform not defined!
232 #endif
236 * Note: dlerror() only keeps track of a single error string, and therefore
237 * must have errors reported through a single eprintf() call. The kernel's
238 * _kobj_printf is somewhat more limited, and must receive messages with only
239 * one argument to the format string. The following macros account for these
240 * differences, as krtld and rtld share the same do_reloc() source.
242 #define REL_ERR_UNIMPL(lml, file, sym, rtype) \
243 _kobj_printf(ops, MSG_REL_PREFIL, (file)); \
244 _kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
245 _kobj_printf(ops, MSG_REL_UNIMPL, (int)(rtype))
247 #define REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
248 _kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
249 _kobj_printf(ops, MSG_REL_FILE, (file)); \
250 _kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
251 _kobj_printf(ops, MSG_REL_UNSUPSZ, (int)(size))
253 #define REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
254 _kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
255 _kobj_printf(ops, MSG_REL_FILE, (file)); \
256 _kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
257 _kobj_printf(ops, MSG_REL_NONALIGN, EC_OFF((off)))
259 #define REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
260 _kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
261 _kobj_printf(ops, MSG_REL_FILE, (file)); \
262 _kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
263 _kobj_printf(ops, MSG_REL_UNNOBITS, (nbits))
265 #define REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
266 _kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
267 _kobj_printf(ops, MSG_REL_FILE, (file)); \
268 _kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
269 _kobj_printf(ops, MSG_REL_VALUE, EC_XWORD((uvalue))); \
270 _kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \
271 _kobj_printf(ops, MSG_REL_OFFSET, EC_NATPTR((off)))
273 #define REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
274 _kobj_printf(ops, MSG_REL_PREGEN, CONV_RELOC_TYPE((rtype))); \
275 _kobj_printf(ops, MSG_REL_FILE, (file)); \
276 _kobj_printf(ops, MSG_REL_SYM, ((sym) ? (sym) : MSG_STR_UNKNOWN)); \
277 _kobj_printf(ops, MSG_REL_NOFIT, EC_XWORD((uvalue)))
280 #else /* !_KERNEL */
282 extern const char *demangle(const char *);
284 #define REL_ERR_UNIMPL(lml, file, sym, rtype) \
285 (eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), (file), \
286 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(rtype)))
288 #define REL_ERR_UNSUPSZ(lml, file, sym, rtype, size) \
289 (eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), \
290 conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
291 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (int)(size)))
293 #define REL_ERR_NONALIGN(lml, file, sym, rtype, off) \
294 (eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \
295 conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
296 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), EC_OFF((off))))
298 #define REL_ERR_UNNOBITS(lml, file, sym, rtype, nbits) \
299 (eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \
300 conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
301 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits)))
303 #define REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, nbits, off) \
304 (eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_LOSEBITS), \
305 conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
306 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
307 EC_XWORD((uvalue)), (nbits), EC_NATPTR((off))))
309 #define REL_ERR_NOFIT(lml, file, sym, rtype, uvalue) \
310 (eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \
311 conv_reloc_type_static(M_MACH, (rtype), 0), (file), \
312 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \
313 EC_XWORD((uvalue))))
315 #endif /* _KERNEL */
317 #ifdef __cplusplus
319 #endif
321 #endif /* _RELOC_DOT_H */