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