X86Relocator.cpp revision 87f34658dec9097d987d254a990ea7f311bfc95f
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 X86Relocator::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 99X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) 100{ 101 return pParent.getTarget().getGOTPLT().addr(); 102} 103 104static 105X86Relocator::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 139X86Relocator::Address helper_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 fragment references and new relocs 806 uint64_t off = pReloc.targetRef().offset(); 807 if (off >= 4) 808 off -= 4; 809 else 810 off = 0; 811 812 FragmentRef* fragref = FragmentRef::Create(*pReloc.targetRef().frag(), off); 813 Relocation* reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT, 814 *fragref, 815 0x0); 816 // FIXME: should we create a special symbol for the tls opt instead? 817 reloc->setSymInfo(pReloc.symInfo()); 818 819 // 2. modify the opcodes to the appropriate ones 820 uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target())); 821 off = pReloc.targetRef().offset() - reloc->targetRef().offset() - 1; 822 if (op[off] == 0xa1) { 823 op[off] = 0xb8; 824 } else { 825 switch (op[off - 1]) { 826 case 0x8b: 827 assert((op[off] & 0xc7) == 0x05); 828 op[off - 1] = 0xc7; 829 op[off] = 0xc0 | ((op[off] >> 3) & 7); 830 break; 831 case 0x03: 832 assert((op[off] & 0xc7) == 0x05); 833 op[off - 1] = 0x81; 834 op[off] = 0xc0 | ((op[off] >> 3) & 7); 835 break; 836 default: 837 assert(0); 838 break; 839 } 840 } 841 842 // 3. insert the new relocs "BEFORE" the original reloc. 843 pSection.getRelocData()->getRelocationList().insert( 844 RelocData::iterator(pReloc), reloc); 845 846 // 4. change the type of the original reloc 847 pReloc.setType(llvm::ELF::R_386_TLS_LE); 848} 849 850//================================================// 851// X86_32 Each relocation function implementation // 852//================================================// 853 854// R_386_NONE 855X86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) 856{ 857 return X86Relocator::OK; 858} 859 860// R_386_32: S + A 861// R_386_16 862// R_386_8 863X86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) 864{ 865 ResolveInfo* rsym = pReloc.symInfo(); 866 Relocator::DWord A = pReloc.target() + pReloc.addend(); 867 Relocator::DWord S = pReloc.symValue(); 868 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 869 *rsym, 870 (rsym->reserved() & X86Relocator::ReservePLT), 871 true); 872 873 874 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 875 // If the flag of target section is not ALLOC, we will not scan this relocation 876 // but perform static relocation. (e.g., applying .debug section) 877 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 878 pReloc.target() = S + A; 879 return X86Relocator::OK; 880 } 881 882 // An external symbol may need PLT and dynamic relocation 883 if (!rsym->isLocal()) { 884 if (rsym->reserved() & X86Relocator::ReservePLT) { 885 S = helper_get_PLT_address(*rsym, pParent); 886 } 887 // If we generate a dynamic relocation (except R_386_RELATIVE) 888 // for a place, we should not perform static relocation on it 889 // in order to keep the addend store in the place correct. 890 if (has_dyn_rel) 891 if (llvm::ELF::R_386_32 != pReloc.type() || 892 (!helper_use_relative_reloc(*rsym, pParent))) 893 return X86Relocator::OK; 894 } 895 896 // perform static relocation 897 pReloc.target() = S + A; 898 return X86Relocator::OK; 899} 900 901// R_386_PC32: S + A - P 902// R_386_PC16 903// R_386_PC8 904X86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) 905{ 906 ResolveInfo* rsym = pReloc.symInfo(); 907 Relocator::DWord A = pReloc.target() + pReloc.addend(); 908 Relocator::DWord S = pReloc.symValue(); 909 Relocator::DWord P = pReloc.place(); 910 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 911 *rsym, 912 (rsym->reserved() & X86Relocator::ReservePLT), 913 true); 914 915 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 916 // If the flag of target section is not ALLOC, we will not scan this relocation 917 // but perform static relocation. (e.g., applying .debug section) 918 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 919 pReloc.target() = S + A - P; 920 return X86Relocator::OK; 921 } 922 923 // An external symbol may need PLT and dynamic relocation 924 if (!rsym->isLocal()) { 925 if (rsym->reserved() & X86Relocator::ReservePLT) { 926 S = helper_get_PLT_address(*rsym, pParent); 927 pReloc.target() = S + A - P; 928 } 929 if (has_dyn_rel) 930 if (!helper_use_relative_reloc(*rsym, pParent)) 931 return X86Relocator::OK; 932 } 933 934 // perform static relocation 935 pReloc.target() = S + A - P; 936 return X86Relocator::OK; 937} 938 939// R_386_GOTOFF: S + A - GOT_ORG 940X86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) 941{ 942 Relocator::DWord A = pReloc.target() + pReloc.addend(); 943 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 944 X86Relocator::Address S = pReloc.symValue(); 945 946 pReloc.target() = S + A - GOT_ORG; 947 return X86Relocator::OK; 948} 949 950// R_386_GOTPC: GOT_ORG + A - P 951X86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) 952{ 953 Relocator::DWord A = pReloc.target() + pReloc.addend(); 954 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 955 // Apply relocation. 956 pReloc.target() = GOT_ORG + A - pReloc.place(); 957 return X86Relocator::OK; 958} 959 960// R_386_GOT32: GOT(S) + A - GOT_ORG 961X86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) 962{ 963 ResolveInfo* rsym = pReloc.symInfo(); 964 if (!(rsym->reserved() & (X86Relocator::ReserveGOT))) 965 return X86Relocator::BadReloc; 966 967 // set up got entry value if the got has no dyn rel or 968 // the dyn rel is RELATIVE 969 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 970 assert(NULL != got_entry); 971 if (got_entry->getValue() == X86Relocator::SymVal) 972 got_entry->setValue(pReloc.symValue()); 973 974 X86Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent); 975 Relocator::DWord A = pReloc.target() + pReloc.addend(); 976 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 977 // Apply relocation. 978 pReloc.target() = GOT_S + A - GOT_ORG; 979 return X86Relocator::OK; 980} 981 982// R_386_PLT32: PLT(S) + A - P 983X86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) 984{ 985 // PLT_S depends on if there is a PLT entry. 986 X86Relocator::Address PLT_S; 987 if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 988 PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 989 else 990 PLT_S = pReloc.symValue(); 991 Relocator::DWord A = pReloc.target() + pReloc.addend(); 992 X86Relocator::Address P = pReloc.place(); 993 pReloc.target() = PLT_S + A - P; 994 return X86Relocator::OK; 995} 996 997// R_386_TLS_GD: 998X86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) 999{ 1000 // global-dynamic 1001 ResolveInfo* rsym = pReloc.symInfo(); 1002 // must reserve two pairs of got and dynamic relocation 1003 if (!(rsym->reserved() & X86Relocator::ReserveGOT)) 1004 return X86Relocator::BadReloc; 1005 1006 ELFFileFormat* file_format = pParent.getTarget().getOutputFormat(); 1007 // setup corresponding got and dynamic relocatio entries: 1008 // get first got entry, if there is already a got entry for rsym, then apply 1009 // this relocation to the got entry directly. If not, setup the corresponding 1010 // got and dyn relocation entries 1011 X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUpFirstEntry(*rsym); 1012 1013 // set the got_entry2 value to symbol value 1014 if (rsym->isLocal()) 1015 pParent.getSymGOTMap().lookUpSecondEntry(*rsym)->setValue(pReloc.symValue()); 1016 1017 // perform relocation to the first got entry 1018 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1019 // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the 1020 // .got.plt section) 1021 X86Relocator::Address GOT_OFF = 1022 file_format->getGOT().addr() + 1023 got_entry1->getOffset() - 1024 file_format->getGOTPLT().addr(); 1025 pReloc.target() = GOT_OFF + A; 1026 return X86Relocator::OK; 1027} 1028 1029// R_386_TLS_LDM 1030X86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) 1031{ 1032 // FIXME: no linker optimization for TLS relocation 1033 const X86_32GOTEntry& got_entry = pParent.getTLSModuleID(); 1034 1035 // All GOT offsets are relative to the end of the GOT. 1036 X86Relocator::SWord GOT_S = got_entry.getOffset() - 1037 (pParent.getTarget().getGOTPLT().addr() - 1038 pParent.getTarget().getGOT().addr()); 1039 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1040 pReloc.target() = GOT_S + A; 1041 1042 return X86Relocator::OK; 1043} 1044 1045// R_386_TLS_LDO_32 1046X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) 1047{ 1048 // FIXME: no linker optimization for TLS relocation 1049 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1050 X86Relocator::Address S = pReloc.symValue(); 1051 pReloc.target() = S + A; 1052 return X86Relocator::OK; 1053} 1054 1055// R_X86_TLS_IE 1056X86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) 1057{ 1058 ResolveInfo* rsym = pReloc.symInfo(); 1059 if (!(rsym->reserved() & X86Relocator::ReserveGOT)) { 1060 return X86Relocator::BadReloc; 1061 } 1062 1063 // set up the got and dynamic relocation entries if not exist 1064 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 1065 assert(NULL != got_entry); 1066 // perform relocation to the absolute address of got_entry 1067 X86Relocator::Address GOT_S = 1068 pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 1069 1070 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1071 pReloc.target() = GOT_S + A; 1072 1073 return X86Relocator::OK; 1074} 1075 1076// R_386_TLS_GOTIE 1077X86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) 1078{ 1079 ResolveInfo* rsym = pReloc.symInfo(); 1080 if (!(rsym->reserved() & X86Relocator::ReserveGOT)) { 1081 return X86Relocator::BadReloc; 1082 } 1083 1084 // set up the got and dynamic relocation entries if not exist 1085 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 1086 assert(NULL != got_entry); 1087 1088 // All GOT offsets are relative to the end of the GOT. 1089 X86Relocator::SWord GOT_S = got_entry->getOffset() - 1090 (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr()); 1091 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1092 pReloc.target() = GOT_S + A; 1093 1094 return X86Relocator::OK; 1095} 1096 1097// R_X86_TLS_LE 1098X86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) 1099{ 1100 if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) 1101 return X86Relocator::OK; 1102 1103 // perform static relocation 1104 // get TLS segment 1105 ELFSegmentFactory::const_iterator tls_seg = 1106 pParent.getTarget().elfSegmentTable().find(llvm::ELF::PT_TLS, 1107 llvm::ELF::PF_R, 1108 0x0); 1109 assert(tls_seg != pParent.getTarget().elfSegmentTable().end()); 1110 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1111 X86Relocator::Address S = pReloc.symValue(); 1112 pReloc.target() = S + A - (*tls_seg)->memsz(); 1113 return X86Relocator::OK; 1114} 1115 1116X86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent) 1117{ 1118 return X86Relocator::Unsupport; 1119} 1120 1121//===--------------------------------------------------------------------===// 1122// X86_64 Relocation helper function 1123//===--------------------------------------------------------------------===// 1124/// helper_DynRel - Get an relocation entry in .rela.dyn 1125static 1126Relocation& helper_DynRel_init(ResolveInfo* pSym, 1127 Fragment& pFrag, 1128 uint64_t pOffset, 1129 X86Relocator::Type pType, 1130 X86_64Relocator& pParent) 1131{ 1132 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 1133 Relocation& rel_entry = *ld_backend.getRelDyn().create(); 1134 rel_entry.setType(pType); 1135 rel_entry.targetRef().assign(pFrag, pOffset); 1136 if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym) 1137 rel_entry.setSymInfo(NULL); 1138 else 1139 rel_entry.setSymInfo(pSym); 1140 1141 return rel_entry; 1142} 1143 1144 1145/// helper_use_relative_reloc - Check if symbol can use relocation 1146/// R_X86_64_RELATIVE 1147static bool 1148helper_use_relative_reloc(const ResolveInfo& pSym, 1149 const X86_64Relocator& pFactory) 1150 1151{ 1152 // if symbol is dynamic or undefine or preemptible 1153 if (pSym.isDyn() || 1154 pSym.isUndef() || 1155 pFactory.getTarget().isSymbolPreemptible(pSym)) 1156 return false; 1157 return true; 1158} 1159 1160static 1161X86_64GOTEntry& helper_GOT_init(Relocation& pReloc, 1162 bool pHasRel, 1163 X86_64Relocator& pParent) 1164{ 1165 // rsym - The relocation target symbol 1166 ResolveInfo* rsym = pReloc.symInfo(); 1167 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 1168 assert(NULL == pParent.getSymGOTMap().lookUp(*rsym)); 1169 1170 X86_64GOTEntry* got_entry = ld_backend.getGOT().create(); 1171 pParent.getSymGOTMap().record(*rsym, *got_entry); 1172 1173 // If we first get this GOT entry, we should initialize it. 1174 if (!pHasRel) { 1175 // No corresponding dynamic relocation, initialize to the symbol value. 1176 got_entry->setValue(X86Relocator::SymVal); 1177 } 1178 else { 1179 // Initialize got_entry content and the corresponding dynamic relocation. 1180 if (helper_use_relative_reloc(*rsym, pParent)) { 1181 Relocation& rel_entry = helper_DynRel_init(rsym, *got_entry, 0x0, 1182 llvm::ELF::R_X86_64_RELATIVE, pParent); 1183 rel_entry.setAddend(X86Relocator::SymVal); 1184 pParent.getRelRelMap().record(pReloc, rel_entry); 1185 } 1186 else { 1187 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, 1188 pParent); 1189 } 1190 got_entry->setValue(0); 1191 } 1192 return *got_entry; 1193} 1194 1195static 1196X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) 1197{ 1198 return pParent.getTarget().getGOT().addr(); 1199} 1200 1201static 1202X86Relocator::Address helper_get_GOT_address(Relocation& pReloc, 1203 X86_64Relocator& pParent) 1204{ 1205 X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 1206 assert(NULL != got_entry); 1207 return got_entry->getOffset(); 1208} 1209 1210static 1211X86Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, 1212 X86_64Relocator& pParent) 1213{ 1214 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 1215 assert(NULL != plt_entry); 1216 return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 1217} 1218 1219static 1220PLTEntryBase& helper_PLT_init(Relocation& pReloc, X86_64Relocator& pParent) 1221{ 1222 // rsym - The relocation target symbol 1223 ResolveInfo* rsym = pReloc.symInfo(); 1224 X86_64GNULDBackend& ld_backend = pParent.getTarget(); 1225 assert(NULL == pParent.getSymPLTMap().lookUp(*rsym)); 1226 1227 PLTEntryBase* plt_entry = ld_backend.getPLT().create(); 1228 pParent.getSymPLTMap().record(*rsym, *plt_entry); 1229 1230 // initialize plt and the corresponding gotplt and dyn rel entry. 1231 assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) && 1232 "PLT entry not exist, but DynRel entry exist!"); 1233 X86_64GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create(); 1234 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 1235 1236 // init the corresponding rel entry in .rel.plt 1237 Relocation& rel_entry = *ld_backend.getRelPLT().create(); 1238 rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT); 1239 rel_entry.targetRef().assign(*gotplt_entry); 1240 rel_entry.setSymInfo(rsym); 1241 return *plt_entry; 1242} 1243 1244//===--------------------------------------------------------------------===// 1245// X86_64 Relocation Functions and Tables 1246//===--------------------------------------------------------------------===// 1247DECL_X86_64_APPLY_RELOC_FUNCS 1248 1249/// the prototype of applying function 1250typedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc, 1251 X86_64Relocator& pParent); 1252 1253// the table entry of applying functions 1254struct X86_64ApplyFunctionTriple 1255{ 1256 X86_64ApplyFunctionType func; 1257 unsigned int type; 1258 const char* name; 1259 unsigned int size; 1260}; 1261 1262// declare the table of applying functions 1263static const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = { 1264 DECL_X86_64_APPLY_RELOC_FUNC_PTRS 1265}; 1266 1267//===--------------------------------------------------------------------===// 1268// X86_64Relocator 1269//===--------------------------------------------------------------------===// 1270X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent, 1271 const LinkerConfig& pConfig) 1272 : X86Relocator(pConfig), m_Target(pParent) { 1273} 1274 1275Relocator::Result 1276X86_64Relocator::applyRelocation(Relocation& pRelocation) 1277{ 1278 Relocation::Type type = pRelocation.type(); 1279 1280 if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) { 1281 return Unknown; 1282 } 1283 1284 // apply the relocation 1285 return X86_64ApplyFunctions[type].func(pRelocation, *this); 1286} 1287 1288const char* X86_64Relocator::getName(Relocation::Type pType) const 1289{ 1290 return X86_64ApplyFunctions[pType].name; 1291} 1292 1293Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const 1294{ 1295 return X86_64ApplyFunctions[pType].size; 1296} 1297 1298void X86_64Relocator::scanLocalReloc(Relocation& pReloc, 1299 IRBuilder& pBuilder, 1300 Module& pModule, 1301 LDSection& pSection) 1302{ 1303 // rsym - The relocation target symbol 1304 ResolveInfo* rsym = pReloc.symInfo(); 1305 1306 switch(pReloc.type()){ 1307 case llvm::ELF::R_X86_64_64: 1308 // If buiding PIC object (shared library or PIC executable), 1309 // a dynamic relocations with RELATIVE type to this location is needed. 1310 // Reserve an entry in .rela.dyn 1311 if (config().isCodeIndep()) { 1312 Relocation& reloc = helper_DynRel_init(rsym, 1313 *pReloc.targetRef().frag(), 1314 pReloc.targetRef().offset(), 1315 llvm::ELF::R_X86_64_RELATIVE, 1316 *this); 1317 getRelRelMap().record(pReloc, reloc); 1318 // set Rel bit 1319 rsym->setReserved(rsym->reserved() | ReserveRel); 1320 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1321 } 1322 return; 1323 1324 case llvm::ELF::R_X86_64_32: 1325 case llvm::ELF::R_X86_64_16: 1326 case llvm::ELF::R_X86_64_8: 1327 case llvm::ELF::R_X86_64_32S: 1328 // If buiding PIC object (shared library or PIC executable), 1329 // a dynamic relocations with RELATIVE type to this location is needed. 1330 // Reserve an entry in .rela.dyn 1331 if (config().isCodeIndep()) { 1332 Relocation& reloc = helper_DynRel_init(rsym, 1333 *pReloc.targetRef().frag(), 1334 pReloc.targetRef().offset(), 1335 pReloc.type(), 1336 *this); 1337 getRelRelMap().record(pReloc, reloc); 1338 // set Rel bit 1339 rsym->setReserved(rsym->reserved() | ReserveRel); 1340 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1341 } 1342 return; 1343 1344 case llvm::ELF::R_X86_64_PC32: 1345 case llvm::ELF::R_X86_64_PC16: 1346 case llvm::ELF::R_X86_64_PC8: 1347 return; 1348 1349 case llvm::ELF::R_X86_64_GOTPCREL: 1350 // Symbol needs GOT entry, reserve entry in .got 1351 // return if we already create GOT for this symbol 1352 if (rsym->reserved() & ReserveGOT) 1353 return; 1354 1355 // If building shared object or the symbol is undefined, a dynamic 1356 // relocation is needed to relocate this GOT entry. Reserve an 1357 // entry in .rela.dyn 1358 if (LinkerConfig::DynObj == 1359 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) 1360 helper_GOT_init(pReloc, true, *this); 1361 else 1362 helper_GOT_init(pReloc, false, *this); 1363 rsym->setReserved(rsym->reserved() | ReserveGOT); 1364 return; 1365 1366 default: 1367 fatal(diag::unsupported_relocation) << (int)pReloc.type() 1368 << "mclinker@googlegroups.com"; 1369 break; 1370 } // end switch 1371} 1372 1373void X86_64Relocator::scanGlobalReloc(Relocation& pReloc, 1374 IRBuilder& pBuilder, 1375 Module& pModule, 1376 LDSection& pSection) 1377{ 1378 // rsym - The relocation target symbol 1379 ResolveInfo* rsym = pReloc.symInfo(); 1380 1381 switch(pReloc.type()) { 1382 case llvm::ELF::R_X86_64_64: 1383 case llvm::ELF::R_X86_64_32: 1384 case llvm::ELF::R_X86_64_16: 1385 case llvm::ELF::R_X86_64_8: 1386 case llvm::ELF::R_X86_64_32S: 1387 // Absolute relocation type, symbol may needs PLT entry or 1388 // dynamic relocation entry 1389 if (getTarget().symbolNeedsPLT(*rsym)) { 1390 // create plt for this symbol if it does not have one 1391 if (!(rsym->reserved() & ReservePLT)){ 1392 // Symbol needs PLT entry, we need to reserve a PLT entry 1393 // and the corresponding GOT and dynamic relocation entry 1394 // in .got and .rela.plt. 1395 helper_PLT_init(pReloc, *this); 1396 // set PLT bit 1397 rsym->setReserved(rsym->reserved() | ReservePLT); 1398 } 1399 } 1400 1401 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 1402 true)) { 1403 // symbol needs dynamic relocation entry, set up the dynrel entry 1404 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 1405 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1406 addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1407 } 1408 else { 1409 // set Rel bit and the dyn rel 1410 rsym->setReserved(rsym->reserved() | ReserveRel); 1411 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1412 if (llvm::ELF::R_386_32 == pReloc.type() && 1413 helper_use_relative_reloc(*rsym, *this)) { 1414 Relocation& reloc = helper_DynRel_init(rsym, 1415 *pReloc.targetRef().frag(), 1416 pReloc.targetRef().offset(), 1417 llvm::ELF::R_X86_64_RELATIVE, 1418 *this); 1419 getRelRelMap().record(pReloc, reloc); 1420 } 1421 else { 1422 Relocation& reloc = helper_DynRel_init(rsym, 1423 *pReloc.targetRef().frag(), 1424 pReloc.targetRef().offset(), 1425 pReloc.type(), 1426 *this); 1427 getRelRelMap().record(pReloc, reloc); 1428 } 1429 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1430 } 1431 } 1432 return; 1433 1434 case llvm::ELF::R_X86_64_GOTPCREL: 1435 // Symbol needs GOT entry, reserve entry in .got 1436 // return if we already create GOT for this symbol 1437 if (rsym->reserved() & ReserveGOT) 1438 return; 1439 1440 // If building shared object or the symbol is undefined, a dynamic 1441 // relocation is needed to relocate this GOT entry. Reserve an 1442 // entry in .rela.dyn 1443 if (LinkerConfig::DynObj == 1444 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) 1445 helper_GOT_init(pReloc, true, *this); 1446 else 1447 helper_GOT_init(pReloc, false, *this); 1448 // set GOT bit 1449 rsym->setReserved(rsym->reserved() | ReserveGOT); 1450 return; 1451 1452 case llvm::ELF::R_X86_64_PLT32: 1453 // A PLT entry is needed when building shared library 1454 1455 // return if we already create plt for this symbol 1456 if (rsym->reserved() & ReservePLT) 1457 return; 1458 1459 // if the symbol's value can be decided at link time, then no need plt 1460 if (getTarget().symbolFinalValueIsKnown(*rsym)) 1461 return; 1462 1463 // if symbol is defined in the ouput file and it's not 1464 // preemptible, no need plt 1465 if (rsym->isDefine() && !rsym->isDyn() && 1466 !getTarget().isSymbolPreemptible(*rsym)) { 1467 return; 1468 } 1469 1470 // Symbol needs PLT entry, we need a PLT entry 1471 // and the corresponding GOT and dynamic relocation entry 1472 // in .got and .rel.plt. 1473 helper_PLT_init(pReloc, *this); 1474 // set PLT bit 1475 rsym->setReserved(rsym->reserved() | ReservePLT); 1476 return; 1477 1478 case llvm::ELF::R_X86_64_PC32: 1479 case llvm::ELF::R_X86_64_PC16: 1480 case llvm::ELF::R_X86_64_PC8: 1481 if (getTarget().symbolNeedsPLT(*rsym) && 1482 LinkerConfig::DynObj != config().codeGenType()) { 1483 // create plt for this symbol if it does not have one 1484 if (!(rsym->reserved() & ReservePLT)){ 1485 // Symbol needs PLT entry, we need a PLT entry 1486 // and the corresponding GOT and dynamic relocation entry 1487 // in .got and .rel.plt. 1488 helper_PLT_init(pReloc, *this); 1489 // set PLT bit 1490 rsym->setReserved(rsym->reserved() | ReservePLT); 1491 } 1492 } 1493 1494 // Only PC relative relocation against dynamic symbol needs a 1495 // dynamic relocation. Only dynamic copy relocation is allowed 1496 // and PC relative relocation will be resolved to the local copy. 1497 // All other dynamic relocations may lead to run-time relocation 1498 // overflow. 1499 if (getTarget().isDynamicSymbol(*rsym) && 1500 getTarget().symbolNeedsDynRel(*rsym, 1501 (rsym->reserved() & ReservePLT), 1502 false) && 1503 getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 1504 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1505 addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1506 } 1507 return; 1508 1509 default: 1510 fatal(diag::unsupported_relocation) << (int)pReloc.type() 1511 << "mclinker@googlegroups.com"; 1512 break; 1513 } // end switch 1514} 1515 1516// === 1517// 1518// === 1519// R_X86_64_NONE 1520X86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) 1521{ 1522 return X86Relocator::OK; 1523} 1524 1525// R_X86_64_64: S + A 1526// R_X86_64_32: 1527// R_X86_64_16: 1528// R_X86_64_8 1529X86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) 1530{ 1531 ResolveInfo* rsym = pReloc.symInfo(); 1532 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1533 Relocator::DWord S = pReloc.symValue(); 1534 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 1535 bool has_dyn_rel = (NULL != dyn_rel); 1536 1537 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1538 // If the flag of target section is not ALLOC, we will not scan this relocation 1539 // but perform static relocation. (e.g., applying .debug section) 1540 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1541 pReloc.target() = S + A; 1542 return X86Relocator::OK; 1543 } 1544 1545 // A local symbol may need RELA Type dynamic relocation 1546 if (rsym->isLocal() && has_dyn_rel) { 1547 dyn_rel->setAddend(S + A); 1548 return X86Relocator::OK; 1549 } 1550 1551 // An external symbol may need PLT and dynamic relocation 1552 if (!rsym->isLocal()) { 1553 if (rsym->reserved() & X86Relocator::ReservePLT) { 1554 S = helper_get_PLT_address(*rsym, pParent); 1555 } 1556 // If we generate a dynamic relocation (except R_X86_64_RELATIVE) 1557 // for a place, we should not perform static relocation on it 1558 // in order to keep the addend store in the place correct. 1559 if (has_dyn_rel) { 1560 if (llvm::ELF::R_X86_64_64 == pReloc.type() && 1561 helper_use_relative_reloc(*rsym, pParent)) { 1562 dyn_rel->setAddend(S + A); 1563 } 1564 else { 1565 dyn_rel->setAddend(A); 1566 return X86Relocator::OK; 1567 } 1568 } 1569 } 1570 1571 // perform static relocation 1572 pReloc.target() = S + A; 1573 return X86Relocator::OK; 1574} 1575 1576// R_X86_64_32S: S + A 1577X86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) 1578{ 1579 ResolveInfo* rsym = pReloc.symInfo(); 1580 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1581 Relocator::DWord S = pReloc.symValue(); 1582 1583 // There should be no dynamic relocations for R_X86_64_32S. 1584 if (NULL != pParent.getRelRelMap().lookUp(pReloc)) 1585 return X86Relocator::BadReloc; 1586 1587 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1588 // If the flag of target section is not ALLOC, we will not scan this relocation 1589 // but perform static relocation. (e.g., applying .debug section) 1590 // An external symbol may need PLT and dynamic relocation 1591 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) && 1592 !rsym->isLocal() && rsym->reserved() & X86Relocator::ReservePLT) 1593 S = helper_get_PLT_address(*rsym, pParent); 1594 1595#if notyet 1596 // Check 32-bit signed overflow. 1597 Relocator::SWord V = S + A; 1598 if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000)) 1599 return X86Relocator::Overflow; 1600#endif 1601 1602 // perform static relocation 1603 pReloc.target() = S + A; 1604 return X86Relocator::OK; 1605} 1606 1607// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P 1608X86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) 1609{ 1610 if (!(pReloc.symInfo()->reserved() & X86Relocator::ReserveGOT)) { 1611 return X86Relocator::BadReloc; 1612 } 1613 1614 // set symbol value of the got entry if needed 1615 X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 1616 if (X86Relocator::SymVal == got_entry->getValue()) 1617 got_entry->setValue(pReloc.symValue()); 1618 1619 // setup relocation addend if needed 1620 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 1621 if ((NULL != dyn_rel) && (X86Relocator::SymVal == dyn_rel->addend())) { 1622 dyn_rel->setAddend(pReloc.symValue()); 1623 } 1624 1625 X86Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent); 1626 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1627 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 1628 // Apply relocation. 1629 pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place(); 1630 return X86Relocator::OK; 1631} 1632 1633// R_X86_64_PLT32: PLT(S) + A - P 1634X86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) 1635{ 1636 // PLT_S depends on if there is a PLT entry. 1637 X86Relocator::Address PLT_S; 1638 if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 1639 PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 1640 else 1641 PLT_S = pReloc.symValue(); 1642 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1643 X86Relocator::Address P = pReloc.place(); 1644 pReloc.target() = PLT_S + A - P; 1645 return X86Relocator::OK; 1646} 1647 1648// R_X86_64_PC32: S + A - P 1649// R_X86_64_PC16 1650// R_X86_64_PC8 1651X86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) 1652{ 1653 ResolveInfo* rsym = pReloc.symInfo(); 1654 Relocator::DWord A = pReloc.target() + pReloc.addend(); 1655 Relocator::DWord S = pReloc.symValue(); 1656 Relocator::DWord P = pReloc.place(); 1657 1658 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1659 // If the flag of target section is not ALLOC, we will not scan this relocation 1660 // but perform static relocation. (e.g., applying .debug section) 1661 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1662 pReloc.target() = S + A - P; 1663 return X86Relocator::OK; 1664 } 1665 1666 // setup relocation addend if needed 1667 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 1668 if ((NULL != dyn_rel) && (X86Relocator::SymVal == dyn_rel->addend())) { 1669 dyn_rel->setAddend(S); 1670 } 1671 1672 // An external symbol may need PLT and dynamic relocation 1673 if (!rsym->isLocal()) { 1674 if (rsym->reserved() & X86Relocator::ReservePLT) { 1675 S = helper_get_PLT_address(*rsym, pParent); 1676 } 1677 if (pParent.getTarget().symbolNeedsDynRel( 1678 *rsym, 1679 (rsym->reserved() & X86Relocator::ReservePLT), 1680 false)) { 1681 return X86Relocator::Overflow; 1682 } 1683 } 1684 1685 // perform static relocation 1686 pReloc.target() = S + A - P; 1687 return X86Relocator::OK; 1688} 1689 1690X86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent) 1691{ 1692 return X86Relocator::Unsupport; 1693} 1694