• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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