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