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 31 using namespace mcld; 32 33 //===----------------------------------------------------------------------===// 34 // X86GNULDBackend 35 //===----------------------------------------------------------------------===// 36 X86GNULDBackend::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 66 X86GNULDBackend::~X86GNULDBackend() 67 { 68 delete m_pRelocator; 69 delete m_pPLT; 70 delete m_pRelDyn; 71 delete m_pRelPLT; 72 delete m_pDynamic; 73 } 74 75 const Relocator* X86GNULDBackend::getRelocator() const 76 { 77 assert(NULL != m_pRelocator); 78 return m_pRelocator; 79 } 80 81 Relocator* X86GNULDBackend::getRelocator() 82 { 83 assert(NULL != m_pRelocator); 84 return m_pRelocator; 85 } 86 87 void 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 120 void 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. 127 X86ELFDynamic& 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. 135 const X86ELFDynamic& X86GNULDBackend::dynamic() const 136 { 137 assert(NULL != m_pDynamic); 138 return *m_pDynamic; 139 } 140 141 void 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 168 uint64_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 (at) googlegroups.com"; 213 } 214 return RegionSize; 215 } 216 217 X86PLT& X86GNULDBackend::getPLT() 218 { 219 assert(NULL != m_pPLT && "PLT section not exist"); 220 return *m_pPLT; 221 } 222 223 const X86PLT& X86GNULDBackend::getPLT() const 224 { 225 assert(NULL != m_pPLT && "PLT section not exist"); 226 return *m_pPLT; 227 } 228 229 OutputRelocSection& X86GNULDBackend::getRelDyn() 230 { 231 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 232 return *m_pRelDyn; 233 } 234 235 const OutputRelocSection& X86GNULDBackend::getRelDyn() const 236 { 237 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 238 return *m_pRelDyn; 239 } 240 241 OutputRelocSection& X86GNULDBackend::getRelPLT() 242 { 243 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 244 return *m_pRelPLT; 245 } 246 247 const OutputRelocSection& X86GNULDBackend::getRelPLT() const 248 { 249 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 250 return *m_pRelPLT; 251 } 252 253 unsigned int 254 X86GNULDBackend::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 276 void 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 294 void 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 340 bool X86GNULDBackend::finalizeTargetSymbols() 341 { 342 return true; 343 } 344 345 /// doCreateProgramHdrs - backend can implement this function to create the 346 /// target-dependent segments 347 void X86GNULDBackend::doCreateProgramHdrs(Module& pModule) 348 { 349 // TODO 350 } 351 352 X86_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 359 X86_32GNULDBackend::~X86_32GNULDBackend() 360 { 361 delete m_pGOT; 362 delete m_pGOTPLT; 363 } 364 365 bool X86_32GNULDBackend::initRelocator() 366 { 367 if (NULL == m_pRelocator) { 368 m_pRelocator = new X86_32Relocator(*this, config()); 369 } 370 return true; 371 } 372 373 void 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 403 X86_32GOT& X86_32GNULDBackend::getGOT() 404 { 405 assert(NULL != m_pGOT); 406 return *m_pGOT; 407 } 408 409 const X86_32GOT& X86_32GNULDBackend::getGOT() const 410 { 411 assert(NULL != m_pGOT); 412 return *m_pGOT; 413 } 414 415 X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() 416 { 417 assert(NULL != m_pGOTPLT); 418 return *m_pGOTPLT; 419 } 420 421 const X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const 422 { 423 assert(NULL != m_pGOTPLT); 424 return *m_pGOTPLT; 425 } 426 427 llvm::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 448 llvm::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 480 void X86_32GNULDBackend::setRelDynSize() 481 { 482 ELFFileFormat* file_format = getOutputFormat(); 483 file_format->getRelDyn().setSize 484 (m_pRelDyn->numOfRelocs() * getRelEntrySize()); 485 } 486 487 void X86_32GNULDBackend::setRelPLTSize() 488 { 489 ELFFileFormat* file_format = getOutputFormat(); 490 file_format->getRelPlt().setSize 491 (m_pRelPLT->numOfRelocs() * getRelEntrySize()); 492 } 493 494 void 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 509 uint64_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 529 uint64_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 552 X86_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 559 X86_64GNULDBackend::~X86_64GNULDBackend() 560 { 561 delete m_pGOT; 562 delete m_pGOTPLT; 563 } 564 565 bool X86_64GNULDBackend::initRelocator() 566 { 567 if (NULL == m_pRelocator) { 568 m_pRelocator = new X86_64Relocator(*this, config()); 569 } 570 return true; 571 } 572 573 X86_64GOT& X86_64GNULDBackend::getGOT() 574 { 575 assert(NULL != m_pGOT); 576 return *m_pGOT; 577 } 578 579 const X86_64GOT& X86_64GNULDBackend::getGOT() const 580 { 581 assert(NULL != m_pGOT); 582 return *m_pGOT; 583 } 584 585 X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() 586 { 587 assert(NULL != m_pGOTPLT); 588 return *m_pGOTPLT; 589 } 590 591 const X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const 592 { 593 assert(NULL != m_pGOTPLT); 594 return *m_pGOTPLT; 595 } 596 597 llvm::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 618 llvm::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 650 void X86_64GNULDBackend::setRelDynSize() 651 { 652 ELFFileFormat* file_format = getOutputFormat(); 653 file_format->getRelaDyn().setSize 654 (m_pRelDyn->numOfRelocs() * getRelaEntrySize()); 655 } 656 657 void X86_64GNULDBackend::setRelPLTSize() 658 { 659 ELFFileFormat* file_format = getOutputFormat(); 660 file_format->getRelaPlt().setSize 661 (m_pRelPLT->numOfRelocs() * getRelaEntrySize()); 662 } 663 664 void 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 694 void 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 709 uint64_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 729 uint64_t 730 X86_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 753 namespace mcld { 754 755 //===----------------------------------------------------------------------===// 756 /// createX86LDBackend - the help funtion to create corresponding X86LDBackend 757 /// 758 TargetLDBackend* 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 //===----------------------------------------------------------------------===// 790 extern "C" void MCLDInitializeX86LDBackend() { 791 // Register the linker backend 792 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend); 793 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend); 794 } 795