MipsGOT.cpp revision affc150dc44fab1911775a49636d0ce85333b634
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 <mcld/LD/ResolveInfo.h> 11#include <mcld/Support/MemoryRegion.h> 12#include <mcld/Support/MsgHandling.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 fatal(diag::fail_allocate_memory) << "GOT0"; 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 assert((it != ie) && "Generation of GOT0 entries is incomplete!"); 45 46 ++it; 47 } 48 49 m_LocalGOTIterator = it; 50 m_GlobalGOTIterator = it; 51 m_pLocalNum = MipsGOT0Num; 52} 53 54MipsGOT::iterator MipsGOT::begin() 55{ 56 return m_SectionData.getFragmentList().begin(); 57} 58 59MipsGOT::iterator MipsGOT::end() 60{ 61 return m_SectionData.getFragmentList().end(); 62} 63 64MipsGOT::const_iterator MipsGOT::begin() const 65{ 66 return m_SectionData.getFragmentList().begin(); 67} 68 69MipsGOT::const_iterator MipsGOT::end() const 70{ 71 return m_SectionData.getFragmentList().end(); 72} 73 74uint64_t MipsGOT::emit(MemoryRegion& pRegion) 75{ 76 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 77 78 size_t entry_size = getEntrySize(); 79 80 uint64_t result = 0; 81 for (iterator it = begin(), ie = end(); 82 it != ie; ++it, ++buffer) { 83 GOTEntry* got = &(llvm::cast<GOTEntry>((*it))); 84 *buffer = static_cast<uint32_t>(got->getContent()); 85 result += entry_size; 86 } 87 return result; 88} 89 90void MipsGOT::reserveEntry(size_t pNum) 91{ 92 for (size_t i = 0; i < pNum; ++i) { 93 GOTEntry* entry = 94 new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData); 95 96 if (NULL == entry) 97 fatal(diag::fail_allocate_memory) << "GOTEntry"; 98 99 m_Section.setSize(m_Section.size() + MipsGOTEntrySize); 100 } 101} 102 103void MipsGOT::reserveLocalEntry() 104{ 105 reserveEntry(1); 106 ++m_pLocalNum; 107 108 // Move global entries iterator forward. 109 // We need to put global GOT entries after all local ones. 110 ++m_GlobalGOTIterator; 111} 112 113void MipsGOT::reserveGlobalEntry() 114{ 115 reserveEntry(1); 116} 117 118GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist) 119{ 120 if (isLocal(&pInfo) && pInfo.type() == ResolveInfo::Section) { 121 pExist = false; 122 iterator& it = m_LocalGOTIterator; 123 ++it; 124 assert(it != m_SectionData.getFragmentList().end() && 125 "The number of GOT Entries and ResolveInfo doesn't match"); 126 GOTEntry* entry = llvm::cast<GOTEntry>(&(*it)); 127 return entry; 128 } 129 130 GOTEntry*& entry = m_GeneralGOTMap[&pInfo]; 131 132 pExist = NULL != entry; 133 134 if (!pExist) { 135 iterator& it = isLocal(&pInfo) ? m_LocalGOTIterator : m_GlobalGOTIterator; 136 137 ++it; 138 139 assert(it != m_SectionData.getFragmentList().end() && 140 "The number of GOT Entries and ResolveInfo doesn't match"); 141 142 entry = llvm::cast<GOTEntry>(&(*it)); 143 } 144 145 return entry; 146} 147 148size_t MipsGOT::getTotalNum() const 149{ 150 return m_SectionData.getFragmentList().size(); 151} 152 153size_t MipsGOT::getLocalNum() const 154{ 155 return m_pLocalNum; 156} 157 158