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