1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- MipsRelocator.cpp  -----------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "MipsRelocator.h"
1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "MipsRelocationFunctions.h"
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/OutputRelocSection.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/ADT/Twine.h>
2087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/ELF.h>
2187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// MipsRelocationInfo
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesclass MipsRelocationInfo {
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines public:
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  static bool HasSubType(const Relocation& pParent, Relocation::Type pType) {
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (llvm::ELF::R_MIPS_NONE == pType)
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return true;
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (Relocation::Type type = pParent.type();
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines         llvm::ELF::R_MIPS_NONE != (type & 0xff);
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines         type >>= 8) {
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if ((type & 0xff) == pType)
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return true;
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsRelocationInfo(Relocation& pParent, bool pIsRel)
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      : m_Parent(&pParent),
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Type(pParent.type()),
46b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        m_Addend(pIsRel ? pParent.target() : pParent.addend()),
4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Symbol(pParent.symValue()),
48b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        m_Result(pParent.target()) {}
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool isNone() const { return llvm::ELF::R_MIPS_NONE == type(); }
51b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  bool isFirst() const { return type() == (parent().type() & 0xff); }
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool isLast() const { return llvm::ELF::R_MIPS_NONE == (m_Type >> 8); }
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  MipsRelocationInfo next() const {
55b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result());
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const Relocation& parent() const { return *m_Parent; }
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation& parent() { return *m_Parent; }
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::Type type() const { return m_Type & 0xff; }
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::DWord A() const { return m_Addend; }
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::DWord S() const { return m_Symbol; }
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::DWord P() const { return parent().place(); }
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::DWord result() const { return m_Result; }
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::DWord& result() { return m_Result; }
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines private:
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation* m_Parent;
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::Type m_Type;
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord m_Addend;
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord m_Symbol;
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord m_Result;
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
81b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  MipsRelocationInfo(Relocation& pParent, Relocation::Type pType,
82b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                     Relocation::DWord pResult, Relocation::DWord pAddend)
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      : m_Parent(&pParent),
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Type(pType),
8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Addend(pAddend),
86b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        m_Symbol(0),
8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Result(pResult) {}
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic void helper_PLT_init(MipsRelocationInfo& pReloc,
91b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                            MipsRelocator& pParent) {
92b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
93b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL && "PLT entry exists");
94b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
95b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  MipsGNULDBackend& backend = pParent.getTarget();
96b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  PLTEntryBase* pltEntry = backend.getPLT().create();
97b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pParent.getSymPLTMap().record(*rsym, *pltEntry);
98b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
99b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL &&
100b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines         "PLT entry not exist, but DynRel entry exist!");
101b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  Fragment* gotpltEntry = backend.getGOTPLT().create();
102b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pParent.getSymGOTPLTMap().record(*rsym, *gotpltEntry);
103b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
104b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  Relocation* relEntry = backend.getRelPLT().create();
105b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  relEntry->setType(llvm::ELF::R_MIPS_JUMP_SLOT);
106b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  relEntry->targetRef().assign(*gotpltEntry);
107b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  relEntry->setSymInfo(rsym);
108b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
109b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
110b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
111b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                                 MipsRelocator& pParent) {
112b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
113b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  assert(plt_entry != NULL);
114b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
115b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
116b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
11867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
11967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinestypedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&,
12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               MipsRelocator& pParent);
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
12737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct ApplyFunctionTriple {
12867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
12967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
13067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
13267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
13367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
13467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
13567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    DECL_MIPS_APPLY_RELOC_FUNC_PTRS};
13767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
13867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator
14067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent,
142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                             const LinkerConfig& pConfig)
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : Relocator(pConfig),
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Target(pParent),
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pApplyingInput(NULL),
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_CurrentLo16Reloc(NULL) {
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result MipsRelocator::applyRelocation(Relocation& pReloc) {
15087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // If m_CurrentLo16Reloc is not NULL we are processing
15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // postponed relocation. Otherwise check relocation type
15287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // and postpone it for later handling.
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_CurrentLo16Reloc == NULL && isPostponed(pReloc)) {
15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    postponeRelocation(pReloc);
15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return OK;
15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone();
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       info = info.next()) {
16087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0]))
16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return Unknown;
16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ApplyFunctionTriple& triple = ApplyFunctions[info.type()];
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
16587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Result res = triple.func(info, *this);
16687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (OK != res)
16787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return res;
16887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (info.isLast()) {
17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size);
17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.target() &= ~mask;
17287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.target() |= info.result() & mask;
17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return OK;
17767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
17937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* MipsRelocator::getName(Relocation::Type pType) const {
18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return ApplyFunctions[pType & 0xff].name;
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanRelocation(Relocation& pReloc,
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   Module& pModule,
18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                   LDSection& pSection,
18737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   Input& pInput) {
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
19037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(rsym != NULL &&
19137b74a387bb3993387029859c2d9d051c41c724eStephen Hines         "ResolveInfo of relocation not set while scanRelocation");
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Skip relocation against _gp_disp
19437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (getTarget().getGpDispSymbol() != NULL &&
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym == getTarget().getGpDispSymbol()->resolveInfo())
19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
19837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pSection.getLink() != NULL);
19937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0)
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone();
20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       info = info.next()) {
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // We test isLocal or if pInputSym is not a dynamic symbol
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Don't put undef symbols into local entries.
20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (isLocalReloc(*rsym))
20887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      scanLocalReloc(info, pBuilder, pSection);
20987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      scanGlobalReloc(info, pBuilder, pSection);
21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
21287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo()))
21387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getTarget().addNonPICBranchSym(pReloc.symInfo());
21487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
21687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Check if we should issue undefined reference
21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // for the relocation target symbol.
218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
21987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    issueUndefRef(pReloc, pSection, pInput);
220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
22237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::initializeScan(Input& pInput) {
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object != config().codeGenType())
22487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    getTarget().getGOT().initializeScan(pInput);
225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::finalizeScan(Input& pInput) {
22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object != config().codeGenType())
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    getTarget().getGOT().finalizeScan(pInput);
231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
23437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::initializeApply(Input& pInput) {
235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pApplyingInput = &pInput;
236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
23937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::finalizeApply(Input& pInput) {
240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pApplyingInput = NULL;
241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc,
245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
24637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   const LDSection& pSection) {
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
24937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_NONE:
251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_16:
252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_32:
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_64:
255b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      if (pReloc.isFirst() && LinkerConfig::DynObj == config().codeGenType()) {
256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // section if the symbol section flags contains SHF_EXECINSTR.
258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // 1. Find the reason of this condition.
259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // 2. Check this condition here.
260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL32:
266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_26:
267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HI16:
268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LO16:
269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT5:
270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT6:
271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SUB:
272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_A:
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_B:
274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_DELETE:
275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHER:
276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHEST:
277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SCN_DISP:
278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL16:
279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PJUMP:
281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_RELGOT:
282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JALR:
283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GLOB_DAT:
284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_COPY:
285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JUMP_SLOT:
286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT16:
288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL16:
289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_HI16:
290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_HI16:
291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_LO16:
292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_LO16:
29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_GOT_DISP:
29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_GOT_PAGE:
29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_GOT_OFST:
29637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (getTarget()
29737b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .getGOT()
29837b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .reserveLocalEntry(*rsym, pReloc.type(), pReloc.A())) {
299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().getGOT().hasMultipleGOT())
300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL32:
304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL16:
305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LITERAL:
306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
307b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_TLS_GD:
308b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().getGOT().reserveTLSGdEntry(*rsym);
309b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
310b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
311b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_TLS_LDM:
312b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().getGOT().reserveTLSLdmEntry();
313b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
314b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
315b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
316b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().getGOT().reserveTLSGotEntry(*rsym);
317b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
318b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL32:
321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL64:
323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL32:
326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL64:
327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
330b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC16:
33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_PC32:
332b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC18_S3:
333b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC19_S2:
334b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC21_S2:
335b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC26_S2:
336b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PCHI16:
337b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PCLO16:
33887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
34037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type())
34137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      << rsym->name();
342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
34587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc,
346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                    IRBuilder& pBuilder,
34737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    const LDSection& pSection) {
34887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
349b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  bool hasPLT = rsym->reserved() & ReservePLT;
350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
35137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_NONE:
353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_A:
354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_B:
355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_DELETE:
356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL64:
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL16:
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PJUMP:
361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_RELGOT:
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL64:
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_32:
365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_64:
366b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      if (pReloc.isFirst() &&
367b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines          getTarget().symbolNeedsDynRel(*rsym, hasPLT, true)) {
368b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        getTarget().getRelDyn().reserveEntry();
369b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
370b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
371b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        if (!getTarget().symbolFinalValueIsKnown(*rsym))
372b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines          getTarget().getGOT().reserveGlobalEntry(*rsym);
373b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      }
374b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HI16:
376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LO16:
377b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, hasPLT, true) ||
378b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines          getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) {
379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
380b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym);
381b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        addCopyReloc(*cpySym.resolveInfo());
382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT16:
385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL16:
386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_DISP:
387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_HI16:
388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_HI16:
389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_LO16:
390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_LO16:
391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_PAGE:
392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_OFST:
393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().getGOT().hasMultipleGOT())
395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LITERAL:
399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL32:
40037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::invalid_global_relocation) << static_cast<int>(pReloc.type())
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             << rsym->name();
402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL16:
404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_26:
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Create a PLT entry if the symbol requires it and does not have it.
407b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) && !hasPLT) {
408b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        helper_PLT_init(pReloc, *this);
40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rsym->setReserved(rsym->reserved() | ReservePLT);
41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
41187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_16:
413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT5:
414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT6:
415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SUB:
416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHER:
417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHEST:
418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SCN_DISP:
419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GD:
421b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().getGOT().reserveTLSGdEntry(*rsym);
422b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
423b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_LDM:
425b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().getGOT().reserveTLSLdmEntry();
426b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
427b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
428b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
429b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().getGOT().reserveTLSGotEntry(*rsym);
430b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
431b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      break;
432b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL32:
433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL32:
436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL32:
440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JALR:
441b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC16:
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_PC32:
443b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC18_S3:
444b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC19_S2:
445b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC21_S2:
446b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PC26_S2:
447b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PCHI16:
448b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_MIPS_PCLO16:
449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_COPY:
451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GLOB_DAT:
452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JUMP_SLOT:
45337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::dynamic_relocation) << static_cast<int>(pReloc.type());
454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
45637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type())
45737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      << rsym->name();
458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
46137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isPostponed(const Relocation& pReloc) const {
462b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (isN64ABI())
463b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return false;
464b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
465b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16) ||
466b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_PCHI16))
46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
46987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) &&
47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.symInfo()->isLocal())
47187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
47287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
47387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return false;
47487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
47587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
47637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::addCopyReloc(ResolveInfo& pSym) {
47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setType(llvm::ELF::R_MIPS_COPY);
47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(pSym.outSymbol()->hasFragRef());
48087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.targetRef().assign(*pSym.outSymbol()->fragRef());
48187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setSymInfo(&pSym);
48287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
48487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesLDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
48537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                  const ResolveInfo& pSym) {
48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Get or create corresponding BSS LDSection
48787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* fileFormat = getTarget().getOutputFormat();
48837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  LDSection* bssSectHdr = ResolveInfo::ThreadLocal == pSym.type()
48937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              ? &fileFormat->getTBSS()
49037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              : &fileFormat->getBSS();
49187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Get or create corresponding BSS SectionData
49337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  SectionData* bssData = bssSectHdr->hasSectionData()
49437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             ? bssSectHdr->getSectionData()
49537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             : IRBuilder::CreateSectionData(*bssSectHdr);
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Determine the alignment by the symbol value
49887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: here we use the largest alignment
49987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t addrAlign = config().targets().bitclass() / 8;
50087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Allocate space in BSS for the copy symbol
50287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
50387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign);
50487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bssSectHdr->setSize(bssSectHdr->size() + size);
50587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Change symbol binding to Global if it's a weak symbol
50787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
50887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (binding == ResolveInfo::Weak)
50987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    binding = ResolveInfo::Global;
51087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Define the copy symbol in the bss section and resolve it
51287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
51337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pSym.name(),
51437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (ResolveInfo::Type)pSym.type(),
51537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Define,
51637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      binding,
51737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pSym.size(),  // size
51837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,          // value
51937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      FragmentRef::Create(*frag, 0x0),
52037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (ResolveInfo::Visibility)pSym.other());
52187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Output all other alias symbols if any
52387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym);
52437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (alias_list == NULL)
52587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return *cpySym;
52687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end();
52837b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
52937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it) {
53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const ResolveInfo* alias = *it;
53187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (alias == &pSym || !alias->isDyn())
53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      continue;
53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
53487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        alias->name(),
53687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (ResolveInfo::Type)alias->type(),
53787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ResolveInfo::Define,
53887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        binding,
53987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        alias->size(),  // size
54087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        0x0,            // value
54187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        FragmentRef::Create(*frag, 0x0),
54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (ResolveInfo::Visibility)alias->other());
5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
54487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *cpySym;
5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::postponeRelocation(Relocation& pReloc) {
54987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_PostponedRelocs[rsym].insert(&pReloc);
5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
55337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc) {
55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_CurrentLo16Reloc = &pLo16Reloc;
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pLo16Reloc.parent().symInfo();
55787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
55837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  RelocationSet& relocs = m_PostponedRelocs[rsym];
55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it)
56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    (*it)->apply(*this);
56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_PostponedRelocs.erase(rsym);
56387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
56487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_CurrentLo16Reloc = NULL;
5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
56737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isGpDisp(const Relocation& pReloc) const {
56837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return strcmp("_gp_disp", pReloc.symInfo()->name()) == 0;
56987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
57137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isRel() const {
57287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return config().targets().is32Bits();
573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
57537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const {
57687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSym.isUndef())
57787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
57887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
57937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return pSym.isLocal() || !getTarget().isDynamicSymbol(pSym) || !pSym.isDyn();
58087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
58187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
58237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Address MipsRelocator::getGPAddress() {
58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return getTarget().getGOT().getGPAddr(getApplyingInput());
58487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
586b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Address MipsRelocator::getTPOffset() {
587b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return getTarget().getTPOffset(getApplyingInput());
588b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
589b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
590b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Address MipsRelocator::getDTPOffset() {
591b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return getTarget().getDTPOffset(getApplyingInput());
592b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
593b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
59437b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Address MipsRelocator::getGP0() {
59587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return getTarget().getGP0(getApplyingInput());
59687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
59787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
59887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesFragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc,
59937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                          Relocation::DWord entryValue) {
6005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
60187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
60287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGOT& got = getTarget().getGOT();
60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(isLocalReloc(*rsym) &&
60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Attempt to get a global GOT entry for the local relocation");
60622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
60787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue);
60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Found a mapping, then return the mapped entry immediately.
61037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (got_entry != NULL)
61122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
6125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
61387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Not found.
61487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got_entry = got.consumeLocal();
61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (got.isPrimaryGOTConsumed())
617b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), NULL);
61822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
61987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got.setEntryValue(got_entry, entryValue);
62022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
62187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got.recordLocalEntry(rsym, entryValue, got_entry);
6225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *got_entry;
62487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
62637b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc) {
62787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
62887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
62987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGOT& got = getTarget().getGOT();
63087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
63187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(!isLocalReloc(*rsym) &&
63287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Attempt to get a local GOT entry for the global relocation");
63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
63487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* got_entry = got.lookupGlobalEntry(rsym);
63587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
63687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Found a mapping, then return the mapped entry immediately.
63737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (got_entry != NULL)
63887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return *got_entry;
63987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Not found.
64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got_entry = got.consumeGlobal();
6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
643f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (got.isPrimaryGOTConsumed())
644b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), rsym);
64587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got.setEntryValue(got_entry, pReloc.parent().symValue());
64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got.recordGlobalEntry(rsym, got_entry);
649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
65022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
653b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesFragment& MipsRelocator::getTLSGOTEntry(MipsRelocationInfo& pReloc) {
654b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  // rsym - The relocation target symbol
655b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
656b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  MipsGOT& got = getTarget().getGOT();
657b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
658b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  Fragment* modEntry = got.lookupTLSEntry(rsym, pReloc.type());
659b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
660b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  // Found a mapping, then return the mapped entry immediately.
661b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (modEntry != NULL)
662b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return *modEntry;
663b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
664b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  // Not found.
665b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  modEntry = got.consumeTLS(pReloc.type());
666b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  setupTLSDynEntry(*modEntry, rsym, pReloc.type());
667b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  got.recordTLSEntry(rsym, modEntry, pReloc.type());
668b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
669b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return *modEntry;
670b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
671b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
67237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc) {
67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
67487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGOT& got = getTarget().getGOT();
67587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
67687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (isLocalReloc(*rsym)) {
67787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t value = pReloc.S();
67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (ResolveInfo::Section == rsym->type())
68087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      value += pReloc.A();
68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return got.getGPRelOffset(getApplyingInput(),
68387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                              getLocalGOTEntry(pReloc, value));
68437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc));
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
689b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Address MipsRelocator::getTLSGOTOffset(MipsRelocationInfo& pReloc) {
690b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  MipsGOT& got = getTarget().getGOT();
691b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return got.getGPRelOffset(getApplyingInput(), getTLSGOTEntry(pReloc));
692b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
693b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
69437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::createDynRel(MipsRelocationInfo& pReloc) {
69587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord A = pReloc.A();
69687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord S = pReloc.S();
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
69987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
700b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (getTarget().isDynamicSymbol(*rsym)) {
701b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRel32DynEntry(pReloc.parent().targetRef(), rsym);
70287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Don't add symbol value that will be resolved by the dynamic linker.
70387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A;
704b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else {
705b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRel32DynEntry(pReloc.parent().targetRef(), NULL);
706b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    pReloc.result() = A + S;
70787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
708b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
709b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (!isLocalReloc(*rsym) && !getTarget().symbolFinalValueIsKnown(*rsym))
710b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    getGlobalGOTEntry(pReloc);
71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
71287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc) {
714b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (isN64ABI())
715b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return pHiReloc.A();
716b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_CurrentLo16Reloc != NULL &&
71887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "There is no saved R_MIPS_LO16 relocation");
7195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
72087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t AHI = pHiReloc.A() & 0xFFFF;
72187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF;
72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t AHL = (AHI << 16) + int16_t(ALO);
7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
7255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
72737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isN64ABI() const {
72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return config().targets().is64Bits();
72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
7305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
73137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t MipsRelocator::getDebugStringOffset(Relocation& pReloc) const {
73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.type() != llvm::ELF::R_MIPS_32)
73337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    error(diag::unsupport_reloc_for_debug_string)
73437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        << getName(pReloc.type()) << "mclinker@googlegroups.com";
73537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->type() == ResolveInfo::Section)
736fda4bbd63841e8ae3418637b24b7416f6bf56ca6Stephen McGroarty    return pReloc.target() + pReloc.addend();
73737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else
73837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
73937b74a387bb3993387029859c2d9d051c41c724eStephen Hines               pReloc.target() + pReloc.addend();
74037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
74137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
74237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::applyDebugStringOffset(Relocation& pReloc,
74337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                           uint32_t pOffset) {
74437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  pReloc.target() = pOffset;
74537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
74637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
747b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid MipsRelocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym,
748b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                     Relocation::Type pType) {
749b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
750b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  relEntry.setType(pType);
751b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  relEntry.targetRef() = pFragRef;
752b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  relEntry.setSymInfo(pSym);
753b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
75437b74a387bb3993387029859c2d9d051c41c724eStephen Hines
75587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
75687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips32Relocator
75787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
75887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent,
75987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                 const LinkerConfig& pConfig)
76037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : MipsRelocator(pParent, pConfig) {
76137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
76287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
763b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips32Relocator::setupRel32DynEntry(FragmentRef& pFragRef,
764b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                         ResolveInfo* pSym) {
765b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  setupRelDynEntry(pFragRef, pSym, llvm::ELF::R_MIPS_REL32);
766b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
767b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
768b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips32Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym,
769b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                       Relocation::Type pType) {
770b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pSym = pSym->isLocal() ? nullptr : pSym;
771b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (pType == llvm::ELF::R_MIPS_TLS_GD) {
772b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
773b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32);
774b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0);
775b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL32);
776b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) {
777b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
778b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32);
779b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) {
780b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
781b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL32);
782b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else {
783b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    llvm_unreachable("Unexpected relocation");
784b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  }
785b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
786b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
787b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Size Mips32Relocator::getSize(Relocation::Type pType) const {
788b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return ApplyFunctions[pType & 0xff].size;
78987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
79087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
79187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips64Relocator
79387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
79487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent,
79587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                 const LinkerConfig& pConfig)
79637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : MipsRelocator(pParent, pConfig) {
79737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
79887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
799b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips64Relocator::setupRel32DynEntry(FragmentRef& pFragRef,
800b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                         ResolveInfo* pSym) {
80137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocation::Type type = llvm::ELF::R_MIPS_REL32 | llvm::ELF::R_MIPS_64 << 8;
802b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  setupRelDynEntry(pFragRef, pSym, type);
803b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
80487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
805b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips64Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym,
806b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                       Relocation::Type pType) {
807b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pSym = pSym->isLocal() ? nullptr : pSym;
808b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (pType == llvm::ELF::R_MIPS_TLS_GD) {
809b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
810b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64);
811b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0);
812b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL64);
813b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) {
814b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
815b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64);
816b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) {
817b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
818b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL64);
819b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else {
820b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    llvm_unreachable("Unexpected relocation");
821b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  }
822b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
823b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
824b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Size Mips64Relocator::getSize(Relocation::Type pType) const {
825b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (((pType >> 16) & 0xff) != llvm::ELF::R_MIPS_NONE)
826b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return ApplyFunctions[(pType >> 16) & 0xff].size;
827b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (((pType >> 8) & 0xff) != llvm::ELF::R_MIPS_NONE)
828b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return ApplyFunctions[(pType >> 8) & 0xff].size;
829b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return ApplyFunctions[pType & 0xff].size;
8305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
8335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
8345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
8355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
83737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result none(MipsRelocationInfo& pReloc,
83837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  MipsRelocator& pParent) {
839551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
84337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result abs32(MipsRelocationInfo& pReloc,
84437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   MipsRelocator& pParent) {
84587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
84687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord A = pReloc.A();
84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord S = pReloc.S();
8495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& target_sect =
85137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.parent().targetRef().frag()->getParent()->getSection();
852affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
85337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
85437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation
855affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
85637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
85787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = S + A;
858551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
859affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
860affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
861f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & MipsRelocator::ReserveRel) {
86287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pParent.createDynRel(pReloc);
863551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
864affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S + A;
86787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
868551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
87087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_26:
87287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   local   : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
87387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   external: (sign–extend(A) + S) >> 2
87437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result rel26(MipsRelocationInfo& pReloc,
87537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   MipsRelocator& pParent) {
87687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
87787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  int32_t A = pParent.isN64ABI() ? pReloc.A() : (pReloc.A() & 0x03FFFFFF) << 2;
87987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t P = pReloc.P();
88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t S = rsym->reserved() & MipsRelocator::ReservePLT
881b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                  ? helper_get_PLT_address(*rsym, pParent)
88287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  : pReloc.S();
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
88487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->isLocal())
88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A | ((P + 4) & 0x3F000000);
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
88737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    pReloc.result() = signExtend<28>(A);
88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = (pReloc.result() + S) >> 2;
8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
891551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
89737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result hi16(MipsRelocationInfo& pReloc,
89837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  MipsRelocator& pParent) {
89987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t AHL = pParent.calcAHL(pReloc);
9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
90187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pParent.isGpDisp(pReloc.parent())) {
90287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t P = pReloc.P();
90387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t GP = pParent.getGPAddress();
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
90537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t S = pReloc.S();
90787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (pParent.isN64ABI())
90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16;
90987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
9115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
9125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
913551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16:
9175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: AHL + S
9185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : AHL + GP - P + 4
91937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result lo16(MipsRelocationInfo& pReloc,
92037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  MipsRelocator& pParent) {
92187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16
92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16
92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // addend here.
92487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t AHL = (pReloc.A() & 0xFFFF);
92587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pParent.isGpDisp(pReloc.parent())) {
92787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t P = pReloc.P();
92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t GP = pParent.getGPAddress();
92987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = AHL + GP - P + 4;
93037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t S = pReloc.S();
93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = AHL + S;
9335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
9345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.applyPostponedRelocations(pReloc);
93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
937551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
93987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
94087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GPREL16:
94187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   external: sign–extend(A) + S - GP
94287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   local   : sign–extend(A) + S + GP0 – GP
94337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc,
94437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
94587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Remember to add the section offset to A.
94687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t A = pReloc.A();
94787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t S = pReloc.S();
94887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP0 = pParent.getGP0();
94987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP = pParent.getGPAddress();
95087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
95287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->isLocal())
95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A + S + GP0 - GP;
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
95587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A + S - GP;
9565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
957551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
9615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
9625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
96337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result got16(MipsRelocationInfo& pReloc,
96437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   MipsRelocator& pParent) {
96587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pReloc.parent().symInfo()->isLocal()) {
96687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t AHL = pParent.calcAHL(pReloc);
96787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t S = pReloc.S();
96887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
9695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
97087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    MipsGOT& got = pParent.getTarget().getGOT();
9715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
97287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res);
973affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
97487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
97537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
97687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = pParent.getGOTOffset(pReloc);
9775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
9785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
979551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
980d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
981d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
982d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16:
983d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: (G - (short)G) >> 16 + A
98437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc,
98537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
98687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::Address G = pParent.getGOTOffset(pReloc);
98787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t A = pReloc.A();
988d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
98987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = (G - (int16_t)G) >> (16 + A);
990d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
991551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
992d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
993d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
994d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16:
995d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: G & 0xffff
99637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc,
99737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
99887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff;
999d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
1000551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_SUB:
100487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   external/local: S - A
100537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result sub(MipsRelocationInfo& pReloc,
100637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                 MipsRelocator& pParent) {
100787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t S = pReloc.S();
100887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t A = pReloc.A();
100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S - A;
1011d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
1012551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
10135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
10145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G
101637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result call16(MipsRelocationInfo& pReloc,
101737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    MipsRelocator& pParent) {
101887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pParent.getGOTOffset(pReloc);
10195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1020551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
10215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
10225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
102437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc,
102537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
1026affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Remember to add the section offset to A.
102787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t A = pReloc.A();
102887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t S = pReloc.S();
102987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP0 = pParent.getGP0();
103087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP = pParent.getGPAddress();
103187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
103287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = A + S + GP0 - GP;
103387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1034551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
103587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
103687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
103787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_64: S + A
103837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result abs64(MipsRelocationInfo& pReloc,
103937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   MipsRelocator& pParent) {
104087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME (simon): Consider to merge with abs32() or use the same function
104187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // but with another mask size.
104287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
104387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
104487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord A = pReloc.A();
104587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord S = pReloc.S();
104687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
104787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& target_sect =
104837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.parent().targetRef().frag()->getParent()->getSection();
104987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
105037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
105137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation
105287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // but perform static relocation. (e.g., applying .debug section)
105387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
105487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = S + A;
1055551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
105687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
105787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
105887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->reserved() & MipsRelocator::ReserveRel) {
105987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pParent.createDynRel(pReloc);
1060551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
106187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
10625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
106387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S + A;
10645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1065551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
10665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1067d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
106887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G
106937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc,
107037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
107187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pParent.getGOTOffset(pReloc);
107287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1073551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
107487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
107587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
107687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GOT_OFST:
107737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc,
107837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    MipsRelocator& pParent) {
107987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME (simon): Needs to be implemented.
1080551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
108187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
108287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
108387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_JALR:
108437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result jalr(MipsRelocationInfo& pReloc,
108537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  MipsRelocator& pParent) {
1086551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
108787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
108887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1089b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC16
1090b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc16(MipsRelocationInfo& pReloc,
1091b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                  MipsRelocator& pParent) {
1092b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t A = signExtend<18>(pReloc.A() << 2);
1093b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1094b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1095b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = (A + S - P) >> 2;
1096b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1097b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
1098b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
1099b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC32
1100b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc32(MipsRelocationInfo& pReloc,
1101b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                  MipsRelocator& pParent) {
1102b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t A = pReloc.A();
1103b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1104b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1105b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = A + S - P;
1106b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1107b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
1108b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
1109b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC18_S3
1110b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc18_s3(MipsRelocationInfo& pReloc,
1111b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                     MipsRelocator& pParent) {
1112b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t A = signExtend<21>(pReloc.A() << 3);
1113b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1114b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1115b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = (S + A - ((P | 7) ^ 7)) >> 3;
1116b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1117b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
1118b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
1119b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC19_S2
1120b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc19_s2(MipsRelocationInfo& pReloc,
1121b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                     MipsRelocator& pParent) {
1122b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t A = signExtend<21>(pReloc.A() << 2);
1123b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1124b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1125b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = (A + S - P) >> 2;
1126b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1127b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
1128b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
1129b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC21_S2
1130b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc21_s2(MipsRelocationInfo& pReloc,
113137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
1132b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int32_t A = signExtend<23>(pReloc.A() << 2);
113387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t S = pReloc.S();
1134b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int32_t P = pReloc.P();
1135b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = (A + S - P) >> 2;
1136b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1137b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
1138b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
1139b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC26_S2
1140b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc26_s2(MipsRelocationInfo& pReloc,
1141b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                     MipsRelocator& pParent) {
1142b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t A = signExtend<28>(pReloc.A() << 2);
1143b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1144b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1145b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = (A + S - P) >> 2;
1146b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1147b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
114887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1149b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PCHI16
1150b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pchi16(MipsRelocationInfo& pReloc,
1151b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                    MipsRelocator& pParent) {
1152b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  uint64_t AHL = pParent.calcAHL(pReloc);
1153b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1154b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1155b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = (S + AHL - P + 0x8000) >> 16;
1156b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return Relocator::OK;
1157b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
115887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1159b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PCLO16
1160b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pclo16(MipsRelocationInfo& pReloc,
1161b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                    MipsRelocator& pParent) {
1162b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int32_t AHL = pReloc.A() & 0xFFFF;
1163b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t S = pReloc.S();
1164b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  int64_t P = pReloc.P();
1165b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = S + AHL - P;
1166b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pParent.applyPostponedRelocations(pReloc);
1167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
116887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
116987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1170b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_DTPREL_HI16
1171b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines//   local/external: (A + S - TP Offset) >> 16
1172b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines//   _gp_disp      : (A + GP - P - TP Offset) >> 16
1173b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result tlshi16(MipsRelocationInfo& pReloc,
1174b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                     MipsRelocator& pParent) {
1175b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  uint64_t A = pReloc.A() & 0xFFFF;
1176b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_HI16)
1177b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    A -= pParent.getTPOffset();
1178b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_HI16)
1179b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    A -= pParent.getDTPOffset();
1180b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  else
1181b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    llvm_unreachable("Unexpected relocation");
118287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1183b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (pParent.isGpDisp(pReloc.parent()))
1184b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    pReloc.result() = (A + pReloc.S() - pReloc.P() + 0x8000) >> 16;
1185b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  else
1186b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    pReloc.result() = (A + pReloc.S() + 0x8000) >> 16;
118787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1188551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
118987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
119087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1191b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_DTPREL_LO16
1192b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines//   local/external: A + S - TP Offset
1193b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines//   _gp_disp      : A + GP - P + 4 - TP Offset
1194b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result tlslo16(MipsRelocationInfo& pReloc,
119537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MipsRelocator& pParent) {
1196b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  uint64_t A = pReloc.A() & 0xFFFF;
1197b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_LO16)
1198b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    A -= pParent.getTPOffset();
1199b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_LO16)
1200b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    A -= pParent.getDTPOffset();
1201b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  else
1202b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    llvm_unreachable("Unexpected relocation");
1203b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
1204b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (pParent.isGpDisp(pReloc.parent()))
1205b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    pReloc.result() = A + pReloc.S() - pReloc.P() + 4;
1206b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  else
1207b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    pReloc.result() = A + pReloc.S();
120887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
121087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
121187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1212b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_TLS_GD, R_MIPS_TLS_LDM
1213b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result tlsgot(MipsRelocationInfo& pReloc,
1214b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                    MipsRelocator& pParent) {
1215b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  pReloc.result() = pParent.getTLSGOTOffset(pReloc);
1216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
121787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
121887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
121937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result unsupported(MipsRelocationInfo& pReloc,
122037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         MipsRelocator& pParent) {
122137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return Relocator::Unsupported;
122287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
122337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
122437b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
1225