Home | History | Annotate | Download | only in X86
      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