1 //===- MipsLDBackend.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 "Mips.h"
10 #include "MipsGNUInfo.h"
11 #include "MipsELFDynamic.h"
12 #include "MipsLA25Stub.h"
13 #include "MipsLDBackend.h"
14 #include "MipsRelocator.h"
15
16 #include "mcld/IRBuilder.h"
17 #include "mcld/LinkerConfig.h"
18 #include "mcld/Module.h"
19 #include "mcld/Fragment/FillFragment.h"
20 #include "mcld/LD/BranchIslandFactory.h"
21 #include "mcld/LD/LDContext.h"
22 #include "mcld/LD/StubFactory.h"
23 #include "mcld/LD/ELFFileFormat.h"
24 #include "mcld/MC/Attribute.h"
25 #include "mcld/Object/ObjectBuilder.h"
26 #include "mcld/Support/MemoryRegion.h"
27 #include "mcld/Support/MemoryArea.h"
28 #include "mcld/Support/MsgHandling.h"
29 #include "mcld/Support/TargetRegistry.h"
30 #include "mcld/Target/OutputRelocSection.h"
31
32 #include <llvm/ADT/Triple.h>
33 #include <llvm/Support/Casting.h>
34 #include <llvm/Support/ELF.h>
35 #include <llvm/Support/Host.h>
36
37 namespace mcld {
38
39 //===----------------------------------------------------------------------===//
40 // MipsGNULDBackend
41 //===----------------------------------------------------------------------===//
MipsGNULDBackend(const LinkerConfig & pConfig,MipsGNUInfo * pInfo)42 MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig,
43 MipsGNUInfo* pInfo)
44 : GNULDBackend(pConfig, pInfo),
45 m_pRelocator(NULL),
46 m_pGOT(NULL),
47 m_pPLT(NULL),
48 m_pGOTPLT(NULL),
49 m_pInfo(*pInfo),
50 m_pRelPlt(NULL),
51 m_pRelDyn(NULL),
52 m_pDynamic(NULL),
53 m_pGOTSymbol(NULL),
54 m_pPLTSymbol(NULL),
55 m_pGpDispSymbol(NULL) {
56 }
57
~MipsGNULDBackend()58 MipsGNULDBackend::~MipsGNULDBackend() {
59 delete m_pRelocator;
60 delete m_pPLT;
61 delete m_pRelPlt;
62 delete m_pRelDyn;
63 delete m_pDynamic;
64 }
65
needsLA25Stub(Relocation::Type pType,const mcld::ResolveInfo * pSym)66 bool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType,
67 const mcld::ResolveInfo* pSym) {
68 if (config().isCodeIndep())
69 return false;
70
71 if (llvm::ELF::R_MIPS_26 != pType)
72 return false;
73
74 if (pSym->isLocal())
75 return false;
76
77 return true;
78 }
79
addNonPICBranchSym(ResolveInfo * rsym)80 void MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym) {
81 m_HasNonPICBranchSyms.insert(rsym);
82 }
83
hasNonPICBranch(const ResolveInfo * rsym) const84 bool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const {
85 return m_HasNonPICBranchSyms.count(rsym);
86 }
87
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)88 void MipsGNULDBackend::initTargetSections(Module& pModule,
89 ObjectBuilder& pBuilder) {
90 if (LinkerConfig::Object == config().codeGenType())
91 return;
92
93 ELFFileFormat* file_format = getOutputFormat();
94
95 // initialize .rel.plt
96 LDSection& relplt = file_format->getRelPlt();
97 m_pRelPlt = new OutputRelocSection(pModule, relplt);
98
99 // initialize .rel.dyn
100 LDSection& reldyn = file_format->getRelDyn();
101 m_pRelDyn = new OutputRelocSection(pModule, reldyn);
102 }
103
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)104 void MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
105 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
106 // same name in input
107 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
108 "_GLOBAL_OFFSET_TABLE_",
109 ResolveInfo::Object,
110 ResolveInfo::Define,
111 ResolveInfo::Local,
112 0x0, // size
113 0x0, // value
114 FragmentRef::Null(), // FragRef
115 ResolveInfo::Hidden);
116
117 // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the
118 // same name in input
119 m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
120 "_PROCEDURE_LINKAGE_TABLE_",
121 ResolveInfo::Object,
122 ResolveInfo::Define,
123 ResolveInfo::Local,
124 0x0, // size
125 0x0, // value
126 FragmentRef::Null(), // FragRef
127 ResolveInfo::Hidden);
128
129 m_pGpDispSymbol =
130 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
131 "_gp_disp",
132 ResolveInfo::Section,
133 ResolveInfo::Define,
134 ResolveInfo::Absolute,
135 0x0, // size
136 0x0, // value
137 FragmentRef::Null(), // FragRef
138 ResolveInfo::Default);
139
140 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
141 "_gp",
142 ResolveInfo::NoType,
143 ResolveInfo::Define,
144 ResolveInfo::Absolute,
145 0x0, // size
146 0x0, // value
147 FragmentRef::Null(), // FragRef
148 ResolveInfo::Default);
149 }
150
getRelocator() const151 const Relocator* MipsGNULDBackend::getRelocator() const {
152 assert(m_pRelocator != NULL);
153 return m_pRelocator;
154 }
155
getRelocator()156 Relocator* MipsGNULDBackend::getRelocator() {
157 assert(m_pRelocator != NULL);
158 return m_pRelocator;
159 }
160
doPreLayout(IRBuilder & pBuilder)161 void MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder) {
162 // initialize .dynamic data
163 if (!config().isCodeStatic() && m_pDynamic == NULL)
164 m_pDynamic = new MipsELFDynamic(*this, config());
165
166 // set .got size
167 // when building shared object, the .got section is must.
168 if (LinkerConfig::Object != config().codeGenType()) {
169 if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
170 m_pGOTSymbol != NULL) {
171 m_pGOT->finalizeScanning(*m_pRelDyn);
172 m_pGOT->finalizeSectionSize();
173
174 defineGOTSymbol(pBuilder);
175 }
176
177 if (m_pGOTPLT->hasGOT1()) {
178 m_pGOTPLT->finalizeSectionSize();
179
180 defineGOTPLTSymbol(pBuilder);
181 }
182
183 if (m_pPLT->hasPLT1())
184 m_pPLT->finalizeSectionSize();
185
186 ELFFileFormat* file_format = getOutputFormat();
187
188 // set .rel.plt size
189 if (!m_pRelPlt->empty()) {
190 assert(
191 !config().isCodeStatic() &&
192 "static linkage should not result in a dynamic relocation section");
193 file_format->getRelPlt().setSize(m_pRelPlt->numOfRelocs() *
194 getRelEntrySize());
195 }
196
197 // set .rel.dyn size
198 if (!m_pRelDyn->empty()) {
199 assert(
200 !config().isCodeStatic() &&
201 "static linkage should not result in a dynamic relocation section");
202 file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
203 getRelEntrySize());
204 }
205 }
206 }
207
doPostLayout(Module & pModule,IRBuilder & pBuilder)208 void MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
209 const ELFFileFormat* format = getOutputFormat();
210
211 if (format->hasGOTPLT()) {
212 assert(m_pGOTPLT != NULL && "doPostLayout failed, m_pGOTPLT is NULL!");
213 m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr());
214 }
215
216 if (format->hasPLT()) {
217 assert(m_pPLT != NULL && "doPostLayout failed, m_pPLT is NULL!");
218 m_pPLT->applyAllPLT(*m_pGOTPLT);
219 }
220
221 m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0);
222
223 // FIXME: (simon) We need to iterate all input sections
224 // check that flags are consistent and merge them properly.
225 uint64_t picFlags = llvm::ELF::EF_MIPS_CPIC;
226 if (config().targets().triple().isArch64Bit()) {
227 picFlags |= llvm::ELF::EF_MIPS_PIC;
228 } else {
229 if (LinkerConfig::DynObj == config().codeGenType())
230 picFlags |= llvm::ELF::EF_MIPS_PIC;
231 }
232
233 m_pInfo.setPICFlags(picFlags);
234 }
235
236 /// dynamic - the dynamic section of the target machine.
237 /// Use co-variant return type to return its own dynamic section.
dynamic()238 MipsELFDynamic& MipsGNULDBackend::dynamic() {
239 assert(m_pDynamic != NULL);
240 return *m_pDynamic;
241 }
242
243 /// dynamic - the dynamic section of the target machine.
244 /// Use co-variant return type to return its own dynamic section.
dynamic() const245 const MipsELFDynamic& MipsGNULDBackend::dynamic() const {
246 assert(m_pDynamic != NULL);
247 return *m_pDynamic;
248 }
249
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const250 uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
251 MemoryRegion& pRegion) const {
252 assert(pRegion.size() && "Size of MemoryRegion is zero!");
253
254 const ELFFileFormat* file_format = getOutputFormat();
255
256 if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
257 return m_pGOT->emit(pRegion);
258 }
259
260 if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
261 return m_pPLT->emit(pRegion);
262 }
263
264 if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
265 return m_pGOTPLT->emit(pRegion);
266 }
267
268 fatal(diag::unrecognized_output_sectoin) << pSection.name()
269 << "mclinker@googlegroups.com";
270 return 0;
271 }
272
hasEntryInStrTab(const LDSymbol & pSym) const273 bool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const {
274 return ResolveInfo::Section != pSym.type() || m_pGpDispSymbol == &pSym;
275 }
276
277 namespace {
278 struct DynsymGOTCompare {
279 const MipsGOT& m_pGOT;
280
DynsymGOTComparemcld::__anon714f9ad10111::DynsymGOTCompare281 explicit DynsymGOTCompare(const MipsGOT& pGOT) : m_pGOT(pGOT) {}
282
operator ()mcld::__anon714f9ad10111::DynsymGOTCompare283 bool operator()(const LDSymbol* X, const LDSymbol* Y) const {
284 return m_pGOT.dynSymOrderCompare(X, Y);
285 }
286 };
287 } // anonymous namespace
288
orderSymbolTable(Module & pModule)289 void MipsGNULDBackend::orderSymbolTable(Module& pModule) {
290 if (config().options().hasGNUHash()) {
291 // The MIPS ABI and .gnu.hash require .dynsym to be sorted
292 // in different ways. The MIPS ABI requires a mapping between
293 // the GOT and the symbol table. At the same time .gnu.hash
294 // needs symbols to be grouped by hash code.
295 llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n";
296 }
297
298 Module::SymbolTable& symbols = pModule.getSymbolTable();
299
300 std::stable_sort(
301 symbols.dynamicBegin(), symbols.dynamicEnd(), DynsymGOTCompare(*m_pGOT));
302 }
303
304 } // namespace mcld
305
306 namespace llvm {
307 namespace ELF {
308 // SHT_MIPS_OPTIONS section's block descriptor.
309 struct Elf_Options {
310 unsigned char kind; // Determines interpretation of variable
311 // part of descriptor. See ODK_xxx enumeration.
312 unsigned char size; // Byte size of descriptor, including this header.
313 Elf64_Half section; // Section header index of section affected,
314 // or 0 for global options.
315 Elf64_Word info; // Kind-specific information.
316 };
317
318 // Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
319 struct Elf32_RegInfo {
320 Elf32_Word ri_gprmask; // Mask of general purpose registers used.
321 Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
322 Elf32_Addr ri_gp_value; // GP register value for this object file.
323 };
324
325 // Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
326 struct Elf64_RegInfo {
327 Elf32_Word ri_gprmask; // Mask of general purpose registers used.
328 Elf32_Word ri_pad; // Padding.
329 Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
330 Elf64_Addr ri_gp_value; // GP register value for this object file.
331 };
332
333 } // namespace ELF
334 } // namespace llvm
335
336 namespace mcld {
337
readSection(Input & pInput,SectionData & pSD)338 bool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
339 llvm::StringRef name(pSD.getSection().name());
340
341 if (name.startswith(".sdata")) {
342 uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
343 uint64_t size = pSD.getSection().size();
344
345 Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
346 ObjectBuilder::AppendFragment(*frag, pSD);
347 return true;
348 }
349
350 if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
351 uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
352 uint32_t size = pSD.getSection().size();
353
354 llvm::StringRef region = pInput.memArea()->request(offset, size);
355 if (region.size() > 0) {
356 const llvm::ELF::Elf_Options* optb =
357 reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
358 const llvm::ELF::Elf_Options* opte =
359 reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() +
360 size);
361
362 for (const llvm::ELF::Elf_Options* opt = optb; opt < opte;
363 opt += opt->size) {
364 switch (opt->kind) {
365 default:
366 // Nothing to do.
367 break;
368 case llvm::ELF::ODK_REGINFO:
369 if (config().targets().triple().isArch32Bit()) {
370 const llvm::ELF::Elf32_RegInfo* reg =
371 reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
372 m_GP0Map[&pInput] = reg->ri_gp_value;
373 } else {
374 const llvm::ELF::Elf64_RegInfo* reg =
375 reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
376 m_GP0Map[&pInput] = reg->ri_gp_value;
377 }
378 break;
379 }
380 }
381 }
382
383 return true;
384 }
385
386 return GNULDBackend::readSection(pInput, pSD);
387 }
388
getGOT()389 MipsGOT& MipsGNULDBackend::getGOT() {
390 assert(m_pGOT != NULL);
391 return *m_pGOT;
392 }
393
getGOT() const394 const MipsGOT& MipsGNULDBackend::getGOT() const {
395 assert(m_pGOT != NULL);
396 return *m_pGOT;
397 }
398
getPLT()399 MipsPLT& MipsGNULDBackend::getPLT() {
400 assert(m_pPLT != NULL);
401 return *m_pPLT;
402 }
403
getPLT() const404 const MipsPLT& MipsGNULDBackend::getPLT() const {
405 assert(m_pPLT != NULL);
406 return *m_pPLT;
407 }
408
getGOTPLT()409 MipsGOTPLT& MipsGNULDBackend::getGOTPLT() {
410 assert(m_pGOTPLT != NULL);
411 return *m_pGOTPLT;
412 }
413
getGOTPLT() const414 const MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const {
415 assert(m_pGOTPLT != NULL);
416 return *m_pGOTPLT;
417 }
418
getRelPLT()419 OutputRelocSection& MipsGNULDBackend::getRelPLT() {
420 assert(m_pRelPlt != NULL);
421 return *m_pRelPlt;
422 }
423
getRelPLT() const424 const OutputRelocSection& MipsGNULDBackend::getRelPLT() const {
425 assert(m_pRelPlt != NULL);
426 return *m_pRelPlt;
427 }
428
getRelDyn()429 OutputRelocSection& MipsGNULDBackend::getRelDyn() {
430 assert(m_pRelDyn != NULL);
431 return *m_pRelDyn;
432 }
433
getRelDyn() const434 const OutputRelocSection& MipsGNULDBackend::getRelDyn() const {
435 assert(m_pRelDyn != NULL);
436 return *m_pRelDyn;
437 }
438
getTargetSectionOrder(const LDSection & pSectHdr) const439 unsigned int MipsGNULDBackend::getTargetSectionOrder(
440 const LDSection& pSectHdr) const {
441 const ELFFileFormat* file_format = getOutputFormat();
442
443 if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
444 return SHO_DATA;
445
446 if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
447 return SHO_DATA;
448
449 if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
450 return SHO_PLT;
451
452 return SHO_UNDEFINED;
453 }
454
455 /// finalizeSymbol - finalize the symbol value
finalizeTargetSymbols()456 bool MipsGNULDBackend::finalizeTargetSymbols() {
457 if (m_pGpDispSymbol != NULL)
458 m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress());
459
460 return true;
461 }
462
463 /// allocateCommonSymbols - allocate common symbols in the corresponding
464 /// sections. This is called at pre-layout stage.
465 /// FIXME: Mips needs to allocate small common symbol
allocateCommonSymbols(Module & pModule)466 bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule) {
467 SymbolCategory& symbol_list = pModule.getSymbolTable();
468
469 if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
470 symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
471 return true;
472
473 SymbolCategory::iterator com_sym, com_end;
474
475 // FIXME: If the order of common symbols is defined, then sort common symbols
476 // std::sort(com_sym, com_end, some kind of order);
477
478 // get corresponding BSS LDSection
479 ELFFileFormat* file_format = getOutputFormat();
480 LDSection& bss_sect = file_format->getBSS();
481 LDSection& tbss_sect = file_format->getTBSS();
482
483 // get or create corresponding BSS SectionData
484 SectionData* bss_sect_data = NULL;
485 if (bss_sect.hasSectionData())
486 bss_sect_data = bss_sect.getSectionData();
487 else
488 bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
489
490 SectionData* tbss_sect_data = NULL;
491 if (tbss_sect.hasSectionData())
492 tbss_sect_data = tbss_sect.getSectionData();
493 else
494 tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
495
496 // remember original BSS size
497 uint64_t bss_offset = bss_sect.size();
498 uint64_t tbss_offset = tbss_sect.size();
499
500 // allocate all local common symbols
501 com_end = symbol_list.localEnd();
502
503 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
504 if (ResolveInfo::Common == (*com_sym)->desc()) {
505 // We have to reset the description of the symbol here. When doing
506 // incremental linking, the output relocatable object may have common
507 // symbols. Therefore, we can not treat common symbols as normal symbols
508 // when emitting the regular name pools. We must change the symbols'
509 // description here.
510 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
511 Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
512
513 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
514 // allocate TLS common symbol in tbss section
515 tbss_offset += ObjectBuilder::AppendFragment(
516 *frag, *tbss_sect_data, (*com_sym)->value());
517 ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
518 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
519 } else {
520 // FIXME: how to identify small and large common symbols?
521 bss_offset += ObjectBuilder::AppendFragment(
522 *frag, *bss_sect_data, (*com_sym)->value());
523 ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
524 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
525 }
526 }
527 }
528
529 // allocate all global common symbols
530 com_end = symbol_list.commonEnd();
531 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
532 // We have to reset the description of the symbol here. When doing
533 // incremental linking, the output relocatable object may have common
534 // symbols. Therefore, we can not treat common symbols as normal symbols
535 // when emitting the regular name pools. We must change the symbols'
536 // description here.
537 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
538 Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
539
540 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
541 // allocate TLS common symbol in tbss section
542 tbss_offset += ObjectBuilder::AppendFragment(
543 *frag, *tbss_sect_data, (*com_sym)->value());
544 ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
545 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
546 } else {
547 // FIXME: how to identify small and large common symbols?
548 bss_offset += ObjectBuilder::AppendFragment(
549 *frag, *bss_sect_data, (*com_sym)->value());
550 ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
551 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
552 }
553 }
554
555 bss_sect.setSize(bss_offset);
556 tbss_sect.setSize(tbss_offset);
557 symbol_list.changeCommonsToGlobal();
558 return true;
559 }
560
getGP0(const Input & pInput) const561 uint64_t MipsGNULDBackend::getGP0(const Input& pInput) const {
562 return m_GP0Map.lookup(&pInput);
563 }
564
defineGOTSymbol(IRBuilder & pBuilder)565 void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
566 // If we do not reserve any GOT entries, we do not need to re-define GOT
567 // symbol.
568 if (!m_pGOT->hasGOT1())
569 return;
570
571 // define symbol _GLOBAL_OFFSET_TABLE_
572 if (m_pGOTSymbol != NULL) {
573 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
574 "_GLOBAL_OFFSET_TABLE_",
575 ResolveInfo::Object,
576 ResolveInfo::Define,
577 ResolveInfo::Local,
578 0x0, // size
579 0x0, // value
580 FragmentRef::Create(*(m_pGOT->begin()), 0x0),
581 ResolveInfo::Hidden);
582 } else {
583 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
584 "_GLOBAL_OFFSET_TABLE_",
585 ResolveInfo::Object,
586 ResolveInfo::Define,
587 ResolveInfo::Local,
588 0x0, // size
589 0x0, // value
590 FragmentRef::Create(*(m_pGOT->begin()), 0x0),
591 ResolveInfo::Hidden);
592 }
593 }
594
defineGOTPLTSymbol(IRBuilder & pBuilder)595 void MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder) {
596 // define symbol _PROCEDURE_LINKAGE_TABLE_
597 if (m_pPLTSymbol != NULL) {
598 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
599 "_PROCEDURE_LINKAGE_TABLE_",
600 ResolveInfo::Object,
601 ResolveInfo::Define,
602 ResolveInfo::Local,
603 0x0, // size
604 0x0, // value
605 FragmentRef::Create(*(m_pPLT->begin()), 0x0),
606 ResolveInfo::Hidden);
607 } else {
608 m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
609 "_PROCEDURE_LINKAGE_TABLE_",
610 ResolveInfo::Object,
611 ResolveInfo::Define,
612 ResolveInfo::Local,
613 0x0, // size
614 0x0, // value
615 FragmentRef::Create(*(m_pPLT->begin()), 0x0),
616 ResolveInfo::Hidden);
617 }
618 }
619
620 /// doCreateProgramHdrs - backend can implement this function to create the
621 /// target-dependent segments
doCreateProgramHdrs(Module & pModule)622 void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule) {
623 // TODO
624 }
625
relaxRelocation(IRBuilder & pBuilder,Relocation & pRel)626 bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) {
627 uint64_t sym_value = 0x0;
628
629 LDSymbol* symbol = pRel.symInfo()->outSymbol();
630 if (symbol->hasFragRef()) {
631 uint64_t value = symbol->fragRef()->getOutputOffset();
632 uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
633 sym_value = addr + value;
634 }
635
636 Stub* stub = getStubFactory()->create(
637 pRel, sym_value, pBuilder, *getBRIslandFactory());
638
639 if (stub == NULL)
640 return false;
641
642 assert(stub->symInfo() != NULL);
643 // increase the size of .symtab and .strtab
644 LDSection& symtab = getOutputFormat()->getSymTab();
645 LDSection& strtab = getOutputFormat()->getStrTab();
646 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
647 strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
648
649 return true;
650 }
651
doRelax(Module & pModule,IRBuilder & pBuilder,bool & pFinished)652 bool MipsGNULDBackend::doRelax(Module& pModule,
653 IRBuilder& pBuilder,
654 bool& pFinished) {
655 assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
656
657 bool isRelaxed = false;
658
659 for (Module::obj_iterator input = pModule.obj_begin();
660 input != pModule.obj_end();
661 ++input) {
662 LDContext* context = (*input)->context();
663
664 for (LDContext::sect_iterator rs = context->relocSectBegin();
665 rs != context->relocSectEnd();
666 ++rs) {
667 LDSection* sec = *rs;
668
669 if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
670 continue;
671
672 for (RelocData::iterator reloc = sec->getRelocData()->begin();
673 reloc != sec->getRelocData()->end();
674 ++reloc) {
675 if (llvm::ELF::R_MIPS_26 != reloc->type())
676 continue;
677
678 if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
679 isRelaxed = true;
680 }
681 }
682 }
683
684 SectionData* textData = getOutputFormat()->getText().getSectionData();
685
686 // find the first fragment w/ invalid offset due to stub insertion
687 Fragment* invalid = NULL;
688 pFinished = true;
689 for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
690 ie = getBRIslandFactory()->end();
691 ii != ie;
692 ++ii) {
693 BranchIsland& island = *ii;
694 if (island.end() == textData->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 (invalid != NULL) {
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 getOutputFormat()->getText().setSize(textData->back().getOffset() +
715 textData->back().size());
716
717 return isRelaxed;
718 }
719
initTargetStubs()720 bool MipsGNULDBackend::initTargetStubs() {
721 if (getStubFactory() == NULL)
722 return false;
723
724 getStubFactory()->addPrototype(new MipsLA25Stub(*this));
725 return true;
726 }
727
readRelocation(const llvm::ELF::Elf32_Rel & pRel,Relocation::Type & pType,uint32_t & pSymIdx,uint32_t & pOffset) const728 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
729 Relocation::Type& pType,
730 uint32_t& pSymIdx,
731 uint32_t& pOffset) const {
732 return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
733 }
734
readRelocation(const llvm::ELF::Elf32_Rela & pRel,Relocation::Type & pType,uint32_t & pSymIdx,uint32_t & pOffset,int32_t & pAddend) const735 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
736 Relocation::Type& pType,
737 uint32_t& pSymIdx,
738 uint32_t& pOffset,
739 int32_t& pAddend) const {
740 return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
741 }
742
readRelocation(const llvm::ELF::Elf64_Rel & pRel,Relocation::Type & pType,uint32_t & pSymIdx,uint64_t & pOffset) const743 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
744 Relocation::Type& pType,
745 uint32_t& pSymIdx,
746 uint64_t& pOffset) const {
747 uint64_t r_info = 0x0;
748 if (llvm::sys::IsLittleEndianHost) {
749 pOffset = pRel.r_offset;
750 r_info = pRel.r_info;
751 } else {
752 pOffset = mcld::bswap64(pRel.r_offset);
753 r_info = mcld::bswap64(pRel.r_info);
754 }
755
756 // MIPS 64 little endian (we do not support big endian now)
757 // has a "special" encoding of r_info relocation
758 // field. Instead of one 64 bit little endian number, it is a little
759 // endian 32 bit number followed by a 32 bit big endian number.
760 pType = mcld::bswap32(r_info >> 32);
761 pSymIdx = r_info & 0xffffffff;
762 return true;
763 }
764
readRelocation(const llvm::ELF::Elf64_Rela & pRel,Relocation::Type & pType,uint32_t & pSymIdx,uint64_t & pOffset,int64_t & pAddend) const765 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
766 Relocation::Type& pType,
767 uint32_t& pSymIdx,
768 uint64_t& pOffset,
769 int64_t& pAddend) const {
770 uint64_t r_info = 0x0;
771 if (llvm::sys::IsLittleEndianHost) {
772 pOffset = pRel.r_offset;
773 r_info = pRel.r_info;
774 pAddend = pRel.r_addend;
775 } else {
776 pOffset = mcld::bswap64(pRel.r_offset);
777 r_info = mcld::bswap64(pRel.r_info);
778 pAddend = mcld::bswap64(pRel.r_addend);
779 }
780
781 pType = mcld::bswap32(r_info >> 32);
782 pSymIdx = r_info & 0xffffffff;
783 return true;
784 }
785
emitRelocation(llvm::ELF::Elf32_Rel & pRel,Relocation::Type pType,uint32_t pSymIdx,uint32_t pOffset) const786 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
787 Relocation::Type pType,
788 uint32_t pSymIdx,
789 uint32_t pOffset) const {
790 GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
791 }
792
emitRelocation(llvm::ELF::Elf32_Rela & pRel,Relocation::Type pType,uint32_t pSymIdx,uint32_t pOffset,int32_t pAddend) const793 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
794 Relocation::Type pType,
795 uint32_t pSymIdx,
796 uint32_t pOffset,
797 int32_t pAddend) const {
798 GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
799 }
800
emitRelocation(llvm::ELF::Elf64_Rel & pRel,Relocation::Type pType,uint32_t pSymIdx,uint64_t pOffset) const801 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
802 Relocation::Type pType,
803 uint32_t pSymIdx,
804 uint64_t pOffset) const {
805 uint64_t r_info = mcld::bswap32(pType);
806 r_info <<= 32;
807 r_info |= pSymIdx;
808
809 pRel.r_info = r_info;
810 pRel.r_offset = pOffset;
811 }
812
emitRelocation(llvm::ELF::Elf64_Rela & pRel,Relocation::Type pType,uint32_t pSymIdx,uint64_t pOffset,int64_t pAddend) const813 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
814 Relocation::Type pType,
815 uint32_t pSymIdx,
816 uint64_t pOffset,
817 int64_t pAddend) const {
818 uint64_t r_info = mcld::bswap32(pType);
819 r_info <<= 32;
820 r_info |= pSymIdx;
821
822 pRel.r_info = r_info;
823 pRel.r_offset = pOffset;
824 pRel.r_addend = pAddend;
825 }
826
827 //===----------------------------------------------------------------------===//
828 // Mips32GNULDBackend
829 //===----------------------------------------------------------------------===//
Mips32GNULDBackend(const LinkerConfig & pConfig,MipsGNUInfo * pInfo)830 Mips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
831 MipsGNUInfo* pInfo)
832 : MipsGNULDBackend(pConfig, pInfo) {
833 }
834
initRelocator()835 bool Mips32GNULDBackend::initRelocator() {
836 if (m_pRelocator == NULL)
837 m_pRelocator = new Mips32Relocator(*this, config());
838
839 return true;
840 }
841
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)842 void Mips32GNULDBackend::initTargetSections(Module& pModule,
843 ObjectBuilder& pBuilder) {
844 MipsGNULDBackend::initTargetSections(pModule, pBuilder);
845
846 if (LinkerConfig::Object == config().codeGenType())
847 return;
848
849 ELFFileFormat* fileFormat = getOutputFormat();
850
851 // initialize .got
852 LDSection& got = fileFormat->getGOT();
853 m_pGOT = new Mips32GOT(got);
854
855 // initialize .got.plt
856 LDSection& gotplt = fileFormat->getGOTPLT();
857 m_pGOTPLT = new MipsGOTPLT(gotplt);
858
859 // initialize .plt
860 LDSection& plt = fileFormat->getPLT();
861 m_pPLT = new MipsPLT(plt);
862 }
863
getRelEntrySize()864 size_t Mips32GNULDBackend::getRelEntrySize() {
865 return 8;
866 }
867
getRelaEntrySize()868 size_t Mips32GNULDBackend::getRelaEntrySize() {
869 return 12;
870 }
871
872 //===----------------------------------------------------------------------===//
873 // Mips64GNULDBackend
874 //===----------------------------------------------------------------------===//
Mips64GNULDBackend(const LinkerConfig & pConfig,MipsGNUInfo * pInfo)875 Mips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
876 MipsGNUInfo* pInfo)
877 : MipsGNULDBackend(pConfig, pInfo) {
878 }
879
initRelocator()880 bool Mips64GNULDBackend::initRelocator() {
881 if (m_pRelocator == NULL)
882 m_pRelocator = new Mips64Relocator(*this, config());
883
884 return true;
885 }
886
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)887 void Mips64GNULDBackend::initTargetSections(Module& pModule,
888 ObjectBuilder& pBuilder) {
889 MipsGNULDBackend::initTargetSections(pModule, pBuilder);
890
891 if (LinkerConfig::Object == config().codeGenType())
892 return;
893
894 ELFFileFormat* fileFormat = getOutputFormat();
895
896 // initialize .got
897 LDSection& got = fileFormat->getGOT();
898 m_pGOT = new Mips64GOT(got);
899
900 // initialize .got.plt
901 LDSection& gotplt = fileFormat->getGOTPLT();
902 m_pGOTPLT = new MipsGOTPLT(gotplt);
903
904 // initialize .plt
905 LDSection& plt = fileFormat->getPLT();
906 m_pPLT = new MipsPLT(plt);
907 }
908
getRelEntrySize()909 size_t Mips64GNULDBackend::getRelEntrySize() {
910 return 16;
911 }
912
getRelaEntrySize()913 size_t Mips64GNULDBackend::getRelaEntrySize() {
914 return 24;
915 }
916
917 //===----------------------------------------------------------------------===//
918 /// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
919 ///
createMipsLDBackend(const LinkerConfig & pConfig)920 static TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig) {
921 const llvm::Triple& triple = pConfig.targets().triple();
922
923 if (triple.isOSDarwin()) {
924 assert(0 && "MachO linker is not supported yet");
925 }
926 if (triple.isOSWindows()) {
927 assert(0 && "COFF linker is not supported yet");
928 }
929
930 llvm::Triple::ArchType arch = triple.getArch();
931
932 if (llvm::Triple::mips64el == arch)
933 return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
934
935 assert(arch == llvm::Triple::mipsel);
936 return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
937 }
938
939 } // namespace mcld
940
941 //===----------------------------------------------------------------------===//
942 // Force static initialization.
943 //===----------------------------------------------------------------------===//
MCLDInitializeMipsLDBackend()944 extern "C" void MCLDInitializeMipsLDBackend() {
945 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
946 mcld::createMipsLDBackend);
947 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
948 mcld::createMipsLDBackend);
949 }
950