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