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]
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
30 #include <sys/bootconf.h>
32 #include <sys/kobj_impl.h>
38 #include "reloc_defs.h"
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.
55 #if defined(DO_RELOC_LIBLD)
59 #if defined(DO_RELOC_LIBLD_X86)
61 #define DO_RELOC_LIBLD
63 #define do_reloc_ld do64_reloc_ld_x86
64 #define reloc_table reloc64_table_x86
66 #define do_reloc_ld do32_reloc_ld_x86
67 #define reloc_table reloc32_table_x86
70 #elif defined(DO_RELOC_LIBLD_SPARC)
72 #define DO_RELOC_LIBLD
74 #define do_reloc_ld do64_reloc_ld_sparc
75 #define reloc_table reloc64_table_sparc
77 #define do_reloc_ld do32_reloc_ld_sparc
78 #define reloc_table reloc32_table_sparc
84 #define do_reloc_rtld do64_reloc_rtld
85 #define reloc_table reloc64_table
87 #define do_reloc_rtld do32_reloc_rtld
88 #define reloc_table reloc32_table
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)
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
142 * 5) String giving the source file for the relocation.
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
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.
161 * The kernel version is provided if the _KERNEL macro is defined.
164 * The ld version is provided if the DO_RELOC_LIBLD_ macro is defined.
167 * The rtld version is provided if neither _KERNEL or DO_RELOC_LIBLD
170 * Implementations of do_reloc() should use these same macros to
171 * conditionalize any code not used by all three versions.
174 extern int do_reloc_krtld(uchar_t
, uchar_t
*, Xword
*, 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 *);
180 extern int do_reloc_rtld(uchar_t
, uchar_t
*, Xword
*, const char *,
181 const char *, void *);
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
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
231 #error platform not defined!
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)))
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)), \
321 #endif /* _RELOC_DOT_H */