1 /* $NetBSD: reloc.c,v 1.51 2002/02/03 23:34:42 thorpej Exp $ */ 2 3 /* 4 * Copyright 1996 John D. Polstra. 5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 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. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by John Polstra. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Dynamic linker for ELF. 36 * 37 * John Polstra <jdp@polstra.com>. 38 */ 39 40 #include <err.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <stdarg.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <sys/types.h> 49 #include <sys/mman.h> 50 #include <dirent.h> 51 52 #include "debug.h" 53 #include "rtld.h" 54 55 #ifndef RTLD_INHIBIT_COPY_RELOCS 56 static int _rtld_do_copy_relocation __P((const Obj_Entry *, const Elf_Rela *, 57 bool)); 58 59 /* 60 * XXX: These don't work for the alpha and i386; don't know about powerpc 61 * The alpha and the i386 avoid the problem by compiling everything PIC. 62 * These relocation are supposed to be writing the address of the 63 * function to be called on the bss.rel or bss.rela segment, but: 64 * - st_size == 0 65 * - on the i386 at least the call instruction is a direct call 66 * not an indirect call. 67 */ 68 static int 69 _rtld_do_copy_relocation(dstobj, rela, dodebug) 70 const Obj_Entry *dstobj; 71 const Elf_Rela *rela; 72 bool dodebug; 73 { 74 void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 75 const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 76 const char *name = dstobj->strtab + dstsym->st_name; 77 unsigned long hash = _rtld_elf_hash(name); 78 size_t size = dstsym->st_size; 79 const void *srcaddr; 80 const Elf_Sym *srcsym = NULL; 81 Obj_Entry *srcobj; 82 83 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) 84 if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, 85 false)) != NULL) 86 break; 87 88 if (srcobj == NULL) { 89 _rtld_error("Undefined symbol \"%s\" referenced from COPY" 90 " relocation in %s", name, dstobj->path); 91 return (-1); 92 } 93 srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value); 94 (void)memcpy(dstaddr, srcaddr, size); 95 rdbg(dodebug, ("COPY %s %s %s --> src=%p dst=%p *dst= %p size %ld", 96 dstobj->path, srcobj->path, name, (void *)srcaddr, 97 (void *)dstaddr, (void *)*(long *)dstaddr, (long)size)); 98 return (0); 99 } 100 #endif /* RTLD_INHIBIT_COPY_RELOCS */ 101 102 103 /* 104 * Process the special R_xxx_COPY relocations in the main program. These 105 * copy data from a shared object into a region in the main program's BSS 106 * segment. 107 * 108 * Returns 0 on success, -1 on failure. 109 */ 110 int 111 _rtld_do_copy_relocations(dstobj, dodebug) 112 const Obj_Entry *dstobj; 113 bool dodebug; 114 { 115 #ifndef RTLD_INHIBIT_COPY_RELOCS 116 117 /* COPY relocations are invalid elsewhere */ 118 assert(dstobj->mainprog); 119 120 if (dstobj->rel != NULL) { 121 const Elf_Rel *rel; 122 for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) { 123 if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) { 124 Elf_Rela ourrela; 125 ourrela.r_info = rel->r_info; 126 ourrela.r_offset = rel->r_offset; 127 ourrela.r_addend = 0; 128 if (_rtld_do_copy_relocation(dstobj, 129 &ourrela, dodebug) < 0) 130 return (-1); 131 } 132 } 133 } 134 if (dstobj->rela != NULL) { 135 const Elf_Rela *rela; 136 for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) { 137 if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) { 138 if (_rtld_do_copy_relocation(dstobj, rela, 139 dodebug) < 0) 140 return (-1); 141 } 142 } 143 } 144 #endif /* RTLD_INHIBIT_COPY_RELOCS */ 145 146 return (0); 147 } 148 149 150 #if !defined(__sparc__) && !defined(__x86_64__) 151 152 int 153 _rtld_relocate_nonplt_object(obj, rela, dodebug) 154 Obj_Entry *obj; 155 const Elf_Rela *rela; 156 bool dodebug; 157 { 158 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 159 const Elf_Sym *def; 160 const Obj_Entry *defobj; 161 #if defined(__alpha__) || defined(__arm__) || defined(__i386__) || \ 162 defined(__m68k__) || defined(__powerpc__) || defined(__sh__) || \ 163 defined(__vax__) 164 Elf_Addr tmp; 165 #endif 166 167 switch (ELF_R_TYPE(rela->r_info)) { 168 169 case R_TYPE(NONE): 170 break; 171 172 #if defined(__i386__) 173 case R_TYPE(GOT32): 174 175 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 176 &defobj, false); 177 if (def == NULL) 178 return -1; 179 180 tmp = (Elf_Addr)(defobj->relocbase + def->st_value); 181 if (*where != tmp) 182 *where = tmp; 183 rdbg(dodebug, ("GOT32 %s in %s --> %p in %s", 184 defobj->strtab + def->st_name, obj->path, 185 (void *)*where, defobj->path)); 186 break; 187 188 case R_TYPE(PC32): 189 /* 190 * I don't think the dynamic linker should ever see this 191 * type of relocation. But the binutils-2.6 tools sometimes 192 * generate it. 193 */ 194 195 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 196 &defobj, false); 197 if (def == NULL) 198 return -1; 199 200 *where += (Elf_Addr)(defobj->relocbase + def->st_value) - 201 (Elf_Addr)where; 202 rdbg(dodebug, ("PC32 %s in %s --> %p in %s", 203 defobj->strtab + def->st_name, obj->path, 204 (void *)*where, defobj->path)); 205 break; 206 207 case R_TYPE(32): 208 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 209 &defobj, false); 210 if (def == NULL) 211 return -1; 212 213 *where += (Elf_Addr)(defobj->relocbase + def->st_value); 214 rdbg(dodebug, ("32 %s in %s --> %p in %s", 215 defobj->strtab + def->st_name, obj->path, 216 (void *)*where, defobj->path)); 217 break; 218 #endif /* __i386__ */ 219 220 #if defined(__m68k__) 221 case R_TYPE(GOT32): 222 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 223 &defobj, false); 224 if (def == NULL) 225 return -1; 226 227 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 228 rela->r_addend); 229 if (*where != tmp) 230 *where = tmp; 231 rdbg(dodebug, ("GOT32 %s in %s --> %p in %s", 232 defobj->strtab + def->st_name, obj->path, 233 (void *)*where, defobj->path)); 234 break; 235 236 case R_TYPE(PC32): 237 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 238 &defobj, false); 239 if (def == NULL) 240 return -1; 241 242 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 243 rela->r_addend) - (Elf_Addr)where; 244 if (*where != tmp) 245 *where = tmp; 246 rdbg(dodebug, ("PC32 %s in %s --> %p in %s", 247 defobj->strtab + def->st_name, obj->path, 248 (void *)*where, defobj->path)); 249 break; 250 251 case R_TYPE(32): 252 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 253 &defobj, false); 254 if (def == NULL) 255 return -1; 256 257 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 258 rela->r_addend); 259 if (*where != tmp) 260 *where = tmp; 261 rdbg(dodebug, ("32 %s in %s --> %p in %s", 262 defobj->strtab + def->st_name, obj->path, 263 (void *)*where, defobj->path)); 264 break; 265 #endif /* __m68k__ */ 266 267 #if defined(__sh__) 268 case R_TYPE(GOT32): 269 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 270 &defobj, false); 271 if (def == NULL) 272 return -1; 273 274 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 275 rela->r_addend); 276 if (*where != tmp) 277 *where = tmp; 278 rdbg(dodebug, ("GOT32 %s in %s --> %p in %s", 279 defobj->strtab + def->st_name, obj->path, 280 (void *)*where, defobj->path)); 281 break; 282 283 case R_TYPE(REL32): 284 /* 285 * I don't think the dynamic linker should ever see this 286 * type of relocation, but some versions of Binutils 287 * generate it. 288 */ 289 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 290 &defobj, false); 291 if (def == NULL) 292 return -1; 293 294 *where += (Elf_Addr)(defobj->relocbase + def->st_value + 295 rela->r_addend) - (Elf_Addr)where; 296 rdbg(dodebug, ("PC32 %s in %s --> %p in %s", 297 defobj->strtab + def->st_name, obj->path, 298 (void *)*where, defobj->path)); 299 break; 300 301 case R_TYPE(DIR32): 302 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 303 &defobj, false); 304 if (def == NULL) 305 return -1; 306 307 *where += (Elf_Addr)(defobj->relocbase + def->st_value + 308 rela->r_addend); 309 rdbg(dodebug, ("32 %s in %s --> %p in %s", 310 defobj->strtab + def->st_name, obj->path, 311 (void *)*where, defobj->path)); 312 break; 313 #endif /* __sh__ */ 314 315 #if defined(__alpha__) 316 case R_TYPE(REFQUAD): 317 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 318 &defobj, false); 319 if (def == NULL) 320 return -1; 321 322 tmp = (Elf_Addr)(defobj->relocbase + def->st_value) + 323 *where + rela->r_addend; 324 if (*where != tmp) 325 *where = tmp; 326 rdbg(dodebug, ("REFQUAD %s in %s --> %p in %s", 327 defobj->strtab + def->st_name, obj->path, 328 (void *)*where, defobj->path)); 329 break; 330 331 case R_TYPE(RELATIVE): 332 { 333 extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; 334 extern Elf_Addr _GOT_END_[]; 335 336 /* This is the ...iffy hueristic. */ 337 if (!dodebug || 338 (caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ || 339 (caddr_t)where >= (caddr_t)_GOT_END_) { 340 *where += (Elf_Addr)obj->relocbase; 341 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path, 342 (void *)*where)); 343 } else 344 rdbg(dodebug, ("RELATIVE in %s stays at %p", 345 obj->path, (void *)*where)); 346 break; 347 } 348 #endif /* __alpha__ */ 349 350 #if defined(__alpha__) || defined(__i386__) || defined(__m68k__) || \ 351 defined(__sh__) 352 case R_TYPE(GLOB_DAT): 353 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 354 &defobj, false); 355 if (def == NULL) 356 return -1; 357 358 tmp = (Elf_Addr)(defobj->relocbase + def->st_value) + 359 rela->r_addend; 360 if (*where != tmp) 361 *where = tmp; 362 rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s", 363 defobj->strtab + def->st_name, obj->path, 364 (void *)*where, defobj->path)); 365 break; 366 #if defined(__sh__) 367 case R_TYPE(RELATIVE): 368 if (rela->r_addend) 369 *where = (Elf_Addr)obj->relocbase + rela->r_addend; 370 else 371 *where += (Elf_Addr)obj->relocbase; 372 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path, 373 (void *)*where)); 374 break; 375 #elif !defined(__alpha__) 376 case R_TYPE(RELATIVE): 377 *where += (Elf_Addr)obj->relocbase; 378 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path, 379 (void *)*where)); 380 break; 381 #endif /* ! __alpha__ */ 382 383 case R_TYPE(COPY): 384 /* 385 * These are deferred until all other relocations have 386 * been done. All we do here is make sure that the COPY 387 * relocation is not in a shared library. They are allowed 388 * only in executable files. 389 */ 390 if (!obj->mainprog) { 391 _rtld_error( 392 "%s: Unexpected R_COPY relocation in shared library", 393 obj->path); 394 return -1; 395 } 396 rdbg(dodebug, ("COPY (avoid in main)")); 397 break; 398 #endif /* __i386__ || __alpha__ || __m68k__ || defined(__sh__) */ 399 400 #if defined(__mips__) 401 case R_TYPE(REL32): 402 /* 32-bit PC-relative reference */ 403 def = obj->symtab + ELF_R_SYM(rela->r_info); 404 405 if (ELFDEFNNAME(ST_BIND)(def->st_info) == STB_LOCAL && 406 (ELFDEFNNAME(ST_TYPE)(def->st_info) == STT_SECTION || 407 ELFDEFNNAME(ST_TYPE)(def->st_info) == STT_NOTYPE)) { 408 /* 409 * XXX: ABI DIFFERENCE! 410 * 411 * Old NetBSD binutils would generate shared libs 412 * with section-relative relocations being already 413 * adjusted for the start address of the section. 414 * 415 * New binutils, OTOH, generate shared libs with 416 * the same relocations being based at zero, so we 417 * need to add in the start address of the section. 418 * 419 * We assume that all section-relative relocs with 420 * contents less than the start of the section need 421 * to be adjusted; this should work with both old 422 * and new shlibs. 423 * 424 * --rkb, Oct 6, 2001 425 */ 426 if (def->st_info == STT_SECTION && 427 (*where < def->st_value)) 428 *where += (Elf_Addr) def->st_value; 429 430 *where += (Elf_Addr)obj->relocbase; 431 432 rdbg(dodebug, ("REL32 %s in %s --> %p in %s", 433 obj->strtab + def->st_name, obj->path, 434 (void *)*where, obj->path)); 435 } else { 436 /* XXX maybe do something re: bootstrapping? */ 437 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, 438 NULL, obj, &defobj, false); 439 if (def == NULL) 440 return -1; 441 *where += (Elf_Addr)(defobj->relocbase + def->st_value); 442 rdbg(dodebug, ("REL32 %s in %s --> %p in %s", 443 defobj->strtab + def->st_name, obj->path, 444 (void *)*where, defobj->path)); 445 } 446 break; 447 448 #endif /* __mips__ */ 449 450 #if defined(__powerpc__) || defined(__vax__) 451 case R_TYPE(32): /* word32 S + A */ 452 case R_TYPE(GLOB_DAT): /* word32 S + A */ 453 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 454 &defobj, false); 455 if (def == NULL) 456 return -1; 457 458 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 459 rela->r_addend); 460 461 if (*where != tmp) 462 *where = tmp; 463 rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s", 464 defobj->strtab + def->st_name, obj->path, 465 (void *)*where, defobj->path)); 466 break; 467 468 case R_TYPE(COPY): 469 rdbg(dodebug, ("COPY")); 470 break; 471 472 case R_TYPE(JMP_SLOT): 473 rdbg(dodebug, ("JMP_SLOT")); 474 break; 475 476 case R_TYPE(RELATIVE): /* word32 B + A */ 477 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); 478 if (*where != tmp) 479 *where = tmp; 480 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path, 481 (void *)*where)); 482 break; 483 #endif /* __powerpc__ || __vax__ */ 484 485 #if defined(__powerpc__) 486 case R_TYPE(16_LO): /* #lo(S + A) */ 487 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); 488 if (*(Elf32_Half *)where != tmp) 489 *(Elf32_Half *)where = tmp; 490 rdbg(dodebug, ("16_LO in %s --> %p", obj->path, 491 (void *)*where)); 492 break; 493 494 case R_TYPE(16_HI): /* #hi(S + A) */ 495 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend) >> 16; 496 if (*(Elf32_Half *)where != tmp) 497 *(Elf32_Half *)where = tmp; 498 rdbg(dodebug, ("16_HI in %s --> %p", obj->path, 499 (void *)*where)); 500 break; 501 502 case R_TYPE(16_HA): /* #ha(S + A) */ 503 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend + 0x8000) 504 >> 16; 505 if (*(Elf32_Half *)where != tmp) 506 *(Elf32_Half *)where = tmp; 507 rdbg(dodebug, ("16_HA in %s --> %p", obj->path, 508 (void *)*where)); 509 break; 510 #endif /* __powerpc__ */ 511 512 #if defined(__arm__) 513 case R_TYPE(GLOB_DAT): /* word32 B + S */ 514 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 515 &defobj, false); 516 if (def == NULL) 517 return -1; 518 *where = (Elf_Addr)(defobj->relocbase + def->st_value); 519 rdbg(dodebug, ("GLOB_DAT %s in %s --> %p @ %p in %s", 520 defobj->strtab + def->st_name, obj->path, 521 (void *)*where, where, defobj->path)); 522 break; 523 524 case R_TYPE(COPY): 525 rdbg(dodebug, ("COPY")); 526 break; 527 528 case R_TYPE(JUMP_SLOT): 529 rdbg(dodebug, ("JUMP_SLOT")); 530 break; 531 532 case R_TYPE(ABS32): /* word32 B + S + A */ 533 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 534 &defobj, false); 535 if (def == NULL) 536 return -1; 537 *where += (Elf_Addr)defobj->relocbase + def->st_value; 538 rdbg(dodebug, ("ABS32 %s in %s --> %p @ %p in %s", 539 defobj->strtab + def->st_name, obj->path, 540 (void *)*where, where, defobj->path)); 541 break; 542 543 case R_TYPE(RELATIVE): /* word32 B + A */ 544 *where += (Elf_Addr)obj->relocbase; 545 rdbg(dodebug, ("RELATIVE in %s --> %p @ %p", obj->path, 546 (void *)*where, where)); 547 break; 548 549 case R_TYPE(PC24): { /* word32 S - P + A */ 550 Elf32_Sword addend; 551 552 /* 553 * Extract addend and sign-extend if needed. 554 */ 555 addend = *where; 556 if (addend & 0x00800000) 557 addend |= 0xff000000; 558 559 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 560 &defobj, false); 561 if (def == NULL) 562 return -1; 563 tmp = (Elf_Addr)obj->relocbase + def->st_value 564 - (Elf_Addr)where + (addend << 2); 565 if ((tmp & 0xfe000000) != 0xfe000000 && 566 (tmp & 0xfe000000) != 0) { 567 _rtld_error( 568 "%s: R_ARM_PC24 relocation @ %p to %s failed " 569 "(displacement %ld (%#lx) out of range)", 570 obj->path, where, defobj->strtab + def->st_name, 571 (long) tmp, (long) tmp); 572 return -1; 573 } 574 tmp >>= 2; 575 *where = (*where & 0xff000000) | (tmp & 0x00ffffff); 576 rdbg(dodebug, ("PC24 %s in %s --> %p @ %p in %s", 577 defobj->strtab + def->st_name, obj->path, 578 (void *)*where, where, defobj->path)); 579 break; 580 } 581 #endif 582 583 default: 584 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 585 &defobj, true); 586 rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, " 587 "addend = %p, contents = %p, symbol = %s", 588 (u_long)ELF_R_SYM(rela->r_info), 589 (u_long)ELF_R_TYPE(rela->r_info), 590 (void *)rela->r_offset, (void *)rela->r_addend, 591 (void *)*where, 592 def ? defobj->strtab + def->st_name : "??")); 593 _rtld_error("%s: Unsupported relocation type %ld " 594 "in non-PLT relocations\n", 595 obj->path, (u_long) ELF_R_TYPE(rela->r_info)); 596 return -1; 597 } 598 return 0; 599 } 600 601 602 #if !defined(__powerpc__) 603 604 int 605 _rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug) 606 Obj_Entry *obj; 607 const Elf_Rela *rela; 608 caddr_t *addrp; 609 bool bind_now; 610 bool dodebug; 611 { 612 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 613 Elf_Addr new_value; 614 615 /* Fully resolve procedure addresses now */ 616 617 #if defined(__alpha__) || defined(__arm__) || defined(__i386__) || \ 618 defined(__m68k__) || defined(__sh__) || defined(__vax__) 619 if (bind_now || obj->pltgot == NULL) { 620 const Elf_Sym *def; 621 const Obj_Entry *defobj; 622 623 #if !defined(__arm__) 624 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); 625 #else 626 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)); 627 #endif 628 629 def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, 630 &defobj, true); 631 if (def == NULL) 632 return -1; 633 634 new_value = (Elf_Addr)(defobj->relocbase + def->st_value); 635 #if defined(__sh__) || defined(__vax__) 636 new_value += rela->r_addend; 637 #endif 638 rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p", 639 (int)bind_now, 640 defobj->strtab + def->st_name, 641 (void *)*where, (void *)new_value)); 642 } else 643 #endif /* __alpha__ || __i386__ || __m68k__ || __sh__ || __vax__ */ 644 if (!obj->mainprog) { 645 /* Just relocate the GOT slots pointing into the PLT */ 646 new_value = *where + (Elf_Addr)(obj->relocbase); 647 rdbg(dodebug, ("fixup !main in %s --> %p", obj->path, 648 (void *)*where)); 649 } else { 650 return 0; 651 } 652 /* 653 * Since this page is probably copy-on-write, let's not write 654 * it unless we really really have to. 655 */ 656 if (*where != new_value) 657 *where = new_value; 658 if (addrp != NULL) { 659 *addrp = *(caddr_t *)(obj->relocbase + rela->r_offset); 660 #if defined(__vax__) 661 *addrp -= rela->r_addend; 662 #endif 663 } 664 return 0; 665 } 666 667 #endif /* __powerpc__ */ 668 669 #endif /* __sparc__ || __x86_64__ */ 670 671 caddr_t 672 _rtld_bind(obj, reloff) 673 Obj_Entry *obj; 674 Elf_Word reloff; 675 { 676 const Elf_Rela *rela; 677 Elf_Rela ourrela; 678 caddr_t addr; 679 680 if (obj->pltrel != NULL) { 681 const Elf_Rel *rel; 682 683 rel = (const Elf_Rel *)((caddr_t) obj->pltrel + reloff); 684 ourrela.r_info = rel->r_info; 685 ourrela.r_offset = rel->r_offset; 686 ourrela.r_addend = 0; 687 rela = &ourrela; 688 } else { 689 rela = (const Elf_Rela *)((caddr_t) obj->pltrela + reloff); 690 #ifdef __sparc64__ 691 if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) { 692 /* 693 * XXXX 694 * 695 * The first four PLT entries are reserved. There 696 * is some disagreement whether they should have 697 * associated relocation entries. Both the SPARC 698 * 32-bit and 64-bit ELF specifications say that 699 * they should have relocation entries, but the 700 * 32-bit SPARC binutils do not generate them, 701 * and now the 64-bit SPARC binutils have stopped 702 * generating them too. 703 * 704 * So, to provide binary compatibility, we will 705 * check the first entry, if it is reserved it 706 * should not be of the type JMP_SLOT. If it 707 * is JMP_SLOT, then the 4 reserved entries were 708 * not generated and our index is 4 entries too far. 709 */ 710 rela -= 4; 711 } 712 #endif 713 } 714 715 if (_rtld_relocate_plt_object(obj, rela, &addr, true, true) < 0) 716 _rtld_die(); 717 718 return addr; 719 } 720 721 /* 722 * Relocate newly-loaded shared objects. The argument is a pointer to 723 * the Obj_Entry for the first such object. All objects from the first 724 * to the end of the list of objects are relocated. Returns 0 on success, 725 * or -1 on failure. 726 */ 727 int 728 _rtld_relocate_objects(first, bind_now, dodebug) 729 Obj_Entry *first; 730 bool bind_now; 731 bool dodebug; 732 { 733 Obj_Entry *obj; 734 int ok = 1; 735 736 for (obj = first; obj != NULL; obj = obj->next) { 737 if (obj->nbuckets == 0 || obj->nchains == 0 || 738 obj->buckets == NULL || obj->symtab == NULL || 739 obj->strtab == NULL) { 740 _rtld_error("%s: Shared object has no run-time" 741 " symbol table", obj->path); 742 return -1; 743 } 744 rdbg(dodebug, (" relocating %s (%ld/%ld rel/rela, " 745 "%ld/%ld plt rel/rela)", 746 obj->path, 747 (long)(obj->rellim - obj->rel), 748 (long)(obj->relalim - obj->rela), 749 (long)(obj->pltrellim - obj->pltrel), 750 (long)(obj->pltrelalim - obj->pltrela))); 751 752 if (obj->textrel) { 753 /* 754 * There are relocations to the write-protected text 755 * segment. 756 */ 757 if (mprotect(obj->mapbase, obj->textsize, 758 PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { 759 _rtld_error("%s: Cannot write-enable text " 760 "segment: %s", obj->path, xstrerror(errno)); 761 return -1; 762 } 763 } 764 if (obj->rel != NULL) { 765 /* Process the non-PLT relocations. */ 766 const Elf_Rel *rel; 767 for (rel = obj->rel; rel < obj->rellim; ++rel) { 768 Elf_Rela ourrela; 769 ourrela.r_info = rel->r_info; 770 ourrela.r_offset = rel->r_offset; 771 #if defined(__mips__) 772 /* rel->r_offset is not valid on mips? */ 773 if (ELF_R_TYPE(ourrela.r_info) == R_TYPE(NONE)) 774 ourrela.r_addend = 0; 775 else 776 #endif 777 ourrela.r_addend = 778 *(Elf_Word *)(obj->relocbase + 779 rel->r_offset); 780 781 if (_rtld_relocate_nonplt_object(obj, &ourrela, 782 dodebug) < 0) 783 ok = 0; 784 } 785 } 786 if (obj->rela != NULL) { 787 /* Process the non-PLT relocations. */ 788 const Elf_Rela *rela; 789 for (rela = obj->rela; rela < obj->relalim; ++rela) { 790 if (_rtld_relocate_nonplt_object(obj, rela, 791 dodebug) < 0) 792 ok = 0; 793 } 794 } 795 if (obj->textrel) { /* Re-protected the text segment. */ 796 if (mprotect(obj->mapbase, obj->textsize, 797 PROT_READ | PROT_EXEC) == -1) { 798 _rtld_error("%s: Cannot write-protect text " 799 "segment: %s", obj->path, xstrerror(errno)); 800 return -1; 801 } 802 } 803 /* Process the PLT relocations. */ 804 if (obj->pltrel != NULL) { 805 const Elf_Rel *rel; 806 for (rel = obj->pltrel; rel < obj->pltrellim; ++rel) { 807 Elf_Rela ourrela; 808 ourrela.r_info = rel->r_info; 809 ourrela.r_offset = rel->r_offset; 810 ourrela.r_addend = 811 *(Elf_Word *)(obj->relocbase + 812 rel->r_offset); 813 if (_rtld_relocate_plt_object(obj, &ourrela, 814 NULL, bind_now, dodebug) < 0) 815 ok = 0; 816 } 817 } 818 if (obj->pltrela != NULL) { 819 const Elf_Rela *rela; 820 for (rela = obj->pltrela; rela < obj->pltrelalim; 821 ++rela) { 822 #ifdef __sparc64__ 823 if (ELF_R_TYPE(rela->r_info) != 824 R_TYPE(JMP_SLOT)) { 825 /* 826 * XXXX 827 * 828 * The first four PLT entries are 829 * reserved. There is some 830 * disagreement whether they should 831 * have associated relocation 832 * entries. Both the SPARC 32-bit 833 * and 64-bit ELF specifications say 834 * that they should have relocation 835 * entries, but the 32-bit SPARC 836 * binutils do not generate them, 837 * and now the 64-bit SPARC binutils 838 * have stopped generating them too. 839 * 840 * To provide binary compatibility, we 841 * will skip any entries that are not 842 * of type JMP_SLOT. 843 */ 844 continue; 845 } 846 #endif 847 if (_rtld_relocate_plt_object(obj, rela, 848 NULL, bind_now, dodebug) < 0) 849 ok = 0; 850 } 851 } 852 if (!ok) 853 return -1; 854 855 856 /* Set some sanity-checking numbers in the Obj_Entry. */ 857 obj->magic = RTLD_MAGIC; 858 obj->version = RTLD_VERSION; 859 860 /* Fill in the dynamic linker entry points. */ 861 obj->dlopen = _rtld_dlopen; 862 obj->dlsym = _rtld_dlsym; 863 obj->dlerror = _rtld_dlerror; 864 obj->dlclose = _rtld_dlclose; 865 obj->dladdr = _rtld_dladdr; 866 867 /* Set the special PLTGOT entries. */ 868 if (obj->pltgot != NULL) { 869 #if defined(__arm__) || defined(__i386__) || defined(__m68k__) || \ 870 defined(__sh__) || defined(__x86_64__) 871 obj->pltgot[1] = (Elf_Addr) obj; 872 obj->pltgot[2] = (Elf_Addr) & _rtld_bind_start; 873 #endif 874 #if defined(__alpha__) 875 _rtld_setup_alpha_pltgot(obj, dodebug); 876 #endif 877 #if defined(__mips__) 878 _rtld_relocate_mips_got(obj); 879 880 obj->pltgot[0] = (Elf_Addr) & _rtld_bind_start; 881 /* XXX only if obj->pltgot[1] & 0x80000000 ?? */ 882 obj->pltgot[1] |= (Elf_Addr) obj; 883 #endif 884 #if defined(__powerpc__) 885 _rtld_setup_powerpc_plt(obj); 886 #endif 887 #if defined(__sparc__) 888 #if defined(__arch64__) || defined(__sparc_v9__) 889 /* 890 * On sparc64 we got troubles. 891 * 892 * Instructions are 4 bytes long. 893 * Elf[64]_Addr is 8 bytes long, so are our pltglot[] 894 * array entries. 895 * Each PLT entry jumps to PLT0 to enter the dynamic 896 * linker. 897 * Loading an arbitrary 64-bit pointer takes 6 898 * instructions and 2 registers. 899 * 900 * Somehow we need to issue a save to get a new stack 901 * frame, load the address of the dynamic linker, and 902 * jump there, in 8 instructions or less. 903 * 904 * Oh, we need to fill out both PLT0 and PLT1. 905 */ 906 { 907 Elf_Word *entry = (Elf_Word *)obj->pltgot; 908 extern void _rtld_install_plt __P((Elf_Word *, 909 Elf_Addr)); 910 extern void _rtld_bind_start_0 __P((long, 911 long)); 912 extern void _rtld_bind_start_1 __P((long, 913 long)); 914 915 /* Install in entries 0 and 1 */ 916 _rtld_install_plt(&entry[0], 917 (Elf_Addr)&_rtld_bind_start_0); 918 _rtld_install_plt(&entry[8], 919 (Elf_Addr)&_rtld_bind_start_1); 920 921 /* 922 * Install the object reference in first slot 923 * of entry 2. 924 */ 925 obj->pltgot[8] = (Elf_Addr) obj; 926 } 927 #else 928 /* 929 * PLTGOT is the PLT on the sparc. 930 * The first entry holds the call the dynamic linker. 931 * We construct a `call' sequence that transfers 932 * to `_rtld_bind_start()'. 933 * The second entry holds the object identification. 934 * Note: each PLT entry is three words long. 935 */ 936 #define SAVE 0x9de3bfc0 /* i.e. `save %sp,-64,%sp' */ 937 #define CALL 0x40000000 938 #define NOP 0x01000000 939 obj->pltgot[0] = SAVE; 940 obj->pltgot[1] = CALL | 941 ((Elf_Addr)&_rtld_bind_start - 942 (Elf_Addr)&obj->pltgot[1]) >> 2; 943 obj->pltgot[2] = NOP; 944 945 obj->pltgot[3] = (Elf_Addr) obj; 946 #endif /* __arch64__ */ 947 #endif /* __sparc__ */ 948 #if defined(__vax__) 949 obj->pltgot[1] = (Elf_Addr) obj; 950 obj->pltgot[2] = (Elf_Addr) & _rtld_bind_start; 951 #endif 952 } 953 } 954 955 return 0; 956 } 957