• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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