MipsGOT.cpp revision d8a752331fe7a30ce41835f139aa8a4c675ad07a
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 15namespace { 16 const size_t MipsGOTEntrySize = 4; 17 const size_t MipsGOT0Num = 1; 18} 19 20using namespace mcld; 21 22//===----------------------------------------------------------------------===// 23// MipsGOT 24MipsGOT::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 55MipsGOT::iterator MipsGOT::begin() 56{ 57 return m_SectionData.getFragmentList().begin(); 58} 59 60MipsGOT::iterator MipsGOT::end() 61{ 62 return m_SectionData.getFragmentList().end(); 63} 64 65MipsGOT::const_iterator MipsGOT::begin() const 66{ 67 return m_SectionData.getFragmentList().begin(); 68} 69 70MipsGOT::const_iterator MipsGOT::end() const 71{ 72 return m_SectionData.getFragmentList().end(); 73} 74 75uint64_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 91void 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 104void 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 114void MipsGOT::reserveGlobalEntry() 115{ 116 reserveEntry(1); 117} 118 119GOTEntry* 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 139size_t MipsGOT::getTotalNum() const 140{ 141 return m_SectionData.getFragmentList().size(); 142} 143 144size_t MipsGOT::getLocalNum() const 145{ 146 return m_pLocalNum; 147} 148