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