reloc.c revision 331206
1/* $NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp $ */ 2 3/*- 4 * Copyright (c) 2000 Eduardo Horvath. 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Paul Kranenburg. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: stable/10/libexec/rtld-elf/sparc64/reloc.c 331206 2018-03-19 14:28:58Z marius $"); 35 36#include <sys/param.h> 37#include <sys/mman.h> 38 39#include <errno.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <unistd.h> 44 45#include "debug.h" 46#include "rtld.h" 47 48/* 49 * The following table holds for each relocation type: 50 * - the width in bits of the memory location the relocation 51 * applies to (not currently used) 52 * - the number of bits the relocation value must be shifted to the 53 * right (i.e. discard least significant bits) to fit into 54 * the appropriate field in the instruction word. 55 * - flags indicating whether 56 * * the relocation involves a symbol 57 * * the relocation is relative to the current position 58 * * the relocation is for a GOT entry 59 * * the relocation is relative to the load address 60 * 61 */ 62#define _RF_S 0x80000000 /* Resolve symbol */ 63#define _RF_A 0x40000000 /* Use addend */ 64#define _RF_P 0x20000000 /* Location relative */ 65#define _RF_G 0x10000000 /* GOT offset */ 66#define _RF_B 0x08000000 /* Load address relative */ 67#define _RF_U 0x04000000 /* Unaligned */ 68#define _RF_X 0x02000000 /* Bare symbols, needs proc */ 69#define _RF_D 0x01000000 /* Use dynamic TLS offset */ 70#define _RF_O 0x00800000 /* Use static TLS offset */ 71#define _RF_I 0x00400000 /* Use TLS object ID */ 72#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ 73#define _RF_RS(s) ( (s) & 0xff) /* right shift */ 74static const int reloc_target_flags[] = { 75 0, /* NONE */ 76 _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* 8 */ 77 _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* 16 */ 78 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 32 */ 79 _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ 80 _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ 81 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ 82 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ 83 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ 84 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(10), /* HI22 */ 85 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 22 */ 86 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 13 */ 87 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* LO10 */ 88 _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ 89 _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ 90 _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ 91 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ 92 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ 93 _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ 94 _RF_SZ(32) | _RF_RS(0), /* COPY */ 95 _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ 96 _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ 97 _RF_A| _RF_B| _RF_SZ(64) | _RF_RS(0), /* RELATIVE */ 98 _RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ 99 100 _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */ 101 _RF_A| _RF_SZ(32) | _RF_RS(10), /* HIPLT22 */ 102 _RF_A| _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ 103 _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ 104 _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PCPLT22 */ 105 _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT10 */ 106 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 10 */ 107 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 11 */ 108 _RF_S|_RF_A|_RF_X| _RF_SZ(64) | _RF_RS(0), /* 64 */ 109 _RF_S|_RF_A|/*extra*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ 110 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(42), /* HH22 */ 111 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(32), /* HM10 */ 112 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(10), /* LM22 */ 113 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(42), /* PC_HH22 */ 114 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(32), /* PC_HM10 */ 115 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC_LM22 */ 116 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP16 */ 117 _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP19 */ 118 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ 119 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 7 */ 120 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 5 */ 121 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* 6 */ 122 _RF_S|_RF_A|_RF_P| _RF_SZ(64) | _RF_RS(0), /* DISP64 */ 123 _RF_A| _RF_SZ(64) | _RF_RS(0), /* PLT64 */ 124 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(10), /* HIX22 */ 125 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* LOX10 */ 126 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(22), /* H44 */ 127 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(12), /* M44 */ 128 _RF_S|_RF_A|_RF_X| _RF_SZ(32) | _RF_RS(0), /* L44 */ 129 _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REGISTER */ 130 _RF_S|_RF_A| _RF_U| _RF_SZ(64) | _RF_RS(0), /* UA64 */ 131 _RF_S|_RF_A| _RF_U| _RF_SZ(16) | _RF_RS(0), /* UA16 */ 132 133 /* TLS */ 134 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* GD_HI22 */ 135 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GD_LO10 */ 136 0, /* GD_ADD */ 137 _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* GD_CALL */ 138 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LDM_HI22 */ 139 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LDM_LO10 */ 140 0, /* LDM_ADD */ 141 _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* LDM_CALL */ 142 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LDO_HIX22 */ 143 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LDO_LOX10 */ 144 0, /* LDO_ADD */ 145 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* IE_HI22 */ 146 _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* IE_LO10 */ 147 0, /* IE_LD */ 148 0, /* IE_LDX */ 149 0, /* IE_ADD */ 150 _RF_S|_RF_A| _RF_O| _RF_SZ(32) | _RF_RS(10), /* LE_HIX22 */ 151 _RF_S|_RF_A| _RF_O| _RF_SZ(32) | _RF_RS(0), /* LE_LOX10 */ 152 _RF_S| _RF_I| _RF_SZ(32) | _RF_RS(0), /* DTPMOD32 */ 153 _RF_S| _RF_I| _RF_SZ(64) | _RF_RS(0), /* DTPMOD64 */ 154 _RF_S|_RF_A| _RF_D| _RF_SZ(32) | _RF_RS(0), /* DTPOFF32 */ 155 _RF_S|_RF_A| _RF_D| _RF_SZ(64) | _RF_RS(0), /* DTPOFF64 */ 156 _RF_S|_RF_A| _RF_O| _RF_SZ(32) | _RF_RS(0), /* TPOFF32 */ 157 _RF_S|_RF_A| _RF_O| _RF_SZ(64) | _RF_RS(0) /* TPOFF64 */ 158}; 159 160#if 0 161static const char *const reloc_names[] = { 162 "NONE", "8", "16", "32", "DISP_8", "DISP_16", "DISP_32", "WDISP_30", 163 "WDISP_22", "HI22", "22", "13", "LO10", "GOT10", "GOT13", "GOT22", 164 "PC10", "PC22", "WPLT30", "COPY", "GLOB_DAT", "JMP_SLOT", "RELATIVE", 165 "UA_32", "PLT32", "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", 166 "PCPLT32", "10", "11", "64", "OLO10", "HH22", "HM10", "LM22", 167 "PC_HH22", "PC_HM10", "PC_LM22", "WDISP16", "WDISP19", "GLOB_JMP", 168 "7", "5", "6", "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", 169 "L44", "REGISTER", "UA64", "UA16", "GD_HI22", "GD_LO10", "GD_ADD", 170 "GD_CALL", "LDM_HI22", "LDMO10", "LDM_ADD", "LDM_CALL", "LDO_HIX22", 171 "LDO_LOX10", "LDO_ADD", "IE_HI22", "IE_LO10", "IE_LD", "IE_LDX", 172 "IE_ADD", "LE_HIX22", "LE_LOX10", "DTPMOD32", "DTPMOD64", "DTPOFF32", 173 "DTPOFF64", "TPOFF32", "TPOFF64" 174}; 175#endif 176 177#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) 178#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) 179#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) 180#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) 181#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) 182#define RELOC_BARE_SYMBOL(t) ((reloc_target_flags[t] & _RF_X) != 0) 183#define RELOC_USE_TLS_DOFF(t) ((reloc_target_flags[t] & _RF_D) != 0) 184#define RELOC_USE_TLS_OFF(t) ((reloc_target_flags[t] & _RF_O) != 0) 185#define RELOC_USE_TLS_ID(t) ((reloc_target_flags[t] & _RF_I) != 0) 186#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) 187#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) 188 189static const long reloc_target_bitmask[] = { 190#define _BM(x) (~(-(1ULL << (x)))) 191 0, /* NONE */ 192 _BM(8), _BM(16), _BM(32), /* 8, 16, 32 */ 193 _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ 194 _BM(30), _BM(22), /* WDISP30, WDISP22 */ 195 _BM(22), _BM(22), /* HI22, 22 */ 196 _BM(13), _BM(10), /* 13, LO10 */ 197 _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ 198 _BM(10), _BM(22), /* PC10, PC22 */ 199 _BM(30), 0, /* WPLT30, COPY */ 200 _BM(32), _BM(32), _BM(32), /* GLOB_DAT, JMP_SLOT, RELATIVE */ 201 _BM(32), _BM(32), /* UA32, PLT32 */ 202 _BM(22), _BM(10), /* HIPLT22, LOPLT10 */ 203 _BM(32), _BM(22), _BM(10), /* PCPLT32, PCPLT22, PCPLT10 */ 204 _BM(10), _BM(11), -1, /* 10, 11, 64 */ 205 _BM(13), _BM(22), /* OLO10, HH22 */ 206 _BM(10), _BM(22), /* HM10, LM22 */ 207 _BM(22), _BM(10), _BM(22), /* PC_HH22, PC_HM10, PC_LM22 */ 208 _BM(16), _BM(19), /* WDISP16, WDISP19 */ 209 -1, /* GLOB_JMP */ 210 _BM(7), _BM(5), _BM(6), /* 7, 5, 6 */ 211 -1, -1, /* DISP64, PLT64 */ 212 _BM(22), _BM(13), /* HIX22, LOX10 */ 213 _BM(22), _BM(10), _BM(13), /* H44, M44, L44 */ 214 -1, -1, _BM(16), /* REGISTER, UA64, UA16 */ 215 _BM(22), _BM(10), 0, _BM(30), /* GD_HI22, GD_LO10, GD_ADD, GD_CALL */ 216 _BM(22), _BM(10), 0, /* LDM_HI22, LDMO10, LDM_ADD */ 217 _BM(30), /* LDM_CALL */ 218 _BM(22), _BM(10), 0, /* LDO_HIX22, LDO_LOX10, LDO_ADD */ 219 _BM(22), _BM(10), 0, 0, /* IE_HI22, IE_LO10, IE_LD, IE_LDX */ 220 0, /* IE_ADD */ 221 _BM(22), _BM(13), /* LE_HIX22, LE_LOX10 */ 222 _BM(32), -1, /* DTPMOD32, DTPMOD64 */ 223 _BM(32), -1, /* DTPOFF32, DTPOFF64 */ 224 _BM(32), -1 /* TPOFF32, TPOFF64 */ 225#undef _BM 226}; 227#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) 228 229#undef flush 230#define flush(va, offs) \ 231 __asm __volatile("flush %0 + %1" : : "r" (va), "I" (offs)); 232 233static int reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, 234 SymCache *cache, int flags, RtldLockState *lockstate); 235static void install_plt(Elf_Word *pltgot, Elf_Addr proc); 236 237extern char _rtld_bind_start_0[]; 238extern char _rtld_bind_start_1[]; 239 240int 241do_copy_relocations(Obj_Entry *dstobj) 242{ 243 const Elf_Rela *relalim; 244 const Elf_Rela *rela; 245 const Elf_Sym *dstsym; 246 const Elf_Sym *srcsym; 247 void *dstaddr; 248 const void *srcaddr; 249 const Obj_Entry *srcobj, *defobj; 250 SymLook req; 251 const char *name; 252 size_t size; 253 int res; 254 255 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 256 257 relalim = (const Elf_Rela *)((caddr_t)dstobj->rela + dstobj->relasize); 258 for (rela = dstobj->rela; rela < relalim; rela++) { 259 if (ELF_R_TYPE(rela->r_info) == R_SPARC_COPY) { 260 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 261 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 262 name = dstobj->strtab + dstsym->st_name; 263 size = dstsym->st_size; 264 symlook_init(&req, name); 265 req.ventry = fetch_ventry(dstobj, 266 ELF_R_SYM(rela->r_info)); 267 req.flags = SYMLOOK_EARLY; 268 269 for (srcobj = globallist_next(dstobj); srcobj != NULL; 270 srcobj = globallist_next(srcobj)) { 271 res = symlook_obj(&req, srcobj); 272 if (res == 0) { 273 srcsym = req.sym_out; 274 defobj = req.defobj_out; 275 break; 276 } 277 } 278 if (srcobj == NULL) { 279 _rtld_error("Undefined symbol \"%s\"" 280 "referenced from COPY relocation" 281 "in %s", name, dstobj->path); 282 return (-1); 283 } 284 285 srcaddr = (const void *)(defobj->relocbase + 286 srcsym->st_value); 287 memcpy(dstaddr, srcaddr, size); 288 } 289 } 290 291 return (0); 292} 293 294int 295reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 296 RtldLockState *lockstate) 297{ 298 const Elf_Rela *relalim; 299 const Elf_Rela *rela; 300 SymCache *cache; 301 int r = -1; 302 303 if ((flags & SYMLOOK_IFUNC) != 0) 304 /* XXX not implemented */ 305 return (0); 306 307 /* 308 * The dynamic loader may be called from a thread, we have 309 * limited amounts of stack available so we cannot use alloca(). 310 */ 311 if (obj != obj_rtld) { 312 cache = calloc(obj->dynsymcount, sizeof(SymCache)); 313 /* No need to check for NULL here */ 314 } else 315 cache = NULL; 316 317 relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize); 318 for (rela = obj->rela; rela < relalim; rela++) { 319 if (reloc_nonplt_object(obj, rela, cache, flags, lockstate) < 0) 320 goto done; 321 } 322 r = 0; 323done: 324 if (cache != NULL) 325 free(cache); 326 return (r); 327} 328 329static int 330reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, SymCache *cache, 331 int flags, RtldLockState *lockstate) 332{ 333 const Obj_Entry *defobj; 334 const Elf_Sym *def; 335 Elf_Addr *where; 336 Elf_Word *where32; 337 Elf_Word type; 338 Elf_Addr value; 339 Elf_Addr mask; 340 341 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 342 where32 = (Elf_Word *)where; 343 defobj = NULL; 344 def = NULL; 345 346 type = ELF64_R_TYPE_ID(rela->r_info); 347 if (type == R_SPARC_NONE) 348 return (0); 349 350 /* We do JMP_SLOTs below. */ 351 if (type == R_SPARC_JMP_SLOT) 352 return (0); 353 354 /* COPY relocs are also handled elsewhere. */ 355 if (type == R_SPARC_COPY) 356 return (0); 357 358 /* Ignore ADD and CALL relocations for dynamic TLS references. */ 359 if (type == R_SPARC_TLS_GD_ADD || type == R_SPARC_TLS_GD_CALL || 360 type == R_SPARC_TLS_LDM_ADD || type == R_SPARC_TLS_LDM_CALL || 361 type == R_SPARC_TLS_LDO_ADD) 362 return (0); 363 364 /* 365 * Note: R_SPARC_TLS_TPOFF64 must be the numerically largest 366 * relocation type. 367 */ 368 if (type >= nitems(reloc_target_bitmask)) { 369 _rtld_error("%s: Unsupported relocation type %d in non-PLT " 370 "object\n", obj->path, type); 371 return (-1); 372 } 373 374 value = rela->r_addend; 375 376 /* 377 * Handle relative relocs here, because we might not be able to access 378 * globals yet. 379 */ 380 if (type == R_SPARC_RELATIVE) { 381 /* XXXX -- apparently we ignore the preexisting value. */ 382 *where = (Elf_Addr)(obj->relocbase + value); 383 return (0); 384 } 385 386 /* 387 * If we get here while relocating rtld itself, we will crash because 388 * a non-local variable is accessed. 389 */ 390 if (RELOC_RESOLVE_SYMBOL(type)) { 391 /* Find the symbol. */ 392 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 393 flags, cache, lockstate); 394 if (def == NULL) 395 return (-1); 396 397 if (RELOC_USE_TLS_ID(type)) 398 value = (Elf_Addr)defobj->tlsindex; 399 else if (RELOC_USE_TLS_DOFF(type)) 400 value += (Elf_Addr)def->st_value; 401 else if (RELOC_USE_TLS_OFF(type)) { 402 /* 403 * We lazily allocate offsets for static TLS as we 404 * see the first relocation that references the TLS 405 * block. This allows us to support (small amounts 406 * of) static TLS in dynamically loaded modules. If 407 * we run out of space, we generate an error. 408 */ 409 if (!defobj->tls_done && 410 !allocate_tls_offset((Obj_Entry*)defobj)) { 411 _rtld_error("%s: No space available for " 412 "static Thread Local Storage", obj->path); 413 return (-1); 414 } 415 value += (Elf_Addr)(def->st_value - 416 defobj->tlsoffset); 417 } else { 418 /* Add in the symbol's absolute address. */ 419 value += (Elf_Addr)(def->st_value + 420 defobj->relocbase); 421 } 422 } 423 424 if (type == R_SPARC_OLO10) 425 value = (value & 0x3ff) + ELF64_R_TYPE_DATA(rela->r_info); 426 427 if (type == R_SPARC_HIX22 || type == R_SPARC_TLS_LE_HIX22) 428 value ^= 0xffffffffffffffff; 429 430 if (RELOC_PC_RELATIVE(type)) 431 value -= (Elf_Addr)where; 432 433 if (RELOC_BASE_RELATIVE(type)) { 434 /* 435 * Note that even though sparcs use `Elf_rela' exclusively 436 * we still need the implicit memory addend in relocations 437 * referring to GOT entries. Undoubtedly, someone f*cked 438 * this up in the distant past, and now we're stuck with 439 * it in the name of compatibility for all eternity ... 440 * 441 * In any case, the implicit and explicit should be mutually 442 * exclusive. We provide a check for that here. 443 */ 444 /* XXXX -- apparently we ignore the preexisting value */ 445 value += (Elf_Addr)(obj->relocbase); 446 } 447 448 mask = RELOC_VALUE_BITMASK(type); 449 value >>= RELOC_VALUE_RIGHTSHIFT(type); 450 value &= mask; 451 452 if (type == R_SPARC_LOX10 || type == R_SPARC_TLS_LE_LOX10) 453 value |= 0x1c00; 454 455 if (RELOC_UNALIGNED(type)) { 456 /* Handle unaligned relocations. */ 457 Elf_Addr tmp; 458 char *ptr; 459 int size; 460 int i; 461 462 size = RELOC_TARGET_SIZE(type) / 8; 463 ptr = (char *)where; 464 tmp = 0; 465 466 /* Read it in one byte at a time. */ 467 for (i = 0; i < size; i++) 468 tmp = (tmp << 8) | ptr[i]; 469 470 tmp &= ~mask; 471 tmp |= value; 472 473 /* Write it back out. */ 474 for (i = 0; i < size; i++) 475 ptr[i] = ((tmp >> ((size - i - 1) * 8)) & 0xff); 476 } else if (RELOC_TARGET_SIZE(type) > 32) { 477 *where &= ~mask; 478 *where |= value; 479 } else { 480 *where32 &= ~mask; 481 *where32 |= value; 482 } 483 484 return (0); 485} 486 487int 488reloc_plt(Obj_Entry *obj) 489{ 490#if 0 491 const Obj_Entry *defobj; 492 const Elf_Rela *relalim; 493 const Elf_Rela *rela; 494 const Elf_Sym *def; 495 Elf_Addr *where; 496 Elf_Addr value; 497 498 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 499 for (rela = obj->pltrela; rela < relalim; rela++) { 500 if (rela->r_addend == 0) 501 continue; 502 assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT); 503 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 504 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 505 SYMLOOK_IN_PLT, NULL, lockstate); 506 value = (Elf_Addr)(defobj->relocbase + def->st_value); 507 *where = value; 508 } 509#endif 510 return (0); 511} 512 513/* 514 * Instruction templates: 515 */ 516#define BAA 0x10400000 /* ba,a %xcc, 0 */ 517#define SETHI 0x03000000 /* sethi %hi(0), %g1 */ 518#define JMP 0x81c06000 /* jmpl %g1+%lo(0), %g0 */ 519#define NOP 0x01000000 /* sethi %hi(0), %g0 */ 520#define OR 0x82806000 /* or %g1, 0, %g1 */ 521#define XOR 0x82c06000 /* xor %g1, 0, %g1 */ 522#define MOV71 0x8283a000 /* or %o7, 0, %g1 */ 523#define MOV17 0x9c806000 /* or %g1, 0, %o7 */ 524#define CALL 0x40000000 /* call 0 */ 525#define SLLX 0x8b407000 /* sllx %g1, 0, %g1 */ 526#define SETHIG5 0x0b000000 /* sethi %hi(0), %g5 */ 527#define ORG5 0x82804005 /* or %g1, %g5, %g1 */ 528 529/* %hi(v) with variable shift */ 530#define HIVAL(v, s) (((v) >> (s)) & 0x003fffff) 531#define LOVAL(v) ((v) & 0x000003ff) 532 533int 534reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 535{ 536 const Obj_Entry *defobj; 537 const Elf_Rela *relalim; 538 const Elf_Rela *rela; 539 const Elf_Sym *def; 540 Elf_Addr *where; 541 Elf_Addr target; 542 543 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 544 for (rela = obj->pltrela; rela < relalim; rela++) { 545 assert(ELF64_R_TYPE_ID(rela->r_info) == R_SPARC_JMP_SLOT); 546 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 547 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 548 SYMLOOK_IN_PLT | flags, NULL, lockstate); 549 if (def == NULL) 550 return -1; 551 target = (Elf_Addr)(defobj->relocbase + def->st_value); 552 reloc_jmpslot(where, target, defobj, obj, (Elf_Rel *)rela); 553 } 554 obj->jmpslots_done = true; 555 return (0); 556} 557 558int 559reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) 560{ 561 562 /* XXX not implemented */ 563 return (0); 564} 565 566int 567reloc_gnu_ifunc(Obj_Entry *obj, int flags, 568 struct Struct_RtldLockState *lockstate) 569{ 570 571 /* XXX not implemented */ 572 return (0); 573} 574 575Elf_Addr 576reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj, 577 const Obj_Entry *refobj, const Elf_Rel *rel) 578{ 579 const Elf_Rela *rela = (const Elf_Rela *)rel; 580 Elf_Addr offset; 581 Elf_Word *where; 582 583 if (rela - refobj->pltrela < 32764) { 584 /* 585 * At the PLT entry pointed at by `where', we now construct 586 * a direct transfer to the now fully resolved function 587 * address. 588 * 589 * A PLT entry is supposed to start by looking like this: 590 * 591 * sethi (. - .PLT0), %g1 592 * ba,a %xcc, .PLT1 593 * nop 594 * nop 595 * nop 596 * nop 597 * nop 598 * nop 599 * 600 * When we replace these entries we start from the second 601 * entry and do it in reverse order so the last thing we 602 * do is replace the branch. That allows us to change this 603 * atomically. 604 * 605 * We now need to find out how far we need to jump. We 606 * have a choice of several different relocation techniques 607 * which are increasingly expensive. 608 */ 609 where = (Elf_Word *)wherep; 610 offset = ((Elf_Addr)where) - target; 611 if (offset <= (1L<<20) && offset >= -(1L<<20)) { 612 /* 613 * We're within 1MB -- we can use a direct branch 614 * instruction. 615 * 616 * We can generate this pattern: 617 * 618 * sethi %hi(. - .PLT0), %g1 619 * ba,a %xcc, addr 620 * nop 621 * nop 622 * nop 623 * nop 624 * nop 625 * nop 626 * 627 */ 628 where[1] = BAA | ((offset >> 2) &0x3fffff); 629 flush(where, 4); 630 } else if (target >= 0 && target < (1L<<32)) { 631 /* 632 * We're within 32-bits of address zero. 633 * 634 * The resulting code in the jump slot is: 635 * 636 * sethi %hi(. - .PLT0), %g1 637 * sethi %hi(addr), %g1 638 * jmp %g1+%lo(addr) 639 * nop 640 * nop 641 * nop 642 * nop 643 * nop 644 * 645 */ 646 where[2] = JMP | LOVAL(target); 647 flush(where, 8); 648 where[1] = SETHI | HIVAL(target, 10); 649 flush(where, 4); 650 } else if (target <= 0 && target > -(1L<<32)) { 651 /* 652 * We're within 32-bits of address -1. 653 * 654 * The resulting code in the jump slot is: 655 * 656 * sethi %hi(. - .PLT0), %g1 657 * sethi %hix(addr), %g1 658 * xor %g1, %lox(addr), %g1 659 * jmp %g1 660 * nop 661 * nop 662 * nop 663 * nop 664 * 665 */ 666 where[3] = JMP; 667 flush(where, 12); 668 where[2] = XOR | ((~target) & 0x00001fff); 669 flush(where, 8); 670 where[1] = SETHI | HIVAL(~target, 10); 671 flush(where, 4); 672 } else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) { 673 /* 674 * We're within 32-bits -- we can use a direct call 675 * insn 676 * 677 * The resulting code in the jump slot is: 678 * 679 * sethi %hi(. - .PLT0), %g1 680 * mov %o7, %g1 681 * call (.+offset) 682 * mov %g1, %o7 683 * nop 684 * nop 685 * nop 686 * nop 687 * 688 */ 689 where[3] = MOV17; 690 flush(where, 12); 691 where[2] = CALL | ((offset >> 4) & 0x3fffffff); 692 flush(where, 8); 693 where[1] = MOV71; 694 flush(where, 4); 695 } else if (offset >= 0 && offset < (1L<<44)) { 696 /* 697 * We're within 44 bits. We can generate this 698 * pattern: 699 * 700 * The resulting code in the jump slot is: 701 * 702 * sethi %hi(. - .PLT0), %g1 703 * sethi %h44(addr), %g1 704 * or %g1, %m44(addr), %g1 705 * sllx %g1, 12, %g1 706 * jmp %g1+%l44(addr) 707 * nop 708 * nop 709 * nop 710 * 711 */ 712 where[4] = JMP | LOVAL(offset); 713 flush(where, 16); 714 where[3] = SLLX | 12; 715 flush(where, 12); 716 where[2] = OR | (((offset) >> 12) & 0x00001fff); 717 flush(where, 8); 718 where[1] = SETHI | HIVAL(offset, 22); 719 flush(where, 4); 720 } else if (offset < 0 && offset > -(1L<<44)) { 721 /* 722 * We're within 44 bits. We can generate this 723 * pattern: 724 * 725 * The resulting code in the jump slot is: 726 * 727 * sethi %hi(. - .PLT0), %g1 728 * sethi %h44(-addr), %g1 729 * xor %g1, %m44(-addr), %g1 730 * sllx %g1, 12, %g1 731 * jmp %g1+%l44(addr) 732 * nop 733 * nop 734 * nop 735 * 736 */ 737 where[4] = JMP | LOVAL(offset); 738 flush(where, 16); 739 where[3] = SLLX | 12; 740 flush(where, 12); 741 where[2] = XOR | (((~offset) >> 12) & 0x00001fff); 742 flush(where, 8); 743 where[1] = SETHI | HIVAL(~offset, 22); 744 flush(where, 4); 745 } else { 746 /* 747 * We need to load all 64-bits 748 * 749 * The resulting code in the jump slot is: 750 * 751 * sethi %hi(. - .PLT0), %g1 752 * sethi %hh(addr), %g1 753 * sethi %lm(addr), %g5 754 * or %g1, %hm(addr), %g1 755 * sllx %g1, 32, %g1 756 * or %g1, %g5, %g1 757 * jmp %g1+%lo(addr) 758 * nop 759 * 760 */ 761 where[6] = JMP | LOVAL(target); 762 flush(where, 24); 763 where[5] = ORG5; 764 flush(where, 20); 765 where[4] = SLLX | 32; 766 flush(where, 16); 767 where[3] = OR | LOVAL((target) >> 32); 768 flush(where, 12); 769 where[2] = SETHIG5 | HIVAL(target, 10); 770 flush(where, 8); 771 where[1] = SETHI | HIVAL(target, 42); 772 flush(where, 4); 773 } 774 } else { 775 /* 776 * This is a high PLT slot; the relocation offset specifies a 777 * pointer that needs to be frobbed; no actual code needs to 778 * be modified. The pointer to be calculated needs the addend 779 * added and the reference object relocation base subtraced. 780 */ 781 *wherep = target + rela->r_addend - 782 (Elf_Addr)refobj->relocbase; 783 } 784 785 return (target); 786} 787 788void 789ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused) 790{ 791 792} 793 794extern void __sparc_utrap_setup(void); 795 796void 797pre_init(void) 798{ 799 800 __sparc_utrap_setup(); 801} 802 803/* 804 * Install rtld function call into this PLT slot. 805 */ 806#define SAVE 0x9de3bf50 807#define SETHI_l0 0x21000000 808#define SETHI_l1 0x23000000 809#define OR_l0_l0 0xa0142000 810#define SLLX_l0_32_l0 0xa12c3020 811#define OR_l0_l1_l0 0xa0140011 812#define JMPL_l0_o1 0x93c42000 813#define MOV_g1_o0 0x90100001 814 815void 816init_pltgot(Obj_Entry *obj) 817{ 818 Elf_Word *entry; 819 820 if (obj->pltgot != NULL) { 821 entry = (Elf_Word *)obj->pltgot; 822 install_plt(&entry[0], (Elf_Addr)_rtld_bind_start_0); 823 install_plt(&entry[8], (Elf_Addr)_rtld_bind_start_1); 824 obj->pltgot[8] = (Elf_Addr)obj; 825 } 826} 827 828static void 829install_plt(Elf_Word *pltgot, Elf_Addr proc) 830{ 831 832 pltgot[0] = SAVE; 833 flush(pltgot, 0); 834 pltgot[1] = SETHI_l0 | HIVAL(proc, 42); 835 flush(pltgot, 4); 836 pltgot[2] = SETHI_l1 | HIVAL(proc, 10); 837 flush(pltgot, 8); 838 pltgot[3] = OR_l0_l0 | LOVAL((proc) >> 32); 839 flush(pltgot, 12); 840 pltgot[4] = SLLX_l0_32_l0; 841 flush(pltgot, 16); 842 pltgot[5] = OR_l0_l1_l0; 843 flush(pltgot, 20); 844 pltgot[6] = JMPL_l0_o1 | LOVAL(proc); 845 flush(pltgot, 24); 846 pltgot[7] = MOV_g1_o0; 847 flush(pltgot, 28); 848} 849 850void 851allocate_initial_tls(Obj_Entry *objs) 852{ 853 Elf_Addr* tpval; 854 855 /* 856 * Fix the size of the static TLS block by using the maximum offset 857 * allocated so far and adding a bit for dynamic modules to use. 858 */ 859 tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA; 860 tpval = allocate_tls(objs, NULL, 3 * sizeof(Elf_Addr), 861 sizeof(Elf_Addr)); 862 __asm __volatile("mov %0, %%g7" : : "r" (tpval)); 863} 864 865void *__tls_get_addr(tls_index *ti) 866{ 867 register Elf_Addr** tp __asm__("%g7"); 868 869 return (tls_get_addr_common(tp, ti->ti_module, ti->ti_offset)); 870} 871