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