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