MipsGOT.cpp revision d0fbbb227051be16931a1aa9b4a7722ac039c698
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 18namespace { 19 const size_t MipsGOT0Num = 1; 20} 21 22using namespace mcld; 23 24//===----------------------------------------------------------------------===// 25// MipsGOT 26//===----------------------------------------------------------------------===// 27MipsGOT::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 50void MipsGOT::reserve(size_t pNum) 51{ 52 for (size_t i = 0; i < pNum; i++) { 53 new MipsGOTEntry(0, m_SectionData); 54 } 55} 56 57MipsGOTEntry* 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 69bool MipsGOT::hasGOT1() const 70{ 71 return (m_SectionData->size() > MipsGOT0Num); 72} 73 74uint64_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 88void 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 98void MipsGOT::reserveGlobalEntry() 99{ 100 reserve(1); 101} 102 103MipsGOTEntry* 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 112MipsGOTEntry* 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 121size_t MipsGOT::getTotalNum() const 122{ 123 return m_SectionData->getFragmentList().size(); 124} 125 126size_t MipsGOT::getLocalNum() const 127{ 128 return m_pLocalNum; 129} 130 131