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