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
10#include <llvm/ADT/Triple.h>
11#include <llvm/Support/ELF.h>
12
13#include <mcld/LD/SectionMap.h>
14#include <mcld/MC/MCLDInfo.h>
15#include <mcld/MC/MCLinker.h>
16#include <mcld/Support/MemoryRegion.h>
17#include <mcld/Support/TargetRegistry.h>
18#include <mcld/Target/OutputRelocSection.h>
19
20#include "Mips.h"
21#include "MipsELFDynamic.h"
22#include "MipsLDBackend.h"
23#include "MipsRelocationFactory.h"
24
25enum {
26  // The original o32 abi.
27  E_MIPS_ABI_O32    = 0x00001000,
28  // O32 extended to work on 64 bit architectures.
29  E_MIPS_ABI_O64    = 0x00002000,
30  // EABI in 32 bit mode.
31  E_MIPS_ABI_EABI32 = 0x00003000,
32  // EABI in 64 bit mode.
33  E_MIPS_ABI_EABI64 = 0x00004000
34};
35
36namespace mcld {
37
38MipsGNULDBackend::MipsGNULDBackend()
39  : m_pRelocFactory(NULL),
40    m_pGOT(NULL),
41    m_pRelDyn(NULL),
42    m_pDynamic(NULL),
43    m_pGOTSymbol(NULL),
44    m_pGpDispSymbol(NULL)
45{
46}
47
48MipsGNULDBackend::~MipsGNULDBackend()
49{
50  if (NULL != m_pRelocFactory)
51    delete m_pRelocFactory;
52  if (NULL != m_pGOT)
53    delete m_pGOT;
54  if (NULL != m_pRelDyn)
55    delete m_pRelDyn;
56  if (NULL != m_pDynamic)
57    delete m_pDynamic;
58}
59
60bool MipsGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
61{
62  // Nothing to do because we do not support
63  // any MIPS specific sections now.
64  return true;
65}
66
67void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
68{
69  // Nothing to do because we do not support
70  // any MIPS specific sections now.
71}
72
73void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker)
74{
75  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
76  // same name in input
77  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
78                   "_GLOBAL_OFFSET_TABLE_",
79                   false,
80                   ResolveInfo::Object,
81                   ResolveInfo::Define,
82                   ResolveInfo::Local,
83                   0x0,  // size
84                   0x0,  // value
85                   NULL, // FragRef
86                   ResolveInfo::Hidden);
87
88  m_pGpDispSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
89                   "_gp_disp",
90                   false,
91                   ResolveInfo::Section,
92                   ResolveInfo::Define,
93                   ResolveInfo::Absolute,
94                   0x0,  // size
95                   0x0,  // value
96                   NULL, // FragRef
97                   ResolveInfo::Default);
98
99  if (NULL != m_pGpDispSymbol) {
100    m_pGpDispSymbol->resolveInfo()->setReserved(ReserveGpDisp);
101  }
102}
103
104bool MipsGNULDBackend::initRelocFactory(const MCLinker& pLinker)
105{
106  if (NULL == m_pRelocFactory) {
107    m_pRelocFactory = new MipsRelocationFactory(1024, *this);
108    m_pRelocFactory->setLayout(pLinker.getLayout());
109  }
110  return true;
111}
112
113RelocationFactory* MipsGNULDBackend::getRelocFactory()
114{
115  assert(NULL != m_pRelocFactory);
116  return m_pRelocFactory;
117}
118
119void MipsGNULDBackend::scanRelocation(Relocation& pReloc,
120                                      const LDSymbol& pInputSym,
121                                      MCLinker& pLinker,
122                                      const MCLDInfo& pLDInfo,
123                                      const Output& pOutput)
124{
125  // rsym - The relocation target symbol
126  ResolveInfo* rsym = pReloc.symInfo();
127  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
128
129  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies
130  // that a .got section is needed.
131  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
132    if (rsym == m_pGOTSymbol->resolveInfo()) {
133      createGOT(pLinker, pOutput);
134    }
135  }
136
137  if (rsym->isLocal())
138    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
139  else
140    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
141}
142
143uint32_t MipsGNULDBackend::machine() const
144{
145  return llvm::ELF::EM_MIPS;
146}
147
148uint8_t MipsGNULDBackend::OSABI() const
149{
150  return llvm::ELF::ELFOSABI_NONE;
151}
152
153uint8_t MipsGNULDBackend::ABIVersion() const
154{
155  return 0;
156}
157
158uint64_t MipsGNULDBackend::flags() const
159{
160  // TODO: (simon) The correct flag's set depend on command line
161  // arguments and flags from input .o files.
162  return llvm::ELF::EF_MIPS_ARCH_32R2 |
163         llvm::ELF::EF_MIPS_NOREORDER |
164         llvm::ELF::EF_MIPS_PIC |
165         llvm::ELF::EF_MIPS_CPIC |
166         E_MIPS_ABI_O32;
167}
168
169bool MipsGNULDBackend::isLittleEndian() const
170{
171  // Now we support little endian (mipsel) target only.
172  return true;
173}
174
175unsigned int MipsGNULDBackend::bitclass() const
176{
177  return 32;
178}
179
180void MipsGNULDBackend::doPreLayout(const Output& pOutput,
181                                   const MCLDInfo& pInfo,
182                                   MCLinker& pLinker)
183{
184  // when building shared object, the .got section is must.
185  if (pOutput.type() == Output::DynObj && NULL == m_pGOT) {
186      createGOT(pLinker, pOutput);
187  }
188}
189
190void MipsGNULDBackend::doPostLayout(const Output& pOutput,
191                                    const MCLDInfo& pInfo,
192                                    MCLinker& pLinker)
193{
194  // emit program headers
195  if (pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
196    emitProgramHdrs(pLinker.getLDInfo().output());
197}
198
199/// dynamic - the dynamic section of the target machine.
200/// Use co-variant return type to return its own dynamic section.
201MipsELFDynamic& MipsGNULDBackend::dynamic()
202{
203  if (NULL == m_pDynamic)
204    m_pDynamic = new MipsELFDynamic(*this);
205
206  return *m_pDynamic;
207}
208
209/// dynamic - the dynamic section of the target machine.
210/// Use co-variant return type to return its own dynamic section.
211const MipsELFDynamic& MipsGNULDBackend::dynamic() const
212{
213  assert( NULL != m_pDynamic);
214  return *m_pDynamic;
215}
216
217uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
218                                           const LDSection& pSection,
219                                           const MCLDInfo& pInfo,
220                                           MemoryRegion& pRegion) const
221{
222  assert(pRegion.size() && "Size of MemoryRegion is zero!");
223
224  ELFFileFormat* file_format = getOutputFormat(pOutput);
225
226  if (&pSection == &(file_format->getGOT())) {
227    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
228    uint64_t result = m_pGOT->emit(pRegion);
229    return result;
230  }
231
232  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
233                           pSection.name() +
234                           llvm::Twine("'.\n"));
235  return 0;
236}
237/// isGOTSymbol - return true if the symbol is the GOT entry.
238bool MipsGNULDBackend::isGOTSymbol(const LDSymbol& pSymbol) const
239{
240  return std::find(m_LocalGOTSyms.begin(),
241                   m_LocalGOTSyms.end(), &pSymbol) != m_LocalGOTSyms.end() ||
242         std::find(m_GlobalGOTSyms.begin(),
243                   m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
244}
245
246/// emitDynamicSymbol - emit dynamic symbol.
247void MipsGNULDBackend::emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
248                                         Output& pOutput,
249                                         LDSymbol& pSymbol,
250                                         const Layout& pLayout,
251                                         char* strtab,
252                                         size_t strtabsize,
253                                         size_t symtabIdx)
254{
255  // maintain output's symbol and index map
256  bool sym_exist = false;
257  HashTableType::entry_type* entry = 0;
258  entry = m_pSymIndexMap->insert(&pSymbol, sym_exist);
259  entry->setValue(symtabIdx);
260
261  // FIXME: check the endian between host and target
262  // write out symbol
263  sym32.st_name  = strtabsize;
264  sym32.st_value = pSymbol.value();
265  sym32.st_size  = getSymbolSize(pSymbol);
266  sym32.st_info  = getSymbolInfo(pSymbol);
267  sym32.st_other = pSymbol.visibility();
268  sym32.st_shndx = getSymbolShndx(pSymbol, pLayout);
269  // write out string
270  strcpy((strtab + strtabsize), pSymbol.name());
271}
272
273/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
274///
275/// the size of these tables should be computed before layout
276/// layout should computes the start offset of these tables
277void MipsGNULDBackend::emitDynNamePools(Output& pOutput,
278                                        SymbolCategory& pSymbols,
279                                        const Layout& pLayout,
280                                        const MCLDInfo& pLDInfo)
281{
282  assert(pOutput.hasMemArea());
283  ELFFileFormat* file_format = getOutputFormat(pOutput);
284
285  LDSection& symtab_sect = file_format->getDynSymTab();
286  LDSection& strtab_sect = file_format->getDynStrTab();
287  LDSection& hash_sect   = file_format->getHashTab();
288  LDSection& dyn_sect    = file_format->getDynamic();
289
290  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
291                                                           symtab_sect.size());
292  MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
293                                                           strtab_sect.size());
294  MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
295                                                         hash_sect.size());
296  MemoryRegion* dyn_region = pOutput.memArea()->request(dyn_sect.offset(),
297                                                        dyn_sect.size());
298  // set up symtab_region
299  llvm::ELF::Elf32_Sym* symtab32 = NULL;
300  symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
301
302  symtab32[0].st_name  = 0;
303  symtab32[0].st_value = 0;
304  symtab32[0].st_size  = 0;
305  symtab32[0].st_info  = 0;
306  symtab32[0].st_other = 0;
307  symtab32[0].st_shndx = 0;
308
309  // set up strtab_region
310  char* strtab = (char*)strtab_region->start();
311  strtab[0] = '\0';
312
313  bool sym_exist = false;
314  HashTableType::entry_type* entry = 0;
315
316  // add index 0 symbol into SymIndexMap
317  entry = m_pSymIndexMap->insert(NULL, sym_exist);
318  entry->setValue(0);
319
320  size_t symtabIdx = 1;
321  size_t strtabsize = 1;
322
323  // emit of .dynsym, and .dynstr except GOT entries
324  for (SymbolCategory::iterator symbol = pSymbols.begin(),
325       sym_end = pSymbols.end(); symbol != sym_end; ++symbol) {
326    if (!isDynamicSymbol(**symbol, pOutput))
327      continue;
328
329    if (isGOTSymbol(**symbol))
330      continue;
331
332    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
333                      strtabsize, symtabIdx);
334
335    // sum up counters
336    ++symtabIdx;
337    strtabsize += (*symbol)->nameSize() + 1;
338  }
339
340  // emit global GOT
341  for (std::vector<LDSymbol*>::const_iterator symbol = m_GlobalGOTSyms.begin(),
342       symbol_end = m_GlobalGOTSyms.end();
343       symbol != symbol_end; ++symbol) {
344
345    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
346                      strtabsize, symtabIdx);
347
348    // sum up counters
349    ++symtabIdx;
350    strtabsize += (*symbol)->nameSize() + 1;
351  }
352
353  // emit DT_NEED
354  // add DT_NEED strings into .dynstr
355  // Rules:
356  //   1. ignore --no-add-needed
357  //   2. force count in --no-as-needed
358  //   3. judge --as-needed
359  ELFDynamic::iterator dt_need = dynamic().needBegin();
360  InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
361  for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
362    if (Input::DynObj == (*input)->type()) {
363      // --add-needed
364      if ((*input)->attribute()->isAddNeeded()) {
365        // --no-as-needed
366        if (!(*input)->attribute()->isAsNeeded()) {
367          strcpy((strtab + strtabsize), (*input)->name().c_str());
368          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
369          strtabsize += (*input)->name().size() + 1;
370          ++dt_need;
371        }
372        // --as-needed
373        else if ((*input)->isNeeded()) {
374          strcpy((strtab + strtabsize), (*input)->name().c_str());
375          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
376          strtabsize += (*input)->name().size() + 1;
377          ++dt_need;
378        }
379      }
380    }
381  } // for
382
383  // emit soname
384  // initialize value of ELF .dynamic section
385  dynamic().applySoname(strtabsize);
386  dynamic().applyEntries(pLDInfo, *file_format);
387  dynamic().emit(dyn_sect, *dyn_region);
388
389  strcpy((strtab + strtabsize), pOutput.name().c_str());
390  strtabsize += pOutput.name().size() + 1;
391
392  // emit hash table
393  // FIXME: this verion only emit SVR4 hash section.
394  //        Please add GNU new hash section
395
396  // both 32 and 64 bits hash table use 32-bit entry
397  // set up hash_region
398  uint32_t* word_array = (uint32_t*)hash_region->start();
399  uint32_t& nbucket = word_array[0];
400  uint32_t& nchain  = word_array[1];
401
402  nbucket = getHashBucketCount(symtabIdx, false);
403  nchain  = symtabIdx;
404
405  uint32_t* bucket = (word_array + 2);
406  uint32_t* chain  = (bucket + nbucket);
407
408  // initialize bucket
409  bzero((void*)bucket, nbucket);
410
411  StringHash<ELF> hash_func;
412
413  for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
414    llvm::StringRef name(strtab + symtab32[sym_idx].st_name);
415    size_t bucket_pos = hash_func(name) % nbucket;
416    chain[sym_idx] = bucket[bucket_pos];
417    bucket[bucket_pos] = sym_idx;
418  }
419
420}
421
422MipsGOT& MipsGNULDBackend::getGOT()
423{
424  assert(NULL != m_pGOT);
425  return *m_pGOT;
426}
427
428const MipsGOT& MipsGNULDBackend::getGOT() const
429{
430  assert(NULL != m_pGOT);
431  return *m_pGOT;
432}
433
434OutputRelocSection& MipsGNULDBackend::getRelDyn()
435{
436  assert(NULL != m_pRelDyn);
437  return *m_pRelDyn;
438}
439
440const OutputRelocSection& MipsGNULDBackend::getRelDyn() const
441{
442  assert(NULL != m_pRelDyn);
443  return *m_pRelDyn;
444}
445
446unsigned int
447MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
448                                        const LDSection& pSectHdr) const
449{
450  ELFFileFormat* file_format = getOutputFormat(pOutput);
451
452  if (&pSectHdr == &file_format->getGOT())
453    return SHO_DATA;
454
455  return SHO_UNDEFINED;
456}
457
458/// finalizeSymbol - finalize the symbol value
459/// If the symbol's reserved field is not zero, MCLinker will call back this
460/// function to ask the final value of the symbol
461bool MipsGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
462{
463  if (&pSymbol == m_pGpDispSymbol) {
464    m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
465    return true;
466  }
467  return false;
468}
469
470/// allocateCommonSymbols - allocate common symbols in the corresponding
471/// sections.
472/// @refer Google gold linker: common.cc: 214
473/// FIXME: Mips needs to allocate small common symbol
474bool
475MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
476{
477  // SymbolCategory contains all symbols that must emit to the output files.
478  // We are not like Google gold linker, we don't remember symbols before symbol
479  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
480  // don't need to care about some symbols may be changed its category due to symbol
481  // resolution.
482  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
483
484  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
485    return true;
486
487  // addralign := max value of all common symbols
488  uint64_t addralign = 0x0;
489
490  // Due to the visibility, some common symbols may be forcefully local.
491  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
492  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
493    if (ResolveInfo::Common == (*com_sym)->desc()) {
494      if ((*com_sym)->value() > addralign)
495        addralign = (*com_sym)->value();
496    }
497  }
498
499  // global common symbols.
500  com_end = symbol_list.commonEnd();
501  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
502    if ((*com_sym)->value() > addralign)
503      addralign = (*com_sym)->value();
504  }
505
506  // FIXME: If the order of common symbols is defined, then sort common symbols
507  // com_sym = symbol_list.commonBegin();
508  // std::sort(com_sym, com_end, some kind of order);
509
510  // get or create corresponding BSS LDSection
511  LDSection* bss_sect_hdr = NULL;
512  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
513    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
514                                   ".tbss",
515                                   LDFileFormat::BSS,
516                                   llvm::ELF::SHT_NOBITS,
517                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
518  }
519  else {
520    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
521                                   LDFileFormat::BSS,
522                                   llvm::ELF::SHT_NOBITS,
523                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
524  }
525
526  // get or create corresponding BSS MCSectionData
527  assert(NULL != bss_sect_hdr);
528  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
529
530  // allocate all common symbols
531  uint64_t offset = bss_sect_hdr->size();
532
533  // allocate all local common symbols
534  com_end = symbol_list.localEnd();
535  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
536    if (ResolveInfo::Common == (*com_sym)->desc()) {
537      alignAddress(offset, (*com_sym)->value());
538      // We have to reset the description of the symbol here. When doing
539      // incremental linking, the output relocatable object may have common
540      // symbols. Therefore, we can not treat common symbols as normal symbols
541      // when emitting the regular name pools. We must change the symbols'
542      // description here.
543      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
544      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
545      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
546      offset += (*com_sym)->size();
547    }
548  }
549
550  // allocate all global common symbols
551  com_end = symbol_list.commonEnd();
552  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
553    alignAddress(offset, (*com_sym)->value());
554
555    // We have to reset the description of the symbol here. When doing
556    // incremental linking, the output relocatable object may have common
557    // symbols. Therefore, we can not treat common symbols as normal symbols
558    // when emitting the regular name pools. We must change the symbols'
559    // description here.
560    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
561    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
562    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
563    offset += (*com_sym)->size();
564  }
565
566  bss_sect_hdr->setSize(offset);
567  symbol_list.changeCommonsToGlobal();
568  return true;
569}
570
571void MipsGNULDBackend::updateAddend(Relocation& pReloc,
572                                   const LDSymbol& pInputSym,
573                                   const Layout& pLayout) const
574{
575  // Update value keep in addend if we meet a section symbol
576  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
577    pReloc.setAddend(pLayout.getOutputOffset(
578                     *pInputSym.fragRef()) + pReloc.addend());
579  }
580}
581
582void MipsGNULDBackend::scanLocalReloc(Relocation& pReloc,
583                                      const LDSymbol& pInputSym,
584                                      MCLinker& pLinker,
585                                      const MCLDInfo& pLDInfo,
586                                      const Output& pOutput)
587{
588  ResolveInfo* rsym = pReloc.symInfo();
589
590  updateAddend(pReloc, pInputSym, pLinker.getLayout());
591
592  switch (pReloc.type()){
593    case llvm::ELF::R_MIPS_NONE:
594    case llvm::ELF::R_MIPS_16:
595      break;
596    case llvm::ELF::R_MIPS_32:
597      if (Output::DynObj == pOutput.type()) {
598        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
599        // section if the symbol section flags contains SHF_EXECINSTR.
600        // 1. Find the reason of this condition.
601        // 2. Check this condition here.
602        if (NULL == m_pRelDyn)
603          createRelDyn(pLinker, pOutput);
604
605        m_pRelDyn->reserveEntry(*m_pRelocFactory);
606        rsym->setReserved(rsym->reserved() | ReserveRel);
607      }
608      break;
609    case llvm::ELF::R_MIPS_REL32:
610    case llvm::ELF::R_MIPS_26:
611    case llvm::ELF::R_MIPS_HI16:
612    case llvm::ELF::R_MIPS_LO16:
613    case llvm::ELF::R_MIPS_PC16:
614    case llvm::ELF::R_MIPS_SHIFT5:
615    case llvm::ELF::R_MIPS_SHIFT6:
616    case llvm::ELF::R_MIPS_64:
617    case llvm::ELF::R_MIPS_GOT_PAGE:
618    case llvm::ELF::R_MIPS_GOT_OFST:
619    case llvm::ELF::R_MIPS_SUB:
620    case llvm::ELF::R_MIPS_INSERT_A:
621    case llvm::ELF::R_MIPS_INSERT_B:
622    case llvm::ELF::R_MIPS_DELETE:
623    case llvm::ELF::R_MIPS_HIGHER:
624    case llvm::ELF::R_MIPS_HIGHEST:
625    case llvm::ELF::R_MIPS_SCN_DISP:
626    case llvm::ELF::R_MIPS_REL16:
627    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
628    case llvm::ELF::R_MIPS_PJUMP:
629    case llvm::ELF::R_MIPS_RELGOT:
630    case llvm::ELF::R_MIPS_JALR:
631    case llvm::ELF::R_MIPS_GLOB_DAT:
632    case llvm::ELF::R_MIPS_COPY:
633    case llvm::ELF::R_MIPS_JUMP_SLOT:
634      break;
635    case llvm::ELF::R_MIPS_GOT16:
636    case llvm::ELF::R_MIPS_CALL16:
637      if (NULL == m_pGOT)
638        createGOT(pLinker, pOutput);
639
640      if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
641        m_pGOT->reserveLocalEntry();
642        rsym->setReserved(rsym->reserved() | ReserveGot);
643        m_LocalGOTSyms.push_back(rsym->outSymbol());
644      }
645      break;
646    case llvm::ELF::R_MIPS_GPREL32:
647    case llvm::ELF::R_MIPS_GPREL16:
648    case llvm::ELF::R_MIPS_LITERAL:
649      break;
650    case llvm::ELF::R_MIPS_GOT_DISP:
651    case llvm::ELF::R_MIPS_GOT_HI16:
652    case llvm::ELF::R_MIPS_CALL_HI16:
653    case llvm::ELF::R_MIPS_GOT_LO16:
654    case llvm::ELF::R_MIPS_CALL_LO16:
655      break;
656    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
657    case llvm::ELF::R_MIPS_TLS_DTPREL32:
658    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
659    case llvm::ELF::R_MIPS_TLS_DTPREL64:
660    case llvm::ELF::R_MIPS_TLS_GD:
661    case llvm::ELF::R_MIPS_TLS_LDM:
662    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
663    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
664    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
665    case llvm::ELF::R_MIPS_TLS_TPREL32:
666    case llvm::ELF::R_MIPS_TLS_TPREL64:
667    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
668    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
669      break;
670    default:
671      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
672                               llvm::Twine(pReloc.type()) +
673                               llvm::Twine("for the local symbol `") +
674                               pReloc.symInfo()->name() +
675                               llvm::Twine("'."));
676  }
677}
678
679void MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc,
680                                       const LDSymbol& pInputSym,
681                                       MCLinker& pLinker,
682                                       const MCLDInfo& pLDInfo,
683                                       const Output& pOutput)
684{
685  ResolveInfo* rsym = pReloc.symInfo();
686
687  switch (pReloc.type()){
688    case llvm::ELF::R_MIPS_NONE:
689    case llvm::ELF::R_MIPS_INSERT_A:
690    case llvm::ELF::R_MIPS_INSERT_B:
691    case llvm::ELF::R_MIPS_DELETE:
692    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
693    case llvm::ELF::R_MIPS_TLS_DTPREL64:
694    case llvm::ELF::R_MIPS_REL16:
695    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
696    case llvm::ELF::R_MIPS_PJUMP:
697    case llvm::ELF::R_MIPS_RELGOT:
698    case llvm::ELF::R_MIPS_TLS_TPREL64:
699      break;
700    case llvm::ELF::R_MIPS_32:
701    case llvm::ELF::R_MIPS_64:
702    case llvm::ELF::R_MIPS_HI16:
703    case llvm::ELF::R_MIPS_LO16:
704      if (isSymbolNeedsDynRel(*rsym, pOutput)) {
705        if (NULL == m_pRelDyn)
706          createRelDyn(pLinker, pOutput);
707
708        m_pRelDyn->reserveEntry(*m_pRelocFactory);
709        rsym->setReserved(rsym->reserved() | ReserveRel);
710      }
711      break;
712    case llvm::ELF::R_MIPS_GOT16:
713    case llvm::ELF::R_MIPS_CALL16:
714    case llvm::ELF::R_MIPS_GOT_DISP:
715    case llvm::ELF::R_MIPS_GOT_HI16:
716    case llvm::ELF::R_MIPS_CALL_HI16:
717    case llvm::ELF::R_MIPS_GOT_LO16:
718    case llvm::ELF::R_MIPS_CALL_LO16:
719    case llvm::ELF::R_MIPS_GOT_PAGE:
720    case llvm::ELF::R_MIPS_GOT_OFST:
721      if (NULL == m_pGOT)
722        createGOT(pLinker, pOutput);
723
724      if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
725        m_pGOT->reserveGlobalEntry();
726        rsym->setReserved(rsym->reserved() | ReserveGot);
727        m_GlobalGOTSyms.push_back(rsym->outSymbol());
728      }
729      break;
730    case llvm::ELF::R_MIPS_LITERAL:
731    case llvm::ELF::R_MIPS_GPREL32:
732      llvm::report_fatal_error(llvm::Twine("Relocation ") +
733                               llvm::Twine(pReloc.type()) +
734                               llvm::Twine(" is not defined for the "
735                                           "global symbol `") +
736                               pReloc.symInfo()->name() +
737                               llvm::Twine("'."));
738      break;
739    case llvm::ELF::R_MIPS_GPREL16:
740      break;
741    case llvm::ELF::R_MIPS_26:
742    case llvm::ELF::R_MIPS_PC16:
743      break;
744    case llvm::ELF::R_MIPS_16:
745    case llvm::ELF::R_MIPS_SHIFT5:
746    case llvm::ELF::R_MIPS_SHIFT6:
747    case llvm::ELF::R_MIPS_SUB:
748    case llvm::ELF::R_MIPS_HIGHER:
749    case llvm::ELF::R_MIPS_HIGHEST:
750    case llvm::ELF::R_MIPS_SCN_DISP:
751      break;
752    case llvm::ELF::R_MIPS_TLS_DTPREL32:
753    case llvm::ELF::R_MIPS_TLS_GD:
754    case llvm::ELF::R_MIPS_TLS_LDM:
755    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
756    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
757    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
758    case llvm::ELF::R_MIPS_TLS_TPREL32:
759    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
760    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
761      break;
762    case llvm::ELF::R_MIPS_REL32:
763      break;
764    case llvm::ELF::R_MIPS_JALR:
765      break;
766    case llvm::ELF::R_MIPS_COPY:
767    case llvm::ELF::R_MIPS_GLOB_DAT:
768    case llvm::ELF::R_MIPS_JUMP_SLOT:
769      llvm::report_fatal_error(llvm::Twine("Relocation ") +
770                               llvm::Twine(pReloc.type()) +
771                               llvm::Twine("for the global symbol `") +
772                               pReloc.symInfo()->name() +
773                               llvm::Twine("' should only be seen "
774                                           "by the dynamic linker"));
775      break;
776    default:
777      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
778                               llvm::Twine(pReloc.type()) +
779                               llvm::Twine("for the global symbol `") +
780                               pReloc.symInfo()->name() +
781                               llvm::Twine("'."));
782  }
783}
784
785bool MipsGNULDBackend::isSymbolNeedsPLT(ResolveInfo& pSym,
786                                        const Output& pOutput) const
787{
788  return (Output::DynObj == pOutput.type() &&
789         ResolveInfo::Function == pSym.type() &&
790         (pSym.isDyn() || pSym.isUndef()));
791}
792
793bool MipsGNULDBackend::isSymbolNeedsDynRel(ResolveInfo& pSym,
794                                           const Output& pOutput) const
795{
796  if(pSym.isUndef() && Output::Exec == pOutput.type())
797    return false;
798  if(pSym.isAbsolute())
799    return false;
800  if(Output::DynObj == pOutput.type())
801    return true;
802  if(pSym.isDyn() || pSym.isUndef())
803    return true;
804
805  return false;
806}
807
808void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
809{
810  ELFFileFormat* file_format = getOutputFormat(pOutput);
811
812  LDSection& got = file_format->getGOT();
813  m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
814
815  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
816  if( m_pGOTSymbol != NULL ) {
817    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
818                     "_GLOBAL_OFFSET_TABLE_",
819                     false,
820                     ResolveInfo::Object,
821                     ResolveInfo::Define,
822                     ResolveInfo::Local,
823                     0x0, // size
824                     0x0, // value
825                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
826                     ResolveInfo::Hidden);
827  }
828  else {
829    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
830                     "_GLOBAL_OFFSET_TABLE_",
831                     false,
832                     ResolveInfo::Object,
833                     ResolveInfo::Define,
834                     ResolveInfo::Local,
835                     0x0, // size
836                     0x0, // value
837                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
838                     ResolveInfo::Hidden);
839  }
840}
841
842void MipsGNULDBackend::createRelDyn(MCLinker& pLinker, const Output& pOutput)
843{
844  ELFFileFormat* file_format = getOutputFormat(pOutput);
845
846  // get .rel.dyn LDSection and create MCSectionData
847  LDSection& reldyn = file_format->getRelDyn();
848  // create MCSectionData and ARMRelDynSection
849  m_pRelDyn = new OutputRelocSection(reldyn,
850                                     pLinker.getOrCreateSectData(reldyn),
851                                     8);
852}
853
854ELFFileFormat* MipsGNULDBackend::getOutputFormat(const Output& pOutput) const
855{
856  switch (pOutput.type()) {
857    case Output::DynObj:
858      return getDynObjFileFormat();
859    case Output::Exec:
860      return getExecFileFormat();
861    case Output::Object:
862      return NULL;
863    default:
864      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
865                               llvm::Twine(pOutput.type()));
866      return NULL;
867  }
868}
869
870//===----------------------------------------------------------------------===//
871/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
872///
873static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
874                                            const std::string& pTriple)
875{
876  llvm::Triple theTriple(pTriple);
877  if (theTriple.isOSDarwin()) {
878    assert(0 && "MachO linker is not supported yet");
879  }
880  if (theTriple.isOSWindows()) {
881    assert(0 && "COFF linker is not supported yet");
882  }
883  return new MipsGNULDBackend();
884}
885
886} // namespace of mcld
887
888//=============================
889// Force static initialization.
890extern "C" void LLVMInitializeMipsLDBackend() {
891  // Register the linker backend
892  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
893                                                mcld::createMipsLDBackend);
894}
895