X86Relocator.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
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/LinkerConfig.h> 13#include <mcld/IRBuilder.h> 14#include <mcld/Support/MsgHandling.h> 15#include <mcld/LD/LDSymbol.h> 16#include <mcld/LD/ELFFileFormat.h> 17#include <mcld/LD/ELFSegmentFactory.h> 18#include <mcld/LD/ELFSegment.h> 19#include <mcld/Object/ObjectBuilder.h> 20 21#include <llvm/ADT/Twine.h> 22#include <llvm/Support/DataTypes.h> 23#include <llvm/Support/ELF.h> 24 25using namespace mcld; 26 27//===--------------------------------------------------------------------===// 28// X86_32 Relocation helper function 29//===--------------------------------------------------------------------===// 30/// helper_DynRel - Get an relocation entry in .rel.dyn 31static 32Relocation& helper_DynRel_init(ResolveInfo* pSym, 33 Fragment& pFrag, 34 uint64_t pOffset, 35 Relocator::Type pType, 36 X86_32Relocator& pParent) 37{ 38 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 39 Relocation& rel_entry = *ld_backend.getRelDyn().create(); 40 rel_entry.setType(pType); 41 rel_entry.targetRef().assign(pFrag, pOffset); 42 if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym) 43 rel_entry.setSymInfo(NULL); 44 else 45 rel_entry.setSymInfo(pSym); 46 47 return rel_entry; 48} 49 50/// helper_use_relative_reloc - Check if symbol ceuse relocation 51/// R_386_RELATIVE 52static bool 53helper_use_relative_reloc(const ResolveInfo& pSym, 54 const X86_32Relocator& pFactory) 55 56{ 57 // if symbol is dynamic or undefine or preemptible 58 if (pSym.isDyn() || 59 pSym.isUndef() || 60 pFactory.getTarget().isSymbolPreemptible(pSym)) 61 return false; 62 return true; 63} 64 65static 66X86_32GOTEntry& helper_GOT_init(Relocation& pReloc, 67 bool pHasRel, 68 X86_32Relocator& pParent) 69{ 70 // rsym - The relocation target symbol 71 ResolveInfo* rsym = pReloc.symInfo(); 72 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 73 assert(NULL == pParent.getSymGOTMap().lookUp(*rsym)); 74 75 X86_32GOTEntry* got_entry = ld_backend.getGOT().create(); 76 pParent.getSymGOTMap().record(*rsym, *got_entry); 77 78 if (!pHasRel) { 79 // No corresponding dynamic relocation, initialize to the symbol value. 80 got_entry->setValue(X86Relocator::SymVal); 81 } 82 else { 83 // Initialize got_entry content and the corresponding dynamic relocation. 84 if (helper_use_relative_reloc(*rsym, pParent)) { 85 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, 86 pParent); 87 got_entry->setValue(X86Relocator::SymVal); 88 } 89 else { 90 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, 91 pParent); 92 got_entry->setValue(0x0); 93 } 94 } 95 return *got_entry; 96} 97 98static 99Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) 100{ 101 return pParent.getTarget().getGOTPLT().addr(); 102} 103 104static 105Relocator::Address helper_get_GOT_address(Relocation& pReloc, 106 X86_32Relocator& pParent) 107{ 108 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 109 assert(NULL != got_entry); 110 return pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 111} 112 113static 114PLTEntryBase& helper_PLT_init(Relocation& pReloc, X86_32Relocator& pParent) 115{ 116 // rsym - The relocation target symbol 117 ResolveInfo* rsym = pReloc.symInfo(); 118 X86_32GNULDBackend& ld_backend = pParent.getTarget(); 119 assert(NULL == pParent.getSymPLTMap().lookUp(*rsym)); 120 121 PLTEntryBase* plt_entry = ld_backend.getPLT().create(); 122 pParent.getSymPLTMap().record(*rsym, *plt_entry); 123 124 // initialize plt and the corresponding gotplt and dyn rel entry. 125 assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) && 126 "PLT entry not exist, but GOTPLT entry exist!"); 127 X86_32GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create(); 128 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 129 130 // init the corresponding rel entry in .rel.plt 131 Relocation& rel_entry = *ld_backend.getRelPLT().create(); 132 rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); 133 rel_entry.targetRef().assign(*gotplt_entry); 134 rel_entry.setSymInfo(rsym); 135 return *plt_entry; 136} 137 138static Relocator::Address 139helper_get_PLT_address(ResolveInfo& pSym, X86_32Relocator& pParent) 140{ 141 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 142 assert(NULL != plt_entry); 143 return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 144} 145 146//===--------------------------------------------------------------------===// 147// X86_32 Relocation Functions and Tables 148//===--------------------------------------------------------------------===// 149DECL_X86_32_APPLY_RELOC_FUNCS 150 151/// the prototype of applying function 152typedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc, 153 X86_32Relocator& pParent); 154 155// the table entry of applying functions 156struct X86_32ApplyFunctionTriple 157{ 158 X86_32ApplyFunctionType func; 159 unsigned int type; 160 const char* name; 161 unsigned int size; 162}; 163 164// declare the table of applying functions 165static const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = { 166 DECL_X86_32_APPLY_RELOC_FUNC_PTRS 167}; 168 169//===--------------------------------------------------------------------===// 170// X86Relocator 171//===--------------------------------------------------------------------===// 172X86Relocator::X86Relocator(const LinkerConfig& pConfig) 173 : Relocator(pConfig) { 174} 175 176X86Relocator::~X86Relocator() 177{ 178} 179 180void X86Relocator::scanRelocation(Relocation& pReloc, 181 IRBuilder& pLinker, 182 Module& pModule, 183 LDSection& pSection, 184 Input& pInput) 185{ 186 if (LinkerConfig::Object == config().codeGenType()) 187 return; 188 // rsym - The relocation target symbol 189 ResolveInfo* rsym = pReloc.symInfo(); 190 assert(NULL != rsym && 191 "ResolveInfo of relocation not set while scanRelocation"); 192 193 assert(NULL != pSection.getLink()); 194 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 195 return; 196 197 // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation 198 // entries should be created. 199 if (rsym->isLocal()) // rsym is local 200 scanLocalReloc(pReloc, pLinker, pModule, pSection); 201 else // rsym is external 202 scanGlobalReloc(pReloc, pLinker, pModule, pSection); 203 204 // check if we should issue undefined reference for the relocation target 205 // symbol 206 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 207 issueUndefRef(pReloc, pSection, pInput); 208} 209 210void X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget) 211{ 212 Relocation& rel_entry = *pTarget.getRelDyn().create(); 213 rel_entry.setType(pTarget.getCopyRelType()); 214 assert(pSym.outSymbol()->hasFragRef()); 215 rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 216 rel_entry.setSymInfo(&pSym); 217} 218 219/// defineSymbolforCopyReloc 220/// For a symbol needing copy relocation, define a copy symbol in the BSS 221/// section and all other reference to this symbol should refer to this 222/// copy. 223/// @note This is executed at `scan relocation' stage. 224LDSymbol& X86Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 225 const ResolveInfo& pSym, 226 X86GNULDBackend& pTarget) 227{ 228 // get or create corresponding BSS LDSection 229 LDSection* bss_sect_hdr = NULL; 230 ELFFileFormat* file_format = pTarget.getOutputFormat(); 231 if (ResolveInfo::ThreadLocal == pSym.type()) 232 bss_sect_hdr = &file_format->getTBSS(); 233 else 234 bss_sect_hdr = &file_format->getBSS(); 235 236 // get or create corresponding BSS SectionData 237 assert(NULL != bss_sect_hdr); 238 SectionData* bss_section = NULL; 239 if (bss_sect_hdr->hasSectionData()) 240 bss_section = bss_sect_hdr->getSectionData(); 241 else 242 bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr); 243 244 // Determine the alignment by the symbol value 245 // FIXME: here we use the largest alignment 246 uint32_t addralign = config().targets().bitclass() / 8; 247 248 // allocate space in BSS for the copy symbol 249 Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 250 uint64_t size = ObjectBuilder::AppendFragment(*frag, 251 *bss_section, 252 addralign); 253 bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 254 255 // change symbol binding to Global if it's a weak symbol 256 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 257 if (binding == ResolveInfo::Weak) 258 binding = ResolveInfo::Global; 259 260 // Define the copy symbol in the bss section and resolve it 261 LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 262 pSym.name(), 263 (ResolveInfo::Type)pSym.type(), 264 ResolveInfo::Define, 265 binding, 266 pSym.size(), // size 267 0x0, // value 268 FragmentRef::Create(*frag, 0x0), 269 (ResolveInfo::Visibility)pSym.other()); 270 271 // output all other alias symbols if any 272 Module &pModule = pBuilder.getModule(); 273 Module::AliasList* alias_list = pModule.getAliasList(pSym); 274 if (NULL!=alias_list) { 275 Module::alias_iterator it, it_e=alias_list->end(); 276 for (it=alias_list->begin(); it!=it_e; ++it) { 277 const ResolveInfo* alias = *it; 278 if (alias!=&pSym && alias->isDyn()) { 279 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 280 alias->name(), 281 (ResolveInfo::Type)alias->type(), 282 ResolveInfo::Define, 283 binding, 284 alias->size(), // size 285 0x0, // value 286 FragmentRef::Create(*frag, 0x0), 287 (ResolveInfo::Visibility)alias->other()); 288 } 289 } 290 } 291 292 return *cpy_sym; 293} 294 295//===--------------------------------------------------------------------===// 296// X86_32Relocator 297//===--------------------------------------------------------------------===// 298X86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent, 299 const LinkerConfig& pConfig) 300 : X86Relocator(pConfig), m_Target(pParent) { 301} 302 303Relocator::Result 304X86_32Relocator::applyRelocation(Relocation& pRelocation) 305{ 306 Relocation::Type type = pRelocation.type(); 307 308 if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) { 309 return Unknown; 310 } 311 312 // apply the relocation 313 return X86_32ApplyFunctions[type].func(pRelocation, *this); 314} 315 316const char* X86_32Relocator::getName(Relocation::Type pType) const 317{ 318 return X86_32ApplyFunctions[pType].name; 319} 320 321Relocator::Size X86_32Relocator::getSize(Relocation::Type pType) const 322{ 323 return X86_32ApplyFunctions[pType].size;; 324} 325 326void X86_32Relocator::scanLocalReloc(Relocation& pReloc, 327 IRBuilder& pBuilder, 328 Module& pModule, 329 LDSection& pSection) 330{ 331 // rsym - The relocation target symbol 332 ResolveInfo* rsym = pReloc.symInfo(); 333 334 switch(pReloc.type()){ 335 336 case llvm::ELF::R_386_32: 337 // If buiding PIC object (shared library or PIC executable), 338 // a dynamic relocations with RELATIVE type to this location is needed. 339 // Reserve an entry in .rel.dyn 340 if (config().isCodeIndep()) { 341 // set Rel bit 342 rsym->setReserved(rsym->reserved() | ReserveRel); 343 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 344 // set up the dyn rel directly 345 helper_DynRel_init(rsym, 346 *pReloc.targetRef().frag(), 347 pReloc.targetRef().offset(), 348 llvm::ELF::R_386_RELATIVE, 349 *this); 350 } 351 return; 352 353 case llvm::ELF::R_386_16: 354 case llvm::ELF::R_386_8: 355 // If buiding PIC object (shared library or PIC executable), 356 // a dynamic relocations with RELATIVE type to this location is needed. 357 // Reserve an entry in .rel.dyn 358 if (config().isCodeIndep()) { 359 // set up the dyn rel directly 360 helper_DynRel_init(rsym, *pReloc.targetRef().frag(), 361 pReloc.targetRef().offset(), pReloc.type(), *this); 362 // set Rel bit 363 rsym->setReserved(rsym->reserved() | ReserveRel); 364 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 365 } 366 return; 367 368 case llvm::ELF::R_386_PLT32: 369 return; 370 371 case llvm::ELF::R_386_GOTOFF: 372 case llvm::ELF::R_386_GOTPC: 373 // FIXME: A GOT section is needed 374 return; 375 376 case llvm::ELF::R_386_GOT32: 377 // Symbol needs GOT entry, reserve entry in .got 378 // return if we already create GOT for this symbol 379 if (rsym->reserved() & ReserveGOT) 380 return; 381 382 // FIXME: check STT_GNU_IFUNC symbol 383 384 // If building shared object or the symbol is undefined, a dynamic 385 // relocation is needed to relocate this GOT entry. Reserve an 386 // entry in .rel.dyn 387 if (LinkerConfig::DynObj == 388 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 389 helper_GOT_init(pReloc, true, *this); 390 // set GOT bit 391 rsym->setReserved(rsym->reserved() | ReserveGOT); 392 return; 393 } 394 395 // elsewhere if the GOT is used in statically linked binaries, 396 // the GOT entry is enough and no relocation is needed. 397 helper_GOT_init(pReloc, false, *this); 398 rsym->setReserved(rsym->reserved() | ReserveGOT); 399 return; 400 401 case llvm::ELF::R_386_PC32: 402 case llvm::ELF::R_386_PC16: 403 case llvm::ELF::R_386_PC8: 404 return; 405 406 case llvm::ELF::R_386_TLS_GD: { 407 // FIXME: no linker optimization for TLS relocation 408 if (rsym->reserved() & ReserveGOT) 409 return; 410 411 // define the section symbol for .tdata or .tbss 412 // the target symbol of the created dynamic relocation should be the 413 // section symbol of the section which this symbol defined. so we 414 // need to define that section symbol here 415 ELFFileFormat* file_format = getTarget().getOutputFormat(); 416 const LDSection* sym_sect = 417 &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 418 LDSymbol* sect_sym = NULL; 419 if (&file_format->getTData() == sym_sect) { 420 if (!getTarget().hasTDATASymbol()) { 421 sect_sym = pModule.getSectionSymbolSet().get(*sym_sect); 422 getTarget().setTDATASymbol(*sect_sym); 423 } 424 } 425 else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) { 426 if (!getTarget().hasTBSSSymbol()) { 427 sect_sym = pModule.getSectionSymbolSet().get(*sym_sect); 428 getTarget().setTBSSSymbol(*sect_sym); 429 } 430 } 431 else 432 error(diag::invalid_tls) << rsym->name() << sym_sect->name(); 433 434 // set up a pair of got entries and a dyn rel 435 // set GOT bit 436 rsym->setReserved(rsym->reserved() | ReserveGOT); 437 X86_32GOTEntry* got_entry1 = getTarget().getGOT().create(); 438 X86_32GOTEntry* got_entry2 = getTarget().getGOT().create(); 439 getSymGOTMap().record(*rsym, *got_entry1, *got_entry2); 440 // set up value of got entries, the value of got_entry2 should be the 441 // symbol value, which has to be set during apply relocation 442 got_entry1->setValue(0x0); 443 444 // setup dyn rel for got_entry1 445 Relocation& rel_entry1 = helper_DynRel_init(rsym, *got_entry1, 0x0, 446 llvm::ELF::R_386_TLS_DTPMOD32, *this); 447 // for local tls symbol, add rel entry against the section symbol this 448 // symbol belong to (.tdata or .tbss) 449 rel_entry1.setSymInfo(sect_sym->resolveInfo()); 450 return; 451 } 452 case llvm::ELF::R_386_TLS_LDM: 453 getTLSModuleID(); 454 return; 455 456 case llvm::ELF::R_386_TLS_LDO_32: 457 return; 458 459 case llvm::ELF::R_386_TLS_IE: { 460 getTarget().setHasStaticTLS(); 461 462 // if building shared object, a RELATIVE dynamic relocation is needed 463 if (LinkerConfig::DynObj == config().codeGenType()) { 464 helper_DynRel_init(rsym, *pReloc.targetRef().frag(), 465 pReloc.targetRef().offset(), 466 llvm::ELF::R_386_RELATIVE, *this); 467 rsym->setReserved(rsym->reserved() | ReserveRel); 468 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 469 } 470 else { 471 // for local sym, we can convert ie to le if not building shared object 472 convertTLSIEtoLE(pReloc, pSection); 473 return; 474 } 475 476 if (rsym->reserved() & ReserveGOT) 477 return; 478 479 // set up the got and the corresponding rel entry 480 X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 481 getSymGOTMap().record(*rsym, *got_entry); 482 got_entry->setValue(0x0); 483 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, 484 *this); 485 // set GOT bit 486 rsym->setReserved(rsym->reserved() | ReserveGOT); 487 // add symbol to dyn sym table 488 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 489 return; 490 } 491 492 case llvm::ELF::R_386_TLS_GOTIE: { 493 getTarget().setHasStaticTLS(); 494 if (rsym->reserved() & ReserveGOT) 495 return; 496 // set up the got and the corresponding dyn rel 497 X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 498 getSymGOTMap().record(*rsym, *got_entry); 499 got_entry->setValue(0x0); 500 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, 501 *this); 502 // set GOT bit 503 rsym->setReserved(rsym->reserved() | ReserveGOT); 504 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 505 return; 506 } 507 508 case llvm::ELF::R_386_TLS_LE: 509 case llvm::ELF::R_386_TLS_LE_32: 510 getTarget().setHasStaticTLS(); 511 // if buildint shared object, a dynamic relocation is needed 512 if (LinkerConfig::DynObj == config().codeGenType()) { 513 helper_DynRel_init(rsym, 514 *pReloc.targetRef().frag(), 515 pReloc.targetRef().offset(), 516 llvm::ELF::R_386_TLS_TPOFF, 517 *this); 518 rsym->setReserved(rsym->reserved() | ReserveRel); 519 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 520 // the target symbol of the dynamic relocation is rsym, so we need to 521 // emit it into .dynsym 522 assert(NULL != rsym->outSymbol()); 523 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 524 } 525 return; 526 527 default: 528 fatal(diag::unsupported_relocation) << (int)pReloc.type() 529 << "mclinker@googlegroups.com"; 530 break; 531 } // end switch 532} 533 534void X86_32Relocator::scanGlobalReloc(Relocation& pReloc, 535 IRBuilder& pBuilder, 536 Module& pModule, 537 LDSection& pSection) 538{ 539 // rsym - The relocation target symbol 540 ResolveInfo* rsym = pReloc.symInfo(); 541 542 switch(pReloc.type()) { 543 case llvm::ELF::R_386_32: 544 case llvm::ELF::R_386_16: 545 case llvm::ELF::R_386_8: 546 // Absolute relocation type, symbol may needs PLT entry or 547 // dynamic relocation entry 548 if (getTarget().symbolNeedsPLT(*rsym)) { 549 // create plt for this symbol if it does not have one 550 if (!(rsym->reserved() & ReservePLT)){ 551 // Symbol needs PLT entry, we need a PLT entry 552 // and the corresponding GOT and dynamic relocation entry 553 // in .got and .rel.plt. 554 helper_PLT_init(pReloc, *this); 555 // set PLT bit 556 rsym->setReserved(rsym->reserved() | ReservePLT); 557 } 558 } 559 560 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 561 true)) { 562 // symbol needs dynamic relocation entry, set up the dynrel entry 563 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 564 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 565 addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 566 } 567 else { 568 // set Rel bit and the dyn rel 569 rsym->setReserved(rsym->reserved() | ReserveRel); 570 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 571 if (llvm::ELF::R_386_32 == pReloc.type() && 572 helper_use_relative_reloc(*rsym, *this)) 573 helper_DynRel_init(rsym, 574 *pReloc.targetRef().frag(), 575 pReloc.targetRef().offset(), 576 llvm::ELF::R_386_RELATIVE, 577 *this); 578 else 579 helper_DynRel_init(rsym, 580 *pReloc.targetRef().frag(), 581 pReloc.targetRef().offset(), 582 pReloc.type(), 583 *this); 584 } 585 } 586 return; 587 588 case llvm::ELF::R_386_GOTOFF: 589 case llvm::ELF::R_386_GOTPC: { 590 // FIXME: A GOT section is needed 591 return; 592 } 593 594 case llvm::ELF::R_386_PLT32: 595 // A PLT entry is needed when building shared library 596 597 // return if we already create plt for this symbol 598 if (rsym->reserved() & ReservePLT) 599 return; 600 601 // if the symbol's value can be decided at link time, then no need plt 602 if (getTarget().symbolFinalValueIsKnown(*rsym)) 603 return; 604 605 // if symbol is defined in the ouput file and it's not 606 // preemptible, no need plt 607 if (rsym->isDefine() && !rsym->isDyn() && 608 !getTarget().isSymbolPreemptible(*rsym)) 609 return; 610 611 // Symbol needs PLT entry, we need a PLT entry 612 // and the corresponding GOT and dynamic relocation entry 613 // in .got and .rel.plt 614 helper_PLT_init(pReloc, *this); 615 // set PLT bit 616 rsym->setReserved(rsym->reserved() | ReservePLT); 617 return; 618 619 case llvm::ELF::R_386_GOT32: 620 // Symbol needs GOT entry, reserve entry in .got 621 // return if we already create GOT for this symbol 622 if (rsym->reserved() & ReserveGOT) 623 return; 624 // If building shared object or the symbol is undefined, a dynamic 625 // relocation is needed to relocate this GOT entry. Reserve an 626 // entry in .rel.dyn 627 if (LinkerConfig::DynObj == 628 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) 629 helper_GOT_init(pReloc, true, *this); 630 else 631 helper_GOT_init(pReloc, false, *this); 632 // set GOT bit 633 rsym->setReserved(rsym->reserved() | ReserveGOT); 634 return; 635 636 case llvm::ELF::R_386_PC32: 637 case llvm::ELF::R_386_PC16: 638 case llvm::ELF::R_386_PC8: 639 640 if (getTarget().symbolNeedsPLT(*rsym) && 641 LinkerConfig::DynObj != config().codeGenType()) { 642 // create plt for this symbol if it does not have one 643 if (!(rsym->reserved() & ReservePLT)){ 644 // Symbol needs PLT entry, we need a PLT entry 645 // and the corresponding GOT and dynamic relocation entry 646 // in .got and .rel.plt. 647 // set PLT bit 648 helper_PLT_init(pReloc, *this); 649 rsym->setReserved(rsym->reserved() | ReservePLT); 650 } 651 } 652 653 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 654 false)) { 655 // symbol needs dynamic relocation entry, setup an entry in .rel.dyn 656 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 657 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, 658 getTarget()); 659 addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 660 } 661 else { 662 // set Rel bit and the dyn rel 663 rsym->setReserved(rsym->reserved() | ReserveRel); 664 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 665 if (llvm::ELF::R_386_32 == pReloc.type() && 666 helper_use_relative_reloc(*rsym, *this)) 667 helper_DynRel_init(rsym, 668 *pReloc.targetRef().frag(), 669 pReloc.targetRef().offset(), 670 llvm::ELF::R_386_RELATIVE, 671 *this); 672 else 673 helper_DynRel_init(rsym, 674 *pReloc.targetRef().frag(), 675 pReloc.targetRef().offset(), 676 pReloc.type(), 677 *this); 678 } 679 } 680 return; 681 682 case llvm::ELF::R_386_TLS_GD: { 683 // FIXME: no linker optimization for TLS relocation 684 if (rsym->reserved() & ReserveGOT) 685 return; 686 687 // set up a pair of got entries and a pair of dyn rel 688 X86_32GOTEntry* got_entry1 = getTarget().getGOT().create(); 689 X86_32GOTEntry* got_entry2 = getTarget().getGOT().create(); 690 getSymGOTMap().record(*rsym, *got_entry1, *got_entry2); 691 got_entry1->setValue(0x0); 692 got_entry2->setValue(0x0); 693 // setup dyn rel for got entries against rsym 694 helper_DynRel_init(rsym, *got_entry1, 0x0, 695 llvm::ELF::R_386_TLS_DTPMOD32, *this); 696 helper_DynRel_init(rsym, *got_entry2, 0x0, 697 llvm::ELF::R_386_TLS_DTPOFF32, *this); 698 699 // add the rsym to dynamic symbol table 700 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 701 // set GOT bit 702 rsym->setReserved(rsym->reserved() | ReserveGOT); 703 return; 704 } 705 706 case llvm::ELF::R_386_TLS_LDM: 707 getTLSModuleID(); 708 return; 709 710 case llvm::ELF::R_386_TLS_LDO_32: 711 return; 712 713 case llvm::ELF::R_386_TLS_IE: { 714 getTarget().setHasStaticTLS(); 715 // if buildint shared object, a RELATIVE dynamic relocation is needed 716 if (LinkerConfig::DynObj == config().codeGenType()) { 717 helper_DynRel_init(rsym, *pReloc.targetRef().frag(), 718 pReloc.targetRef().offset(), 719 llvm::ELF::R_386_RELATIVE, *this); 720 rsym->setReserved(rsym->reserved() | ReserveRel); 721 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 722 } else { 723 // for global sym, we can convert ie to le if its final value is known 724 if (getTarget().symbolFinalValueIsKnown(*rsym)) { 725 convertTLSIEtoLE(pReloc, pSection); 726 return; 727 } 728 } 729 if (rsym->reserved() & ReserveGOT) 730 return; 731 // set up the got and the corresponding rel entry 732 X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 733 getSymGOTMap().record(*rsym, *got_entry); 734 got_entry->setValue(0x0); 735 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, 736 *this); 737 // set GOT bit 738 rsym->setReserved(rsym->reserved() | ReserveGOT); 739 return; 740 } 741 742 case llvm::ELF::R_386_TLS_GOTIE: { 743 getTarget().setHasStaticTLS(); 744 if (rsym->reserved() & ReserveGOT) 745 return; 746 // set up the got and the corresponding dyn rel 747 X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 748 getSymGOTMap().record(*rsym, *got_entry); 749 got_entry->setValue(0x0); 750 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, 751 *this); 752 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 753 // set GOT bit 754 rsym->setReserved(rsym->reserved() | ReserveGOT); 755 return; 756 } 757 758 case llvm::ELF::R_386_TLS_LE: 759 case llvm::ELF::R_386_TLS_LE_32: 760 getTarget().setHasStaticTLS(); 761 // if buildint shared object, a dynamic relocation is needed 762 if (LinkerConfig::DynObj == config().codeGenType()) { 763 helper_DynRel_init(rsym, 764 *pReloc.targetRef().frag(), 765 pReloc.targetRef().offset(), 766 llvm::ELF::R_386_TLS_TPOFF, 767 *this); 768 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 769 rsym->setReserved(rsym->reserved() | ReserveRel); 770 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 771 } 772 return; 773 774 default: { 775 fatal(diag::unsupported_relocation) << (int)pReloc.type() 776 << "mclinker@googlegroups.com"; 777 break; 778 } 779 } // end switch 780} 781 782// Create a GOT entry for the TLS module index 783X86_32GOTEntry& X86_32Relocator::getTLSModuleID() 784{ 785 static X86_32GOTEntry* got_entry = NULL; 786 if (NULL != got_entry) 787 return *got_entry; 788 789 // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM 790 got_entry = getTarget().getGOT().create(); 791 getTarget().getGOT().create()->setValue(0x0); 792 793 helper_DynRel_init(NULL, *got_entry, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, 794 *this); 795 return *got_entry; 796} 797 798/// convert R_386_TLS_IE to R_386_TLS_LE 799void X86_32Relocator::convertTLSIEtoLE(Relocation& pReloc, 800 LDSection& pSection) 801{ 802 assert(pReloc.type() == llvm::ELF::R_386_TLS_IE); 803 assert(NULL != pReloc.targetRef().frag()); 804 805 // 1. create the new relocs 806 Relocation* reloc = 807 Relocation::Create(X86_32Relocator::R_386_TLS_OPT, 808 *FragmentRef::Create(*pReloc.targetRef().frag(), 809 pReloc.targetRef().offset() - 1), 810 0x0); 811 // FIXME: should we create a special symbol for the tls opt instead? 812 reloc->setSymInfo(pReloc.symInfo()); 813 814 // 2. modify the opcodes to the appropriate ones 815 uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target())); 816 if (op[0] == 0xa1) { 817 op[0] = 0xb8; 818 } else { 819 // create the new reloc (move 1 byte forward). 820 reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT, 821 *FragmentRef::Create(*pReloc.targetRef().frag(), 822 pReloc.targetRef().offset() - 2), 823 0x0); 824 reloc->setSymInfo(pReloc.symInfo()); 825 op = (reinterpret_cast<uint8_t*>(&reloc->target())); 826 switch (op[0]) { 827 case 0x8b: 828 assert((op[1] & 0xc7) == 0x05); 829 op[0] = 0xc7; 830 op[1] = 0xc0 | ((op[1] >> 3) & 7); 831 break; 832 case 0x03: 833 assert((op[1] & 0xc7) == 0x05); 834 op[0] = 0x81; 835 op[1] = 0xc0 | ((op[1] >> 3) & 7); 836 break; 837 default: 838 assert(0); 839 break; 840 } 841 } 842 843 // 3. insert the new relocs "BEFORE" the original reloc. 844 assert(reloc != NULL); 845 pSection.getRelocData()->getRelocationList().insert( 846 RelocData::iterator(pReloc), reloc); 847 848 // 4. change the type of the original reloc 849 pReloc.setType(llvm::ELF::R_386_TLS_LE); 850} 851 852//================================================// 853// X86_32 Each relocation function implementation // 854//================================================// 855 856// R_386_NONE 857Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) 858{ 859 return Relocator::OK; 860} 861 862// R_386_32: S + A 863// R_386_16 864// R_386_8 865Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) 866{ 867 ResolveInfo* rsym = pReloc.symInfo(); 868 Relocator::DWord A = pReloc.target() + pReloc.addend(); 869 Relocator::DWord S = pReloc.symValue(); 870 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 871 *rsym, 872 (rsym->reserved() & X86Relocator::ReservePLT), 873 true); 874 875 876 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 877 // If the flag of target section is not ALLOC, we will not scan this relocation 878 // but perform static relocation. (e.g., applying .debug section) 879 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 880 pReloc.target() = S + A; 881 return Relocator::OK; 882 } 883 884 // An external symbol may need PLT and dynamic relocation 885 if (!rsym->isLocal()) { 886 if (rsym->reserved() & X86Relocator::ReservePLT) { 887 S = helper_get_PLT_address(*rsym, pParent); 888 } 889 // If we generate a dynamic relocation (except R_386_RELATIVE) 890 // for a place, we should not perform static relocation on it 891 // in order to keep the addend store in the place correct. 892 if (has_dyn_rel) 893 if (llvm::ELF::R_386_32 != pReloc.type() || 894 (!helper_use_relative_reloc(*rsym, pParent))) 895 return Relocator::OK; 896 } 897 898 // perform static relocation 899 pReloc.target() = S + A; 900 return Relocator::OK; 901} 902 903// R_386_PC32: S + A - P 904// R_386_PC16 905// R_386_PC8 906Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) 907{ 908 ResolveInfo* rsym = pReloc.symInfo(); 909 Relocator::DWord A = pReloc.target() + pReloc.addend(); 910 Relocator::DWord S = pReloc.symValue(); 911 Relocator::DWord P = pReloc.place(); 912 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 913 *rsym, 914 (rsym->reserved() & X86Relocator::ReservePLT), 915 true); 916 917 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 918 // If the flag of target section is not ALLOC, we will not scan this relocation 919 // but perform static relocation. (e.g., applying .debug section) 920 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 921 pReloc.target() = S + A - P; 922 return Relocator::OK; 923 } 924 925 // An external symbol may need PLT and dynamic relocation 926 if (!rsym->isLocal()) { 927 if (rsym->reserved() & X86Relocator::ReservePLT) { 928 S = helper_get_PLT_address(*rsym, pParent); 929 pReloc.target() = S + A - P; 930 } 931 if (has_dyn_rel) 932 if (!helper_use_relative_reloc(*rsym, pParent)) 933 return Relocator::OK; 934 } 935 936 // perform static relocation 937 pReloc.target() = S + A - P; 938 return Relocator::OK; 939} 940 941// R_386_GOTOFF: S + A - GOT_ORG 942Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) 943{ 944 Relocator::DWord A = pReloc.target() + pReloc.addend(); 945 Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 946 Relocator::Address S = pReloc.symValue(); 947 948 pReloc.target() = S + A - GOT_ORG; 949 return Relocator::OK; 950} 951 952// R_386_GOTPC: GOT_ORG + A - P 953Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) 954{ 955 Relocator::DWord A = pReloc.target() + pReloc.addend(); 956 Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 957 // Apply relocation. 958 pReloc.target() = GOT_ORG + A - pReloc.place(); 959 return Relocator::OK; 960} 961 962// R_386_GOT32: GOT(S) + A - GOT_ORG 963Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) 964{ 965 ResolveInfo* rsym = pReloc.symInfo(); 966 if (!(rsym->reserved() & (X86Relocator::ReserveGOT))) 967 return Relocator::BadReloc; 968 969 // set up got entry value if the got has no dyn rel or 970 // the dyn rel is RELATIVE 971 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 972 assert(NULL != got_entry); 973 if (got_entry->getValue() == X86Relocator::SymVal) 974 got_entry->setValue(pReloc.symValue()); 975 976 Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent); 977 Relocator::DWord A = pReloc.target() + pReloc.addend(); 978 Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 979 // Apply relocation. 980 pReloc.target() = GOT_S + A - GOT_ORG; 981 return Relocator::OK; 982} 983 984// R_386_PLT32: PLT(S) + A - P 985Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) 986{ 987 // PLT_S depends on if there is a PLT entry. 988 Relocator::Address PLT_S; 989 if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 990 PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 991 else 992 PLT_S = pReloc.symValue(); 993 Relocator::DWord A = pReloc.target() + pReloc.addend(); 994 Relocator::Address P = pReloc.place(); 995 pReloc.target() = PLT_S + A - P; 996 return Relocator::OK; 997} 998 999// R_386_TLS_GD: 1000Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) 1001{ 1002 // global-dynamic 1003 ResolveInfo* rsym = pReloc.symInfo(); 1004 // must reserve two pairs of got and dynamic relocation 1005 if (!(rsym->reserved() & X86Relocator::ReserveGOT)) 1006 return Relocator::BadReloc; 1007 1008 ELFFileFormat* file_format = pParent.getTarget().getOutputFormat(); 1009 // setup corresponding got and dynamic relocatio entries: 1010 // get first got entry, if there is already a got entry for rsym, then apply 1011 // this relocation to the got entry directly. If not, setup the corresponding 1012 // got and dyn relocation entries 1013 X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUpFirstEntry(*rsym); 1014 1015 // set the got_entry2 value to symbol value 1016 if (rsym->isLocal()) 1017 pParent.getSymGOTMap().lookUpSecondEntry(*rsym)->setValue(pReloc.symValue()); 1018 1019 // perform relocation to the first got entry 1020 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1021 // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the 1022 // .got.plt section) 1023 Relocator::Address GOT_OFF = 1024 file_format->getGOT().addr() + 1025 got_entry1->getOffset() - 1026 file_format->getGOTPLT().addr(); 1027 pReloc.target() = GOT_OFF + A; 1028 return Relocator::OK; 1029} 1030 1031// R_386_TLS_LDM 1032Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) 1033{ 1034 // FIXME: no linker optimization for TLS relocation 1035 const X86_32GOTEntry& got_entry = pParent.getTLSModuleID(); 1036 1037 // All GOT offsets are relative to the end of the GOT. 1038 X86Relocator::SWord GOT_S = got_entry.getOffset() - 1039 (pParent.getTarget().getGOTPLT().addr() - 1040 pParent.getTarget().getGOT().addr()); 1041 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1042 pReloc.target() = GOT_S + A; 1043 1044 return Relocator::OK; 1045} 1046 1047// R_386_TLS_LDO_32 1048Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) 1049{ 1050 // FIXME: no linker optimization for TLS relocation 1051 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1052 Relocator::Address S = pReloc.symValue(); 1053 pReloc.target() = S + A; 1054 return Relocator::OK; 1055} 1056 1057// R_X86_TLS_IE 1058Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) 1059{ 1060 ResolveInfo* rsym = pReloc.symInfo(); 1061 if (!(rsym->reserved() & X86Relocator::ReserveGOT)) { 1062 return Relocator::BadReloc; 1063 } 1064 1065 // set up the got and dynamic relocation entries if not exist 1066 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 1067 assert(NULL != got_entry); 1068 // perform relocation to the absolute address of got_entry 1069 Relocator::Address GOT_S = 1070 pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 1071 1072 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1073 pReloc.target() = GOT_S + A; 1074 1075 return Relocator::OK; 1076} 1077 1078// R_386_TLS_GOTIE 1079Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) 1080{ 1081 ResolveInfo* rsym = pReloc.symInfo(); 1082 if (!(rsym->reserved() & X86Relocator::ReserveGOT)) { 1083 return Relocator::BadReloc; 1084 } 1085 1086 // set up the got and dynamic relocation entries if not exist 1087 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 1088 assert(NULL != got_entry); 1089 1090 // All GOT offsets are relative to the end of the GOT. 1091 X86Relocator::SWord GOT_S = got_entry->getOffset() - 1092 (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr()); 1093 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1094 pReloc.target() = GOT_S + A; 1095 1096 return Relocator::OK; 1097} 1098 1099// R_X86_TLS_LE 1100Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) 1101{ 1102 if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) 1103 return Relocator::OK; 1104 1105 // perform static relocation 1106 // get TLS segment 1107 ELFSegmentFactory::const_iterator tls_seg = 1108 pParent.getTarget().elfSegmentTable().find(llvm::ELF::PT_TLS, 1109 llvm::ELF::PF_R, 1110 0x0); 1111 assert(tls_seg != pParent.getTarget().elfSegmentTable().end()); 1112 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1113 Relocator::Address S = pReloc.symValue(); 1114 pReloc.target() = S + A - (*tls_seg)->memsz(); 1115 return Relocator::OK; 1116} 1117 1118Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent) 1119{ 1120 return Relocator::Unsupport; 1121} 1122 1123//===--------------------------------------------------------------------===// 1124// X86_64 Relocation helper function 1125//===--------------------------------------------------------------------===// 1126/// helper_DynRel - Get an relocation entry in .rela.dyn 1127static 1128Relocation& helper_DynRel_init(ResolveInfo* pSym, 1129 Fragment& pFrag, 1130 uint64_t pOffset, 1131 Relocator::Type pType, 1132 X86_64Relocator& pParent) 1133{ 1134 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 1135 Relocation& rel_entry = *ld_backend.getRelDyn().create(); 1136 rel_entry.setType(pType); 1137 rel_entry.targetRef().assign(pFrag, pOffset); 1138 if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym) 1139 rel_entry.setSymInfo(NULL); 1140 else 1141 rel_entry.setSymInfo(pSym); 1142 1143 return rel_entry; 1144} 1145 1146 1147/// helper_use_relative_reloc - Check if symbol can use relocation 1148/// R_X86_64_RELATIVE 1149static bool 1150helper_use_relative_reloc(const ResolveInfo& pSym, 1151 const X86_64Relocator& pFactory) 1152 1153{ 1154 // if symbol is dynamic or undefine or preemptible 1155 if (pSym.isDyn() || 1156 pSym.isUndef() || 1157 pFactory.getTarget().isSymbolPreemptible(pSym)) 1158 return false; 1159 return true; 1160} 1161 1162static 1163X86_64GOTEntry& helper_GOT_init(Relocation& pReloc, 1164 bool pHasRel, 1165 X86_64Relocator& pParent) 1166{ 1167 // rsym - The relocation target symbol 1168 ResolveInfo* rsym = pReloc.symInfo(); 1169 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 1170 assert(NULL == pParent.getSymGOTMap().lookUp(*rsym)); 1171 1172 X86_64GOTEntry* got_entry = ld_backend.getGOT().create(); 1173 pParent.getSymGOTMap().record(*rsym, *got_entry); 1174 1175 // If we first get this GOT entry, we should initialize it. 1176 if (!pHasRel) { 1177 // No corresponding dynamic relocation, initialize to the symbol value. 1178 got_entry->setValue(X86Relocator::SymVal); 1179 } 1180 else { 1181 // Initialize got_entry content and the corresponding dynamic relocation. 1182 if (helper_use_relative_reloc(*rsym, pParent)) { 1183 Relocation& rel_entry = helper_DynRel_init(rsym, *got_entry, 0x0, 1184 llvm::ELF::R_X86_64_RELATIVE, pParent); 1185 rel_entry.setAddend(X86Relocator::SymVal); 1186 pParent.getRelRelMap().record(pReloc, rel_entry); 1187 } 1188 else { 1189 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, 1190 pParent); 1191 } 1192 got_entry->setValue(0); 1193 } 1194 return *got_entry; 1195} 1196 1197static 1198Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) 1199{ 1200 return pParent.getTarget().getGOT().addr(); 1201} 1202 1203static 1204Relocator::Address helper_get_GOT_address(Relocation& pReloc, 1205 X86_64Relocator& pParent) 1206{ 1207 X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 1208 assert(NULL != got_entry); 1209 return got_entry->getOffset(); 1210} 1211 1212static 1213Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, 1214 X86_64Relocator& pParent) 1215{ 1216 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 1217 assert(NULL != plt_entry); 1218 return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 1219} 1220 1221static 1222PLTEntryBase& helper_PLT_init(Relocation& pReloc, X86_64Relocator& pParent) 1223{ 1224 // rsym - The relocation target symbol 1225 ResolveInfo* rsym = pReloc.symInfo(); 1226 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 1227 assert(NULL == pParent.getSymPLTMap().lookUp(*rsym)); 1228 1229 PLTEntryBase* plt_entry = ld_backend.getPLT().create(); 1230 pParent.getSymPLTMap().record(*rsym, *plt_entry); 1231 1232 // initialize plt and the corresponding gotplt and dyn rel entry. 1233 assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) && 1234 "PLT entry not exist, but DynRel entry exist!"); 1235 X86_64GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create(); 1236 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 1237 1238 // init the corresponding rel entry in .rel.plt 1239 Relocation& rel_entry = *ld_backend.getRelPLT().create(); 1240 rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT); 1241 rel_entry.targetRef().assign(*gotplt_entry); 1242 rel_entry.setSymInfo(rsym); 1243 return *plt_entry; 1244} 1245 1246//===--------------------------------------------------------------------===// 1247// X86_64 Relocation Functions and Tables 1248//===--------------------------------------------------------------------===// 1249DECL_X86_64_APPLY_RELOC_FUNCS 1250 1251/// the prototype of applying function 1252typedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc, 1253 X86_64Relocator& pParent); 1254 1255// the table entry of applying functions 1256struct X86_64ApplyFunctionTriple 1257{ 1258 X86_64ApplyFunctionType func; 1259 unsigned int type; 1260 const char* name; 1261 unsigned int size; 1262}; 1263 1264// declare the table of applying functions 1265static const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = { 1266 DECL_X86_64_APPLY_RELOC_FUNC_PTRS 1267}; 1268 1269//===--------------------------------------------------------------------===// 1270// X86_64Relocator 1271//===--------------------------------------------------------------------===// 1272X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent, 1273 const LinkerConfig& pConfig) 1274 : X86Relocator(pConfig), m_Target(pParent) { 1275} 1276 1277Relocator::Result 1278X86_64Relocator::applyRelocation(Relocation& pRelocation) 1279{ 1280 Relocation::Type type = pRelocation.type(); 1281 1282 if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) { 1283 return Unknown; 1284 } 1285 1286 // apply the relocation 1287 return X86_64ApplyFunctions[type].func(pRelocation, *this); 1288} 1289 1290const char* X86_64Relocator::getName(Relocation::Type pType) const 1291{ 1292 return X86_64ApplyFunctions[pType].name; 1293} 1294 1295Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const 1296{ 1297 return X86_64ApplyFunctions[pType].size; 1298} 1299 1300void X86_64Relocator::scanLocalReloc(Relocation& pReloc, 1301 IRBuilder& pBuilder, 1302 Module& pModule, 1303 LDSection& pSection) 1304{ 1305 // rsym - The relocation target symbol 1306 ResolveInfo* rsym = pReloc.symInfo(); 1307 1308 switch(pReloc.type()){ 1309 case llvm::ELF::R_X86_64_64: 1310 // If buiding PIC object (shared library or PIC executable), 1311 // a dynamic relocations with RELATIVE type to this location is needed. 1312 // Reserve an entry in .rela.dyn 1313 if (config().isCodeIndep()) { 1314 Relocation& reloc = helper_DynRel_init(rsym, 1315 *pReloc.targetRef().frag(), 1316 pReloc.targetRef().offset(), 1317 llvm::ELF::R_X86_64_RELATIVE, 1318 *this); 1319 getRelRelMap().record(pReloc, reloc); 1320 // set Rel bit 1321 rsym->setReserved(rsym->reserved() | ReserveRel); 1322 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1323 } 1324 return; 1325 1326 case llvm::ELF::R_X86_64_32: 1327 case llvm::ELF::R_X86_64_16: 1328 case llvm::ELF::R_X86_64_8: 1329 case llvm::ELF::R_X86_64_32S: 1330 // If buiding PIC object (shared library or PIC executable), 1331 // a dynamic relocations with RELATIVE type to this location is needed. 1332 // Reserve an entry in .rela.dyn 1333 if (config().isCodeIndep()) { 1334 Relocation& reloc = helper_DynRel_init(rsym, 1335 *pReloc.targetRef().frag(), 1336 pReloc.targetRef().offset(), 1337 pReloc.type(), 1338 *this); 1339 getRelRelMap().record(pReloc, reloc); 1340 // set Rel bit 1341 rsym->setReserved(rsym->reserved() | ReserveRel); 1342 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1343 } 1344 return; 1345 1346 case llvm::ELF::R_X86_64_PC32: 1347 case llvm::ELF::R_X86_64_PC16: 1348 case llvm::ELF::R_X86_64_PC8: 1349 return; 1350 1351 case llvm::ELF::R_X86_64_GOTPCREL: 1352 // Symbol needs GOT entry, reserve entry in .got 1353 // return if we already create GOT for this symbol 1354 if (rsym->reserved() & ReserveGOT) 1355 return; 1356 1357 // If building shared object or the symbol is undefined, a dynamic 1358 // relocation is needed to relocate this GOT entry. Reserve an 1359 // entry in .rela.dyn 1360 if (LinkerConfig::DynObj == 1361 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) 1362 helper_GOT_init(pReloc, true, *this); 1363 else 1364 helper_GOT_init(pReloc, false, *this); 1365 rsym->setReserved(rsym->reserved() | ReserveGOT); 1366 return; 1367 1368 default: 1369 fatal(diag::unsupported_relocation) << (int)pReloc.type() 1370 << "mclinker@googlegroups.com"; 1371 break; 1372 } // end switch 1373} 1374 1375void X86_64Relocator::scanGlobalReloc(Relocation& pReloc, 1376 IRBuilder& pBuilder, 1377 Module& pModule, 1378 LDSection& pSection) 1379{ 1380 // rsym - The relocation target symbol 1381 ResolveInfo* rsym = pReloc.symInfo(); 1382 1383 switch(pReloc.type()) { 1384 case llvm::ELF::R_X86_64_64: 1385 case llvm::ELF::R_X86_64_32: 1386 case llvm::ELF::R_X86_64_16: 1387 case llvm::ELF::R_X86_64_8: 1388 case llvm::ELF::R_X86_64_32S: 1389 // Absolute relocation type, symbol may needs PLT entry or 1390 // dynamic relocation entry 1391 if (getTarget().symbolNeedsPLT(*rsym)) { 1392 // create plt for this symbol if it does not have one 1393 if (!(rsym->reserved() & ReservePLT)){ 1394 // Symbol needs PLT entry, we need to reserve a PLT entry 1395 // and the corresponding GOT and dynamic relocation entry 1396 // in .got and .rela.plt. 1397 helper_PLT_init(pReloc, *this); 1398 // set PLT bit 1399 rsym->setReserved(rsym->reserved() | ReservePLT); 1400 } 1401 } 1402 1403 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 1404 true)) { 1405 // symbol needs dynamic relocation entry, set up the dynrel entry 1406 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 1407 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1408 addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1409 } 1410 else { 1411 // set Rel bit and the dyn rel 1412 rsym->setReserved(rsym->reserved() | ReserveRel); 1413 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1414 if (llvm::ELF::R_386_32 == pReloc.type() && 1415 helper_use_relative_reloc(*rsym, *this)) { 1416 Relocation& reloc = helper_DynRel_init(rsym, 1417 *pReloc.targetRef().frag(), 1418 pReloc.targetRef().offset(), 1419 llvm::ELF::R_X86_64_RELATIVE, 1420 *this); 1421 getRelRelMap().record(pReloc, reloc); 1422 } 1423 else { 1424 Relocation& reloc = helper_DynRel_init(rsym, 1425 *pReloc.targetRef().frag(), 1426 pReloc.targetRef().offset(), 1427 pReloc.type(), 1428 *this); 1429 getRelRelMap().record(pReloc, reloc); 1430 } 1431 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1432 } 1433 } 1434 return; 1435 1436 case llvm::ELF::R_X86_64_GOTPCREL: 1437 // Symbol needs GOT entry, reserve entry in .got 1438 // return if we already create GOT for this symbol 1439 if (rsym->reserved() & ReserveGOT) 1440 return; 1441 1442 // If building shared object or the symbol is undefined, a dynamic 1443 // relocation is needed to relocate this GOT entry. Reserve an 1444 // entry in .rela.dyn 1445 if (LinkerConfig::DynObj == 1446 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) 1447 helper_GOT_init(pReloc, true, *this); 1448 else 1449 helper_GOT_init(pReloc, false, *this); 1450 // set GOT bit 1451 rsym->setReserved(rsym->reserved() | ReserveGOT); 1452 return; 1453 1454 case llvm::ELF::R_X86_64_PLT32: 1455 // A PLT entry is needed when building shared library 1456 1457 // return if we already create plt for this symbol 1458 if (rsym->reserved() & ReservePLT) 1459 return; 1460 1461 // if the symbol's value can be decided at link time, then no need plt 1462 if (getTarget().symbolFinalValueIsKnown(*rsym)) 1463 return; 1464 1465 // if symbol is defined in the ouput file and it's not 1466 // preemptible, no need plt 1467 if (rsym->isDefine() && !rsym->isDyn() && 1468 !getTarget().isSymbolPreemptible(*rsym)) { 1469 return; 1470 } 1471 1472 // Symbol needs PLT entry, we need a PLT entry 1473 // and the corresponding GOT and dynamic relocation entry 1474 // in .got and .rel.plt. 1475 helper_PLT_init(pReloc, *this); 1476 // set PLT bit 1477 rsym->setReserved(rsym->reserved() | ReservePLT); 1478 return; 1479 1480 case llvm::ELF::R_X86_64_PC32: 1481 case llvm::ELF::R_X86_64_PC16: 1482 case llvm::ELF::R_X86_64_PC8: 1483 if (getTarget().symbolNeedsPLT(*rsym) && 1484 LinkerConfig::DynObj != config().codeGenType()) { 1485 // create plt for this symbol if it does not have one 1486 if (!(rsym->reserved() & ReservePLT)){ 1487 // Symbol needs PLT entry, we need a PLT entry 1488 // and the corresponding GOT and dynamic relocation entry 1489 // in .got and .rel.plt. 1490 helper_PLT_init(pReloc, *this); 1491 // set PLT bit 1492 rsym->setReserved(rsym->reserved() | ReservePLT); 1493 } 1494 } 1495 1496 // Only PC relative relocation against dynamic symbol needs a 1497 // dynamic relocation. Only dynamic copy relocation is allowed 1498 // and PC relative relocation will be resolved to the local copy. 1499 // All other dynamic relocations may lead to run-time relocation 1500 // overflow. 1501 if (getTarget().isDynamicSymbol(*rsym) && 1502 getTarget().symbolNeedsDynRel(*rsym, 1503 (rsym->reserved() & ReservePLT), 1504 false) && 1505 getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 1506 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1507 addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1508 } 1509 return; 1510 1511 default: 1512 fatal(diag::unsupported_relocation) << (int)pReloc.type() 1513 << "mclinker@googlegroups.com"; 1514 break; 1515 } // end switch 1516} 1517 1518// === 1519// 1520// === 1521// R_X86_64_NONE 1522Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) 1523{ 1524 return Relocator::OK; 1525} 1526 1527// R_X86_64_64: S + A 1528// R_X86_64_32: 1529// R_X86_64_16: 1530// R_X86_64_8 1531Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) 1532{ 1533 ResolveInfo* rsym = pReloc.symInfo(); 1534 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1535 Relocator::DWord S = pReloc.symValue(); 1536 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 1537 bool has_dyn_rel = (NULL != dyn_rel); 1538 1539 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1540 // If the flag of target section is not ALLOC, we will not scan this relocation 1541 // but perform static relocation. (e.g., applying .debug section) 1542 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1543 pReloc.target() = S + A; 1544 return Relocator::OK; 1545 } 1546 1547 // A local symbol may need RELA Type dynamic relocation 1548 if (rsym->isLocal() && has_dyn_rel) { 1549 dyn_rel->setAddend(S + A); 1550 return Relocator::OK; 1551 } 1552 1553 // An external symbol may need PLT and dynamic relocation 1554 if (!rsym->isLocal()) { 1555 if (rsym->reserved() & X86Relocator::ReservePLT) { 1556 S = helper_get_PLT_address(*rsym, pParent); 1557 } 1558 // If we generate a dynamic relocation (except R_X86_64_RELATIVE) 1559 // for a place, we should not perform static relocation on it 1560 // in order to keep the addend store in the place correct. 1561 if (has_dyn_rel) { 1562 if (llvm::ELF::R_X86_64_64 == pReloc.type() && 1563 helper_use_relative_reloc(*rsym, pParent)) { 1564 dyn_rel->setAddend(S + A); 1565 } 1566 else { 1567 dyn_rel->setAddend(A); 1568 return Relocator::OK; 1569 } 1570 } 1571 } 1572 1573 // perform static relocation 1574 pReloc.target() = S + A; 1575 return Relocator::OK; 1576} 1577 1578// R_X86_64_32S: S + A 1579Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) 1580{ 1581 ResolveInfo* rsym = pReloc.symInfo(); 1582 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1583 Relocator::DWord S = pReloc.symValue(); 1584 1585 // There should be no dynamic relocations for R_X86_64_32S. 1586 if (NULL != pParent.getRelRelMap().lookUp(pReloc)) 1587 return Relocator::BadReloc; 1588 1589 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1590 // If the flag of target section is not ALLOC, we will not scan this relocation 1591 // but perform static relocation. (e.g., applying .debug section) 1592 // An external symbol may need PLT and dynamic relocation 1593 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) && 1594 !rsym->isLocal() && rsym->reserved() & X86Relocator::ReservePLT) 1595 S = helper_get_PLT_address(*rsym, pParent); 1596 1597#if notyet 1598 // Check 32-bit signed overflow. 1599 Relocator::SWord V = S + A; 1600 if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000)) 1601 return Relocator::Overflow; 1602#endif 1603 1604 // perform static relocation 1605 pReloc.target() = S + A; 1606 return Relocator::OK; 1607} 1608 1609// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P 1610Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) 1611{ 1612 if (!(pReloc.symInfo()->reserved() & X86Relocator::ReserveGOT)) { 1613 return Relocator::BadReloc; 1614 } 1615 1616 // set symbol value of the got entry if needed 1617 X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 1618 if (X86Relocator::SymVal == got_entry->getValue()) 1619 got_entry->setValue(pReloc.symValue()); 1620 1621 // setup relocation addend if needed 1622 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 1623 if ((NULL != dyn_rel) && (X86Relocator::SymVal == dyn_rel->addend())) { 1624 dyn_rel->setAddend(pReloc.symValue()); 1625 } 1626 1627 Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent); 1628 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1629 Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 1630 // Apply relocation. 1631 pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place(); 1632 return Relocator::OK; 1633} 1634 1635// R_X86_64_PLT32: PLT(S) + A - P 1636Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) 1637{ 1638 // PLT_S depends on if there is a PLT entry. 1639 Relocator::Address PLT_S; 1640 if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 1641 PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 1642 else 1643 PLT_S = pReloc.symValue(); 1644 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1645 Relocator::Address P = pReloc.place(); 1646 pReloc.target() = PLT_S + A - P; 1647 return Relocator::OK; 1648} 1649 1650// R_X86_64_PC32: S + A - P 1651// R_X86_64_PC16 1652// R_X86_64_PC8 1653Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) 1654{ 1655 ResolveInfo* rsym = pReloc.symInfo(); 1656 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1657 Relocator::DWord S = pReloc.symValue(); 1658 Relocator::DWord P = pReloc.place(); 1659 1660 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1661 // If the flag of target section is not ALLOC, we will not scan this relocation 1662 // but perform static relocation. (e.g., applying .debug section) 1663 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1664 pReloc.target() = S + A - P; 1665 return Relocator::OK; 1666 } 1667 1668 // setup relocation addend if needed 1669 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 1670 if ((NULL != dyn_rel) && (X86Relocator::SymVal == dyn_rel->addend())) { 1671 dyn_rel->setAddend(S); 1672 } 1673 1674 // An external symbol may need PLT and dynamic relocation 1675 if (!rsym->isLocal()) { 1676 if (rsym->reserved() & X86Relocator::ReservePLT) { 1677 S = helper_get_PLT_address(*rsym, pParent); 1678 } 1679 if (pParent.getTarget().symbolNeedsDynRel( 1680 *rsym, 1681 (rsym->reserved() & X86Relocator::ReservePLT), 1682 false)) { 1683 return Relocator::Overflow; 1684 } 1685 } 1686 1687 // perform static relocation 1688 pReloc.target() = S + A - P; 1689 return Relocator::OK; 1690} 1691 1692Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent) 1693{ 1694 return Relocator::Unsupport; 1695} 1696