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 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <string.h> 29 #include <stdio.h> 30 #include <strings.h> 31 #include <sys/elf_amd64.h> 32 #include <debug.h> 33 #include <reloc.h> 34 #include <msg.h> 35 #include <_libld.h> 36 37 Word 38 init_rel(Rel_desc *reld, void *reloc) 39 { 40 Rela * rel = (Rela *)reloc; 41 42 /* LINTED */ 43 reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info); 44 reld->rel_roffset = rel->r_offset; 45 reld->rel_raddend = rel->r_addend; 46 reld->rel_typedata = 0; 47 48 reld->rel_flags |= FLG_REL_RELA; 49 50 return ((Word)ELF_R_SYM(rel->r_info)); 51 } 52 53 void 54 mach_eflags(Ehdr *ehdr, Ofl_desc *ofl) 55 { 56 ofl->ofl_e_flags |= ehdr->e_flags; 57 } 58 59 void 60 mach_make_dynamic(Ofl_desc *ofl, size_t *cnt) 61 { 62 if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) { 63 /* 64 * Create this entry if we are going to create a PLT table. 65 */ 66 if (ofl->ofl_pltcnt) 67 (*cnt)++; /* DT_PLTGOT */ 68 } 69 } 70 71 void 72 mach_update_odynamic(Ofl_desc * ofl, Dyn ** dyn) 73 { 74 if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) { 75 if (ofl->ofl_pltcnt) { 76 (*dyn)->d_tag = DT_PLTGOT; 77 (*dyn)->d_un.d_ptr = fillin_gotplt2(ofl); 78 (*dyn)++; 79 } 80 } 81 } 82 83 Xword 84 calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl) 85 { 86 Xword value; 87 88 value = (Xword)(ofl->ofl_osplt->os_shdr->sh_addr) + 89 M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) * M_PLT_ENTSIZE); 90 return (value); 91 } 92 93 /* 94 * Build a single plt entry - code is: 95 * JMP *name1@GOTPCREL(%rip) 96 * PUSHL $index 97 * JMP .PLT0 98 */ 99 static unsigned char pltn_entry[M_PLT_ENTSIZE] = { 100 /* 0x00 jmpq *name1@GOTPCREL(%rip) */ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 101 /* 0x06 pushq $index */ 0x68, 0x00, 0x00, 0x00, 0x00, 102 /* 0x0b jmpq .plt0(%rip) */ 0xe9, 0x00, 0x00, 0x00, 0x00 103 /* 0x10 */ 104 }; 105 106 static uintptr_t 107 plt_entry(Ofl_desc * ofl, Sym_desc * sdp) 108 { 109 unsigned char *plt0; 110 unsigned char *pltent, *gotent; 111 Sword plt_off; 112 Word got_off; 113 Xword val1; 114 Word flags = ofl->ofl_flags; 115 Word dtflags1 = ofl->ofl_dtflags_1; 116 117 got_off = sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE; 118 plt_off = M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) * 119 M_PLT_ENTSIZE); 120 plt0 = (unsigned char *)(ofl->ofl_osplt->os_outdata->d_buf); 121 pltent = plt0 + plt_off; 122 gotent = (unsigned char *)(ofl->ofl_osgot->os_outdata->d_buf) + got_off; 123 124 bcopy(pltn_entry, pltent, sizeof (pltn_entry)); 125 /* 126 * Fill in the got entry with the address of the next instruction. 127 */ 128 /* LINTED */ 129 *(Word *)gotent = ((uintptr_t)ofl->ofl_osplt->os_shdr->sh_addr + 130 (uintptr_t)plt_off + M_PLT_INSSIZE); 131 132 /* 133 * patchup: 134 * jmpq *name1@gotpcrel(%rip) 135 * 136 * NOTE: 0x06 represents next instruction. 137 */ 138 val1 = (ofl->ofl_osgot->os_shdr->sh_addr + got_off) - 139 (ofl->ofl_osplt->os_shdr->sh_addr + plt_off) - 0x06; 140 141 /* 142 * If '-z noreloc' is specified - skip the do_reloc 143 * stage. 144 */ 145 if ((flags & FLG_OF_RELOBJ) || 146 !(dtflags1 & DF_1_NORELOC)) { 147 if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x02], 148 &val1, MSG_ORIG(MSG_SYM_PLTENT), 149 MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) { 150 eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL), 151 sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name)); 152 return (S_ERROR); 153 } 154 } 155 156 /* 157 * patchup: 158 * pushq $pltndx 159 */ 160 val1 = (Xword)(sdp->sd_aux->sa_PLTndx - 1); 161 /* 162 * If '-z noreloc' is specified - skip the do_reloc 163 * stage. 164 */ 165 if ((flags & FLG_OF_RELOBJ) || 166 !(dtflags1 & DF_1_NORELOC)) { 167 if (do_reloc(R_AMD64_32, &pltent[0x07], 168 &val1, MSG_ORIG(MSG_SYM_PLTENT), 169 MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) { 170 eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL), 171 sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name)); 172 return (S_ERROR); 173 } 174 } 175 176 /* 177 * patchup: 178 * jmpq .plt0(%rip) 179 * NOTE: 0x10 represents next instruction 180 */ 181 val1 = (Xword)((Xword)plt0 - (uintptr_t)(&pltent[0x10])); 182 /* 183 * If '-z noreloc' is specified - skip the do_reloc 184 * stage. 185 */ 186 if ((flags & FLG_OF_RELOBJ) || 187 !(dtflags1 & DF_1_NORELOC)) { 188 if (do_reloc(R_AMD64_PC32, &pltent[0x0c], 189 &val1, MSG_ORIG(MSG_SYM_PLTENT), 190 MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) { 191 eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL), 192 sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name)); 193 return (S_ERROR); 194 } 195 } 196 return (1); 197 } 198 199 uintptr_t 200 perform_outreloc(Rel_desc * orsp, Ofl_desc * ofl) 201 { 202 Os_desc * relosp, * osp = 0; 203 Word ndx; 204 Xword roffset, value; 205 Sxword raddend; 206 Rela rea; 207 char *relbits; 208 Sym_desc * sdp, * psym = (Sym_desc *)0; 209 int sectmoved = 0; 210 211 raddend = orsp->rel_raddend; 212 sdp = orsp->rel_sym; 213 214 /* 215 * If the section this relocation is against has been discarded 216 * (-zignore), then also discard (skip) the relocation itself. 217 */ 218 if (orsp->rel_isdesc && ((orsp->rel_flags & 219 (FLG_REL_GOT | FLG_REL_BSS | FLG_REL_PLT | FLG_REL_NOINFO)) == 0) && 220 (orsp->rel_isdesc->is_flags & FLG_IS_DISCARD)) { 221 DBG_CALL(Dbg_reloc_discard(M_MACH, orsp)); 222 return (1); 223 } 224 225 /* 226 * If this is a relocation against a move table, or expanded move 227 * table, adjust the relocation entries. 228 */ 229 if (orsp->rel_move) 230 adj_movereloc(ofl, orsp); 231 232 /* 233 * If this is a relocation against a section then we need to adjust the 234 * raddend field to compensate for the new position of the input section 235 * within the new output section. 236 */ 237 if (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) { 238 if (ofl->ofl_parsym.head && 239 (sdp->sd_isc->is_flags & FLG_IS_RELUPD) && 240 /* LINTED */ 241 (psym = am_I_partial(orsp, orsp->rel_raddend))) { 242 DBG_CALL(Dbg_move_outsctadj(psym)); 243 sectmoved = 1; 244 if (ofl->ofl_flags & FLG_OF_RELOBJ) 245 raddend = psym->sd_sym->st_value; 246 else 247 raddend = psym->sd_sym->st_value - 248 psym->sd_isc->is_osdesc->os_shdr->sh_addr; 249 /* LINTED */ 250 raddend += (Off)_elf_getxoff(psym->sd_isc->is_indata); 251 if (psym->sd_isc->is_shdr->sh_flags & SHF_ALLOC) 252 raddend += 253 psym->sd_isc->is_osdesc->os_shdr->sh_addr; 254 } else { 255 /* LINTED */ 256 raddend += (Off)_elf_getxoff(sdp->sd_isc->is_indata); 257 if (sdp->sd_isc->is_shdr->sh_flags & SHF_ALLOC) 258 raddend += 259 sdp->sd_isc->is_osdesc->os_shdr->sh_addr; 260 } 261 } 262 263 value = sdp->sd_sym->st_value; 264 265 if (orsp->rel_flags & FLG_REL_GOT) { 266 /* 267 * Note: for GOT relative relocations on amd64 268 * we discard the addend. It was relevant 269 * to the reference - not to the data item 270 * being referenced (ie: that -4 thing). 271 */ 272 raddend = 0; 273 osp = ofl->ofl_osgot; 274 roffset = calc_got_offset(orsp, ofl); 275 } else if (orsp->rel_flags & FLG_REL_PLT) { 276 /* 277 * Note that relocations for PLT's actually 278 * cause a relocation againt the GOT. 279 */ 280 osp = ofl->ofl_osplt; 281 roffset = (ofl->ofl_osgot->os_shdr->sh_addr) + 282 sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE; 283 raddend = 0; 284 if (plt_entry(ofl, sdp) == S_ERROR) 285 return (S_ERROR); 286 287 } else if (orsp->rel_flags & FLG_REL_BSS) { 288 /* 289 * This must be a R_AMD64_COPY. For these set the roffset to 290 * point to the new symbols location. 291 */ 292 osp = ofl->ofl_isbss->is_osdesc; 293 roffset = value; 294 295 /* 296 * The raddend doesn't mean anything in a R_SPARC_COPY 297 * relocation. Null it out because it can confuse people. 298 */ 299 raddend = 0; 300 } else { 301 osp = orsp->rel_osdesc; 302 303 /* 304 * Calculate virtual offset of reference point; equals offset 305 * into section + vaddr of section for loadable sections, or 306 * offset plus section displacement for nonloadable sections. 307 */ 308 roffset = orsp->rel_roffset + 309 (Off)_elf_getxoff(orsp->rel_isdesc->is_indata); 310 if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) 311 roffset += orsp->rel_isdesc->is_osdesc-> 312 os_shdr->sh_addr; 313 } 314 315 if ((osp == 0) || ((relosp = osp->os_relosdesc) == 0)) 316 relosp = ofl->ofl_osrel; 317 318 /* 319 * Assign the symbols index for the output relocation. If the 320 * relocation refers to a SECTION symbol then it's index is based upon 321 * the output sections symbols index. Otherwise the index can be 322 * derived from the symbols index itself. 323 */ 324 if (orsp->rel_rtype == R_AMD64_RELATIVE) 325 ndx = STN_UNDEF; 326 else if ((orsp->rel_flags & FLG_REL_SCNNDX) || 327 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) { 328 if (sectmoved == 0) { 329 /* 330 * Check for a null input section. This can 331 * occur if this relocation references a symbol 332 * generated by sym_add_sym(). 333 */ 334 if ((sdp->sd_isc != 0) && 335 (sdp->sd_isc->is_osdesc != 0)) 336 ndx = sdp->sd_isc->is_osdesc->os_scnsymndx; 337 else 338 ndx = sdp->sd_shndx; 339 } else 340 ndx = ofl->ofl_sunwdata1ndx; 341 } else 342 ndx = sdp->sd_symndx; 343 344 /* 345 * Add the symbols 'value' to the addend field. 346 */ 347 if (orsp->rel_flags & FLG_REL_ADVAL) 348 raddend += value; 349 350 /* 351 * addend field for R_AMD64_DTPMOD64 means nothing. The addend 352 * is propogated in the corresponding R_AMD64_DTPOFF64 353 * relocation. 354 */ 355 if (orsp->rel_rtype == R_AMD64_DTPMOD64) 356 raddend = 0; 357 358 relbits = (char *)relosp->os_outdata->d_buf; 359 360 rea.r_info = ELF_R_INFO(ndx, orsp->rel_rtype); 361 rea.r_offset = roffset; 362 rea.r_addend = raddend; 363 DBG_CALL(Dbg_reloc_out(M_MACH, SHT_RELA, &rea, orsp->rel_sname, 364 relosp->os_name)); 365 366 /* 367 * Assert we haven't walked off the end of our relocation table. 368 */ 369 assert(relosp->os_szoutrels <= relosp->os_shdr->sh_size); 370 371 (void) memcpy((relbits + relosp->os_szoutrels), 372 (char *)&rea, sizeof (Rela)); 373 relosp->os_szoutrels += (Xword)sizeof (Rela); 374 375 /* 376 * Determine if this relocation is against a non-writable, allocatable 377 * section. If so we may need to provide a text relocation diagnostic. 378 * Note that relocations against the .plt (R_AMD64_JUMP_SLOT) actually 379 * result in modifications to the .got. 380 */ 381 if (orsp->rel_rtype == R_AMD64_JUMP_SLOT) 382 osp = ofl->ofl_osgot; 383 384 reloc_remain_entry(orsp, osp, ofl); 385 return (1); 386 } 387 388 /* 389 * amd64 Instructions for TLS processing 390 */ 391 static unsigned char tlsinstr_gd_ie[] = { 392 /* 393 * 0x00 movq %fs:0, %rax 394 */ 395 0x64, 0x48, 0x8b, 0x04, 0x25, 396 0x00, 0x00, 0x00, 0x00, 397 /* 398 * 0x09 addq x@gottpoff(%rip), %rax 399 */ 400 0x48, 0x03, 0x05, 0x00, 0x00, 401 0x00, 0x00 402 }; 403 404 static unsigned char tlsinstr_gd_le[] = { 405 /* 406 * 0x00 movq %fs:0, %rax 407 */ 408 0x64, 0x48, 0x8b, 0x04, 0x25, 409 0x00, 0x00, 0x00, 0x00, 410 /* 411 * 0x09 leaq x@gottpoff(%rip), %rax 412 */ 413 0x48, 0x8d, 0x80, 0x00, 0x00, 414 0x00, 0x00 415 }; 416 417 static unsigned char tlsinstr_ld_le[] = { 418 /* 419 * .byte 0x66 420 */ 421 0x66, 422 /* 423 * .byte 0x66 424 */ 425 0x66, 426 /* 427 * .byte 0x66 428 */ 429 0x66, 430 /* 431 * movq %fs:0, %rax 432 */ 433 0x64, 0x48, 0x8b, 0x04, 0x25, 434 0x00, 0x00, 0x00, 0x00 435 }; 436 437 438 Fixupret 439 tls_fixups(Rel_desc *arsp) 440 { 441 Sym_desc *sdp = arsp->rel_sym; 442 Word rtype = arsp->rel_rtype; 443 unsigned char *offset; 444 445 offset = (unsigned char *)(arsp->rel_roffset + 446 _elf_getxoff(arsp->rel_isdesc->is_indata) + 447 (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf); 448 449 450 if (sdp->sd_ref == REF_DYN_NEED) { 451 /* 452 * IE reference model 453 */ 454 switch (rtype) { 455 case R_AMD64_TLSGD: 456 /* 457 * GD -> IE 458 * 459 * Transition: 460 * 0x00 .byte 0x66 461 * 0x01 leaq x@tlsgd(%rip), %rdi 462 * 0x08 .word 0x6666 463 * 0x0a rex64 464 * 0x0b call __tls_get_addr@plt 465 * 0x10 466 * To: 467 * 0x00 movq %fs:0, %rax 468 * 0x09 addq x@gottpoff(%rip), %rax 469 * 0x10 470 */ 471 DBG_CALL(Dbg_reloc_transition(M_MACH, 472 rtype, 473 R_AMD64_GOTTPOFF, 474 arsp->rel_roffset, 475 sdp->sd_name)); 476 arsp->rel_rtype = R_AMD64_GOTTPOFF; 477 arsp->rel_roffset += 8; 478 arsp->rel_raddend = (Sxword)-4; 479 /* 480 * Addjust 'offset' to beginning of instruction 481 * sequence. 482 */ 483 offset -= 4; 484 (void) memcpy(offset, tlsinstr_gd_ie, 485 sizeof (tlsinstr_gd_ie)); 486 return (FIX_RELOC); 487 case R_AMD64_PLT32: 488 /* 489 * Fixup done via the TLS_GD relocation 490 */ 491 DBG_CALL(Dbg_reloc_transition(M_MACH, 492 rtype, 493 R_AMD64_NONE, 494 arsp->rel_roffset, 495 sdp->sd_name)); 496 return (FIX_DONE); 497 } 498 } 499 500 /* 501 * LE reference model 502 */ 503 switch (rtype) { 504 case R_AMD64_TLSGD: 505 /* 506 * GD -> LE 507 * 508 * Transition: 509 * 0x00 .byte 0x66 510 * 0x01 leaq x@tlsgd(%rip), %rdi 511 * 0x08 .word 0x6666 512 * 0x0a rex64 513 * 0x0b call __tls_get_addr@plt 514 * 0x10 515 * To: 516 * 0x00 movq %fs:0, %rax 517 * 0x09 leaq x@tpoff(%rax), %rax 518 * 0x10 519 */ 520 DBG_CALL(Dbg_reloc_transition(M_MACH, 521 rtype, 522 R_AMD64_TPOFF32, 523 arsp->rel_roffset, 524 sdp->sd_name)); 525 526 arsp->rel_rtype = R_AMD64_TPOFF32; 527 arsp->rel_roffset += 8; 528 arsp->rel_raddend = 0; 529 /* 530 * Addjust 'offset' to beginning of instruction 531 * sequence. 532 */ 533 offset -= 4; 534 (void) memcpy(offset, tlsinstr_gd_le, 535 sizeof (tlsinstr_gd_le)); 536 return (FIX_RELOC); 537 case R_AMD64_GOTTPOFF: 538 /* 539 * IE -> LE 540 * 541 * Transition: 542 * 0x00 movq %fs:0, %rax 543 * 0x09 addq x@gottopoff(%rip), %rax 544 * 0x10 545 * To: 546 * 0x00 movq %fs:0, %rax 547 * 0x09 leaq x@tpoff(%rax), %rax 548 * 0x10 549 */ 550 DBG_CALL(Dbg_reloc_transition(M_MACH, 551 rtype, 552 R_AMD64_TPOFF32, 553 arsp->rel_roffset, 554 sdp->sd_name)); 555 556 arsp->rel_rtype = R_AMD64_TPOFF32; 557 arsp->rel_raddend = 0; 558 /* 559 * Addjust 'offset' to beginning of instruction 560 * sequence. 561 */ 562 offset -= 12; 563 /* 564 * Same code sequence used in the GD -> LE 565 * transition. 566 */ 567 (void) memcpy(offset, tlsinstr_gd_le, 568 sizeof (tlsinstr_gd_le)); 569 return (FIX_RELOC); 570 case R_AMD64_TLSLD: 571 /* 572 * LD -> LE 573 * 574 * Transition 575 * 0x00 leaq x1@tlsgd(%rip), %rdi 576 * 0x07 call __tls_get_addr@plt 577 * 0x0c 578 * To: 579 * 0x00 .byte 0x66 580 * 0x01 .byte 0x66 581 * 0x02 .byte 0x66 582 * 0x03 movq %fs:0, %rax 583 */ 584 DBG_CALL(Dbg_reloc_transition(M_MACH, 585 rtype, 586 R_AMD64_NONE, 587 arsp->rel_roffset, 588 sdp->sd_name)); 589 offset -= 3; 590 (void) memcpy(offset, tlsinstr_ld_le, 591 sizeof (tlsinstr_ld_le)); 592 return (FIX_DONE); 593 case R_AMD64_DTPOFF32: 594 /* 595 * LD->LE 596 * 597 * Transition: 598 * 0x00 leaq x1@dtpoff(%rax), %rcx 599 * To: 600 * 0x00 leaq x1@tpoff(%rax), %rcx 601 */ 602 DBG_CALL(Dbg_reloc_transition(M_MACH, 603 rtype, 604 R_AMD64_TPOFF32, 605 arsp->rel_roffset, 606 sdp->sd_name)); 607 arsp->rel_rtype = R_AMD64_TPOFF32; 608 arsp->rel_raddend = 0; 609 return (FIX_RELOC); 610 } 611 612 return (FIX_RELOC); 613 } 614 615 uintptr_t 616 do_activerelocs(Ofl_desc *ofl) 617 { 618 Rel_desc * arsp; 619 Rel_cache * rcp; 620 Listnode * lnp; 621 uintptr_t return_code = 1; 622 Word flags = ofl->ofl_flags; 623 Word dtflags1 = ofl->ofl_dtflags_1; 624 625 DBG_CALL(Dbg_reloc_doactiverel()); 626 /* 627 * process active relocs 628 */ 629 for (LIST_TRAVERSE(&ofl->ofl_actrels, lnp, rcp)) { 630 /* LINTED */ 631 for (arsp = (Rel_desc *)(rcp + 1); 632 arsp < rcp->rc_free; arsp++) { 633 unsigned char *addr; 634 Xword value; 635 Sym_desc *sdp; 636 const char *ifl_name; 637 Xword refaddr; 638 int moved = 0; 639 Gotref gref; 640 641 /* 642 * If the section this relocation is against has been 643 * discarded (-zignore), then discard (skip) the 644 * relocation itself. 645 */ 646 if ((arsp->rel_isdesc->is_flags & FLG_IS_DISCARD) && 647 ((arsp->rel_flags & 648 (FLG_REL_GOT | FLG_REL_BSS | 649 FLG_REL_PLT | FLG_REL_NOINFO)) == 0)) { 650 DBG_CALL(Dbg_reloc_discard(M_MACH, arsp)); 651 continue; 652 } 653 654 /* 655 * We deteremine what the 'got reference' 656 * model (if required) is at this point. This 657 * needs to be done before tls_fixup() since 658 * it may 'transition' our instructions. 659 * 660 * The got table entries have already been assigned, 661 * and we bind to those initial entries. 662 */ 663 if (arsp->rel_flags & FLG_REL_DTLS) 664 gref = GOT_REF_TLSGD; 665 else if (arsp->rel_flags & FLG_REL_MTLS) 666 gref = GOT_REF_TLSLD; 667 else if (arsp->rel_flags & FLG_REL_STLS) 668 gref = GOT_REF_TLSIE; 669 else 670 gref = GOT_REF_GENERIC; 671 672 /* 673 * Perform any required TLS fixups. 674 */ 675 if (arsp->rel_flags & FLG_REL_TLSFIX) { 676 Fixupret ret; 677 if ((ret = tls_fixups(arsp)) == FIX_ERROR) 678 return (S_ERROR); 679 if (ret == FIX_DONE) 680 continue; 681 } 682 683 /* 684 * If this is a relocation against a move table, or 685 * expanded move table, adjust the relocation entries. 686 */ 687 if (arsp->rel_move) 688 adj_movereloc(ofl, arsp); 689 690 sdp = arsp->rel_sym; 691 refaddr = arsp->rel_roffset + 692 (Off)_elf_getxoff(arsp->rel_isdesc->is_indata); 693 694 if ((arsp->rel_flags & FLG_REL_CLVAL) || 695 (arsp->rel_flags & FLG_REL_GOTCL)) 696 value = 0; 697 else if (ELF_ST_TYPE(sdp->sd_sym->st_info) == 698 STT_SECTION) { 699 Sym_desc * sym; 700 701 /* 702 * The value for a symbol pointing to a SECTION 703 * is based off of that sections position. 704 * 705 * The second argument of the am_I_partial() is 706 * the value stored at the target address 707 * relocation is going to be applied. 708 */ 709 if ((sdp->sd_isc->is_flags & FLG_IS_RELUPD) && 710 /* LINTED */ 711 (sym = am_I_partial(arsp, *(Xword *) 712 ((unsigned char *) 713 (arsp->rel_isdesc->is_indata->d_buf) + 714 arsp->rel_roffset)))) { 715 /* 716 * If the symbol is moved, 717 * adjust the value 718 */ 719 value = sym->sd_sym->st_value; 720 moved = 1; 721 } else { 722 value = (Off)_elf_getxoff(sdp->sd_isc-> 723 is_indata); 724 if (sdp->sd_isc->is_shdr->sh_flags & 725 SHF_ALLOC) 726 value += sdp->sd_isc->is_osdesc-> 727 os_shdr->sh_addr; 728 } 729 if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS) 730 value -= ofl->ofl_tlsphdr->p_vaddr; 731 } else 732 /* 733 * else the value is the symbols value 734 */ 735 value = sdp->sd_sym->st_value; 736 737 /* 738 * Relocation against the GLOBAL_OFFSET_TABLE. 739 */ 740 if (arsp->rel_flags & FLG_REL_GOT) 741 arsp->rel_osdesc = ofl->ofl_osgot; 742 743 /* 744 * If loadable and not producing a relocatable object 745 * add the sections virtual address to the reference 746 * address. 747 */ 748 if ((arsp->rel_flags & FLG_REL_LOAD) && 749 !(ofl->ofl_flags & FLG_OF_RELOBJ)) 750 refaddr += arsp->rel_isdesc->is_osdesc-> 751 os_shdr->sh_addr; 752 753 754 /* 755 * If this entry has a PLT assigned to it, it's 756 * value is actually the address of the PLT (and 757 * not the address of the function). 758 */ 759 if (IS_PLT(arsp->rel_rtype)) { 760 if (sdp->sd_aux && sdp->sd_aux->sa_PLTndx) 761 value = calc_plt_addr(sdp, ofl); 762 } 763 764 /* 765 * Add relocations addend to value. Add extra 766 * relocation addend if needed. 767 * 768 * Note: for GOT relative relocations on amd64 769 * we discard the addend. It was relevant 770 * to the reference - not to the data item 771 * being referenced (ie: that -4 thing). 772 */ 773 if ((arsp->rel_flags & FLG_REL_GOT) == 0) 774 value += arsp->rel_raddend; 775 776 if (arsp->rel_flags & FLG_REL_GOT) { 777 Xword R1addr; 778 uintptr_t R2addr; 779 Word gotndx; 780 Gotndx *gnp; 781 782 /* 783 * Perform relocation against GOT table. Since 784 * this doesn't fit exactly into a relocation 785 * we place the appropriate byte in the GOT 786 * directly 787 * 788 * Calculate offset into GOT at which to apply 789 * the relocation. 790 */ 791 gnp = find_gotndx(&(sdp->sd_GOTndxs), gref, 792 ofl, arsp); 793 assert(gnp); 794 795 if (arsp->rel_rtype == R_AMD64_DTPOFF64) 796 gotndx = gnp->gn_gotndx + 1; 797 else 798 gotndx = gnp->gn_gotndx; 799 800 R1addr = (Xword)(gotndx * M_GOT_ENTSIZE); 801 802 /* 803 * Add the GOTs data's offset. 804 */ 805 R2addr = R1addr + (uintptr_t) 806 arsp->rel_osdesc->os_outdata->d_buf; 807 808 DBG_CALL(Dbg_reloc_doact(M_MACH, 809 arsp->rel_rtype, R1addr, value, 810 arsp->rel_sname, arsp->rel_osdesc)); 811 812 /* 813 * And do it. 814 */ 815 *(Xword *)R2addr = (Xword)value; 816 continue; 817 818 } else if (IS_GOT_BASED(arsp->rel_rtype)) { 819 value -= ofl->ofl_osgot->os_shdr->sh_addr; 820 } else if (IS_GOTPCREL(arsp->rel_rtype)) { 821 Gotndx * gnp; 822 /* 823 * Calculation: 824 * G + GOT + A - P 825 */ 826 gnp = find_gotndx(&(sdp->sd_GOTndxs), 827 gref, ofl, arsp); 828 assert(gnp != 0); 829 value = (Xword)(ofl->ofl_osgot->os_shdr-> 830 sh_addr) + ((Xword)gnp->gn_gotndx * 831 M_GOT_ENTSIZE) + arsp->rel_raddend - 832 refaddr; 833 } else if (IS_GOT_PC(arsp->rel_rtype)) { 834 value = (Xword) (ofl->ofl_osgot->os_shdr-> 835 sh_addr) - refaddr; 836 } else if ((IS_PC_RELATIVE(arsp->rel_rtype)) && 837 (!(ofl->ofl_flags & FLG_OF_RELOBJ) || 838 (arsp->rel_osdesc == sdp->sd_isc->is_osdesc))) { 839 value -= refaddr; 840 } else if (IS_TLS_INS(arsp->rel_rtype) && 841 IS_GOT_RELATIVE(arsp->rel_rtype)) { 842 Gotndx *gnp; 843 844 gnp = find_gotndx(&(sdp->sd_GOTndxs), gref, 845 ofl, arsp); 846 assert(gnp != 0); 847 value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE; 848 } else if (IS_GOT_RELATIVE(arsp->rel_rtype)) { 849 Gotndx * gnp; 850 851 gnp = find_gotndx(&(sdp->sd_GOTndxs), 852 gref, ofl, arsp); 853 assert(gnp); 854 value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE; 855 } else if (arsp->rel_flags & FLG_REL_STLS) { 856 Xword tlsstatsize; 857 /* 858 * This is the LE TLS reference model. Static 859 * offset is hard-coded. 860 */ 861 tlsstatsize = S_ROUND(ofl-> 862 ofl_tlsphdr->p_memsz, 863 M_TLSSTATALIGN); 864 value = tlsstatsize - value; 865 /* 866 * Since this code is fixedup 867 * it assumes a negative offset 868 * that can be added to the thread pointer 869 */ 870 if (arsp->rel_rtype == R_AMD64_TPOFF32) 871 value = -value; 872 } 873 874 if (arsp->rel_isdesc->is_file) 875 ifl_name = arsp->rel_isdesc->is_file->ifl_name; 876 else 877 ifl_name = MSG_INTL(MSG_STR_NULL); 878 879 /* 880 * Make sure we have data to relocate. Compiler and 881 * assembler developers have been known to generate 882 * relocations against invalid sections (normally .bss), 883 * so for their benefit give them sufficient information 884 * to help analyze the problem. End users should never 885 * see this. 886 */ 887 if (arsp->rel_isdesc->is_indata->d_buf == 0) { 888 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_EMPTYSEC), 889 conv_reloc_amd64_type_str(arsp->rel_rtype), 890 ifl_name, demangle(arsp->rel_sname), 891 arsp->rel_isdesc->is_name); 892 return (S_ERROR); 893 } 894 895 /* 896 * Get the address of the data item we need to modify. 897 */ 898 addr = (unsigned char *)_elf_getxoff(arsp->rel_isdesc-> 899 is_indata) + arsp->rel_roffset; 900 901 /* LINTED */ 902 DBG_CALL(Dbg_reloc_doact(M_MACH, arsp->rel_rtype, 903 (Xword)addr, value, arsp->rel_sname, 904 arsp->rel_osdesc)); 905 addr += (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf; 906 907 if ((((uintptr_t)addr - (uintptr_t)ofl->ofl_ehdr) > 908 ofl->ofl_size) || (arsp->rel_roffset > 909 arsp->rel_osdesc->os_shdr->sh_size)) { 910 int class; 911 912 if (((uintptr_t)addr - (Xword)ofl->ofl_ehdr) > 913 ofl->ofl_size) 914 class = ERR_FATAL; 915 else 916 class = ERR_WARNING; 917 918 eprintf(class, MSG_INTL(MSG_REL_INVALOFFSET), 919 conv_reloc_amd64_type_str(arsp->rel_rtype), 920 ifl_name, arsp->rel_isdesc->is_name, 921 demangle(arsp->rel_sname), 922 EC_ADDR((uintptr_t)addr - 923 (uintptr_t)ofl->ofl_ehdr)); 924 925 if (class == ERR_FATAL) { 926 return_code = S_ERROR; 927 continue; 928 } 929 } 930 931 /* 932 * The relocation is additive. Ignore the previous 933 * symbol value if this local partial symbol is 934 * expanded. 935 */ 936 if (moved) 937 value -= *addr; 938 939 /* 940 * If '-z noreloc' is specified - skip the do_reloc 941 * stage. 942 */ 943 if ((flags & FLG_OF_RELOBJ) || 944 !(dtflags1 & DF_1_NORELOC)) { 945 if (do_reloc((unsigned char)arsp->rel_rtype, 946 addr, &value, arsp->rel_sname, 947 ifl_name) == 0) 948 return_code = S_ERROR; 949 } 950 } 951 } 952 return (return_code); 953 } 954 955 uintptr_t 956 add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl) 957 { 958 Rel_desc * orsp; 959 Rel_cache * rcp; 960 Sym_desc * sdp = rsp->rel_sym; 961 962 /* 963 * Static executables *do not* want any relocations against them. 964 * Since our engine still creates relocations against a WEAK UNDEFINED 965 * symbol in a static executable, it's best to disable them here 966 * instead of through out the relocation code. 967 */ 968 if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) == 969 (FLG_OF_STATIC | FLG_OF_EXEC)) 970 return (1); 971 972 /* 973 * If no relocation cache structures are available allocate 974 * a new one and link it into the cache list. 975 */ 976 if ((ofl->ofl_outrels.tail == 0) || 977 ((rcp = (Rel_cache *)ofl->ofl_outrels.tail->data) == 0) || 978 ((orsp = rcp->rc_free) == rcp->rc_end)) { 979 static size_t nextsize = 0; 980 size_t size; 981 982 /* 983 * Output relocation numbers can vary considerably between 984 * building executables or shared objects (pic vs. non-pic), 985 * etc. But, they typically aren't very large, so for these 986 * objects use a standard bucket size. For building relocatable 987 * objects, typically there will be an output relocation for 988 * every input relocation. 989 */ 990 if (nextsize == 0) { 991 if (ofl->ofl_flags & FLG_OF_RELOBJ) { 992 if ((size = ofl->ofl_relocincnt) == 0) 993 size = REL_LOIDESCNO; 994 if (size > REL_HOIDESCNO) 995 nextsize = REL_HOIDESCNO; 996 else 997 nextsize = REL_LOIDESCNO; 998 } else 999 nextsize = size = REL_HOIDESCNO; 1000 } else 1001 size = nextsize; 1002 1003 size = size * sizeof (Rel_desc); 1004 1005 if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) || 1006 (list_appendc(&ofl->ofl_outrels, rcp) == 0)) 1007 return (S_ERROR); 1008 1009 /* LINTED */ 1010 rcp->rc_free = orsp = (Rel_desc *)(rcp + 1); 1011 /* LINTED */ 1012 rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size); 1013 } 1014 1015 /* 1016 * If we are adding a output relocation against a section 1017 * symbol (non-RELATIVE) then mark that section. These sections 1018 * will be added to the .dynsym symbol table. 1019 */ 1020 if (sdp && (rsp->rel_rtype != M_R_RELATIVE) && 1021 ((flags & FLG_REL_SCNNDX) || 1022 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION))) { 1023 1024 /* 1025 * If this is a COMMON symbol - no output section 1026 * exists yet - (it's created as part of sym_validate()). 1027 * So - we mark here that when it's created it should 1028 * be tagged with the FLG_OS_OUTREL flag. 1029 */ 1030 if ((sdp->sd_flags & FLG_SY_SPECSEC) && 1031 (sdp->sd_shndx == SHN_COMMON)) 1032 if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS) 1033 ofl->ofl_flags1 |= FLG_OF1_BSSOREL; 1034 else 1035 ofl->ofl_flags1 |= FLG_OF1_TLSOREL; 1036 else { 1037 Os_desc * osp = sdp->sd_isc->is_osdesc; 1038 1039 if ((osp->os_flags & FLG_OS_OUTREL) == 0) { 1040 ofl->ofl_dynshdrcnt++; 1041 osp->os_flags |= FLG_OS_OUTREL; 1042 } 1043 } 1044 } 1045 1046 *orsp = *rsp; 1047 orsp->rel_flags |= flags; 1048 1049 rcp->rc_free++; 1050 ofl->ofl_outrelscnt++; 1051 1052 if (flags & FLG_REL_GOT) 1053 ofl->ofl_relocgotsz += (Xword)sizeof (Rela); 1054 else if (flags & FLG_REL_PLT) 1055 ofl->ofl_relocpltsz += (Xword)sizeof (Rela); 1056 else if (flags & FLG_REL_BSS) 1057 ofl->ofl_relocbsssz += (Xword)sizeof (Rela); 1058 else if (flags & FLG_REL_NOINFO) 1059 ofl->ofl_relocrelsz += (Xword)sizeof (Rela); 1060 else 1061 orsp->rel_osdesc->os_szoutrels += (Xword)sizeof (Rela); 1062 1063 if (orsp->rel_rtype == M_R_RELATIVE) 1064 ofl->ofl_relocrelcnt++; 1065 1066 /* 1067 * We don't perform sorting on PLT relocations because 1068 * they have already been assigned a PLT index and if we 1069 * were to sort them we would have to re-assign the plt indexes. 1070 */ 1071 if (!(flags & FLG_REL_PLT)) 1072 ofl->ofl_reloccnt++; 1073 1074 /* 1075 * Identify and possibly warn of a displacement relocation. 1076 */ 1077 if (orsp->rel_flags & FLG_REL_DISP) { 1078 ofl->ofl_dtflags_1 |= DF_1_DISPRELPND; 1079 1080 if (ofl->ofl_flags & FLG_OF_VERBOSE) 1081 disp_errmsg(MSG_INTL(MSG_REL_DISPREL4), orsp, ofl); 1082 } 1083 DBG_CALL(Dbg_reloc_ors_entry(M_MACH, orsp)); 1084 return (1); 1085 } 1086 1087 1088 uintptr_t 1089 add_actrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl) 1090 { 1091 Rel_desc * arsp; 1092 Rel_cache * rcp; 1093 1094 /* 1095 * If no relocation cache structures are available allocate a 1096 * new one and link it into the bucket list. 1097 */ 1098 if ((ofl->ofl_actrels.tail == 0) || 1099 ((rcp = (Rel_cache *)ofl->ofl_actrels.tail->data) == 0) || 1100 ((arsp = rcp->rc_free) == rcp->rc_end)) { 1101 static size_t nextsize = 0; 1102 size_t size; 1103 1104 /* 1105 * Typically, when generating an executable or shared object 1106 * there will be a active relocation for every input relocation. 1107 */ 1108 if (nextsize == 0) { 1109 if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) { 1110 if ((size = ofl->ofl_relocincnt) == 0) 1111 size = REL_LAIDESCNO; 1112 if (size > REL_HAIDESCNO) 1113 nextsize = REL_HAIDESCNO; 1114 else 1115 nextsize = REL_LAIDESCNO; 1116 } else 1117 nextsize = size = REL_HAIDESCNO; 1118 } else 1119 size = nextsize; 1120 1121 size = size * sizeof (Rel_desc); 1122 1123 if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) || 1124 (list_appendc(&ofl->ofl_actrels, rcp) == 0)) 1125 return (S_ERROR); 1126 1127 /* LINTED */ 1128 rcp->rc_free = arsp = (Rel_desc *)(rcp + 1); 1129 /* LINTED */ 1130 rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size); 1131 } 1132 1133 *arsp = *rsp; 1134 arsp->rel_flags |= flags; 1135 1136 rcp->rc_free++; 1137 ofl->ofl_actrelscnt++; 1138 1139 /* 1140 * If this is a displacement relocation relocation, warn. 1141 */ 1142 if (arsp->rel_flags & FLG_REL_DISP) { 1143 ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE; 1144 1145 if (ofl->ofl_flags & FLG_OF_VERBOSE) 1146 disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl); 1147 } 1148 DBG_CALL(Dbg_reloc_ars_entry(M_MACH, arsp)); 1149 return (1); 1150 } 1151 1152 1153 /* 1154 * Stub routine since register symbols are not supported on amd64. 1155 */ 1156 /* ARGSUSED */ 1157 uintptr_t 1158 reloc_register(Rel_desc * rsp, Is_desc * isp, Ofl_desc * ofl) 1159 { 1160 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOREG)); 1161 return (S_ERROR); 1162 } 1163 1164 /* 1165 * process relocation for a LOCAL symbol 1166 */ 1167 uintptr_t 1168 reloc_local(Rel_desc * rsp, Ofl_desc * ofl) 1169 { 1170 Word flags = ofl->ofl_flags; 1171 Sym_desc *sdp = rsp->rel_sym; 1172 Word shndx = rsp->rel_sym->sd_shndx; 1173 Word ortype = rsp->rel_rtype; 1174 1175 /* 1176 * if ((shared object) and (not pc relative relocation) and 1177 * (not against ABS symbol)) 1178 * then 1179 * build R_AMD64_RELATIVE 1180 * fi 1181 */ 1182 if ((flags & FLG_OF_SHAROBJ) && (rsp->rel_flags & FLG_REL_LOAD) && 1183 !(IS_PC_RELATIVE(rsp->rel_rtype)) && 1184 !(IS_GOT_BASED(rsp->rel_rtype)) && 1185 !(rsp->rel_isdesc != NULL && 1186 (rsp->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof)) && 1187 (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) || 1188 (shndx != SHN_ABS) || (sdp->sd_aux && sdp->sd_aux->sa_symspec))) { 1189 1190 /* 1191 * R_AMD64_RELATIVE updates a 64bit address, if this 1192 * relocation isn't a 64bit binding then we can not 1193 * simplify it to a RELATIVE relocation. 1194 */ 1195 if (reloc_table[ortype].re_fsize != sizeof (Addr)) { 1196 return (add_outrel(NULL, rsp, ofl)); 1197 } 1198 1199 rsp->rel_rtype = R_AMD64_RELATIVE; 1200 if (add_outrel(FLG_REL_ADVAL, rsp, ofl) == S_ERROR) 1201 return (S_ERROR); 1202 rsp->rel_rtype = ortype; 1203 return (1); 1204 } 1205 1206 if (!(rsp->rel_flags & FLG_REL_LOAD) && 1207 (shndx == SHN_UNDEF)) { 1208 (void) eprintf(ERR_WARNING, MSG_INTL(MSG_REL_EXTERNSYM), 1209 conv_reloc_amd64_type_str(rsp->rel_rtype), 1210 rsp->rel_isdesc->is_file->ifl_name, 1211 demangle(rsp->rel_sname), rsp->rel_osdesc->os_name); 1212 return (1); 1213 } 1214 1215 /* 1216 * Perform relocation. 1217 */ 1218 return (add_actrel(NULL, rsp, ofl)); 1219 } 1220 1221 1222 uintptr_t 1223 /* ARGSUSED */ 1224 reloc_GOTOP(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) 1225 { 1226 /* 1227 * Stub routine for common code compatibility, we shouldn't 1228 * actually get here on amd64. 1229 */ 1230 return (S_ERROR); 1231 } 1232 1233 uintptr_t 1234 reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) 1235 { 1236 Word rtype = rsp->rel_rtype; 1237 Sym_desc *sdp = rsp->rel_sym; 1238 Word flags = ofl->ofl_flags; 1239 Word rflags; 1240 Gotndx *gnp; 1241 1242 /* 1243 * all TLS relocations are illegal in a static executable. 1244 */ 1245 if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) == 1246 (FLG_OF_STATIC | FLG_OF_EXEC)) { 1247 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT), 1248 conv_reloc_386_type_str(rsp->rel_rtype), 1249 rsp->rel_isdesc->is_file->ifl_name, 1250 demangle(rsp->rel_sname)); 1251 return (S_ERROR); 1252 } 1253 1254 /* 1255 * Any TLS relocation must be against a STT_TLS symbol, all others 1256 * are illegal. 1257 */ 1258 if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS) { 1259 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM), 1260 conv_reloc_386_type_str(rsp->rel_rtype), 1261 rsp->rel_isdesc->is_file->ifl_name, 1262 demangle(rsp->rel_sname), 1263 conv_info_type_str(ofl->ofl_e_machine, 1264 ELF_ST_TYPE(sdp->sd_sym->st_info))); 1265 return (S_ERROR); 1266 } 1267 1268 /* 1269 * We're a executable - use either the IE or LE 1270 * access model. 1271 */ 1272 if (flags & FLG_OF_EXEC) { 1273 /* 1274 * If we are using either IE or LE reference 1275 * model set the DF_STATIC_TLS flag. 1276 */ 1277 ofl->ofl_dtflags |= DF_STATIC_TLS; 1278 1279 if (!local) { 1280 Gotref gref; 1281 /* 1282 * IE access model 1283 */ 1284 /* 1285 * It's not possible for LD or LE reference 1286 * models to reference a symbol external to 1287 * the current object. 1288 */ 1289 if (IS_TLS_LD(rtype) || IS_TLS_LE(rtype)) { 1290 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), 1291 conv_reloc_amd64_type_str(rsp->rel_rtype), 1292 rsp->rel_isdesc->is_file->ifl_name, 1293 demangle(rsp->rel_sname), 1294 sdp->sd_file->ifl_name); 1295 return (S_ERROR); 1296 } 1297 1298 gref = GOT_REF_TLSIE; 1299 1300 /* 1301 * Assign a GOT entry for static TLS references 1302 */ 1303 if ((gnp = find_gotndx(&(sdp->sd_GOTndxs), 1304 gref, ofl, rsp)) == 0) { 1305 if (assign_gotndx(&(sdp->sd_GOTndxs), 1306 gnp, gref, ofl, rsp, sdp) == S_ERROR) 1307 return (S_ERROR); 1308 rsp->rel_rtype = R_AMD64_TPOFF64; 1309 if (add_outrel((FLG_REL_GOT | FLG_REL_STLS), 1310 rsp, ofl) == S_ERROR) 1311 return (S_ERROR); 1312 rsp->rel_rtype = rtype; 1313 } 1314 if (IS_TLS_IE(rtype)) 1315 return (add_actrel(FLG_REL_STLS, rsp, ofl)); 1316 1317 /* 1318 * If (GD or LD) reference models - fixups 1319 * are required. 1320 */ 1321 return (add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), 1322 rsp, ofl)); 1323 } 1324 /* 1325 * LE access model 1326 */ 1327 if (IS_TLS_LE(rtype)) 1328 return (add_actrel(FLG_REL_STLS, rsp, ofl)); 1329 return (add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), rsp, ofl)); 1330 } 1331 1332 1333 /* 1334 * Building a shared object 1335 */ 1336 1337 /* 1338 * Building a shared object - only GD & LD access models 1339 * will work here. 1340 */ 1341 if (IS_TLS_IE(rtype) || IS_TLS_LE(rtype)) { 1342 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSIE), 1343 conv_reloc_amd64_type_str(rsp->rel_rtype), 1344 rsp->rel_isdesc->is_file->ifl_name, 1345 demangle(rsp->rel_sname)); 1346 return (S_ERROR); 1347 } 1348 1349 /* 1350 * LD access mode can only bind to local symbols. 1351 */ 1352 if (!local && IS_TLS_LD(rtype)) { 1353 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), 1354 conv_reloc_amd64_type_str(rsp->rel_rtype), 1355 rsp->rel_isdesc->is_file->ifl_name, 1356 demangle(rsp->rel_sname), 1357 sdp->sd_file->ifl_name); 1358 return (S_ERROR); 1359 } 1360 1361 1362 if (IS_TLS_LD(rtype) && ((gnp = find_gotndx(&(sdp->sd_GOTndxs), 1363 GOT_REF_TLSLD, ofl, rsp)) == 0)) { 1364 if (assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSLD, 1365 ofl, rsp, sdp) == S_ERROR) 1366 return (S_ERROR); 1367 rflags = FLG_REL_GOT | FLG_REL_MTLS; 1368 if (local) 1369 rflags |= FLG_REL_SCNNDX; 1370 rsp->rel_rtype = R_AMD64_DTPMOD64; 1371 if (add_outrel(rflags, rsp, ofl) == S_ERROR) 1372 return (S_ERROR); 1373 rsp->rel_rtype = rtype; 1374 } else if (IS_TLS_GD(rtype) && ((gnp = find_gotndx(&(sdp->sd_GOTndxs), 1375 GOT_REF_TLSGD, ofl, rsp)) == 0)) { 1376 if (assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSGD, 1377 ofl, rsp, sdp) == S_ERROR) 1378 return (S_ERROR); 1379 rflags = FLG_REL_GOT | FLG_REL_DTLS; 1380 if (local) 1381 rflags |= FLG_REL_SCNNDX; 1382 rsp->rel_rtype = R_AMD64_DTPMOD64; 1383 if (add_outrel(rflags, rsp, ofl) == S_ERROR) 1384 return (S_ERROR); 1385 if (local == TRUE) { 1386 rsp->rel_rtype = R_AMD64_DTPOFF64; 1387 if (add_actrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, 1388 ofl) == S_ERROR) 1389 return (S_ERROR); 1390 } else { 1391 rsp->rel_rtype = R_AMD64_DTPOFF64; 1392 if (add_outrel((FLG_REL_GOT | FLG_REL_DTLS), rsp, 1393 ofl) == S_ERROR) 1394 return (S_ERROR); 1395 } 1396 rsp->rel_rtype = rtype; 1397 } 1398 1399 if (IS_TLS_LD(rtype)) 1400 return (add_actrel(FLG_REL_MTLS, rsp, ofl)); 1401 1402 return (add_actrel(FLG_REL_DTLS, rsp, ofl)); 1403 } 1404 1405 uintptr_t 1406 reloc_relobj(Boolean local, Rel_desc * rsp, Ofl_desc * ofl) 1407 { 1408 Word rtype = rsp->rel_rtype; 1409 Sym_desc * sdp = rsp->rel_sym; 1410 Is_desc * isp = rsp->rel_isdesc; 1411 Word flags = ofl->ofl_flags; 1412 1413 /* 1414 * Try to determine if we can do any relocations at 1415 * this point. We can if: 1416 * 1417 * (local_symbol) and (non_GOT_relocation) and 1418 * (IS_PC_RELATIVE()) and 1419 * (relocation to symbol in same section) 1420 */ 1421 if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) && 1422 !IS_GOT_PC(rtype) && IS_PC_RELATIVE(rtype) && 1423 ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc))) { 1424 return (add_actrel(NULL, rsp, ofl)); 1425 } 1426 1427 /* 1428 * If '-zredlocsym' is in effect make all local sym relocations 1429 * against the 'section symbols', since they are the only symbols 1430 * which will be added to the .symtab. 1431 */ 1432 if (local && (((ofl->ofl_flags1 & FLG_OF1_REDLSYM) && 1433 (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) || 1434 ((sdp->sd_flags & FLG_SY1_ELIM) && (flags & FLG_OF_PROCRED)))) { 1435 /* 1436 * But if this is a PIC code, don't allow it for now. 1437 */ 1438 if (IS_GOT_RELATIVE(rsp->rel_rtype)) { 1439 eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC), 1440 demangle(rsp->rel_sname), 1441 rsp->rel_isdesc->is_file->ifl_name, 1442 conv_reloc_386_type_str(rsp->rel_rtype)); 1443 return (S_ERROR); 1444 } 1445 return (add_actrel(FLG_REL_SCNNDX | FLG_REL_ADVAL, rsp, ofl)); 1446 } 1447 1448 return (add_outrel(NULL, rsp, ofl)); 1449 } 1450 1451 1452 /* ARGSUSED3 */ 1453 Gotndx * 1454 find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc) 1455 { 1456 Listnode * lnp; 1457 Gotndx * gnp; 1458 1459 assert(rdesc != 0); 1460 1461 if ((gref == GOT_REF_TLSLD) && ofl->ofl_tlsldgotndx) 1462 return (ofl->ofl_tlsldgotndx); 1463 1464 for (LIST_TRAVERSE(lst, lnp, gnp)) { 1465 if ((rdesc->rel_raddend == gnp->gn_addend) && 1466 (gnp->gn_gotref == gref)) { 1467 return (gnp); 1468 } 1469 } 1470 return ((Gotndx *)0); 1471 } 1472 1473 Xword 1474 calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl) 1475 { 1476 Os_desc *osp = ofl->ofl_osgot; 1477 Sym_desc *sdp = rdesc->rel_sym; 1478 Xword gotndx; 1479 Gotref gref; 1480 Gotndx *gnp; 1481 1482 if (rdesc->rel_flags & FLG_REL_DTLS) 1483 gref = GOT_REF_TLSGD; 1484 else if (rdesc->rel_flags & FLG_REL_MTLS) 1485 gref = GOT_REF_TLSLD; 1486 else if (rdesc->rel_flags & FLG_REL_STLS) 1487 gref = GOT_REF_TLSIE; 1488 else 1489 gref = GOT_REF_GENERIC; 1490 1491 gnp = find_gotndx(&(sdp->sd_GOTndxs), gref, ofl, rdesc); 1492 assert(gnp); 1493 1494 gotndx = (Xword)gnp->gn_gotndx; 1495 1496 if ((rdesc->rel_flags & FLG_REL_DTLS) && 1497 (rdesc->rel_rtype == R_AMD64_DTPOFF64)) 1498 gotndx++; 1499 1500 return ((Xword)(osp->os_shdr->sh_addr + (gotndx * M_GOT_ENTSIZE))); 1501 } 1502 1503 1504 /* ARGSUSED5 */ 1505 uintptr_t 1506 assign_gotndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl, 1507 Rel_desc * rsp, Sym_desc * sdp) 1508 { 1509 Xword raddend; 1510 Gotndx *gnp, *_gnp; 1511 Listnode *lnp, *plnp; 1512 uint_t gotents; 1513 1514 raddend = rsp->rel_raddend; 1515 if (pgnp && (pgnp->gn_addend == raddend) && 1516 (pgnp->gn_gotref == gref)) 1517 return (1); 1518 1519 if ((gref == GOT_REF_TLSGD) || (gref == GOT_REF_TLSLD)) 1520 gotents = 2; 1521 else 1522 gotents = 1; 1523 1524 plnp = 0; 1525 for (LIST_TRAVERSE(lst, lnp, _gnp)) { 1526 if (_gnp->gn_addend > raddend) 1527 break; 1528 plnp = lnp; 1529 } 1530 1531 /* 1532 * Allocate a new entry. 1533 */ 1534 if ((gnp = libld_calloc(sizeof (Gotndx), 1)) == 0) 1535 return (S_ERROR); 1536 gnp->gn_addend = raddend; 1537 gnp->gn_gotndx = ofl->ofl_gotcnt; 1538 gnp->gn_gotref = gref; 1539 1540 ofl->ofl_gotcnt += gotents; 1541 1542 if (gref == GOT_REF_TLSLD) { 1543 ofl->ofl_tlsldgotndx = gnp; 1544 return (1); 1545 } 1546 1547 if (plnp == 0) { 1548 /* 1549 * Insert at head of list 1550 */ 1551 if (list_prependc(lst, (void *)gnp) == 0) 1552 return (S_ERROR); 1553 } else if (_gnp->gn_addend > raddend) { 1554 /* 1555 * Insert in middle of lest 1556 */ 1557 if (list_insertc(lst, (void *)gnp, plnp) == 0) 1558 return (S_ERROR); 1559 } else { 1560 /* 1561 * Append to tail of list 1562 */ 1563 if (list_appendc(lst, (void *)gnp) == 0) 1564 return (S_ERROR); 1565 } 1566 return (1); 1567 } 1568 1569 1570 void 1571 assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl) 1572 { 1573 sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++; 1574 sdp->sd_aux->sa_PLTGOTndx = ofl->ofl_gotcnt++; 1575 } 1576 1577 static unsigned char plt0_template[M_PLT_ENTSIZE] = { 1578 /* 0x00 PUSHQ GOT+8(%rip) */ 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, 1579 /* 0x06 JMP *GOT+16(%rip) */ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 1580 /* 0x0c NOP */ 0x90, 1581 /* 0x0d NOP */ 0x90, 1582 /* 0x0e NOP */ 0x90, 1583 /* 0x0f NOP */ 0x90 1584 }; 1585 1586 /* 1587 * Initializes .got[0] with the _DYNAMIC symbol value. 1588 */ 1589 uintptr_t 1590 fillin_gotplt1(Ofl_desc * ofl) 1591 { 1592 Word flags = ofl->ofl_flags; 1593 Word dtflags1 = ofl->ofl_dtflags_1; 1594 1595 if (ofl->ofl_osgot) { 1596 Sym_desc * sdp; 1597 1598 if ((sdp = sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U), 1599 SYM_NOHASH, 0, ofl)) != NULL) { 1600 unsigned char *genptr = ((unsigned char *) 1601 ofl->ofl_osgot->os_outdata->d_buf + 1602 (M_GOT_XDYNAMIC * M_GOT_ENTSIZE)); 1603 /* LINTED */ 1604 *(Xword *)genptr = sdp->sd_sym->st_value; 1605 } 1606 } 1607 1608 /* 1609 * Fill in the reserved slot in the procedure linkage table the first 1610 * entry is: 1611 * 0x00 PUSHQ GOT+8(%rip) # GOT[1] 1612 * 0x06 JMP *GOT+16(%rip) # GOT[2] 1613 * 0x0c NOP 1614 * 0x0d NOP 1615 * 0x0e NOP 1616 * 0x0f NOP 1617 */ 1618 if ((flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) { 1619 unsigned char *pltent; 1620 Xword val1; 1621 1622 pltent = (unsigned char *)ofl->ofl_osplt->os_outdata->d_buf; 1623 bcopy(plt0_template, pltent, sizeof (plt0_template)); 1624 1625 /* 1626 * filin: 1627 * PUSHQ GOT + 8(%rip) 1628 * 1629 * Note: 0x06 below represents the offset to the 1630 * next instruction - which is what %rip will 1631 * be pointing at. 1632 */ 1633 val1 = (ofl->ofl_osgot->os_shdr->sh_addr) + 1634 (M_GOT_XLINKMAP * M_GOT_ENTSIZE) - 1635 ofl->ofl_osplt->os_shdr->sh_addr - 0x06; 1636 1637 /* 1638 * If '-z noreloc' is specified - skip the do_reloc 1639 * stage. 1640 */ 1641 if ((flags & FLG_OF_RELOBJ) || 1642 !(dtflags1 & DF_1_NORELOC)) { 1643 if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x02], 1644 &val1, MSG_ORIG(MSG_SYM_PLTENT), 1645 MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) { 1646 eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLT0FAIL)); 1647 return (S_ERROR); 1648 } 1649 } 1650 1651 /* 1652 * filin: 1653 * JMP *GOT+16(%rip) 1654 */ 1655 val1 = (ofl->ofl_osgot->os_shdr->sh_addr) + 1656 (M_GOT_XRTLD * M_GOT_ENTSIZE) - 1657 ofl->ofl_osplt->os_shdr->sh_addr - 0x0c; 1658 /* 1659 * If '-z noreloc' is specified - skip the do_reloc 1660 * stage. 1661 */ 1662 if ((flags & FLG_OF_RELOBJ) || 1663 !(dtflags1 & DF_1_NORELOC)) { 1664 if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x08], 1665 &val1, MSG_ORIG(MSG_SYM_PLTENT), 1666 MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) { 1667 eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLT0FAIL)); 1668 return (S_ERROR); 1669 } 1670 } 1671 } 1672 return (1); 1673 } 1674 1675 /* 1676 * Return got[0]. 1677 */ 1678 Addr 1679 fillin_gotplt2(Ofl_desc * ofl) 1680 { 1681 if (ofl->ofl_osgot) { 1682 return (ofl->ofl_osgot->os_shdr->sh_addr); 1683 } else 1684 return (0); 1685 } 1686