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
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
17cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
18cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
21cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
22cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// PLT entry data
23cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32DynPLT0::X86_32DynPLT0(SectionData& pParent)
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT::Entry<sizeof(x86_32_dyn_plt0)>(pParent) {
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32DynPLT1::X86_32DynPLT1(SectionData& pParent)
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT::Entry<sizeof(x86_32_dyn_plt1)>(pParent) {
30d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32ExecPLT0::X86_32ExecPLT0(SectionData& pParent)
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT::Entry<sizeof(x86_32_exec_plt0)>(pParent) {
34d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32ExecPLT1::X86_32ExecPLT1(SectionData& pParent)
3737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT::Entry<sizeof(x86_32_exec_plt1)>(pParent) {
386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT0::X86_64PLT0(SectionData& pParent)
4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT::Entry<sizeof(x86_64_plt0)>(pParent) {
426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT1::X86_64PLT1(SectionData& pParent)
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT::Entry<sizeof(x86_64_plt1)>(pParent) {
46d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// X86PLT
50cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesX86PLT::X86PLT(LDSection& pSection, const LinkerConfig& pConfig, int got_size)
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : PLT(pSection), m_Config(pConfig) {
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines         LinkerConfig::Exec == m_Config.codeGenType() ||
55d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao         LinkerConfig::Binary == m_Config.codeGenType());
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (got_size == 32) {
586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LinkerConfig::DynObj == m_Config.codeGenType()) {
596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0 = x86_32_dyn_plt0;
606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1 = x86_32_dyn_plt1;
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_PLT0Size = sizeof(x86_32_dyn_plt0);
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_PLT1Size = sizeof(x86_32_dyn_plt1);
636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // create PLT0
64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      new X86_32DynPLT0(*m_pSectionData);
6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT0 = x86_32_exec_plt0;
676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PLT1 = x86_32_exec_plt1;
6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_PLT0Size = sizeof(x86_32_exec_plt0);
6937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_PLT1Size = sizeof(x86_32_exec_plt1);
706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // create PLT0
71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      new X86_32ExecPLT0(*m_pSectionData);
726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    assert(got_size == 64);
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT0 = x86_64_plt0;
766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PLT1 = x86_64_plt1;
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_PLT0Size = sizeof(x86_64_plt0);
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_PLT1Size = sizeof(x86_64_plt1);
79d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // create PLT0
80551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    new X86_64PLT0(*m_pSectionData);
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8437b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86PLT::~X86PLT() {
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86PLT::finalizeSectionSize() {
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t size = 0;
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // plt0 size
90d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  size = getPLT0()->size();
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first plt1 entry
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  X86PLT::iterator it = begin();
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ++it;
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (end() != it) {
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // plt1 size
97d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it));
98551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    size += (m_pSectionData->size() - 1) * plt1->size();
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_Section.setSize(size);
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = 0;
103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::iterator frag, fragEnd = m_pSectionData->end();
104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) {
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag->setOffset(offset);
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset += frag->size();
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86PLT::hasPLT1() const {
111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return (m_pSectionData->size() > 1);
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11437b74a387bb3993387029859c2d9d051c41c724eStephen HinesPLTEntryBase* X86PLT::create() {
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::DynObj == m_Config.codeGenType())
116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return new X86_32DynPLT1(*m_pSectionData);
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
118551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return new X86_32ExecPLT1(*m_pSectionData);
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12137b74a387bb3993387029859c2d9d051c41c724eStephen HinesPLTEntryBase* X86PLT::getPLT0() const {
122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  iterator first = m_pSectionData->getFragmentList().begin();
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
124551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(first != m_pSectionData->getFragmentList().end() &&
12567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao         "FragmentList is empty, getPLT0 failed!");
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
127d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return plt0;
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32PLT
1346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
1356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32PLT::X86_32PLT(LDSection& pSection,
136551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     X86_32GOTPLT& pGOTPLT,
137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     const LinkerConfig& pConfig)
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : X86PLT(pSection, pConfig, 32), m_GOTPLT(pGOTPLT) {
1396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32PLT::applyPLT0() {
143d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt0 = getPLT0();
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  unsigned char* data = 0;
146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  data = static_cast<unsigned char*>(malloc(plt0->size()));
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!data)
149cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    fatal(diag::fail_allocate_memory_plt);
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
151d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  memcpy(data, m_PLT0, plt0->size());
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_PLT0 == x86_32_exec_plt0) {
15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    uint32_t* offset = reinterpret_cast<uint32_t*>(data + 2);
15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 4;
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 8);
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = m_GOTPLT.addr() + 8;
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
160d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  plt0->setValue(data);
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine.
16437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32PLT::applyPLT1() {
16522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(m_Section.addr() && ".plt base address is NULL!");
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator it = m_pSectionData->begin();
168551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator ie = m_pSectionData->end();
16967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_32GOTEntry::EntrySize;
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Skip GOT0
174affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Exec == m_Config.codeGenType())
17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    GOTEntryOffset += m_GOTPLT.addr();
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
17837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // skip PLT0
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTEntryOffset = m_PLT0Size;
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++it;
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
182d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt1 = 0;
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTRelOffset = 0;
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (it != ie) {
187d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1 = &(llvm::cast<PLTEntryBase>(*it));
18837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    unsigned char* data;
189d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    data = static_cast<unsigned char*>(malloc(plt1->size()));
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (!data)
192cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::fail_allocate_memory_plt);
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
194d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    memcpy(data, m_PLT1, plt1->size());
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint32_t* offset;
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 2);
19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    *offset = GOTEntryOffset;
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    GOTEntryOffset += GOTEntrySize;
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 7);
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = PLTRelOffset;
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    PLTRelOffset += sizeof(llvm::ELF::Elf32_Rel);
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = reinterpret_cast<uint32_t*>(data + 12);
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *offset = -(PLTEntryOffset + 12 + 4);
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTEntryOffset += m_PLT1Size;
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
210d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1->setValue(data);
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++it;
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64PLT
2176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT::X86_64PLT(LDSection& pSection,
219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     X86_64GOTPLT& pGOTPLT,
220551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     const LinkerConfig& pConfig)
22137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : X86PLT(pSection, pConfig, 64), m_GOTPLT(pGOTPLT) {
2226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
22537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64PLT::applyPLT0() {
2266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt0 = getPLT0();
2276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned char* data = 0;
2296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  data = static_cast<unsigned char*>(malloc(plt0->size()));
2306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!data)
2326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::fail_allocate_memory_plt);
2336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  memcpy(data, m_PLT0, plt0->size());
2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // pushq GOT + 8(%rip)
23737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t* offset = reinterpret_cast<uint32_t*>(data + 2);
2386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 8 - 6;
2396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // jmq *GOT + 16(%rip)
2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  offset = reinterpret_cast<uint32_t*>(data + 8);
2416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  *offset = m_GOTPLT.addr() - addr() + 16 - 12;
2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  plt0->setValue(data);
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine.
24737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64PLT::applyPLT1() {
2486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_Section.addr() && ".plt base address is NULL!");
2496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
250551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator it = m_pSectionData->begin();
251551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  X86PLT::iterator ie = m_pSectionData->end();
2526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
2536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t GOTEntrySize = X86_64GOTEntry::EntrySize;
2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // compute sym@GOTPCREL of the PLT1 entry.
2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t SymGOTPCREL = m_GOTPLT.addr();
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Skip GOT0
2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL += GOTEntrySize * X86GOTPLT0Num;
2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip PLT0
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTEntryOffset = m_PLT0Size;
2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ++it;
2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PC-relative to entry in PLT section.
2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SymGOTPCREL -= addr() + PLTEntryOffset + 6;
2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt1 = 0;
2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t PLTRelIndex = 0;
2726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  while (it != ie) {
2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1 = &(llvm::cast<PLTEntryBase>(*it));
27537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    unsigned char* data;
2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    data = static_cast<unsigned char*>(malloc(plt1->size()));
2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!data)
2796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::fail_allocate_memory_plt);
2806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    memcpy(data, m_PLT1, plt1->size());
2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t* offset;
2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq *sym@GOTPCREL(%rip)
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 2);
2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = SymGOTPCREL;
2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    SymGOTPCREL += GOTEntrySize - m_PLT1Size;
2896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // pushq $index
2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 7);
2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = PLTRelIndex;
2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTRelIndex++;
2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // jmpq plt0
2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    offset = reinterpret_cast<uint32_t*>(data + 12);
2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *offset = -(PLTEntryOffset + 12 + 4);
2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTEntryOffset += m_PLT1Size;
2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    plt1->setValue(data);
3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ++it;
3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
30537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
306