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 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _RELOC_DOT_H 28 #define _RELOC_DOT_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #if defined(_KERNEL) 33 #include <sys/machelf.h> 34 #include <sys/bootconf.h> 35 #include <sys/kobj.h> 36 #include <sys/kobj_impl.h> 37 #else 38 #include <machdep.h> 39 #endif /* _KERNEL */ 40 41 #include <relmach.h> 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 /* 48 * Global include file for relocation common code. 49 * 50 * Flags for reloc_entry->re_flags 51 */ 52 #define FLG_RE_NOTREL 0x00000000 53 #define FLG_RE_GOTADD 0x00000001 /* create a GOT entry */ 54 #define FLG_RE_GOTREL 0x00000002 /* GOT based */ 55 #define FLG_RE_GOTPC 0x00000004 /* GOT - P */ 56 #define FLG_RE_GOTOPINS 0x00000008 /* GOTOP instruction */ 57 #define FLG_RE_PCREL 0x00000010 58 #define FLG_RE_PLTREL 0x00000020 59 #define FLG_RE_VERIFY 0x00000040 /* verify value fits */ 60 #define FLG_RE_UNALIGN 0x00000080 /* offset is not aligned */ 61 #define FLG_RE_WDISP16 0x00000100 /* funky sparc DISP16 rel */ 62 #define FLG_RE_SIGN 0x00000200 /* value is signed */ 63 #define FLG_RE_ADDRELATIVE 0x00000400 /* RELATIVE relocation */ 64 /* required for non-fixed */ 65 /* objects */ 66 #define FLG_RE_EXTOFFSET 0x00000800 /* extra offset required */ 67 #define FLG_RE_REGISTER 0x00001000 /* relocation initializes */ 68 /* a REGISTER by OLO10 */ 69 #define FLG_RE_MSB 0x00002000 /* merced MSB data field */ 70 #define FLG_RE_LSB 0x00004000 /* merced LSB data field */ 71 #define FLG_RE_ADDFIELD 0x00008000 /* add contents of field at */ 72 /* r_offset to value */ 73 #define FLG_RE_NOTSUP 0x00010000 /* relocation not supported */ 74 #define FLG_RE_FRMOFF 0x00020000 /* offset contains islot */ 75 /* value (IA64) */ 76 #define FLG_RE_SEGREL 0x00040000 /* Segment relative */ 77 78 #define FLG_RE_SECREL 0x00080000 /* Section relative */ 79 #define FLG_RE_TLSINS 0x00100000 /* TLS instructino rel */ 80 #define FLG_RE_TLSGD 0x00200000 /* TLS GD relocation */ 81 #define FLG_RE_TLSLD 0x00400000 /* TLS LD relocation */ 82 #define FLG_RE_TLSIE 0x00800000 /* TLS IE relocation */ 83 #define FLG_RE_TLSLE 0x01000000 /* TLS LE relocation */ 84 85 #define FLG_RE_LOCLBND 0x02000000 /* relocation must bind */ 86 /* locally */ 87 88 /* 89 * Macros for testing relocation table flags 90 */ 91 extern const Rel_entry reloc_table[]; 92 93 #define IS_PLT(X) ((reloc_table[(X)].re_flags & \ 94 FLG_RE_PLTREL) != 0) 95 #define IS_GOT_RELATIVE(X) ((reloc_table[(X)].re_flags & \ 96 FLG_RE_GOTADD) != 0) 97 #define IS_GOT_PC(X) ((reloc_table[(X)].re_flags & \ 98 FLG_RE_GOTPC) != 0) 99 #define IS_GOTPCREL(X) ((reloc_table[(X)].re_flags & \ 100 (FLG_RE_GOTPC | FLG_RE_GOTADD)) == \ 101 (FLG_RE_GOTPC | FLG_RE_GOTADD)) 102 #define IS_GOT_BASED(X) ((reloc_table[(X)].re_flags & \ 103 FLG_RE_GOTREL) != 0) 104 #define IS_GOT_INS(X) ((reloc_table[(X)].re_flags &\ 105 FLG_RE_GOTOPINS) != 0) 106 #define IS_PC_RELATIVE(X) ((reloc_table[(X)].re_flags & \ 107 FLG_RE_PCREL) != 0) 108 #define IS_ADD_RELATIVE(X) ((reloc_table[(X)].re_flags & \ 109 FLG_RE_ADDRELATIVE) != 0) 110 #define IS_REGISTER(X) ((reloc_table[(X)].re_flags & \ 111 FLG_RE_REGISTER) != 0) 112 #define IS_FORMOFF(X) ((reloc_table[(X)].re_flags &\ 113 FLG_RE_FRMOFF) != 0) 114 #define IS_NOTSUP(X) ((reloc_table[(X)].re_flags &\ 115 FLG_RE_NOTSUP) != 0) 116 #define IS_SEG_RELATIVE(X) ((reloc_table[(X)].re_flags &\ 117 FLG_RE_SEGREL) != 0) 118 #define IS_EXTOFFSET(X) ((reloc_table[(X)].re_flags &\ 119 FLG_RE_EXTOFFSET) != 0) 120 #define IS_SEC_RELATIVE(X) ((reloc_table[(X)].re_flags &\ 121 FLG_RE_SECREL) != 0) 122 #define IS_TLS_INS(X) ((reloc_table[(X)].re_flags &\ 123 FLG_RE_TLSINS) != 0) 124 #define IS_TLS_GD(X) ((reloc_table[(X)].re_flags &\ 125 FLG_RE_TLSGD) != 0) 126 #define IS_TLS_LD(X) ((reloc_table[(X)].re_flags &\ 127 FLG_RE_TLSLD) != 0) 128 #define IS_TLS_IE(X) ((reloc_table[(X)].re_flags &\ 129 FLG_RE_TLSIE) != 0) 130 #define IS_TLS_LE(X) ((reloc_table[(X)].re_flags &\ 131 FLG_RE_TLSLE) != 0) 132 #define IS_TLS(X) ((reloc_table[(X)].re_flags &\ 133 (FLG_RE_TLSINS|FLG_RE_TLSGD| \ 134 FLG_RE_TLSLD|FLG_RE_TLSIE| \ 135 FLG_RE_TLSLE)) != 0) 136 #define IS_LOCALBND(X) ((reloc_table[(X)].re_flags &\ 137 FLG_RE_LOCLBND) != 0) 138 139 /* 140 * Functions. 141 */ 142 #if defined(__i386) || defined(__ia64) || defined(__amd64) 143 extern int do_reloc(unsigned char, unsigned char *, Xword *, 144 const char *, const char *); 145 #elif defined(__sparc) 146 extern int do_reloc(unsigned char, unsigned char *, Xword *, 147 const char *, const char *); 148 #endif 149 150 151 /* 152 * NOTE - this CONVRELOC macro is only used 153 * in the REL_ERR_NOFIT() macro below. For Intel 154 * this macro is only referenced from the amd64 side - it's 155 * not relevant for i386. So - we just define AMD64 for i386 156 * and sparc is sparc. 157 */ 158 #if defined(__amd64) || defined(__i386) 159 #define CONVRELOC conv_reloc_amd64_type_str 160 #elif defined(__sparc) 161 #define CONVRELOC conv_reloc_SPARC_type_str 162 #else 163 #error platform not defined! 164 #endif 165 166 #if defined(_KERNEL) 167 /* 168 * These are macro's that are only needed for krtld. Many of these 169 * are already defined in the sgs/include files referenced by 170 * ld and rtld 171 */ 172 173 #define S_MASK(n) ((1l << (n)) - 1l) 174 #define S_INRANGE(v, n) (((-(1l << (n)) - 1l) < (v)) && ((v) < (1l << (n)))) 175 176 /* 177 * This converts the sgs eprintf() routine into the _printf() 178 * as used by krtld. 179 */ 180 #define eprintf _kobj_printf 181 #define ERR_FATAL ops 182 183 /* 184 * Message strings used by doreloc() 185 */ 186 #define MSG_ORIG(x) x 187 #define MSG_INTL(x) x 188 189 #define MSG_STR_UNKNOWN "(unknown)" 190 #define MSG_REL_UNSUPSZ "relocation error: %s: file %s: symbol %s: " \ 191 "offset size (%d bytes) is not supported" 192 #define MSG_REL_ERR_STR "relocation error: %s:" 193 #define MSG_REL_ERR_WITH_FILE "relocation error: file %s: " 194 #define MSG_REL_ERR_FILE " file %s: " 195 #define MSG_REL_ERR_SYM " symbol %s: " 196 #define MSG_REL_ERR_VALUE " value 0x%llx" 197 #define MSG_REL_ERR_OFF " offset 0x%llx\n" 198 #define MSG_REL_UNIMPL " unimplemented relocation type: %d" 199 #define MSG_REL_NONALIGN " offset 0x%llx is non-aligned\n" 200 #define MSG_REL_UNNOBITS " unsupported number of bits: %d" 201 #define MSG_REL_NOFIT " value 0x%llx does not fit\n" 202 #define MSG_REL_LOSEBITS " loses %d bits at" 203 204 extern const char *conv_reloc_SPARC_type_str(Word rtype); 205 extern const char *conv_reloc_386_type_str(Word rtype); 206 extern const char *conv_reloc_amd64_type_str(Word rtype); 207 208 /* 209 * Note: Related to bug 4128755, dlerror() only keeps track 210 * of a single error string, and therefore must have errors 211 * reported through a single eprintf() call. The kernel's 212 * printf is somewhat more limited, and must receive messages 213 * with only one arguement to the format string. The following 214 * macros are to straighted all this out because krtld and 215 * rtld share do_reloc(). 216 */ 217 #define REL_ERR_UNIMPL(file, sym, rtype) \ 218 eprintf(ERR_FATAL, MSG_REL_ERR_WITH_FILE, (file)); \ 219 eprintf(ERR_FATAL, MSG_REL_ERR_SYM, \ 220 ((sym) ? (sym) : MSG_STR_UNKNOWN)); \ 221 eprintf(ERR_FATAL, MSG_REL_UNIMPL, \ 222 (int)(rtype)) 223 224 #define REL_ERR_NONALIGN(file, sym, rtype, off) \ 225 eprintf(ERR_FATAL, MSG_REL_ERR_STR, \ 226 conv_reloc_SPARC_type_str((rtype))); \ 227 eprintf(ERR_FATAL, MSG_REL_ERR_FILE, (file)); \ 228 eprintf(ERR_FATAL, MSG_REL_ERR_SYM, \ 229 ((sym) ? (sym) : MSG_STR_UNKNOWN)); \ 230 eprintf(ERR_FATAL, MSG_REL_NONALIGN, \ 231 EC_OFF((off))) 232 233 #define REL_ERR_UNNOBITS(file, sym, rtype, nbits) \ 234 eprintf(ERR_FATAL, MSG_REL_ERR_STR, \ 235 conv_reloc_SPARC_type_str((rtype))); \ 236 eprintf(ERR_FATAL, MSG_REL_ERR_FILE, (file)); \ 237 eprintf(ERR_FATAL, MSG_REL_ERR_SYM, \ 238 ((sym) ? (sym) : MSG_STR_UNKNOWN)); \ 239 eprintf(ERR_FATAL, MSG_REL_UNNOBITS, (nbits)) 240 241 #define REL_ERR_LOSEBITS(file, sym, rtype, uvalue, nbits, off) \ 242 eprintf(ERR_FATAL, MSG_REL_ERR_STR, \ 243 conv_reloc_SPARC_type_str((rtype))); \ 244 eprintf(ERR_FATAL, MSG_REL_ERR_FILE, (file)); \ 245 eprintf(ERR_FATAL, MSG_REL_ERR_SYM, \ 246 ((sym) ? (sym) : MSG_STR_UNKNOWN)); \ 247 eprintf(ERR_FATAL, MSG_REL_ERR_VALUE, EC_XWORD((uvalue))); \ 248 eprintf(ERR_FATAL, MSG_REL_LOSEBITS, (nbits)); \ 249 eprintf(ERR_FATAL, MSG_REL_ERR_OFF, EC_ADDR((off))) 250 251 #define REL_ERR_NOFIT(file, sym, rtype, uvalue) \ 252 eprintf(ERR_FATAL, MSG_REL_ERR_STR, \ 253 CONVRELOC((rtype))); \ 254 eprintf(ERR_FATAL, MSG_REL_ERR_FILE, (file)); \ 255 eprintf(ERR_FATAL, MSG_REL_ERR_SYM, \ 256 ((sym) ? (sym) : MSG_STR_UNKNOWN)); \ 257 eprintf(ERR_FATAL, MSG_REL_NOFIT, EC_XWORD((uvalue))) 258 259 260 #else /* !_KERNEL */ 261 262 extern const char *demangle(const char *); 263 264 #define REL_ERR_UNIMPL(file, sym, rtype) \ 265 (eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNIMPL), \ 266 (file), ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \ 267 (int)(rtype))) 268 269 #define REL_ERR_NONALIGN(file, sym, rtype, off) \ 270 (eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NONALIGN), \ 271 conv_reloc_SPARC_type_str(rtype), (file), \ 272 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \ 273 EC_OFF((off)))) 274 275 #define REL_ERR_UNNOBITS(file, sym, rtype, nbits) \ 276 (eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNNOBITS), \ 277 conv_reloc_SPARC_type_str(rtype), (file), \ 278 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), (nbits))) 279 280 #define REL_ERR_LOSEBITS(file, sym, rtype, uvalue, nbits, off) \ 281 (eprintf(ERR_FATAL, MSG_INTL(MSG_REL_LOSEBITS), \ 282 conv_reloc_SPARC_type_str((rtype)), (file), \ 283 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \ 284 EC_XWORD((uvalue)), (nbits), EC_ADDR((off)))) 285 286 #define REL_ERR_NOFIT(file, sym, rtype, uvalue) \ 287 (eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOFIT), \ 288 CONVRELOC((rtype)), (file), \ 289 ((sym) ? demangle(sym) : MSG_INTL(MSG_STR_UNKNOWN)), \ 290 EC_XWORD((uvalue)))) 291 292 #endif /* _KERNEL */ 293 294 #ifdef __cplusplus 295 } 296 #endif 297 298 #endif /* _RELOC_DOT_H */ 299