MipsRelocator.cpp revision 67e37f1be98c926645219cfb47fab9e90d8c725c
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>
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/OutputRelocSection.h>
14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.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                                                       const MCLDInfo& pLDInfo,
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                                       MipsRelocationFactory&);
3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
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//===----------------------------------------------------------------------===//
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MipsRelocationFactory
4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::MipsRelocationFactory(size_t pNum,
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                             MipsGNULDBackend& pParent)
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : RelocationFactory(pNum),
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent),
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_AHL(0)
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result
5667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoMipsRelocationFactory::applyRelocation(Relocation& pRelocation,
5767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                       const MCLDInfo& pLDInfo)
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    fatal(diag::unknown_relocation) << (int)type
64affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                    << pRelocation.symInfo()->name();
6567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
6967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
7067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* MipsRelocationFactory::getName(Relocation::Type pType) const
7367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===//
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp";
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc.
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc)
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (NULL != reloc)
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        reloc->symInfo() == pReloc.symInfo())
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return reloc;
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reloc = static_cast<Relocation*>(reloc->getNextNode());
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp.
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc)
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const ResolveInfo* rsym = pReloc.symInfo();
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0 == strcmp(GP_DISP_NAME, rsym->name());
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0;
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_GetGOTEntry(Relocation& pReloc,
115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             MipsRelocationFactory& pParent,
116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             bool& pExist, int32_t value)
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  GOTEntry& got_entry = *got.getEntry(*rsym, pExist);
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pExist)
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return got_entry;
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!(got.isLocal(rsym) && rsym->type() == ResolveInfo::Section)) {
130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      got_entry.setContent(pReloc.symValue());
132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    else {
134affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      fatal(diag::reserve_entry_number_mismatch) << "GOT";
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return got_entry;
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                               MipsRelocationFactory& pParent)
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  bool exist;
146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         "Incorrect type of relocation for AHL calculation");
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Note the addend is section symbol offset here
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert (pHiReloc.addend() == pLoReloc.addend());
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHI = pHiReloc.target();
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t ALO = pLoReloc.target();
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend();
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc,
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   MipsRelocationFactory& pParent)
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
173affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  MipsGOT& got = ld_backend.getGOT();
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation& rel_entry =
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
181affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord S = pReloc.symValue();
184affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (got.isLocal(rsym)) {
186affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(NULL);
187affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A + S;
188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    rel_entry.setSymInfo(rsym);
191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Don't add symbol value that will be resolved by the dynamic linker
192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = A;
193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result none(Relocation& pReloc,
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result abs32(Relocation& pReloc,
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    const MCLDInfo& pLDInfo,
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    MipsRelocationFactory& pParent)
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
217affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
218affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord S = pReloc.symValue();
219affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
220affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
221affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
227affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return MipsRelocationFactory::OK;
228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
229affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, pParent);
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
233affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return MipsRelocationFactory::OK;
234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = (S + A);
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result hi16(Relocation& pReloc,
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& 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)) {
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t P = pReloc.place(pParent.getLayout());
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
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::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
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result lo16(Relocation& pReloc,
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t P = pReloc.place(pParent.getLayout());
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
286affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t AHL = pParent.getAHL();
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = AHL + GP - P + 4;
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // The previous AHL may be for other hi/lo pairs.
292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // We need to calcuate the lo part now.  It is easy.
293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Remember to add the section offset to ALO.
294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    res = ALO + S;
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result got16(Relocation& pReloc,
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    const MCLDInfo& pLDInfo,
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;
326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    got_entry.setContent(res);
329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    G = pParent.getLayout().getOutputOffset(got_entry) - 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                                     const MCLDInfo& pLDInfo,
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     MipsRelocationFactory& pParent)
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result gprel32(Relocation& pReloc,
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      MipsRelocationFactory& pParent)
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
361affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Remember to add the section offset to A.
362affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  int32_t A = pReloc.target() + pReloc.addend();
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t S = pReloc.symValue();
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t GP = helper_GetGP(pParent);
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // llvm does not emits SHT_MIPS_REGINFO section.
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Assume that GP0 is zero.
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
372