MipsRelocator.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.h"
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.h"
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
2167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
26d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&);
2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_MIPS_APPLY_RELOC_FUNC_PTRS
4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
43d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator
4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent)
46d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : Relocator(),
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent),
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_AHL(0)
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
52d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result
53d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::applyRelocation(Relocation& pRelocation)
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
5967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return ApplyFunctions[type].func(pRelocation, *this);
6467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
66d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* MipsRelocator::getName(Relocation::Type pType) const
6767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size MipsRelocator::getSize(Relocation::Type pType) const
726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return ApplyFunctions[pType].size;
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp";
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc.
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc)
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (NULL != reloc)
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        reloc->symInfo() == pReloc.symInfo())
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return reloc;
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reloc = static_cast<Relocation*>(reloc->getNextNode());
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp.
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc)
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const ResolveInfo* rsym = pReloc.symInfo();
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0 == strcmp(GP_DISP_NAME, rsym->name());
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGP(MipsRelocator& pParent)
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return pParent.getTarget().getGOT().addr() + 0x7FF0;
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc,
113d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 MipsRelocator& pParent,
114d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 bool& pExist, int32_t value)
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
119affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) {
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // Local section symbols consume local got entries.
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got.consumeLocal();
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
126d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  MipsGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != got_entry) {
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // found a mapping, then return the mapped entry immediately
12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (got.isLocal(rsym))
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = got.consumeLocal();
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = got.consumeGlobal();
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pParent.getSymGOTMap().record(*rsym, *got_entry);
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(pReloc.symValue());
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::reserve_entry_number_mismatch_got);
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
152d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGOTOffset(Relocation& pReloc,
153d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                       MipsRelocator& pParent)
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  bool exist;
156d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return got_entry.getOffset() - 0x7FF0;
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         "Incorrect type of relocation for AHL calculation");
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Note the addend is section symbol offset here
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert (pHiReloc.addend() == pLoReloc.addend());
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHI = pHiReloc.target();
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t ALO = pLoReloc.target();
17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) +
17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 pLoReloc.addend();
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
179d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, MipsRelocator& pParent)
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
190d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
191d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (got.isLocal(rsym)) {
194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(NULL);
195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A + S;
196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(rsym);
199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Don't add symbol value that will be resolved by the dynamic linker
200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A;
201affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
210d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent)
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
212d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
217d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent)
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
221d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
222d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
22722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
229d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return MipsRelocator::OK;
230affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
231affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, pParent);
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
235d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return MipsRelocator::OK;
236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
238affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = (S + A);
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
240d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
247d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& pParent)
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pParent.setAHL(AHL);
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t P = pReloc.place();
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
270d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16:
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: AHL + S
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : AHL + GP - P + 4
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
277d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent)
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t P = pReloc.place();
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
284affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t AHL = pParent.getAHL();
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = AHL + GP - P + 4;
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // The previous AHL may be for other hi/lo pairs.
290affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // We need to calcuate the lo part now.  It is easy.
291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Remember to add the section offset to ALO.
292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    res = ALO + S;
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
306d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent)
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
309d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = 0;
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->isLocal()) {
3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16");
3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pParent.setAHL(AHL);
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    bool exist;
322d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
324d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry.setValue(res);
32522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    G = got_entry.getOffset() - 0x7FF0;
326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    G = helper_GetGOTOffset(pReloc, pParent);
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
334d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
335d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
336d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
337d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16:
338d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: (G - (short)G) >> 16 + A
339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic
340d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent)
341d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
342d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  int32_t res = 0;
343d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
344d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
345d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  int32_t A = pReloc.target() + pReloc.addend();
346d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
347d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  res = (G - (int16_t)G) >> (16 + A);
348d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
349d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
350d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
351d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
353d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
354d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
355d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16:
356d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//   external: G & 0xffff
357d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic
358d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent)
359d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
360d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
361d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
362d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
363d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
364d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
365d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
370d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent)
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
372d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
377d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
382d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent)
3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
384affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Remember to add the section offset to A.
385affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  int32_t A = pReloc.target() + pReloc.addend();
3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t S = pReloc.symValue();
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t GP = helper_GetGP(pParent);
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // llvm does not emits SHT_MIPS_REGINFO section.
3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Assume that GP0 is zero.
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
393d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return MipsRelocator::OK;
3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
395d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
396