15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- X86RelocationFactory.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/DataTypes.h>
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLDInfo.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86RelocationFactory.h"
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86RelocationFunctions.h"
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_X86_APPLY_RELOC_FUNCS
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaotypedef RelocationFactory::Result
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                          (*ApplyFunctionType)(Relocation& pReloc,
3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                               const MCLDInfo& pLDInfo,
3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                               X86RelocationFactory& pParent);
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_X86_APPLY_RELOC_FUNC_PTRS
4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// X86RelocationFactory
4867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::X86RelocationFactory(size_t pNum,
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           X86GNULDBackend& pParent)
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : RelocationFactory(pNum),
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent) {
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::~X86RelocationFactory()
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result
6067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoX86RelocationFactory::applyRelocation(Relocation& pRelocation,
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           const MCLDInfo& pLDInfo)
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) {
66affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    fatal(diag::unknown_relocation) << (int)type <<
67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                       pRelocation.symInfo()->name();
6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
7267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* X86RelocationFactory::getName(Relocation::Type pType) const
7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
8167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
8267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check if symbol can use relocation R_386_RELATIVE
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym,
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                          const MCLDInfo& pLDInfo,
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                          const X86RelocationFactory& pFactory)
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol is dynamic or undefine or preemptible
92affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pSym.isDyn() ||
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao     pSym.isUndef() ||
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao     pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  const MCLDInfo& pLDInfo,
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  X86RelocationFactory& pParent)
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86GNULDBackend& ld_backend = pParent.getTarget();
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!exist) {
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If we first get this GOT entry, we should initialize it.
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // No corresponding dynamic relocation, initialize to the symbol value.
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      got_entry.setContent(pReloc.symValue());
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // Initialize corresponding dynamic relocation.
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      Relocation& rel_entry =
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // Initialize got entry to target symbol address
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        got_entry.setContent(pReloc.symValue());
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setType(llvm::ELF::R_386_RELATIVE);
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setSymInfo(0);
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else {
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        got_entry.setContent(0);
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setType(llvm::ELF::R_386_GLOB_DAT);
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setSymInfo(rsym);
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.targetRef().assign(got_entry);
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::reserve_entry_number_mismatch_got);
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return got_entry;
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return pParent.getTarget().getGOTPLT().getSection().addr();
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_GOT(Relocation& pReloc,
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         const MCLDInfo& pLDInfo,
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         X86RelocationFactory& pParent)
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo,  pParent);
155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  X86RelocationFactory::Address got_addr =
156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pParent.getTarget().getGOT().getSection().addr();
157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return got_addr + pParent.getLayout().getOutputOffset(got_entry);
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoPLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  X86RelocationFactory& pParent)
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86GNULDBackend& ld_backend = pParent.getTarget();
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!exist) {
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If we first get this PLT entry, we should initialize it.
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      GOTEntry& gotplt_entry =
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // Initialize corresponding dynamic relocation.
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      Relocation& rel_entry =
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.targetRef().assign(gotplt_entry);
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.setSymInfo(rsym);
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
185cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::reserve_entry_number_mismatch_plt);
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return plt_entry;
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_PLT_ORG(X86RelocationFactory& pParent)
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getTarget().getPLT().getSection().addr();
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_PLT(Relocation& pReloc,
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         X86RelocationFactory& pParent)
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Get an relocation entry in .rel.dyn and set its type to pType,
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc,
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   X86RelocationFactory::Type pType,
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   X86RelocationFactory& pParent)
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86GNULDBackend& ld_backend = pParent.getTarget();
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation& rel_entry =
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(pType);
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pType == llvm::ELF::R_386_RELATIVE)
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    rel_entry.setSymInfo(0);
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    rel_entry.setSymInfo(rsym);
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation //
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result none(Relocation& pReloc,
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  const MCLDInfo& pLDInfo,
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  X86RelocationFactory& pParent)
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result abs32(Relocation& pReloc,
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   X86RelocationFactory& pParent)
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord S = pReloc.symValue();
25267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
25367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                       *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT),
25467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                       pLDInfo, pLDInfo.output(), true);
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
256affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
257affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
258affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
262affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
263affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return X86RelocationFactory::OK;
264affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
265affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
266affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // A local symbol may need REL Type dynamic relocation
26767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (rsym->isLocal() && has_dyn_rel) {
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = S + A;
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return X86RelocationFactory::OK;
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
272affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
273affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
274affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
275affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      S = helper_PLT(pReloc, pParent);
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      pReloc.target() = S + A;
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
279affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // If we generate a dynamic relocation (except R_386_RELATIVE)
280affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // for a place, we should not perform static relocation on it
281affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // in order to keep the addend store in the place correct.
28267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    if (has_dyn_rel) {
283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else {
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        helper_DynRel(pReloc, pReloc.type(), pParent);
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        return X86RelocationFactory::OK;
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A;
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result rel32(Relocation& pReloc,
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   X86RelocationFactory& pParent)
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
303affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ResolveInfo* rsym = pReloc.symInfo();
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
305affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord S = pReloc.symValue();
306affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  RelocationFactory::DWord P = pReloc.place(pParent.getLayout());
307affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
308affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
309affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
310affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
311affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A - P;
315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return X86RelocationFactory::OK;
316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
319affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       S = helper_PLT(pReloc, pParent);
322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       pReloc.target() = S + A - P;
323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (pParent.getTarget().symbolNeedsDynRel(
325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo,
326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                  pLDInfo.output(), false)) {
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      else {
331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        helper_DynRel(pReloc, pReloc.type(), pParent);
332affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          return X86RelocationFactory::OK;
333affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
334affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
335affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
336affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
337affc150dc44fab1911775a49636d0ce85333b634Zonr Chang   // perform static relocation
338affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = S + A - P;
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result gotoff32(Relocation& pReloc,
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      X86RelocationFactory& pParent)
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address S = pReloc.symValue();
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A - GOT_ORG;
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result gotpc32(Relocation& pReloc,
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     const MCLDInfo& pLDInfo,
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     X86RelocationFactory& pParent)
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout());
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result got32(Relocation& pReloc,
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   X86RelocationFactory& pParent)
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
372affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!(pReloc.symInfo()->reserved()
3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return X86RelocationFactory::BadReloc;
3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - GOT_ORG;
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P
3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result plt32(Relocation& pReloc,
3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   X86RelocationFactory& pParent)
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // PLT_S depends on if there is a PLT entry.
3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address PLT_S;
391affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = helper_PLT(pReloc, pParent);
3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = pReloc.symValue();
3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X86RelocationFactory::Address P = pReloc.place(pParent.getLayout());
3975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = PLT_S + A - P;
3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return X86RelocationFactory::OK;
3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
400