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