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