1 //===- MipsGOT.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 10 #include <llvm/Support/ErrorHandling.h> 11 #include <mcld/LD/ResolveInfo.h> 12 #include <mcld/Support/MemoryRegion.h> 13 #include "MipsGOT.h" 14 15 namespace { 16 const size_t MipsGOTEntrySize = 4; 17 const size_t MipsGOT0Num = 1; 18 } 19 20 using namespace mcld; 21 22 //===----------------------------------------------------------------------===// 23 // MipsGOT 24 MipsGOT::MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData) 25 : GOT(pSection, pSectionData, MipsGOTEntrySize), 26 m_pLocalNum(0) 27 { 28 // Create GOT0 entries. 29 for (size_t i = 0; i < MipsGOT0Num; ++i) { 30 GOTEntry* entry = 31 new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData); 32 33 if (NULL == entry) 34 llvm::report_fatal_error("Allocating GOT0 entries failed!"); 35 36 m_Section.setSize(m_Section.size() + MipsGOTEntrySize); 37 } 38 39 // Skip GOT0 entries. 40 iterator it = m_SectionData.begin(); 41 iterator ie = m_SectionData.end(); 42 43 for (size_t i = 1; i < MipsGOT0Num; ++i) { 44 if (it == ie) 45 llvm::report_fatal_error("Generation of GOT0 entries is incomplete!"); 46 47 ++it; 48 } 49 50 m_LocalGOTIterator = it; 51 m_GlobalGOTIterator = it; 52 m_pLocalNum = MipsGOT0Num; 53 } 54 55 MipsGOT::iterator MipsGOT::begin() 56 { 57 return m_SectionData.getFragmentList().begin(); 58 } 59 60 MipsGOT::iterator MipsGOT::end() 61 { 62 return m_SectionData.getFragmentList().end(); 63 } 64 65 MipsGOT::const_iterator MipsGOT::begin() const 66 { 67 return m_SectionData.getFragmentList().begin(); 68 } 69 70 MipsGOT::const_iterator MipsGOT::end() const 71 { 72 return m_SectionData.getFragmentList().end(); 73 } 74 75 uint64_t MipsGOT::emit(MemoryRegion& pRegion) 76 { 77 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 78 79 size_t entry_size = getEntrySize(); 80 81 uint64_t result = 0; 82 for (iterator it = begin(), ie = end(); 83 it != ie; ++it, ++buffer) { 84 GOTEntry* got = &(llvm::cast<GOTEntry>((*it))); 85 *buffer = static_cast<uint32_t>(got->getContent()); 86 result += entry_size; 87 } 88 return result; 89 } 90 91 void MipsGOT::reserveEntry(size_t pNum) 92 { 93 for (size_t i = 0; i < pNum; ++i) { 94 GOTEntry* entry = 95 new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData); 96 97 if (NULL == entry) 98 llvm::report_fatal_error("Allocating new GOTEntry failed"); 99 100 m_Section.setSize(m_Section.size() + MipsGOTEntrySize); 101 } 102 } 103 104 void MipsGOT::reserveLocalEntry() 105 { 106 reserveEntry(1); 107 ++m_pLocalNum; 108 109 // Move global entries iterator forward. 110 // We need to put global GOT entries after all local ones. 111 ++m_GlobalGOTIterator; 112 } 113 114 void MipsGOT::reserveGlobalEntry() 115 { 116 reserveEntry(1); 117 } 118 119 GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist) 120 { 121 GOTEntry*& entry = m_GeneralGOTMap[&pInfo]; 122 123 pExist = NULL != entry; 124 125 if (!pExist) { 126 iterator& it = pInfo.isLocal() ? m_LocalGOTIterator : m_GlobalGOTIterator; 127 128 ++it; 129 130 assert(it != m_SectionData.getFragmentList().end() && 131 "The number of GOT Entries and ResolveInfo doesn't match"); 132 133 entry = llvm::cast<GOTEntry>(&(*it)); 134 } 135 136 return entry; 137 } 138 139 size_t MipsGOT::getTotalNum() const 140 { 141 return m_SectionData.getFragmentList().size(); 142 } 143 144 size_t MipsGOT::getLocalNum() const 145 { 146 return m_pLocalNum; 147 } 148