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