X86LDBackend.cpp revision 0dea6bc96bb52346737966839ac68644f7939f58
1//===- X86LDBackend.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 "X86.h" 10#include "X86ELFDynamic.h" 11#include "X86LDBackend.h" 12#include "X86Relocator.h" 13#include "X86GNUInfo.h" 14 15#include <llvm/ADT/StringRef.h> 16#include <llvm/ADT/Triple.h> 17#include <llvm/Support/Casting.h> 18 19#include <mcld/LinkerConfig.h> 20#include <mcld/IRBuilder.h> 21#include <mcld/LD/ELFFileFormat.h> 22#include <mcld/Fragment/FillFragment.h> 23#include <mcld/Fragment/RegionFragment.h> 24#include <mcld/Support/MsgHandling.h> 25#include <mcld/Support/TargetRegistry.h> 26#include <mcld/Object/ObjectBuilder.h> 27#include <llvm/Support/Dwarf.h> 28 29#include <cstring> 30 31using namespace mcld; 32 33//===----------------------------------------------------------------------===// 34// X86GNULDBackend 35//===----------------------------------------------------------------------===// 36X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig, 37 GNUInfo* pInfo, 38 Relocation::Type pCopyRel) 39 : GNULDBackend(pConfig, pInfo), 40 m_pRelocator(NULL), 41 m_pPLT(NULL), 42 m_pRelDyn(NULL), 43 m_pRelPLT(NULL), 44 m_pDynamic(NULL), 45 m_pGOTSymbol(NULL), 46 m_CopyRel(pCopyRel) 47{ 48 llvm::Triple::ArchType arch = pConfig.targets().triple().getArch(); 49 assert (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64); 50 if (arch == llvm::Triple::x86 || 51 pConfig.targets().triple().getEnvironment() == llvm::Triple::GNUX32) { 52 m_RelEntrySize = 8; 53 m_RelaEntrySize = 12; 54 if (arch == llvm::Triple::x86) 55 m_PointerRel = llvm::ELF::R_386_32; 56 else 57 m_PointerRel = llvm::ELF::R_X86_64_32; 58 } 59 else { 60 m_RelEntrySize = 16; 61 m_RelaEntrySize = 24; 62 m_PointerRel = llvm::ELF::R_X86_64_64; 63 } 64} 65 66X86GNULDBackend::~X86GNULDBackend() 67{ 68 delete m_pRelocator; 69 delete m_pPLT; 70 delete m_pRelDyn; 71 delete m_pRelPLT; 72 delete m_pDynamic; 73} 74 75const Relocator* X86GNULDBackend::getRelocator() const 76{ 77 assert(NULL != m_pRelocator); 78 return m_pRelocator; 79} 80 81Relocator* X86GNULDBackend::getRelocator() 82{ 83 assert(NULL != m_pRelocator); 84 return m_pRelocator; 85} 86 87void X86GNULDBackend::doPreLayout(IRBuilder& pBuilder) 88{ 89 // initialize .dynamic data 90 if (!config().isCodeStatic() && NULL == m_pDynamic) 91 m_pDynamic = new X86ELFDynamic(*this, config()); 92 93 // set .got.plt and .got sizes 94 // when building shared object, the .got section is must 95 if (LinkerConfig::Object != config().codeGenType()) { 96 setGOTSectionSize(pBuilder); 97 98 // set .plt size 99 if (m_pPLT->hasPLT1()) 100 m_pPLT->finalizeSectionSize(); 101 102 // set .rel.dyn/.rela.dyn size 103 if (!m_pRelDyn->empty()) { 104 assert(!config().isCodeStatic() && 105 "static linkage should not result in a dynamic relocation section"); 106 setRelDynSize(); 107 } 108 // set .rel.plt/.rela.plt size 109 if (!m_pRelPLT->empty()) { 110 assert(!config().isCodeStatic() && 111 "static linkage should not result in a dynamic relocation section"); 112 setRelPLTSize(); 113 } 114 } 115 116 if (config().options().genUnwindInfo()) 117 addEhFrameForPLT(pBuilder.getModule()); 118} 119 120void X86GNULDBackend::doPostLayout(Module& pModule, 121 IRBuilder& pBuilder) 122{ 123} 124 125/// dynamic - the dynamic section of the target machine. 126/// Use co-variant return type to return its own dynamic section. 127X86ELFDynamic& X86GNULDBackend::dynamic() 128{ 129 assert(NULL != m_pDynamic); 130 return *m_pDynamic; 131} 132 133/// dynamic - the dynamic section of the target machine. 134/// Use co-variant return type to return its own dynamic section. 135const X86ELFDynamic& X86GNULDBackend::dynamic() const 136{ 137 assert(NULL != m_pDynamic); 138 return *m_pDynamic; 139} 140 141void X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder, Fragment& pFrag) 142{ 143 // define symbol _GLOBAL_OFFSET_TABLE_ 144 if (m_pGOTSymbol != NULL) { 145 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 146 "_GLOBAL_OFFSET_TABLE_", 147 ResolveInfo::Object, 148 ResolveInfo::Define, 149 ResolveInfo::Local, 150 0x0, // size 151 0x0, // value 152 FragmentRef::Create(pFrag, 0x0), 153 ResolveInfo::Hidden); 154 } 155 else { 156 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 157 "_GLOBAL_OFFSET_TABLE_", 158 ResolveInfo::Object, 159 ResolveInfo::Define, 160 ResolveInfo::Local, 161 0x0, // size 162 0x0, // value 163 FragmentRef::Create(pFrag, 0x0), 164 ResolveInfo::Hidden); 165 } 166} 167 168uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection, 169 MemoryRegion& pRegion) const 170{ 171 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 172 173 const ELFFileFormat* FileFormat = getOutputFormat(); 174 assert(FileFormat && 175 "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!"); 176 177 unsigned int EntrySize = 0; 178 uint64_t RegionSize = 0; 179 180 if (FileFormat->hasPLT() && (&pSection == &(FileFormat->getPLT()))) { 181 unsigned char* buffer = pRegion.begin(); 182 183 m_pPLT->applyPLT0(); 184 m_pPLT->applyPLT1(); 185 X86PLT::iterator it = m_pPLT->begin(); 186 unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size(); 187 188 memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size); 189 RegionSize += plt0_size; 190 ++it; 191 192 PLTEntryBase* plt1 = 0; 193 X86PLT::iterator ie = m_pPLT->end(); 194 while (it != ie) { 195 plt1 = &(llvm::cast<PLTEntryBase>(*it)); 196 EntrySize = plt1->size(); 197 memcpy(buffer + RegionSize, plt1->getValue(), EntrySize); 198 RegionSize += EntrySize; 199 ++it; 200 } 201 } 202 else if (FileFormat->hasGOT() && (&pSection == &(FileFormat->getGOT()))) { 203 RegionSize += emitGOTSectionData(pRegion); 204 } 205 else if (FileFormat->hasGOTPLT() && 206 (&pSection == &(FileFormat->getGOTPLT()))) { 207 RegionSize += emitGOTPLTSectionData(pRegion, FileFormat); 208 } 209 else { 210 fatal(diag::unrecognized_output_sectoin) 211 << pSection.name() 212 << "mclinker@googlegroups.com"; 213 } 214 return RegionSize; 215} 216 217X86PLT& X86GNULDBackend::getPLT() 218{ 219 assert(NULL != m_pPLT && "PLT section not exist"); 220 return *m_pPLT; 221} 222 223const X86PLT& X86GNULDBackend::getPLT() const 224{ 225 assert(NULL != m_pPLT && "PLT section not exist"); 226 return *m_pPLT; 227} 228 229OutputRelocSection& X86GNULDBackend::getRelDyn() 230{ 231 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 232 return *m_pRelDyn; 233} 234 235const OutputRelocSection& X86GNULDBackend::getRelDyn() const 236{ 237 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 238 return *m_pRelDyn; 239} 240 241OutputRelocSection& X86GNULDBackend::getRelPLT() 242{ 243 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 244 return *m_pRelPLT; 245} 246 247const OutputRelocSection& X86GNULDBackend::getRelPLT() const 248{ 249 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 250 return *m_pRelPLT; 251} 252 253unsigned int 254X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const 255{ 256 const ELFFileFormat* file_format = getOutputFormat(); 257 258 if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) { 259 if (config().options().hasNow()) 260 return SHO_RELRO; 261 return SHO_RELRO_LAST; 262 } 263 264 if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) { 265 if (config().options().hasNow()) 266 return SHO_RELRO; 267 return SHO_NON_RELRO_FIRST; 268 } 269 270 if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT())) 271 return SHO_PLT; 272 273 return SHO_UNDEFINED; 274} 275 276void X86GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) 277{ 278 if (LinkerConfig::Object != config().codeGenType()) { 279 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 280 // same name in input 281 m_pGOTSymbol = 282 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 283 "_GLOBAL_OFFSET_TABLE_", 284 ResolveInfo::Object, 285 ResolveInfo::Define, 286 ResolveInfo::Local, 287 0x0, // size 288 0x0, // value 289 FragmentRef::Null(), // FragRef 290 ResolveInfo::Hidden); 291 } 292} 293 294void X86GNULDBackend::addEhFrameForPLT(Module& pModule) 295{ 296 LDSection* plt_sect = pModule.getSection(".plt"); 297 if (!plt_sect || plt_sect->size() == 0u) 298 return; 299 300 LDSection* eh_sect = pModule.getSection(".eh_frame"); 301 if (!eh_sect || !eh_sect->hasEhFrame()) 302 return; 303 304 EhFrame* eh_frame = eh_sect->getEhFrame(); 305 SectionData::FragmentListType& frag_list = 306 eh_frame->getSectionData()->getFragmentList(); 307 llvm::StringRef cie_region = createCIERegionForPLT(); 308 llvm::StringRef fde_region = createFDERegionForPLT(); 309 EhFrame::CIE* cie = new EhFrame::GeneratedCIE(cie_region); 310 EhFrame::FDE* fde = new EhFrame::GeneratedFDE(fde_region, *cie); 311 // Augmentation data only contains FDE encoding. 312 uint8_t aug_data = (uint8_t)(llvm::dwarf::DW_EH_PE_pcrel | 313 llvm::dwarf::DW_EH_PE_sdata4); 314 cie->setFDEEncode(aug_data); 315 cie->setAugmentationData(std::string(1, aug_data)); 316 317 EhFrame::cie_iterator i = eh_frame->cie_begin(); 318 for (EhFrame::cie_iterator e = eh_frame->cie_end(); i != e; ++i) { 319 EhFrame::CIE& exist_cie = **i; 320 if (exist_cie == *cie) { 321 // Insert the FDE fragment 322 SectionData::iterator cur_iter(exist_cie); 323 frag_list.insertAfter(cur_iter, fde); 324 fde->setCIE(exist_cie); 325 326 // Cleanup the CIE we created 327 cie->clearFDEs(); 328 delete cie; 329 break; 330 } 331 } 332 if (i == eh_frame->cie_end()) { 333 // Newly insert 334 eh_frame->addCIE(*cie); 335 eh_frame->addFDE(*fde); 336 } 337} 338 339/// finalizeSymbol - finalize the symbol value 340bool X86GNULDBackend::finalizeTargetSymbols() 341{ 342 return true; 343} 344 345/// doCreateProgramHdrs - backend can implement this function to create the 346/// target-dependent segments 347void X86GNULDBackend::doCreateProgramHdrs(Module& pModule) 348{ 349 // TODO 350} 351 352X86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig, 353 GNUInfo* pInfo) 354 : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY), 355 m_pGOT (NULL), 356 m_pGOTPLT (NULL) { 357} 358 359X86_32GNULDBackend::~X86_32GNULDBackend() 360{ 361 delete m_pGOT; 362 delete m_pGOTPLT; 363} 364 365bool X86_32GNULDBackend::initRelocator() 366{ 367 if (NULL == m_pRelocator) { 368 m_pRelocator = new X86_32Relocator(*this, config()); 369 } 370 return true; 371} 372 373void X86_32GNULDBackend::initTargetSections(Module& pModule, 374 ObjectBuilder& pBuilder) 375{ 376 if (LinkerConfig::Object != config().codeGenType()) { 377 ELFFileFormat* file_format = getOutputFormat(); 378 // initialize .got 379 LDSection& got = file_format->getGOT(); 380 m_pGOT = new X86_32GOT(got); 381 382 // initialize .got.plt 383 LDSection& gotplt = file_format->getGOTPLT(); 384 m_pGOTPLT = new X86_32GOTPLT(gotplt); 385 386 // initialize .plt 387 LDSection& plt = file_format->getPLT(); 388 plt.setAlign(16u); 389 m_pPLT = new X86_32PLT(plt, *m_pGOTPLT, config()); 390 391 // initialize .rel.plt 392 LDSection& relplt = file_format->getRelPlt(); 393 relplt.setLink(&plt); 394 m_pRelPLT = new OutputRelocSection(pModule, relplt); 395 396 // initialize .rel.dyn 397 LDSection& reldyn = file_format->getRelDyn(); 398 m_pRelDyn = new OutputRelocSection(pModule, reldyn); 399 400 } 401} 402 403X86_32GOT& X86_32GNULDBackend::getGOT() 404{ 405 assert(NULL != m_pGOT); 406 return *m_pGOT; 407} 408 409const X86_32GOT& X86_32GNULDBackend::getGOT() const 410{ 411 assert(NULL != m_pGOT); 412 return *m_pGOT; 413} 414 415X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() 416{ 417 assert(NULL != m_pGOTPLT); 418 return *m_pGOTPLT; 419} 420 421const X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const 422{ 423 assert(NULL != m_pGOTPLT); 424 return *m_pGOTPLT; 425} 426 427llvm::StringRef X86_32GNULDBackend::createCIERegionForPLT() 428{ 429 using namespace llvm::dwarf; 430 static const uint8_t data[4+4+16] = { 431 0x14, 0, 0, 0, // length 432 0, 0, 0, 0, // ID 433 1, // version 434 'z', 'R', '\0', // augmentation string 435 1, // code alignment factor 436 0x7c, // data alignment factor 437 8, // return address column 438 1, // augmentation data size 439 DW_EH_PE_pcrel | DW_EH_PE_sdata4, // FDE encoding 440 DW_CFA_def_cfa, 4, 4, 441 DW_CFA_offset + 8, 1, 442 DW_CFA_nop, 443 DW_CFA_nop 444 }; 445 return llvm::StringRef((const char*)data, 4+4+16); 446} 447 448llvm::StringRef X86_32GNULDBackend::createFDERegionForPLT() 449{ 450 using namespace llvm::dwarf; 451 static const uint8_t data[4+4+32] = { 452 0x24, 0, 0, 0, // length 453 0, 0, 0, 0, // offset to CIE 454 0, 0, 0, 0, // offset to PLT 455 0, 0, 0, 0, // size of PLT 456 0, // augmentation data size 457 DW_CFA_def_cfa_offset, 8, 458 DW_CFA_advance_loc + 6, 459 DW_CFA_def_cfa_offset, 12, 460 DW_CFA_advance_loc + 10, 461 DW_CFA_def_cfa_expression, 462 11, 463 DW_OP_breg4, 4, 464 DW_OP_breg8, 0, 465 DW_OP_lit15, 466 DW_OP_and, 467 DW_OP_lit11, 468 DW_OP_ge, 469 DW_OP_lit2, 470 DW_OP_shl, 471 DW_OP_plus, 472 DW_CFA_nop, 473 DW_CFA_nop, 474 DW_CFA_nop, 475 DW_CFA_nop 476 }; 477 return llvm::StringRef((const char*)data, 4+4+32); 478} 479 480void X86_32GNULDBackend::setRelDynSize() 481{ 482 ELFFileFormat* file_format = getOutputFormat(); 483 file_format->getRelDyn().setSize 484 (m_pRelDyn->numOfRelocs() * getRelEntrySize()); 485} 486 487void X86_32GNULDBackend::setRelPLTSize() 488{ 489 ELFFileFormat* file_format = getOutputFormat(); 490 file_format->getRelPlt().setSize 491 (m_pRelPLT->numOfRelocs() * getRelEntrySize()); 492} 493 494void X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) 495{ 496 // set .got.plt size 497 if (LinkerConfig::DynObj == config().codeGenType() || 498 m_pGOTPLT->hasGOT1() || 499 NULL != m_pGOTSymbol) { 500 m_pGOTPLT->finalizeSectionSize(); 501 defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin())); 502 } 503 504 // set .got size 505 if (!m_pGOT->empty()) 506 m_pGOT->finalizeSectionSize(); 507} 508 509uint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const 510{ 511 assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!"); 512 513 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin()); 514 515 X86_32GOTEntry* got = 0; 516 unsigned int EntrySize = X86_32GOTEntry::EntrySize; 517 uint64_t RegionSize = 0; 518 519 for (X86_32GOT::iterator it = m_pGOT->begin(), 520 ie = m_pGOT->end(); it != ie; ++it, ++buffer) { 521 got = &(llvm::cast<X86_32GOTEntry>((*it))); 522 *buffer = static_cast<uint32_t>(got->getValue()); 523 RegionSize += EntrySize; 524 } 525 526 return RegionSize; 527} 528 529uint64_t X86_32GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion, 530 const ELFFileFormat* FileFormat) const 531{ 532 assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!"); 533 m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr()); 534 m_pGOTPLT->applyAllGOTPLT(*m_pPLT); 535 536 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin()); 537 538 X86_32GOTEntry* got = 0; 539 unsigned int EntrySize = X86_32GOTEntry::EntrySize; 540 uint64_t RegionSize = 0; 541 542 for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(), 543 ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) { 544 got = &(llvm::cast<X86_32GOTEntry>((*it))); 545 *buffer = static_cast<uint32_t>(got->getValue()); 546 RegionSize += EntrySize; 547 } 548 549 return RegionSize; 550} 551 552X86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig, 553 GNUInfo* pInfo) 554 : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY), 555 m_pGOT (NULL), 556 m_pGOTPLT (NULL) { 557} 558 559X86_64GNULDBackend::~X86_64GNULDBackend() 560{ 561 delete m_pGOT; 562 delete m_pGOTPLT; 563} 564 565bool X86_64GNULDBackend::initRelocator() 566{ 567 if (NULL == m_pRelocator) { 568 m_pRelocator = new X86_64Relocator(*this, config()); 569 } 570 return true; 571} 572 573X86_64GOT& X86_64GNULDBackend::getGOT() 574{ 575 assert(NULL != m_pGOT); 576 return *m_pGOT; 577} 578 579const X86_64GOT& X86_64GNULDBackend::getGOT() const 580{ 581 assert(NULL != m_pGOT); 582 return *m_pGOT; 583} 584 585X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() 586{ 587 assert(NULL != m_pGOTPLT); 588 return *m_pGOTPLT; 589} 590 591const X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const 592{ 593 assert(NULL != m_pGOTPLT); 594 return *m_pGOTPLT; 595} 596 597llvm::StringRef X86_64GNULDBackend::createCIERegionForPLT() 598{ 599 using namespace llvm::dwarf; 600 static const uint8_t data[4+4+16] = { 601 0x14, 0, 0, 0, // length 602 0, 0, 0, 0, // ID 603 1, // CIE version 604 'z', 'R', '\0', // augmentation string 605 1, // code alignment factor 606 0x78, // data alignment factor 607 16, // return address column 608 1, // augmentation data size 609 DW_EH_PE_pcrel | DW_EH_PE_sdata4, // FDE encoding 610 DW_CFA_def_cfa, 7, 8, 611 DW_CFA_offset + 16, 1, 612 DW_CFA_nop, 613 DW_CFA_nop 614 }; 615 return llvm::StringRef((const char*)data, 4+4+16); 616} 617 618llvm::StringRef X86_64GNULDBackend::createFDERegionForPLT() 619{ 620 using namespace llvm::dwarf; 621 static const uint8_t data[4+4+32] = { 622 0x24, 0, 0, 0, // length 623 0, 0, 0, 0, // ID 624 0, 0, 0, 0, // offset to PLT 625 0, 0, 0, 0, // size of PLT 626 0, // augmentation data size 627 DW_CFA_def_cfa_offset, 16, 628 DW_CFA_advance_loc + 6, 629 DW_CFA_def_cfa_offset, 24, 630 DW_CFA_advance_loc + 10, 631 DW_CFA_def_cfa_expression, 632 11, 633 DW_OP_breg7, 8, 634 DW_OP_breg16, 0, 635 DW_OP_lit15, 636 DW_OP_and, 637 DW_OP_lit11, 638 DW_OP_ge, 639 DW_OP_lit3, 640 DW_OP_shl, 641 DW_OP_plus, 642 DW_CFA_nop, 643 DW_CFA_nop, 644 DW_CFA_nop, 645 DW_CFA_nop 646 }; 647 return llvm::StringRef((const char*)data, 4+4+32); 648} 649 650void X86_64GNULDBackend::setRelDynSize() 651{ 652 ELFFileFormat* file_format = getOutputFormat(); 653 file_format->getRelaDyn().setSize 654 (m_pRelDyn->numOfRelocs() * getRelaEntrySize()); 655} 656 657void X86_64GNULDBackend::setRelPLTSize() 658{ 659 ELFFileFormat* file_format = getOutputFormat(); 660 file_format->getRelaPlt().setSize 661 (m_pRelPLT->numOfRelocs() * getRelaEntrySize()); 662} 663 664void X86_64GNULDBackend::initTargetSections(Module& pModule, 665 ObjectBuilder& pBuilder) 666{ 667 if (LinkerConfig::Object != config().codeGenType()) { 668 ELFFileFormat* file_format = getOutputFormat(); 669 // initialize .got 670 LDSection& got = file_format->getGOT(); 671 m_pGOT = new X86_64GOT(got); 672 673 // initialize .got.plt 674 LDSection& gotplt = file_format->getGOTPLT(); 675 m_pGOTPLT = new X86_64GOTPLT(gotplt); 676 677 // initialize .plt 678 LDSection& plt = file_format->getPLT(); 679 plt.setAlign(16u); 680 m_pPLT = new X86_64PLT(plt, *m_pGOTPLT, config()); 681 682 // initialize .rela.plt 683 LDSection& relplt = file_format->getRelaPlt(); 684 relplt.setLink(&plt); 685 m_pRelPLT = new OutputRelocSection(pModule, relplt); 686 687 // initialize .rela.dyn 688 LDSection& reldyn = file_format->getRelaDyn(); 689 m_pRelDyn = new OutputRelocSection(pModule, reldyn); 690 691 } 692} 693 694void X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) 695{ 696 // set .got.plt size 697 if (LinkerConfig::DynObj == config().codeGenType() || 698 m_pGOTPLT->hasGOT1() || 699 NULL != m_pGOTSymbol) { 700 m_pGOTPLT->finalizeSectionSize(); 701 defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin())); 702 } 703 704 // set .got size 705 if (!m_pGOT->empty()) 706 m_pGOT->finalizeSectionSize(); 707} 708 709uint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const 710{ 711 assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!"); 712 713 uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin()); 714 715 X86_64GOTEntry* got = 0; 716 unsigned int EntrySize = X86_64GOTEntry::EntrySize; 717 uint64_t RegionSize = 0; 718 719 for (X86_64GOT::iterator it = m_pGOT->begin(), 720 ie = m_pGOT->end(); it != ie; ++it, ++buffer) { 721 got = &(llvm::cast<X86_64GOTEntry>((*it))); 722 *buffer = static_cast<uint64_t>(got->getValue()); 723 RegionSize += EntrySize; 724 } 725 726 return RegionSize; 727} 728 729uint64_t 730X86_64GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion, 731 const ELFFileFormat* FileFormat) const 732{ 733 assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!"); 734 m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr()); 735 m_pGOTPLT->applyAllGOTPLT(*m_pPLT); 736 737 uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin()); 738 739 X86_64GOTEntry* got = 0; 740 unsigned int EntrySize = X86_64GOTEntry::EntrySize; 741 uint64_t RegionSize = 0; 742 743 for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(), 744 ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) { 745 got = &(llvm::cast<X86_64GOTEntry>((*it))); 746 *buffer = static_cast<uint64_t>(got->getValue()); 747 RegionSize += EntrySize; 748 } 749 750 return RegionSize; 751} 752 753namespace mcld { 754 755//===----------------------------------------------------------------------===// 756/// createX86LDBackend - the help funtion to create corresponding X86LDBackend 757/// 758TargetLDBackend* createX86LDBackend(const LinkerConfig& pConfig) 759{ 760 if (pConfig.targets().triple().isOSDarwin()) { 761 assert(0 && "MachO linker is not supported yet"); 762 /** 763 return new X86MachOLDBackend(createX86MachOArchiveReader, 764 createX86MachOObjectReader, 765 createX86MachOObjectWriter); 766 **/ 767 } 768 if (pConfig.targets().triple().isOSWindows()) { 769 assert(0 && "COFF linker is not supported yet"); 770 /** 771 return new X86COFFLDBackend(createX86COFFArchiveReader, 772 createX86COFFObjectReader, 773 createX86COFFObjectWriter); 774 **/ 775 } 776 llvm::Triple::ArchType arch = pConfig.targets().triple().getArch(); 777 if (arch == llvm::Triple::x86) 778 return new X86_32GNULDBackend(pConfig, 779 new X86_32GNUInfo(pConfig.targets().triple())); 780 assert (arch == llvm::Triple::x86_64); 781 return new X86_64GNULDBackend(pConfig, 782 new X86_64GNUInfo(pConfig.targets().triple())); 783} 784 785} // namespace of mcld 786 787//===----------------------------------------------------------------------===// 788// Force static initialization. 789//===----------------------------------------------------------------------===// 790extern "C" void MCLDInitializeX86LDBackend() { 791 // Register the linker backend 792 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend); 793 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend); 794} 795