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