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