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