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