ARMPLT.cpp revision 87f34658dec9097d987d254a990ea7f311bfc95f
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- 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 12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <new> 13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h> 15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h> 17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMPLT0::ARMPLT0(SectionData& pParent) 22d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : PLT::Entry<sizeof(arm_plt0)>(pParent) {} 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMPLT1::ARMPLT1(SectionData& pParent) 25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : PLT::Entry<sizeof(arm_plt1)>(pParent) {} 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMPLT 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3087f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMPLT::ARMPLT(LDSection& pSection, ARMGOT &pGOTPLT) 3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines : PLT(pSection), m_GOT(pGOTPLT) { 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao new ARMPLT0(*m_SectionData); 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMPLT::~ARMPLT() 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMPLT::hasPLT1() const 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return (m_SectionData->size() > 1); 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMPLT::finalizeSectionSize() 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t size = (m_SectionData->size() - 1) * sizeof(arm_plt1) + 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao sizeof(arm_plt0); 4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_Section.setSize(size); 4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t offset = 0; 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SectionData::iterator frag, fragEnd = m_SectionData->end(); 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) { 5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao frag->setOffset(offset); 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao offset += frag->size(); 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMPLT1* ARMPLT::create() 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMPLT1* plt1_entry = new (std::nothrow) ARMPLT1(*m_SectionData); 6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!plt1_entry) 6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines fatal(diag::fail_allocate_memory_plt); 6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return plt1_entry; 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ARMPLT::applyPLT0() { 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t plt_base = m_Section.addr(); 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(plt_base && ".plt base address is NULL!"); 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t got_base = m_GOT.addr(); 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(got_base && ".got base address is NULL!"); 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t offset = 0; 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (got_base > plt_base) 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = got_base - (plt_base + 16); 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao offset = (plt_base + 16) - got_base; 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao iterator first = m_SectionData->getFragmentList().begin(); 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(first != m_SectionData->getFragmentList().end() && 8467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao "FragmentList is empty, applyPLT0 failed!"); 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first)); 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t* data = 0; 89d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao data = static_cast<uint32_t*>(malloc(ARMPLT0::EntrySize)); 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!data) 92cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 94d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(data, arm_plt0, ARMPLT0::EntrySize); 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao data[4] = offset; 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 97d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt0->setValue(reinterpret_cast<unsigned char*>(data)); 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ARMPLT::applyPLT1() { 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t plt_base = m_Section.addr(); 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(plt_base && ".plt base address is NULL!"); 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t got_base = m_GOT.addr(); 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(got_base && ".got base address is NULL!"); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ARMPLT::iterator it = m_SectionData->begin(); 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ARMPLT::iterator ie = m_SectionData->end(); 11067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao uint32_t GOTEntrySize = ARMGOTEntry::EntrySize; 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t GOTEntryAddress = 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_base + GOTEntrySize * 3; 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t PLTEntryAddress = 117d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt_base + ARMPLT0::EntrySize; //Offset of PLT0 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; //skip PLT0 120d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao uint64_t PLT1EntrySize = ARMPLT1::EntrySize; 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT1* plt1 = NULL; 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t* Out = NULL; 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (it != ie) { 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao plt1 = &(llvm::cast<ARMPLT1>(*it)); 126d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Out = static_cast<uint32_t*>(malloc(ARMPLT1::EntrySize)); 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!Out) 129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::fail_allocate_memory_plt); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Offset is the distance between the last PLT entry and the associated 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // GOT entry. 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t Offset = (GOTEntryAddress - (PLTEntryAddress + 8)); 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Out[0] = arm_plt1[0] | ((Offset >> 20) & 0xFF); 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Out[1] = arm_plt1[1] | ((Offset >> 12) & 0xFF); 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Out[2] = arm_plt1[2] | (Offset & 0xFFF); 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao plt1->setValue(reinterpret_cast<unsigned char*>(Out)); 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntryAddress += GOTEntrySize; 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntryAddress += PLT1EntrySize; 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOT.applyGOTPLT(plt_base); 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t ARMPLT::emit(MemoryRegion& pRegion) 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t result = 0x0; 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao iterator it = begin(); 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines unsigned char* buffer = pRegion.begin(); 155d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getValue(), ARMPLT0::EntrySize); 156d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao result += ARMPLT0::EntrySize; 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT1* plt1 = 0; 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMPLT::iterator ie = end(); 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (it != ie) { 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao plt1 = &(llvm::cast<ARMPLT1>(*it)); 163d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao memcpy(buffer + result, plt1->getValue(), ARMPLT1::EntrySize); 164d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao result += ARMPLT1::EntrySize; 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ++it; 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 169affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 170