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