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