1 /* $NetBSD: mips_reloc.c,v 1.72 2018/01/19 23:17:41 christos Exp $ */ 2 3 /* 4 * Copyright 1997 Michael L. Hitch <mhitch@montana.edu> 5 * Portions copyright 2002 Charles M. Hannum <root@ihack.net> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #ifndef lint 33 __RCSID("$NetBSD: mips_reloc.c,v 1.72 2018/01/19 23:17:41 christos Exp $"); 34 #endif /* not lint */ 35 36 #include <sys/types.h> 37 #include <sys/endian.h> 38 #include <sys/tls.h> 39 40 #include <stdlib.h> 41 #include <string.h> 42 43 #include "debug.h" 44 #include "rtld.h" 45 46 #ifdef __mips_o32 47 #define SUPPORT_OLD_BROKEN_LD 48 #endif 49 50 void _rtld_bind_start(void); 51 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); 52 caddr_t _rtld_bind(Elf_Word, Elf_Addr, Elf_Addr, Elf_Addr); 53 54 /* 55 * It is possible for the compiler to emit relocations for unaligned data. 56 * We handle this situation with these inlines. 57 */ 58 59 #if ELFSIZE == 64 60 /* 61 * ELF64 MIPS encodes the relocs uniquely. The first 32-bits of info contain 62 * the symbol index. The top 32-bits contain three relocation types encoded 63 * in big-endian integer with first relocation in LSB. This means for little 64 * endian we have to byte swap that integer (r_type). 65 */ 66 #define Elf_Sxword Elf64_Sxword 67 #define ELF_R_NXTTYPE_64_P(r_type) ((((r_type) >> 8) & 0xff) == R_TYPE(64)) 68 #if BYTE_ORDER == LITTLE_ENDIAN 69 #undef ELF_R_SYM 70 #undef ELF_R_TYPE 71 #define ELF_R_SYM(r_info) ((r_info) & 0xffffffff) 72 #define ELF_R_TYPE(r_info) bswap32((r_info) >> 32) 73 #endif 74 #else 75 #define ELF_R_NXTTYPE_64_P(r_type) (0) 76 #define Elf_Sxword Elf32_Sword 77 #endif 78 #define GOT1_MASK (~(Elf_Addr)0 >> 1) 79 80 static inline Elf_Sxword 81 load_ptr(void *where, size_t len) 82 { 83 Elf_Sxword val; 84 85 if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) { 86 #if ELFSIZE == 64 87 if (len == sizeof(Elf_Sxword)) 88 return *(Elf_Sxword *)where; 89 #endif 90 return *(Elf_Sword *)where; 91 } 92 93 val = 0; 94 #if BYTE_ORDER == LITTLE_ENDIAN 95 (void)memcpy(&val, where, len); 96 #endif 97 #if BYTE_ORDER == BIG_ENDIAN 98 (void)memcpy((uint8_t *)((&val)+1) - len, where, len); 99 #endif 100 return (len == sizeof(Elf_Sxword)) ? val : (Elf_Sword)val; 101 } 102 103 static inline void 104 store_ptr(void *where, Elf_Sxword val, size_t len) 105 { 106 if (__predict_true(((uintptr_t)where & (len - 1)) == 0)) { 107 #if ELFSIZE == 64 108 if (len == sizeof(Elf_Sxword)) { 109 *(Elf_Sxword *)where = val; 110 return; 111 } 112 #endif 113 *(Elf_Sword *)where = val; 114 return; 115 } 116 #if BYTE_ORDER == LITTLE_ENDIAN 117 (void)memcpy(where, &val, len); 118 #endif 119 #if BYTE_ORDER == BIG_ENDIAN 120 (void)memcpy(where, (const uint8_t *)((&val)+1) - len, len); 121 #endif 122 } 123 124 125 void 126 _rtld_setup_pltgot(const Obj_Entry *obj) 127 { 128 obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start; 129 /* XXX only if obj->pltgot[1] & 0x80000000 ?? */ 130 obj->pltgot[1] |= (Elf_Addr) obj; 131 } 132 133 void 134 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) 135 { 136 const Elf_Rel *rel = 0, *rellim; 137 Elf_Addr relsz = 0; 138 void *where; 139 const Elf_Sym *symtab = NULL, *sym; 140 Elf_Addr *got = NULL; 141 Elf_Word local_gotno = 0, symtabno = 0, gotsym = 0; 142 size_t i; 143 144 for (; dynp->d_tag != DT_NULL; dynp++) { 145 switch (dynp->d_tag) { 146 case DT_REL: 147 rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); 148 break; 149 case DT_RELSZ: 150 relsz = dynp->d_un.d_val; 151 break; 152 case DT_SYMTAB: 153 symtab = (const Elf_Sym *)(relocbase + dynp->d_un.d_ptr); 154 break; 155 case DT_PLTGOT: 156 got = (Elf_Addr *)(relocbase + dynp->d_un.d_ptr); 157 break; 158 case DT_MIPS_LOCAL_GOTNO: 159 local_gotno = dynp->d_un.d_val; 160 break; 161 case DT_MIPS_SYMTABNO: 162 symtabno = dynp->d_un.d_val; 163 break; 164 case DT_MIPS_GOTSYM: 165 gotsym = dynp->d_un.d_val; 166 break; 167 } 168 } 169 170 i = (got[1] & 0x80000000) ? 2 : 1; 171 /* Relocate the local GOT entries */ 172 got += i; 173 for (; i < local_gotno; i++) 174 *got++ += relocbase; 175 sym = symtab + gotsym; 176 /* Now do the global GOT entries */ 177 for (i = gotsym; i < symtabno; i++) { 178 *got = sym->st_value + relocbase; 179 ++sym; 180 ++got; 181 } 182 183 rellim = (const Elf_Rel *)((uintptr_t)rel + relsz); 184 for (; rel < rellim; rel++) { 185 Elf_Word r_symndx, r_type; 186 187 where = (void *)(relocbase + rel->r_offset); 188 189 r_symndx = ELF_R_SYM(rel->r_info); 190 r_type = ELF_R_TYPE(rel->r_info); 191 192 switch (r_type & 0xff) { 193 case R_TYPE(REL32): { 194 const size_t rlen = 195 ELF_R_NXTTYPE_64_P(r_type) 196 ? sizeof(Elf_Sxword) 197 : sizeof(Elf_Sword); 198 Elf_Sxword old = load_ptr(where, rlen); 199 Elf_Sxword val = old; 200 #if ELFSIZE == 64 201 assert(r_type == R_TYPE(REL32) 202 || r_type == (R_TYPE(REL32)|(R_TYPE(64) << 8))); 203 #endif 204 assert(r_symndx < gotsym); 205 sym = symtab + r_symndx; 206 assert(ELF_ST_BIND(sym->st_info) == STB_LOCAL); 207 val += relocbase; 208 store_ptr(where, val, sizeof(Elf_Sword)); 209 rdbg(("REL32/L(%p) %p -> %p in <self>", 210 where, (void *)old, (void *)val)); 211 store_ptr(where, val, rlen); 212 break; 213 } 214 215 case R_TYPE(GPREL32): 216 case R_TYPE(NONE): 217 break; 218 219 220 default: 221 abort(); 222 } 223 } 224 } 225 226 int 227 _rtld_relocate_nonplt_objects(Obj_Entry *obj) 228 { 229 const Elf_Rel *rel; 230 Elf_Addr *got = obj->pltgot; 231 const Elf_Sym *sym, *def = NULL; 232 const Obj_Entry *defobj = NULL; 233 unsigned long last_symnum = ULONG_MAX; 234 Elf_Word i; 235 #ifdef SUPPORT_OLD_BROKEN_LD 236 int broken; 237 #endif 238 239 #ifdef SUPPORT_OLD_BROKEN_LD 240 broken = 0; 241 sym = obj->symtab; 242 for (i = 1; i < 12; i++) 243 if (sym[i].st_info == ELF_ST_INFO(STB_LOCAL, STT_NOTYPE)) 244 broken = 1; 245 dbg(("%s: broken=%d", obj->path, broken)); 246 #endif 247 248 i = (got[1] & 0x80000000) ? 2 : 1; 249 /* Relocate the local GOT entries */ 250 got += i; 251 for (; i < obj->local_gotno; i++) 252 *got++ += (Elf_Addr)obj->relocbase; 253 sym = obj->symtab + obj->gotsym; 254 /* Now do the global GOT entries */ 255 for (i = obj->gotsym; i < obj->symtabno; i++) { 256 rdbg((" doing got %d sym %p (%s, %lx)", i - obj->gotsym, sym, 257 sym->st_name + obj->strtab, (u_long) *got)); 258 259 #ifdef SUPPORT_OLD_BROKEN_LD 260 if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && 261 broken && sym->st_shndx == SHN_UNDEF) { 262 /* 263 * XXX DANGER WILL ROBINSON! 264 * You might think this is stupid, as it intentionally 265 * defeats lazy binding -- and you'd be right. 266 * Unfortunately, for lazy binding to work right, we 267 * need to a way to force the GOT slots used for 268 * function pointers to be resolved immediately. This 269 * is supposed to be done automatically by the linker, 270 * by not outputting a PLT slot and setting st_value 271 * to 0 if there are non-PLT references, but older 272 * versions of GNU ld do not do this. 273 */ 274 def = _rtld_find_symdef(i, obj, &defobj, false); 275 if (def == NULL) 276 return -1; 277 *got = def->st_value + (Elf_Addr)defobj->relocbase; 278 } else 279 #endif 280 if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && 281 sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) { 282 /* 283 * If there are non-PLT references to the function, 284 * st_value should be 0, forcing us to resolve the 285 * address immediately. 286 * 287 * XXX DANGER WILL ROBINSON! 288 * The linker is not outputting PLT slots for calls to 289 * functions that are defined in the same shared 290 * library. This is a bug, because it can screw up 291 * link ordering rules if the symbol is defined in 292 * more than one module. For now, if there is a 293 * definition, we fail the test above and force a full 294 * symbol lookup. This means that all intra-module 295 * calls are bound immediately. - mycroft, 2003/09/24 296 */ 297 *got = sym->st_value + (Elf_Addr)obj->relocbase; 298 } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) { 299 /* Symbols with index SHN_ABS are not relocated. */ 300 if (sym->st_shndx != SHN_ABS) 301 *got = sym->st_value + 302 (Elf_Addr)obj->relocbase; 303 } else { 304 def = _rtld_find_symdef(i, obj, &defobj, false); 305 if (def == NULL) 306 return -1; 307 *got = def->st_value + (Elf_Addr)defobj->relocbase; 308 } 309 310 rdbg((" --> now %lx", (u_long) *got)); 311 ++sym; 312 ++got; 313 } 314 315 got = obj->pltgot; 316 for (rel = obj->rel; rel < obj->rellim; rel++) { 317 unsigned long symnum; 318 void *where; 319 320 where = obj->relocbase + rel->r_offset; 321 322 switch (ELF_R_TYPE(rel->r_info) & 0xff) { 323 #if ELFSIZE == 64 324 case R_TYPE(TLS_DTPMOD64): 325 case R_TYPE(TLS_DTPREL64): 326 case R_TYPE(TLS_TPREL64): 327 #else 328 case R_TYPE(TLS_DTPMOD32): 329 case R_TYPE(TLS_DTPREL32): 330 case R_TYPE(TLS_TPREL32): 331 #endif 332 symnum = ELF_R_SYM(rel->r_info); 333 if (last_symnum != symnum) { 334 last_symnum = symnum; 335 def = _rtld_find_symdef(symnum, obj, &defobj, 336 false); 337 if (def == NULL) 338 return -1; 339 } 340 break; 341 default: 342 break; 343 } 344 345 switch (ELF_R_TYPE(rel->r_info) & 0xff) { 346 case R_TYPE(NONE): 347 break; 348 349 case R_TYPE(REL32): { 350 /* 32-bit PC-relative reference */ 351 const Elf_Sym *def2; 352 const size_t rlen = 353 ELF_R_NXTTYPE_64_P(ELF_R_TYPE(rel->r_info)) 354 ? sizeof(Elf_Sxword) 355 : sizeof(Elf_Sword); 356 Elf_Sxword old = load_ptr(where, rlen); 357 Elf_Sxword val = old; 358 359 def2 = obj->symtab + ELF_R_SYM(rel->r_info); 360 361 if (ELF_R_SYM(rel->r_info) >= obj->gotsym) { 362 val += got[obj->local_gotno + 363 ELF_R_SYM(rel->r_info) - obj->gotsym]; 364 rdbg(("REL32/G(%p) %p --> %p (%s) in %s", 365 where, (void *)old, (void *)val, 366 obj->strtab + def2->st_name, 367 obj->path)); 368 } else { 369 /* 370 * XXX: ABI DIFFERENCE! 371 * 372 * Old NetBSD binutils would generate shared 373 * libs with section-relative relocations being 374 * already adjusted for the start address of 375 * the section. 376 * 377 * New binutils, OTOH, generate shared libs 378 * with the same relocations being based at 379 * zero, so we need to add in the start address 380 * of the section. 381 * 382 * --rkb, Oct 6, 2001 383 */ 384 385 if (def2->st_info == 386 ELF_ST_INFO(STB_LOCAL, STT_SECTION) 387 #ifdef SUPPORT_OLD_BROKEN_LD 388 && !broken 389 #endif 390 ) 391 val += (Elf_Addr)def->st_value; 392 393 val += (Elf_Addr)obj->relocbase; 394 395 rdbg(("REL32/L(%p) %p -> %p (%s) in %s", 396 where, (void *)old, (void *)val, 397 obj->strtab + def2->st_name, obj->path)); 398 } 399 store_ptr(where, val, rlen); 400 break; 401 } 402 403 #if ELFSIZE == 64 404 case R_TYPE(TLS_DTPMOD64): 405 #else 406 case R_TYPE(TLS_DTPMOD32): 407 #endif 408 { 409 Elf_Addr old = load_ptr(where, ELFSIZE / 8); 410 Elf_Addr val = old; 411 412 val += (Elf_Addr)defobj->tlsindex; 413 414 store_ptr(where, val, ELFSIZE / 8); 415 rdbg(("DTPMOD %s in %s --> %p in %s", 416 obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name, 417 obj->path, (void *)old, defobj->path)); 418 break; 419 } 420 421 #if ELFSIZE == 64 422 case R_TYPE(TLS_DTPREL64): 423 #else 424 case R_TYPE(TLS_DTPREL32): 425 #endif 426 { 427 Elf_Addr old = load_ptr(where, ELFSIZE / 8); 428 Elf_Addr val = old; 429 430 if (!defobj->tls_done && _rtld_tls_offset_allocate(obj)) 431 return -1; 432 433 val += (Elf_Addr)def->st_value - TLS_DTV_OFFSET; 434 store_ptr(where, val, ELFSIZE / 8); 435 436 rdbg(("DTPREL %s in %s --> %p in %s", 437 obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name, 438 obj->path, (void *)old, defobj->path)); 439 break; 440 } 441 442 #if ELFSIZE == 64 443 case R_TYPE(TLS_TPREL64): 444 #else 445 case R_TYPE(TLS_TPREL32): 446 #endif 447 { 448 Elf_Addr old = load_ptr(where, ELFSIZE / 8); 449 Elf_Addr val = old; 450 451 if (!defobj->tls_done && _rtld_tls_offset_allocate(obj)) 452 return -1; 453 454 val += (Elf_Addr)(def->st_value + defobj->tlsoffset 455 - TLS_TP_OFFSET); 456 store_ptr(where, val, ELFSIZE / 8); 457 458 rdbg(("TPREL %s in %s --> %p in %s", 459 obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name, 460 obj->path, where, defobj->path)); 461 break; 462 } 463 464 default: 465 rdbg(("sym = %lu, type = %lu, offset = %p, " 466 "contents = %p, symbol = %s", 467 (u_long)ELF_R_SYM(rel->r_info), 468 (u_long)ELF_R_TYPE(rel->r_info), 469 (void *)rel->r_offset, 470 (void *)load_ptr(where, sizeof(Elf_Sword)), 471 obj->strtab + obj->symtab[ELF_R_SYM(rel->r_info)].st_name)); 472 _rtld_error("%s: Unsupported relocation type %ld " 473 "in non-PLT relocations", 474 obj->path, (u_long) ELF_R_TYPE(rel->r_info)); 475 return -1; 476 } 477 } 478 479 return 0; 480 } 481 482 int 483 _rtld_relocate_plt_lazy(Obj_Entry *obj) 484 { 485 /* PLT fixups were done above in the GOT relocation. */ 486 return 0; 487 } 488 489 static inline int 490 _rtld_relocate_plt_object(const Obj_Entry *obj, Elf_Word sym, Elf_Addr *tp) 491 { 492 Elf_Addr *got = obj->pltgot; 493 const Elf_Sym *def; 494 const Obj_Entry *defobj; 495 Elf_Addr new_value; 496 497 def = _rtld_find_plt_symdef(sym, obj, &defobj, tp != NULL); 498 if (__predict_false(def == NULL)) 499 return -1; 500 if (__predict_false(def == &_rtld_sym_zero)) 501 return 0; 502 503 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 504 if (tp == NULL) 505 return 0; 506 new_value = _rtld_resolve_ifunc(defobj, def); 507 } else { 508 new_value = (Elf_Addr)(defobj->relocbase + def->st_value); 509 } 510 rdbg(("bind now/fixup in %s --> new=%p", 511 defobj->strtab + def->st_name, (void *)new_value)); 512 got[obj->local_gotno + sym - obj->gotsym] = new_value; 513 514 if (tp) 515 *tp = new_value; 516 return 0; 517 } 518 519 caddr_t 520 _rtld_bind(Elf_Word a0, Elf_Addr a1, Elf_Addr a2, Elf_Addr a3) 521 { 522 Elf_Addr *got = (Elf_Addr *)(a2 - 0x7ff0); 523 const Obj_Entry *obj = (Obj_Entry *)(got[1] & GOT1_MASK); 524 Elf_Addr new_value = 0; /* XXX gcc */ 525 int err; 526 527 _rtld_shared_enter(); 528 err = _rtld_relocate_plt_object(obj, a0, &new_value); 529 if (err) 530 _rtld_die(); 531 _rtld_shared_exit(); 532 533 return (caddr_t)new_value; 534 } 535 536 int 537 _rtld_relocate_plt_objects(const Obj_Entry *obj) 538 { 539 const Elf_Sym *sym = obj->symtab + obj->gotsym; 540 Elf_Word i; 541 542 for (i = obj->gotsym; i < obj->symtabno; i++, sym++) { 543 if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) 544 if (_rtld_relocate_plt_object(obj, i, NULL) < 0) 545 return -1; 546 } 547 548 return 0; 549 } 550