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