ARMGOT.cpp revision 67e37f1be98c926645219cfb47fab9e90d8c725c
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#include <mcld/LD/LDFileFormat.h> 11#include <mcld/Support/MemoryRegion.h> 12#include <mcld/Support/MsgHandling.h> 13#include <new> 14 15namespace { 16 const size_t ARMGOTEntrySize = 4; 17} // end of anonymous namespace 18 19using namespace mcld; 20 21//===----------------------------------------------------------------------===// 22// ARMGOT 23ARMGOT::ARMGOT(LDSection& pSection, llvm::MCSectionData& pSectionData) 24 : GOT(pSection, pSectionData, ARMGOTEntrySize), 25 m_NormalGOTIterator(), m_GOTPLTIterator(), 26 m_GOTPLTBegin(), m_GOTPLTEnd() 27{ 28 GOTEntry* Entry = 0; 29 30 // Create GOT0 entries. 31 for (int i = 0; i < 3; i++) { 32 Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize, 33 &m_SectionData); 34 35 if (!Entry) 36 fatal(diag::fail_allocate_memory) << "GOT0"; 37 38 m_Section.setSize(m_Section.size() + ARMGOTEntrySize); 39 } 40 41 // Skip GOT0 entries. 42 iterator it = m_SectionData.begin(); 43 44 for (int i = 1; i < ARMGOT0Num; ++i) { 45 assert((it != m_SectionData.end()) && "Generation of GOT0 entries is incomplete!"); 46 ++it; 47 } 48 49 m_NormalGOTIterator = it; 50 m_GOTPLTIterator = it; 51 52 m_GOTPLTBegin = it; 53 m_GOTPLTEnd = it; 54} 55 56ARMGOT::~ARMGOT() 57{ 58} 59 60void ARMGOT::reserveEntry(size_t pNum) 61{ 62 GOTEntry* Entry = 0; 63 64 for (size_t i = 0; i < pNum; i++) { 65 Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize, 66 &m_SectionData); 67 68 if (!Entry) 69 fatal(diag::fail_allocate_memory) << "GOTEntry"; 70 71 m_Section.setSize(m_Section.size() + ARMGOTEntrySize); 72 } 73} 74 75void ARMGOT::reserveGOTPLTEntry() 76{ 77 GOTEntry* got_entry = 0; 78 79 got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData())); 80 81 if (!got_entry) 82 fatal(diag::fail_allocate_memory) << "GOTEntry"; 83 84 m_Section.setSize(m_Section.size() + getEntrySize()); 85 86 ++m_GOTPLTEnd; 87 ++m_NormalGOTIterator; 88} 89 90GOTEntry* ARMGOT::getEntry(const ResolveInfo& pInfo, bool& pExist) 91{ 92 GOTEntry *&Entry = m_NormalGOTMap[&pInfo]; 93 pExist = 1; 94 95 if (!Entry) { 96 pExist = 0; 97 98 ++m_NormalGOTIterator; 99 assert(m_NormalGOTIterator != m_SectionData.getFragmentList().end() 100 && "The number of GOT Entries and ResolveInfo doesn't match!"); 101 102 Entry = llvm::cast<GOTEntry>(&(*m_NormalGOTIterator)); 103 } 104 105 return Entry; 106} 107 108void ARMGOT::applyGOT0(uint64_t pAddress) 109{ 110 llvm::cast<GOTEntry> 111 (*(m_SectionData.getFragmentList().begin())).setContent(pAddress); 112} 113 114void ARMGOT::applyAllGOTPLT(uint64_t pPLTBase) 115{ 116 iterator begin = getGOTPLTBegin(); 117 iterator end = getGOTPLTEnd(); 118 119 for (;begin != end ;++begin) 120 llvm::cast<GOTEntry>(*begin).setContent(pPLTBase); 121} 122 123GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol) 124{ 125 return m_GOTPLTMap[&pSymbol]; 126} 127 128ARMGOT::iterator ARMGOT::begin() 129{ 130 return m_SectionData.getFragmentList().begin(); 131} 132 133ARMGOT::const_iterator ARMGOT::begin() const 134{ 135 return m_SectionData.getFragmentList().begin(); 136} 137 138ARMGOT::iterator ARMGOT::end() 139{ 140 return m_SectionData.getFragmentList().end(); 141} 142 143ARMGOT::const_iterator ARMGOT::end() const 144{ 145 return m_SectionData.getFragmentList().end(); 146} 147 148ARMGOT::iterator ARMGOT::getNextGOTPLTEntry() 149{ 150 return ++m_GOTPLTIterator; 151} 152 153ARMGOT::iterator ARMGOT::getGOTPLTBegin() 154{ 155 // Move to the first GOTPLT entry from last GOT0 entry. 156 iterator begin = m_GOTPLTBegin; 157 return ++begin; 158} 159 160const ARMGOT::iterator ARMGOT::getGOTPLTEnd() 161{ 162 // Move to end or the first normal GOT entry from the last GOTPLT entry. 163 iterator end = m_GOTPLTEnd; 164 return ++end; 165} 166 167uint64_t ARMGOT::emit(MemoryRegion& pRegion) 168{ 169 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 170 171 GOTEntry* got = 0; 172 unsigned int entry_size = getEntrySize(); 173 uint64_t result = 0x0; 174 for (iterator it = begin(), ie = end(); 175 it != ie; ++it, ++buffer) { 176 got = &(llvm::cast<GOTEntry>((*it))); 177 *buffer = static_cast<uint32_t>(got->getContent()); 178 result += entry_size; 179 } 180 return result; 181} 182 183