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