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); 936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_Last = m_SectionData->begin(); 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_Last = m_SectionData->begin(); 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86PLT::~X86PLT() 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86PLT::finalizeSectionSize() 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t size = 0; 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // plt0 size 106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao size = getPLT0()->size(); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get first plt1 entry 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao X86PLT::iterator it = begin(); 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++it; 11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (end() != it) { 11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // plt1 size 113d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it)); 114d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao size += (m_SectionData->size() - 1) * plt1->size(); 11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_Section.setSize(size); 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t offset = 0; 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SectionData::iterator frag, fragEnd = m_SectionData->end(); 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) { 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao frag->setOffset(offset); 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao offset += frag->size(); 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool X86PLT::hasPLT1() const 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return (m_SectionData->size() > 1); 12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86PLT::reserveEntry(size_t pNum) 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 133d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt1_entry = NULL; 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (size_t i = 0; i < pNum; ++i) { 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (LinkerConfig::DynObj == m_Config.codeGenType()) 1386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt1_entry = new X86_32DynPLT1(*m_SectionData); 139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao else 1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt1_entry = new X86_32ExecPLT1(*m_SectionData); 141d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (NULL == plt1_entry) 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoPLTEntryBase* X86PLT::consume() 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // This will skip PLT0. 15022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++m_Last; 15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(m_Last != m_SectionData->end() && 15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao "The number of PLT Entries and ResolveInfo doesn't match"); 153d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return llvm::cast<PLTEntryBase>(&(*m_Last)); 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 156d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoPLTEntryBase* X86PLT::getPLT0() const 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao iterator first = m_SectionData->getFragmentList().begin(); 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(first != m_SectionData->getFragmentList().end() && 16167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao "FragmentList is empty, getPLT0 failed!"); 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 163d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first)); 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return plt0; 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 1696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32PLT 1706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32PLT::X86_32PLT(LDSection& pSection, 1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTPLT& pGOTPLT, 1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const LinkerConfig& pConfig) 1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : X86PLT(pSection, pConfig, 32), 1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_GOTPLT(pGOTPLT) { 1766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine. 1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT0() 18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 181d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt0 = getPLT0(); 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned char* data = 0; 184d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao data = static_cast<unsigned char*>(malloc(plt0->size())); 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!data) 187cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 189d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(data, m_PLT0, plt0->size()); 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (m_PLT0 == x86_32_exec_plt0) { 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2); 19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *offset = m_GOTPLT.addr() + 4; 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = reinterpret_cast<uint32_t*>(data + 8); 19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *offset = m_GOTPLT.addr() + 8; 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 198d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt0->setValue(data); 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// FIXME: It only works on little endian machine. 2026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32PLT::applyPLT1() 20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(m_Section.addr() && ".plt base address is NULL!"); 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao X86PLT::iterator it = m_SectionData->begin(); 20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao X86PLT::iterator ie = m_SectionData->end(); 20867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t GOTEntrySize = X86_32GOTEntry::EntrySize; 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Skip GOT0 213affc150dc44fab1911775a49636d0ce85333b634Zonr Chang uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num; 21422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::Exec == m_Config.codeGenType()) 21522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao GOTEntryOffset += m_GOTPLT.addr(); 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao //skip PLT0 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t PLTEntryOffset = m_PLT0Size; 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 221d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt1 = 0; 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t PLTRelOffset = 0; 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (it != ie) { 226d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt1 = &(llvm::cast<PLTEntryBase>(*it)); 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned char *data; 228d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao data = static_cast<unsigned char*>(malloc(plt1->size())); 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!data) 231cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 233d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(data, m_PLT1, plt1->size()); 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t* offset; 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = reinterpret_cast<uint32_t*>(data + 2); 23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *offset = GOTEntryOffset; 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntryOffset += GOTEntrySize; 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = reinterpret_cast<uint32_t*>(data + 7); 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *offset = PLTRelOffset; 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTRelOffset += sizeof (llvm::ELF::Elf32_Rel); 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = reinterpret_cast<uint32_t*>(data + 12); 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *offset = -(PLTEntryOffset + 12 + 4); 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntryOffset += m_PLT1Size; 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 249d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt1->setValue(data); 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64PLT 2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64PLT::X86_64PLT(LDSection& pSection, 2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTPLT& pGOTPLT, 2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const LinkerConfig& pConfig) 2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : X86PLT(pSection, pConfig, 64), 2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_GOTPLT(pGOTPLT) { 2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine. 2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT0() 2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase* plt0 = getPLT0(); 2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned char* data = 0; 2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines data = static_cast<unsigned char*>(malloc(plt0->size())); 2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!data) 2736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::fail_allocate_memory_plt); 2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines memcpy(data, m_PLT0, plt0->size()); 2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // pushq GOT + 8(%rip) 2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2); 2796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *offset = m_GOTPLT.addr() - addr() + 8 - 6; 2806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // jmq *GOT + 16(%rip) 2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines offset = reinterpret_cast<uint32_t*>(data + 8); 2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *offset = m_GOTPLT.addr() - addr() + 16 - 12; 2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt0->setValue(data); 2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// FIXME: It only works on little endian machine. 2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64PLT::applyPLT1() 2896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(m_Section.addr() && ".plt base address is NULL!"); 2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86PLT::iterator it = m_SectionData->begin(); 2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86PLT::iterator ie = m_SectionData->end(); 2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 2956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t GOTEntrySize = X86_64GOTEntry::EntrySize; 2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // compute sym@GOTPCREL of the PLT1 entry. 2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t SymGOTPCREL = m_GOTPLT.addr(); 3006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Skip GOT0 3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines SymGOTPCREL += GOTEntrySize * X86GOTPLT0Num; 3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // skip PLT0 3056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t PLTEntryOffset = m_PLT0Size; 3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ++it; 3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // PC-relative to entry in PLT section. 3096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines SymGOTPCREL -= addr() + PLTEntryOffset + 6; 3106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase* plt1 = 0; 3126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t PLTRelIndex = 0; 3146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines while (it != ie) { 3166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt1 = &(llvm::cast<PLTEntryBase>(*it)); 3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned char *data; 3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines data = static_cast<unsigned char*>(malloc(plt1->size())); 3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!data) 3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::fail_allocate_memory_plt); 3226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines memcpy(data, m_PLT1, plt1->size()); 3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint32_t* offset; 3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // jmpq *sym@GOTPCREL(%rip) 3286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines offset = reinterpret_cast<uint32_t*>(data + 2); 3296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *offset = SymGOTPCREL; 3306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines SymGOTPCREL += GOTEntrySize - m_PLT1Size; 3316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // pushq $index 3336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines offset = reinterpret_cast<uint32_t*>(data + 7); 3346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *offset = PLTRelIndex; 3356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTRelIndex++; 3366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // jmpq plt0 3386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines offset = reinterpret_cast<uint32_t*>(data + 12); 3396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *offset = -(PLTEntryOffset + 12 + 4); 3406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryOffset += m_PLT1Size; 3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt1->setValue(data); 3436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ++it; 3446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 3456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 347