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