137b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===- ARMPLT.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//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMGOT.h" 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMPLT.h" 11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines 15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <new> 16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 17cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h> 18cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 1937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2137b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMPLT0::ARMPLT0(SectionData& pParent) : PLT::Entry<sizeof(arm_plt0)>(pParent) { 2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2437b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMPLT1::ARMPLT1(SectionData& pParent) : PLT::Entry<sizeof(arm_plt1)>(pParent) { 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMPLT 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3037b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMPLT::ARMPLT(LDSection& pSection, ARMGOT& pGOTPLT) 3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines : PLT(pSection), m_GOT(pGOTPLT) { 32551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines new ARMPLT0(*m_pSectionData); 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3537b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMPLT::~ARMPLT() { 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMPLT::hasPLT1() const { 39551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return (m_pSectionData->size() > 1); 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMPLT::finalizeSectionSize() { 4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t size = 4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines (m_pSectionData->size() - 1) * sizeof(arm_plt1) + sizeof(arm_plt0); 4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_Section.setSize(size); 4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t offset = 0; 48551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData::iterator frag, fragEnd = m_pSectionData->end(); 49551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) { 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao frag->setOffset(offset); 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao offset += frag->size(); 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5537b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMPLT1* ARMPLT::create() { 56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ARMPLT1* plt1_entry = new (std::nothrow) ARMPLT1(*m_pSectionData); 5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!plt1_entry) 5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines fatal(diag::fail_allocate_memory_plt); 5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return plt1_entry; 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMPLT::applyPLT0() { 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t plt_base = m_Section.addr(); 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(plt_base && ".plt base address is NULL!"); 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t got_base = m_GOT.addr(); 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(got_base && ".got base address is NULL!"); 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t offset = 0; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (got_base > plt_base) 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = got_base - (plt_base + 16); 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = (plt_base + 16) - got_base; 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines iterator first = m_pSectionData->getFragmentList().begin(); 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 78551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(first != m_pSectionData->getFragmentList().end() && 7967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao "FragmentList is empty, applyPLT0 failed!"); 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first)); 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t* data = 0; 84d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao data = static_cast<uint32_t*>(malloc(ARMPLT0::EntrySize)); 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!data) 87cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 89d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(data, arm_plt0, ARMPLT0::EntrySize); 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao data[4] = offset; 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 92d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt0->setValue(reinterpret_cast<unsigned char*>(data)); 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMPLT::applyPLT1() { 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t plt_base = m_Section.addr(); 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(plt_base && ".plt base address is NULL!"); 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t got_base = m_GOT.addr(); 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(got_base && ".got base address is NULL!"); 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 102551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ARMPLT::iterator it = m_pSectionData->begin(); 103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ARMPLT::iterator ie = m_pSectionData->end(); 10467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao uint32_t GOTEntrySize = ARMGOTEntry::EntrySize; 10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint32_t GOTEntryAddress = got_base + GOTEntrySize * 3; 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t PLTEntryAddress = plt_base + ARMPLT0::EntrySize; // Offset of PLT0 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it; // skip PLT0 112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao uint64_t PLT1EntrySize = ARMPLT1::EntrySize; 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT1* plt1 = NULL; 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t* Out = NULL; 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (it != ie) { 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao plt1 = &(llvm::cast<ARMPLT1>(*it)); 118d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Out = static_cast<uint32_t*>(malloc(ARMPLT1::EntrySize)); 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!Out) 121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Offset is the distance between the last PLT entry and the associated 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // GOT entry. 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t Offset = (GOTEntryAddress - (PLTEntryAddress + 8)); 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Out[0] = arm_plt1[0] | ((Offset >> 20) & 0xFF); 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Out[1] = arm_plt1[1] | ((Offset >> 12) & 0xFF); 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Out[2] = arm_plt1[2] | (Offset & 0xFFF); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt1->setValue(reinterpret_cast<unsigned char*>(Out)); 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntryAddress += GOTEntrySize; 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntryAddress += PLT1EntrySize; 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOT.applyGOTPLT(plt_base); 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t ARMPLT::emit(MemoryRegion& pRegion) { 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t result = 0x0; 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao iterator it = begin(); 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines unsigned char* buffer = pRegion.begin(); 146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getValue(), ARMPLT0::EntrySize); 147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao result += ARMPLT0::EntrySize; 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT1* plt1 = 0; 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT::iterator ie = end(); 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (it != ie) { 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao plt1 = &(llvm::cast<ARMPLT1>(*it)); 154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(buffer + result, plt1->getValue(), ARMPLT1::EntrySize); 155d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao result += ARMPLT1::EntrySize; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 160affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 162