X86PLT.cpp revision 87f34658dec9097d987d254a990ea7f311bfc95f
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);
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86PLT::~X86PLT()
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86PLT::finalizeSectionSize()
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t size = 0;
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // plt0 size
104d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  size = getPLT0()->size();
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first plt1 entry
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator it = begin();
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ++it;
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (end() != it) {
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // plt1 size
111d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it));
112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    size += (m_SectionData->size() - 1) * plt1->size();
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_Section.setSize(size);
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = 0;
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData::iterator frag, fragEnd = m_SectionData->end();
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag->setOffset(offset);
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset += frag->size();
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool X86PLT::hasPLT1() const
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (m_SectionData->size() > 1);
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12987f34658dec9097d987d254a990ea7f311bfc95fStephen HinesPLTEntryBase* X86PLT::create()
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::DynObj == m_Config.codeGenType())
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return new X86_32DynPLT1(*m_SectionData);
13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
13487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return new X86_32ExecPLT1(*m_SectionData);
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoPLTEntryBase* X86PLT::getPLT0() const
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  iterator first = m_SectionData->getFragmentList().begin();
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(first != m_SectionData->getFragmentList().end() &&
14267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao         "FragmentList is empty, getPLT0 failed!");
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return plt0;
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32PLT
1516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32PLT::X86_32PLT(LDSection& pSection,
1536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     X86_32GOTPLT& pGOTPLT,
1546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     const LinkerConfig& pConfig)
1556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86PLT(pSection, pConfig, 32),
1566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_GOTPLT(pGOTPLT) {
1576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
1606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT0()
16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
162d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = getPLT0();
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  unsigned char* data = 0;
165d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  data = static_cast<unsigned char*>(malloc(plt0->size()));
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!data)
168cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    fatal(diag::fail_allocate_memory_plt);
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
170d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  memcpy(data, m_PLT0, plt0->size());
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_PLT0 == x86_32_exec_plt0) {
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 4;
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 8);
17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 8;
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
179d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  plt0->setValue(data);
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
1836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT1()
18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(m_Section.addr() && ".plt base address is NULL!");
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator it = m_SectionData->begin();
18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator ie = m_SectionData->end();
18967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_32GOTEntry::EntrySize;
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Skip GOT0
194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Exec == m_Config.codeGenType())
19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    GOTEntryOffset += m_GOTPLT.addr();
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //skip PLT0
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTEntryOffset = m_PLT0Size;
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++it;
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
202d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt1 = 0;
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTRelOffset = 0;
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (it != ie) {
207d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1 = &(llvm::cast<PLTEntryBase>(*it));
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    unsigned char *data;
209d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    data = static_cast<unsigned char*>(malloc(plt1->size()));
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (!data)
212cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::fail_allocate_memory_plt);
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
214d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    memcpy(data, m_PLT1, plt1->size());
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t* offset;
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 2);
21922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = GOTEntryOffset;
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    GOTEntryOffset += GOTEntrySize;
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 7);
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = PLTRelOffset;
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTRelOffset += sizeof (llvm::ELF::Elf32_Rel);
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 12);
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = -(PLTEntryOffset + 12 + 4);
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTEntryOffset += m_PLT1Size;
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
230d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1->setValue(data);
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++it;
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64PLT
2376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT::X86_64PLT(LDSection& pSection,
2396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     X86_64GOTPLT& pGOTPLT,
2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		     const LinkerConfig& pConfig)
2416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : X86PLT(pSection, pConfig, 64),
2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_GOTPLT(pGOTPLT) {
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT0()
2476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt0 = getPLT0();
2496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned char* data = 0;
2516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  data = static_cast<unsigned char*>(malloc(plt0->size()));
2526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!data)
2546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::fail_allocate_memory_plt);
2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  memcpy(data, m_PLT0, plt0->size());
2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // pushq GOT + 8(%rip)
2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 8 - 6;
2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // jmq *GOT + 16(%rip)
2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  offset = reinterpret_cast<uint32_t*>(data + 8);
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 16 - 12;
2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  plt0->setValue(data);
2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT1()
2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_Section.addr() && ".plt base address is NULL!");
2726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86PLT::iterator it = m_SectionData->begin();
2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86PLT::iterator ie = m_SectionData->end();
2756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_64GOTEntry::EntrySize;
2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // compute sym@GOTPCREL of the PLT1 entry.
2806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t SymGOTPCREL = m_GOTPLT.addr();
2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Skip GOT0
2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL += GOTEntrySize * X86GOTPLT0Num;
2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip PLT0
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTEntryOffset = m_PLT0Size;
2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ++it;
2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PC-relative to entry in PLT section.
2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL -= addr() + PLTEntryOffset + 6;
2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt1 = 0;
2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTRelIndex = 0;
2956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  while (it != ie) {
2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1 = &(llvm::cast<PLTEntryBase>(*it));
2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    unsigned char *data;
2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    data = static_cast<unsigned char*>(malloc(plt1->size()));
3006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!data)
3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::fail_allocate_memory_plt);
3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    memcpy(data, m_PLT1, plt1->size());
3056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t* offset;
3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq *sym@GOTPCREL(%rip)
3096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 2);
3106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = SymGOTPCREL;
3116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    SymGOTPCREL += GOTEntrySize - m_PLT1Size;
3126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // pushq $index
3146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 7);
3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = PLTRelIndex;
3166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTRelIndex++;
3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq plt0
3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 12);
3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = -(PLTEntryOffset + 12 + 4);
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTEntryOffset += m_PLT1Size;
3226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1->setValue(data);
3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ++it;
3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
328