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