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//===----------------------------------------------------------------------===//
57551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesX86PLT::X86PLT(LDSection& pSection, const LinkerConfig& pConfig, int got_size)
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : PLT(pSection),
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Config(pConfig)
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         LinkerConfig::Exec   == m_Config.codeGenType() ||
63d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         LinkerConfig::Binary == m_Config.codeGenType());
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (got_size == 32) {
666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LinkerConfig::DynObj == m_Config.codeGenType()) {
676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0 = x86_32_dyn_plt0;
686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1 = x86_32_dyn_plt1;
696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0Size = sizeof (x86_32_dyn_plt0);
706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1Size = sizeof (x86_32_dyn_plt1);
716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // create PLT0
72551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      new X86_32DynPLT0(*m_pSectionData);
736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0 = x86_32_exec_plt0;
766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1 = x86_32_exec_plt1;
776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0Size = sizeof (x86_32_exec_plt0);
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1Size = sizeof (x86_32_exec_plt1);
796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // create PLT0
80551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      new X86_32ExecPLT0(*m_pSectionData);
816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    assert(got_size == 64);
856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT0 = x86_64_plt0;
866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT1 = x86_64_plt1;
876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT0Size = sizeof (x86_64_plt0);
886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT1Size = sizeof (x86_64_plt1);
89d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // create PLT0
90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    new X86_64PLT0(*m_pSectionData);
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86PLT::~X86PLT()
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86PLT::finalizeSectionSize()
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t size = 0;
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // plt0 size
102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  size = getPLT0()->size();
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first plt1 entry
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator it = begin();
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ++it;
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (end() != it) {
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // plt1 size
109d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it));
110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    size += (m_pSectionData->size() - 1) * plt1->size();
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_Section.setSize(size);
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = 0;
115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::iterator frag, fragEnd = m_pSectionData->end();
116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) {
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag->setOffset(offset);
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset += frag->size();
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool X86PLT::hasPLT1() const
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
124551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return (m_pSectionData->size() > 1);
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12787f34658dec9097d987d254a990ea7f311bfc95fStephen HinesPLTEntryBase* X86PLT::create()
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::DynObj == m_Config.codeGenType())
130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return new X86_32DynPLT1(*m_pSectionData);
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
132551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return new X86_32ExecPLT1(*m_pSectionData);
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
135d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoPLTEntryBase* X86PLT::getPLT0() const
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  iterator first = m_pSectionData->getFragmentList().begin();
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
139551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(first != m_pSectionData->getFragmentList().end() &&
14067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao         "FragmentList is empty, getPLT0 failed!");
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return plt0;
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32PLT
1496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32PLT::X86_32PLT(LDSection& pSection,
151551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     X86_32GOTPLT& pGOTPLT,
152551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     const LinkerConfig& pConfig)
1536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86PLT(pSection, pConfig, 32),
1546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_GOTPLT(pGOTPLT) {
1556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
1586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT0()
15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
160d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = getPLT0();
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  unsigned char* data = 0;
163d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  data = static_cast<unsigned char*>(malloc(plt0->size()));
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!data)
166cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    fatal(diag::fail_allocate_memory_plt);
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
168d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  memcpy(data, m_PLT0, plt0->size());
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_PLT0 == x86_32_exec_plt0) {
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 4;
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 8);
17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 8;
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
177d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  plt0->setValue(data);
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
1816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT1()
18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(m_Section.addr() && ".plt base address is NULL!");
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
185551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator it = m_pSectionData->begin();
186551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator ie = m_pSectionData->end();
18767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_32GOTEntry::EntrySize;
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Skip GOT0
192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Exec == m_Config.codeGenType())
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    GOTEntryOffset += m_GOTPLT.addr();
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //skip PLT0
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTEntryOffset = m_PLT0Size;
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++it;
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
200d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt1 = 0;
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTRelOffset = 0;
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (it != ie) {
205d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1 = &(llvm::cast<PLTEntryBase>(*it));
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    unsigned char *data;
207d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    data = static_cast<unsigned char*>(malloc(plt1->size()));
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (!data)
210cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::fail_allocate_memory_plt);
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
212d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    memcpy(data, m_PLT1, plt1->size());
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t* offset;
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 2);
21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = GOTEntryOffset;
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    GOTEntryOffset += GOTEntrySize;
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 7);
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = PLTRelOffset;
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTRelOffset += sizeof (llvm::ELF::Elf32_Rel);
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 12);
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = -(PLTEntryOffset + 12 + 4);
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTEntryOffset += m_PLT1Size;
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
228d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1->setValue(data);
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++it;
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64PLT
2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT::X86_64PLT(LDSection& pSection,
237551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     X86_64GOTPLT& pGOTPLT,
238551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     const LinkerConfig& pConfig)
2396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86PLT(pSection, pConfig, 64),
2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_GOTPLT(pGOTPLT) {
2416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT0()
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt0 = getPLT0();
2476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned char* data = 0;
2496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  data = static_cast<unsigned char*>(malloc(plt0->size()));
2506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!data)
2526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::fail_allocate_memory_plt);
2536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  memcpy(data, m_PLT0, plt0->size());
2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // pushq GOT + 8(%rip)
2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 8 - 6;
2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // jmq *GOT + 16(%rip)
2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  offset = reinterpret_cast<uint32_t*>(data + 8);
2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 16 - 12;
2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  plt0->setValue(data);
2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT1()
2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_Section.addr() && ".plt base address is NULL!");
2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator it = m_pSectionData->begin();
272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator ie = m_pSectionData->end();
2736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_64GOTEntry::EntrySize;
2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // compute sym@GOTPCREL of the PLT1 entry.
2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t SymGOTPCREL = m_GOTPLT.addr();
2796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Skip GOT0
2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL += GOTEntrySize * X86GOTPLT0Num;
2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip PLT0
2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTEntryOffset = m_PLT0Size;
2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ++it;
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PC-relative to entry in PLT section.
2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL -= addr() + PLTEntryOffset + 6;
2896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt1 = 0;
2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTRelIndex = 0;
2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  while (it != ie) {
2956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1 = &(llvm::cast<PLTEntryBase>(*it));
2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    unsigned char *data;
2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    data = static_cast<unsigned char*>(malloc(plt1->size()));
2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!data)
3006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::fail_allocate_memory_plt);
3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    memcpy(data, m_PLT1, plt1->size());
3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t* offset;
3056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq *sym@GOTPCREL(%rip)
3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 2);
3086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = SymGOTPCREL;
3096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    SymGOTPCREL += GOTEntrySize - m_PLT1Size;
3106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // pushq $index
3126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 7);
3136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = PLTRelIndex;
3146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTRelIndex++;
3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq plt0
3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 12);
3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = -(PLTEntryOffset + 12 + 4);
3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTEntryOffset += m_PLT1Size;
3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1->setValue(data);
3226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ++it;
3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
326