1cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===- X86PLT.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//===----------------------------------------------------------------------===//
9affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "X86GOTPLT.h"
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86PLT.h"
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h>
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LinkerConfig.h>
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
19d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaousing namespace mcld;
20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
21cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
22cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// PLT entry data
23cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32DynPLT0::X86_32DynPLT0(SectionData& pParent)
256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : PLT::Entry<sizeof(x86_32_dyn_plt0)>(pParent)
26d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32DynPLT1::X86_32DynPLT1(SectionData& pParent)
306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : PLT::Entry<sizeof(x86_32_dyn_plt1)>(pParent)
31d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
32d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32ExecPLT0::X86_32ExecPLT0(SectionData& pParent)
356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : PLT::Entry<sizeof(x86_32_exec_plt0)>(pParent)
36d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
37d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32ExecPLT1::X86_32ExecPLT1(SectionData& pParent)
406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : PLT::Entry<sizeof(x86_32_exec_plt1)>(pParent)
416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT0::X86_64PLT0(SectionData& pParent)
456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : PLT::Entry<sizeof(x86_64_plt0)>(pParent)
466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT1::X86_64PLT1(SectionData& pParent)
506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : PLT::Entry<sizeof(x86_64_plt1)>(pParent)
51d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
52d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// X86PLT
56cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86PLT::X86PLT(LDSection& pSection,
586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines	       const LinkerConfig& pConfig,
596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines	       int got_size)
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : PLT(pSection),
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Config(pConfig)
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
64d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         LinkerConfig::Exec   == m_Config.codeGenType() ||
65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         LinkerConfig::Binary == m_Config.codeGenType());
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (got_size == 32) {
686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LinkerConfig::DynObj == m_Config.codeGenType()) {
696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0 = x86_32_dyn_plt0;
706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1 = x86_32_dyn_plt1;
716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0Size = sizeof (x86_32_dyn_plt0);
726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1Size = sizeof (x86_32_dyn_plt1);
736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // create PLT0
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      new X86_32DynPLT0(*m_SectionData);
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0 = x86_32_exec_plt0;
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1 = x86_32_exec_plt1;
796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0Size = sizeof (x86_32_exec_plt0);
806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1Size = sizeof (x86_32_exec_plt1);
816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // create PLT0
826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      new X86_32ExecPLT0(*m_SectionData);
836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    assert(got_size == 64);
876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT0 = x86_64_plt0;
886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT1 = x86_64_plt1;
896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT0Size = sizeof (x86_64_plt0);
906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT1Size = sizeof (x86_64_plt1);
91d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // create PLT0
926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    new X86_64PLT0(*m_SectionData);
936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_Last = m_SectionData->begin();
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_Last = m_SectionData->begin();
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86PLT::~X86PLT()
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86PLT::finalizeSectionSize()
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t size = 0;
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // plt0 size
106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  size = getPLT0()->size();
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first plt1 entry
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator it = begin();
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ++it;
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (end() != it) {
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // plt1 size
113d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it));
114d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    size += (m_SectionData->size() - 1) * plt1->size();
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_Section.setSize(size);
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = 0;
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData::iterator frag, fragEnd = m_SectionData->end();
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag->setOffset(offset);
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset += frag->size();
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool X86PLT::hasPLT1() const
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (m_SectionData->size() > 1);
12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86PLT::reserveEntry(size_t pNum)
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
133d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt1_entry = NULL;
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t i = 0; i < pNum; ++i) {
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (LinkerConfig::DynObj == m_Config.codeGenType())
1386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      plt1_entry = new X86_32DynPLT1(*m_SectionData);
139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    else
1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      plt1_entry = new X86_32ExecPLT1(*m_SectionData);
141d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (NULL == plt1_entry)
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::fail_allocate_memory_plt);
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoPLTEntryBase* X86PLT::consume()
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // This will skip PLT0.
15022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ++m_Last;
15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(m_Last != m_SectionData->end() &&
15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         "The number of PLT Entries and ResolveInfo doesn't match");
153d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return llvm::cast<PLTEntryBase>(&(*m_Last));
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
156d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoPLTEntryBase* X86PLT::getPLT0() const
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  iterator first = m_SectionData->getFragmentList().begin();
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(first != m_SectionData->getFragmentList().end() &&
16167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao         "FragmentList is empty, getPLT0 failed!");
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
163d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return plt0;
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32PLT
1706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32PLT::X86_32PLT(LDSection& pSection,
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     X86_32GOTPLT& pGOTPLT,
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     const LinkerConfig& pConfig)
1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86PLT(pSection, pConfig, 32),
1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_GOTPLT(pGOTPLT) {
1766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT0()
18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
181d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = getPLT0();
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  unsigned char* data = 0;
184d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  data = static_cast<unsigned char*>(malloc(plt0->size()));
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!data)
187cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    fatal(diag::fail_allocate_memory_plt);
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
189d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  memcpy(data, m_PLT0, plt0->size());
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_PLT0 == x86_32_exec_plt0) {
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 4;
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 8);
19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 8;
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
198d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  plt0->setValue(data);
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
2026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT1()
20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(m_Section.addr() && ".plt base address is NULL!");
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator it = m_SectionData->begin();
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator ie = m_SectionData->end();
20867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_32GOTEntry::EntrySize;
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Skip GOT0
213affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
21422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Exec == m_Config.codeGenType())
21522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    GOTEntryOffset += m_GOTPLT.addr();
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //skip PLT0
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTEntryOffset = m_PLT0Size;
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++it;
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
221d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt1 = 0;
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTRelOffset = 0;
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (it != ie) {
226d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1 = &(llvm::cast<PLTEntryBase>(*it));
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    unsigned char *data;
228d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    data = static_cast<unsigned char*>(malloc(plt1->size()));
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (!data)
231cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::fail_allocate_memory_plt);
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
233d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    memcpy(data, m_PLT1, plt1->size());
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t* offset;
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 2);
23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = GOTEntryOffset;
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    GOTEntryOffset += GOTEntrySize;
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 7);
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = PLTRelOffset;
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTRelOffset += sizeof (llvm::ELF::Elf32_Rel);
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 12);
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = -(PLTEntryOffset + 12 + 4);
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTEntryOffset += m_PLT1Size;
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
249d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1->setValue(data);
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++it;
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64PLT
2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT::X86_64PLT(LDSection& pSection,
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     X86_64GOTPLT& pGOTPLT,
2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     const LinkerConfig& pConfig)
2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86PLT(pSection, pConfig, 64),
2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_GOTPLT(pGOTPLT) {
2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT0()
2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt0 = getPLT0();
2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned char* data = 0;
2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  data = static_cast<unsigned char*>(malloc(plt0->size()));
2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!data)
2736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::fail_allocate_memory_plt);
2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  memcpy(data, m_PLT0, plt0->size());
2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // pushq GOT + 8(%rip)
2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
2796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 8 - 6;
2806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // jmq *GOT + 16(%rip)
2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  offset = reinterpret_cast<uint32_t*>(data + 8);
2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 16 - 12;
2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  plt0->setValue(data);
2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT1()
2896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_Section.addr() && ".plt base address is NULL!");
2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86PLT::iterator it = m_SectionData->begin();
2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86PLT::iterator ie = m_SectionData->end();
2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
2956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_64GOTEntry::EntrySize;
2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // compute sym@GOTPCREL of the PLT1 entry.
2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t SymGOTPCREL = m_GOTPLT.addr();
3006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Skip GOT0
3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL += GOTEntrySize * X86GOTPLT0Num;
3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip PLT0
3056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTEntryOffset = m_PLT0Size;
3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ++it;
3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PC-relative to entry in PLT section.
3096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL -= addr() + PLTEntryOffset + 6;
3106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt1 = 0;
3126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTRelIndex = 0;
3146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  while (it != ie) {
3166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1 = &(llvm::cast<PLTEntryBase>(*it));
3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    unsigned char *data;
3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    data = static_cast<unsigned char*>(malloc(plt1->size()));
3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!data)
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::fail_allocate_memory_plt);
3226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    memcpy(data, m_PLT1, plt1->size());
3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t* offset;
3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq *sym@GOTPCREL(%rip)
3286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 2);
3296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = SymGOTPCREL;
3306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    SymGOTPCREL += GOTEntrySize - m_PLT1Size;
3316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // pushq $index
3336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 7);
3346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = PLTRelIndex;
3356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTRelIndex++;
3366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq plt0
3386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 12);
3396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = -(PLTEntryOffset + 12 + 4);
3406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTEntryOffset += m_PLT1Size;
3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1->setValue(data);
3436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ++it;
3446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
347