X86Relocator.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- X86Relocator.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//===----------------------------------------------------------------------===//
96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "X86Relocator.h"
106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "X86RelocationFunctions.h"
116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Support/MsgHandling.h>
136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/LDSymbol.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h>
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.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//===--------------------------------------------------------------------===//
246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_32_APPLY_RELOC_FUNCS
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc,
286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines						     X86_32Relocator& pParent);
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_32ApplyFunctionTriple
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32ApplyFunctionType func;
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = {
416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  DECL_X86_32_APPLY_RELOC_FUNC_PTRS
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// X86Relocator
4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::X86Relocator()
486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : Relocator() {
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
51d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoX86Relocator::~X86Relocator()
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32Relocator
576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent)
596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86Relocator(), m_Target(pParent) {
606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result
636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32Relocator::applyRelocation(Relocation& pRelocation)
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) {
6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[type].func(pRelocation, *this);
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_32Relocator::getName(Relocation::Type pType) const
7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[pType].name;
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_32Relocator::getSize(Relocation::Type pType) const
816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[pType].size;;
8367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
8667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
8767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_DynRel - Get an relocation entry in .rel.dyn
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoRelocation& helper_DynRel(ResolveInfo* pSym,
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          Fragment& pFrag,
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          uint64_t pOffset,
94d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                          X86Relocator::Type pType,
956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          X86_32Relocator& pParent)
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  rel_entry.setType(pType);
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  rel_entry.targetRef().assign(pFrag, pOffset);
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym)
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(0);
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(pSym);
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return rel_entry;
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_use_relative_reloc - Check if symbol can use relocation
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// R_386_RELATIVE
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym,
1146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          const X86_32Relocator& pFactory)
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol is dynamic or undefine or preemptible
118affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pSym.isDyn() ||
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pSym.isUndef() ||
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pFactory.getTarget().isSymbolPreemptible(pSym))
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					X86_32Relocator& pParent)
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != got_entry)
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  got_entry = ld_backend.getGOT().consume();
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pParent.getSymGOTMap().record(*rsym, *got_entry);
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // No corresponding dynamic relocation, initialize to the symbol value.
144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(pReloc.symValue());
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // Initialize got_entry content and the corresponding dynamic relocation.
14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (helper_use_relative_reloc(*rsym, pParent)) {
14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
150d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got_entry->setValue(pReloc.symValue());
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got_entry->setValue(0);
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::reserve_entry_number_mismatch_got);
15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
16722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return pParent.getTarget().getGOTPLT().addr();
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent)
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
175d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr();
17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return got_addr + got_entry.getOffset();
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines				      X86_32Relocator& pParent)
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
188d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != plt_entry)
19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *plt_entry;
19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  plt_entry = ld_backend.getPLT().consume();
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pParent.getSymPLTMap().record(*rsym, *plt_entry);
19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If we first get this PLT entry, we should initialize it.
19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
1976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    gotplt_entry = ld_backend.getGOTPLT().consume();
20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // init the corresponding rel entry in .rel.plt
20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.targetRef().assign(*gotplt_entry);
20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(rsym);
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::reserve_entry_number_mismatch_plt);
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *plt_entry;
21222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent)
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return pParent.getTarget().getPLT().addr();
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent)
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
225d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
22622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation //
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE
2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent)
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
237d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A
24122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_16
24222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_8
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent)
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
246d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
247d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
24867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              *rsym,
25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              true);
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
254affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
255affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
257affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
258d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // A local symbol may need REL Type dynamic relocation
26267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (rsym->isLocal() && has_dyn_rel) {
26322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::ELF::R_386_32 == pReloc.type()) {
26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *pReloc.targetRef().frag(),
26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                    pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE,
26622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                    pParent);
26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
26822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
26922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // FIXME: check Section symbol
27022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *pReloc.targetRef().frag(),
27122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                    pReloc.targetRef().offset(), pReloc.type(), pParent);
27222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = S + A;
274d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
276affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
277affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
278affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
279affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      S = helper_PLT(pReloc, pParent);
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
282affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // If we generate a dynamic relocation (except R_386_RELATIVE)
283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // for a place, we should not perform static relocation on it
284affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // in order to keep the addend store in the place correct.
28567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    if (has_dyn_rel) {
28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (llvm::ELF::R_386_32 == pReloc.type() &&
28722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          helper_use_relative_reloc(*rsym, pParent)) {
28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        helper_DynRel(rsym, *pReloc.targetRef().frag(),
28922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else {
29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        helper_DynRel(rsym, *pReloc.targetRef().frag(),
29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          pReloc.targetRef().offset(), pReloc.type(), pParent);
294d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        return X86Relocator::OK;
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A;
301d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P
30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC16
30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC8
3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent)
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
309affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ResolveInfo* rsym = pReloc.symInfo();
310d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
311d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
312d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord P = pReloc.place();
313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A - P;
319d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       S = helper_PLT(pReloc, pParent);
326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       pReloc.target() = S + A - P;
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (pParent.getTarget().symbolNeedsDynRel(
32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              *rsym,
33022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
33122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              false)) {
33222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (helper_use_relative_reloc(*rsym, pParent) ) {
33322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        helper_DynRel(rsym, *pReloc.targetRef().frag(),
33422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
335affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
336affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      else {
33722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        helper_DynRel(rsym, *pReloc.targetRef().frag(),
33822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          pReloc.targetRef().offset(), pReloc.type(), pParent);
339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao          return X86Relocator::OK;
340affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
341affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
342affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
343affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
344affc150dc44fab1911775a49636d0ce85333b634Zonr Chang   // perform static relocation
345affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = S + A - P;
346d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG
3506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent)
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A = pReloc.target() + pReloc.addend();
353d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
354d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address S = pReloc.symValue();
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A - GOT_ORG;
357d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P
3616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent)
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
363d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A       = pReloc.target() + pReloc.addend();
364d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
36622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_ORG + A - pReloc.place();
367d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG
3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent)
3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
373affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!(pReloc.symInfo()->reserved()
3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
375d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::BadReloc;
3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
377d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
378d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A       = pReloc.target() + pReloc.addend();
379d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - GOT_ORG;
382d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P
3866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent)
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // PLT_S depends on if there is a PLT entry.
389d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address PLT_S;
390affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = helper_PLT(pReloc, pParent);
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = pReloc.symValue();
394d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A = pReloc.target() + pReloc.addend();
395d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address P = pReloc.place();
3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = PLT_S + A - P;
397d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
39922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
40022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GD:
4016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent)
40222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
40322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // global-dynamic
40422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
40522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // must reserve two pairs of got and dynamic relocation
40622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
407d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao     return X86Relocator::BadReloc;
40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
41222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // setup corresponding got and dynamic relocatio entries:
41322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first got entry, if there is already a got entry for rsym, then apply
41422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // this relocation to the got entry directly. If not, setup the corresponding
41522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // got and dyn relocation entries
4166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
41722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == got_entry1) {
41922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get and init two got entries if not exist
42022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry1 = ld_backend.getGOT().consume();
42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTMap().record(*rsym, *got_entry1);
4226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume();
423d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry1->setValue(0x0);
424d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry2->setValue(0x0);
42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // setup dyn rel for get_entry1
42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                        llvm::ELF::R_386_TLS_DTPMOD32, pParent);
42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (rsym->isLocal()) {
42922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for local symbol, set got_entry2 to symbol value
430d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got_entry2->setValue(pReloc.symValue());
43122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
43222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for local tls symbol, add rel entry against the section symbol this
43322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // symbol belong to (.tdata or .tbss)
43422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      const LDSection* sym_sect =
43522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
43622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      ResolveInfo* sect_sym = NULL;
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (&file_format->getTData() == sym_sect)
43822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo();
43922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      else
44022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo();
44122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      rel_entry1.setSymInfo(sect_sym);
44222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
44322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for non-local symbol, add a pair of rel entries against this symbol
44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for those two got entries
44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *got_entry2, 0x0,
44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                        llvm::ELF::R_386_TLS_DTPOFF32, pParent);
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
44922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
45122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation to the first got entry
452d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
45322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
45422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // .got.plt section)
455d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_OFF =
45622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     file_format->getGOT().addr() +
45722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     got_entry1->getOffset() -
45822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     file_format->getGOTPLT().addr();
45922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_OFF + A;
460d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
46122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
46222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
46322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDM
4646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent)
46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: no linker optimization for TLS relocation
4676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const X86_32GOTEntry& got_entry = pParent.getTarget().getTLSModuleID();
46822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // All GOT offsets are relative to the end of the GOT.
470d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::SWord GOT_S = got_entry.getOffset() -
47122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      (pParent.getTarget().getGOTPLT().addr() -
47222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                       pParent.getTarget().getGOT().addr());
473d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
476d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
47722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
47822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
47922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDO_32
4806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent)
48122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
48222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: no linker optimization for TLS relocation
483d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
484d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address S = pReloc.symValue();
48522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = S + A;
486d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_IE
4906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent)
49122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
49322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
494d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao     return X86Relocator::BadReloc;
49522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (rsym->reserved() & X86GNULDBackend::ReserveRel) {
49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // when building shared object, set up a RELATIVE dynamic relocation
49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(),
50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                            llvm::ELF::R_386_RELATIVE, pParent);
50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
50322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up the got and dynamic relocation entries if not exist
5046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == got_entry) {
50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set got entry
5076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GNULDBackend& ld_backend = pParent.getTarget();
50822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = ld_backend.getGOT().consume();
50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTMap().record(*rsym, *got_entry);
510d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(0x0);
51122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set relocation entry
51222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
51322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
51422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(rsym);
51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.targetRef().assign(*got_entry);
51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
51722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
51822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation to the absolute address of got_entry
519d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_S =
52022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 pParent.getTarget().getGOT().addr() + got_entry->getOffset();
52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
522d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
52322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
52422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
525d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GOTIE
5296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent)
53022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
53122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
533d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao     return X86Relocator::BadReloc;
53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up the got and dynamic relocation entries if not exist
5376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
53822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == got_entry) {
53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set got entry
5406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GNULDBackend& ld_backend = pParent.getTarget();
54122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = ld_backend.getGOT().consume();
54222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTMap().record(*rsym, *got_entry);
543d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(0x0);
54422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set relocation entry
54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
54722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(rsym);
54822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.targetRef().assign(*got_entry);
54922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
55122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // All GOT offsets are relative to the end of the GOT.
552d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::SWord GOT_S = got_entry->getOffset() -
55322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
554d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
55522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
55622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
557d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
55822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
55922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
56022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_LE
5616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent)
56222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
56322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
56422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) {
56522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    helper_DynRel(rsym,
56622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  *pReloc.targetRef().frag(),
56722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  pReloc.targetRef().offset(),
56822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  llvm::ELF::R_386_TLS_TPOFF,
56922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  pParent);
570d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
57122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
57222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
57322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform static relocation
57422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get TLS segment
57522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
57622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                       llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
577d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
578d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address S = pReloc.symValue();
57922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = S + A - tls_seg->memsz();
580d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
58122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
58222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent)
58422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
585d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::Unsupport;
58622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
58722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
5896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Relocation Functions and Tables
5906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
5916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_64_APPLY_RELOC_FUNCS
5926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// the prototype of applying function
5946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc,
5956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines						     X86_64Relocator& pParent);
5966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions
5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_64ApplyFunctionTriple
5996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64ApplyFunctionType func;
6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int type;
6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* name;
6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
6056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions
6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = {
6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  DECL_X86_64_APPLY_RELOC_FUNC_PTRS
6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64Relocator
6136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
6146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent)
6156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86Relocator(), m_Target(pParent) {
6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Result
6196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64Relocator::applyRelocation(Relocation& pRelocation)
6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation::Type type = pRelocation.type();
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) {
6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Unknown;
6256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // apply the relocation
6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[type].func(pRelocation, *this);
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_64Relocator::getName(Relocation::Type pType) const
6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[pType].name;
6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_64Relocator::getSize(Relocation::Type pType) const
6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[pType].size;
6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn
6426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
6436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocation& helper_DynRel(ResolveInfo* pSym,
6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          Fragment& pFrag,
6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          uint64_t pOffset,
6466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          X86Relocator::Type pType,
6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          X86_64Relocator& pParent)
6486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
6506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
6516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  rel_entry.setType(pType);
6526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  rel_entry.targetRef().assign(pFrag, pOffset);
6536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym)
6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setSymInfo(0);
6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setSymInfo(pSym);
6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return rel_entry;
6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation
6636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// R_X86_64_RELATIVE
6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic bool
6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hineshelper_use_relative_reloc(const ResolveInfo& pSym,
6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          const X86_64Relocator& pFactory)
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if symbol is dynamic or undefine or preemptible
6706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pSym.isDyn() ||
6716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      pSym.isUndef() ||
6726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      pFactory.getTarget().isSymbolPreemptible(pSym))
6736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return false;
6746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					X86_64Relocator& pParent)
6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // rsym - The relocation target symbol
6826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
6836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
6866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL != got_entry)
6876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return *got_entry;
6886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // not found
6906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  got_entry = ld_backend.getGOT().consume();
6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pParent.getSymGOTMap().record(*rsym, *got_entry);
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If we first get this GOT entry, we should initialize it.
6946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
6956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // No corresponding dynamic relocation, initialize to the symbol value.
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got_entry->setValue(pReloc.symValue());
6976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Initialize got_entry content and the corresponding dynamic relocation.
7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (helper_use_relative_reloc(*rsym, pParent)) {
7016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0,
7026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    llvm::ELF::R_X86_64_RELATIVE,
7036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pParent);
7046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      rel_entry.setAddend(pReloc.symValue());
7056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
7076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT,
7086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		    pParent);
7096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got_entry->setValue(0);
7116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
7126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
7136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::reserve_entry_number_mismatch_got);
7146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
7156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *got_entry;
7166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
7196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
7206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return pParent.getTarget().getGOT().addr();
7226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
7256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent)
7266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
7286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return got_entry.getOffset();
7296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
7326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
7336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines				      X86_64Relocator& pParent)
7346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // rsym - The relocation target symbol
7366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
7386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
7406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL != plt_entry)
7416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return *plt_entry;
7426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // not found
7446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  plt_entry = ld_backend.getPLT().consume();
7456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pParent.getSymPLTMap().record(*rsym, *plt_entry);
7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If we first get this PLT entry, we should initialize it.
7476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
7486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
7496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
7506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    gotplt_entry = ld_backend.getGOTPLT().consume();
7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
7526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // init the corresponding rel entry in .rel.plt
7536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
7546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
7556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.targetRef().assign(*gotplt_entry);
7566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setSymInfo(rsym);
7576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
7586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
7596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::reserve_entry_number_mismatch_plt);
7606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
7616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *plt_entry;
7636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
7666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent)
7676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return pParent.getTarget().getPLT().addr();
7696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
7726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent)
7736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
7756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
7766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
7796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_NONE
7806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent)
7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
7836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_64: S + A
7866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32:
7876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_16:
7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_8
7896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent)
7906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
7926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord A = pReloc.addend();
7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
7956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              *rsym,
7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              true);
7986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
8016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // but perform static relocation. (e.g., applying .debug section)
8026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pReloc.target() = S + A;
8046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::OK;
8056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation::Type pointerRel = pParent.getTarget().getPointerRel();
8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // A local symbol may need REL Type dynamic relocation
8106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (rsym->isLocal() && has_dyn_rel) {
8116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pointerRel == pReloc.type()) {
8126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
8136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pReloc.targetRef().offset(),
8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    llvm::ELF::R_X86_64_RELATIVE,
8156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pParent);
8166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      rel_entry.setAddend(S + A);
8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
8196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // FIXME: check Section symbol
8206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pReloc.targetRef().offset(),
8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pReloc.type(), pParent);
8236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      rel_entry.setAddend(S + A);
8246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::OK;
8266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
8296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!rsym->isLocal()) {
8306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // If we generate a dynamic relocation for a place with explicit
8316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // addend, there is no need to perform static relocation on it.
8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (has_dyn_rel) {
8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pReloc.targetRef().offset(),
8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    llvm::ELF::R_X86_64_RELATIVE,
8366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pParent);
8376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Copy addend.
8386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      rel_entry.setAddend(A);
8396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return X86Relocator::OK;
8406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      S = helper_PLT(pReloc, pParent);
8436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // perform static relocation
8476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A;
8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32S: S + A
8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent)
8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord A = pReloc.addend();
8566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
8576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
8586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              *rsym,
8596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
8606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              true);
8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // There should be no dynamic relocations for R_X86_64_32S.
8636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (has_dyn_rel)
8646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::BadReloc;
8656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // but perform static relocation. (e.g., applying .debug section)
8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
8706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) &&
8716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      !rsym->isLocal() && rsym->reserved() & X86GNULDBackend::ReservePLT)
8726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    S = helper_PLT(pReloc, pParent);
8736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Check 32-bit signed overflow.
8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::SWord V = S + A;
8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000))
8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::Overflow;
8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // perform static relocation
8806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A;
8816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
8826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
8856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent)
8866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!(pReloc.symInfo()->reserved()
8886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
8896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::BadReloc;
8906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
8926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord      A       = pReloc.addend();
8936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
8946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Apply relocation.
8956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place();
8966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
8976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PLT32: PLT(S) + A - P
9006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent)
9016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
9026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PLT_S depends on if there is a PLT entry.
9036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address PLT_S;
9046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
9056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLT_S = helper_PLT(pReloc, pParent);
9066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
9076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLT_S = pReloc.symValue();
9086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord      A = pReloc.addend();
9096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address P = pReloc.place();
9106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = PLT_S + A - P;
9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
9126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
9136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC32: S + A - P
9156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC16
9166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC8
9176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent)
9186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
9196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
9206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord A = pReloc.addend();
9216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord P = pReloc.place();
9236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
9256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
9266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // but perform static relocation. (e.g., applying .debug section)
9276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
9286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pReloc.target() = S + A - P;
9296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::OK;
9306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
9336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!rsym->isLocal()) {
9346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
9356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       S = helper_PLT(pReloc, pParent);
9366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       pReloc.target() = S + A - P;
9376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pParent.getTarget().symbolNeedsDynRel(
9396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              *rsym,
9406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
9416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              false)) {
9426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          return X86Relocator::Overflow;
9436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines   // perform static relocation
9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A - P;
9486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
9496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
9506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent)
9526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
9536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::Unsupport;
9546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
955