• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- ARMLDBackend.cpp ---------------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "ARM.h"
10 #include "ARMGNUInfo.h"
11 #include "ARMELFAttributeData.h"
12 #include "ARMELFDynamic.h"
13 #include "ARMException.h"
14 #include "ARMLDBackend.h"
15 #include "ARMRelocator.h"
16 #include "ARMToARMStub.h"
17 #include "ARMToTHMStub.h"
18 #include "THMToTHMStub.h"
19 #include "THMToARMStub.h"
20 
21 #include "mcld/IRBuilder.h"
22 #include "mcld/LinkerConfig.h"
23 #include "mcld/ADT/ilist_sort.h"
24 #include "mcld/Fragment/AlignFragment.h"
25 #include "mcld/Fragment/FillFragment.h"
26 #include "mcld/Fragment/NullFragment.h"
27 #include "mcld/Fragment/RegionFragment.h"
28 #include "mcld/Fragment/Stub.h"
29 #include "mcld/LD/BranchIslandFactory.h"
30 #include "mcld/LD/ELFFileFormat.h"
31 #include "mcld/LD/ELFSegment.h"
32 #include "mcld/LD/ELFSegmentFactory.h"
33 #include "mcld/LD/LDContext.h"
34 #include "mcld/LD/StubFactory.h"
35 #include "mcld/Object/ObjectBuilder.h"
36 #include "mcld/Support/MemoryArea.h"
37 #include "mcld/Support/MemoryRegion.h"
38 #include "mcld/Support/MsgHandling.h"
39 #include "mcld/Support/TargetRegistry.h"
40 #include "mcld/Target/ELFAttribute.h"
41 #include "mcld/Target/GNUInfo.h"
42 
43 #include <llvm/ADT/StringRef.h>
44 #include <llvm/ADT/Triple.h>
45 #include <llvm/ADT/Twine.h>
46 #include <llvm/Support/Casting.h>
47 #include <llvm/Support/ELF.h>
48 
49 #include <cstring>
50 #include <vector>
51 
52 namespace mcld {
53 
54 /// Fragment data for EXIDX_CANTUNWIND.
55 static const char g_CantUnwindEntry[8] = {
56   // Relocation to text section.
57   0, 0, 0, 0,
58   // EXIDX_CANTUNWIND (little endian.)
59   1, 0, 0, 0,
60 };
61 
62 /// Helper function to create a local symbol at the end of the fragment.
63 static mcld::ResolveInfo*
CreateLocalSymbolToFragmentEnd(mcld::Module & pModule,mcld::Fragment & pFrag)64 CreateLocalSymbolToFragmentEnd(mcld::Module& pModule, mcld::Fragment& pFrag) {
65   // Create and add symbol to the name pool.
66   mcld::ResolveInfo* resolveInfo =
67       pModule.getNamePool().createSymbol(/* pName */"",
68                                          /* pIsDyn */false,
69                                          mcld::ResolveInfo::Section,
70                                          mcld::ResolveInfo::Define,
71                                          mcld::ResolveInfo::Local,
72                                          /* pSize */0,
73                                          mcld::ResolveInfo::Hidden);
74   if (resolveInfo == nullptr) {
75     return nullptr;
76   }
77 
78   // Create input symbol.
79   mcld::LDSymbol* inputSym = mcld::LDSymbol::Create(*resolveInfo);
80   if (inputSym == nullptr) {
81     return nullptr;
82   }
83 
84   inputSym->setFragmentRef(mcld::FragmentRef::Create(pFrag, pFrag.size()));
85   inputSym->setValue(/* pValue */0);
86 
87   // The output symbol is simply an alias to the input symbol.
88   resolveInfo->setSymPtr(inputSym);
89 
90   return resolveInfo;
91 }
92 
93 /// Comparator to sort .ARM.exidx fragments according to the address of the
94 /// corresponding .text fragment.
95 class ExIdxFragmentComparator {
96  private:
97   const ARMExData& m_pExData;
98 
99  public:
ExIdxFragmentComparator(const ARMExData & pExData)100   explicit ExIdxFragmentComparator(const ARMExData& pExData)
101       : m_pExData(pExData) {
102   }
103 
operator ()(const Fragment & a,const Fragment & b)104   bool operator()(const Fragment& a, const Fragment& b) {
105     ARMExSectionTuple* tupleA = m_pExData.getTupleByExIdx(&a);
106     ARMExSectionTuple* tupleB = m_pExData.getTupleByExIdx(&b);
107 
108     Fragment* textFragA = tupleA->getTextFragment();
109     Fragment* textFragB = tupleB->getTextFragment();
110 
111     uint64_t addrA = textFragA->getParent()->getSection().addr() +
112                      textFragA->getOffset();
113     uint64_t addrB = textFragB->getParent()->getSection().addr() +
114                      textFragB->getOffset();
115     return (addrA < addrB);
116   }
117 };
118 
119 //===----------------------------------------------------------------------===//
120 // ARMGNULDBackend
121 //===----------------------------------------------------------------------===//
ARMGNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)122 ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo)
123     : GNULDBackend(pConfig, pInfo),
124       m_pRelocator(NULL),
125       m_pGOT(NULL),
126       m_pPLT(NULL),
127       m_pRelDyn(NULL),
128       m_pRelPLT(NULL),
129       m_pAttrData(NULL),
130       m_pDynamic(NULL),
131       m_pGOTSymbol(NULL),
132       m_pEXIDXStart(NULL),
133       m_pEXIDXEnd(NULL),
134       m_pEXIDX(NULL),
135       m_pEXTAB(NULL),
136       m_pAttributes(NULL) {
137 }
138 
~ARMGNULDBackend()139 ARMGNULDBackend::~ARMGNULDBackend() {
140   delete m_pRelocator;
141   delete m_pGOT;
142   delete m_pPLT;
143   delete m_pRelDyn;
144   delete m_pRelPLT;
145   delete m_pDynamic;
146   delete m_pAttrData;
147 }
148 
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)149 void ARMGNULDBackend::initTargetSections(Module& pModule,
150                                          ObjectBuilder& pBuilder) {
151   // FIXME: Currently we set exidx and extab to "Exception" and directly emit
152   // them from input
153   m_pEXIDX =
154       pBuilder.CreateSection(".ARM.exidx",
155                              LDFileFormat::Target,
156                              llvm::ELF::SHT_ARM_EXIDX,
157                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
158                              config().targets().bitclass() / 8);
159   m_pEXTAB = pBuilder.CreateSection(".ARM.extab",
160                                     LDFileFormat::Target,
161                                     llvm::ELF::SHT_PROGBITS,
162                                     llvm::ELF::SHF_ALLOC,
163                                     0x1);
164   m_pAttributes = pBuilder.CreateSection(".ARM.attributes",
165                                          LDFileFormat::Target,
166                                          llvm::ELF::SHT_ARM_ATTRIBUTES,
167                                          0x0,
168                                          0x1);
169 
170   // initialize "aeabi" attributes subsection
171   m_pAttrData = new ARMELFAttributeData();
172   attribute().registerAttributeData(*m_pAttrData);
173 
174   if (LinkerConfig::Object != config().codeGenType()) {
175     ELFFileFormat* file_format = getOutputFormat();
176 
177     // initialize .got
178     LDSection& got = file_format->getGOT();
179     m_pGOT = new ARMGOT(got);
180 
181     // initialize .plt
182     LDSection& plt = file_format->getPLT();
183     m_pPLT = new ARMPLT(plt, *m_pGOT);
184 
185     // initialize .rel.plt
186     LDSection& relplt = file_format->getRelPlt();
187     relplt.setLink(&plt);
188     // create SectionData and ARMRelDynSection
189     m_pRelPLT = new OutputRelocSection(pModule, relplt);
190 
191     // initialize .rel.dyn
192     LDSection& reldyn = file_format->getRelDyn();
193     m_pRelDyn = new OutputRelocSection(pModule, reldyn);
194   }
195 }
196 
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)197 void ARMGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
198   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
199   // same name in input
200   if (LinkerConfig::Object != config().codeGenType()) {
201     m_pGOTSymbol =
202         pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
203             "_GLOBAL_OFFSET_TABLE_",
204             ResolveInfo::Object,
205             ResolveInfo::Define,
206             ResolveInfo::Local,
207             0x0,  // size
208             0x0,  // value
209             FragmentRef::Null(),
210             ResolveInfo::Hidden);
211   }
212   if (m_pEXIDX != NULL && m_pEXIDX->size() != 0x0) {
213     FragmentRef* exidx_start =
214         FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
215     FragmentRef* exidx_end = FragmentRef::Create(
216         m_pEXIDX->getSectionData()->front(), m_pEXIDX->size());
217     m_pEXIDXStart =
218         pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
219             "__exidx_start",
220             ResolveInfo::Object,
221             ResolveInfo::Define,
222             ResolveInfo::Local,
223             0x0,          // size
224             0x0,          // value
225             exidx_start,  // FragRef
226             ResolveInfo::Default);
227 
228     m_pEXIDXEnd = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
229         "__exidx_end",
230         ResolveInfo::Object,
231         ResolveInfo::Define,
232         ResolveInfo::Local,
233         0x0,        // size
234         0x0,        // value
235         exidx_end,  // FragRef
236         ResolveInfo::Default);
237     // change __exidx_start/_end to local dynamic category
238     if (m_pEXIDXStart != NULL)
239       pModule.getSymbolTable().changeToDynamic(*m_pEXIDXStart);
240     if (m_pEXIDXEnd != NULL)
241       pModule.getSymbolTable().changeToDynamic(*m_pEXIDXEnd);
242   } else {
243     m_pEXIDXStart =
244         pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
245             "__exidx_start",
246             ResolveInfo::NoType,
247             ResolveInfo::Define,
248             ResolveInfo::Absolute,
249             0x0,  // size
250             0x0,  // value
251             FragmentRef::Null(),
252             ResolveInfo::Default);
253 
254     m_pEXIDXEnd = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
255         "__exidx_end",
256         ResolveInfo::NoType,
257         ResolveInfo::Define,
258         ResolveInfo::Absolute,
259         0x0,  // size
260         0x0,  // value
261         FragmentRef::Null(),
262         ResolveInfo::Default);
263   }
264 }
265 
initRelocator()266 bool ARMGNULDBackend::initRelocator() {
267   if (m_pRelocator == NULL) {
268     m_pRelocator = new ARMRelocator(*this, config());
269   }
270   return true;
271 }
272 
getRelocator() const273 const Relocator* ARMGNULDBackend::getRelocator() const {
274   assert(m_pRelocator != NULL);
275   return m_pRelocator;
276 }
277 
getRelocator()278 Relocator* ARMGNULDBackend::getRelocator() {
279   assert(m_pRelocator != NULL);
280   return m_pRelocator;
281 }
282 
doPreLayout(IRBuilder & pBuilder)283 void ARMGNULDBackend::doPreLayout(IRBuilder& pBuilder) {
284   // initialize .dynamic data
285   if (!config().isCodeStatic() && m_pDynamic == NULL)
286     m_pDynamic = new ARMELFDynamic(*this, config());
287 
288   // set attribute section size
289   m_pAttributes->setSize(attribute().sizeOutput());
290 
291   // set .got size
292   // when building shared object, the .got section is must
293   if (LinkerConfig::Object != config().codeGenType()) {
294     if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
295         m_pGOTSymbol != NULL) {
296       m_pGOT->finalizeSectionSize();
297       defineGOTSymbol(pBuilder);
298     }
299 
300     // set .plt size
301     if (m_pPLT->hasPLT1())
302       m_pPLT->finalizeSectionSize();
303 
304     ELFFileFormat* file_format = getOutputFormat();
305     // set .rel.dyn size
306     if (!m_pRelDyn->empty()) {
307       assert(
308           !config().isCodeStatic() &&
309           "static linkage should not result in a dynamic relocation section");
310       file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
311                                        getRelEntrySize());
312     }
313 
314     // set .rel.plt size
315     if (!m_pRelPLT->empty()) {
316       assert(
317           !config().isCodeStatic() &&
318           "static linkage should not result in a dynamic relocation section");
319       file_format->getRelPlt().setSize(m_pRelPLT->numOfRelocs() *
320                                        getRelEntrySize());
321     }
322   }
323 }
324 
doPostLayout(Module & pModule,IRBuilder & pBuilder)325 void ARMGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
326   const ELFFileFormat* file_format = getOutputFormat();
327 
328   // apply PLT
329   if (file_format->hasPLT()) {
330     // Since we already have the size of LDSection PLT, m_pPLT should not be
331     // NULL.
332     assert(m_pPLT != NULL);
333     m_pPLT->applyPLT0();
334     m_pPLT->applyPLT1();
335   }
336 
337   // apply GOT
338   if (file_format->hasGOT()) {
339     // Since we already have the size of GOT, m_pGOT should not be NULL.
340     assert(m_pGOT != NULL);
341     if (LinkerConfig::DynObj == config().codeGenType())
342       m_pGOT->applyGOT0(file_format->getDynamic().addr());
343     else {
344       // executable file and object file? should fill with zero.
345       m_pGOT->applyGOT0(0);
346     }
347   }
348 }
349 
350 /// dynamic - the dynamic section of the target machine.
351 /// Use co-variant return type to return its own dynamic section.
dynamic()352 ARMELFDynamic& ARMGNULDBackend::dynamic() {
353   assert(m_pDynamic != NULL);
354   return *m_pDynamic;
355 }
356 
357 /// dynamic - the dynamic section of the target machine.
358 /// Use co-variant return type to return its own dynamic section.
dynamic() const359 const ARMELFDynamic& ARMGNULDBackend::dynamic() const {
360   assert(m_pDynamic != NULL);
361   return *m_pDynamic;
362 }
363 
defineGOTSymbol(IRBuilder & pBuilder)364 void ARMGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
365   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
366   if (m_pGOTSymbol != NULL) {
367     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
368         "_GLOBAL_OFFSET_TABLE_",
369         ResolveInfo::Object,
370         ResolveInfo::Define,
371         ResolveInfo::Local,
372         0x0,  // size
373         0x0,  // value
374         FragmentRef::Create(*(m_pGOT->begin()), 0x0),
375         ResolveInfo::Hidden);
376   } else {
377     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
378         "_GLOBAL_OFFSET_TABLE_",
379         ResolveInfo::Object,
380         ResolveInfo::Define,
381         ResolveInfo::Local,
382         0x0,  // size
383         0x0,  // value
384         FragmentRef::Create(*(m_pGOT->begin()), 0x0),
385         ResolveInfo::Hidden);
386   }
387 }
388 
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const389 uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
390                                           MemoryRegion& pRegion) const {
391   assert(pRegion.size() && "Size of MemoryRegion is zero!");
392 
393   const ELFFileFormat* file_format = getOutputFormat();
394 
395   if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
396     uint64_t result = m_pPLT->emit(pRegion);
397     return result;
398   }
399 
400   if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
401     uint64_t result = m_pGOT->emit(pRegion);
402     return result;
403   }
404 
405   if (&pSection == m_pAttributes) {
406     return attribute().emit(pRegion);
407   }
408 
409   // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
410   // directly from the input file.
411   const SectionData* sect_data = pSection.getSectionData();
412   SectionData::const_iterator frag_iter, frag_end = sect_data->end();
413   uint8_t* out_offset = pRegion.begin();
414   for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
415     size_t size = frag_iter->size();
416     switch (frag_iter->getKind()) {
417       case Fragment::Fillment: {
418         const FillFragment& fill_frag = llvm::cast<FillFragment>(*frag_iter);
419         if (fill_frag.getValueSize() == 0) {
420           // virtual fillment, ignore it.
421           break;
422         }
423 
424         memset(out_offset, fill_frag.getValue(), fill_frag.size());
425         break;
426       }
427       case Fragment::Region: {
428         const RegionFragment& region_frag =
429             llvm::cast<RegionFragment>(*frag_iter);
430         const char* start = region_frag.getRegion().begin();
431         memcpy(out_offset, start, size);
432         break;
433       }
434       case Fragment::Alignment: {
435         const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
436         uint64_t count = size / align_frag.getValueSize();
437         switch (align_frag.getValueSize()) {
438           case 1u:
439             std::memset(out_offset, align_frag.getValue(), count);
440             break;
441           default:
442             llvm::report_fatal_error(
443                 "unsupported value size for align fragment emission yet.\n");
444             break;
445         }  // end switch
446         break;
447       }
448       case Fragment::Null: {
449         assert(0x0 == size);
450         break;
451       }
452       default:
453         llvm::report_fatal_error("unsupported fragment type.\n");
454         break;
455     }  // end switch
456     out_offset += size;
457   }  // end for
458   return pRegion.size();
459 }
460 
461 /// finalizeSymbol - finalize the symbol value
finalizeTargetSymbols()462 bool ARMGNULDBackend::finalizeTargetSymbols() {
463   return true;
464 }
465 
466 
467 /// preMergeSections - hooks to be executed before merging sections
preMergeSections(Module & pModule)468 void ARMGNULDBackend::preMergeSections(Module& pModule) {
469   // Since the link relationship between .text and .ARM.exidx will be discarded
470   // after merging sections, we have to build the exception handling section
471   // mapping before section merge.
472   m_pExData = ARMExData::create(pModule);
473 }
474 
475 /// postMergeSections - hooks to be executed after merging sections
postMergeSections(Module & pModule)476 void ARMGNULDBackend::postMergeSections(Module& pModule) {
477   if (m_pEXIDX->hasSectionData()) {
478     // Append the NullFragment so that __exidx_end can be correctly inserted.
479     NullFragment* null = new NullFragment(m_pEXIDX->getSectionData());
480     null->setOffset(m_pEXIDX->size());
481   }
482 }
483 
mergeSection(Module & pModule,const Input & pInput,LDSection & pSection)484 bool ARMGNULDBackend::mergeSection(Module& pModule,
485                                    const Input& pInput,
486                                    LDSection& pSection) {
487   switch (pSection.type()) {
488     case llvm::ELF::SHT_ARM_ATTRIBUTES: {
489       return attribute().merge(pInput, pSection);
490     }
491 
492     case llvm::ELF::SHT_ARM_EXIDX: {
493       assert(pSection.getLink() != NULL);
494       if ((pSection.getLink()->kind() == LDFileFormat::Ignore) ||
495           (pSection.getLink()->kind() == LDFileFormat::Folded)) {
496         // if the target section of the .ARM.exidx is Ignore, then it should be
497         // ignored as well
498         pSection.setKind(LDFileFormat::Ignore);
499         return true;
500       }
501 
502       if (!m_pEXIDX->hasSectionData()) {
503         // Create SectionData for m_pEXIDX.
504         SectionData* sectData = IRBuilder::CreateSectionData(*m_pEXIDX);
505 
506         // Initialize the alignment of m_pEXIDX.
507         const size_t alignExIdx = 4;
508         m_pEXIDX->setAlign(alignExIdx);
509 
510         // Insert an AlignFragment to the beginning of m_pEXIDX.
511         AlignFragment* frag =
512             new AlignFragment(/*alignment*/alignExIdx,
513                               /*the filled value*/0x0,
514                               /*the size of filled value*/1u,
515                               /*max bytes to emit*/alignExIdx - 1);
516         frag->setOffset(0);
517         frag->setParent(sectData);
518         sectData->getFragmentList().push_back(frag);
519         m_pEXIDX->setSize(frag->size());
520       }
521 
522       // Move RegionFragment from pSection to m_pEXIDX.
523       uint64_t offset = m_pEXIDX->size();
524       SectionData::FragmentListType& src =
525           pSection.getSectionData()->getFragmentList();
526       SectionData::FragmentListType& dst =
527           m_pEXIDX->getSectionData()->getFragmentList();
528       SectionData::FragmentListType::iterator frag = src.begin();
529       SectionData::FragmentListType::iterator fragEnd = src.end();
530       while (frag != fragEnd) {
531         if (frag->getKind() != Fragment::Region) {
532           ++frag;
533         } else {
534           frag->setParent(m_pEXIDX->getSectionData());
535           frag->setOffset(offset);
536           offset += frag->size();
537           dst.splice(dst.end(), src, frag++);
538         }
539       }
540 
541       // Update the size of m_pEXIDX.
542       m_pEXIDX->setSize(offset);
543       return true;
544     }
545 
546     default: {
547       ObjectBuilder builder(pModule);
548       builder.MergeSection(pInput, pSection);
549       return true;
550     }
551   }  // end of switch
552   return true;
553 }
554 
setUpReachedSectionsForGC(const Module & pModule,GarbageCollection::SectionReachedListMap & pSectReachedListMap) const555 void ARMGNULDBackend::setUpReachedSectionsForGC(
556     const Module& pModule,
557     GarbageCollection::SectionReachedListMap& pSectReachedListMap) const {
558   // traverse all the input relocations to find the relocation sections applying
559   // .ARM.exidx sections
560   Module::const_obj_iterator input, inEnd = pModule.obj_end();
561   for (input = pModule.obj_begin(); input != inEnd; ++input) {
562     LDContext::const_sect_iterator rs,
563         rsEnd = (*input)->context()->relocSectEnd();
564     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
565       // bypass the discarded relocation section
566       // 1. its section kind is changed to Ignore. (The target section is a
567       // discarded group section.)
568       // 2. it has no reloc data. (All symbols in the input relocs are in the
569       // discarded group sections)
570       LDSection* reloc_sect = *rs;
571       LDSection* apply_sect = reloc_sect->getLink();
572       if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
573           (!reloc_sect->hasRelocData()))
574         continue;
575 
576       if (llvm::ELF::SHT_ARM_EXIDX == apply_sect->type()) {
577         // 1. set up the reference according to relocations
578         bool add_first = false;
579         GarbageCollection::SectionListTy* reached_sects = NULL;
580         RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
581         for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd;
582              ++reloc_it) {
583           Relocation* reloc = llvm::cast<Relocation>(reloc_it);
584           ResolveInfo* sym = reloc->symInfo();
585           // only the target symbols defined in the input fragments can make the
586           // reference
587           if (sym == NULL)
588             continue;
589           if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
590             continue;
591 
592           // only the target symbols defined in the concerned sections can make
593           // the reference
594           const LDSection* target_sect =
595               &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
596           if (target_sect->kind() != LDFileFormat::TEXT &&
597               target_sect->kind() != LDFileFormat::DATA &&
598               target_sect->kind() != LDFileFormat::BSS)
599             continue;
600 
601           // setup the reached list, if we first add the element to reached list
602           // of this section, create an entry in ReachedSections map
603           if (!add_first) {
604             reached_sects = &pSectReachedListMap.getReachedList(*apply_sect);
605             add_first = true;
606           }
607           reached_sects->insert(target_sect);
608         }
609         reached_sects = NULL;
610         add_first = false;
611         // 2. set up the reference from XXX to .ARM.exidx.XXX
612         assert(apply_sect->getLink() != NULL);
613         pSectReachedListMap.addReference(*apply_sect->getLink(), *apply_sect);
614       }
615     }
616   }
617 }
618 
readSection(Input & pInput,SectionData & pSD)619 bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
620   Fragment* frag = NULL;
621   uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
622   uint32_t size = pSD.getSection().size();
623 
624   llvm::StringRef region = pInput.memArea()->request(offset, size);
625   if (region.size() == 0) {
626     // If the input section's size is zero, we got a NULL region.
627     // use a virtual fill fragment
628     frag = new FillFragment(0x0, 0, 0);
629   } else {
630     frag = new RegionFragment(region);
631   }
632 
633   ObjectBuilder::AppendFragment(*frag, pSD);
634   return true;
635 }
636 
getGOT()637 ARMGOT& ARMGNULDBackend::getGOT() {
638   assert(m_pGOT != NULL && "GOT section not exist");
639   return *m_pGOT;
640 }
641 
getGOT() const642 const ARMGOT& ARMGNULDBackend::getGOT() const {
643   assert(m_pGOT != NULL && "GOT section not exist");
644   return *m_pGOT;
645 }
646 
getPLT()647 ARMPLT& ARMGNULDBackend::getPLT() {
648   assert(m_pPLT != NULL && "PLT section not exist");
649   return *m_pPLT;
650 }
651 
getPLT() const652 const ARMPLT& ARMGNULDBackend::getPLT() const {
653   assert(m_pPLT != NULL && "PLT section not exist");
654   return *m_pPLT;
655 }
656 
getRelDyn()657 OutputRelocSection& ARMGNULDBackend::getRelDyn() {
658   assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
659   return *m_pRelDyn;
660 }
661 
getRelDyn() const662 const OutputRelocSection& ARMGNULDBackend::getRelDyn() const {
663   assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
664   return *m_pRelDyn;
665 }
666 
getRelPLT()667 OutputRelocSection& ARMGNULDBackend::getRelPLT() {
668   assert(m_pRelPLT != NULL && ".rel.plt section not exist");
669   return *m_pRelPLT;
670 }
671 
getRelPLT() const672 const OutputRelocSection& ARMGNULDBackend::getRelPLT() const {
673   assert(m_pRelPLT != NULL && ".rel.plt section not exist");
674   return *m_pRelPLT;
675 }
676 
getAttributeData()677 ARMELFAttributeData& ARMGNULDBackend::getAttributeData() {
678   assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
679   return *m_pAttrData;
680 }
681 
getAttributeData() const682 const ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const {
683   assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
684   return *m_pAttrData;
685 }
686 
getTargetSectionOrder(const LDSection & pSectHdr) const687 unsigned int ARMGNULDBackend::getTargetSectionOrder(
688     const LDSection& pSectHdr) const {
689   const ELFFileFormat* file_format = getOutputFormat();
690 
691   if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
692     if (config().options().hasNow())
693       return SHO_RELRO_LAST;
694     return SHO_DATA;
695   }
696 
697   if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
698     return SHO_PLT;
699 
700   if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
701     // put ARM.exidx and ARM.extab in the same order of .eh_frame
702     return SHO_EXCEPTION;
703   }
704 
705   return SHO_UNDEFINED;
706 }
707 
rewriteARMExIdxSection(Module & pModule)708 void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
709   if (!m_pEXIDX->hasSectionData()) {
710     // Return if this is empty section.
711     return;
712   }
713 
714   SectionData* sectData = m_pEXIDX->getSectionData();
715   SectionData::FragmentListType& list = sectData->getFragmentList();
716 
717   // Move the first fragment (align fragment) and last fragment (null fragment)
718   // to temporary list because we would only like to sort the region fragment.
719   SectionData::FragmentListType tmp;
720   {
721     SectionData::iterator first = sectData->begin();
722     SectionData::iterator last = sectData->end();
723     --last;
724 
725     assert(first->getKind() == Fragment::Alignment);
726     assert(last->getKind() == Fragment::Null);
727 
728     tmp.splice(tmp.end(), list, first);
729     tmp.splice(tmp.end(), list, last);
730   }
731 
732   // Sort the region fragments in the .ARM.exidx output section.
733   sort(list, ExIdxFragmentComparator(*m_pExData));
734 
735   // Fix the coverage of the .ARM.exidx table.
736   llvm::StringRef cantUnwindRegion(g_CantUnwindEntry,
737                                    sizeof(g_CantUnwindEntry));
738 
739   SectionData::FragmentListType::iterator it = list.begin();
740   if (it != list.end()) {
741     Fragment* prevTextFrag = m_pExData->getTupleByExIdx(&*it)->getTextFragment();
742     uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() +
743                            prevTextFrag->getOffset() +
744                            prevTextFrag->size();
745     ++it;
746     while (it != list.end()) {
747       Fragment* currTextFrag =
748           m_pExData->getTupleByExIdx(&*it)->getTextFragment();
749       uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() +
750                                currTextFrag->getOffset();
751 
752       if (currTextBegin > prevTextEnd) {
753         // Found a gap. Insert a can't unwind entry.
754         RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
755         frag->setParent(sectData);
756         list.insert(it, frag);
757 
758         // Add PREL31 reference to the beginning of the uncovered region.
759         Relocation* reloc =
760             Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
761                                *FragmentRef::Create(*frag, /* pOffset */0),
762                                /* pAddend */0);
763         reloc->setSymInfo(
764             CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
765         addExtraRelocation(reloc);
766       }
767 
768       prevTextEnd = currTextBegin + currTextFrag->size();
769       prevTextFrag = currTextFrag;
770       ++it;
771     }
772 
773     // Add a can't unwind entry to terminate .ARM.exidx section.
774     RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
775     frag->setParent(sectData);
776     list.push_back(frag);
777 
778     // Add PREL31 reference to the end of the .text section.
779     Relocation* reloc =
780         Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
781                            *FragmentRef::Create(*frag, /* pOffset */0),
782                            /* pAddend */0);
783     reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
784     addExtraRelocation(reloc);
785   }
786 
787   // Add the first and the last fragment back.
788   list.splice(list.begin(), tmp, tmp.begin());
789   list.splice(list.end(), tmp, tmp.begin());
790 
791   // Update the fragment offsets.
792   uint64_t offset = 0;
793   for (SectionData::iterator it = sectData->begin(), end = sectData->end();
794        it != end; ++it) {
795     it->setOffset(offset);
796     offset += it->size();
797   }
798 
799   // Update the section size.
800   m_pEXIDX->setSize(offset);
801 
802   // Rebuild the section header.
803   setOutputSectionAddress(pModule);
804 }
805 
806 /// relax - the relaxation pass
relax(Module & pModule,IRBuilder & pBuilder)807 bool ARMGNULDBackend::relax(Module& pModule, IRBuilder& pBuilder) {
808   if (!GNULDBackend::relax(pModule, pBuilder)) {
809     return false;
810   }
811   rewriteARMExIdxSection(pModule);
812   return true;
813 }
814 
815 /// doRelax
doRelax(Module & pModule,IRBuilder & pBuilder,bool & pFinished)816 bool ARMGNULDBackend::doRelax(Module& pModule,
817                               IRBuilder& pBuilder,
818                               bool& pFinished) {
819   assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
820 
821   bool isRelaxed = false;
822   ELFFileFormat* file_format = getOutputFormat();
823   // check branch relocs and create the related stubs if needed
824   Module::obj_iterator input, inEnd = pModule.obj_end();
825   for (input = pModule.obj_begin(); input != inEnd; ++input) {
826     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
827     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
828       if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
829         continue;
830       RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
831       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
832         Relocation* relocation = llvm::cast<Relocation>(reloc);
833 
834         switch (relocation->type()) {
835           case llvm::ELF::R_ARM_PC24:
836           case llvm::ELF::R_ARM_CALL:
837           case llvm::ELF::R_ARM_JUMP24:
838           case llvm::ELF::R_ARM_PLT32:
839           case llvm::ELF::R_ARM_THM_CALL:
840           case llvm::ELF::R_ARM_THM_XPC22:
841           case llvm::ELF::R_ARM_THM_JUMP24:
842           case llvm::ELF::R_ARM_THM_JUMP19: {
843             // calculate the possible symbol value
844             uint64_t sym_value = 0x0;
845             LDSymbol* symbol = relocation->symInfo()->outSymbol();
846             if (symbol->hasFragRef()) {
847               uint64_t value = symbol->fragRef()->getOutputOffset();
848               uint64_t addr =
849                   symbol->fragRef()->frag()->getParent()->getSection().addr();
850               sym_value = addr + value;
851             }
852             if ((relocation->symInfo()->reserved() &
853                  ARMRelocator::ReservePLT) != 0x0) {
854               // FIXME: we need to find out the address of the specific plt
855               // entry
856               assert(file_format->hasPLT());
857               sym_value = file_format->getPLT().addr();
858             }
859             Stub* stub = getStubFactory()->create(*relocation,  // relocation
860                                                   sym_value,    // symbol value
861                                                   pBuilder,
862                                                   *getBRIslandFactory());
863             if (stub != NULL) {
864               assert(stub->symInfo() != NULL);
865               // reset the branch target of the reloc to this stub instead
866               relocation->setSymInfo(stub->symInfo());
867 
868               switch (config().options().getStripSymbolMode()) {
869                 case GeneralOptions::StripSymbolMode::StripAllSymbols:
870                 case GeneralOptions::StripSymbolMode::StripLocals:
871                   break;
872                 default: {
873                   // a stub symbol should be local
874                   assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
875                   LDSection& symtab = file_format->getSymTab();
876                   LDSection& strtab = file_format->getStrTab();
877 
878                   // increase the size of .symtab and .strtab if needed
879                   symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
880                   symtab.setInfo(symtab.getInfo() + 1);
881                   strtab.setSize(strtab.size() + stub->symInfo()->nameSize() +
882                                  1);
883                 }
884               }  // end of switch
885               isRelaxed = true;
886             }
887             break;
888           }
889           case llvm::ELF::R_ARM_V4BX:
890             /* FIXME: bypass R_ARM_V4BX relocation now */
891             break;
892           default:
893             break;
894         }  // end of switch
895       }  // for all relocations
896     }  // for all relocation section
897   }  // for all inputs
898 
899   // find the first fragment w/ invalid offset due to stub insertion
900   std::vector<Fragment*> invalid_frags;
901   pFinished = true;
902   for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
903                                      island_end = getBRIslandFactory()->end();
904        island != island_end;
905        ++island) {
906     if ((*island).size() > stubGroupSize()) {
907       error(diag::err_no_space_to_place_stubs) << stubGroupSize();
908       return false;
909     }
910 
911     if ((*island).numOfStubs() == 0) {
912       continue;
913     }
914 
915     Fragment* exit = &*(*island).end();
916     if (exit == (*island).begin()->getParent()->end()) {
917       continue;
918     }
919 
920     if (((*island).offset() + (*island).size()) > exit->getOffset()) {
921       if (invalid_frags.empty() ||
922           (invalid_frags.back()->getParent() != (*island).getParent())) {
923         invalid_frags.push_back(exit);
924         pFinished = false;
925       }
926       continue;
927     }
928   }
929 
930   // reset the offset of invalid fragments
931   for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie;
932        ++it) {
933     Fragment* invalid = *it;
934     while (invalid != NULL) {
935       invalid->setOffset(invalid->getPrevNode()->getOffset() +
936                          invalid->getPrevNode()->size());
937       invalid = invalid->getNextNode();
938     }
939   }
940 
941   // reset the size of section that has stubs inserted.
942   if (isRelaxed) {
943     SectionData* prev = NULL;
944     for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
945                                        island_end = getBRIslandFactory()->end();
946          island != island_end;
947          ++island) {
948       SectionData* sd = (*island).begin()->getParent();
949       if ((*island).numOfStubs() != 0) {
950         if (sd != prev) {
951           sd->getSection().setSize(sd->back().getOffset() + sd->back().size());
952         }
953       }
954       prev = sd;
955     }
956   }
957   return isRelaxed;
958 }
959 
960 /// initTargetStubs
initTargetStubs()961 bool ARMGNULDBackend::initTargetStubs() {
962   if (getStubFactory() != NULL) {
963     getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep()));
964     getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep()));
965     getStubFactory()->addPrototype(
966         new THMToTHMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
967     getStubFactory()->addPrototype(
968         new THMToARMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
969     return true;
970   }
971   return false;
972 }
973 
974 /// maxFwdBranchOffset
maxFwdBranchOffset() const975 int64_t ARMGNULDBackend::maxFwdBranchOffset() const {
976   if (m_pAttrData->usingThumb2()) {
977     return THM2_MAX_FWD_BRANCH_OFFSET;
978   } else {
979     return THM_MAX_FWD_BRANCH_OFFSET;
980   }
981 }
982 
983 /// maxBwdBranchOffset
maxBwdBranchOffset() const984 int64_t ARMGNULDBackend::maxBwdBranchOffset() const {
985   if (m_pAttrData->usingThumb2()) {
986     return THM2_MAX_BWD_BRANCH_OFFSET;
987   } else {
988     return THM_MAX_BWD_BRANCH_OFFSET;
989   }
990 }
991 
992 /// doCreateProgramHdrs - backend can implement this function to create the
993 /// target-dependent segments
doCreateProgramHdrs(Module & pModule)994 void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule) {
995   if (m_pEXIDX != NULL && m_pEXIDX->size() != 0x0) {
996     // make PT_ARM_EXIDX
997     ELFSegment* exidx_seg =
998         elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX, llvm::ELF::PF_R);
999     exidx_seg->append(m_pEXIDX);
1000   }
1001 }
1002 
1003 /// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
1004 /// function pointer access
mayHaveUnsafeFunctionPointerAccess(const LDSection & pSection) const1005 bool ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess(
1006     const LDSection& pSection) const {
1007   llvm::StringRef name(pSection.name());
1008   return !name.startswith(".ARM.exidx") && !name.startswith(".ARM.extab") &&
1009          GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection);
1010 }
1011 
1012 //===----------------------------------------------------------------------===//
1013 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
1014 ///
createARMLDBackend(const LinkerConfig & pConfig)1015 TargetLDBackend* createARMLDBackend(const LinkerConfig& pConfig) {
1016   if (pConfig.targets().triple().isOSDarwin()) {
1017     assert(0 && "MachO linker is not supported yet");
1018     /**
1019     return new ARMMachOLDBackend(createARMMachOArchiveReader,
1020                                createARMMachOObjectReader,
1021                                createARMMachOObjectWriter);
1022     **/
1023   }
1024   if (pConfig.targets().triple().isOSWindows()) {
1025     assert(0 && "COFF linker is not supported yet");
1026     /**
1027     return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
1028                                createARMCOFFObjectReader,
1029                                createARMCOFFObjectWriter);
1030     **/
1031   }
1032   return new ARMGNULDBackend(pConfig,
1033                              new ARMGNUInfo(pConfig.targets().triple()));
1034 }
1035 
1036 }  // namespace mcld
1037 
1038 //===----------------------------------------------------------------------===//
1039 // Force static initialization.
1040 //===----------------------------------------------------------------------===//
MCLDInitializeARMLDBackend()1041 extern "C" void MCLDInitializeARMLDBackend() {
1042   // Register the linker backend
1043   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheARMTarget,
1044                                                 mcld::createARMLDBackend);
1045   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheThumbTarget,
1046                                                 mcld::createARMLDBackend);
1047 }
1048