Home | History | Annotate | Download | only in AArch64
      1 //===- AArch64LDBackend.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 "AArch64.h"
     10 #include "AArch64CA53Erratum835769Stub.h"
     11 #include "AArch64CA53Erratum843419Stub.h"
     12 #include "AArch64CA53Erratum843419Stub2.h"
     13 #include "AArch64ELFDynamic.h"
     14 #include "AArch64GNUInfo.h"
     15 #include "AArch64InsnHelpers.h"
     16 #include "AArch64LDBackend.h"
     17 #include "AArch64LongBranchStub.h"
     18 #include "AArch64Relocator.h"
     19 
     20 #include "mcld/IRBuilder.h"
     21 #include "mcld/LinkerConfig.h"
     22 #include "mcld/Fragment/AlignFragment.h"
     23 #include "mcld/Fragment/FillFragment.h"
     24 #include "mcld/Fragment/NullFragment.h"
     25 #include "mcld/Fragment/RegionFragment.h"
     26 #include "mcld/Fragment/Stub.h"
     27 #include "mcld/LD/BranchIslandFactory.h"
     28 #include "mcld/LD/ELFFileFormat.h"
     29 #include "mcld/LD/ELFSegment.h"
     30 #include "mcld/LD/ELFSegmentFactory.h"
     31 #include "mcld/LD/LDContext.h"
     32 #include "mcld/LD/StubFactory.h"
     33 #include "mcld/Support/MemoryRegion.h"
     34 #include "mcld/Support/MemoryArea.h"
     35 #include "mcld/Support/MsgHandling.h"
     36 #include "mcld/Support/TargetRegistry.h"
     37 #include "mcld/Target/ELFAttribute.h"
     38 #include "mcld/Target/GNUInfo.h"
     39 #include "mcld/Object/ObjectBuilder.h"
     40 
     41 #include <llvm/ADT/Triple.h>
     42 #include <llvm/ADT/Twine.h>
     43 #include <llvm/Support/Casting.h>
     44 #include <llvm/Support/ELF.h>
     45 
     46 #include <cstring>
     47 
     48 namespace mcld {
     49 
     50 //===----------------------------------------------------------------------===//
     51 // AArch64GNULDBackend
     52 //===----------------------------------------------------------------------===//
     53 AArch64GNULDBackend::AArch64GNULDBackend(const LinkerConfig& pConfig,
     54                                          GNUInfo* pInfo)
     55     : GNULDBackend(pConfig, pInfo),
     56       m_pRelocator(NULL),
     57       m_pGOT(NULL),
     58       m_pGOTPLT(NULL),
     59       m_pPLT(NULL),
     60       m_pRelaDyn(NULL),
     61       m_pRelaPLT(NULL),
     62       m_pDynamic(NULL),
     63       m_pGOTSymbol(NULL) {
     64 }
     65 
     66 AArch64GNULDBackend::~AArch64GNULDBackend() {
     67   if (m_pRelocator != NULL)
     68     delete m_pRelocator;
     69   if (m_pGOT == m_pGOTPLT) {
     70     if (m_pGOT != NULL)
     71       delete m_pGOT;
     72   } else {
     73     if (m_pGOT != NULL)
     74       delete m_pGOT;
     75     if (m_pGOTPLT != NULL)
     76       delete m_pGOTPLT;
     77   }
     78   if (m_pPLT != NULL)
     79     delete m_pPLT;
     80   if (m_pRelaDyn != NULL)
     81     delete m_pRelaDyn;
     82   if (m_pRelaPLT != NULL)
     83     delete m_pRelaPLT;
     84   if (m_pDynamic != NULL)
     85     delete m_pDynamic;
     86 }
     87 
     88 void AArch64GNULDBackend::initTargetSections(Module& pModule,
     89                                              ObjectBuilder& pBuilder) {
     90   if (LinkerConfig::Object != config().codeGenType()) {
     91     ELFFileFormat* file_format = getOutputFormat();
     92 
     93     // initialize .got
     94     LDSection& got = file_format->getGOT();
     95     m_pGOT = new AArch64GOT(got);
     96     if (config().options().hasNow()) {
     97       // when -z now is given, there will be only one .got section (contains
     98       // both GOTPLT and normal GOT entries), create GOT0 for .got section and
     99       // set m_pGOTPLT to the same .got
    100       m_pGOT->createGOT0();
    101       m_pGOTPLT = m_pGOT;
    102     } else {
    103       // Otherwise, got should be seperated to two sections, .got and .got.plt
    104       // initialize .got.plt
    105       LDSection& gotplt = file_format->getGOTPLT();
    106       m_pGOTPLT = new AArch64GOT(gotplt);
    107       m_pGOTPLT->createGOT0();
    108     }
    109 
    110     // initialize .plt
    111     LDSection& plt = file_format->getPLT();
    112     m_pPLT = new AArch64PLT(plt, *m_pGOTPLT);
    113 
    114     // initialize .rela.plt
    115     LDSection& relaplt = file_format->getRelaPlt();
    116     relaplt.setLink(&plt);
    117     m_pRelaPLT = new OutputRelocSection(pModule, relaplt);
    118 
    119     // initialize .rela.dyn
    120     LDSection& reladyn = file_format->getRelaDyn();
    121     m_pRelaDyn = new OutputRelocSection(pModule, reladyn);
    122   }
    123 }
    124 
    125 void AArch64GNULDBackend::initTargetSymbols(IRBuilder& pBuilder,
    126                                             Module& pModule) {
    127   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
    128   // same name in input
    129   if (LinkerConfig::Object != config().codeGenType()) {
    130     m_pGOTSymbol =
    131         pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    132             "_GLOBAL_OFFSET_TABLE_",
    133             ResolveInfo::Object,
    134             ResolveInfo::Define,
    135             ResolveInfo::Local,
    136             0x0,  // size
    137             0x0,  // value
    138             FragmentRef::Null(),
    139             ResolveInfo::Hidden);
    140   }
    141 }
    142 
    143 bool AArch64GNULDBackend::initRelocator() {
    144   if (m_pRelocator == NULL) {
    145     m_pRelocator = new AArch64Relocator(*this, config());
    146   }
    147   return true;
    148 }
    149 
    150 const Relocator* AArch64GNULDBackend::getRelocator() const {
    151   assert(m_pRelocator != NULL);
    152   return m_pRelocator;
    153 }
    154 
    155 Relocator* AArch64GNULDBackend::getRelocator() {
    156   assert(m_pRelocator != NULL);
    157   return m_pRelocator;
    158 }
    159 
    160 void AArch64GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
    161   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
    162   if (m_pGOTSymbol != NULL) {
    163     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
    164         "_GLOBAL_OFFSET_TABLE_",
    165         ResolveInfo::Object,
    166         ResolveInfo::Define,
    167         ResolveInfo::Local,
    168         0x0,  // size
    169         0x0,  // value
    170         FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
    171         ResolveInfo::Hidden);
    172   } else {
    173     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    174         "_GLOBAL_OFFSET_TABLE_",
    175         ResolveInfo::Object,
    176         ResolveInfo::Define,
    177         ResolveInfo::Local,
    178         0x0,  // size
    179         0x0,  // value
    180         FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
    181         ResolveInfo::Hidden);
    182   }
    183 }
    184 
    185 void AArch64GNULDBackend::doPreLayout(IRBuilder& pBuilder) {
    186   // initialize .dynamic data
    187   if (!config().isCodeStatic() && m_pDynamic == NULL)
    188     m_pDynamic = new AArch64ELFDynamic(*this, config());
    189 
    190   if (LinkerConfig::Object != config().codeGenType()) {
    191     // set .got size
    192     if (config().options().hasNow()) {
    193       // when building shared object, the GOTPLT section is must
    194       if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
    195           m_pGOTSymbol != NULL) {
    196         m_pGOT->finalizeSectionSize();
    197         defineGOTSymbol(pBuilder);
    198       }
    199     } else {
    200       // when building shared object, the GOTPLT section is must
    201       if (LinkerConfig::DynObj == config().codeGenType() ||
    202           m_pGOTPLT->hasGOT1() || m_pGOTSymbol != NULL) {
    203         m_pGOTPLT->finalizeSectionSize();
    204         defineGOTSymbol(pBuilder);
    205       }
    206       if (m_pGOT->hasGOT1())
    207         m_pGOT->finalizeSectionSize();
    208     }
    209 
    210     // set .plt size
    211     if (m_pPLT->hasPLT1())
    212       m_pPLT->finalizeSectionSize();
    213 
    214     ELFFileFormat* file_format = getOutputFormat();
    215     // set .rela.dyn size
    216     if (!m_pRelaDyn->empty()) {
    217       assert(
    218           !config().isCodeStatic() &&
    219           "static linkage should not result in a dynamic relocation section");
    220       file_format->getRelaDyn().setSize(m_pRelaDyn->numOfRelocs() *
    221                                         getRelaEntrySize());
    222     }
    223 
    224     // set .rela.plt size
    225     if (!m_pRelaPLT->empty()) {
    226       assert(
    227           !config().isCodeStatic() &&
    228           "static linkage should not result in a dynamic relocation section");
    229       file_format->getRelaPlt().setSize(m_pRelaPLT->numOfRelocs() *
    230                                         getRelaEntrySize());
    231     }
    232   }
    233 }
    234 
    235 void AArch64GNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
    236   const ELFFileFormat* file_format = getOutputFormat();
    237 
    238   // apply PLT
    239   if (file_format->hasPLT()) {
    240     assert(m_pPLT != NULL);
    241     m_pPLT->applyPLT0();
    242     m_pPLT->applyPLT1();
    243   }
    244 
    245   // apply GOTPLT
    246   if ((config().options().hasNow() && file_format->hasGOT()) ||
    247       file_format->hasGOTPLT()) {
    248     assert(m_pGOTPLT != NULL);
    249     if (LinkerConfig::DynObj == config().codeGenType())
    250       m_pGOTPLT->applyGOT0(file_format->getDynamic().addr());
    251     else {
    252       // executable file and object file? should fill with zero.
    253       m_pGOTPLT->applyGOT0(0);
    254     }
    255   }
    256 }
    257 
    258 AArch64ELFDynamic& AArch64GNULDBackend::dynamic() {
    259   assert(m_pDynamic != NULL);
    260   return *m_pDynamic;
    261 }
    262 
    263 const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const {
    264   assert(m_pDynamic != NULL);
    265   return *m_pDynamic;
    266 }
    267 
    268 uint64_t AArch64GNULDBackend::emitSectionData(const LDSection& pSection,
    269                                               MemoryRegion& pRegion) const {
    270   assert(pRegion.size() && "Size of MemoryRegion is zero!");
    271 
    272   const ELFFileFormat* file_format = getOutputFormat();
    273 
    274   if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
    275     uint64_t result = m_pPLT->emit(pRegion);
    276     return result;
    277   }
    278 
    279   if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
    280     uint64_t result = m_pGOT->emit(pRegion);
    281     return result;
    282   }
    283 
    284   if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
    285     uint64_t result = m_pGOT->emit(pRegion);
    286     return result;
    287   }
    288 
    289   return pRegion.size();
    290 }
    291 
    292 unsigned int AArch64GNULDBackend::getTargetSectionOrder(
    293     const LDSection& pSectHdr) const {
    294   const ELFFileFormat* file_format = getOutputFormat();
    295 
    296   if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
    297     if (config().options().hasNow())
    298       return SHO_RELRO;
    299     return SHO_RELRO_LAST;
    300   }
    301 
    302   if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
    303     return SHO_NON_RELRO_FIRST;
    304 
    305   if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
    306     return SHO_PLT;
    307 
    308   return SHO_UNDEFINED;
    309 }
    310 
    311 void AArch64GNULDBackend::scanErrata(Module& pModule,
    312                                      IRBuilder& pBuilder,
    313                                      size_t& num_new_stubs,
    314                                      size_t& stubs_strlen) {
    315   // TODO: Implement AArch64 ErrataStubFactory to create the specific erratum
    316   //       stub and simplify the logics.
    317   for (Module::iterator sect = pModule.begin(), sectEnd = pModule.end();
    318        sect != sectEnd; ++sect) {
    319     if (((*sect)->kind() == LDFileFormat::TEXT) && (*sect)->hasSectionData()) {
    320       SectionData* sd = (*sect)->getSectionData();
    321       for (SectionData::iterator it = sd->begin(), ie = sd->end(); it != ie;
    322            ++it) {
    323         Fragment* frag = llvm::dyn_cast<RegionFragment>(it);
    324         if (frag != NULL) {
    325           FragmentRef* frag_ref = FragmentRef::Create(*frag, 0);
    326           for (unsigned offset = 0; offset < frag->size();
    327                offset += AArch64InsnHelpers::InsnSize) {
    328             Stub* stub = getStubFactory()->create(*frag_ref,
    329                                                   pBuilder,
    330                                                   *getBRIslandFactory());
    331             if (stub != NULL) {
    332               // A stub symbol should be local
    333               assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
    334               const AArch64CA53ErratumStub* erratum_stub =
    335                   reinterpret_cast<const AArch64CA53ErratumStub*>(stub);
    336               assert(erratum_stub != NULL);
    337               // Rewrite the erratum instruction as a branch to the stub.
    338               uint64_t offset = frag_ref->offset() +
    339                                 erratum_stub->getErratumInsnOffset();
    340               Relocation* reloc =
    341                   Relocation::Create(llvm::ELF::R_AARCH64_JUMP26,
    342                                      *(FragmentRef::Create(*frag, offset)),
    343                                      /* pAddend */0);
    344               reloc->setSymInfo(stub->symInfo());
    345               reloc->target() = AArch64InsnHelpers::buildBranchInsn();
    346               addExtraRelocation(reloc);
    347 
    348               ++num_new_stubs;
    349               stubs_strlen += stub->symInfo()->nameSize() + 1;
    350             }
    351 
    352             frag_ref->assign(*frag, offset + AArch64InsnHelpers::InsnSize);
    353           }  // for each INSN
    354         }
    355       }  // for each FRAGMENT
    356     }
    357   }  // for each TEXT section
    358 }
    359 
    360 bool AArch64GNULDBackend::doRelax(Module& pModule,
    361                                   IRBuilder& pBuilder,
    362                                   bool& pFinished) {
    363   assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
    364 
    365   // Number of new stubs added
    366   size_t num_new_stubs = 0;
    367   // String lengh to hold new stub symbols
    368   size_t stubs_strlen = 0;
    369 
    370   if (config().targets().fixCA53Erratum835769() ||
    371       config().targets().fixCA53Erratum843419()) {
    372     scanErrata(pModule, pBuilder, num_new_stubs, stubs_strlen);
    373   }
    374 
    375   ELFFileFormat* file_format = getOutputFormat();
    376   // check branch relocs and create the related stubs if needed
    377   Module::obj_iterator input, inEnd = pModule.obj_end();
    378   for (input = pModule.obj_begin(); input != inEnd; ++input) {
    379     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    380     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
    381       if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
    382         continue;
    383       RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
    384       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
    385         Relocation* relocation = llvm::cast<Relocation>(reloc);
    386 
    387         switch (relocation->type()) {
    388           case llvm::ELF::R_AARCH64_CALL26:
    389           case llvm::ELF::R_AARCH64_JUMP26: {
    390             // calculate the possible symbol value
    391             uint64_t sym_value = 0x0;
    392             LDSymbol* symbol = relocation->symInfo()->outSymbol();
    393             if (symbol->hasFragRef()) {
    394               uint64_t value = symbol->fragRef()->getOutputOffset();
    395               uint64_t addr =
    396                   symbol->fragRef()->frag()->getParent()->getSection().addr();
    397               sym_value = addr + value;
    398             }
    399             if ((relocation->symInfo()->reserved() &
    400                  AArch64Relocator::ReservePLT) != 0x0) {
    401               // FIXME: we need to find out the address of the specific plt
    402               // entry
    403               assert(file_format->hasPLT());
    404               sym_value = file_format->getPLT().addr();
    405             }
    406             Stub* stub = getStubFactory()->create(*relocation,  // relocation
    407                                                   sym_value,    // symbol value
    408                                                   pBuilder,
    409                                                   *getBRIslandFactory());
    410             if (stub != NULL) {
    411               // a stub symbol should be local
    412               assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
    413               // reset the branch target of the reloc to this stub instead
    414               relocation->setSymInfo(stub->symInfo());
    415 
    416               ++num_new_stubs;
    417               stubs_strlen += stub->symInfo()->nameSize() + 1;
    418             }
    419             break;
    420           }
    421           default: {
    422             break;
    423           }
    424         }  // end of switch
    425       }  // for all relocations
    426     }  // for all relocation section
    427   }  // for all inputs
    428 
    429   // Find the first fragment w/ invalid offset due to stub insertion.
    430   std::vector<Fragment*> invalid_frags;
    431   pFinished = true;
    432   for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
    433                                      island_end = getBRIslandFactory()->end();
    434        island != island_end;
    435        ++island) {
    436     if ((*island).size() > stubGroupSize()) {
    437       error(diag::err_no_space_to_place_stubs) << stubGroupSize();
    438       return false;
    439     }
    440 
    441     if ((*island).numOfStubs() == 0) {
    442       continue;
    443     }
    444 
    445     Fragment* exit = &*(*island).end();
    446     if (exit == &*(*island).begin()->getParent()->end()) {
    447       continue;
    448     }
    449 
    450     if (((*island).offset() + (*island).size()) > exit->getOffset()) {
    451       if (invalid_frags.empty() ||
    452           (invalid_frags.back()->getParent() != (*island).getParent())) {
    453         invalid_frags.push_back(exit);
    454         pFinished = false;
    455       }
    456       continue;
    457     }
    458   }
    459 
    460   // Reset the offset of invalid fragments.
    461   for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie;
    462        ++it) {
    463     Fragment* invalid = *it;
    464     while (invalid != NULL) {
    465       invalid->setOffset(invalid->getPrevNode()->getOffset() +
    466                          invalid->getPrevNode()->size());
    467       invalid = invalid->getNextNode();
    468     }
    469   }
    470 
    471   // Fix up the size of .symtab, .strtab, and TEXT sections
    472   if (num_new_stubs == 0) {
    473     return false;
    474   } else {
    475     switch (config().options().getStripSymbolMode()) {
    476       case GeneralOptions::StripSymbolMode::StripAllSymbols:
    477       case GeneralOptions::StripSymbolMode::StripLocals:
    478         break;
    479       default: {
    480         LDSection& symtab = file_format->getSymTab();
    481         LDSection& strtab = file_format->getStrTab();
    482 
    483         symtab.setSize(symtab.size() +
    484                        sizeof(llvm::ELF::Elf64_Sym) * num_new_stubs);
    485         symtab.setInfo(symtab.getInfo() + num_new_stubs);
    486         strtab.setSize(strtab.size() + stubs_strlen);
    487       }
    488     }  // switch (config().options().getStripSymbolMode())
    489 
    490     SectionData* prev = NULL;
    491     for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
    492                                        island_end = getBRIslandFactory()->end();
    493          island != island_end;
    494          ++island) {
    495       SectionData* sd = (*island).begin()->getParent();
    496       if ((*island).numOfStubs() != 0) {
    497         if (sd != prev) {
    498           sd->getSection().setSize(sd->back().getOffset() + sd->back().size());
    499         }
    500       }
    501       prev = sd;
    502     }
    503     return true;
    504   }  // if (num_new_stubs == 0)
    505 }
    506 
    507 bool AArch64GNULDBackend::initTargetStubs() {
    508   StubFactory* factory = getStubFactory();
    509   if (factory != NULL) {
    510     factory->addPrototype(new AArch64LongBranchStub(config().isCodeIndep()));
    511     if (config().targets().fixCA53Erratum835769()) {
    512       factory->addPrototype(new AArch64CA53Erratum835769Stub());
    513     }
    514     if (config().targets().fixCA53Erratum843419()) {
    515       factory->addPrototype(new AArch64CA53Erratum843419Stub());
    516       factory->addPrototype(new AArch64CA53Erratum843419Stub2());
    517     }
    518     return true;
    519   }
    520   return false;
    521 }
    522 
    523 void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule) {
    524 }
    525 
    526 bool AArch64GNULDBackend::finalizeTargetSymbols() {
    527   return true;
    528 }
    529 
    530 bool AArch64GNULDBackend::mergeSection(Module& pModule,
    531                                        const Input& pInput,
    532                                        LDSection& pSection) {
    533   return true;
    534 }
    535 
    536 bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD) {
    537   return true;
    538 }
    539 
    540 AArch64GOT& AArch64GNULDBackend::getGOT() {
    541   assert(m_pGOT != NULL && "GOT section not exist");
    542   return *m_pGOT;
    543 }
    544 
    545 const AArch64GOT& AArch64GNULDBackend::getGOT() const {
    546   assert(m_pGOT != NULL && "GOT section not exist");
    547   return *m_pGOT;
    548 }
    549 
    550 AArch64GOT& AArch64GNULDBackend::getGOTPLT() {
    551   assert(m_pGOTPLT != NULL && "GOTPLT section not exist");
    552   return *m_pGOTPLT;
    553 }
    554 
    555 const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const {
    556   assert(m_pGOTPLT != NULL && "GOTPLT section not exist");
    557   return *m_pGOTPLT;
    558 }
    559 
    560 AArch64PLT& AArch64GNULDBackend::getPLT() {
    561   assert(m_pPLT != NULL && "PLT section not exist");
    562   return *m_pPLT;
    563 }
    564 
    565 const AArch64PLT& AArch64GNULDBackend::getPLT() const {
    566   assert(m_pPLT != NULL && "PLT section not exist");
    567   return *m_pPLT;
    568 }
    569 
    570 OutputRelocSection& AArch64GNULDBackend::getRelaDyn() {
    571   assert(m_pRelaDyn != NULL && ".rela.dyn section not exist");
    572   return *m_pRelaDyn;
    573 }
    574 
    575 const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const {
    576   assert(m_pRelaDyn != NULL && ".rela.dyn section not exist");
    577   return *m_pRelaDyn;
    578 }
    579 
    580 OutputRelocSection& AArch64GNULDBackend::getRelaPLT() {
    581   assert(m_pRelaPLT != NULL && ".rela.plt section not exist");
    582   return *m_pRelaPLT;
    583 }
    584 
    585 const OutputRelocSection& AArch64GNULDBackend::getRelaPLT() const {
    586   assert(m_pRelaPLT != NULL && ".rela.plt section not exist");
    587   return *m_pRelaPLT;
    588 }
    589 
    590 //===----------------------------------------------------------------------===//
    591 //  createAArch64LDBackend - the help funtion to create corresponding
    592 //  AArch64LDBackend
    593 //===----------------------------------------------------------------------===//
    594 TargetLDBackend* createAArch64LDBackend(const LinkerConfig& pConfig) {
    595   if (pConfig.targets().triple().isOSDarwin()) {
    596     assert(0 && "MachO linker is not supported yet");
    597     /**
    598     return new AArch64MachOLDBackend(createAArch64MachOArchiveReader,
    599                                      createAArch64MachOObjectReader,
    600                                      createAArch64MachOObjectWriter);
    601     **/
    602   }
    603   if (pConfig.targets().triple().isOSWindows()) {
    604     assert(0 && "COFF linker is not supported yet");
    605     /**
    606     return new AArch64COFFLDBackend(createAArch64COFFArchiveReader,
    607                                     createAArch64COFFObjectReader,
    608                                     createAArch64COFFObjectWriter);
    609     **/
    610   }
    611   return new AArch64GNULDBackend(
    612       pConfig, new AArch64GNUInfo(pConfig.targets().triple()));
    613 }
    614 
    615 }  // namespace mcld
    616 
    617 //===----------------------------------------------------------------------===//
    618 // Force static initialization.
    619 //===----------------------------------------------------------------------===//
    620 extern "C" void MCLDInitializeAArch64LDBackend() {
    621   // Register the linker backend
    622   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheAArch64Target,
    623                                                 mcld::createAArch64LDBackend);
    624 }
    625