MipsRelocator.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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 <llvm/Support/ErrorHandling.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-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
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//==========================
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MipsRelocationFactory
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::MipsRelocationFactory(size_t pNum,
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                             MipsGNULDBackend& pParent)
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : RelocationFactory(pNum),
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent),
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_AHL(0)
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsRelocationFactory::applyRelocation(Relocation& pRelocation,
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                            const MCLDInfo& pLDInfo)
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  /// the prototype of applying function
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  typedef Result (*ApplyFunctionType)(Relocation&,
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      MipsRelocationFactory&);
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // the table entry of applying functions
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  struct ApplyFunctionTriple {
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ApplyFunctionType func;
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    unsigned int type;
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    const char* name;
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  };
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // declare the table of applying functions
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  static ApplyFunctionTriple apply_functions[] = {
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    DECL_MIPS_APPLY_RELOC_FUNC_PTRS
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  };
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (type >= sizeof(apply_functions) / sizeof(apply_functions[0])) {
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         "To symbol `") +
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             pRelocation.symInfo()->name() +
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine("'."));
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // check result
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (Overflow == result) {
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(apply_functions[type].name) +
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine("' causes overflow. on symbol: `") +
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(pRelocation.symInfo()->name()) +
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine("'."));
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return;
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (BadReloc == result) {
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(apply_functions[type].name) +
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine("' encounters unexpected opcode. "
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         "on symbol: `") +
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(pRelocation.symInfo()->name()) +
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine("'."));
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return;
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation helper function              //
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp";
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Get an relocation entry in .rel.dyn and set its type to R_MIPS_REL32,
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// its FragmentRef to pReloc->targetFrag() and its ResolveInfo
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// to pReloc->symInfo()
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_SetRelDynEntry(Relocation& pReloc,
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   MipsRelocationFactory& pParent)
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation& rel_entry =
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setSymInfo(0);
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc.
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc)
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (NULL != reloc)
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  {
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        reloc->symInfo() == pReloc.symInfo())
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return reloc;
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reloc = static_cast<Relocation*>(reloc->getNextNode());
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp.
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc)
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const ResolveInfo* rsym = pReloc.symInfo();
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0 == strcmp(GP_DISP_NAME, rsym->name());
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0;
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_GetGOTEntry(Relocation& pReloc,
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             MipsRelocationFactory& pParent)
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (exist)
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return got_entry;
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    got_entry.setContent(pReloc.symValue());
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return got_entry;
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                               MipsRelocationFactory& pParent)
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         "Incorrect type of relocation for AHL calculation");
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Note the addend is section symbol offset here
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert (pHiReloc.addend() == pLoReloc.addend());
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHI = pHiReloc.target();
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t ALO = pLoReloc.target();
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend();
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return AHL;
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc,
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   MipsRelocationFactory& pParent)
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MipsGNULDBackend& ld_backend = pParent.getTarget();
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation& rel_entry =
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setSymInfo(rsym->isLocal() ? NULL : rsym);
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation     //
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result none(Relocation& pReloc,
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result abs32(Relocation& pReloc,
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    const MCLDInfo& pLDInfo,
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    MipsRelocationFactory& pParent)
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, pParent);
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord S = pReloc.symValue();
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (S + A);
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16:
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result hi16(Relocation& pReloc,
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pParent.setAHL(AHL);
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t P = pReloc.place(pParent.getLayout());
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16:
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local/external: AHL + S
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   _gp_disp      : AHL + GP - P + 4
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result lo16(Relocation& pReloc,
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MipsRelocationFactory& pParent)
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t AHL = pParent.getAHL();
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t res = 0;
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_isGpDisp(pReloc)) {
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t P = pReloc.place(pParent.getLayout());
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t GP = helper_GetGP(pParent);
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = AHL + GP - P + 4;
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t S = pReloc.symValue();
2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    res = AHL + S;
2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (res & 0xFFFF);
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16:
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   local   : G (calculate AHL and put high 16 bit to GOT)
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//   external: G
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result got16(Relocation& pReloc,
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    const MCLDInfo& pLDInfo,
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    MipsRelocationFactory& pParent)
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
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    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    got_entry.setContent(res);
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result call16(Relocation& pReloc,
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     const MCLDInfo& pLDInfo,
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     MipsRelocationFactory& pParent)
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() &= 0xFFFF0000;
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() |= (G & 0xFFFF);
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result gprel32(Relocation& pReloc,
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      MipsRelocationFactory& pParent)
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t A = pReloc.target();
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t S = pReloc.symValue();
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t GP = helper_GetGP(pParent);
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // llvm does not emits SHT_MIPS_REGINFO section.
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Assume that GP0 is zero.
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return MipsRelocationFactory::OK;
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
364