• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //===----------------------------------------------------------------------===//
AArch64GNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)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 
~AArch64GNULDBackend()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 
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)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 
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)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 
initRelocator()143 bool AArch64GNULDBackend::initRelocator() {
144   if (m_pRelocator == NULL) {
145     m_pRelocator = new AArch64Relocator(*this, config());
146   }
147   return true;
148 }
149 
getRelocator() const150 const Relocator* AArch64GNULDBackend::getRelocator() const {
151   assert(m_pRelocator != NULL);
152   return m_pRelocator;
153 }
154 
getRelocator()155 Relocator* AArch64GNULDBackend::getRelocator() {
156   assert(m_pRelocator != NULL);
157   return m_pRelocator;
158 }
159 
defineGOTSymbol(IRBuilder & pBuilder)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 
doPreLayout(IRBuilder & pBuilder)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 
doPostLayout(Module & pModule,IRBuilder & pBuilder)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 
dynamic()258 AArch64ELFDynamic& AArch64GNULDBackend::dynamic() {
259   assert(m_pDynamic != NULL);
260   return *m_pDynamic;
261 }
262 
dynamic() const263 const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const {
264   assert(m_pDynamic != NULL);
265   return *m_pDynamic;
266 }
267 
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const268 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 
getTargetSectionOrder(const LDSection & pSectHdr) const292 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 
scanErrata(Module & pModule,IRBuilder & pBuilder,size_t & num_new_stubs,size_t & stubs_strlen)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 
doRelax(Module & pModule,IRBuilder & pBuilder,bool & pFinished)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 
initTargetStubs()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 
doCreateProgramHdrs(Module & pModule)523 void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule) {
524 }
525 
finalizeTargetSymbols()526 bool AArch64GNULDBackend::finalizeTargetSymbols() {
527   return true;
528 }
529 
mergeSection(Module & pModule,const Input & pInput,LDSection & pSection)530 bool AArch64GNULDBackend::mergeSection(Module& pModule,
531                                        const Input& pInput,
532                                        LDSection& pSection) {
533   return true;
534 }
535 
readSection(Input & pInput,SectionData & pSD)536 bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD) {
537   return true;
538 }
539 
getGOT()540 AArch64GOT& AArch64GNULDBackend::getGOT() {
541   assert(m_pGOT != NULL && "GOT section not exist");
542   return *m_pGOT;
543 }
544 
getGOT() const545 const AArch64GOT& AArch64GNULDBackend::getGOT() const {
546   assert(m_pGOT != NULL && "GOT section not exist");
547   return *m_pGOT;
548 }
549 
getGOTPLT()550 AArch64GOT& AArch64GNULDBackend::getGOTPLT() {
551   assert(m_pGOTPLT != NULL && "GOTPLT section not exist");
552   return *m_pGOTPLT;
553 }
554 
getGOTPLT() const555 const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const {
556   assert(m_pGOTPLT != NULL && "GOTPLT section not exist");
557   return *m_pGOTPLT;
558 }
559 
getPLT()560 AArch64PLT& AArch64GNULDBackend::getPLT() {
561   assert(m_pPLT != NULL && "PLT section not exist");
562   return *m_pPLT;
563 }
564 
getPLT() const565 const AArch64PLT& AArch64GNULDBackend::getPLT() const {
566   assert(m_pPLT != NULL && "PLT section not exist");
567   return *m_pPLT;
568 }
569 
getRelaDyn()570 OutputRelocSection& AArch64GNULDBackend::getRelaDyn() {
571   assert(m_pRelaDyn != NULL && ".rela.dyn section not exist");
572   return *m_pRelaDyn;
573 }
574 
getRelaDyn() const575 const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const {
576   assert(m_pRelaDyn != NULL && ".rela.dyn section not exist");
577   return *m_pRelaDyn;
578 }
579 
getRelaPLT()580 OutputRelocSection& AArch64GNULDBackend::getRelaPLT() {
581   assert(m_pRelaPLT != NULL && ".rela.plt section not exist");
582   return *m_pRelaPLT;
583 }
584 
getRelaPLT() const585 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 //===----------------------------------------------------------------------===//
createAArch64LDBackend(const LinkerConfig & pConfig)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 //===----------------------------------------------------------------------===//
MCLDInitializeAArch64LDBackend()620 extern "C" void MCLDInitializeAArch64LDBackend() {
621   // Register the linker backend
622   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheAArch64Target,
623                                                 mcld::createAArch64LDBackend);
624 }
625