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 "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