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//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Target/OutputRelocSection.h>
14f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LinkerConfig.h>
15f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/IRBuilder.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
17d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.h"
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.h"
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
28d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&);
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_MIPS_APPLY_RELOC_FUNC_PTRS
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator
4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent,
48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                             const LinkerConfig& pConfig)
49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : Relocator(pConfig),
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent),
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pApplyingInput(NULL),
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_AHL(0)
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
56d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result
57d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::applyRelocation(Relocation& pRelocation)
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return ApplyFunctions[type].func(pRelocation, *this);
6767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
69d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* MipsRelocator::getName(Relocation::Type pType) const
7067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
7167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size MipsRelocator::getSize(Relocation::Type pType) const
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return ApplyFunctions[pType].size;
776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanRelocation(Relocation& pReloc,
80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   Module& pModule,
82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   LDSection& pSection)
83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Skip relocation against _gp_disp
89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (NULL != getTarget().getGpDispSymbol()) {
90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (pReloc.symInfo() == getTarget().getGpDispSymbol()->resolveInfo())
91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.updateAddend();
95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != pSection.getLink());
97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // We test isLocal or if pInputSym is not a dynamic symbol
101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Don't put undef symbols into local entries.
103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((rsym->isLocal() || !getTarget().isDynamicSymbol(*rsym) ||
104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      !rsym->isDyn()) && !rsym->isUndef())
105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanLocalReloc(pReloc, pBuilder, pSection);
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanGlobalReloc(pReloc, pBuilder, pSection);
108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // check if we shoule issue undefined reference for the relocation target
110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol
111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    fatal(diag::undefined_reference) << rsym->name();
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::initializeScan(Input& pInput)
116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  getTarget().getGOT().initializeScan(pInput);
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::finalizeScan(Input& pInput)
122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  getTarget().getGOT().finalizeScan(pInput);
124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::initializeApply(Input& pInput)
128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pApplyingInput = &pInput;
130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::finalizeApply(Input& pInput)
134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pApplyingInput = NULL;
136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
139f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanLocalReloc(Relocation& pReloc,
140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   const LDSection& pSection)
142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch (pReloc.type()){
146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_NONE:
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_16:
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_32:
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // section if the symbol section flags contains SHF_EXECINSTR.
153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // 1. Find the reason of this condition.
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // 2. Check this condition here.
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // Remeber this rsym is a local GOT entry (as if it needs an entry).
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // Actually we don't allocate an GOT entry.
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getGOT().setLocal(rsym);
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL32:
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_26:
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HI16:
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LO16:
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PC16:
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT5:
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT6:
171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_64:
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_PAGE:
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_OFST:
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SUB:
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_A:
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_B:
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_DELETE:
178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHER:
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHEST:
180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SCN_DISP:
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL16:
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PJUMP:
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_RELGOT:
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JALR:
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GLOB_DAT:
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_COPY:
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JUMP_SLOT:
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT16:
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL16:
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_HI16:
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_HI16:
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_LO16:
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_LO16:
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().getGOT().reserveLocalEntry(*rsym)) {
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().getGOT().hasMultipleGOT())
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // Remeber this rsym is a local GOT entry
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getGOT().setLocal(rsym);
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL32:
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL16:
205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LITERAL:
206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_DISP:
207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL32:
210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL64:
212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GD:
213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_LDM:
214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL32:
218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL64:
219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::unknown_relocation) << (int)pReloc.type()
224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      << pReloc.symInfo()->name();
225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanGlobalReloc(Relocation& pReloc,
229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                    IRBuilder& pBuilder,
230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                    const LDSection& pSection)
231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch (pReloc.type()){
235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_NONE:
236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_A:
237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_INSERT_B:
238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_DELETE:
239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL64:
241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL16:
242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PJUMP:
244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_RELGOT:
245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL64:
246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_32:
248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_64:
249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HI16:
250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LO16:
251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, false, true)) {
252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // Remeber this rsym is a global GOT entry (as if it needs an entry).
257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // Actually we don't allocate an GOT entry.
258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getGOT().setGlobal(rsym);
259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT16:
262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL16:
263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_DISP:
264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_HI16:
265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_HI16:
266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_LO16:
267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_CALL_LO16:
268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_PAGE:
269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GOT_OFST:
270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().getGOT().hasMultipleGOT())
272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // Remeber this rsym is a global GOT entry
274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getGOT().setGlobal(rsym);
275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_LITERAL:
278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL32:
279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::invalid_global_relocation) << (int)pReloc.type()
280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                             << pReloc.symInfo()->name();
281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GPREL16:
283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_26:
285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_PC16:
286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_16:
288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT5:
289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SHIFT6:
290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SUB:
291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHER:
292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_HIGHEST:
293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_SCN_DISP:
294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL32:
296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GD:
297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_LDM:
298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL32:
302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_REL32:
306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JALR:
308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_COPY:
310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_GLOB_DAT:
311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_MIPS_JUMP_SLOT:
312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::dynamic_relocation) << (int)pReloc.type();
313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::unknown_relocation) << (int)pReloc.type()
316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      << pReloc.symInfo()->name();
317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
32067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
32167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
32267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp";
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc.
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc)
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (NULL != reloc)
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        reloc->symInfo() == pReloc.symInfo())
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return reloc;
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reloc = static_cast<Relocation*>(reloc->getNextNode());
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp.
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc)
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const ResolveInfo* rsym = pReloc.symInfo();
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0 == strcmp(GP_DISP_NAME, rsym->name());
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
350d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGP(MipsRelocator& pParent)
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return pParent.getTarget().getGOT().getGPAddr(pParent.getApplyingInput());
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid helper_SetupRelDynForGOTEntry(MipsGOTEntry& got_entry,
357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   Relocation& pReloc,
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   ResolveInfo* rsym,
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   MipsRelocator& pParent)
360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGNULDBackend& ld_backend = pParent.getTarget();
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.targetRef() = *FragmentRef::Create(got_entry, 0);
366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setSymInfo(rsym);
367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstatic
370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc, MipsRelocator& pParent)
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
375affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGOTEntry* got_entry;
3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
37822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) {
37922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // Local section symbols consume local got entries.
380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    got_entry = got.consumeLocal();
381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (got.isPrimaryGOTConsumed())
382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      helper_SetupRelDynForGOTEntry(*got_entry, pReloc, NULL, pParent);
383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return *got_entry;
38422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
38522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  got_entry = got.lookupEntry(rsym);
38722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != got_entry) {
38822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // found a mapping, then return the mapped entry immediately
38922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
39022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
39222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
39322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (got.isLocal(rsym))
39422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = got.consumeLocal();
39522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
39622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = got.consumeGlobal();
39722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  got.recordEntry(rsym, got_entry);
3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!got.isLocal(rsym) || ResolveInfo::Section != rsym->type()) {
402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (!got.isPrimaryGOTConsumed())
403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      got_entry->setValue(pReloc.symValue());
4045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (got.isPrimaryGOTConsumed())
407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_SetupRelDynForGOTEntry(*got_entry, pReloc,
408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  got.isLocal(rsym) ? NULL : rsym, pParent);
409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
414d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGOTOffset(Relocation& pReloc,
415d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                       MipsRelocator& pParent)
4165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGNULDBackend& ld_backend = pParent.getTarget();
418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGOT& got = ld_backend.getGOT();
419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
4275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
4285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         "Incorrect type of relocation for AHL calculation");
4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Note the addend is section symbol offset here
4325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert (pHiReloc.addend() == pLoReloc.addend());
4335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHI = pHiReloc.target();
4355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t ALO = pLoReloc.target();
43622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) +
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 pLoReloc.addend();
4385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
4395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
442d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, MipsRelocator& pParent)
4435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
4455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
446affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
4475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
4495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
4515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
452affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
453d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
454d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
455affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
456affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (got.isLocal(rsym)) {
457affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(NULL);
458affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A + S;
459affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
460affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
461affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(rsym);
462affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Don't add symbol value that will be resolved by the dynamic linker
463affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A;
464affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
4655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
4695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
4705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
473d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent)
4745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
475d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
4765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
4795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
480d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent)
4815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
484d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
485d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
486affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
488affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
489affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
49022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
491affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
492d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return MipsRelocator::OK;
493affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
494affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & MipsRelocator::ReserveRel) {
4965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, pParent);
4975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
498d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return MipsRelocator::OK;
499affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
501affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = (S + A);
5025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
503d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
5045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
5085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
5095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
510d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& pParent)
5115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
5125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
5135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
5145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
5165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
5175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pParent.setAHL(AHL);
5195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t P = pReloc.place();
5225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
5235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
5245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
5265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
5275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
5285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
5315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
5325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
533d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
5345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16:
5375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: AHL + S
5385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : AHL + GP - P + 4
5395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
540d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent)
5415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
5425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t P = pReloc.place();
5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
547affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t AHL = pParent.getAHL();
5485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = AHL + GP - P + 4;
5495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
552affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // The previous AHL may be for other hi/lo pairs.
553affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // We need to calcuate the lo part now.  It is easy.
554affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Remember to add the section offset to ALO.
555affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
556affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    res = ALO + S;
5575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
5605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
562d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
5635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
5685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
569d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent)
5705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGNULDBackend& ld_backend = pParent.getTarget();
572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  MipsGOT& got = ld_backend.getGOT();
5735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
574d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = 0;
5755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->isLocal()) {
5775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
5785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16");
5795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
5815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pParent.setAHL(AHL);
5845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
587affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
588d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry.setValue(res);
589f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    G = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
590affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
591affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
592affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    G = helper_GetGOTOffset(pReloc, pParent);
5935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
5965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
5975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
598d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
599d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
600d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
601d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16:
602d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: (G - (short)G) >> 16 + A
603d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic
604d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent)
605d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
606d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  int32_t res = 0;
607d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
608d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
609d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  int32_t A = pReloc.target() + pReloc.addend();
610d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
611d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  res = (G - (int16_t)G) >> (16 + A);
612d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
613d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
614d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
615d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
616d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
617d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
618d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
619d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16:
620d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: G & 0xffff
621d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic
622d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent)
623d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
624d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
625d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
626d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
627d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
628d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
629d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
6305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G
6335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
634d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent)
6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
636d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
6375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
6405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
641d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
646d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent)
6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
648affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Remember to add the section offset to A.
649affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  int32_t A = pReloc.target() + pReloc.addend();
6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t S = pReloc.symValue();
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t GP = helper_GetGP(pParent);
6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // llvm does not emits SHT_MIPS_REGINFO section.
6545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Assume that GP0 is zero.
6555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
6565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
657d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
6585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
659d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
660