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 17 namespace { 18 const unsigned int AArch64GOT0Num = 3; 19 } // end of anonymous namespace 20 21 namespace mcld { 22 23 //===----------------------------------------------------------------------===// 24 // AArch64GOT 25 AArch64GOT::AArch64GOT(LDSection& pSection) 26 : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) { 27 } 28 29 AArch64GOT::~AArch64GOT() { 30 } 31 32 void 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 38 bool AArch64GOT::hasGOT1() const { 39 return ((!m_GOT.empty()) || (!m_GOTPLT.empty())); 40 } 41 42 AArch64GOTEntry* AArch64GOT::createGOT() { 43 AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL); 44 m_GOT.push_back(entry); 45 return entry; 46 } 47 48 AArch64GOTEntry* AArch64GOT::createGOTPLT() { 49 AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL); 50 m_GOTPLT.push_back(entry); 51 return entry; 52 } 53 54 void 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 96 void AArch64GOT::applyGOT0(uint64_t pAddress) { 97 llvm::cast<AArch64GOTEntry>(*(m_SectionData->getFragmentList().begin())) 98 .setValue(pAddress); 99 } 100 101 void 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 118 uint64_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