MipsRelocator.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MipsRelocationFactory.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>
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentLinker.h>
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Target/OutputRelocSection.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFactory.h"
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.h"
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaotypedef RelocationFactory::Result (*ApplyFunctionType)(Relocation&,
2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                                       MipsRelocationFactory&);
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;
3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_MIPS_APPLY_RELOC_FUNC_PTRS
4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MipsRelocationFactory
4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::MipsRelocationFactory(size_t pNum,
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                             MipsGNULDBackend& pParent)
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : RelocationFactory(pNum),
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent),
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_AHL(0)
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoMipsRelocationFactory::applyRelocation(Relocation& pRelocation)
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
6167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return ApplyFunctions[type].func(pRelocation, *this);
6667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* MipsRelocationFactory::getName(Relocation::Type pType) const
6967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
7067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp";
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc.
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc)
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (NULL != reloc)
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        reloc->symInfo() == pReloc.symInfo())
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return reloc;
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reloc = static_cast<Relocation*>(reloc->getNextNode());
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp.
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc)
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const ResolveInfo* rsym = pReloc.symInfo();
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0 == strcmp(GP_DISP_NAME, rsym->name());
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return pParent.getTarget().getGOT().addr() + 0x7FF0;
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoGOT::Entry& helper_GetGOTEntry(Relocation& pReloc,
111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             MipsRelocationFactory& pParent,
112affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             bool& pExist, int32_t value)
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) {
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // Local section symbols consume local got entries.
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got.consumeLocal();
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != got_entry) {
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // found a mapping, then return the mapped entry immediately
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (got.isLocal(rsym))
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = got.consumeLocal();
13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = got.consumeGlobal();
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pParent.getSymGOTMap().record(*rsym, *got_entry);
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry->setContent(pReloc.symValue());
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::reserve_entry_number_mismatch_got);
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                               MipsRelocationFactory& pParent)
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  bool exist;
15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return got_entry.getOffset() - 0x7FF0;
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         "Incorrect type of relocation for AHL calculation");
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Note the addend is section symbol offset here
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert (pHiReloc.addend() == pLoReloc.addend());
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHI = pHiReloc.target();
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t ALO = pLoReloc.target();
17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) +
17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 pLoReloc.addend();
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc,
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   MipsRelocationFactory& pParent)
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord S = pReloc.symValue();
191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (got.isLocal(rsym)) {
193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(NULL);
194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A + S;
195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(rsym);
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Don't add symbol value that will be resolved by the dynamic linker
199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A;
200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result none(Relocation& pReloc,
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result abs32(Relocation& pReloc,
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    MipsRelocationFactory& pParent)
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord S = pReloc.symValue();
224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
227affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
22822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
229affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
230affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return MipsRelocationFactory::OK;
231affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
232affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, pParent);
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return MipsRelocationFactory::OK;
237affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
239affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = (S + A);
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result hi16(Relocation& pReloc,
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pParent.setAHL(AHL);
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
26022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t P = pReloc.place();
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16:
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: AHL + S
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : AHL + GP - P + 4
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result lo16(Relocation& pReloc,
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
28522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t P = pReloc.place();
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t AHL = pParent.getAHL();
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = AHL + GP - P + 4;
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // The previous AHL may be for other hi/lo pairs.
293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // We need to calcuate the lo part now.  It is easy.
294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Remember to add the section offset to ALO.
295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
296affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    res = ALO + S;
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result got16(Relocation& pReloc,
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    MipsRelocationFactory& pParent)
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::Address G = 0;
3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->isLocal()) {
3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16");
3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pParent.setAHL(AHL);
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    bool exist;
32622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    got_entry.setContent(res);
32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    G = got_entry.getOffset() - 0x7FF0;
330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
332affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    G = helper_GetGOTOffset(pReloc, pParent);
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result call16(Relocation& pReloc,
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     MipsRelocationFactory& pParent)
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result gprel32(Relocation& pReloc,
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      MipsRelocationFactory& pParent)
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
359affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Remember to add the section offset to A.
360affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  int32_t A = pReloc.target() + pReloc.addend();
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t S = pReloc.symValue();
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t GP = helper_GetGP(pParent);
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // llvm does not emits SHT_MIPS_REGINFO section.
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Assume that GP0 is zero.
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
370