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