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 
49 namespace mcld {
50 
51 //===----------------------------------------------------------------------===//
52 // ARMGNULDBackend
53 //===----------------------------------------------------------------------===//
ARMGNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)54 ARMGNULDBackend::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 
~ARMGNULDBackend()71 ARMGNULDBackend::~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 
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)81 void 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 
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)129 void 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 
initRelocator()198 bool ARMGNULDBackend::initRelocator() {
199   if (m_pRelocator == NULL) {
200     m_pRelocator = new ARMRelocator(*this, config());
201   }
202   return true;
203 }
204 
getRelocator() const205 const Relocator* ARMGNULDBackend::getRelocator() const {
206   assert(m_pRelocator != NULL);
207   return m_pRelocator;
208 }
209 
getRelocator()210 Relocator* ARMGNULDBackend::getRelocator() {
211   assert(m_pRelocator != NULL);
212   return m_pRelocator;
213 }
214 
doPreLayout(IRBuilder & pBuilder)215 void 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 
doPostLayout(Module & pModule,IRBuilder & pBuilder)257 void 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.
dynamic()284 ARMELFDynamic& 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.
dynamic() const291 const ARMELFDynamic& ARMGNULDBackend::dynamic() const {
292   assert(m_pDynamic != NULL);
293   return *m_pDynamic;
294 }
295 
defineGOTSymbol(IRBuilder & pBuilder)296 void 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 
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const321 uint64_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
finalizeTargetSymbols()394 bool ARMGNULDBackend::finalizeTargetSymbols() {
395   return true;
396 }
397 
398 
399 /// preMergeSections - hooks to be executed before merging sections
preMergeSections(Module & pModule)400 void ARMGNULDBackend::preMergeSections(Module& pModule) {
401   scanInputExceptionSections(pModule);
402 }
403 
404 /// postMergeSections - hooks to be executed after merging sections
postMergeSections(Module & pModule)405 void 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 
mergeSection(Module & pModule,const Input & pInput,LDSection & pSection)413 bool 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 
setUpReachedSectionsForGC(const Module & pModule,GarbageCollection::SectionReachedListMap & pSectReachedListMap) const484 void 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 
readSection(Input & pInput,SectionData & pSD)548 bool 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 
getGOT()566 ARMGOT& ARMGNULDBackend::getGOT() {
567   assert(m_pGOT != NULL && "GOT section not exist");
568   return *m_pGOT;
569 }
570 
getGOT() const571 const ARMGOT& ARMGNULDBackend::getGOT() const {
572   assert(m_pGOT != NULL && "GOT section not exist");
573   return *m_pGOT;
574 }
575 
getPLT()576 ARMPLT& ARMGNULDBackend::getPLT() {
577   assert(m_pPLT != NULL && "PLT section not exist");
578   return *m_pPLT;
579 }
580 
getPLT() const581 const ARMPLT& ARMGNULDBackend::getPLT() const {
582   assert(m_pPLT != NULL && "PLT section not exist");
583   return *m_pPLT;
584 }
585 
getRelDyn()586 OutputRelocSection& ARMGNULDBackend::getRelDyn() {
587   assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
588   return *m_pRelDyn;
589 }
590 
getRelDyn() const591 const OutputRelocSection& ARMGNULDBackend::getRelDyn() const {
592   assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
593   return *m_pRelDyn;
594 }
595 
getRelPLT()596 OutputRelocSection& ARMGNULDBackend::getRelPLT() {
597   assert(m_pRelPLT != NULL && ".rel.plt section not exist");
598   return *m_pRelPLT;
599 }
600 
getRelPLT() const601 const OutputRelocSection& ARMGNULDBackend::getRelPLT() const {
602   assert(m_pRelPLT != NULL && ".rel.plt section not exist");
603   return *m_pRelPLT;
604 }
605 
getAttributeData()606 ARMELFAttributeData& ARMGNULDBackend::getAttributeData() {
607   assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
608   return *m_pAttrData;
609 }
610 
getAttributeData() const611 const ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const {
612   assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
613   return *m_pAttrData;
614 }
615 
getTargetSectionOrder(const LDSection & pSectHdr) const616 unsigned 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
relax(Module & pModule,IRBuilder & pBuilder)638 bool 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
doRelax(Module & pModule,IRBuilder & pBuilder,bool & pFinished)647 bool 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::StripSymbolMode::StripAllSymbols:
697                 case GeneralOptions::StripSymbolMode::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
initTargetStubs()766 bool 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
maxFwdBranchOffset()780 int64_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
maxBwdBranchOffset()789 int64_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
doCreateProgramHdrs(Module & pModule)799 void 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
mayHaveUnsafeFunctionPointerAccess(const LDSection & pSection) const810 bool 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 ///
createARMLDBackend(const LinkerConfig & pConfig)820 TargetLDBackend* 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 //===----------------------------------------------------------------------===//
MCLDInitializeARMLDBackend()846 extern "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