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 17 namespace { 18 const unsigned int ARMGOT0Num = 3; 19 } // end of anonymous namespace 20 21 namespace mcld { 22 23 //===----------------------------------------------------------------------===// 24 // ARMGOT 25 ARMGOT::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 32 ARMGOT::~ARMGOT() { 33 } 34 35 bool ARMGOT::hasGOT1() const { 36 return ((!m_GOT.empty()) || (!m_GOTPLT.empty())); 37 } 38 39 ARMGOTEntry* ARMGOT::createGOT() { 40 ARMGOTEntry* entry = new ARMGOTEntry(0, NULL); 41 m_GOT.push_back(entry); 42 return entry; 43 } 44 45 ARMGOTEntry* ARMGOT::createGOTPLT() { 46 ARMGOTEntry* entry = new ARMGOTEntry(0, NULL); 47 m_GOTPLT.push_back(entry); 48 return entry; 49 } 50 51 void 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 93 void ARMGOT::applyGOT0(uint64_t pAddress) { 94 llvm::cast<ARMGOTEntry>(*(m_SectionData->getFragmentList().begin())) 95 .setValue(pAddress); 96 } 97 98 void 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 115 uint64_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