15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- impl.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" 10cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h> 12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/LDFileFormat.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h> 16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace { 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const unsigned int ARMGOT0Num = 3; 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // end of anonymous namespace 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMGOT 2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMGOT::ARMGOT(LDSection& pSection) 27d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : GOT(pSection), m_pLast(NULL) 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Create GOT0 entries. 3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao reserve(ARMGOT0Num); 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Skip GOT0 entries. 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (unsigned int i = 0; i < ARMGOT0Num; ++i) { 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao consume(); 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMGOT::~ARMGOT() 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMGOT::hasGOT1() const 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return (m_SectionData->size() > ARMGOT0Num); 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 47d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid ARMGOT::reserve(size_t pNum) 48d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 49d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao for (size_t i = 0; i < pNum; i++) { 50d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao new ARMGOTEntry(0, m_SectionData); 51d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao } 52d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 53d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 54d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGOTEntry* ARMGOT::consume() 55d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 56d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (NULL == m_pLast) { 57d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao assert(!empty() && "Consume empty GOT entry!"); 58d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pLast = llvm::cast<ARMGOTEntry>(&m_SectionData->front()); 59d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return m_pLast; 60d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao } 61d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pLast = llvm::cast<ARMGOTEntry>(m_pLast->getNextNode()); 63d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return m_pLast; 64d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::reserveGOTPLT() 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 68d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData); 6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOTPLT.front) { 7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOTPLT is empty 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOT.front) { 7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOT part is also empty. Since entry is the last entry, we can assign 7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // it to GOTPLT directly. 7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOTPLT.front = entry; 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOTn is not empty. Shift GOTn backward by one entry. 7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOTPLT.front = m_GOT.front; 79d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode()); 8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOTPLT is not empty 8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != m_GOT.front) 85d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode()); 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::reserveGOT() 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 91d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData); 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOT.front) { 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Entry must be the last entry. We can directly assign it to GOT part. 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOT.front = entry; 9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 98d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGOTEntry* ARMGOT::consumeGOTPLT() 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!"); 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOTPLT.last_used) { 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOTPLT.last_used = m_GOTPLT.front; 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_GOTPLT.last_used = llvm::cast<ARMGOTEntry>(m_GOTPLT.last_used->getNextNode()); 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!"); 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return m_GOTPLT.last_used; 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGOTEntry* ARMGOT::consumeGOT() 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(NULL != m_GOT.front && "Consuming empty GOT section!"); 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOT.last_used) { 11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_GOT.last_used = m_GOT.front; 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 120d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_GOT.last_used = llvm::cast<ARMGOTEntry>(m_GOT.last_used->getNextNode()); 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(m_GOT.last_used != NULL && "No GOTn entry to consume!"); 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return m_GOT.last_used; 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::applyGOT0(uint64_t pAddress) 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao llvm::cast<ARMGOTEntry> 129d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao (*(m_SectionData->getFragmentList().begin())).setValue(pAddress); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::applyGOTPLT(uint64_t pPLTBase) 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOTPLT.front) 13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SectionData::iterator entry(m_GOTPLT.front); 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SectionData::iterator e_end; 13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == m_GOT.front) 14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao e_end = m_SectionData->end(); 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao e_end = SectionData::iterator(m_GOT.front); 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao while (entry != e_end) { 145d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase); 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++entry; 14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t ARMGOT::emit(MemoryRegion& pRegion) 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao ARMGOTEntry* got = NULL; 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t result = 0x0; 15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) { 157d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got = &(llvm::cast<ARMGOTEntry>((*it))); 158d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao *buffer = static_cast<uint32_t>(got->getValue()); 159d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao result += ARMGOTEntry::EntrySize; 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 163affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 164