MipsLDBackend.cpp revision a6c24dff8b7fa2551a3a885e77a2e814f5b764a2
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
37namespace mcld {
38
39//===----------------------------------------------------------------------===//
40// MipsGNULDBackend
41//===----------------------------------------------------------------------===//
42MipsGNULDBackend::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
58MipsGNULDBackend::~MipsGNULDBackend() {
59  delete m_pRelocator;
60  delete m_pPLT;
61  delete m_pRelPlt;
62  delete m_pRelDyn;
63  delete m_pDynamic;
64}
65
66bool 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
80void MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym) {
81  m_HasNonPICBranchSyms.insert(rsym);
82}
83
84bool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const {
85  return m_HasNonPICBranchSyms.count(rsym);
86}
87
88void 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
104void 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
151const Relocator* MipsGNULDBackend::getRelocator() const {
152  assert(m_pRelocator != NULL);
153  return m_pRelocator;
154}
155
156Relocator* MipsGNULDBackend::getRelocator() {
157  assert(m_pRelocator != NULL);
158  return m_pRelocator;
159}
160
161void 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
208void 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.
238MipsELFDynamic& 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.
245const MipsELFDynamic& MipsGNULDBackend::dynamic() const {
246  assert(m_pDynamic != NULL);
247  return *m_pDynamic;
248}
249
250uint64_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
273bool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const {
274  return ResolveInfo::Section != pSym.type() || m_pGpDispSymbol == &pSym;
275}
276
277namespace {
278struct DynsymGOTCompare {
279  const MipsGOT& m_pGOT;
280
281  explicit DynsymGOTCompare(const MipsGOT& pGOT) : m_pGOT(pGOT) {}
282
283  bool operator()(const LDSymbol* X, const LDSymbol* Y) const {
284    return m_pGOT.dynSymOrderCompare(X, Y);
285  }
286};
287}  // anonymous namespace
288
289void MipsGNULDBackend::orderSymbolTable(Module& pModule) {
290  if (GeneralOptions::GNU == config().options().getHashStyle() ||
291      GeneralOptions::Both == config().options().getHashStyle()) {
292    // The MIPS ABI and .gnu.hash require .dynsym to be sorted
293    // in different ways. The MIPS ABI requires a mapping between
294    // the GOT and the symbol table. At the same time .gnu.hash
295    // needs symbols to be grouped by hash code.
296    llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n";
297  }
298
299  Module::SymbolTable& symbols = pModule.getSymbolTable();
300
301  std::stable_sort(
302      symbols.dynamicBegin(), symbols.dynamicEnd(), DynsymGOTCompare(*m_pGOT));
303}
304
305}  // namespace mcld
306
307namespace llvm {
308namespace ELF {
309// SHT_MIPS_OPTIONS section's block descriptor.
310struct Elf_Options {
311  unsigned char kind;  // Determines interpretation of variable
312                       // part of descriptor. See ODK_xxx enumeration.
313  unsigned char size;  // Byte size of descriptor, including this header.
314  Elf64_Half section;  // Section header index of section affected,
315                       // or 0 for global options.
316  Elf64_Word info;     // Kind-specific information.
317};
318
319// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
320struct Elf32_RegInfo {
321  Elf32_Word ri_gprmask;     // Mask of general purpose registers used.
322  Elf32_Word ri_cprmask[4];  // Mask of co-processor registers used.
323  Elf32_Addr ri_gp_value;    // GP register value for this object file.
324};
325
326// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
327struct Elf64_RegInfo {
328  Elf32_Word ri_gprmask;     // Mask of general purpose registers used.
329  Elf32_Word ri_pad;         // Padding.
330  Elf32_Word ri_cprmask[4];  // Mask of co-processor registers used.
331  Elf64_Addr ri_gp_value;    // GP register value for this object file.
332};
333
334}  // namespace ELF
335}  // namespace llvm
336
337namespace mcld {
338
339bool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
340  llvm::StringRef name(pSD.getSection().name());
341
342  if (name.startswith(".sdata")) {
343    uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
344    uint64_t size = pSD.getSection().size();
345
346    Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
347    ObjectBuilder::AppendFragment(*frag, pSD);
348    return true;
349  }
350
351  if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
352    uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
353    uint32_t size = pSD.getSection().size();
354
355    llvm::StringRef region = pInput.memArea()->request(offset, size);
356    if (region.size() > 0) {
357      const llvm::ELF::Elf_Options* optb =
358          reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
359      const llvm::ELF::Elf_Options* opte =
360          reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() +
361                                                          size);
362
363      for (const llvm::ELF::Elf_Options* opt = optb; opt < opte;
364           opt += opt->size) {
365        switch (opt->kind) {
366          default:
367            // Nothing to do.
368            break;
369          case llvm::ELF::ODK_REGINFO:
370            if (config().targets().triple().isArch32Bit()) {
371              const llvm::ELF::Elf32_RegInfo* reg =
372                  reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
373              m_GP0Map[&pInput] = reg->ri_gp_value;
374            } else {
375              const llvm::ELF::Elf64_RegInfo* reg =
376                  reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
377              m_GP0Map[&pInput] = reg->ri_gp_value;
378            }
379            break;
380        }
381      }
382    }
383
384    return true;
385  }
386
387  return GNULDBackend::readSection(pInput, pSD);
388}
389
390MipsGOT& MipsGNULDBackend::getGOT() {
391  assert(m_pGOT != NULL);
392  return *m_pGOT;
393}
394
395const MipsGOT& MipsGNULDBackend::getGOT() const {
396  assert(m_pGOT != NULL);
397  return *m_pGOT;
398}
399
400MipsPLT& MipsGNULDBackend::getPLT() {
401  assert(m_pPLT != NULL);
402  return *m_pPLT;
403}
404
405const MipsPLT& MipsGNULDBackend::getPLT() const {
406  assert(m_pPLT != NULL);
407  return *m_pPLT;
408}
409
410MipsGOTPLT& MipsGNULDBackend::getGOTPLT() {
411  assert(m_pGOTPLT != NULL);
412  return *m_pGOTPLT;
413}
414
415const MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const {
416  assert(m_pGOTPLT != NULL);
417  return *m_pGOTPLT;
418}
419
420OutputRelocSection& MipsGNULDBackend::getRelPLT() {
421  assert(m_pRelPlt != NULL);
422  return *m_pRelPlt;
423}
424
425const OutputRelocSection& MipsGNULDBackend::getRelPLT() const {
426  assert(m_pRelPlt != NULL);
427  return *m_pRelPlt;
428}
429
430OutputRelocSection& MipsGNULDBackend::getRelDyn() {
431  assert(m_pRelDyn != NULL);
432  return *m_pRelDyn;
433}
434
435const OutputRelocSection& MipsGNULDBackend::getRelDyn() const {
436  assert(m_pRelDyn != NULL);
437  return *m_pRelDyn;
438}
439
440unsigned int MipsGNULDBackend::getTargetSectionOrder(
441    const LDSection& pSectHdr) const {
442  const ELFFileFormat* file_format = getOutputFormat();
443
444  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
445    return SHO_DATA;
446
447  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
448    return SHO_DATA;
449
450  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
451    return SHO_PLT;
452
453  return SHO_UNDEFINED;
454}
455
456/// finalizeSymbol - finalize the symbol value
457bool MipsGNULDBackend::finalizeTargetSymbols() {
458  if (m_pGpDispSymbol != NULL)
459    m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress());
460
461  return true;
462}
463
464/// allocateCommonSymbols - allocate common symbols in the corresponding
465/// sections. This is called at pre-layout stage.
466/// FIXME: Mips needs to allocate small common symbol
467bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule) {
468  SymbolCategory& symbol_list = pModule.getSymbolTable();
469
470  if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
471      symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
472    return true;
473
474  SymbolCategory::iterator com_sym, com_end;
475
476  // FIXME: If the order of common symbols is defined, then sort common symbols
477  // std::sort(com_sym, com_end, some kind of order);
478
479  // get corresponding BSS LDSection
480  ELFFileFormat* file_format = getOutputFormat();
481  LDSection& bss_sect = file_format->getBSS();
482  LDSection& tbss_sect = file_format->getTBSS();
483
484  // get or create corresponding BSS SectionData
485  SectionData* bss_sect_data = NULL;
486  if (bss_sect.hasSectionData())
487    bss_sect_data = bss_sect.getSectionData();
488  else
489    bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
490
491  SectionData* tbss_sect_data = NULL;
492  if (tbss_sect.hasSectionData())
493    tbss_sect_data = tbss_sect.getSectionData();
494  else
495    tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
496
497  // remember original BSS size
498  uint64_t bss_offset = bss_sect.size();
499  uint64_t tbss_offset = tbss_sect.size();
500
501  // allocate all local common symbols
502  com_end = symbol_list.localEnd();
503
504  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
505    if (ResolveInfo::Common == (*com_sym)->desc()) {
506      // We have to reset the description of the symbol here. When doing
507      // incremental linking, the output relocatable object may have common
508      // symbols. Therefore, we can not treat common symbols as normal symbols
509      // when emitting the regular name pools. We must change the symbols'
510      // description here.
511      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
512      Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
513
514      if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
515        // allocate TLS common symbol in tbss section
516        tbss_offset += ObjectBuilder::AppendFragment(
517            *frag, *tbss_sect_data, (*com_sym)->value());
518        ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
519        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
520      } else {
521        // FIXME: how to identify small and large common symbols?
522        bss_offset += ObjectBuilder::AppendFragment(
523            *frag, *bss_sect_data, (*com_sym)->value());
524        ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
525        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
526      }
527    }
528  }
529
530  // allocate all global common symbols
531  com_end = symbol_list.commonEnd();
532  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
533    // We have to reset the description of the symbol here. When doing
534    // incremental linking, the output relocatable object may have common
535    // symbols. Therefore, we can not treat common symbols as normal symbols
536    // when emitting the regular name pools. We must change the symbols'
537    // description here.
538    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
539    Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
540
541    if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
542      // allocate TLS common symbol in tbss section
543      tbss_offset += ObjectBuilder::AppendFragment(
544          *frag, *tbss_sect_data, (*com_sym)->value());
545      ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
546      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
547    } else {
548      // FIXME: how to identify small and large common symbols?
549      bss_offset += ObjectBuilder::AppendFragment(
550          *frag, *bss_sect_data, (*com_sym)->value());
551      ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
552      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
553    }
554  }
555
556  bss_sect.setSize(bss_offset);
557  tbss_sect.setSize(tbss_offset);
558  symbol_list.changeCommonsToGlobal();
559  return true;
560}
561
562uint64_t MipsGNULDBackend::getGP0(const Input& pInput) const {
563  return m_GP0Map.lookup(&pInput);
564}
565
566void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
567  // If we do not reserve any GOT entries, we do not need to re-define GOT
568  // symbol.
569  if (!m_pGOT->hasGOT1())
570    return;
571
572  // define symbol _GLOBAL_OFFSET_TABLE_
573  if (m_pGOTSymbol != NULL) {
574    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
575        "_GLOBAL_OFFSET_TABLE_",
576        ResolveInfo::Object,
577        ResolveInfo::Define,
578        ResolveInfo::Local,
579        0x0,  // size
580        0x0,  // value
581        FragmentRef::Create(*(m_pGOT->begin()), 0x0),
582        ResolveInfo::Hidden);
583  } else {
584    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
585        "_GLOBAL_OFFSET_TABLE_",
586        ResolveInfo::Object,
587        ResolveInfo::Define,
588        ResolveInfo::Local,
589        0x0,  // size
590        0x0,  // value
591        FragmentRef::Create(*(m_pGOT->begin()), 0x0),
592        ResolveInfo::Hidden);
593  }
594}
595
596void MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder) {
597  // define symbol _PROCEDURE_LINKAGE_TABLE_
598  if (m_pPLTSymbol != NULL) {
599    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
600        "_PROCEDURE_LINKAGE_TABLE_",
601        ResolveInfo::Object,
602        ResolveInfo::Define,
603        ResolveInfo::Local,
604        0x0,  // size
605        0x0,  // value
606        FragmentRef::Create(*(m_pPLT->begin()), 0x0),
607        ResolveInfo::Hidden);
608  } else {
609    m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
610        "_PROCEDURE_LINKAGE_TABLE_",
611        ResolveInfo::Object,
612        ResolveInfo::Define,
613        ResolveInfo::Local,
614        0x0,  // size
615        0x0,  // value
616        FragmentRef::Create(*(m_pPLT->begin()), 0x0),
617        ResolveInfo::Hidden);
618  }
619}
620
621/// doCreateProgramHdrs - backend can implement this function to create the
622/// target-dependent segments
623void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule) {
624  // TODO
625}
626
627bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) {
628  uint64_t sym_value = 0x0;
629
630  LDSymbol* symbol = pRel.symInfo()->outSymbol();
631  if (symbol->hasFragRef()) {
632    uint64_t value = symbol->fragRef()->getOutputOffset();
633    uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
634    sym_value = addr + value;
635  }
636
637  Stub* stub = getStubFactory()->create(
638      pRel, sym_value, pBuilder, *getBRIslandFactory());
639
640  if (stub == NULL)
641    return false;
642
643  assert(stub->symInfo() != NULL);
644  // increase the size of .symtab and .strtab
645  LDSection& symtab = getOutputFormat()->getSymTab();
646  LDSection& strtab = getOutputFormat()->getStrTab();
647  symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
648  strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
649
650  return true;
651}
652
653bool MipsGNULDBackend::doRelax(Module& pModule,
654                               IRBuilder& pBuilder,
655                               bool& pFinished) {
656  assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
657
658  bool isRelaxed = false;
659
660  for (Module::obj_iterator input = pModule.obj_begin();
661       input != pModule.obj_end();
662       ++input) {
663    LDContext* context = (*input)->context();
664
665    for (LDContext::sect_iterator rs = context->relocSectBegin();
666         rs != context->relocSectEnd();
667         ++rs) {
668      LDSection* sec = *rs;
669
670      if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
671        continue;
672
673      for (RelocData::iterator reloc = sec->getRelocData()->begin();
674           reloc != sec->getRelocData()->end();
675           ++reloc) {
676        if (llvm::ELF::R_MIPS_26 != reloc->type())
677          continue;
678
679        if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
680          isRelaxed = true;
681      }
682    }
683  }
684
685  SectionData* textData = getOutputFormat()->getText().getSectionData();
686
687  // find the first fragment w/ invalid offset due to stub insertion
688  Fragment* invalid = NULL;
689  pFinished = true;
690  for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
691                                     ie = getBRIslandFactory()->end();
692       ii != ie;
693       ++ii) {
694    BranchIsland& island = *ii;
695    if (island.end() == textData->end())
696      break;
697
698    Fragment* exit = island.end();
699    if ((island.offset() + island.size()) > exit->getOffset()) {
700      invalid = exit;
701      pFinished = false;
702      break;
703    }
704  }
705
706  // reset the offset of invalid fragments
707  while (invalid != NULL) {
708    invalid->setOffset(invalid->getPrevNode()->getOffset() +
709                       invalid->getPrevNode()->size());
710    invalid = invalid->getNextNode();
711  }
712
713  // reset the size of .text
714  if (isRelaxed)
715    getOutputFormat()->getText().setSize(textData->back().getOffset() +
716                                         textData->back().size());
717
718  return isRelaxed;
719}
720
721bool MipsGNULDBackend::initTargetStubs() {
722  if (getStubFactory() == NULL)
723    return false;
724
725  getStubFactory()->addPrototype(new MipsLA25Stub(*this));
726  return true;
727}
728
729bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
730                                      Relocation::Type& pType,
731                                      uint32_t& pSymIdx,
732                                      uint32_t& pOffset) const {
733  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
734}
735
736bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
737                                      Relocation::Type& pType,
738                                      uint32_t& pSymIdx,
739                                      uint32_t& pOffset,
740                                      int32_t& pAddend) const {
741  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
742}
743
744bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
745                                      Relocation::Type& pType,
746                                      uint32_t& pSymIdx,
747                                      uint64_t& pOffset) const {
748  uint64_t r_info = 0x0;
749  if (llvm::sys::IsLittleEndianHost) {
750    pOffset = pRel.r_offset;
751    r_info = pRel.r_info;
752  } else {
753    pOffset = mcld::bswap64(pRel.r_offset);
754    r_info = mcld::bswap64(pRel.r_info);
755  }
756
757  // MIPS 64 little endian (we do not support big endian now)
758  // has a "special" encoding of r_info relocation
759  // field. Instead of one 64 bit little endian number, it is a little
760  // endian 32 bit number followed by a 32 bit big endian number.
761  pType = mcld::bswap32(r_info >> 32);
762  pSymIdx = r_info & 0xffffffff;
763  return true;
764}
765
766bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
767                                      Relocation::Type& pType,
768                                      uint32_t& pSymIdx,
769                                      uint64_t& pOffset,
770                                      int64_t& pAddend) const {
771  uint64_t r_info = 0x0;
772  if (llvm::sys::IsLittleEndianHost) {
773    pOffset = pRel.r_offset;
774    r_info = pRel.r_info;
775    pAddend = pRel.r_addend;
776  } else {
777    pOffset = mcld::bswap64(pRel.r_offset);
778    r_info = mcld::bswap64(pRel.r_info);
779    pAddend = mcld::bswap64(pRel.r_addend);
780  }
781
782  pType = mcld::bswap32(r_info >> 32);
783  pSymIdx = r_info & 0xffffffff;
784  return true;
785}
786
787void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
788                                      Relocation::Type pType,
789                                      uint32_t pSymIdx,
790                                      uint32_t pOffset) const {
791  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
792}
793
794void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
795                                      Relocation::Type pType,
796                                      uint32_t pSymIdx,
797                                      uint32_t pOffset,
798                                      int32_t pAddend) const {
799  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
800}
801
802void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
803                                      Relocation::Type pType,
804                                      uint32_t pSymIdx,
805                                      uint64_t pOffset) const {
806  uint64_t r_info = mcld::bswap32(pType);
807  r_info <<= 32;
808  r_info |= pSymIdx;
809
810  pRel.r_info = r_info;
811  pRel.r_offset = pOffset;
812}
813
814void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
815                                      Relocation::Type pType,
816                                      uint32_t pSymIdx,
817                                      uint64_t pOffset,
818                                      int64_t pAddend) const {
819  uint64_t r_info = mcld::bswap32(pType);
820  r_info <<= 32;
821  r_info |= pSymIdx;
822
823  pRel.r_info = r_info;
824  pRel.r_offset = pOffset;
825  pRel.r_addend = pAddend;
826}
827
828//===----------------------------------------------------------------------===//
829// Mips32GNULDBackend
830//===----------------------------------------------------------------------===//
831Mips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
832                                       MipsGNUInfo* pInfo)
833    : MipsGNULDBackend(pConfig, pInfo) {
834}
835
836bool Mips32GNULDBackend::initRelocator() {
837  if (m_pRelocator == NULL)
838    m_pRelocator = new Mips32Relocator(*this, config());
839
840  return true;
841}
842
843void Mips32GNULDBackend::initTargetSections(Module& pModule,
844                                            ObjectBuilder& pBuilder) {
845  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
846
847  if (LinkerConfig::Object == config().codeGenType())
848    return;
849
850  ELFFileFormat* fileFormat = getOutputFormat();
851
852  // initialize .got
853  LDSection& got = fileFormat->getGOT();
854  m_pGOT = new Mips32GOT(got);
855
856  // initialize .got.plt
857  LDSection& gotplt = fileFormat->getGOTPLT();
858  m_pGOTPLT = new MipsGOTPLT(gotplt);
859
860  // initialize .plt
861  LDSection& plt = fileFormat->getPLT();
862  m_pPLT = new MipsPLT(plt);
863}
864
865size_t Mips32GNULDBackend::getRelEntrySize() {
866  return 8;
867}
868
869size_t Mips32GNULDBackend::getRelaEntrySize() {
870  return 12;
871}
872
873//===----------------------------------------------------------------------===//
874// Mips64GNULDBackend
875//===----------------------------------------------------------------------===//
876Mips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
877                                       MipsGNUInfo* pInfo)
878    : MipsGNULDBackend(pConfig, pInfo) {
879}
880
881bool Mips64GNULDBackend::initRelocator() {
882  if (m_pRelocator == NULL)
883    m_pRelocator = new Mips64Relocator(*this, config());
884
885  return true;
886}
887
888void Mips64GNULDBackend::initTargetSections(Module& pModule,
889                                            ObjectBuilder& pBuilder) {
890  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
891
892  if (LinkerConfig::Object == config().codeGenType())
893    return;
894
895  ELFFileFormat* fileFormat = getOutputFormat();
896
897  // initialize .got
898  LDSection& got = fileFormat->getGOT();
899  m_pGOT = new Mips64GOT(got);
900
901  // initialize .got.plt
902  LDSection& gotplt = fileFormat->getGOTPLT();
903  m_pGOTPLT = new MipsGOTPLT(gotplt);
904
905  // initialize .plt
906  LDSection& plt = fileFormat->getPLT();
907  m_pPLT = new MipsPLT(plt);
908}
909
910size_t Mips64GNULDBackend::getRelEntrySize() {
911  return 16;
912}
913
914size_t Mips64GNULDBackend::getRelaEntrySize() {
915  return 24;
916}
917
918//===----------------------------------------------------------------------===//
919/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
920///
921static TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig) {
922  const llvm::Triple& triple = pConfig.targets().triple();
923
924  if (triple.isOSDarwin()) {
925    assert(0 && "MachO linker is not supported yet");
926  }
927  if (triple.isOSWindows()) {
928    assert(0 && "COFF linker is not supported yet");
929  }
930
931  llvm::Triple::ArchType arch = triple.getArch();
932
933  if (llvm::Triple::mips64el == arch)
934    return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
935
936  assert(arch == llvm::Triple::mipsel);
937  return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
938}
939
940}  // namespace mcld
941
942//===----------------------------------------------------------------------===//
943// Force static initialization.
944//===----------------------------------------------------------------------===//
945extern "C" void MCLDInitializeMipsLDBackend() {
946  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
947                                                mcld::createMipsLDBackend);
948  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
949                                                mcld::createMipsLDBackend);
950}
951