1 //===- ARMLDBackend.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 "ARM.h"
10 #include "ARMGNUInfo.h"
11 #include "ARMELFDynamic.h"
12 #include "ARMLDBackend.h"
13 #include "ARMRelocator.h"
14 #include "ARMToARMStub.h"
15 #include "ARMToTHMStub.h"
16 #include "THMToTHMStub.h"
17 #include "THMToARMStub.h"
18
19 #include <cstring>
20
21 #include <llvm/ADT/Triple.h>
22 #include <llvm/ADT/Twine.h>
23 #include <llvm/Support/ELF.h>
24 #include <llvm/Support/Casting.h>
25
26 #include <mcld/IRBuilder.h>
27 #include <mcld/LinkerConfig.h>
28 #include <mcld/Fragment/FillFragment.h>
29 #include <mcld/Fragment/AlignFragment.h>
30 #include <mcld/Fragment/RegionFragment.h>
31 #include <mcld/Support/MemoryRegion.h>
32 #include <mcld/Support/MemoryArea.h>
33 #include <mcld/Support/MsgHandling.h>
34 #include <mcld/Support/TargetRegistry.h>
35 #include <mcld/Fragment/Stub.h>
36 #include <mcld/LD/BranchIslandFactory.h>
37 #include <mcld/LD/StubFactory.h>
38 #include <mcld/Object/ObjectBuilder.h>
39 #include <mcld/Fragment/NullFragment.h>
40 #include <mcld/LD/LDContext.h>
41 #include <mcld/Target/GNUInfo.h>
42
43 using namespace mcld;
44
45 //===----------------------------------------------------------------------===//
46 // ARMGNULDBackend
47 //===----------------------------------------------------------------------===//
ARMGNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)48 ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo)
49 : GNULDBackend(pConfig, pInfo),
50 m_pRelocator(NULL),
51 m_pGOT(NULL),
52 m_pPLT(NULL),
53 m_pRelDyn(NULL),
54 m_pRelPLT(NULL),
55 m_pDynamic(NULL),
56 m_pGOTSymbol(NULL),
57 m_pEXIDXStart(NULL),
58 m_pEXIDXEnd(NULL),
59 m_pEXIDX(NULL),
60 m_pEXTAB(NULL),
61 m_pAttributes(NULL) {
62 }
63
~ARMGNULDBackend()64 ARMGNULDBackend::~ARMGNULDBackend()
65 {
66 delete m_pRelocator;
67 delete m_pGOT;
68 delete m_pPLT;
69 delete m_pRelDyn;
70 delete m_pRelPLT;
71 delete m_pDynamic;
72 }
73
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)74 void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
75 {
76 // FIXME: Currently we set exidx and extab to "Exception" and directly emit
77 // them from input
78 m_pEXIDX = pBuilder.CreateSection(".ARM.exidx",
79 LDFileFormat::Target,
80 llvm::ELF::SHT_ARM_EXIDX,
81 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
82 config().targets().bitclass() / 8);
83 m_pEXTAB = pBuilder.CreateSection(".ARM.extab",
84 LDFileFormat::Target,
85 llvm::ELF::SHT_PROGBITS,
86 llvm::ELF::SHF_ALLOC,
87 0x1);
88 m_pAttributes = pBuilder.CreateSection(".ARM.attributes",
89 LDFileFormat::Target,
90 llvm::ELF::SHT_ARM_ATTRIBUTES,
91 0x0,
92 0x1);
93
94 if (LinkerConfig::Object != config().codeGenType()) {
95 ELFFileFormat* file_format = getOutputFormat();
96
97 // initialize .got
98 LDSection& got = file_format->getGOT();
99 m_pGOT = new ARMGOT(got);
100
101 // initialize .plt
102 LDSection& plt = file_format->getPLT();
103 m_pPLT = new ARMPLT(plt, *m_pGOT);
104
105 // initialize .rel.plt
106 LDSection& relplt = file_format->getRelPlt();
107 relplt.setLink(&plt);
108 // create SectionData and ARMRelDynSection
109 m_pRelPLT = new OutputRelocSection(pModule, relplt);
110
111 // initialize .rel.dyn
112 LDSection& reldyn = file_format->getRelDyn();
113 m_pRelDyn = new OutputRelocSection(pModule, reldyn);
114 }
115 }
116
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)117 void ARMGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
118 {
119 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
120 // same name in input
121 if (LinkerConfig::Object != config().codeGenType()) {
122 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
123 "_GLOBAL_OFFSET_TABLE_",
124 ResolveInfo::Object,
125 ResolveInfo::Define,
126 ResolveInfo::Local,
127 0x0, // size
128 0x0, // value
129 FragmentRef::Null(),
130 ResolveInfo::Hidden);
131 }
132 if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
133 FragmentRef* exidx_start =
134 FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
135 FragmentRef* exidx_end =
136 FragmentRef::Create(m_pEXIDX->getSectionData()->front(),
137 m_pEXIDX->size());
138 m_pEXIDXStart =
139 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
140 "__exidx_start",
141 ResolveInfo::Object,
142 ResolveInfo::Define,
143 ResolveInfo::Local,
144 0x0, // size
145 0x0, // value
146 exidx_start, // FragRef
147 ResolveInfo::Default);
148
149 m_pEXIDXEnd =
150 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
151 "__exidx_end",
152 ResolveInfo::Object,
153 ResolveInfo::Define,
154 ResolveInfo::Local,
155 0x0, // size
156 0x0, // value
157 exidx_end, // FragRef
158 ResolveInfo::Default);
159 // change __exidx_start/_end to local dynamic category
160 if (NULL != m_pEXIDXStart)
161 pModule.getSymbolTable().changeToDynamic(*m_pEXIDXStart);
162 if (NULL != m_pEXIDXEnd)
163 pModule.getSymbolTable().changeToDynamic(*m_pEXIDXEnd);
164 } else {
165 m_pEXIDXStart =
166 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
167 "__exidx_start",
168 ResolveInfo::NoType,
169 ResolveInfo::Define,
170 ResolveInfo::Absolute,
171 0x0, // size
172 0x0, // value
173 FragmentRef::Null(),
174 ResolveInfo::Default);
175
176 m_pEXIDXEnd =
177 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
178 "__exidx_end",
179 ResolveInfo::NoType,
180 ResolveInfo::Define,
181 ResolveInfo::Absolute,
182 0x0, // size
183 0x0, // value
184 FragmentRef::Null(),
185 ResolveInfo::Default);
186 }
187 }
188
initRelocator()189 bool ARMGNULDBackend::initRelocator()
190 {
191 if (NULL == m_pRelocator) {
192 m_pRelocator = new ARMRelocator(*this, config());
193 }
194 return true;
195 }
196
getRelocator()197 Relocator* ARMGNULDBackend::getRelocator()
198 {
199 assert(NULL != m_pRelocator);
200 return m_pRelocator;
201 }
202
doPreLayout(IRBuilder & pBuilder)203 void ARMGNULDBackend::doPreLayout(IRBuilder& pBuilder)
204 {
205 // initialize .dynamic data
206 if (!config().isCodeStatic() && NULL == m_pDynamic)
207 m_pDynamic = new ARMELFDynamic(*this, config());
208
209 // set .got size
210 // when building shared object, the .got section is must
211 if (LinkerConfig::Object != config().codeGenType()) {
212 if (LinkerConfig::DynObj == config().codeGenType() ||
213 m_pGOT->hasGOT1() ||
214 NULL != m_pGOTSymbol) {
215 m_pGOT->finalizeSectionSize();
216 defineGOTSymbol(pBuilder);
217 }
218
219 // set .plt size
220 if (m_pPLT->hasPLT1())
221 m_pPLT->finalizeSectionSize();
222
223 ELFFileFormat* file_format = getOutputFormat();
224 // set .rel.dyn size
225 if (!m_pRelDyn->empty()) {
226 assert(!config().isCodeStatic() &&
227 "static linkage should not result in a dynamic relocation section");
228 file_format->getRelDyn().setSize(
229 m_pRelDyn->numOfRelocs() * getRelEntrySize());
230 }
231
232 // set .rel.plt size
233 if (!m_pRelPLT->empty()) {
234 assert(!config().isCodeStatic() &&
235 "static linkage should not result in a dynamic relocation section");
236 file_format->getRelPlt().setSize(
237 m_pRelPLT->numOfRelocs() * getRelEntrySize());
238 }
239 }
240 }
241
doPostLayout(Module & pModule,IRBuilder & pBuilder)242 void ARMGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
243 {
244 const ELFFileFormat *file_format = getOutputFormat();
245
246 // apply PLT
247 if (file_format->hasPLT()) {
248 // Since we already have the size of LDSection PLT, m_pPLT should not be
249 // NULL.
250 assert(NULL != m_pPLT);
251 m_pPLT->applyPLT0();
252 m_pPLT->applyPLT1();
253 }
254
255 // apply GOT
256 if (file_format->hasGOT()) {
257 // Since we already have the size of GOT, m_pGOT should not be NULL.
258 assert(NULL != m_pGOT);
259 if (LinkerConfig::DynObj == config().codeGenType())
260 m_pGOT->applyGOT0(file_format->getDynamic().addr());
261 else {
262 // executable file and object file? should fill with zero.
263 m_pGOT->applyGOT0(0);
264 }
265 }
266 }
267
268 /// dynamic - the dynamic section of the target machine.
269 /// Use co-variant return type to return its own dynamic section.
dynamic()270 ARMELFDynamic& ARMGNULDBackend::dynamic()
271 {
272 assert(NULL != m_pDynamic);
273 return *m_pDynamic;
274 }
275
276 /// dynamic - the dynamic section of the target machine.
277 /// Use co-variant return type to return its own dynamic section.
dynamic() const278 const ARMELFDynamic& ARMGNULDBackend::dynamic() const
279 {
280 assert(NULL != m_pDynamic);
281 return *m_pDynamic;
282 }
283
defineGOTSymbol(IRBuilder & pBuilder)284 void ARMGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
285 {
286 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
287 if (m_pGOTSymbol != NULL) {
288 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
289 "_GLOBAL_OFFSET_TABLE_",
290 ResolveInfo::Object,
291 ResolveInfo::Define,
292 ResolveInfo::Local,
293 0x0, // size
294 0x0, // value
295 FragmentRef::Create(*(m_pGOT->begin()), 0x0),
296 ResolveInfo::Hidden);
297 }
298 else {
299 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
300 "_GLOBAL_OFFSET_TABLE_",
301 ResolveInfo::Object,
302 ResolveInfo::Define,
303 ResolveInfo::Local,
304 0x0, // size
305 0x0, // value
306 FragmentRef::Create(*(m_pGOT->begin()), 0x0),
307 ResolveInfo::Hidden);
308 }
309
310 }
311
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const312 uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
313 MemoryRegion& pRegion) const
314 {
315 assert(pRegion.size() && "Size of MemoryRegion is zero!");
316
317 const ELFFileFormat* file_format = getOutputFormat();
318
319 if (&pSection == m_pAttributes ||
320 &pSection == m_pEXIDX ||
321 &pSection == m_pEXTAB) {
322 // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
323 // directly from the input file.
324 const SectionData* sect_data = pSection.getSectionData();
325 SectionData::const_iterator frag_iter, frag_end = sect_data->end();
326 uint8_t* out_offset = pRegion.start();
327 for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
328 size_t size = frag_iter->size();
329 switch(frag_iter->getKind()) {
330 case Fragment::Fillment: {
331 const FillFragment& fill_frag =
332 llvm::cast<FillFragment>(*frag_iter);
333 if (0 == fill_frag.getValueSize()) {
334 // virtual fillment, ignore it.
335 break;
336 }
337
338 memset(out_offset, fill_frag.getValue(), fill_frag.size());
339 break;
340 }
341 case Fragment::Region: {
342 const RegionFragment& region_frag =
343 llvm::cast<RegionFragment>(*frag_iter);
344 const uint8_t* start = region_frag.getRegion().start();
345 memcpy(out_offset, start, size);
346 break;
347 }
348 case Fragment::Alignment: {
349 const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
350 uint64_t count = size / align_frag.getValueSize();
351 switch (align_frag.getValueSize()) {
352 case 1u:
353 std::memset(out_offset, align_frag.getValue(), count);
354 break;
355 default:
356 llvm::report_fatal_error(
357 "unsupported value size for align fragment emission yet.\n");
358 break;
359 } // end switch
360 break;
361 }
362 case Fragment::Null: {
363 assert(0x0 == size);
364 break;
365 }
366 default:
367 llvm::report_fatal_error("unsupported fragment type.\n");
368 break;
369 } // end switch
370 out_offset += size;
371 } // end for
372 return pRegion.size();
373 } // end if
374
375 if (&pSection == &(file_format->getPLT())) {
376 assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
377 uint64_t result = m_pPLT->emit(pRegion);
378 return result;
379 }
380
381 if (&pSection == &(file_format->getGOT())) {
382 assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
383 uint64_t result = m_pGOT->emit(pRegion);
384 return result;
385 }
386 fatal(diag::unrecognized_output_sectoin)
387 << pSection.name()
388 << "mclinker@googlegroups.com";
389 return 0x0;
390 }
391
392 /// finalizeSymbol - finalize the symbol value
finalizeTargetSymbols()393 bool ARMGNULDBackend::finalizeTargetSymbols()
394 {
395 return true;
396 }
397
mergeSection(Module & pModule,LDSection & pSection)398 bool ARMGNULDBackend::mergeSection(Module& pModule, LDSection& pSection)
399 {
400 switch (pSection.type()) {
401 case llvm::ELF::SHT_ARM_ATTRIBUTES: {
402 // FIXME: (Luba)
403 // Handle ARM attributes in the right way.
404 // In current milestone, we goes through the shortcut.
405 // It reads input's ARM attributes and copies the first ARM attributes
406 // into the output file. The correct way is merge these sections, not
407 // just copy.
408 if (0 != m_pAttributes->size())
409 return true;
410
411 // First time we meet a ARM attributes section.
412 SectionData* sd = IRBuilder::CreateSectionData(*m_pAttributes);
413 ObjectBuilder::MoveSectionData(*pSection.getSectionData(), *sd);
414 return true;
415 }
416 default: {
417 ObjectBuilder builder(config(), pModule);
418 return builder.MergeSection(pSection);
419 }
420 } // end of switch
421 return true;
422 }
423
readSection(Input & pInput,SectionData & pSD)424 bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD)
425 {
426 Fragment* frag = NULL;
427 uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
428 uint32_t size = pSD.getSection().size();
429
430 MemoryRegion* region = pInput.memArea()->request(offset, size);
431 if (NULL == region) {
432 // If the input section's size is zero, we got a NULL region.
433 // use a virtual fill fragment
434 frag = new FillFragment(0x0, 0, 0);
435 }
436 else {
437 frag = new RegionFragment(*region);
438 }
439
440 ObjectBuilder::AppendFragment(*frag, pSD);
441 return true;
442 }
443
getGOT()444 ARMGOT& ARMGNULDBackend::getGOT()
445 {
446 assert(NULL != m_pGOT && "GOT section not exist");
447 return *m_pGOT;
448 }
449
getGOT() const450 const ARMGOT& ARMGNULDBackend::getGOT() const
451 {
452 assert(NULL != m_pGOT && "GOT section not exist");
453 return *m_pGOT;
454 }
455
getPLT()456 ARMPLT& ARMGNULDBackend::getPLT()
457 {
458 assert(NULL != m_pPLT && "PLT section not exist");
459 return *m_pPLT;
460 }
461
getPLT() const462 const ARMPLT& ARMGNULDBackend::getPLT() const
463 {
464 assert(NULL != m_pPLT && "PLT section not exist");
465 return *m_pPLT;
466 }
467
getRelDyn()468 OutputRelocSection& ARMGNULDBackend::getRelDyn()
469 {
470 assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
471 return *m_pRelDyn;
472 }
473
getRelDyn() const474 const OutputRelocSection& ARMGNULDBackend::getRelDyn() const
475 {
476 assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
477 return *m_pRelDyn;
478 }
479
getRelPLT()480 OutputRelocSection& ARMGNULDBackend::getRelPLT()
481 {
482 assert(NULL != m_pRelPLT && ".rel.plt section not exist");
483 return *m_pRelPLT;
484 }
485
getRelPLT() const486 const OutputRelocSection& ARMGNULDBackend::getRelPLT() const
487 {
488 assert(NULL != m_pRelPLT && ".rel.plt section not exist");
489 return *m_pRelPLT;
490 }
491
492 unsigned int
getTargetSectionOrder(const LDSection & pSectHdr) const493 ARMGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
494 {
495 const ELFFileFormat* file_format = getOutputFormat();
496
497 if (&pSectHdr == &file_format->getGOT()) {
498 if (config().options().hasNow())
499 return SHO_RELRO_LAST;
500 return SHO_DATA;
501 }
502
503 if (&pSectHdr == &file_format->getPLT())
504 return SHO_PLT;
505
506 if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
507 // put ARM.exidx and ARM.extab in the same order of .eh_frame
508 return SHO_EXCEPTION;
509 }
510
511 return SHO_UNDEFINED;
512 }
513
514 /// doRelax
515 bool
doRelax(Module & pModule,IRBuilder & pBuilder,bool & pFinished)516 ARMGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished)
517 {
518 assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
519
520 bool isRelaxed = false;
521 ELFFileFormat* file_format = getOutputFormat();
522 // check branch relocs and create the related stubs if needed
523 Module::obj_iterator input, inEnd = pModule.obj_end();
524 for (input = pModule.obj_begin(); input != inEnd; ++input) {
525 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
526 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
527 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
528 continue;
529 RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
530 for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
531 Relocation* relocation = llvm::cast<Relocation>(reloc);
532
533 switch (relocation->type()) {
534 case llvm::ELF::R_ARM_PC24:
535 case llvm::ELF::R_ARM_CALL:
536 case llvm::ELF::R_ARM_JUMP24:
537 case llvm::ELF::R_ARM_PLT32:
538 case llvm::ELF::R_ARM_THM_CALL:
539 case llvm::ELF::R_ARM_THM_XPC22:
540 case llvm::ELF::R_ARM_THM_JUMP24:
541 case llvm::ELF::R_ARM_THM_JUMP19:
542 case llvm::ELF::R_ARM_V4BX: {
543 // calculate the possible symbol value
544 uint64_t sym_value = 0x0;
545 LDSymbol* symbol = relocation->symInfo()->outSymbol();
546 if (symbol->hasFragRef()) {
547 uint64_t value = symbol->fragRef()->getOutputOffset();
548 uint64_t addr =
549 symbol->fragRef()->frag()->getParent()->getSection().addr();
550 sym_value = addr + value;
551 }
552 if (relocation->symInfo()->isGlobal() &&
553 (relocation->symInfo()->reserved() & ARMRelocator::ReservePLT) != 0x0) {
554 // FIXME: we need to find out the address of the specific plt entry
555 assert(file_format->hasPLT());
556 sym_value = file_format->getPLT().addr();
557 }
558
559 Stub* stub = getStubFactory()->create(*relocation, // relocation
560 sym_value, // symbol value
561 pBuilder,
562 *getBRIslandFactory());
563 if (NULL != stub) {
564 // a stub symbol should be local
565 assert(NULL != stub->symInfo() && stub->symInfo()->isLocal());
566 LDSection& symtab = file_format->getSymTab();
567 LDSection& strtab = file_format->getStrTab();
568
569 // increase the size of .symtab and .strtab if needed
570 if (config().targets().is32Bits())
571 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
572 else
573 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym));
574 symtab.setInfo(symtab.getInfo() + 1);
575 strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
576
577 isRelaxed = true;
578 }
579 break;
580 }
581 default:
582 break;
583 } // end of switch
584
585 } // for all relocations
586 } // for all relocation section
587 } // for all inputs
588
589 // find the first fragment w/ invalid offset due to stub insertion
590 Fragment* invalid = NULL;
591 pFinished = true;
592 for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
593 island_end = getBRIslandFactory()->end(); island != island_end; ++island) {
594 if ((*island).end() == file_format->getText().getSectionData()->end())
595 break;
596
597 Fragment* exit = (*island).end();
598 if (((*island).offset() + (*island).size()) > exit->getOffset()) {
599 invalid = exit;
600 pFinished = false;
601 break;
602 }
603 }
604
605 // reset the offset of invalid fragments
606 while (NULL != invalid) {
607 invalid->setOffset(invalid->getPrevNode()->getOffset() +
608 invalid->getPrevNode()->size());
609 invalid = invalid->getNextNode();
610 }
611
612 // reset the size of .text
613 if (isRelaxed) {
614 file_format->getText().setSize(
615 file_format->getText().getSectionData()->back().getOffset() +
616 file_format->getText().getSectionData()->back().size());
617 }
618 return isRelaxed;
619 }
620
621 /// initTargetStubs
initTargetStubs()622 bool ARMGNULDBackend::initTargetStubs()
623 {
624 if (NULL != getStubFactory()) {
625 getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep()));
626 getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep()));
627 getStubFactory()->addPrototype(new THMToTHMStub(config().isCodeIndep()));
628 getStubFactory()->addPrototype(new THMToARMStub(config().isCodeIndep()));
629 return true;
630 }
631 return false;
632 }
633
634 /// doCreateProgramHdrs - backend can implement this function to create the
635 /// target-dependent segments
doCreateProgramHdrs(Module & pModule)636 void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule)
637 {
638 if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
639 // make PT_ARM_EXIDX
640 ELFSegment* exidx_seg = elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX,
641 llvm::ELF::PF_R);
642 exidx_seg->addSection(m_pEXIDX);
643 }
644 }
645
646 namespace mcld {
647
648 //===----------------------------------------------------------------------===//
649 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
650 ///
createARMLDBackend(const llvm::Target & pTarget,const LinkerConfig & pConfig)651 TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
652 const LinkerConfig& pConfig)
653 {
654 if (pConfig.targets().triple().isOSDarwin()) {
655 assert(0 && "MachO linker is not supported yet");
656 /**
657 return new ARMMachOLDBackend(createARMMachOArchiveReader,
658 createARMMachOObjectReader,
659 createARMMachOObjectWriter);
660 **/
661 }
662 if (pConfig.targets().triple().isOSWindows()) {
663 assert(0 && "COFF linker is not supported yet");
664 /**
665 return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
666 createARMCOFFObjectReader,
667 createARMCOFFObjectWriter);
668 **/
669 }
670 return new ARMGNULDBackend(pConfig, new ARMGNUInfo(pConfig.targets().triple()));
671 }
672
673 } // namespace of mcld
674
675 //===----------------------------------------------------------------------===//
676 // Force static initialization.
677 //===----------------------------------------------------------------------===//
MCLDInitializeARMLDBackend()678 extern "C" void MCLDInitializeARMLDBackend() {
679 // Register the linker backend
680 mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
681 mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend);
682 }
683
684