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