ARMLDBackend.cpp revision 04c59f3b00def22b7c75f5a490c323cec58a7c71
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
398
399/// preMergeSections - hooks to be executed before merging sections
400void ARMGNULDBackend::preMergeSections(Module& pModule) {
401  scanInputExceptionSections(pModule);
402}
403
404/// postMergeSections - hooks to be executed after merging sections
405void ARMGNULDBackend::postMergeSections(Module& pModule) {
406  if (m_pEXIDX->hasSectionData()) {
407    // Append the NullFragment so that __exidx_end can be correctly inserted.
408    NullFragment* null = new NullFragment(m_pEXIDX->getSectionData());
409    null->setOffset(m_pEXIDX->size());
410  }
411}
412
413bool ARMGNULDBackend::mergeSection(Module& pModule,
414                                   const Input& pInput,
415                                   LDSection& pSection) {
416  switch (pSection.type()) {
417    case llvm::ELF::SHT_ARM_ATTRIBUTES: {
418      return attribute().merge(pInput, pSection);
419    }
420
421    case llvm::ELF::SHT_ARM_EXIDX: {
422      assert(pSection.getLink() != NULL);
423      if ((pSection.getLink()->kind() == LDFileFormat::Ignore) ||
424          (pSection.getLink()->kind() == LDFileFormat::Folded)) {
425        // if the target section of the .ARM.exidx is Ignore, then it should be
426        // ignored as well
427        pSection.setKind(LDFileFormat::Ignore);
428        return true;
429      }
430
431      if (!m_pEXIDX->hasSectionData()) {
432        // Create SectionData for m_pEXIDX.
433        SectionData* sectData = IRBuilder::CreateSectionData(*m_pEXIDX);
434
435        // Initialize the alignment of m_pEXIDX.
436        const size_t alignExIdx = 4;
437        m_pEXIDX->setAlign(alignExIdx);
438
439        // Insert an AlignFragment to the beginning of m_pEXIDX.
440        AlignFragment* frag =
441            new AlignFragment(/*alignment*/alignExIdx,
442                              /*the filled value*/0x0,
443                              /*the size of filled value*/1u,
444                              /*max bytes to emit*/alignExIdx - 1);
445        frag->setOffset(0);
446        frag->setParent(sectData);
447        sectData->getFragmentList().push_back(frag);
448        m_pEXIDX->setSize(frag->size());
449      }
450
451      // Move RegionFragment from pSection to m_pEXIDX.
452      uint64_t offset = m_pEXIDX->size();
453      SectionData::FragmentListType& src =
454          pSection.getSectionData()->getFragmentList();
455      SectionData::FragmentListType& dst =
456          m_pEXIDX->getSectionData()->getFragmentList();
457      SectionData::FragmentListType::iterator frag = src.begin();
458      SectionData::FragmentListType::iterator fragEnd = src.end();
459      while (frag != fragEnd) {
460        if (frag->getKind() != Fragment::Region) {
461          ++frag;
462        } else {
463          frag->setParent(m_pEXIDX->getSectionData());
464          frag->setOffset(offset);
465          offset += frag->size();
466          dst.splice(dst.end(), src, frag++);
467        }
468      }
469
470      // Update the size of m_pEXIDX.
471      m_pEXIDX->setSize(offset);
472      return true;
473    }
474
475    default: {
476      ObjectBuilder builder(pModule);
477      builder.MergeSection(pInput, pSection);
478      return true;
479    }
480  }  // end of switch
481  return true;
482}
483
484void ARMGNULDBackend::setUpReachedSectionsForGC(
485    const Module& pModule,
486    GarbageCollection::SectionReachedListMap& pSectReachedListMap) const {
487  // traverse all the input relocations to find the relocation sections applying
488  // .ARM.exidx sections
489  Module::const_obj_iterator input, inEnd = pModule.obj_end();
490  for (input = pModule.obj_begin(); input != inEnd; ++input) {
491    LDContext::const_sect_iterator rs,
492        rsEnd = (*input)->context()->relocSectEnd();
493    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
494      // bypass the discarded relocation section
495      // 1. its section kind is changed to Ignore. (The target section is a
496      // discarded group section.)
497      // 2. it has no reloc data. (All symbols in the input relocs are in the
498      // discarded group sections)
499      LDSection* reloc_sect = *rs;
500      LDSection* apply_sect = reloc_sect->getLink();
501      if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
502          (!reloc_sect->hasRelocData()))
503        continue;
504
505      if (llvm::ELF::SHT_ARM_EXIDX == apply_sect->type()) {
506        // 1. set up the reference according to relocations
507        bool add_first = false;
508        GarbageCollection::SectionListTy* reached_sects = NULL;
509        RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
510        for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd;
511             ++reloc_it) {
512          Relocation* reloc = llvm::cast<Relocation>(reloc_it);
513          ResolveInfo* sym = reloc->symInfo();
514          // only the target symbols defined in the input fragments can make the
515          // reference
516          if (sym == NULL)
517            continue;
518          if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
519            continue;
520
521          // only the target symbols defined in the concerned sections can make
522          // the reference
523          const LDSection* target_sect =
524              &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
525          if (target_sect->kind() != LDFileFormat::TEXT &&
526              target_sect->kind() != LDFileFormat::DATA &&
527              target_sect->kind() != LDFileFormat::BSS)
528            continue;
529
530          // setup the reached list, if we first add the element to reached list
531          // of this section, create an entry in ReachedSections map
532          if (!add_first) {
533            reached_sects = &pSectReachedListMap.getReachedList(*apply_sect);
534            add_first = true;
535          }
536          reached_sects->insert(target_sect);
537        }
538        reached_sects = NULL;
539        add_first = false;
540        // 2. set up the reference from XXX to .ARM.exidx.XXX
541        assert(apply_sect->getLink() != NULL);
542        pSectReachedListMap.addReference(*apply_sect->getLink(), *apply_sect);
543      }
544    }
545  }
546}
547
548bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
549  Fragment* frag = NULL;
550  uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
551  uint32_t size = pSD.getSection().size();
552
553  llvm::StringRef region = pInput.memArea()->request(offset, size);
554  if (region.size() == 0) {
555    // If the input section's size is zero, we got a NULL region.
556    // use a virtual fill fragment
557    frag = new FillFragment(0x0, 0, 0);
558  } else {
559    frag = new RegionFragment(region);
560  }
561
562  ObjectBuilder::AppendFragment(*frag, pSD);
563  return true;
564}
565
566ARMGOT& ARMGNULDBackend::getGOT() {
567  assert(m_pGOT != NULL && "GOT section not exist");
568  return *m_pGOT;
569}
570
571const ARMGOT& ARMGNULDBackend::getGOT() const {
572  assert(m_pGOT != NULL && "GOT section not exist");
573  return *m_pGOT;
574}
575
576ARMPLT& ARMGNULDBackend::getPLT() {
577  assert(m_pPLT != NULL && "PLT section not exist");
578  return *m_pPLT;
579}
580
581const ARMPLT& ARMGNULDBackend::getPLT() const {
582  assert(m_pPLT != NULL && "PLT section not exist");
583  return *m_pPLT;
584}
585
586OutputRelocSection& ARMGNULDBackend::getRelDyn() {
587  assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
588  return *m_pRelDyn;
589}
590
591const OutputRelocSection& ARMGNULDBackend::getRelDyn() const {
592  assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
593  return *m_pRelDyn;
594}
595
596OutputRelocSection& ARMGNULDBackend::getRelPLT() {
597  assert(m_pRelPLT != NULL && ".rel.plt section not exist");
598  return *m_pRelPLT;
599}
600
601const OutputRelocSection& ARMGNULDBackend::getRelPLT() const {
602  assert(m_pRelPLT != NULL && ".rel.plt section not exist");
603  return *m_pRelPLT;
604}
605
606ARMELFAttributeData& ARMGNULDBackend::getAttributeData() {
607  assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
608  return *m_pAttrData;
609}
610
611const ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const {
612  assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
613  return *m_pAttrData;
614}
615
616unsigned int ARMGNULDBackend::getTargetSectionOrder(
617    const LDSection& pSectHdr) const {
618  const ELFFileFormat* file_format = getOutputFormat();
619
620  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
621    if (config().options().hasNow())
622      return SHO_RELRO_LAST;
623    return SHO_DATA;
624  }
625
626  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
627    return SHO_PLT;
628
629  if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
630    // put ARM.exidx and ARM.extab in the same order of .eh_frame
631    return SHO_EXCEPTION;
632  }
633
634  return SHO_UNDEFINED;
635}
636
637/// relax - the relaxation pass
638bool ARMGNULDBackend::relax(Module& pModule, IRBuilder& pBuilder) {
639  if (!GNULDBackend::relax(pModule, pBuilder)) {
640    return false;
641  }
642  rewriteARMExIdxSection(pModule);
643  return true;
644}
645
646/// doRelax
647bool ARMGNULDBackend::doRelax(Module& pModule,
648                              IRBuilder& pBuilder,
649                              bool& pFinished) {
650  assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
651
652  bool isRelaxed = false;
653  ELFFileFormat* file_format = getOutputFormat();
654  // check branch relocs and create the related stubs if needed
655  Module::obj_iterator input, inEnd = pModule.obj_end();
656  for (input = pModule.obj_begin(); input != inEnd; ++input) {
657    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
658    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
659      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
660        continue;
661      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
662      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
663        Relocation* relocation = llvm::cast<Relocation>(reloc);
664
665        switch (relocation->type()) {
666          case llvm::ELF::R_ARM_PC24:
667          case llvm::ELF::R_ARM_CALL:
668          case llvm::ELF::R_ARM_JUMP24:
669          case llvm::ELF::R_ARM_PLT32:
670          case llvm::ELF::R_ARM_THM_CALL:
671          case llvm::ELF::R_ARM_THM_XPC22:
672          case llvm::ELF::R_ARM_THM_JUMP24:
673          case llvm::ELF::R_ARM_THM_JUMP19: {
674            // calculate the possible symbol value
675            uint64_t sym_value = 0x0;
676            LDSymbol* symbol = relocation->symInfo()->outSymbol();
677            if (symbol->hasFragRef()) {
678              uint64_t value = symbol->fragRef()->getOutputOffset();
679              uint64_t addr =
680                  symbol->fragRef()->frag()->getParent()->getSection().addr();
681              sym_value = addr + value;
682            }
683            if ((relocation->symInfo()->reserved() &
684                 ARMRelocator::ReservePLT) != 0x0) {
685              // FIXME: we need to find out the address of the specific plt
686              // entry
687              assert(file_format->hasPLT());
688              sym_value = file_format->getPLT().addr();
689            }
690            Stub* stub = getStubFactory()->create(*relocation,  // relocation
691                                                  sym_value,    // symbol value
692                                                  pBuilder,
693                                                  *getBRIslandFactory());
694            if (stub != NULL) {
695              switch (config().options().getStripSymbolMode()) {
696                case GeneralOptions::StripAllSymbols:
697                case GeneralOptions::StripLocals:
698                  break;
699                default: {
700                  // a stub symbol should be local
701                  assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
702                  LDSection& symtab = file_format->getSymTab();
703                  LDSection& strtab = file_format->getStrTab();
704
705                  // increase the size of .symtab and .strtab if needed
706                  if (config().targets().is32Bits())
707                    symtab.setSize(symtab.size() +
708                                   sizeof(llvm::ELF::Elf32_Sym));
709                  else
710                    symtab.setSize(symtab.size() +
711                                   sizeof(llvm::ELF::Elf64_Sym));
712                  symtab.setInfo(symtab.getInfo() + 1);
713                  strtab.setSize(strtab.size() + stub->symInfo()->nameSize() +
714                                 1);
715                }
716              }  // end of switch
717              isRelaxed = true;
718            }
719            break;
720          }
721          case llvm::ELF::R_ARM_V4BX:
722            /* FIXME: bypass R_ARM_V4BX relocation now */
723            break;
724          default:
725            break;
726        }  // end of switch
727      }  // for all relocations
728    }  // for all relocation section
729  }  // for all inputs
730
731  // find the first fragment w/ invalid offset due to stub insertion
732  Fragment* invalid = NULL;
733  pFinished = true;
734  for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
735                                     island_end = getBRIslandFactory()->end();
736       island != island_end;
737       ++island) {
738    if ((*island).end() == file_format->getText().getSectionData()->end())
739      break;
740
741    Fragment* exit = (*island).end();
742    if (((*island).offset() + (*island).size()) > exit->getOffset()) {
743      invalid = exit;
744      pFinished = false;
745      break;
746    }
747  }
748
749  // reset the offset of invalid fragments
750  while (invalid != NULL) {
751    invalid->setOffset(invalid->getPrevNode()->getOffset() +
752                       invalid->getPrevNode()->size());
753    invalid = invalid->getNextNode();
754  }
755
756  // reset the size of .text
757  if (isRelaxed) {
758    file_format->getText().setSize(
759        file_format->getText().getSectionData()->back().getOffset() +
760        file_format->getText().getSectionData()->back().size());
761  }
762  return isRelaxed;
763}
764
765/// initTargetStubs
766bool ARMGNULDBackend::initTargetStubs() {
767  if (getStubFactory() != NULL) {
768    getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep()));
769    getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep()));
770    getStubFactory()->addPrototype(
771        new THMToTHMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
772    getStubFactory()->addPrototype(
773        new THMToARMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
774    return true;
775  }
776  return false;
777}
778
779/// maxFwdBranchOffset
780int64_t ARMGNULDBackend::maxFwdBranchOffset() {
781  if (m_pAttrData->usingThumb2()) {
782    return THM2_MAX_FWD_BRANCH_OFFSET;
783  } else {
784    return THM_MAX_FWD_BRANCH_OFFSET;
785  }
786}
787
788/// maxBwdBranchOffset
789int64_t ARMGNULDBackend::maxBwdBranchOffset() {
790  if (m_pAttrData->usingThumb2()) {
791    return THM2_MAX_BWD_BRANCH_OFFSET;
792  } else {
793    return THM_MAX_BWD_BRANCH_OFFSET;
794  }
795}
796
797/// doCreateProgramHdrs - backend can implement this function to create the
798/// target-dependent segments
799void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule) {
800  if (m_pEXIDX != NULL && m_pEXIDX->size() != 0x0) {
801    // make PT_ARM_EXIDX
802    ELFSegment* exidx_seg =
803        elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX, llvm::ELF::PF_R);
804    exidx_seg->append(m_pEXIDX);
805  }
806}
807
808/// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
809/// function pointer access
810bool ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess(
811    const LDSection& pSection) const {
812  llvm::StringRef name(pSection.name());
813  return !name.startswith(".ARM.exidx") && !name.startswith(".ARM.extab") &&
814         GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection);
815}
816
817//===----------------------------------------------------------------------===//
818/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
819///
820TargetLDBackend* createARMLDBackend(const LinkerConfig& pConfig) {
821  if (pConfig.targets().triple().isOSDarwin()) {
822    assert(0 && "MachO linker is not supported yet");
823    /**
824    return new ARMMachOLDBackend(createARMMachOArchiveReader,
825                               createARMMachOObjectReader,
826                               createARMMachOObjectWriter);
827    **/
828  }
829  if (pConfig.targets().triple().isOSWindows()) {
830    assert(0 && "COFF linker is not supported yet");
831    /**
832    return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
833                               createARMCOFFObjectReader,
834                               createARMCOFFObjectWriter);
835    **/
836  }
837  return new ARMGNULDBackend(pConfig,
838                             new ARMGNUInfo(pConfig.targets().triple()));
839}
840
841}  // namespace mcld
842
843//===----------------------------------------------------------------------===//
844// Force static initialization.
845//===----------------------------------------------------------------------===//
846extern "C" void MCLDInitializeARMLDBackend() {
847  // Register the linker backend
848  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheARMTarget,
849                                                mcld::createARMLDBackend);
850  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheThumbTarget,
851                                                mcld::createARMLDBackend);
852}
853