HexagonPLT.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
16f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===- HexagonPLT.cpp -----------------------------------------------------===// 26f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 36f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// The MCLinker Project 46f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 56f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// This file is distributed under the University of Illinois Open Source 66f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// License. See LICENSE.TXT for details. 76f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 86f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "HexagonPLT.h" 10f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include "HexagonRelocationFunctions.h" 116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/ELF.h> 136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/Casting.h> 146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/LDSection.h> 166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LinkerConfig.h> 176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Support/MsgHandling.h> 186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld; 206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// PLT entry data 236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 24f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesHexagonPLT0::HexagonPLT0(SectionData& pParent) 25f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : PLT::Entry<sizeof(hexagon_plt0)>(pParent) 266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 29f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesHexagonPLT1::HexagonPLT1(SectionData& pParent) 30f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : PLT::Entry<sizeof(hexagon_plt1)>(pParent) 316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// HexagonPLT 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesHexagonPLT::HexagonPLT(LDSection& pSection, 38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines HexagonGOTPLT &pGOTPLT, 396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const LinkerConfig& pConfig) 406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : PLT(pSection), 41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_GOTPLT(pGOTPLT), 426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_Config(pConfig) 436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(LinkerConfig::DynObj == m_Config.codeGenType() || 456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LinkerConfig::Exec == m_Config.codeGenType() || 466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LinkerConfig::Binary == m_Config.codeGenType()); 476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_PLT0 = hexagon_plt0; 49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_PLT0Size = sizeof (hexagon_plt0); 50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create PLT0 51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines new HexagonPLT0(*m_pSectionData); 52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSection.setAlign(16); 536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesHexagonPLT::~HexagonPLT() 566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase* HexagonPLT::getPLT0() const 606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines iterator first = m_pSectionData->getFragmentList().begin(); 626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(first != m_pSectionData->getFragmentList().end() && 646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines "FragmentList is empty, getPLT0 failed!"); 656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first)); 676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return plt0; 696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid HexagonPLT::finalizeSectionSize() 726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t size = 0; 746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // plt0 size 756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines size = getPLT0()->size(); 766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get first plt1 entry 78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines HexagonPLT::iterator it = begin(); 79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++it; 80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (end() != it) { 81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // plt1 size 82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it)); 83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines size += (m_pSectionData->size() - 1) * plt1->size(); 84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_Section.setSize(size); 866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint32_t offset = 0; 88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData::iterator frag, fragEnd = m_pSectionData->end(); 89551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) { 906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines frag->setOffset(offset); 916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines offset += frag->size(); 926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool HexagonPLT::hasPLT1() const 96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 97551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return (m_pSectionData->size() > 1); 98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 10087f34658dec9097d987d254a990ea7f311bfc95fStephen HinesHexagonPLT1* HexagonPLT::create() 1016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 102551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return new HexagonPLT1(*m_pSectionData); 103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid HexagonPLT::applyPLT0() 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines PLTEntryBase* plt0 = getPLT0(); 108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t pltBase = m_Section.addr(); 109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines unsigned char* data = 0; 111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines data = static_cast<unsigned char*>(malloc(plt0->size())); 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!data) 114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::fail_allocate_memory_plt); 115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines memcpy(data, m_PLT0, plt0->size()); 117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t gotpltAddr = m_GOTPLT.addr(); 118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines int32_t *dest = (int32_t *)data; 120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines int32_t result = ((gotpltAddr - pltBase ) >> 6); 121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *dest |= ApplyMask<int32_t>(0xfff3fff, result); 122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines dest = dest + 1; 123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Already calculated using pltBase 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines result = (gotpltAddr - pltBase); 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(dest) |= ApplyMask<int32_t>(0x1f80, result); 126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines plt0->setValue(data); 128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid HexagonPLT::applyPLT1() { 131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t plt_base = m_Section.addr(); 133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(plt_base && ".plt base address is NULL!"); 134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t got_base = m_GOTPLT.addr(); 136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(got_base && ".got base address is NULL!"); 137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 138551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines HexagonPLT::iterator it = m_pSectionData->begin(); 139551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines HexagonPLT::iterator ie = m_pSectionData->end(); 140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t GOTEntrySize = HexagonGOTEntry::EntrySize; 143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t GOTEntryAddress = 144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got_base + GOTEntrySize * 4; 145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t PLTEntryAddress = 147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines plt_base + HexagonPLT0::EntrySize; //Offset of PLT0 148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++it; //skip PLT0 150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t PLT1EntrySize = HexagonPLT1::EntrySize; 151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines HexagonPLT1* plt1 = NULL; 152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t* Out = NULL; 154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines while (it != ie) { 155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines plt1 = &(llvm::cast<HexagonPLT1>(*it)); 156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Out = static_cast<uint32_t*>(malloc(HexagonPLT1::EntrySize)); 157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!Out) 159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::fail_allocate_memory_plt); 160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines memcpy(Out, hexagon_plt1, plt1->size()); 162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines int32_t *dest = (int32_t *)Out; 164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines int32_t result = ((GOTEntryAddress - PLTEntryAddress ) >> 6); 165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *dest |= ApplyMask<int32_t>(0xfff3fff, result); 166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines dest = dest + 1; 167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines result = (GOTEntryAddress - PLTEntryAddress); 168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(dest) |= ApplyMask<int32_t>(0x1f80, result); 169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Address in the PLT entries point to the corresponding GOT entries 171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // TODO: Fixup plt to point to the corresponding GOTEntryAddress 172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // We need to borrow the same relocation code to fix the relocation 173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines plt1->setValue(reinterpret_cast<unsigned char*>(Out)); 174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++it; 175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines GOTEntryAddress += GOTEntrySize; 177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines PLTEntryAddress += PLT1EntrySize; 178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesuint64_t HexagonPLT::emit(MemoryRegion& pRegion) 182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t result = 0x0; 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines iterator it = begin(); 185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines unsigned char* buffer = pRegion.begin(); 187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines memcpy(buffer, llvm::cast<HexagonPLT0>((*it)).getValue(), HexagonPLT0::EntrySize); 188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines result += HexagonPLT0::EntrySize; 189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++it; 190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines HexagonPLT1* plt1 = 0; 192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines HexagonPLT::iterator ie = end(); 193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines while (it != ie) { 194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines plt1 = &(llvm::cast<HexagonPLT1>(*it)); 195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines memcpy(buffer + result, plt1->getValue(), HexagonPLT1::EntrySize); 196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines result += HexagonPLT1::EntrySize; 197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ++it; 198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return result; 2006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 2016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 202