MipsRelocator.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- MipsRelocator.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 "MipsRelocator.h"
10#include "MipsRelocationFunctions.h"
11
12#include <mcld/IRBuilder.h>
13#include <mcld/LinkerConfig.h>
14#include <mcld/Object/ObjectBuilder.h>
15#include <mcld/Support/MsgHandling.h>
16#include <mcld/Target/OutputRelocSection.h>
17#include <mcld/LD/ELFFileFormat.h>
18
19#include <llvm/ADT/Twine.h>
20#include <llvm/Support/ELF.h>
21
22namespace llvm {
23namespace ELF {
24
25// FIXME: Consider upstream these relocation types to LLVM.
26enum {
27  R_MIPS_LA25_LUI = 200,
28  R_MIPS_LA25_J   = 201,
29  R_MIPS_LA25_ADD = 202,
30  R_MIPS_PC32     = 248,
31};
32
33} // end namespace ELF
34} // end namespace llvm
35
36using namespace mcld;
37
38//===----------------------------------------------------------------------===//
39// MipsRelocationInfo
40//===----------------------------------------------------------------------===//
41class mcld::MipsRelocationInfo
42{
43public:
44  static bool HasSubType(const Relocation& pParent, Relocation::Type pType)
45  {
46    if (llvm::ELF::R_MIPS_NONE == pType)
47      return true;
48
49    for (Relocation::Type type = pParent.type();
50         llvm::ELF::R_MIPS_NONE != (type & 0xff); type >>= 8) {
51      if ((type & 0xff) == pType)
52        return true;
53    }
54
55    return false;
56  }
57
58  MipsRelocationInfo(Relocation& pParent, bool pIsRel)
59    : m_Parent(&pParent),
60      m_Type(pParent.type()),
61      m_Addend(0),
62      m_Symbol(pParent.symValue()),
63      m_Result(pParent.target())
64  {
65    if (pIsRel && (type() < llvm::ELF::R_MIPS_LA25_LUI ||
66                   type() > llvm::ELF::R_MIPS_LA25_ADD))
67      m_Addend = pParent.target();
68    else
69      m_Addend = pParent.addend();
70  }
71
72  bool isNone() const
73  {
74    return llvm::ELF::R_MIPS_NONE == type();
75  }
76
77  bool isLast() const
78  {
79    return llvm::ELF::R_MIPS_NONE == (m_Type >> 8);
80  }
81
82  MipsRelocationInfo next() const
83  {
84    return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result(), 0);
85  }
86
87  const Relocation& parent() const
88  {
89    return *m_Parent;
90  }
91
92  Relocation& parent()
93  {
94    return *m_Parent;
95  }
96
97  Relocation::Type type() const
98  {
99    return m_Type & 0xff;
100  }
101
102  Relocation::DWord A() const
103  {
104    return m_Addend;
105  }
106
107  Relocation::DWord S() const
108  {
109    return m_Symbol;
110  }
111
112  Relocation::DWord P() const
113  {
114    return parent().place();
115  }
116
117  Relocation::DWord result() const
118  {
119    return m_Result;
120  }
121
122  Relocation::DWord& result()
123  {
124    return m_Result;
125  }
126
127private:
128  Relocation* m_Parent;
129  Relocation::Type m_Type;
130  Relocation::DWord m_Addend;
131  Relocation::DWord m_Symbol;
132  Relocation::DWord m_Result;
133
134  MipsRelocationInfo(Relocation& pParent, Relocation::Type pType,
135                     Relocation::DWord pResult,
136                     Relocation::DWord pAddend, Relocation::DWord pSymbol)
137    : m_Parent(&pParent),
138      m_Type(pType),
139      m_Addend(pAddend),
140      m_Symbol(pSymbol),
141      m_Result(pResult)
142  {}
143
144  bool isFirst() const {
145    return m_Type == parent().type();
146  }
147};
148
149//===----------------------------------------------------------------------===//
150// Relocation Functions and Tables
151//===----------------------------------------------------------------------===//
152DECL_MIPS_APPLY_RELOC_FUNCS
153
154/// the prototype of applying function
155typedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&,
156                                               MipsRelocator& pParent);
157
158
159// the table entry of applying functions
160struct ApplyFunctionTriple
161{
162  ApplyFunctionType func;
163  unsigned int type;
164  const char* name;
165  unsigned int size;
166};
167
168// declare the table of applying functions
169static const ApplyFunctionTriple ApplyFunctions[] = {
170  DECL_MIPS_APPLY_RELOC_FUNC_PTRS
171};
172
173//===----------------------------------------------------------------------===//
174// MipsRelocator
175//===----------------------------------------------------------------------===//
176MipsRelocator::MipsRelocator(MipsGNULDBackend& pParent,
177                             const LinkerConfig& pConfig)
178  : Relocator(pConfig),
179    m_Target(pParent),
180    m_pApplyingInput(NULL),
181    m_CurrentLo16Reloc(NULL)
182{
183}
184
185Relocator::Result
186MipsRelocator::applyRelocation(Relocation& pReloc)
187{
188  // If m_CurrentLo16Reloc is not NULL we are processing
189  // postponed relocation. Otherwise check relocation type
190  // and postpone it for later handling.
191  if (NULL == m_CurrentLo16Reloc && isPostponed(pReloc)) {
192    postponeRelocation(pReloc);
193    return OK;
194  }
195
196  for (MipsRelocationInfo info(pReloc, isRel());
197       !info.isNone(); info = info.next()) {
198    if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0]))
199      return Unknown;
200
201    const ApplyFunctionTriple & triple = ApplyFunctions[info.type()];
202
203    Result res = triple.func(info, *this);
204    if (OK != res)
205      return res;
206
207    if (info.isLast()) {
208      uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size);
209      pReloc.target() &= ~mask;
210      pReloc.target() |= info.result() & mask;
211    }
212  }
213
214  return OK;
215}
216
217const char* MipsRelocator::getName(Relocation::Type pType) const
218{
219  return ApplyFunctions[pType & 0xff].name;
220}
221
222Relocator::Size MipsRelocator::getSize(Relocation::Type pType) const
223{
224  return ApplyFunctions[pType & 0xff].size;
225}
226
227void MipsRelocator::scanRelocation(Relocation& pReloc,
228                                   IRBuilder& pBuilder,
229                                   Module& pModule,
230                                   LDSection& pSection,
231                                   Input& pInput)
232{
233  // rsym - The relocation target symbol
234  ResolveInfo* rsym = pReloc.symInfo();
235  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
236
237  // Skip relocation against _gp_disp
238  if (NULL != getTarget().getGpDispSymbol() &&
239      rsym == getTarget().getGpDispSymbol()->resolveInfo())
240    return;
241
242  assert(NULL != pSection.getLink());
243  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
244    return;
245
246  for (MipsRelocationInfo info(pReloc, isRel());
247       !info.isNone(); info = info.next()) {
248    // We test isLocal or if pInputSym is not a dynamic symbol
249    // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
250    // Don't put undef symbols into local entries.
251    if (isLocalReloc(*rsym))
252      scanLocalReloc(info, pBuilder, pSection);
253    else
254      scanGlobalReloc(info, pBuilder, pSection);
255
256    if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo()))
257      getTarget().addNonPICBranchSym(pReloc.symInfo());
258  }
259
260  // Check if we should issue undefined reference
261  // for the relocation target symbol.
262  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
263    issueUndefRef(pReloc, pSection, pInput);
264}
265
266bool MipsRelocator::initializeScan(Input& pInput)
267{
268  if (LinkerConfig::Object != config().codeGenType())
269    getTarget().getGOT().initializeScan(pInput);
270  return true;
271}
272
273bool MipsRelocator::finalizeScan(Input& pInput)
274{
275  if (LinkerConfig::Object != config().codeGenType())
276    getTarget().getGOT().finalizeScan(pInput);
277  return true;
278}
279
280bool MipsRelocator::initializeApply(Input& pInput)
281{
282  m_pApplyingInput = &pInput;
283  return true;
284}
285
286bool MipsRelocator::finalizeApply(Input& pInput)
287{
288  m_pApplyingInput = NULL;
289  return true;
290}
291
292void MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc,
293                                   IRBuilder& pBuilder,
294                                   const LDSection& pSection)
295{
296  ResolveInfo* rsym = pReloc.parent().symInfo();
297
298  switch (pReloc.type()){
299    case llvm::ELF::R_MIPS_NONE:
300    case llvm::ELF::R_MIPS_16:
301      break;
302    case llvm::ELF::R_MIPS_32:
303    case llvm::ELF::R_MIPS_64:
304      if (LinkerConfig::DynObj == config().codeGenType()) {
305        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
306        // section if the symbol section flags contains SHF_EXECINSTR.
307        // 1. Find the reason of this condition.
308        // 2. Check this condition here.
309        getTarget().getRelDyn().reserveEntry();
310        rsym->setReserved(rsym->reserved() | ReserveRel);
311        getTarget().checkAndSetHasTextRel(*pSection.getLink());
312      }
313      break;
314    case llvm::ELF::R_MIPS_REL32:
315    case llvm::ELF::R_MIPS_26:
316    case llvm::ELF::R_MIPS_HI16:
317    case llvm::ELF::R_MIPS_LO16:
318    case llvm::ELF::R_MIPS_PC16:
319    case llvm::ELF::R_MIPS_SHIFT5:
320    case llvm::ELF::R_MIPS_SHIFT6:
321    case llvm::ELF::R_MIPS_SUB:
322    case llvm::ELF::R_MIPS_INSERT_A:
323    case llvm::ELF::R_MIPS_INSERT_B:
324    case llvm::ELF::R_MIPS_DELETE:
325    case llvm::ELF::R_MIPS_HIGHER:
326    case llvm::ELF::R_MIPS_HIGHEST:
327    case llvm::ELF::R_MIPS_SCN_DISP:
328    case llvm::ELF::R_MIPS_REL16:
329    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
330    case llvm::ELF::R_MIPS_PJUMP:
331    case llvm::ELF::R_MIPS_RELGOT:
332    case llvm::ELF::R_MIPS_JALR:
333    case llvm::ELF::R_MIPS_GLOB_DAT:
334    case llvm::ELF::R_MIPS_COPY:
335    case llvm::ELF::R_MIPS_JUMP_SLOT:
336      break;
337    case llvm::ELF::R_MIPS_GOT16:
338    case llvm::ELF::R_MIPS_CALL16:
339    case llvm::ELF::R_MIPS_GOT_HI16:
340    case llvm::ELF::R_MIPS_CALL_HI16:
341    case llvm::ELF::R_MIPS_GOT_LO16:
342    case llvm::ELF::R_MIPS_CALL_LO16:
343    case llvm::ELF::R_MIPS_GOT_DISP:
344    case llvm::ELF::R_MIPS_GOT_PAGE:
345    case llvm::ELF::R_MIPS_GOT_OFST:
346      if (getTarget().getGOT().reserveLocalEntry(*rsym,
347                                                 pReloc.type(), pReloc.A())) {
348        if (getTarget().getGOT().hasMultipleGOT())
349          getTarget().checkAndSetHasTextRel(*pSection.getLink());
350      }
351      break;
352    case llvm::ELF::R_MIPS_GPREL32:
353    case llvm::ELF::R_MIPS_GPREL16:
354    case llvm::ELF::R_MIPS_LITERAL:
355      break;
356    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
357    case llvm::ELF::R_MIPS_TLS_DTPREL32:
358    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
359    case llvm::ELF::R_MIPS_TLS_DTPREL64:
360    case llvm::ELF::R_MIPS_TLS_GD:
361    case llvm::ELF::R_MIPS_TLS_LDM:
362    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
363    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
364    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
365    case llvm::ELF::R_MIPS_TLS_TPREL32:
366    case llvm::ELF::R_MIPS_TLS_TPREL64:
367    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
368    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
369      break;
370    case llvm::ELF::R_MIPS_PC32:
371      break;
372    default:
373      fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name();
374  }
375}
376
377void MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc,
378                                    IRBuilder& pBuilder,
379                                    const LDSection& pSection)
380{
381  ResolveInfo* rsym = pReloc.parent().symInfo();
382
383  switch (pReloc.type()){
384    case llvm::ELF::R_MIPS_NONE:
385    case llvm::ELF::R_MIPS_INSERT_A:
386    case llvm::ELF::R_MIPS_INSERT_B:
387    case llvm::ELF::R_MIPS_DELETE:
388    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
389    case llvm::ELF::R_MIPS_TLS_DTPREL64:
390    case llvm::ELF::R_MIPS_REL16:
391    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
392    case llvm::ELF::R_MIPS_PJUMP:
393    case llvm::ELF::R_MIPS_RELGOT:
394    case llvm::ELF::R_MIPS_TLS_TPREL64:
395      break;
396    case llvm::ELF::R_MIPS_32:
397    case llvm::ELF::R_MIPS_64:
398    case llvm::ELF::R_MIPS_HI16:
399    case llvm::ELF::R_MIPS_LO16:
400      if (getTarget().symbolNeedsDynRel(*rsym, false, true)) {
401        getTarget().getRelDyn().reserveEntry();
402        if (getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) {
403          LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym);
404          addCopyReloc(*cpySym.resolveInfo());
405        }
406        else {
407          // set Rel bit
408          rsym->setReserved(rsym->reserved() | ReserveRel);
409          getTarget().checkAndSetHasTextRel(*pSection.getLink());
410        }
411      }
412      break;
413    case llvm::ELF::R_MIPS_GOT16:
414    case llvm::ELF::R_MIPS_CALL16:
415    case llvm::ELF::R_MIPS_GOT_DISP:
416    case llvm::ELF::R_MIPS_GOT_HI16:
417    case llvm::ELF::R_MIPS_CALL_HI16:
418    case llvm::ELF::R_MIPS_GOT_LO16:
419    case llvm::ELF::R_MIPS_CALL_LO16:
420    case llvm::ELF::R_MIPS_GOT_PAGE:
421    case llvm::ELF::R_MIPS_GOT_OFST:
422      if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
423        if (getTarget().getGOT().hasMultipleGOT())
424          getTarget().checkAndSetHasTextRel(*pSection.getLink());
425      }
426      break;
427    case llvm::ELF::R_MIPS_LITERAL:
428    case llvm::ELF::R_MIPS_GPREL32:
429      fatal(diag::invalid_global_relocation) << (int)pReloc.type()
430                                             << rsym->name();
431      break;
432    case llvm::ELF::R_MIPS_GPREL16:
433      break;
434    case llvm::ELF::R_MIPS_26:
435      // Create a PLT entry if the symbol requires it and does not have it.
436      if (getTarget().symbolNeedsPLT(*rsym) &&
437          !(rsym->reserved() & ReservePLT)) {
438        getTarget().getPLT().reserveEntry();
439        getTarget().getGOTPLT().reserve();
440        getTarget().getRelPLT().reserveEntry();
441        rsym->setReserved(rsym->reserved() | ReservePLT);
442      }
443      break;
444    case llvm::ELF::R_MIPS_PC16:
445      break;
446    case llvm::ELF::R_MIPS_16:
447    case llvm::ELF::R_MIPS_SHIFT5:
448    case llvm::ELF::R_MIPS_SHIFT6:
449    case llvm::ELF::R_MIPS_SUB:
450    case llvm::ELF::R_MIPS_HIGHER:
451    case llvm::ELF::R_MIPS_HIGHEST:
452    case llvm::ELF::R_MIPS_SCN_DISP:
453      break;
454    case llvm::ELF::R_MIPS_TLS_DTPREL32:
455    case llvm::ELF::R_MIPS_TLS_GD:
456    case llvm::ELF::R_MIPS_TLS_LDM:
457    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
458    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
459    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
460    case llvm::ELF::R_MIPS_TLS_TPREL32:
461    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
462    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
463      break;
464    case llvm::ELF::R_MIPS_REL32:
465    case llvm::ELF::R_MIPS_JALR:
466    case llvm::ELF::R_MIPS_PC32:
467      break;
468    case llvm::ELF::R_MIPS_COPY:
469    case llvm::ELF::R_MIPS_GLOB_DAT:
470    case llvm::ELF::R_MIPS_JUMP_SLOT:
471      fatal(diag::dynamic_relocation) << (int)pReloc.type();
472      break;
473    default:
474      fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name();
475  }
476}
477
478bool MipsRelocator::isPostponed(const Relocation& pReloc) const
479{
480  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16))
481    return true;
482
483  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) &&
484      pReloc.symInfo()->isLocal())
485    return true;
486
487  return false;
488}
489
490void MipsRelocator::addCopyReloc(ResolveInfo& pSym)
491{
492  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
493  relEntry.setType(llvm::ELF::R_MIPS_COPY);
494  assert(pSym.outSymbol()->hasFragRef());
495  relEntry.targetRef().assign(*pSym.outSymbol()->fragRef());
496  relEntry.setSymInfo(&pSym);
497}
498
499LDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
500                                                  const ResolveInfo& pSym)
501{
502  // Get or create corresponding BSS LDSection
503  ELFFileFormat* fileFormat = getTarget().getOutputFormat();
504  LDSection* bssSectHdr =
505    ResolveInfo::ThreadLocal == pSym.type() ? &fileFormat->getTBSS()
506                                            : &fileFormat->getBSS();
507
508  // Get or create corresponding BSS SectionData
509  SectionData* bssData =
510    bssSectHdr->hasSectionData() ? bssSectHdr->getSectionData()
511                                 : IRBuilder::CreateSectionData(*bssSectHdr);
512
513  // Determine the alignment by the symbol value
514  // FIXME: here we use the largest alignment
515  uint32_t addrAlign = config().targets().bitclass() / 8;
516
517  // Allocate space in BSS for the copy symbol
518  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
519  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign);
520  bssSectHdr->setSize(bssSectHdr->size() + size);
521
522  // Change symbol binding to Global if it's a weak symbol
523  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
524  if (binding == ResolveInfo::Weak)
525    binding = ResolveInfo::Global;
526
527  // Define the copy symbol in the bss section and resolve it
528  LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
529                      pSym.name(),
530                      (ResolveInfo::Type)pSym.type(),
531                      ResolveInfo::Define,
532                      binding,
533                      pSym.size(),  // size
534                      0x0,          // value
535                      FragmentRef::Create(*frag, 0x0),
536                      (ResolveInfo::Visibility)pSym.other());
537
538  // Output all other alias symbols if any
539  Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym);
540  if (NULL == alias_list)
541    return *cpySym;
542
543  for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end();
544       it != ie; ++it) {
545    const ResolveInfo* alias = *it;
546    if (alias == &pSym || !alias->isDyn())
547      continue;
548
549    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
550        alias->name(),
551        (ResolveInfo::Type)alias->type(),
552        ResolveInfo::Define,
553        binding,
554        alias->size(),  // size
555        0x0,            // value
556        FragmentRef::Create(*frag, 0x0),
557        (ResolveInfo::Visibility)alias->other());
558  }
559
560  return *cpySym;
561}
562
563void MipsRelocator::postponeRelocation(Relocation& pReloc)
564{
565  ResolveInfo* rsym = pReloc.symInfo();
566  m_PostponedRelocs[rsym].insert(&pReloc);
567}
568
569void MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc)
570{
571  m_CurrentLo16Reloc = &pLo16Reloc;
572
573  ResolveInfo* rsym = pLo16Reloc.parent().symInfo();
574
575  RelocationSet & relocs = m_PostponedRelocs[rsym];
576  for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it)
577    (*it)->apply(*this);
578
579  m_PostponedRelocs.erase(rsym);
580
581  m_CurrentLo16Reloc = NULL;
582}
583
584bool MipsRelocator::isGpDisp(const Relocation& pReloc) const
585{
586  return 0 == strcmp("_gp_disp", pReloc.symInfo()->name());
587}
588
589bool MipsRelocator::isRel() const
590{
591  return config().targets().is32Bits();
592}
593
594bool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const
595{
596  if (pSym.isUndef())
597    return false;
598
599  return pSym.isLocal() ||
600         !getTarget().isDynamicSymbol(pSym) ||
601         !pSym.isDyn();
602}
603
604Relocator::Address MipsRelocator::getGPAddress()
605{
606  return getTarget().getGOT().getGPAddr(getApplyingInput());
607}
608
609Relocator::Address MipsRelocator::getGP0()
610{
611  return getTarget().getGP0(getApplyingInput());
612}
613
614Fragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc,
615                                          Relocation::DWord entryValue)
616{
617  // rsym - The relocation target symbol
618  ResolveInfo* rsym = pReloc.parent().symInfo();
619  MipsGOT& got = getTarget().getGOT();
620
621  assert(isLocalReloc(*rsym) &&
622         "Attempt to get a global GOT entry for the local relocation");
623
624  Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue);
625
626  // Found a mapping, then return the mapped entry immediately.
627  if (NULL != got_entry)
628    return *got_entry;
629
630  // Not found.
631  got_entry = got.consumeLocal();
632
633  if (got.isPrimaryGOTConsumed())
634    setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), NULL);
635  else
636    got.setEntryValue(got_entry, entryValue);
637
638  got.recordLocalEntry(rsym, entryValue, got_entry);
639
640  return *got_entry;
641}
642
643Fragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc)
644{
645  // rsym - The relocation target symbol
646  ResolveInfo* rsym = pReloc.parent().symInfo();
647  MipsGOT& got = getTarget().getGOT();
648
649  assert(!isLocalReloc(*rsym) &&
650         "Attempt to get a local GOT entry for the global relocation");
651
652  Fragment* got_entry = got.lookupGlobalEntry(rsym);
653
654  // Found a mapping, then return the mapped entry immediately.
655  if (NULL != got_entry)
656    return *got_entry;
657
658  // Not found.
659  got_entry = got.consumeGlobal();
660
661  if (got.isPrimaryGOTConsumed())
662    setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), rsym);
663  else
664    got.setEntryValue(got_entry, pReloc.parent().symValue());
665
666  got.recordGlobalEntry(rsym, got_entry);
667
668  return *got_entry;
669}
670
671Relocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc)
672{
673  ResolveInfo* rsym = pReloc.parent().symInfo();
674  MipsGOT& got = getTarget().getGOT();
675
676  if (isLocalReloc(*rsym)) {
677    uint64_t value = pReloc.S();
678
679    if (ResolveInfo::Section == rsym->type())
680      value += pReloc.A();
681
682    return got.getGPRelOffset(getApplyingInput(),
683                              getLocalGOTEntry(pReloc, value));
684  }
685  else {
686    return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc));
687  }
688}
689
690void MipsRelocator::createDynRel(MipsRelocationInfo& pReloc)
691{
692  Relocator::DWord A = pReloc.A();
693  Relocator::DWord S = pReloc.S();
694
695  ResolveInfo* rsym = pReloc.parent().symInfo();
696
697  if (isLocalReloc(*rsym)) {
698    setupRelDynEntry(pReloc.parent().targetRef(), NULL);
699    pReloc.result() = A + S;
700  }
701  else {
702    setupRelDynEntry(pReloc.parent().targetRef(), rsym);
703    // Don't add symbol value that will be resolved by the dynamic linker.
704    pReloc.result() = A;
705  }
706}
707
708uint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc)
709{
710  assert(NULL != m_CurrentLo16Reloc &&
711         "There is no saved R_MIPS_LO16 relocation");
712
713  uint64_t AHI = pHiReloc.A() & 0xFFFF;
714  uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF;
715  uint64_t AHL = (AHI << 16) + int16_t(ALO);
716
717  return AHL;
718}
719
720bool MipsRelocator::isN64ABI() const
721{
722  return config().targets().is64Bits();
723}
724
725uint64_t MipsRelocator::getPLTAddress(ResolveInfo& rsym)
726{
727  assert((rsym.reserved() & MipsRelocator::ReservePLT) &&
728         "Symbol does not require a PLT entry");
729
730  SymPLTMap::const_iterator it = m_SymPLTMap.find(&rsym);
731
732  Fragment* plt;
733
734  if (it != m_SymPLTMap.end()) {
735    plt = it->second.first;
736  }
737  else {
738    plt = getTarget().getPLT().consume();
739
740    Fragment* got = getTarget().getGOTPLT().consume();
741    Relocation* rel = getTarget().getRelPLT().consumeEntry();
742
743    rel->setType(llvm::ELF::R_MIPS_JUMP_SLOT);
744    rel->targetRef().assign(*got);
745    rel->setSymInfo(&rsym);
746
747    m_SymPLTMap[&rsym] = PLTDescriptor(plt, got);
748  }
749
750  return getTarget().getPLT().addr() + plt->getOffset();
751}
752
753//===----------------------------------------------------------------------===//
754// Mips32Relocator
755//===----------------------------------------------------------------------===//
756Mips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent,
757                                 const LinkerConfig& pConfig)
758  : MipsRelocator(pParent, pConfig)
759{}
760
761void Mips32Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym)
762{
763  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
764  relEntry.setType(llvm::ELF::R_MIPS_REL32);
765  relEntry.targetRef() = pFragRef;
766  relEntry.setSymInfo(pSym);
767}
768
769//===----------------------------------------------------------------------===//
770// Mips64Relocator
771//===----------------------------------------------------------------------===//
772Mips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent,
773                                 const LinkerConfig& pConfig)
774  : MipsRelocator(pParent, pConfig)
775{}
776
777void Mips64Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym)
778{
779  Relocation::Type type = llvm::ELF::R_MIPS_REL32 |
780                          llvm::ELF::R_MIPS_64 << 8;
781  // FIXME (simon): Fix dynamic relocations.
782  type = llvm::ELF::R_MIPS_NONE;
783
784  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
785  relEntry.setType(type);
786  relEntry.targetRef() = pFragRef;
787  relEntry.setSymInfo(pSym);
788}
789
790//=========================================//
791// Relocation functions implementation     //
792//=========================================//
793
794// R_MIPS_NONE and those unsupported/deprecated relocation type
795static
796MipsRelocator::Result none(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
797{
798  return Relocator::OK;
799}
800
801// R_MIPS_32: S + A
802static
803MipsRelocator::Result abs32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
804{
805  ResolveInfo* rsym = pReloc.parent().symInfo();
806
807  Relocator::DWord A = pReloc.A();
808  Relocator::DWord S = pReloc.S();
809
810  LDSection& target_sect =
811    pReloc.parent().targetRef().frag()->getParent()->getSection();
812
813  // If the flag of target section is not ALLOC, we will not scan this relocation
814  // but perform static relocation. (e.g., applying .debug section)
815  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
816    pReloc.result() = S + A;
817    return Relocator::OK;
818  }
819
820  if (rsym->reserved() & MipsRelocator::ReserveRel) {
821    pParent.createDynRel(pReloc);
822    return Relocator::OK;
823  }
824
825  pReloc.result() = S + A;
826
827  return Relocator::OK;
828}
829
830// R_MIPS_26:
831//   local   : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
832//   external: (sign–extend(A) + S) >> 2
833static
834MipsRelocator::Result rel26(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
835{
836  ResolveInfo* rsym = pReloc.parent().symInfo();
837
838  int32_t A = ((pReloc.parent().target() & 0x03FFFFFF) << 2);
839  int32_t P = pReloc.P();
840  int32_t S = rsym->reserved() & MipsRelocator::ReservePLT
841                  ? pParent.getPLTAddress(*rsym)
842                  : pReloc.S();
843
844  if (rsym->isLocal())
845    pReloc.result() = A | ((P + 4) & 0x3F000000);
846  else
847    pReloc.result() = mcld::signExtend<28>(A);
848
849  pReloc.result() = (pReloc.result() + S) >> 2;
850
851  return Relocator::OK;
852}
853
854// R_MIPS_HI16:
855//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
856//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
857static
858MipsRelocator::Result hi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
859{
860  uint64_t AHL = pParent.calcAHL(pReloc);
861
862  if (pParent.isGpDisp(pReloc.parent())) {
863    int32_t P = pReloc.P();
864    int32_t GP = pParent.getGPAddress();
865    pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
866  }
867  else {
868    int32_t S = pReloc.S();
869    if (pParent.isN64ABI())
870      pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16;
871    else
872      pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
873  }
874
875  return Relocator::OK;
876}
877
878// R_MIPS_LO16:
879//   local/external: AHL + S
880//   _gp_disp      : AHL + GP - P + 4
881static
882MipsRelocator::Result lo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
883{
884  // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16
885  // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16
886  // addend here.
887  int32_t AHL = (pReloc.A() & 0xFFFF);
888
889  if (pParent.isGpDisp(pReloc.parent())) {
890    int32_t P = pReloc.P();
891    int32_t GP = pParent.getGPAddress();
892    pReloc.result() = AHL + GP - P + 4;
893  }
894  else {
895    int32_t S = pReloc.S();
896    pReloc.result() = AHL + S;
897  }
898
899  pParent.applyPostponedRelocations(pReloc);
900
901  return Relocator::OK;
902}
903
904// R_MIPS_GPREL16:
905//   external: sign–extend(A) + S - GP
906//   local   : sign–extend(A) + S + GP0 – GP
907static
908MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
909{
910  // Remember to add the section offset to A.
911  uint64_t A = pReloc.A();
912  uint64_t S = pReloc.S();
913  uint64_t GP0 = pParent.getGP0();
914  uint64_t GP = pParent.getGPAddress();
915
916  ResolveInfo* rsym = pReloc.parent().symInfo();
917  if (rsym->isLocal())
918    pReloc.result() = A + S + GP0 - GP;
919  else
920    pReloc.result() = A + S - GP;
921
922  return Relocator::OK;
923}
924
925// R_MIPS_GOT16:
926//   local   : G (calculate AHL and put high 16 bit to GOT)
927//   external: G
928static
929MipsRelocator::Result got16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
930{
931  if (pReloc.parent().symInfo()->isLocal()) {
932    int32_t AHL = pParent.calcAHL(pReloc);
933    int32_t S = pReloc.S();
934    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
935
936    MipsGOT& got = pParent.getTarget().getGOT();
937
938    Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res);
939
940    pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
941  }
942  else {
943    pReloc.result() = pParent.getGOTOffset(pReloc);
944  }
945
946  return Relocator::OK;
947}
948
949// R_MIPS_GOTHI16:
950//   external: (G - (short)G) >> 16 + A
951static
952MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
953{
954  Relocator::Address G = pParent.getGOTOffset(pReloc);
955  int32_t A = pReloc.A();
956
957  pReloc.result() = (G - (int16_t)G) >> (16 + A);
958
959  return Relocator::OK;
960}
961
962// R_MIPS_GOTLO16:
963//   external: G & 0xffff
964static
965MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
966{
967  pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff;
968
969  return Relocator::OK;
970}
971
972// R_MIPS_SUB:
973//   external/local: S - A
974static
975MipsRelocator::Result sub(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
976{
977  uint64_t S = pReloc.S();
978  uint64_t A = pReloc.A();
979
980  pReloc.result() = S - A;
981
982  return Relocator::OK;
983}
984
985// R_MIPS_CALL16: G
986static
987MipsRelocator::Result call16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
988{
989  pReloc.result() = pParent.getGOTOffset(pReloc);
990
991  return Relocator::OK;
992}
993
994// R_MIPS_GPREL32: A + S + GP0 - GP
995static
996MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
997{
998  // Remember to add the section offset to A.
999  uint64_t A = pReloc.A();
1000  uint64_t S = pReloc.S();
1001  uint64_t GP0 = pParent.getGP0();
1002  uint64_t GP = pParent.getGPAddress();
1003
1004  pReloc.result() = A + S + GP0 - GP;
1005
1006  return Relocator::OK;
1007}
1008
1009// R_MIPS_64: S + A
1010static
1011MipsRelocator::Result abs64(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1012{
1013  // FIXME (simon): Consider to merge with abs32() or use the same function
1014  // but with another mask size.
1015  ResolveInfo* rsym = pReloc.parent().symInfo();
1016
1017  Relocator::DWord A = pReloc.A();
1018  Relocator::DWord S = pReloc.S();
1019
1020  LDSection& target_sect =
1021    pReloc.parent().targetRef().frag()->getParent()->getSection();
1022
1023  // If the flag of target section is not ALLOC, we will not scan this relocation
1024  // but perform static relocation. (e.g., applying .debug section)
1025  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1026    pReloc.result() = S + A;
1027    return Relocator::OK;
1028  }
1029
1030  if (rsym->reserved() & MipsRelocator::ReserveRel) {
1031    pParent.createDynRel(pReloc);
1032    return Relocator::OK;
1033  }
1034
1035  pReloc.result() = S + A;
1036
1037  return Relocator::OK;
1038}
1039
1040// R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G
1041static
1042MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1043{
1044  pReloc.result() = pParent.getGOTOffset(pReloc);
1045
1046  return Relocator::OK;
1047}
1048
1049// R_MIPS_GOT_OFST:
1050static
1051MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1052{
1053  // FIXME (simon): Needs to be implemented.
1054  return Relocator::OK;
1055}
1056
1057// R_MIPS_JALR:
1058static
1059MipsRelocator::Result jalr(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1060{
1061  return Relocator::OK;
1062}
1063
1064// R_MIPS_LA25_LUI
1065static
1066MipsRelocator::Result la25lui(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1067{
1068  int32_t S = pReloc.S();
1069
1070  pReloc.result() = (S + 0x8000) >> 16;
1071
1072  return Relocator::OK;
1073}
1074
1075// R_MIPS_LA25_J
1076static
1077MipsRelocator::Result la25j(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1078{
1079  int32_t S = pReloc.S();
1080
1081  pReloc.result() = S >> 2;
1082
1083  return Relocator::OK;
1084}
1085
1086// R_MIPS_LA25_ADD
1087static
1088MipsRelocator::Result la25add(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1089{
1090  pReloc.result() = pReloc.S();
1091
1092  return Relocator::OK;
1093}
1094
1095// R_MIPS_PC32:
1096static
1097MipsRelocator::Result pc32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1098{
1099  return Relocator::OK;
1100}
1101
1102static
1103MipsRelocator::Result unsupport(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
1104{
1105  return Relocator::Unsupport;
1106}
1107