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 15 namespace { 16 const size_t ARMGOTEntrySize = 4; 17 } // end of anonymous namespace 18 19 using namespace mcld; 20 21 //===----------------------------------------------------------------------===// 22 // ARMGOT 23 ARMGOT::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 59 ARMGOT::~ARMGOT() 60 { 61 } 62 63 void 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 78 void 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 93 GOTEntry* 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 111 void ARMGOT::applyGOT0(uint64_t pAddress) 112 { 113 llvm::cast<GOTEntry> 114 (*(m_SectionData.getFragmentList().begin())).setContent(pAddress); 115 } 116 117 void 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 126 GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol) 127 { 128 return m_GOTPLTMap[&pSymbol]; 129 } 130 131 ARMGOT::iterator ARMGOT::begin() 132 { 133 return m_SectionData.getFragmentList().begin(); 134 } 135 136 ARMGOT::const_iterator ARMGOT::begin() const 137 { 138 return m_SectionData.getFragmentList().begin(); 139 } 140 141 ARMGOT::iterator ARMGOT::end() 142 { 143 return m_SectionData.getFragmentList().end(); 144 } 145 146 ARMGOT::const_iterator ARMGOT::end() const 147 { 148 return m_SectionData.getFragmentList().end(); 149 } 150 151 ARMGOT::iterator ARMGOT::getNextGOTPLTEntry() 152 { 153 return ++m_GOTPLTIterator; 154 } 155 156 ARMGOT::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 163 const 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 170 uint64_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