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 "MipsGOT.h" 11 12 #include <llvm/Support/Casting.h> 13 14 #include <mcld/LD/ResolveInfo.h> 15 #include <mcld/Support/MemoryRegion.h> 16 #include <mcld/Support/MsgHandling.h> 17 18 namespace { 19 const size_t MipsGOT0Num = 1; 20 } 21 22 using namespace mcld; 23 24 //===----------------------------------------------------------------------===// 25 // MipsGOT 26 //===----------------------------------------------------------------------===// 27 MipsGOT::MipsGOT(LDSection& pSection) 28 : GOT(pSection), 29 m_pLocalNum(0), 30 m_pLast(NULL) 31 { 32 // Create GOT0 entries. 33 reserve(MipsGOT0Num); 34 35 // Skip GOT0 entries. 36 iterator it = m_SectionData->begin(); 37 38 for (size_t i = 1; i < MipsGOT0Num; ++i) { 39 assert((it != m_SectionData->end()) && 40 "Generation of GOT0 entries is incomplete!"); 41 42 ++it; 43 } 44 45 m_LocalGOTIterator = it; 46 m_GlobalGOTIterator = it; 47 m_pLocalNum = MipsGOT0Num; 48 } 49 50 void MipsGOT::reserve(size_t pNum) 51 { 52 for (size_t i = 0; i < pNum; i++) { 53 new MipsGOTEntry(0, m_SectionData); 54 } 55 } 56 57 MipsGOTEntry* MipsGOT::consume() 58 { 59 if (NULL == m_pLast) { 60 assert(!empty() && "Consume empty GOT entry!"); 61 m_pLast = llvm::cast<MipsGOTEntry>(&m_SectionData->front()); 62 return m_pLast; 63 } 64 65 m_pLast = llvm::cast<MipsGOTEntry>(m_pLast->getNextNode()); 66 return m_pLast; 67 } 68 69 bool MipsGOT::hasGOT1() const 70 { 71 return (m_SectionData->size() > MipsGOT0Num); 72 } 73 74 uint64_t MipsGOT::emit(MemoryRegion& pRegion) 75 { 76 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 77 78 uint64_t result = 0; 79 for (iterator it = begin(), ie = end(); 80 it != ie; ++it, ++buffer) { 81 MipsGOTEntry* got = &(llvm::cast<MipsGOTEntry>((*it))); 82 *buffer = static_cast<uint32_t>(got->getValue()); 83 result += got->size(); 84 } 85 return result; 86 } 87 88 void MipsGOT::reserveLocalEntry() 89 { 90 reserve(1); 91 ++m_pLocalNum; 92 93 // Move global entries iterator forward. 94 // We need to put global GOT entries after all local ones. 95 ++m_GlobalGOTIterator; 96 } 97 98 void MipsGOT::reserveGlobalEntry() 99 { 100 reserve(1); 101 } 102 103 MipsGOTEntry* MipsGOT::consumeLocal() 104 { 105 iterator& it = m_LocalGOTIterator; 106 ++it; 107 assert(it != m_SectionData->getFragmentList().end() && 108 "The number of GOT Entries and ResolveInfo doesn't match"); 109 return llvm::cast<MipsGOTEntry>(&(*it)); 110 } 111 112 MipsGOTEntry* MipsGOT::consumeGlobal() 113 { 114 iterator& it = m_GlobalGOTIterator; 115 ++it; 116 assert(it != m_SectionData->getFragmentList().end() && 117 "The number of GOT Entries and ResolveInfo doesn't match"); 118 return llvm::cast<MipsGOTEntry>(&(*it)); 119 } 120 121 size_t MipsGOT::getTotalNum() const 122 { 123 return m_SectionData->getFragmentList().size(); 124 } 125 126 size_t MipsGOT::getLocalNum() const 127 { 128 return m_pLocalNum; 129 } 130 131