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 17 namespace { 18 const unsigned int AArch64GOT0Num = 3; 19 } // end of anonymous namespace 20 21 using namespace mcld; 22 23 //===----------------------------------------------------------------------===// 24 // AArch64GOT 25 AArch64GOT::AArch64GOT(LDSection& pSection) 26 : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) 27 { 28 } 29 30 AArch64GOT::~AArch64GOT() 31 { 32 } 33 34 void 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 41 bool AArch64GOT::hasGOT1() const 42 { 43 return ((!m_GOT.empty()) || (!m_GOTPLT.empty())); 44 } 45 46 AArch64GOTEntry* AArch64GOT::createGOT() 47 { 48 AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL); 49 m_GOT.push_back(entry); 50 return entry; 51 } 52 53 AArch64GOTEntry* AArch64GOT::createGOTPLT() 54 { 55 AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL); 56 m_GOTPLT.push_back(entry); 57 return entry; 58 } 59 60 void 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 104 void AArch64GOT::applyGOT0(uint64_t pAddress) 105 { 106 llvm::cast<AArch64GOTEntry> 107 (*(m_SectionData->getFragmentList().begin())).setValue(pAddress); 108 } 109 110 void 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 128 uint64_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