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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #if defined(_KERNEL) 30 #include <sys/types.h> 31 #include "reloc.h" 32 #else 33 #include <stdio.h> 34 #include "sgs.h" 35 #include "machdep.h" 36 #include "libld.h" 37 #include "reloc.h" 38 #include "conv.h" 39 #include "msg.h" 40 #endif 41 42 /* 43 * This table represents the current relocations that do_reloc() is able to 44 * process. The relocations below that are marked SPECIAL are relocations that 45 * take special processing and shouldn't actually ever be passed to do_reloc(). 46 */ 47 const Rel_entry reloc_table[R_SPARC_NUM] = { 48 /* R_SPARC_NONE */ {0x0, FLG_RE_NOTREL, 0, 0, 0}, 49 /* R_SPARC_8 */ {0x0, FLG_RE_VERIFY, 1, 0, 0}, 50 /* R_SPARC_16 */ {0x0, FLG_RE_VERIFY, 2, 0, 0}, 51 /* R_SPARC_32 */ {0x0, FLG_RE_VERIFY, 4, 0, 0}, 52 /* R_SPARC_DISP8 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 53 1, 0, 0}, 54 /* R_SPARC_DISP16 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 55 2, 0, 0}, 56 /* R_SPARC_DISP32 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 57 4, 0, 0}, 58 /* R_SPARC_WDISP30 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 59 4, 2, 30}, 60 /* R_SPARC_WDISP22 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 61 4, 2, 22}, 62 #if defined(_ELF64) 63 /* R_SPARC_HI22 */ {0x0, FLG_RE_VERIFY, 4, 10, 22}, 64 #else 65 /* R_SPARC_HI22 */ {0x0, FLG_RE_NOTREL, 4, 10, 22}, 66 #endif 67 /* R_SPARC_22 */ {0x0, FLG_RE_VERIFY, 4, 0, 22}, 68 /* R_SPARC_13 */ {0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 13}, 69 /* R_SPARC_LO10 */ {0x3ff, FLG_RE_SIGN, 4, 0, 13}, 70 /* R_SPARC_GOT10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_SIGN, 4, 0, 13}, 71 /* R_SPARC_GOT13 */ {0x0, FLG_RE_GOTADD | FLG_RE_VERIFY | FLG_RE_SIGN, 72 4, 0, 13}, 73 /* R_SPARC_GOT22 */ {0x0, FLG_RE_GOTADD, 4, 10, 22}, 74 /* R_SPARC_PC10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_LOCLBND, 75 4, 0, 13}, 76 /* R_SPARC_PC22 */ {0x0, FLG_RE_PCREL | FLG_RE_SIGN | FLG_RE_VERIFY | 77 FLG_RE_LOCLBND, 4, 10, 22}, 78 /* R_SPARC_WPLT30 */ {0x0, FLG_RE_PCREL | FLG_RE_PLTREL | 79 FLG_RE_VERIFY | FLG_RE_SIGN, 80 4, 2, 30}, 81 /* R_SPARC_COPY */ {0x0, 0, 0, 0, 0}, /* SPECIAL */ 82 #if defined(_ELF64) 83 /* R_SPARC_GLOB_DAT */ {0x0, FLG_RE_NOTREL, 8, 0, 0}, 84 #else 85 /* R_SPARC_GLOB_DAT */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, 86 #endif 87 /* R_SPARC_JMP_SLOT */ {0x0, 0, 0, 0, 0}, /* SPECIAL */ 88 #if defined(_ELF64) 89 /* R_SPARC_RELATIVE */ {0x0, FLG_RE_NOTREL, 8, 0, 0}, 90 #else 91 /* R_SPARC_RELATIVE */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, 92 #endif 93 /* R_SPARC_UA32 */ {0x0, FLG_RE_UNALIGN, 4, 0, 0}, 94 /* R_SPARC_PLT32 */ {0x0, FLG_RE_PLTREL | FLG_RE_VERIFY | 95 FLG_RE_ADDRELATIVE, 4, 0, 0}, 96 /* R_SPARC_HIPLT22 */ {0x0, FLG_RE_PLTREL, 4, 10, 22}, 97 /* R_SPARC_LOPLT10 */ {0x3ff, FLG_RE_PLTREL, 4, 0, 13}, 98 /* R_SPARC_PCPLT32 */ {0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY, 99 4, 0, 0}, 100 /* R_SPARC_PCPLT22 */ {0x0, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY, 101 4, 10, 22}, 102 /* R_SPARC_PCPLT10 */ {0x3ff, FLG_RE_PLTREL | FLG_RE_PCREL | FLG_RE_VERIFY, 103 4, 0, 13}, 104 /* R_SPARC_10 */ {0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 10}, 105 /* R_SPARC_11 */ {0x0, FLG_RE_VERIFY | FLG_RE_SIGN, 4, 0, 11}, 106 /* R_SPARC_64 */ {0x0, FLG_RE_VERIFY, 8, 0, 0}, /* V9 */ 107 /* R_SPARC_OLO10 */ {0x3ff, FLG_RE_EXTOFFSET | FLG_RE_SIGN, 108 4, 0, 13}, /* V9 */ 109 /* R_SPARC_HH22 */ {0x0, FLG_RE_VERIFY, 4, 42, 22}, /* V9 */ 110 /* R_SPARC_HM10 */ {0x3ff, FLG_RE_SIGN, 4, 32, 13}, /* V9 */ 111 /* R_SPARC_LM22 */ {0x0, FLG_RE_NOTREL, 4, 10, 22}, /* V9 */ 112 /* R_SPARC_PC_HH22 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY, 113 4, 42, 22}, /* V9 */ 114 /* R_SPARC_PC_HM10 */ {0x3ff, FLG_RE_PCREL | FLG_RE_SIGN, 115 4, 32, 13}, /* V9 */ 116 /* R_SPARC_PC_LM22 */ {0x0, FLG_RE_PCREL, 117 4, 10, 22}, /* V9 */ 118 /* R_SPARC_WDISP16 */ {0x0, FLG_RE_PCREL | FLG_RE_WDISP16 | 119 FLG_RE_VERIFY | FLG_RE_SIGN, 120 4, 2, 16}, 121 /* R_SPARC_WDISP19 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 122 4, 2, 19}, 123 /* R_SPARC_GLOB_JMP */ {0x0, 0, 0, 0, 0}, /* V9 - not implemented */ 124 /* removed from v9 ABI */ 125 /* R_SPARC_7 */ {0x0, FLG_RE_NOTREL, 4, 0, 7}, 126 /* R_SPARC_5 */ {0x0, FLG_RE_NOTREL, 4, 0, 5}, 127 /* R_SPARC_6 */ {0x0, FLG_RE_NOTREL, 4, 0, 6}, 128 /* R_SPARC_DISP64 */ {0x0, FLG_RE_PCREL | FLG_RE_VERIFY | FLG_RE_SIGN, 129 8, 0, 0}, 130 /* R_SPARC_PLT64 */ {0x0, FLG_RE_PLTREL | FLG_RE_VERIFY | 131 FLG_RE_ADDRELATIVE, 8, 0, 0}, 132 /* R_SPARC_HIX22 */ {(Xword)(-1LL), FLG_RE_VERIFY, 133 4, 10, 22}, /* V9 - HaL */ 134 /* R_SPARC_LOX10 */ {0x3ff, FLG_RE_SIGN, 4, 0, 13}, /* V9 - HaL */ 135 /* R_SPARC_H44 */ {0x0, FLG_RE_VERIFY, 4, 22, 22}, /* V9 */ 136 /* R_SPARC_M44 */ {0x3ff, FLG_RE_NOTREL, 4, 12, 10}, /* V9 */ 137 /* R_SPARC_L44 */ {0xfff, FLG_RE_NOTREL, 4, 0, 13}, /* V9 */ 138 /* R_SPARC_REGISTER */ {0x0, FLG_RE_REGISTER, 0, 0, 0}, /* SPECIAL */ 139 /* R_SPARC_UA64 */ {0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN, 140 8, 0, 0}, /* V9 */ 141 /* R_SPARC_UA16 */ {0x0, FLG_RE_VERIFY | FLG_RE_UNALIGN, 142 2, 0, 0}, 143 /* R_SPARC_TLS_GD_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSGD, 4, 10, 22}, 144 /* R_SPARC_TLS_GD_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSGD | 145 FLG_RE_SIGN, 4, 0, 13}, 146 /* R_SPARC_TLS_GD_ADD */ {0x0, FLG_RE_TLSGD, 0, 0, 0}, 147 /* R_SPARC_TLS_GD_CALL */ {0x0, FLG_RE_TLSGD, 0, 0, 0}, 148 /* R_SPARC_TLS_LDM_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSLD, 4, 10, 22}, 149 /* R_SPARC_TLS_LDM_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSLD | 150 FLG_RE_SIGN, 4, 0, 13}, 151 /* R_SPARC_TLS_LDM_ADD */ {0x0, FLG_RE_TLSLD, 0, 0, 0}, 152 /* R_SPARC_TLS_LDM_CALL */ {0x0, FLG_RE_TLSLD, 0, 0, 0}, 153 /* R_SPARC_TLS_LDO_HIX22 */ {0x0, FLG_RE_VERIFY | FLG_RE_TLSLD, 4, 10, 22}, 154 /* R_SPARC_TLS_LDO_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLD, 4, 0, 13}, 155 /* R_SPARC_TLS_LDO_ADD */ {0x0, FLG_RE_TLSLD, 0, 0, 0}, 156 /* R_SPARC_TLS_IE_HI22 */ {0x0, FLG_RE_GOTADD | FLG_RE_TLSIE, 4, 10, 22}, 157 /* R_SPARC_TLS_IE_LO10 */ {0x3ff, FLG_RE_GOTADD | FLG_RE_TLSIE | 158 FLG_RE_SIGN, 4, 0, 13}, 159 /* R_SPARC_TLS_IE_LD */ {0x0, FLG_RE_TLSIE, 0, 0, 0}, 160 /* R_SPARC_TLS_IE_LDX */ {0x0, FLG_RE_TLSIE, 0, 0, 0}, 161 /* R_SPARC_TLS_IE_ADD */ {0x0, FLG_RE_TLSIE, 0, 0, 0}, 162 /* R_SPARC_TLS_LE_HIX22 */ {(Xword)(-1LL), 163 FLG_RE_VERIFY | FLG_RE_TLSLE, 4, 10, 22}, 164 /* R_SPARC_TLS_LE_LOX10 */ {0x3ff, FLG_RE_SIGN | FLG_RE_TLSLE, 4, 0, 13}, 165 /* R_SPARC_TLS_DTPMOD32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, 166 /* R_SPARC_TLS_DTPMOD64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0}, 167 /* R_SPARC_TLS_DTPOFF32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, 168 /* R_SPARC_TLS_DTPOFF64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0}, 169 /* R_SPARC_TLS_TPOFF32 */ {0x0, FLG_RE_NOTREL, 4, 0, 0}, 170 /* R_SPARC_TLS_TPOFF64 */ {0x0, FLG_RE_NOTREL, 8, 0, 0}, 171 /* R_SPARC_GOTDATA_HIX22 */ {0, FLG_RE_SIGN | FLG_RE_GOTREL | 172 FLG_RE_VERIFY, 4, 10, 22}, 173 /* R_SPARC_GOTDATA_LOX10 */ { 0x3ff, FLG_RE_GOTREL | FLG_RE_SIGN, 4, 0, 13}, 174 /* R_SPARC_GOTDATA_OP_HIX22 */ { 0x0, FLG_RE_GOTOPINS | FLG_RE_GOTADD, 175 4, 10, 22}, 176 /* R_SPARC_GOTDATA_OP_LOX10 */ { 0x3ff, FLG_RE_SIGN | FLG_RE_GOTOPINS | 177 FLG_RE_GOTADD, 4, 0, 13}, 178 /* R_SPARC_GOTDATA_OP */ { 0x0, FLG_RE_GOTOPINS, 0, 0, 0}, 179 /* R_SPARC_H34 */ {0x0, FLG_RE_VERIFY, 4, 12, 22}, /* V9 */ 180 /* R_SPARC_SIZE32 */ {0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 4, 0, 0}, 181 /* R_SPARC_SIZE64 */ {0x0, FLG_RE_SIZE | FLG_RE_VERIFY, 8, 0, 0}, 182 }; 183 184 185 /* 186 * Write a single relocated value to its reference location. 187 * We assume we wish to add the relocation amount, value, to the 188 * value of the address already present in the instruction. 189 * 190 * NAME VALUE FIELD CALCULATION 191 * 192 * R_SPARC_NONE 0 none none 193 * R_SPARC_8 1 V-byte8 S + A 194 * R_SPARC_16 2 V-half16 S + A 195 * R_SPARC_32 3 V-word32 S + A 196 * R_SPARC_DISP8 4 V-byte8 S + A - P 197 * R_SPARC_DISP16 5 V-half16 S + A - P 198 * R_SPARC_DISP32 6 V-word32 S + A - P 199 * R_SPARC_WDISP30 7 V-disp30 (S + A - P) >> 2 200 * R_SPARC_WDISP22 8 V-disp22 (S + A - P) >> 2 201 * R_SPARC_HI22 9 T-imm22 (S + A) >> 10 202 * R_SPARC_22 10 V-imm22 S + A 203 * R_SPARC_13 11 V-simm13 S + A 204 * R_SPARC_LO10 12 T-simm13 (S + A) & 0x3ff 205 * R_SPARC_GOT10 13 T-simm13 G & 0x3ff 206 * R_SPARC_GOT13 14 V-simm13 G 207 * R_SPARC_GOT22 15 T-imm22 G >> 10 208 * R_SPARC_PC10 16 T-simm13 (S + A - P) & 0x3ff 209 * R_SPARC_PC22 17 V-disp22 (S + A - P) >> 10 210 * R_SPARC_WPLT30 18 V-disp30 (L + A - P) >> 2 211 * R_SPARC_COPY 19 none none 212 * R_SPARC_GLOB_DAT 20 V-word32 S + A 213 * R_SPARC_JMP_SLOT 21 V-plt22 S + A 214 * R_SPARC_RELATIVE 22 V-word32 S + A 215 * R_SPARC_UA32 23 V-word32 S + A 216 * R_SPARC_PLT32 24 V-word32 L + A 217 * R_SPARC_HIPLT22 25 T-imm22 (L + A) >> 10 218 * R_SPARC_LOPLT10 26 T-simm13 (L + A) & 0x3ff 219 * R_SPARC_PCPLT32 27 V-word32 L + A - P 220 * R_SPARC_PCPLT22 28 V-disp22 (L + A - P) >> 10 221 * R_SPARC_PCPLT10 29 V-simm13 (L + A - P) & 0x3ff 222 * R_SPARC_10 30 V-simm10 S + A 223 * R_SPARC_11 31 V-simm11 S + A 224 * R_SPARC_64 32 V-xword64 S + A 225 * R_SPARC_OLO10 33 V-simm13 ((S + A) & 0x3ff) + O 226 * R_SPARC_HH22 34 V-imm22 (S + A) >> 42 227 * R_SPARC_HM10 35 T-simm13 ((S + A) >> 32) & 0x3ff 228 * R_SPARC_LM22 36 T-imm22 (S + A) >> 10 229 * R_SPARC_PC_HH22 37 V-imm22 (S + A - P) >> 42 230 * R_SPARC_PC_HM10 38 T-simm13 ((S + A - P) >> 32) & 0x3ff 231 * R_SPARC_PC_LM22 39 T-imm22 (S + A - P) >> 10 232 * R_SPARC_WDISP16 40 V-d2/disp14 (S + A - P) >> 2 233 * R_SPARC_WDISP19 41 V-disp19 (S + A - P) >> 2 234 * R_SPARC_GLOB_JMP 42 V-xword64 S + A 235 * R_SPARC_7 43 V-imm7 S + A 236 * R_SPARC_5 44 V-imm5 S + A 237 * R_SPARC_6 45 V-imm6 S + A 238 * R_SPARC_DISP64 46 V-xword64 S + A - P 239 * R_SPARC_PLT64 47 V-xword64 L + A 240 * R_SPARC_HIX22 48 V-imm22 ((S + A) ^ 241 * 0xffffffffffffffff) >> 10 242 * R_SPARC_LOX10 49 T-simm13 ((S + A) & 0x3ff) | 0x1c00 243 * R_SPARC_H44 50 V-imm22 (S + A) >> 22 244 * R_SPARC_M44 51 T-imm10 ((S + A) >> 12) & 0x3ff 245 * R_SPARC_L44 52 T-imm13 (S + A) & 0xfff 246 * R_SPARC_REGISTER 53 V-xword64 S + A 247 * R_SPARC_UA64 54 V-xword64 S + A 248 * R_SPARC_UA16 55 V-half16 S + A 249 * R_SPARC_TLS_GD_HI22 56 T-simm22 @dtlndx(S + A) >> 10 250 * R_SPARC_TLS_GD_LO10 57 T-simm13 @dtlndx(S + A) & 0x3ff 251 * R_SPARC_TLS_GD_ADD 58 none SPECIAL 252 * R_SPARC_TLS_GD_CALL 59 V-disp30 SPECIAL 253 * R_SPARC_TLS_LDM_HI22 60 T-simm22 @tmndx(S + A) >> 10 254 * R_SPARC_TLS_LDM_LO10 61 T-simm13 @tmndx(S + A) & 0x3ff 255 * R_SPARC_TLS_LDM_ADD 62 none SPECIAL 256 * R_SPARC_TLS_LDM_CALL 63 V-disp30 SPECIAL 257 * R_SPARC_TLS_LDO_HIX22 64 V-simm22 @dtpoff(S + A) >> 10 258 * R_SPARC_TLS_LDO_LOX10 65 T-simm13 @dtpoff(S + A) & 0x3ff 259 * R_SPARC_TLS_LDO_ADD 66 none SPECIAL 260 * R_SPARC_TLS_IE_HI22 67 T-simm22 @got(@tpoff(S + A)) >> 10 261 * R_SPARC_TLS_IE_LO10 68 T-simm13 @got(@tpoff(S + A)) & 0x3ff 262 * R_SPARC_TLS_IE_LD 69 none SPECIAL 263 * R_SPARC_TLS_IE_LDX 70 none SPECIAL 264 * R_SPARC_TLS_IE_ADD 71 none SPECIAL 265 * R_SPARC_TLS_LE_HIX22 72 V-simm22 (@tpoff(S + A) ^ 266 * 0xffffffff) >> 10 267 * R_SPARC_TLS_LE_LOX10 73 T-simm13 (@tpoff(S + A) & 0x3ff) | 0x1c00 268 * R_SPARC_TLS_DTPMOD32 74 V-word32 @dtmod(S + A) 269 * R_SPARC_TLS_DTPMOD64 75 V-word64 @dtmod(S + A) 270 * R_SPARC_TLS_DTPOFF32 76 V-word32 @dtpoff(S + A) 271 * R_SPARC_TLS_DTPOFF64 77 V-word64 @dtpoff(S + A) 272 * R_SPARC_TLS_TPOFF32 78 V-word32 @tpoff(S + A) 273 * R_SPARC_TLS_TPOFF64 79 V-word64 @tpoff(S + A) 274 * R_SPARC_GOTDATA_HIX22 80 V-imm22 ((S + A - GOT) >> 10) ^ 275 * ((S + A - GOT) >> 31) 276 * R_SPARC_GOTDATA_LOX10 81 T-simm13 ((S + A - GOT) & 0x3ff) | 277 * (((S + A - GOT) >> 31) & 278 * 0x1c00) 279 * R_SPARC_GOTDATA_OP_HIX22 82 T-imm22 (G >> 10) & (G >> 31) 280 * R_SPARC_GOTDATA_OP_LOX10 83 T-simm13 (G & 0x3ff) | 281 * ((G >> 31) & 0x1c00) 282 * R_SPARC_GOTDATA_OP 84 Word32 SPECIAL 283 * R_SPARC_H34 85 V-imm22 (S + A) >> 12 284 * R_SPARC_SIZE32 86 V-word32 Z + A 285 * R_SPARC_SIZE64 87 V-xword64 Z + A 286 * 287 * This is Figure 4-20: Relocation Types from the Draft Copy of 288 * the ABI, Printed on 11/29/88. 289 * 290 * NOTE1: relocations 24->45 are newly registered relocations to support 291 * C++ ABI & SPARC V8+ and SPARC V9 architectures (1/9/94), and 292 * 64-bit relocations 46-55 were added for SPARC V9. 293 * 294 * NOTE2: relocations 56->79 are added to support Thread-Local storage 295 * as recorded in PSARC/2001/509 296 * 297 * NOTE3: The value to be passed for relocations R_SPARC_HIX22 and 298 * R_SPARC_TLS_HIX22 are negative values. So the upper 10 or 40 bits 299 * are 1. (So when the exclusive OR is applied, the upper bits 300 * will be 0.) 301 * 302 * Relocation calculations: 303 * 304 * The FIELD names indicate whether the relocation type checks for overflow. 305 * A calculated relocation value may be larger than the intended field, and 306 * the relocation type may verify (V) that the value fits, or truncate (T) 307 * the result. 308 * 309 * CALCULATION uses the following notation: 310 * A the addend used 311 * B the base address of the shared object in memory 312 * G the offset into the global offset table 313 * L the procedure linkage entry 314 * P the place of the storage unit being relocated 315 * S the value of the symbol 316 * O secondary addend (extra offset) in v9 r_info field 317 * Z the size of the symbol whose index resides in the relocation 318 * entry 319 * 320 * @dtlndx(x): Allocate two contiguous entries in the GOT table to hold 321 * a Tls_index structure (for passing to __tls_get_addr()). The 322 * instructions referencing this entry will be bound to the first 323 * of the two GOT entries. 324 * 325 * @tmndx(x): Allocate two contiguous entries in the GOT table to hold 326 * a Tls_index structure (for passing to __tls_get_addr()). The 327 * ti_offset field of the Tls_index will be set to 0 (zero) and the 328 * ti_module will be filled in at run-time. The call to 329 * __tls_get_addr() will return the starting offset of the dynamic 330 * TLS block. 331 * 332 * @dtpoff(x): calculate the tlsoffset relative to the TLS block. 333 * 334 * @tpoff(x): calculate the negative tlsoffset relative to the static 335 * TLS block. This value can be added to the thread-pointer to 336 * calculate the tls address. 337 * 338 * @dtpmod(x): calculate the module id of the object containing symbol x. 339 * 340 * The calculations in the CALCULATION column are assumed to have been performed 341 * before calling this function except for the addition of the addresses in the 342 * instructions. 343 * 344 * Upon successful completion of do_reloc() *value will be set to the 345 * 'bit-shifted' value that will be or'ed into memory. 346 */ 347 #if defined(_KERNEL) 348 #define lml 0 /* Needed by arglist of REL_ERR_* macros */ 349 int 350 do_reloc_krtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym, 351 const char *file) 352 #elif defined(DO_RELOC_LIBLD) 353 int 354 do_reloc_ld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym, 355 const char *file, int bswap, void *lml) 356 #else 357 int 358 do_reloc_rtld(uchar_t rtype, uchar_t *off, Xword *value, const char *sym, 359 const char *file, void *lml) 360 #endif 361 { 362 Xword uvalue = 0; 363 Xword basevalue, sigbit_mask, sigfit_mask; 364 Xword corevalue = *value; 365 uchar_t bshift; 366 int field_size, re_flags; 367 const Rel_entry * rep; 368 369 #if defined(DO_RELOC_LIBLD) 370 /* 371 * We do not support building the sparc linker as a cross linker 372 * at this time. 373 */ 374 if (bswap) { 375 REL_ERR_NOSWAP(lml, file, sym, rtype); 376 return (0); 377 } 378 #endif 379 380 rep = &reloc_table[rtype]; 381 bshift = rep->re_bshift; 382 field_size = rep->re_fsize; 383 re_flags = rep->re_flags; 384 sigbit_mask = S_MASK(rep->re_sigbits); 385 386 if ((re_flags & FLG_RE_SIGN) && sigbit_mask) { 387 /* 388 * sigfit_mask takes into account that a value 389 * might be signed and discards the signbit for 390 * comparison. 391 */ 392 sigfit_mask = S_MASK(rep->re_sigbits - 1); 393 } else 394 sigfit_mask = sigbit_mask; 395 396 if (field_size == 0) { 397 REL_ERR_UNIMPL(lml, file, sym, rtype); 398 return (0); 399 } 400 401 if (re_flags & FLG_RE_UNALIGN) { 402 int i; 403 uchar_t *dest = (uchar_t *)&basevalue; 404 405 /* 406 * Adjust the offset. 407 */ 408 /* LINTED */ 409 i = (int)(sizeof (Xword) - field_size); 410 if (i > 0) 411 dest += i; 412 413 basevalue = 0; 414 for (i = field_size - 1; i >= 0; i--) 415 dest[i] = off[i]; 416 } else { 417 if (((field_size == 2) && ((uintptr_t)off & 0x1)) || 418 ((field_size == 4) && ((uintptr_t)off & 0x3)) || 419 ((field_size == 8) && ((uintptr_t)off & 0x7))) { 420 REL_ERR_NONALIGN(lml, file, sym, rtype, (uintptr_t)off); 421 return (0); 422 } 423 switch (field_size) { 424 case 1: 425 basevalue = (Xword)*((uchar_t *)off); 426 break; 427 case 2: 428 /* LINTED */ 429 basevalue = (Xword)*((Half *)off); 430 break; 431 case 4: 432 /* LINTED */ 433 basevalue = (Xword)*((Word *)off); 434 break; 435 case 8: 436 /* LINTED */ 437 basevalue = (Xword)*((Xword *)off); 438 break; 439 default: 440 REL_ERR_UNNOBITS(lml, file, sym, rtype, 441 (rep->re_fsize * 8)); 442 return (0); 443 } 444 } 445 446 if (sigbit_mask) { 447 /* 448 * The WDISP16 relocation is an unusual one in that it's bits 449 * are not all contiguous. We have to selectivly pull them out. 450 */ 451 if (re_flags & FLG_RE_WDISP16) { 452 uvalue = ((basevalue & 0x300000) >> 6) | 453 (basevalue & 0x3fff); 454 basevalue &= ~0x303fff; 455 } else { 456 uvalue = sigbit_mask & basevalue; 457 basevalue &= ~sigbit_mask; 458 } 459 /* 460 * If value is signed make sure that we signextend the uvalue. 461 */ 462 if (re_flags & FLG_RE_SIGN) { 463 if (uvalue & (~sigbit_mask & sigfit_mask)) 464 uvalue |= ~sigbit_mask; 465 } 466 } else 467 uvalue = basevalue; 468 469 if (bshift) 470 uvalue <<= bshift; 471 472 uvalue += *value; 473 474 if (rep->re_mask && 475 ((rtype == R_SPARC_HIX22) || (rtype == R_SPARC_TLS_LE_HIX22))) 476 uvalue ^= rep->re_mask; 477 478 if (bshift) { 479 /* 480 * This is to check that we are not attempting to 481 * jump to a non-4 byte aligned address. 482 */ 483 if ((bshift == 2) && (uvalue & 0x3)) { 484 REL_ERR_LOSEBITS(lml, file, sym, rtype, uvalue, 2, off); 485 return (0); 486 } 487 488 if (re_flags & FLG_RE_SIGN) { 489 uvalue = (Sxword)uvalue >> bshift; 490 } else { 491 uvalue >>= bshift; 492 } 493 corevalue >>= bshift; 494 } 495 496 if ((rtype == R_SPARC_GOTDATA_HIX22) || 497 (rtype == R_SPARC_GOTDATA_OP_HIX22)) { 498 uvalue ^= ((Sxword)(*value) >> 31); 499 corevalue ^= ((Sxword)(*value) >> 31); 500 } 501 502 if (rep->re_mask && 503 (rtype != R_SPARC_HIX22) && (rtype != R_SPARC_TLS_LE_HIX22) && 504 (rtype != R_SPARC_GOTDATA_HIX22)) 505 uvalue &= rep->re_mask; 506 507 if ((rtype == R_SPARC_LOX10) || (rtype == R_SPARC_TLS_LE_LOX10)) { 508 uvalue |= 0x1c00; 509 corevalue |= 0x1c00; 510 } 511 512 if ((rtype == R_SPARC_GOTDATA_LOX10) || 513 (rtype == R_SPARC_GOTDATA_OP_LOX10)) { 514 uvalue |= ((Sxword)(*value) >> 31) & 0x1c00; 515 corevalue |= ((Sxword)(*value) >> 31) & 0x1c00; 516 } 517 518 519 if ((re_flags & FLG_RE_VERIFY) && sigbit_mask) { 520 if (((re_flags & FLG_RE_SIGN) && 521 (S_INRANGE((Sxword)uvalue, rep->re_sigbits - 1) == 0)) || 522 (!(re_flags & FLG_RE_SIGN) && 523 ((sigbit_mask & uvalue) != uvalue))) { 524 REL_ERR_NOFIT(lml, file, sym, rtype, uvalue); 525 return (0); 526 } 527 } 528 529 if (sigbit_mask) { 530 /* 531 * Again the R_SPARC_WDISP16 relocation takes special 532 * processing because of its non-continguous bits. 533 */ 534 if (re_flags & FLG_RE_WDISP16) 535 uvalue = ((uvalue & 0xc000) << 6) | 536 (uvalue & 0x3fff); 537 else 538 uvalue &= sigbit_mask; 539 /* 540 * Combine value back with original word 541 */ 542 uvalue |= basevalue; 543 } 544 *value = corevalue; 545 546 if (re_flags & FLG_RE_UNALIGN) { 547 int i; 548 uchar_t *src = (uchar_t *)&uvalue; 549 550 /* 551 * Adjust the offset. 552 */ 553 /* LINTED */ 554 i = (int)(sizeof (Xword) - field_size); 555 if (i > 0) 556 src += i; 557 558 for (i = field_size - 1; i >= 0; i--) 559 off[i] = src[i]; 560 } else { 561 switch (rep->re_fsize) { 562 case 1: 563 /* LINTED */ 564 *((uchar_t *)off) = (uchar_t)uvalue; 565 break; 566 case 2: 567 /* LINTED */ 568 *((Half *)off) = (Half)uvalue; 569 break; 570 case 4: 571 /* LINTED */ 572 *((Word *)off) = uvalue; 573 break; 574 case 8: 575 /* LINTED */ 576 *((Xword *)off) = uvalue; 577 break; 578 default: 579 /* 580 * To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ) 581 */ 582 REL_ERR_UNSUPSZ(lml, file, sym, rtype, rep->re_fsize); 583 return (0); 584 } 585 } 586 return (1); 587 } 588