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
1287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/IRBuilder.h>
1387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LinkerConfig.h>
1487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/Object/ObjectBuilder.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Target/OutputRelocSection.h>
1787f34658dec9097d987d254a990ea7f311bfc95fStephen 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
2287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace llvm {
2387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace ELF {
2487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// FIXME: Consider upstream these relocation types to LLVM.
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesenum {
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  R_MIPS_LA25_LUI = 200,
2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  R_MIPS_LA25_J   = 201,
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  R_MIPS_LA25_ADD = 202,
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} // end namespace ELF
3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} // end namespace llvm
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// MipsRelocationInfo
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesclass mcld::MipsRelocationInfo
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinespublic:
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  static bool HasSubType(const Relocation& pParent, Relocation::Type pType)
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (llvm::ELF::R_MIPS_NONE == pType)
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return true;
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (Relocation::Type type = pParent.type();
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         llvm::ELF::R_MIPS_NONE != (type & 0xff); type >>= 8) {
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if ((type & 0xff) == pType)
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return true;
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsRelocationInfo(Relocation& pParent, bool pIsRel)
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    : m_Parent(&pParent),
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Type(pParent.type()),
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Addend(0),
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Symbol(pParent.symValue()),
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Result(pParent.target())
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (pIsRel && (type() < llvm::ELF::R_MIPS_LA25_LUI ||
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   type() > llvm::ELF::R_MIPS_LA25_ADD))
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Addend = pParent.target();
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Addend = pParent.addend();
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool isNone() const
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return llvm::ELF::R_MIPS_NONE == type();
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool isLast() const
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return llvm::ELF::R_MIPS_NONE == (m_Type >> 8);
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsRelocationInfo next() const
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result(), 0);
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const Relocation& parent() const
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return *m_Parent;
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& parent()
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return *m_Parent;
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::Type type() const
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_Type & 0xff;
9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord A() const
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_Addend;
10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord S() const
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_Symbol;
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord P() const
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return parent().place();
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord result() const
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_Result;
11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord& result()
12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_Result;
12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesprivate:
12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation* m_Parent;
12887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::Type m_Type;
12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord m_Addend;
13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord m_Symbol;
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::DWord m_Result;
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsRelocationInfo(Relocation& pParent, Relocation::Type pType,
13487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     Relocation::DWord pResult,
13587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     Relocation::DWord pAddend, Relocation::DWord pSymbol)
13687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    : m_Parent(&pParent),
13787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Type(pType),
13887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Addend(pAddend),
13987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Symbol(pSymbol),
14087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Result(pResult)
14187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {}
14287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool isFirst() const {
14487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_Type == parent().type();
14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
14687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
14787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
14967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
15067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinestypedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&,
15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               MipsRelocator& pParent);
15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
15867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
15967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
16067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
16167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
16267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
16367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
1646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
16567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
16667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
16767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
16867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
16967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_MIPS_APPLY_RELOC_FUNC_PTRS
17067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
17167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
17267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
173d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator
17467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent,
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                             const LinkerConfig& pConfig)
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : Relocator(pConfig),
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent),
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pApplyingInput(NULL),
18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_CurrentLo16Reloc(NULL)
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
184d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result
18587f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::applyRelocation(Relocation& pReloc)
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // If m_CurrentLo16Reloc is not NULL we are processing
18887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // postponed relocation. Otherwise check relocation type
18987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // and postpone it for later handling.
19087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == m_CurrentLo16Reloc && isPostponed(pReloc)) {
19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    postponeRelocation(pReloc);
19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return OK;
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (MipsRelocationInfo info(pReloc, isRel());
19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       !info.isNone(); info = info.next()) {
19787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0]))
19887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return Unknown;
19987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const ApplyFunctionTriple & triple = ApplyFunctions[info.type()];
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Result res = triple.func(info, *this);
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (OK != res)
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return res;
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (info.isLast()) {
20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size);
20887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.target() &= ~mask;
20987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.target() |= info.result() & mask;
21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
21387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return OK;
21467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
216d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* MipsRelocator::getName(Relocation::Type pType) const
21767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return ApplyFunctions[pType & 0xff].name;
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size MipsRelocator::getSize(Relocation::Type pType) const
2226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return ApplyFunctions[pType & 0xff].size;
2246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanRelocation(Relocation& pReloc,
227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   Module& pModule,
22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                   LDSection& pSection,
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                   Input& pInput)
231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Skip relocation against _gp_disp
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL != getTarget().getGpDispSymbol() &&
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym == getTarget().getGpDispSymbol()->resolveInfo())
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != pSection.getLink());
242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (MipsRelocationInfo info(pReloc, isRel());
24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       !info.isNone(); info = info.next()) {
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // We test isLocal or if pInputSym is not a dynamic symbol
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Don't put undef symbols into local entries.
25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (isLocalReloc(*rsym))
25187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      scanLocalReloc(info, pBuilder, pSection);
25287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
25387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      scanGlobalReloc(info, pBuilder, pSection);
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo()))
25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getTarget().addNonPICBranchSym(pReloc.symInfo());
25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
25987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Check if we should issue undefined reference
26087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // for the relocation target symbol.
261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
26287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    issueUndefRef(pReloc, pSection, pInput);
263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::initializeScan(Input& pInput)
266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object != config().codeGenType())
26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    getTarget().getGOT().initializeScan(pInput);
269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::finalizeScan(Input& pInput)
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object != config().codeGenType())
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    getTarget().getGOT().finalizeScan(pInput);
276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::initializeApply(Input& pInput)
280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pApplyingInput = &pInput;
282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::finalizeApply(Input& pInput)
286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pApplyingInput = NULL;
288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
29187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc,
292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   const LDSection& pSection)
294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch (pReloc.type()){
298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_NONE:
299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_16:
300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_32:
30287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_64:
303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // section if the symbol section flags contains SHF_EXECINSTR.
306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // 1. Find the reason of this condition.
307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // 2. Check this condition here.
308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL32:
314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_26:
315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HI16:
316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LO16:
317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PC16:
318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT5:
319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT6:
320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SUB:
321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_A:
322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_B:
323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_DELETE:
324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHER:
325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHEST:
326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SCN_DISP:
327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL16:
328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PJUMP:
330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_RELGOT:
331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JALR:
332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GLOB_DAT:
333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_COPY:
334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JUMP_SLOT:
335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT16:
337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL16:
338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_HI16:
339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_HI16:
340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_LO16:
341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_LO16:
34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_GOT_DISP:
34387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_GOT_PAGE:
34487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_GOT_OFST:
34587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (getTarget().getGOT().reserveLocalEntry(*rsym,
34687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                 pReloc.type(), pReloc.A())) {
347f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().getGOT().hasMultipleGOT())
348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL32:
352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL16:
353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LITERAL:
354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL32:
357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL64:
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GD:
360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_LDM:
361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL32:
365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL64:
366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
36987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_PC32:
37087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
37287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name();
373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
37687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc,
377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                    IRBuilder& pBuilder,
378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                    const LDSection& pSection)
379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
38087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch (pReloc.type()){
383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_NONE:
384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_A:
385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_B:
386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_DELETE:
387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL64:
389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL16:
390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PJUMP:
392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_RELGOT:
393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL64:
394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_32:
396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_64:
397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HI16:
398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LO16:
399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, false, true)) {
400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) {
40287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym);
40387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          addCopyReloc(*cpySym.resolveInfo());
40487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        else {
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // set Rel bit
40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
40887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT16:
413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL16:
414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_DISP:
415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_HI16:
416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_HI16:
417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_LO16:
418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_LO16:
419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_PAGE:
420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_OFST:
421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().getGOT().hasMultipleGOT())
423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LITERAL:
427f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL32:
428f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::invalid_global_relocation) << (int)pReloc.type()
42987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             << rsym->name();
430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL16:
432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_26:
43487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Create a PLT entry if the symbol requires it and does not have it.
43587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
43687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          !(rsym->reserved() & ReservePLT)) {
43787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getTarget().getPLT().reserveEntry();
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getTarget().getGOTPLT().reserve();
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getTarget().getRelPLT().reserveEntry();
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rsym->setReserved(rsym->reserved() | ReservePLT);
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PC16:
444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_16:
446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT5:
447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT6:
448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SUB:
449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHER:
450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHEST:
451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SCN_DISP:
452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL32:
454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GD:
455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_LDM:
456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL32:
460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
463f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL32:
464f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JALR:
46587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_MIPS_PC32:
466f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
467f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_COPY:
468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GLOB_DAT:
469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JUMP_SLOT:
470f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::dynamic_relocation) << (int)pReloc.type();
471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
472f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
47387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name();
474f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
476f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsRelocator::isPostponed(const Relocation& pReloc) const
47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16))
48087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
4815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
48287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) &&
48387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.symInfo()->isLocal())
48487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
48587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return false;
48787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
48887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
48987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::addCopyReloc(ResolveInfo& pSym)
4905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
49187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
49287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setType(llvm::ELF::R_MIPS_COPY);
49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(pSym.outSymbol()->hasFragRef());
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.targetRef().assign(*pSym.outSymbol()->fragRef());
49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setSymInfo(&pSym);
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
4975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
49887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesLDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
49987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                  const ResolveInfo& pSym)
50087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
50187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Get or create corresponding BSS LDSection
50287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* fileFormat = getTarget().getOutputFormat();
50387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection* bssSectHdr =
50487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ResolveInfo::ThreadLocal == pSym.type() ? &fileFormat->getTBSS()
50587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                            : &fileFormat->getBSS();
50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Get or create corresponding BSS SectionData
50887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData* bssData =
50987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bssSectHdr->hasSectionData() ? bssSectHdr->getSectionData()
51087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                 : IRBuilder::CreateSectionData(*bssSectHdr);
51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Determine the alignment by the symbol value
51387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: here we use the largest alignment
51487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t addrAlign = config().targets().bitclass() / 8;
51587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Allocate space in BSS for the copy symbol
51787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
51887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign);
51987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bssSectHdr->setSize(bssSectHdr->size() + size);
52087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Change symbol binding to Global if it's a weak symbol
52287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
52387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (binding == ResolveInfo::Weak)
52487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    binding = ResolveInfo::Global;
52587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Define the copy symbol in the bss section and resolve it
52787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
52887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      pSym.name(),
52987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      (ResolveInfo::Type)pSym.type(),
53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      ResolveInfo::Define,
53187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      binding,
53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      pSym.size(),  // size
53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      0x0,          // value
53487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      FragmentRef::Create(*frag, 0x0),
53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                      (ResolveInfo::Visibility)pSym.other());
53687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
53787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Output all other alias symbols if any
53887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym);
53987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == alias_list)
54087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return *cpySym;
54187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end();
54387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       it != ie; ++it) {
54487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const ResolveInfo* alias = *it;
54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (alias == &pSym || !alias->isDyn())
54687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      continue;
54787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
54887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
54987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        alias->name(),
55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (ResolveInfo::Type)alias->type(),
55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ResolveInfo::Define,
55287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        binding,
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        alias->size(),  // size
55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        0x0,            // value
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        FragmentRef::Create(*frag, 0x0),
55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (ResolveInfo::Visibility)alias->other());
5575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
55887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *cpySym;
5605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::postponeRelocation(Relocation& pReloc)
5635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
56487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
56587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_PostponedRelocs[rsym].insert(&pReloc);
5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
56887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc)
5695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
57087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_CurrentLo16Reloc = &pLo16Reloc;
57187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
57287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pLo16Reloc.parent().symInfo();
57387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
57487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  RelocationSet & relocs = m_PostponedRelocs[rsym];
57587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it)
57687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    (*it)->apply(*this);
57787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
57887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_PostponedRelocs.erase(rsym);
57987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
58087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_CurrentLo16Reloc = NULL;
5815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsRelocator::isGpDisp(const Relocation& pReloc) const
584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 0 == strcmp("_gp_disp", pReloc.symInfo()->name());
58687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
58887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsRelocator::isRel() const
58987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
59087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return config().targets().is32Bits();
591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
592f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
59387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const
59487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
59587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSym.isUndef())
59687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
59787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
59887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pSym.isLocal() ||
59987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         !getTarget().isDynamicSymbol(pSym) ||
60087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         !pSym.isDyn();
60187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
60287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60387f34658dec9097d987d254a990ea7f311bfc95fStephen HinesRelocator::Address MipsRelocator::getGPAddress()
60487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return getTarget().getGOT().getGPAddr(getApplyingInput());
60687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
60787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesRelocator::Address MipsRelocator::getGP0()
60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
61087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return getTarget().getGP0(getApplyingInput());
61187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
61287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
61387f34658dec9097d987d254a990ea7f311bfc95fStephen HinesFragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc,
61487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                          Relocation::DWord entryValue)
6155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
61787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
61887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGOT& got = getTarget().getGOT();
61987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
62087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(isLocalReloc(*rsym) &&
62187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Attempt to get a global GOT entry for the local relocation");
62222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue);
62487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Found a mapping, then return the mapped entry immediately.
62687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL != got_entry)
62722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
6285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
62987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Not found.
63087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got_entry = got.consumeLocal();
63187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
63287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (got.isPrimaryGOTConsumed())
63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), NULL);
63422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
63587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got.setEntryValue(got_entry, entryValue);
63622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
63787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got.recordLocalEntry(rsym, entryValue, got_entry);
6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
63987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *got_entry;
64087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64287f34658dec9097d987d254a990ea7f311bfc95fStephen HinesFragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc)
64387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
64487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
64587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGOT& got = getTarget().getGOT();
64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(!isLocalReloc(*rsym) &&
64987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Attempt to get a local GOT entry for the global relocation");
65087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
65187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* got_entry = got.lookupGlobalEntry(rsym);
65287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
65387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Found a mapping, then return the mapped entry immediately.
65487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL != got_entry)
65587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return *got_entry;
65687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
65787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Not found.
65887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got_entry = got.consumeGlobal();
6595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (got.isPrimaryGOTConsumed())
66187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), rsym);
66287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
66387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got.setEntryValue(got_entry, pReloc.parent().symValue());
66487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
66587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got.recordGlobalEntry(rsym, got_entry);
666f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
66722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
6685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
67087f34658dec9097d987d254a990ea7f311bfc95fStephen HinesRelocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc)
6715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
67287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGOT& got = getTarget().getGOT();
67487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
67587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (isLocalReloc(*rsym)) {
67687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t value = pReloc.S();
67787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (ResolveInfo::Section == rsym->type())
67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      value += pReloc.A();
68087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return got.getGPRelOffset(getApplyingInput(),
68287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                              getLocalGOTEntry(pReloc, value));
68387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
68487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc));
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
68987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::createDynRel(MipsRelocationInfo& pReloc)
69087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
69187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord A = pReloc.A();
69287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord S = pReloc.S();
69387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
69587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (isLocalReloc(*rsym)) {
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    setupRelDynEntry(pReloc.parent().targetRef(), NULL);
69887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A + S;
69987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
70087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
70187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    setupRelDynEntry(pReloc.parent().targetRef(), rsym);
70287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Don't add symbol value that will be resolved by the dynamic linker.
70387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A;
70487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
70587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
70687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
70787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc)
7085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
70987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_CurrentLo16Reloc &&
71087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "There is no saved R_MIPS_LO16 relocation");
7115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
71287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t AHI = pHiReloc.A() & 0xFFFF;
71387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF;
71487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t AHL = (AHI << 16) + int16_t(ALO);
7155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
7175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
71987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsRelocator::isN64ABI() const
7205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
72187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return config().targets().is64Bits();
72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
72487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t MipsRelocator::getPLTAddress(ResolveInfo& rsym)
72587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
72687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert((rsym.reserved() & MipsRelocator::ReservePLT) &&
72787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Symbol does not require a PLT entry");
7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SymPLTMap::const_iterator it = m_SymPLTMap.find(&rsym);
730affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
73187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* plt;
732affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
73387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (it != m_SymPLTMap.end()) {
73487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    plt = it->second.first;
735affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
736affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
73787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    plt = getTarget().getPLT().consume();
73887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
73987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Fragment* got = getTarget().getGOTPLT().consume();
74087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Relocation* rel = getTarget().getRelPLT().consumeEntry();
74187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel->setType(llvm::ELF::R_MIPS_JUMP_SLOT);
74387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel->targetRef().assign(*got);
74487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel->setSymInfo(&rsym);
74587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_SymPLTMap[&rsym] = PLTDescriptor(plt, got);
747affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
74887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return getTarget().getPLT().addr() + plt->getOffset();
75087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
75187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
75287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
75387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips32Relocator
75487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
75587f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent,
75687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                 const LinkerConfig& pConfig)
75787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  : MipsRelocator(pParent, pConfig)
75887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{}
75987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
76087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Mips32Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym)
76187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
76287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
76387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setType(llvm::ELF::R_MIPS_REL32);
76487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.targetRef() = pFragRef;
76587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setSymInfo(pSym);
76687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
76887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
76987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips64Relocator
77087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
77187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent,
77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                 const LinkerConfig& pConfig)
77387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  : MipsRelocator(pParent, pConfig)
77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{}
77587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Mips64Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym)
77787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
77887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation::Type type = llvm::ELF::R_MIPS_REL32 |
77987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                          llvm::ELF::R_MIPS_64 << 8;
78087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME (simon): Fix dynamic relocations.
78187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  type = llvm::ELF::R_MIPS_NONE;
78287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
78387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
78487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setType(type);
78587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.targetRef() = pFragRef;
78687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  relEntry.setSymInfo(pSym);
7875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
7905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
7915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
7925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
7945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
79587f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result none(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
7965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
797551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
7985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
8015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
80287f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result abs32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
8035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
80487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
80587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
80687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord A = pReloc.A();
80787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord S = pReloc.S();
8085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
80987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& target_sect =
81087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.parent().targetRef().frag()->getParent()->getSection();
811affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
812affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
813affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
81422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
81587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = S + A;
816551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
817affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
818affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
819f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & MipsRelocator::ReserveRel) {
82087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pParent.createDynRel(pReloc);
821551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
822affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
8235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
82487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S + A;
82587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
826551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
82787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
82887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
82987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_26:
83087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   local   : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
83187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   external: (sign–extend(A) + S) >> 2
83287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
83387f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result rel26(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
83487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
83587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
83687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
83787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t A = ((pReloc.parent().target() & 0x03FFFFFF) << 2);
83887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t P = pReloc.P();
83987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t S = rsym->reserved() & MipsRelocator::ReservePLT
84087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  ? pParent.getPLTAddress(*rsym)
84187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  : pReloc.S();
84287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->isLocal())
84487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A | ((P + 4) & 0x3F000000);
84587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
84687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = mcld::signExtend<28>(A);
84787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = (pReloc.result() + S) >> 2;
8495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
850551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
8545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
8555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
8565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
85787f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result hi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t AHL = pParent.calcAHL(pReloc);
8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
86187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pParent.isGpDisp(pReloc.parent())) {
86287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t P = pReloc.P();
86387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t GP = pParent.getGPAddress();
86487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
86787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t S = pReloc.S();
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (pParent.isN64ABI())
86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16;
87087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
8725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
874551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16:
8785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: AHL + S
8795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : AHL + GP - P + 4
8805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
88187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result lo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
8825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16
88487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16
88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // addend here.
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t AHL = (pReloc.A() & 0xFFFF);
88787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pParent.isGpDisp(pReloc.parent())) {
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t P = pReloc.P();
89087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t GP = pParent.getGPAddress();
89187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = AHL + GP - P + 4;
8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
89487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t S = pReloc.S();
89587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = AHL + S;
8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
89887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.applyPostponedRelocations(pReloc);
89987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
900551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
90187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
90287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GPREL16:
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   external: sign–extend(A) + S - GP
90587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   local   : sign–extend(A) + S + GP0 – GP
90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
90787f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result gprel16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
90987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Remember to add the section offset to A.
91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t A = pReloc.A();
91187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t S = pReloc.S();
91287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP0 = pParent.getGP0();
91387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP = pParent.getGPAddress();
91487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
91687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->isLocal())
91787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A + S + GP0 - GP;
91887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = A + S - GP;
9205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
921551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
9255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
9265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
9275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
92887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result got16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
9295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
93087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pReloc.parent().symInfo()->isLocal()) {
93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t AHL = pParent.calcAHL(pReloc);
93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t S = pReloc.S();
93387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
9345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    MipsGOT& got = pParent.getTarget().getGOT();
9365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res);
938affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
93987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
940affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
941affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
94287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = pParent.getGOTOffset(pReloc);
9435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
9445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
945551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
946d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
947d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
948d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16:
949d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: (G - (short)G) >> 16 + A
950d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic
95187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result gothi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
952d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::Address G = pParent.getGOTOffset(pReloc);
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t A = pReloc.A();
955d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = (G - (int16_t)G) >> (16 + A);
957d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
958551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
959d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
960d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
961d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16:
962d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: G & 0xffff
963d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic
96487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
965d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
96687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff;
967d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
968551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
96987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
97087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_SUB:
97287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//   external/local: S - A
97387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
97487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result sub(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
97587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
97687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t S = pReloc.S();
97787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t A = pReloc.A();
97887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S - A;
980d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
981551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G
9855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
98687f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result call16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
9875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
98887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pParent.getGOTOffset(pReloc);
9895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
990551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
9945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
99587f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result gprel32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
9965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
997affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Remember to add the section offset to A.
99887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t A = pReloc.A();
99987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t S = pReloc.S();
100087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP0 = pParent.getGP0();
100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t GP = pParent.getGPAddress();
100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = A + S + GP0 - GP;
100487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1005551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
100687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
100787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_64: S + A
100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
101087f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result abs64(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
101187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
101287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME (simon): Consider to merge with abs32() or use the same function
101387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // but with another mask size.
101487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.parent().symInfo();
101587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord A = pReloc.A();
101787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord S = pReloc.S();
101887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& target_sect =
102087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.parent().targetRef().frag()->getParent()->getSection();
102187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
102287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
102387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // but perform static relocation. (e.g., applying .debug section)
102487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
102587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.result() = S + A;
1026551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
102787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
102887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
102987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->reserved() & MipsRelocator::ReserveRel) {
103087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pParent.createDynRel(pReloc);
1031551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
103287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
10335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
103487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S + A;
10355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1036551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
10375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1038d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
103987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G
104087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
104187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
104287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
104387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pParent.getGOTOffset(pReloc);
104487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1045551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
104687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
104787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
104887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GOT_OFST:
104987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
105087f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result gotoff(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
105187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
105287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME (simon): Needs to be implemented.
1053551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
105487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
105587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
105687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_JALR:
105787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
105887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result jalr(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
105987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
1060551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
106187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
106287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
106387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_LA25_LUI
106487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
106587f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result la25lui(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
106687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
106787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t S = pReloc.S();
106887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
106987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = (S + 0x8000) >> 16;
107087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1071551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
107287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
107387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
107487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_LA25_J
107587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
107687f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result la25j(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
107787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
107887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t S = pReloc.S();
107987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
108087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = S >> 2;
108187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1082551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
108387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
108487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
108587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_LA25_ADD
108687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
108787f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result la25add(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
108887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
108987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.result() = pReloc.S();
109087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1091551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
109287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
109387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
109487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_PC32:
109587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
109687f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result pc32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
109787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
1098551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
109987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
110087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
110187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
110287f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsRelocator::Result unsupport(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
110387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
1104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::Unsupport;
110587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
1106