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/Triple.h> 16 #include <llvm/Support/Casting.h> 17 18 #include <mcld/LinkerConfig.h> 19 #include <mcld/IRBuilder.h> 20 #include <mcld/Fragment/FillFragment.h> 21 #include <mcld/Fragment/RegionFragment.h> 22 #include <mcld/Fragment/FragmentLinker.h> 23 #include <mcld/Support/MemoryRegion.h> 24 #include <mcld/Support/MsgHandling.h> 25 #include <mcld/Support/TargetRegistry.h> 26 #include <mcld/Object/ObjectBuilder.h> 27 28 #include <cstring> 29 30 using namespace mcld; 31 32 //===----------------------------------------------------------------------===// 33 // X86GNULDBackend 34 //===----------------------------------------------------------------------===// 35 X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig, 36 GNUInfo* pInfo, 37 Relocation::Type pCopyRel) 38 : GNULDBackend(pConfig, pInfo), 39 m_pRelocator(NULL), 40 m_pPLT(NULL), 41 m_pRelDyn(NULL), 42 m_pRelPLT(NULL), 43 m_pDynamic(NULL), 44 m_pGOTSymbol(NULL), 45 m_CopyRel(pCopyRel) 46 { 47 Triple::ArchType arch = pConfig.targets().triple().getArch(); 48 assert (arch == Triple::x86 || arch == Triple::x86_64); 49 if (arch == Triple::x86 || 50 pConfig.targets().triple().getEnvironment() == Triple::GNUX32) { 51 m_RelEntrySize = 8; 52 m_RelaEntrySize = 12; 53 if (arch == Triple::x86) 54 m_PointerRel = llvm::ELF::R_386_32; 55 else 56 m_PointerRel = llvm::ELF::R_X86_64_32; 57 } 58 else { 59 m_RelEntrySize = 16; 60 m_RelaEntrySize = 24; 61 m_PointerRel = llvm::ELF::R_X86_64_64; 62 } 63 } 64 65 X86GNULDBackend::~X86GNULDBackend() 66 { 67 delete m_pRelocator; 68 delete m_pPLT; 69 delete m_pRelDyn; 70 delete m_pRelPLT; 71 delete m_pDynamic; 72 } 73 74 Relocator* X86GNULDBackend::getRelocator() 75 { 76 assert(NULL != m_pRelocator); 77 return m_pRelocator; 78 } 79 80 void X86GNULDBackend::doPreLayout(IRBuilder& pBuilder) 81 { 82 // initialize .dynamic data 83 if (!config().isCodeStatic() && NULL == m_pDynamic) 84 m_pDynamic = new X86ELFDynamic(*this, config()); 85 86 // set .got.plt and .got sizes 87 // when building shared object, the .got section is must 88 if (LinkerConfig::Object != config().codeGenType()) { 89 setGOTSectionSize(pBuilder); 90 91 // set .plt size 92 if (m_pPLT->hasPLT1()) 93 m_pPLT->finalizeSectionSize(); 94 95 // set .rel.dyn/.rela.dyn size 96 if (!m_pRelDyn->empty()) { 97 assert(!config().isCodeStatic() && 98 "static linkage should not result in a dynamic relocation section"); 99 setRelDynSize(); 100 } 101 // set .rel.plt/.rela.plt size 102 if (!m_pRelPLT->empty()) { 103 assert(!config().isCodeStatic() && 104 "static linkage should not result in a dynamic relocation section"); 105 setRelPLTSize(); 106 } 107 } 108 } 109 110 void X86GNULDBackend::doPostLayout(Module& pModule, 111 IRBuilder& pBuilder) 112 { 113 } 114 115 /// dynamic - the dynamic section of the target machine. 116 /// Use co-variant return type to return its own dynamic section. 117 X86ELFDynamic& X86GNULDBackend::dynamic() 118 { 119 assert(NULL != m_pDynamic); 120 return *m_pDynamic; 121 } 122 123 /// dynamic - the dynamic section of the target machine. 124 /// Use co-variant return type to return its own dynamic section. 125 const X86ELFDynamic& X86GNULDBackend::dynamic() const 126 { 127 assert(NULL != m_pDynamic); 128 return *m_pDynamic; 129 } 130 131 void X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder, 132 Fragment& pFrag) 133 { 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 } 146 else { 147 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 148 "_GLOBAL_OFFSET_TABLE_", 149 ResolveInfo::Object, 150 ResolveInfo::Define, 151 ResolveInfo::Local, 152 0x0, // size 153 0x0, // value 154 FragmentRef::Create(pFrag, 0x0), 155 ResolveInfo::Hidden); 156 } 157 } 158 159 uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection, 160 MemoryRegion& pRegion) const 161 { 162 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 163 164 const ELFFileFormat* FileFormat = getOutputFormat(); 165 assert(FileFormat && 166 "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!"); 167 168 unsigned int EntrySize = 0; 169 uint64_t RegionSize = 0; 170 171 if (&pSection == &(FileFormat->getPLT())) { 172 assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!"); 173 174 unsigned char* buffer = pRegion.getBuffer(); 175 176 m_pPLT->applyPLT0(); 177 m_pPLT->applyPLT1(); 178 X86PLT::iterator it = m_pPLT->begin(); 179 unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size(); 180 181 memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size); 182 RegionSize += plt0_size; 183 ++it; 184 185 PLTEntryBase* plt1 = 0; 186 X86PLT::iterator ie = m_pPLT->end(); 187 while (it != ie) { 188 plt1 = &(llvm::cast<PLTEntryBase>(*it)); 189 EntrySize = plt1->size(); 190 memcpy(buffer + RegionSize, plt1->getValue(), EntrySize); 191 RegionSize += EntrySize; 192 ++it; 193 } 194 } 195 196 else if (&pSection == &(FileFormat->getGOT())) { 197 RegionSize += emitGOTSectionData(pRegion); 198 } 199 200 else if (&pSection == &(FileFormat->getGOTPLT())) { 201 RegionSize += emitGOTPLTSectionData(pRegion, FileFormat); 202 } 203 204 else { 205 fatal(diag::unrecognized_output_sectoin) 206 << pSection.name() 207 << "mclinker (at) googlegroups.com"; 208 } 209 return RegionSize; 210 } 211 212 X86PLT& X86GNULDBackend::getPLT() 213 { 214 assert(NULL != m_pPLT && "PLT section not exist"); 215 return *m_pPLT; 216 } 217 218 const X86PLT& X86GNULDBackend::getPLT() const 219 { 220 assert(NULL != m_pPLT && "PLT section not exist"); 221 return *m_pPLT; 222 } 223 224 OutputRelocSection& X86GNULDBackend::getRelDyn() 225 { 226 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 227 return *m_pRelDyn; 228 } 229 230 const OutputRelocSection& X86GNULDBackend::getRelDyn() const 231 { 232 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 233 return *m_pRelDyn; 234 } 235 236 OutputRelocSection& X86GNULDBackend::getRelPLT() 237 { 238 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 239 return *m_pRelPLT; 240 } 241 242 const OutputRelocSection& X86GNULDBackend::getRelPLT() const 243 { 244 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 245 return *m_pRelPLT; 246 } 247 248 unsigned int 249 X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const 250 { 251 const ELFFileFormat* file_format = getOutputFormat(); 252 253 if (&pSectHdr == &file_format->getGOT()) { 254 if (config().options().hasNow()) 255 return SHO_RELRO; 256 return SHO_RELRO_LAST; 257 } 258 259 if (&pSectHdr == &file_format->getGOTPLT()) { 260 if (config().options().hasNow()) 261 return SHO_RELRO; 262 return SHO_NON_RELRO_FIRST; 263 } 264 265 if (&pSectHdr == &file_format->getPLT()) 266 return SHO_PLT; 267 268 return SHO_UNDEFINED; 269 } 270 271 void 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 289 /// finalizeSymbol - finalize the symbol value 290 bool X86GNULDBackend::finalizeTargetSymbols() 291 { 292 return true; 293 } 294 295 /// doCreateProgramHdrs - backend can implement this function to create the 296 /// target-dependent segments 297 void X86GNULDBackend::doCreateProgramHdrs(Module& pModule) 298 { 299 // TODO 300 } 301 302 X86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig, 303 GNUInfo* pInfo) 304 : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY), 305 m_pGOT (NULL), 306 m_pGOTPLT (NULL) { 307 } 308 309 X86_32GNULDBackend::~X86_32GNULDBackend() 310 { 311 delete m_pGOT; 312 delete m_pGOTPLT; 313 } 314 315 bool X86_32GNULDBackend::initRelocator() 316 { 317 if (NULL == m_pRelocator) { 318 m_pRelocator = new X86_32Relocator(*this, config()); 319 } 320 return true; 321 } 322 323 void X86_32GNULDBackend::initTargetSections(Module& pModule, 324 ObjectBuilder& pBuilder) 325 { 326 if (LinkerConfig::Object != config().codeGenType()) { 327 ELFFileFormat* file_format = getOutputFormat(); 328 // initialize .got 329 LDSection& got = file_format->getGOT(); 330 m_pGOT = new X86_32GOT(got); 331 332 // initialize .got.plt 333 LDSection& gotplt = file_format->getGOTPLT(); 334 m_pGOTPLT = new X86_32GOTPLT(gotplt); 335 336 // initialize .plt 337 LDSection& plt = file_format->getPLT(); 338 m_pPLT = new X86_32PLT(plt, 339 *m_pGOTPLT, 340 config()); 341 342 // initialize .rel.plt 343 LDSection& relplt = file_format->getRelPlt(); 344 relplt.setLink(&plt); 345 m_pRelPLT = new OutputRelocSection(pModule, relplt); 346 347 // initialize .rel.dyn 348 LDSection& reldyn = file_format->getRelDyn(); 349 m_pRelDyn = new OutputRelocSection(pModule, reldyn); 350 351 } 352 } 353 354 X86_32GOT& X86_32GNULDBackend::getGOT() 355 { 356 assert(NULL != m_pGOT); 357 return *m_pGOT; 358 } 359 360 const X86_32GOT& X86_32GNULDBackend::getGOT() const 361 { 362 assert(NULL != m_pGOT); 363 return *m_pGOT; 364 } 365 366 X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() 367 { 368 assert(NULL != m_pGOTPLT); 369 return *m_pGOTPLT; 370 } 371 372 const X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const 373 { 374 assert(NULL != m_pGOTPLT); 375 return *m_pGOTPLT; 376 } 377 378 void X86_32GNULDBackend::setRelDynSize() 379 { 380 ELFFileFormat* file_format = getOutputFormat(); 381 file_format->getRelDyn().setSize 382 (m_pRelDyn->numOfRelocs() * getRelEntrySize()); 383 } 384 385 void X86_32GNULDBackend::setRelPLTSize() 386 { 387 ELFFileFormat* file_format = getOutputFormat(); 388 file_format->getRelPlt().setSize 389 (m_pRelPLT->numOfRelocs() * getRelEntrySize()); 390 } 391 392 void X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) 393 { 394 // set .got.plt size 395 if (LinkerConfig::DynObj == config().codeGenType() || 396 m_pGOTPLT->hasGOT1() || 397 NULL != m_pGOTSymbol) { 398 m_pGOTPLT->finalizeSectionSize(); 399 defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin())); 400 } 401 402 // set .got size 403 if (!m_pGOT->empty()) 404 m_pGOT->finalizeSectionSize(); 405 } 406 407 uint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const 408 { 409 assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!"); 410 411 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 412 413 X86_32GOTEntry* got = 0; 414 unsigned int EntrySize = X86_32GOTEntry::EntrySize; 415 uint64_t RegionSize = 0; 416 417 for (X86_32GOT::iterator it = m_pGOT->begin(), 418 ie = m_pGOT->end(); it != ie; ++it, ++buffer) { 419 got = &(llvm::cast<X86_32GOTEntry>((*it))); 420 *buffer = static_cast<uint32_t>(got->getValue()); 421 RegionSize += EntrySize; 422 } 423 424 return RegionSize; 425 } 426 427 uint64_t X86_32GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion, 428 const ELFFileFormat* FileFormat) const 429 { 430 assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!"); 431 m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr()); 432 m_pGOTPLT->applyAllGOTPLT(*m_pPLT); 433 434 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 435 436 X86_32GOTEntry* got = 0; 437 unsigned int EntrySize = X86_32GOTEntry::EntrySize; 438 uint64_t RegionSize = 0; 439 440 for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(), 441 ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) { 442 got = &(llvm::cast<X86_32GOTEntry>((*it))); 443 *buffer = static_cast<uint32_t>(got->getValue()); 444 RegionSize += EntrySize; 445 } 446 447 return RegionSize; 448 } 449 450 X86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig, 451 GNUInfo* pInfo) 452 : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY), 453 m_pGOT (NULL), 454 m_pGOTPLT (NULL) { 455 } 456 457 X86_64GNULDBackend::~X86_64GNULDBackend() 458 { 459 delete m_pGOT; 460 delete m_pGOTPLT; 461 } 462 463 bool X86_64GNULDBackend::initRelocator() 464 { 465 if (NULL == m_pRelocator) { 466 m_pRelocator = new X86_64Relocator(*this, config()); 467 } 468 return true; 469 } 470 471 X86_64GOT& X86_64GNULDBackend::getGOT() 472 { 473 assert(NULL != m_pGOT); 474 return *m_pGOT; 475 } 476 477 const X86_64GOT& X86_64GNULDBackend::getGOT() const 478 { 479 assert(NULL != m_pGOT); 480 return *m_pGOT; 481 } 482 483 X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() 484 { 485 assert(NULL != m_pGOTPLT); 486 return *m_pGOTPLT; 487 } 488 489 const X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const 490 { 491 assert(NULL != m_pGOTPLT); 492 return *m_pGOTPLT; 493 } 494 495 void X86_64GNULDBackend::setRelDynSize() 496 { 497 ELFFileFormat* file_format = getOutputFormat(); 498 file_format->getRelaDyn().setSize 499 (m_pRelDyn->numOfRelocs() * getRelaEntrySize()); 500 } 501 502 void X86_64GNULDBackend::setRelPLTSize() 503 { 504 ELFFileFormat* file_format = getOutputFormat(); 505 file_format->getRelaPlt().setSize 506 (m_pRelPLT->numOfRelocs() * getRelaEntrySize()); 507 } 508 509 void X86_64GNULDBackend::initTargetSections(Module& pModule, 510 ObjectBuilder& pBuilder) 511 { 512 if (LinkerConfig::Object != config().codeGenType()) { 513 ELFFileFormat* file_format = getOutputFormat(); 514 // initialize .got 515 LDSection& got = file_format->getGOT(); 516 m_pGOT = new X86_64GOT(got); 517 518 // initialize .got.plt 519 LDSection& gotplt = file_format->getGOTPLT(); 520 m_pGOTPLT = new X86_64GOTPLT(gotplt); 521 522 // initialize .plt 523 LDSection& plt = file_format->getPLT(); 524 m_pPLT = new X86_64PLT(plt, 525 *m_pGOTPLT, 526 config()); 527 528 // initialize .rela.plt 529 LDSection& relplt = file_format->getRelaPlt(); 530 relplt.setLink(&plt); 531 m_pRelPLT = new OutputRelocSection(pModule, relplt); 532 533 // initialize .rela.dyn 534 LDSection& reldyn = file_format->getRelaDyn(); 535 m_pRelDyn = new OutputRelocSection(pModule, reldyn); 536 537 } 538 } 539 540 void X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) 541 { 542 // set .got.plt size 543 if (LinkerConfig::DynObj == config().codeGenType() || 544 m_pGOTPLT->hasGOT1() || 545 NULL != m_pGOTSymbol) { 546 m_pGOTPLT->finalizeSectionSize(); 547 defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin())); 548 } 549 550 // set .got size 551 if (!m_pGOT->empty()) 552 m_pGOT->finalizeSectionSize(); 553 } 554 555 uint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const 556 { 557 assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!"); 558 559 uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer()); 560 561 X86_64GOTEntry* got = 0; 562 unsigned int EntrySize = X86_64GOTEntry::EntrySize; 563 uint64_t RegionSize = 0; 564 565 for (X86_64GOT::iterator it = m_pGOT->begin(), 566 ie = m_pGOT->end(); it != ie; ++it, ++buffer) { 567 got = &(llvm::cast<X86_64GOTEntry>((*it))); 568 *buffer = static_cast<uint64_t>(got->getValue()); 569 RegionSize += EntrySize; 570 } 571 572 return RegionSize; 573 } 574 575 uint64_t X86_64GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion, 576 const ELFFileFormat* FileFormat) const 577 { 578 assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!"); 579 m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr()); 580 m_pGOTPLT->applyAllGOTPLT(*m_pPLT); 581 582 uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer()); 583 584 X86_64GOTEntry* got = 0; 585 unsigned int EntrySize = X86_64GOTEntry::EntrySize; 586 uint64_t RegionSize = 0; 587 588 for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(), 589 ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) { 590 got = &(llvm::cast<X86_64GOTEntry>((*it))); 591 *buffer = static_cast<uint64_t>(got->getValue()); 592 RegionSize += EntrySize; 593 } 594 595 return RegionSize; 596 } 597 598 namespace mcld { 599 600 //===----------------------------------------------------------------------===// 601 /// createX86LDBackend - the help funtion to create corresponding X86LDBackend 602 /// 603 TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget, 604 const LinkerConfig& pConfig) 605 { 606 if (pConfig.targets().triple().isOSDarwin()) { 607 assert(0 && "MachO linker is not supported yet"); 608 /** 609 return new X86MachOLDBackend(createX86MachOArchiveReader, 610 createX86MachOObjectReader, 611 createX86MachOObjectWriter); 612 **/ 613 } 614 if (pConfig.targets().triple().isOSWindows()) { 615 assert(0 && "COFF linker is not supported yet"); 616 /** 617 return new X86COFFLDBackend(createX86COFFArchiveReader, 618 createX86COFFObjectReader, 619 createX86COFFObjectWriter); 620 **/ 621 } 622 Triple::ArchType arch = pConfig.targets().triple().getArch(); 623 if (arch == Triple::x86) 624 return new X86_32GNULDBackend(pConfig, 625 new X86_32GNUInfo(pConfig.targets().triple())); 626 assert (arch == Triple::x86_64); 627 return new X86_64GNULDBackend(pConfig, 628 new X86_64GNUInfo(pConfig.targets().triple())); 629 } 630 631 } // namespace of mcld 632 633 //===----------------------------------------------------------------------===// 634 // Force static initialization. 635 //===----------------------------------------------------------------------===// 636 extern "C" void MCLDInitializeX86LDBackend() { 637 // Register the linker backend 638 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend); 639 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend); 640 } 641