1551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===- AArch64GOT.cpp -----------------------------------------------------===// 2551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// 3551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// The MCLinker Project 4551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// 5551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// This file is distributed under the University of Illinois Open Source 6551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// License. See LICENSE.TXT for details. 7551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// 8551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 9551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64GOT.h" 10551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDFileFormat.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 14551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/Casting.h> 16551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 17551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesnamespace { 1837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst unsigned int AArch64GOT0Num = 3; 1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // end of anonymous namespace 20551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 2137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 22551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 23551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 24551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// AArch64GOT 25551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64GOT::AArch64GOT(LDSection& pSection) 2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) { 27551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 28551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 2937b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64GOT::~AArch64GOT() { 30551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 31551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 3237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::createGOT0() { 33551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create GOT0, and put them into m_SectionData immediately 34551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (unsigned int i = 0; i < AArch64GOT0Num; ++i) 35551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines new AArch64GOTEntry(0, m_SectionData); 36551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 37551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 3837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool AArch64GOT::hasGOT1() const { 39551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return ((!m_GOT.empty()) || (!m_GOTPLT.empty())); 40551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 4237b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64GOTEntry* AArch64GOT::createGOT() { 43551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL); 44551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_GOT.push_back(entry); 45551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return entry; 46551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 47551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 4837b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64GOTEntry* AArch64GOT::createGOTPLT() { 49551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL); 50551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_GOTPLT.push_back(entry); 51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return entry; 52551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 53551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 5437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::finalizeSectionSize() { 55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint32_t offset = 0; 56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList(); 57551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup GOT0 offset 58551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData::iterator frag, fragEnd = m_SectionData->end(); 59551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) { 60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines frag->setOffset(offset); 61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines offset += frag->size(); 62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // push GOTPLT into the SectionData and setup the offset 65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!m_GOTPLT.empty()) { 66551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_pGOTPLTFront = m_GOTPLT.front(); 67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines entry_iterator it, end = m_GOTPLT.end(); 68551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (it = m_GOTPLT.begin(); it != end; ++it) { 69551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* entry = *it; 70551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines frag_list.push_back(entry); 71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines entry->setParent(m_SectionData); 72551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines entry->setOffset(offset); 73551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines offset += entry->size(); 74551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 75551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_GOTPLT.clear(); 77551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 78551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // push GOT into the SectionData and setup the offset 79551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!m_GOT.empty()) { 80551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_pGOTFront = m_GOT.front(); 81551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines entry_iterator it, end = m_GOT.end(); 82551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (it = m_GOT.begin(); it != end; ++it) { 83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* entry = *it; 84551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines frag_list.push_back(entry); 85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines entry->setParent(m_SectionData); 86551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines entry->setOffset(offset); 87551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines offset += entry->size(); 88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 89551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_GOT.clear(); 91551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 92551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set section size 93551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_Section.setSize(offset); 94551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 95551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 9637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::applyGOT0(uint64_t pAddress) { 9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::cast<AArch64GOTEntry>(*(m_SectionData->getFragmentList().begin())) 9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines .setValue(pAddress); 99551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 10137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::applyGOTPLT(uint64_t pPLTBase) { 10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (m_pGOTPLTFront == NULL) 103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 105551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData::iterator entry(m_pGOTPLTFront); 106551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData::iterator e_end; 10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (m_pGOTFront == NULL) 108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines e_end = m_SectionData->end(); 109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines e_end = SectionData::iterator(m_pGOTFront); 111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines while (entry != e_end) { 113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines llvm::cast<AArch64GOTEntry>(entry)->setValue(pPLTBase); 114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ++entry; 115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 11837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t AArch64GOT::emit(MemoryRegion& pRegion) { 119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin()); 120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* got = NULL; 122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint64_t result = 0x0; 123551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) { 12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines got = &(llvm::cast<AArch64GOTEntry>((*it))); 12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines *buffer = static_cast<uint64_t>(got->getValue()); 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines result += AArch64GOTEntry::EntrySize; 127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return result; 129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 132