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, (u_longlong_t)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, (u_longlong_t)EC_XWORD((uvalue))); \ 272 _kobj_printf(ops, MSG_REL_LOSEBITS, (int)(nbits)); \ 273 _kobj_printf(ops, MSG_REL_OFFSET, (u_longlong_t)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 */ 324