1 //===- X86Relocator.cpp -------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "X86Relocator.h" 10 #include "X86RelocationFunctions.h" 11 12 #include <mcld/Support/MsgHandling.h> 13 #include <mcld/LD/LDSymbol.h> 14 15 #include <llvm/ADT/Twine.h> 16 #include <llvm/Support/DataTypes.h> 17 #include <llvm/Support/ELF.h> 18 19 using namespace mcld; 20 21 //===--------------------------------------------------------------------===// 22 // Relocation Functions and Tables 23 //===--------------------------------------------------------------------===// 24 DECL_X86_32_APPLY_RELOC_FUNCS 25 26 /// the prototype of applying function 27 typedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc, 28 X86_32Relocator& pParent); 29 30 // the table entry of applying functions 31 struct X86_32ApplyFunctionTriple 32 { 33 X86_32ApplyFunctionType func; 34 unsigned int type; 35 const char* name; 36 unsigned int size; 37 }; 38 39 // declare the table of applying functions 40 static const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = { 41 DECL_X86_32_APPLY_RELOC_FUNC_PTRS 42 }; 43 44 //===--------------------------------------------------------------------===// 45 // X86Relocator 46 //===--------------------------------------------------------------------===// 47 X86Relocator::X86Relocator() 48 : Relocator() { 49 } 50 51 X86Relocator::~X86Relocator() 52 { 53 } 54 55 //===--------------------------------------------------------------------===// 56 // X86_32Relocator 57 //===--------------------------------------------------------------------===// 58 X86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent) 59 : X86Relocator(), m_Target(pParent) { 60 } 61 62 Relocator::Result 63 X86_32Relocator::applyRelocation(Relocation& pRelocation) 64 { 65 Relocation::Type type = pRelocation.type(); 66 67 if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) { 68 return Unknown; 69 } 70 71 // apply the relocation 72 return X86_32ApplyFunctions[type].func(pRelocation, *this); 73 } 74 75 const char* X86_32Relocator::getName(Relocation::Type pType) const 76 { 77 return X86_32ApplyFunctions[pType].name; 78 } 79 80 Relocator::Size X86_32Relocator::getSize(Relocation::Type pType) const 81 { 82 return X86_32ApplyFunctions[pType].size;; 83 } 84 85 //===--------------------------------------------------------------------===// 86 // Relocation helper function 87 //===--------------------------------------------------------------------===// 88 89 /// helper_DynRel - Get an relocation entry in .rel.dyn 90 static 91 Relocation& helper_DynRel(ResolveInfo* pSym, 92 Fragment& pFrag, 93 uint64_t pOffset, 94 X86Relocator::Type pType, 95 X86_32Relocator& pParent) 96 { 97 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 98 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 99 rel_entry.setType(pType); 100 rel_entry.targetRef().assign(pFrag, pOffset); 101 if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym) 102 rel_entry.setSymInfo(0); 103 else 104 rel_entry.setSymInfo(pSym); 105 106 return rel_entry; 107 } 108 109 110 /// helper_use_relative_reloc - Check if symbol can use relocation 111 /// R_386_RELATIVE 112 static bool 113 helper_use_relative_reloc(const ResolveInfo& pSym, 114 const X86_32Relocator& pFactory) 115 116 { 117 // if symbol is dynamic or undefine or preemptible 118 if (pSym.isDyn() || 119 pSym.isUndef() || 120 pFactory.getTarget().isSymbolPreemptible(pSym)) 121 return false; 122 return true; 123 } 124 125 static 126 X86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 127 X86_32Relocator& pParent) 128 { 129 // rsym - The relocation target symbol 130 ResolveInfo* rsym = pReloc.symInfo(); 131 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 132 133 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 134 if (NULL != got_entry) 135 return *got_entry; 136 137 // not found 138 got_entry = ld_backend.getGOT().consume(); 139 pParent.getSymGOTMap().record(*rsym, *got_entry); 140 141 // If we first get this GOT entry, we should initialize it. 142 if (rsym->reserved() & X86GNULDBackend::ReserveGOT) { 143 // No corresponding dynamic relocation, initialize to the symbol value. 144 got_entry->setValue(pReloc.symValue()); 145 } 146 else if (rsym->reserved() & X86GNULDBackend::GOTRel) { 147 // Initialize got_entry content and the corresponding dynamic relocation. 148 if (helper_use_relative_reloc(*rsym, pParent)) { 149 helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent); 150 got_entry->setValue(pReloc.symValue()); 151 } 152 else { 153 helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent); 154 got_entry->setValue(0); 155 } 156 } 157 else { 158 fatal(diag::reserve_entry_number_mismatch_got); 159 } 160 return *got_entry; 161 } 162 163 164 static 165 X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) 166 { 167 return pParent.getTarget().getGOTPLT().addr(); 168 } 169 170 171 static 172 X86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent) 173 { 174 X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 175 X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr(); 176 return got_addr + got_entry.getOffset(); 177 } 178 179 180 static 181 PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, 182 X86_32Relocator& pParent) 183 { 184 // rsym - The relocation target symbol 185 ResolveInfo* rsym = pReloc.symInfo(); 186 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 187 188 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 189 if (NULL != plt_entry) 190 return *plt_entry; 191 192 // not found 193 plt_entry = ld_backend.getPLT().consume(); 194 pParent.getSymPLTMap().record(*rsym, *plt_entry); 195 // If we first get this PLT entry, we should initialize it. 196 if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 197 X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 198 assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 199 gotplt_entry = ld_backend.getGOTPLT().consume(); 200 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 201 // init the corresponding rel entry in .rel.plt 202 Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 203 rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); 204 rel_entry.targetRef().assign(*gotplt_entry); 205 rel_entry.setSymInfo(rsym); 206 } 207 else { 208 fatal(diag::reserve_entry_number_mismatch_plt); 209 } 210 211 return *plt_entry; 212 } 213 214 215 static 216 X86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent) 217 { 218 return pParent.getTarget().getPLT().addr(); 219 } 220 221 222 static 223 X86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent) 224 { 225 PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 226 return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 227 } 228 229 230 //=========================================// 231 // Each relocation function implementation // 232 //=========================================// 233 234 // R_386_NONE 235 X86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) 236 { 237 return X86Relocator::OK; 238 } 239 240 // R_386_32: S + A 241 // R_386_16 242 // R_386_8 243 X86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) 244 { 245 ResolveInfo* rsym = pReloc.symInfo(); 246 Relocator::DWord A = pReloc.target() + pReloc.addend(); 247 Relocator::DWord S = pReloc.symValue(); 248 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 249 *rsym, 250 (rsym->reserved() & X86GNULDBackend::ReservePLT), 251 true); 252 253 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 254 // If the flag of target section is not ALLOC, we will not scan this relocation 255 // but perform static relocation. (e.g., applying .debug section) 256 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 257 pReloc.target() = S + A; 258 return X86Relocator::OK; 259 } 260 261 // A local symbol may need REL Type dynamic relocation 262 if (rsym->isLocal() && has_dyn_rel) { 263 if (llvm::ELF::R_386_32 == pReloc.type()) { 264 helper_DynRel(rsym, *pReloc.targetRef().frag(), 265 pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, 266 pParent); 267 } 268 else { 269 // FIXME: check Section symbol 270 helper_DynRel(rsym, *pReloc.targetRef().frag(), 271 pReloc.targetRef().offset(), pReloc.type(), pParent); 272 } 273 pReloc.target() = S + A; 274 return X86Relocator::OK; 275 } 276 277 // An external symbol may need PLT and dynamic relocation 278 if (!rsym->isLocal()) { 279 if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 280 S = helper_PLT(pReloc, pParent); 281 } 282 // If we generate a dynamic relocation (except R_386_RELATIVE) 283 // for a place, we should not perform static relocation on it 284 // in order to keep the addend store in the place correct. 285 if (has_dyn_rel) { 286 if (llvm::ELF::R_386_32 == pReloc.type() && 287 helper_use_relative_reloc(*rsym, pParent)) { 288 helper_DynRel(rsym, *pReloc.targetRef().frag(), 289 pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent); 290 } 291 else { 292 helper_DynRel(rsym, *pReloc.targetRef().frag(), 293 pReloc.targetRef().offset(), pReloc.type(), pParent); 294 return X86Relocator::OK; 295 } 296 } 297 } 298 299 // perform static relocation 300 pReloc.target() = S + A; 301 return X86Relocator::OK; 302 } 303 304 // R_386_PC32: S + A - P 305 // R_386_PC16 306 // R_386_PC8 307 X86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) 308 { 309 ResolveInfo* rsym = pReloc.symInfo(); 310 Relocator::DWord A = pReloc.target() + pReloc.addend(); 311 Relocator::DWord S = pReloc.symValue(); 312 Relocator::DWord P = pReloc.place(); 313 314 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 315 // If the flag of target section is not ALLOC, we will not scan this relocation 316 // but perform static relocation. (e.g., applying .debug section) 317 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 318 pReloc.target() = S + A - P; 319 return X86Relocator::OK; 320 } 321 322 // An external symbol may need PLT and dynamic relocation 323 if (!rsym->isLocal()) { 324 if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 325 S = helper_PLT(pReloc, pParent); 326 pReloc.target() = S + A - P; 327 } 328 if (pParent.getTarget().symbolNeedsDynRel( 329 *rsym, 330 (rsym->reserved() & X86GNULDBackend::ReservePLT), 331 false)) { 332 if (helper_use_relative_reloc(*rsym, pParent) ) { 333 helper_DynRel(rsym, *pReloc.targetRef().frag(), 334 pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent); 335 } 336 else { 337 helper_DynRel(rsym, *pReloc.targetRef().frag(), 338 pReloc.targetRef().offset(), pReloc.type(), pParent); 339 return X86Relocator::OK; 340 } 341 } 342 } 343 344 // perform static relocation 345 pReloc.target() = S + A - P; 346 return X86Relocator::OK; 347 } 348 349 // R_386_GOTOFF: S + A - GOT_ORG 350 X86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) 351 { 352 Relocator::DWord A = pReloc.target() + pReloc.addend(); 353 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 354 X86Relocator::Address S = pReloc.symValue(); 355 356 pReloc.target() = S + A - GOT_ORG; 357 return X86Relocator::OK; 358 } 359 360 // R_386_GOTPC: GOT_ORG + A - P 361 X86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) 362 { 363 Relocator::DWord A = pReloc.target() + pReloc.addend(); 364 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 365 // Apply relocation. 366 pReloc.target() = GOT_ORG + A - pReloc.place(); 367 return X86Relocator::OK; 368 } 369 370 // R_386_GOT32: GOT(S) + A - GOT_ORG 371 X86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) 372 { 373 if (!(pReloc.symInfo()->reserved() 374 & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) { 375 return X86Relocator::BadReloc; 376 } 377 X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent); 378 Relocator::DWord A = pReloc.target() + pReloc.addend(); 379 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 380 // Apply relocation. 381 pReloc.target() = GOT_S + A - GOT_ORG; 382 return X86Relocator::OK; 383 } 384 385 // R_386_PLT32: PLT(S) + A - P 386 X86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) 387 { 388 // PLT_S depends on if there is a PLT entry. 389 X86Relocator::Address PLT_S; 390 if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT)) 391 PLT_S = helper_PLT(pReloc, pParent); 392 else 393 PLT_S = pReloc.symValue(); 394 Relocator::DWord A = pReloc.target() + pReloc.addend(); 395 X86Relocator::Address P = pReloc.place(); 396 pReloc.target() = PLT_S + A - P; 397 return X86Relocator::OK; 398 } 399 400 // R_386_TLS_GD: 401 X86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) 402 { 403 // global-dynamic 404 ResolveInfo* rsym = pReloc.symInfo(); 405 // must reserve two pairs of got and dynamic relocation 406 if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) { 407 return X86Relocator::BadReloc; 408 } 409 410 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 411 ELFFileFormat* file_format = pParent.getTarget().getOutputFormat(); 412 // setup corresponding got and dynamic relocatio entries: 413 // get first got entry, if there is already a got entry for rsym, then apply 414 // this relocation to the got entry directly. If not, setup the corresponding 415 // got and dyn relocation entries 416 X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym); 417 418 if (NULL == got_entry1) { 419 // get and init two got entries if not exist 420 got_entry1 = ld_backend.getGOT().consume(); 421 pParent.getSymGOTMap().record(*rsym, *got_entry1); 422 X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume(); 423 got_entry1->setValue(0x0); 424 got_entry2->setValue(0x0); 425 // setup dyn rel for get_entry1 426 Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0, 427 llvm::ELF::R_386_TLS_DTPMOD32, pParent); 428 if (rsym->isLocal()) { 429 // for local symbol, set got_entry2 to symbol value 430 got_entry2->setValue(pReloc.symValue()); 431 432 // for local tls symbol, add rel entry against the section symbol this 433 // symbol belong to (.tdata or .tbss) 434 const LDSection* sym_sect = 435 &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 436 ResolveInfo* sect_sym = NULL; 437 if (&file_format->getTData() == sym_sect) 438 sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo(); 439 else 440 sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo(); 441 rel_entry1.setSymInfo(sect_sym); 442 } 443 else { 444 // for non-local symbol, add a pair of rel entries against this symbol 445 // for those two got entries 446 helper_DynRel(rsym, *got_entry2, 0x0, 447 llvm::ELF::R_386_TLS_DTPOFF32, pParent); 448 } 449 } 450 451 // perform relocation to the first got entry 452 Relocator::DWord A = pReloc.target() + pReloc.addend(); 453 // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the 454 // .got.plt section) 455 X86Relocator::Address GOT_OFF = 456 file_format->getGOT().addr() + 457 got_entry1->getOffset() - 458 file_format->getGOTPLT().addr(); 459 pReloc.target() = GOT_OFF + A; 460 return X86Relocator::OK; 461 } 462 463 // R_386_TLS_LDM 464 X86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) 465 { 466 // FIXME: no linker optimization for TLS relocation 467 const X86_32GOTEntry& got_entry = pParent.getTarget().getTLSModuleID(); 468 469 // All GOT offsets are relative to the end of the GOT. 470 X86Relocator::SWord GOT_S = got_entry.getOffset() - 471 (pParent.getTarget().getGOTPLT().addr() - 472 pParent.getTarget().getGOT().addr()); 473 Relocator::DWord A = pReloc.target() + pReloc.addend(); 474 pReloc.target() = GOT_S + A; 475 476 return X86Relocator::OK; 477 } 478 479 // R_386_TLS_LDO_32 480 X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) 481 { 482 // FIXME: no linker optimization for TLS relocation 483 Relocator::DWord A = pReloc.target() + pReloc.addend(); 484 X86Relocator::Address S = pReloc.symValue(); 485 pReloc.target() = S + A; 486 return X86Relocator::OK; 487 } 488 489 // R_X86_TLS_IE 490 X86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) 491 { 492 ResolveInfo* rsym = pReloc.symInfo(); 493 if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) { 494 return X86Relocator::BadReloc; 495 } 496 497 if (rsym->reserved() & X86GNULDBackend::ReserveRel) { 498 // when building shared object, set up a RELATIVE dynamic relocation 499 helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(), 500 llvm::ELF::R_386_RELATIVE, pParent); 501 } 502 503 // set up the got and dynamic relocation entries if not exist 504 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 505 if (NULL == got_entry) { 506 // set got entry 507 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 508 got_entry = ld_backend.getGOT().consume(); 509 pParent.getSymGOTMap().record(*rsym, *got_entry); 510 got_entry->setValue(0x0); 511 // set relocation entry 512 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 513 rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF); 514 rel_entry.setSymInfo(rsym); 515 rel_entry.targetRef().assign(*got_entry); 516 } 517 518 // perform relocation to the absolute address of got_entry 519 X86Relocator::Address GOT_S = 520 pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 521 522 Relocator::DWord A = pReloc.target() + pReloc.addend(); 523 pReloc.target() = GOT_S + A; 524 525 return X86Relocator::OK; 526 } 527 528 // R_386_TLS_GOTIE 529 X86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) 530 { 531 ResolveInfo* rsym = pReloc.symInfo(); 532 if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) { 533 return X86Relocator::BadReloc; 534 } 535 536 // set up the got and dynamic relocation entries if not exist 537 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 538 if (NULL == got_entry) { 539 // set got entry 540 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 541 got_entry = ld_backend.getGOT().consume(); 542 pParent.getSymGOTMap().record(*rsym, *got_entry); 543 got_entry->setValue(0x0); 544 // set relocation entry 545 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 546 rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF); 547 rel_entry.setSymInfo(rsym); 548 rel_entry.targetRef().assign(*got_entry); 549 } 550 551 // All GOT offsets are relative to the end of the GOT. 552 X86Relocator::SWord GOT_S = got_entry->getOffset() - 553 (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr()); 554 Relocator::DWord A = pReloc.target() + pReloc.addend(); 555 pReloc.target() = GOT_S + A; 556 557 return X86Relocator::OK; 558 } 559 560 // R_X86_TLS_LE 561 X86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) 562 { 563 ResolveInfo* rsym = pReloc.symInfo(); 564 if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) { 565 helper_DynRel(rsym, 566 *pReloc.targetRef().frag(), 567 pReloc.targetRef().offset(), 568 llvm::ELF::R_386_TLS_TPOFF, 569 pParent); 570 return X86Relocator::OK; 571 } 572 573 // perform static relocation 574 // get TLS segment 575 ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find( 576 llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0); 577 Relocator::DWord A = pReloc.target() + pReloc.addend(); 578 X86Relocator::Address S = pReloc.symValue(); 579 pReloc.target() = S + A - tls_seg->memsz(); 580 return X86Relocator::OK; 581 } 582 583 X86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent) 584 { 585 return X86Relocator::Unsupport; 586 } 587 588 //===--------------------------------------------------------------------===// 589 // Relocation Functions and Tables 590 //===--------------------------------------------------------------------===// 591 DECL_X86_64_APPLY_RELOC_FUNCS 592 593 /// the prototype of applying function 594 typedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc, 595 X86_64Relocator& pParent); 596 597 // the table entry of applying functions 598 struct X86_64ApplyFunctionTriple 599 { 600 X86_64ApplyFunctionType func; 601 unsigned int type; 602 const char* name; 603 unsigned int size; 604 }; 605 606 // declare the table of applying functions 607 static const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = { 608 DECL_X86_64_APPLY_RELOC_FUNC_PTRS 609 }; 610 611 //===--------------------------------------------------------------------===// 612 // X86_64Relocator 613 //===--------------------------------------------------------------------===// 614 X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent) 615 : X86Relocator(), m_Target(pParent) { 616 } 617 618 Relocator::Result 619 X86_64Relocator::applyRelocation(Relocation& pRelocation) 620 { 621 Relocation::Type type = pRelocation.type(); 622 623 if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) { 624 return Unknown; 625 } 626 627 // apply the relocation 628 return X86_64ApplyFunctions[type].func(pRelocation, *this); 629 } 630 631 const char* X86_64Relocator::getName(Relocation::Type pType) const 632 { 633 return X86_64ApplyFunctions[pType].name; 634 } 635 636 Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const 637 { 638 return X86_64ApplyFunctions[pType].size; 639 } 640 641 /// helper_DynRel - Get an relocation entry in .rela.dyn 642 static 643 Relocation& helper_DynRel(ResolveInfo* pSym, 644 Fragment& pFrag, 645 uint64_t pOffset, 646 X86Relocator::Type pType, 647 X86_64Relocator& pParent) 648 { 649 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 650 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 651 rel_entry.setType(pType); 652 rel_entry.targetRef().assign(pFrag, pOffset); 653 if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym) 654 rel_entry.setSymInfo(0); 655 else 656 rel_entry.setSymInfo(pSym); 657 658 return rel_entry; 659 } 660 661 662 /// helper_use_relative_reloc - Check if symbol can use relocation 663 /// R_X86_64_RELATIVE 664 static bool 665 helper_use_relative_reloc(const ResolveInfo& pSym, 666 const X86_64Relocator& pFactory) 667 668 { 669 // if symbol is dynamic or undefine or preemptible 670 if (pSym.isDyn() || 671 pSym.isUndef() || 672 pFactory.getTarget().isSymbolPreemptible(pSym)) 673 return false; 674 return true; 675 } 676 677 static 678 X86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 679 X86_64Relocator& pParent) 680 { 681 // rsym - The relocation target symbol 682 ResolveInfo* rsym = pReloc.symInfo(); 683 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 684 685 X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 686 if (NULL != got_entry) 687 return *got_entry; 688 689 // not found 690 got_entry = ld_backend.getGOT().consume(); 691 pParent.getSymGOTMap().record(*rsym, *got_entry); 692 693 // If we first get this GOT entry, we should initialize it. 694 if (rsym->reserved() & X86GNULDBackend::ReserveGOT) { 695 // No corresponding dynamic relocation, initialize to the symbol value. 696 got_entry->setValue(pReloc.symValue()); 697 } 698 else if (rsym->reserved() & X86GNULDBackend::GOTRel) { 699 // Initialize got_entry content and the corresponding dynamic relocation. 700 if (helper_use_relative_reloc(*rsym, pParent)) { 701 Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0, 702 llvm::ELF::R_X86_64_RELATIVE, 703 pParent); 704 rel_entry.setAddend(pReloc.symValue()); 705 } 706 else { 707 helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, 708 pParent); 709 } 710 got_entry->setValue(0); 711 } 712 else { 713 fatal(diag::reserve_entry_number_mismatch_got); 714 } 715 return *got_entry; 716 } 717 718 static 719 X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) 720 { 721 return pParent.getTarget().getGOT().addr(); 722 } 723 724 static 725 X86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent) 726 { 727 X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 728 return got_entry.getOffset(); 729 } 730 731 static 732 PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, 733 X86_64Relocator& pParent) 734 { 735 // rsym - The relocation target symbol 736 ResolveInfo* rsym = pReloc.symInfo(); 737 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 738 739 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 740 if (NULL != plt_entry) 741 return *plt_entry; 742 743 // not found 744 plt_entry = ld_backend.getPLT().consume(); 745 pParent.getSymPLTMap().record(*rsym, *plt_entry); 746 // If we first get this PLT entry, we should initialize it. 747 if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 748 X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 749 assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 750 gotplt_entry = ld_backend.getGOTPLT().consume(); 751 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 752 // init the corresponding rel entry in .rel.plt 753 Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 754 rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT); 755 rel_entry.targetRef().assign(*gotplt_entry); 756 rel_entry.setSymInfo(rsym); 757 } 758 else { 759 fatal(diag::reserve_entry_number_mismatch_plt); 760 } 761 762 return *plt_entry; 763 } 764 765 static 766 X86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent) 767 { 768 return pParent.getTarget().getPLT().addr(); 769 } 770 771 static 772 X86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent) 773 { 774 PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 775 return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 776 } 777 778 // 779 // R_X86_64_NONE 780 X86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) 781 { 782 return X86Relocator::OK; 783 } 784 785 // R_X86_64_64: S + A 786 // R_X86_64_32: 787 // R_X86_64_16: 788 // R_X86_64_8 789 X86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) 790 { 791 ResolveInfo* rsym = pReloc.symInfo(); 792 Relocator::DWord A = pReloc.addend(); 793 Relocator::DWord S = pReloc.symValue(); 794 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 795 *rsym, 796 (rsym->reserved() & X86GNULDBackend::ReservePLT), 797 true); 798 799 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 800 // If the flag of target section is not ALLOC, we will not scan this relocation 801 // but perform static relocation. (e.g., applying .debug section) 802 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 803 pReloc.target() = S + A; 804 return X86Relocator::OK; 805 } 806 807 Relocation::Type pointerRel = pParent.getTarget().getPointerRel(); 808 809 // A local symbol may need REL Type dynamic relocation 810 if (rsym->isLocal() && has_dyn_rel) { 811 if (pointerRel == pReloc.type()) { 812 Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(), 813 pReloc.targetRef().offset(), 814 llvm::ELF::R_X86_64_RELATIVE, 815 pParent); 816 rel_entry.setAddend(S + A); 817 } 818 else { 819 // FIXME: check Section symbol 820 Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(), 821 pReloc.targetRef().offset(), 822 pReloc.type(), pParent); 823 rel_entry.setAddend(S + A); 824 } 825 return X86Relocator::OK; 826 } 827 828 // An external symbol may need PLT and dynamic relocation 829 if (!rsym->isLocal()) { 830 // If we generate a dynamic relocation for a place with explicit 831 // addend, there is no need to perform static relocation on it. 832 if (has_dyn_rel) { 833 Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(), 834 pReloc.targetRef().offset(), 835 llvm::ELF::R_X86_64_RELATIVE, 836 pParent); 837 // Copy addend. 838 rel_entry.setAddend(A); 839 return X86Relocator::OK; 840 } 841 else if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 842 S = helper_PLT(pReloc, pParent); 843 } 844 } 845 846 // perform static relocation 847 pReloc.target() = S + A; 848 return X86Relocator::OK; 849 } 850 851 // R_X86_64_32S: S + A 852 X86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) 853 { 854 ResolveInfo* rsym = pReloc.symInfo(); 855 Relocator::DWord A = pReloc.addend(); 856 Relocator::DWord S = pReloc.symValue(); 857 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 858 *rsym, 859 (rsym->reserved() & X86GNULDBackend::ReservePLT), 860 true); 861 862 // There should be no dynamic relocations for R_X86_64_32S. 863 if (has_dyn_rel) 864 return X86Relocator::BadReloc; 865 866 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 867 // If the flag of target section is not ALLOC, we will not scan this relocation 868 // but perform static relocation. (e.g., applying .debug section) 869 // An external symbol may need PLT and dynamic relocation 870 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) && 871 !rsym->isLocal() && rsym->reserved() & X86GNULDBackend::ReservePLT) 872 S = helper_PLT(pReloc, pParent); 873 874 // Check 32-bit signed overflow. 875 Relocator::SWord V = S + A; 876 if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000)) 877 return X86Relocator::Overflow; 878 879 // perform static relocation 880 pReloc.target() = S + A; 881 return X86Relocator::OK; 882 } 883 884 // R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P 885 X86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) 886 { 887 if (!(pReloc.symInfo()->reserved() 888 & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) { 889 return X86Relocator::BadReloc; 890 } 891 X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent); 892 Relocator::DWord A = pReloc.addend(); 893 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 894 // Apply relocation. 895 pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place(); 896 return X86Relocator::OK; 897 } 898 899 // R_X86_64_PLT32: PLT(S) + A - P 900 X86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) 901 { 902 // PLT_S depends on if there is a PLT entry. 903 X86Relocator::Address PLT_S; 904 if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT)) 905 PLT_S = helper_PLT(pReloc, pParent); 906 else 907 PLT_S = pReloc.symValue(); 908 Relocator::DWord A = pReloc.addend(); 909 X86Relocator::Address P = pReloc.place(); 910 pReloc.target() = PLT_S + A - P; 911 return X86Relocator::OK; 912 } 913 914 // R_X86_64_PC32: S + A - P 915 // R_X86_64_PC16 916 // R_X86_64_PC8 917 X86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) 918 { 919 ResolveInfo* rsym = pReloc.symInfo(); 920 Relocator::DWord A = pReloc.addend(); 921 Relocator::DWord S = pReloc.symValue(); 922 Relocator::DWord P = pReloc.place(); 923 924 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 925 // If the flag of target section is not ALLOC, we will not scan this relocation 926 // but perform static relocation. (e.g., applying .debug section) 927 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 928 pReloc.target() = S + A - P; 929 return X86Relocator::OK; 930 } 931 932 // An external symbol may need PLT and dynamic relocation 933 if (!rsym->isLocal()) { 934 if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 935 S = helper_PLT(pReloc, pParent); 936 pReloc.target() = S + A - P; 937 } 938 if (pParent.getTarget().symbolNeedsDynRel( 939 *rsym, 940 (rsym->reserved() & X86GNULDBackend::ReservePLT), 941 false)) { 942 return X86Relocator::Overflow; 943 } 944 } 945 946 // perform static relocation 947 pReloc.target() = S + A - P; 948 return X86Relocator::OK; 949 } 950 951 X86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent) 952 { 953 return X86Relocator::Unsupport; 954 } 955