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