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