1//===- ARMGOT.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#include "ARMGOT.h" 10 11#include <llvm/Support/Casting.h> 12 13#include <mcld/LD/LDSection.h> 14#include <mcld/LD/LDFileFormat.h> 15#include <mcld/Support/MsgHandling.h> 16 17namespace { 18 const unsigned int ARMGOT0Num = 3; 19} // end of anonymous namespace 20 21using namespace mcld; 22 23//===----------------------------------------------------------------------===// 24// ARMGOT 25ARMGOT::ARMGOT(LDSection& pSection) 26 : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) 27{ 28 // create GOT0, and put them into m_SectionData immediately 29 for (unsigned int i = 0; i < ARMGOT0Num; ++i) 30 new ARMGOTEntry(0, m_SectionData); 31} 32 33ARMGOT::~ARMGOT() 34{ 35} 36 37bool ARMGOT::hasGOT1() const 38{ 39 return ((!m_GOT.empty()) || (!m_GOTPLT.empty())); 40} 41 42ARMGOTEntry* ARMGOT::createGOT() 43{ 44 ARMGOTEntry* entry = new ARMGOTEntry(0, NULL); 45 m_GOT.push_back(entry); 46 return entry; 47} 48 49ARMGOTEntry* ARMGOT::createGOTPLT() 50{ 51 ARMGOTEntry* entry = new ARMGOTEntry(0, NULL); 52 m_GOTPLT.push_back(entry); 53 return entry; 54} 55 56void ARMGOT::finalizeSectionSize() 57{ 58 uint32_t offset = 0; 59 SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList(); 60 // setup GOT0 offset 61 SectionData::iterator frag, fragEnd = m_SectionData->end(); 62 for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) { 63 frag->setOffset(offset); 64 offset += frag->size(); 65 } 66 67 // push GOTPLT into the SectionData and setup the offset 68 if (!m_GOTPLT.empty()) { 69 m_pGOTPLTFront = m_GOTPLT.front(); 70 entry_iterator it, end = m_GOTPLT.end(); 71 for (it = m_GOTPLT.begin(); it != end; ++it) { 72 ARMGOTEntry* entry = *it; 73 frag_list.push_back(entry); 74 entry->setParent(m_SectionData); 75 entry->setOffset(offset); 76 offset += entry->size(); 77 } 78 } 79 m_GOTPLT.clear(); 80 81 // push GOT into the SectionData and setup the offset 82 if (!m_GOT.empty()) { 83 m_pGOTFront = m_GOT.front(); 84 entry_iterator it, end = m_GOT.end(); 85 for (it = m_GOT.begin(); it != end; ++it) { 86 ARMGOTEntry* entry = *it; 87 frag_list.push_back(entry); 88 entry->setParent(m_SectionData); 89 entry->setOffset(offset); 90 offset += entry->size(); 91 } 92 } 93 m_GOT.clear(); 94 95 // set section size 96 m_Section.setSize(offset); 97} 98 99void ARMGOT::applyGOT0(uint64_t pAddress) 100{ 101 llvm::cast<ARMGOTEntry> 102 (*(m_SectionData->getFragmentList().begin())).setValue(pAddress); 103} 104 105void ARMGOT::applyGOTPLT(uint64_t pPLTBase) 106{ 107 if (NULL == m_pGOTPLTFront) 108 return; 109 110 SectionData::iterator entry(m_pGOTPLTFront); 111 SectionData::iterator e_end; 112 if (NULL == m_pGOTFront) 113 e_end = m_SectionData->end(); 114 else 115 e_end = SectionData::iterator(m_pGOTFront); 116 117 while (entry != e_end) { 118 llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase); 119 ++entry; 120 } 121} 122 123uint64_t ARMGOT::emit(MemoryRegion& pRegion) 124{ 125 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin()); 126 127 ARMGOTEntry* got = NULL; 128 uint64_t result = 0x0; 129 for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) { 130 got = &(llvm::cast<ARMGOTEntry>((*it))); 131 *buffer = static_cast<uint32_t>(got->getValue()); 132 result += ARMGOTEntry::EntrySize; 133 } 134 return result; 135} 136 137