ARMGOT.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
1//===- impl.cpp -----------------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include "ARMGOT.h" 10 11#include <new> 12 13#include <llvm/Support/Casting.h> 14 15#include <mcld/LD/LDSection.h> 16#include <mcld/LD/LDFileFormat.h> 17#include <mcld/Support/MemoryRegion.h> 18#include <mcld/Support/MsgHandling.h> 19 20namespace { 21 const size_t ARMGOTEntrySize = 4; 22 const unsigned int ARMGOT0Num = 3; 23} // end of anonymous namespace 24 25using namespace mcld; 26 27//===----------------------------------------------------------------------===// 28// ARMGOT 29ARMGOT::ARMGOT(LDSection& pSection) 30 : GOT(pSection, ARMGOTEntrySize) 31{ 32 // Create GOT0 entries. 33 reserve(ARMGOT0Num); 34 35 // Skip GOT0 entries. 36 for (unsigned int i = 0; i < ARMGOT0Num; ++i) { 37 consume(); 38 } 39} 40 41ARMGOT::~ARMGOT() 42{ 43} 44 45bool ARMGOT::hasGOT1() const 46{ 47 return (m_SectionData->size() > ARMGOT0Num); 48} 49 50void ARMGOT::reserveGOTPLT() 51{ 52 Entry* entry = new Entry(0, getEntrySize(), m_SectionData); 53 if (NULL == m_GOTPLT.front) { 54 // GOTPLT is empty 55 if (NULL == m_GOT.front) { 56 // GOT part is also empty. Since entry is the last entry, we can assign 57 // it to GOTPLT directly. 58 m_GOTPLT.front = entry; 59 } 60 else { 61 // GOTn is not empty. Shift GOTn backward by one entry. 62 m_GOTPLT.front = m_GOT.front; 63 m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode()); 64 } 65 } 66 else { 67 // GOTPLT is not empty 68 if (NULL != m_GOT.front) 69 m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode()); 70 } 71} 72 73void ARMGOT::reserveGOT() 74{ 75 Entry* entry = new Entry(0, getEntrySize(), m_SectionData); 76 if (NULL == m_GOT.front) { 77 // Entry must be the last entry. We can directly assign it to GOT part. 78 m_GOT.front = entry; 79 } 80} 81 82GOT::Entry* ARMGOT::consumeGOTPLT() 83{ 84 assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!"); 85 86 if (NULL == m_GOTPLT.last_used) { 87 m_GOTPLT.last_used = m_GOTPLT.front; 88 } 89 else { 90 m_GOTPLT.last_used = llvm::cast<GOT::Entry>(m_GOTPLT.last_used->getNextNode()); 91 assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!"); 92 } 93 return m_GOTPLT.last_used; 94} 95 96GOT::Entry* ARMGOT::consumeGOT() 97{ 98 assert(NULL != m_GOT.front && "Consuming empty GOT section!"); 99 100 if (NULL == m_GOT.last_used) { 101 m_GOT.last_used = m_GOT.front; 102 } 103 else { 104 m_GOT.last_used = llvm::cast<GOT::Entry>(m_GOT.last_used->getNextNode()); 105 assert(m_GOT.last_used != NULL && "No GOTn entry to consume!"); 106 } 107 return m_GOT.last_used; 108} 109 110void ARMGOT::applyGOT0(uint64_t pAddress) 111{ 112 llvm::cast<Entry> 113 (*(m_SectionData->getFragmentList().begin())).setContent(pAddress); 114} 115 116void ARMGOT::applyGOTPLT(uint64_t pPLTBase) 117{ 118 if (NULL == m_GOTPLT.front) 119 return; 120 121 SectionData::iterator entry(m_GOTPLT.front); 122 SectionData::iterator e_end; 123 if (NULL == m_GOT.front) 124 e_end = m_SectionData->end(); 125 else 126 e_end = SectionData::iterator(m_GOT.front); 127 128 while (entry != e_end) { 129 llvm::cast<GOT::Entry>(entry)->setContent(pPLTBase); 130 ++entry; 131 } 132} 133 134uint64_t ARMGOT::emit(MemoryRegion& pRegion) 135{ 136 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 137 138 Entry* got = 0; 139 unsigned int entry_size = getEntrySize(); 140 uint64_t result = 0x0; 141 for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) { 142 got = &(llvm::cast<Entry>((*it))); 143 *buffer = static_cast<uint32_t>(got->getContent()); 144 result += entry_size; 145 } 146 return result; 147} 148 149