HexagonPLT.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- HexagonPLT.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 "HexagonPLT.h" 10#include "HexagonRelocationFunctions.h" 11 12#include <llvm/Support/ELF.h> 13#include <llvm/Support/Casting.h> 14 15#include <mcld/LD/LDSection.h> 16#include <mcld/LinkerConfig.h> 17#include <mcld/Support/MsgHandling.h> 18 19using namespace mcld; 20 21//===----------------------------------------------------------------------===// 22// PLT entry data 23//===----------------------------------------------------------------------===// 24HexagonPLT0::HexagonPLT0(SectionData& pParent) 25 : PLT::Entry<sizeof(hexagon_plt0)>(pParent) 26{ 27} 28 29HexagonPLT1::HexagonPLT1(SectionData& pParent) 30 : PLT::Entry<sizeof(hexagon_plt1)>(pParent) 31{ 32} 33 34//===----------------------------------------------------------------------===// 35// HexagonPLT 36//===----------------------------------------------------------------------===// 37HexagonPLT::HexagonPLT(LDSection& pSection, 38 HexagonGOTPLT &pGOTPLT, 39 const LinkerConfig& pConfig) 40 : PLT(pSection), 41 m_GOTPLT(pGOTPLT), 42 m_Config(pConfig) 43{ 44 assert(LinkerConfig::DynObj == m_Config.codeGenType() || 45 LinkerConfig::Exec == m_Config.codeGenType() || 46 LinkerConfig::Binary == m_Config.codeGenType()); 47 48 m_PLT0 = hexagon_plt0; 49 m_PLT0Size = sizeof (hexagon_plt0); 50 // create PLT0 51 new HexagonPLT0(*m_pSectionData); 52 pSection.setAlign(16); 53} 54 55HexagonPLT::~HexagonPLT() 56{ 57} 58 59PLTEntryBase* HexagonPLT::getPLT0() const 60{ 61 iterator first = m_pSectionData->getFragmentList().begin(); 62 63 assert(first != m_pSectionData->getFragmentList().end() && 64 "FragmentList is empty, getPLT0 failed!"); 65 66 PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first)); 67 68 return plt0; 69} 70 71void HexagonPLT::finalizeSectionSize() 72{ 73 uint64_t size = 0; 74 // plt0 size 75 size = getPLT0()->size(); 76 77 // get first plt1 entry 78 HexagonPLT::iterator it = begin(); 79 ++it; 80 if (end() != it) { 81 // plt1 size 82 PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it)); 83 size += (m_pSectionData->size() - 1) * plt1->size(); 84 } 85 m_Section.setSize(size); 86 87 uint32_t offset = 0; 88 SectionData::iterator frag, fragEnd = m_pSectionData->end(); 89 for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) { 90 frag->setOffset(offset); 91 offset += frag->size(); 92 } 93} 94 95bool HexagonPLT::hasPLT1() const 96{ 97 return (m_pSectionData->size() > 1); 98} 99 100HexagonPLT1* HexagonPLT::create() 101{ 102 return new HexagonPLT1(*m_pSectionData); 103} 104 105void HexagonPLT::applyPLT0() 106{ 107 PLTEntryBase* plt0 = getPLT0(); 108 uint64_t pltBase = m_Section.addr(); 109 110 unsigned char* data = 0; 111 data = static_cast<unsigned char*>(malloc(plt0->size())); 112 113 if (!data) 114 fatal(diag::fail_allocate_memory_plt); 115 116 memcpy(data, m_PLT0, plt0->size()); 117 uint32_t gotpltAddr = m_GOTPLT.addr(); 118 119 int32_t *dest = (int32_t *)data; 120 int32_t result = ((gotpltAddr - pltBase ) >> 6); 121 *dest |= ApplyMask<int32_t>(0xfff3fff, result); 122 dest = dest + 1; 123 // Already calculated using pltBase 124 result = (gotpltAddr - pltBase); 125 *(dest) |= ApplyMask<int32_t>(0x1f80, result); 126 127 plt0->setValue(data); 128} 129 130void HexagonPLT::applyPLT1() { 131 132 uint64_t plt_base = m_Section.addr(); 133 assert(plt_base && ".plt base address is NULL!"); 134 135 uint64_t got_base = m_GOTPLT.addr(); 136 assert(got_base && ".got base address is NULL!"); 137 138 HexagonPLT::iterator it = m_pSectionData->begin(); 139 HexagonPLT::iterator ie = m_pSectionData->end(); 140 assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 141 142 uint32_t GOTEntrySize = HexagonGOTEntry::EntrySize; 143 uint32_t GOTEntryAddress = 144 got_base + GOTEntrySize * 4; 145 146 uint64_t PLTEntryAddress = 147 plt_base + HexagonPLT0::EntrySize; //Offset of PLT0 148 149 ++it; //skip PLT0 150 uint64_t PLT1EntrySize = HexagonPLT1::EntrySize; 151 HexagonPLT1* plt1 = NULL; 152 153 uint32_t* Out = NULL; 154 while (it != ie) { 155 plt1 = &(llvm::cast<HexagonPLT1>(*it)); 156 Out = static_cast<uint32_t*>(malloc(HexagonPLT1::EntrySize)); 157 158 if (!Out) 159 fatal(diag::fail_allocate_memory_plt); 160 161 memcpy(Out, hexagon_plt1, plt1->size()); 162 163 int32_t *dest = (int32_t *)Out; 164 int32_t result = ((GOTEntryAddress - PLTEntryAddress ) >> 6); 165 *dest |= ApplyMask<int32_t>(0xfff3fff, result); 166 dest = dest + 1; 167 result = (GOTEntryAddress - PLTEntryAddress); 168 *(dest) |= ApplyMask<int32_t>(0x1f80, result); 169 170 // Address in the PLT entries point to the corresponding GOT entries 171 // TODO: Fixup plt to point to the corresponding GOTEntryAddress 172 // We need to borrow the same relocation code to fix the relocation 173 plt1->setValue(reinterpret_cast<unsigned char*>(Out)); 174 ++it; 175 176 GOTEntryAddress += GOTEntrySize; 177 PLTEntryAddress += PLT1EntrySize; 178 } 179} 180 181uint64_t HexagonPLT::emit(MemoryRegion& pRegion) 182{ 183 uint64_t result = 0x0; 184 iterator it = begin(); 185 186 unsigned char* buffer = pRegion.begin(); 187 memcpy(buffer, llvm::cast<HexagonPLT0>((*it)).getValue(), HexagonPLT0::EntrySize); 188 result += HexagonPLT0::EntrySize; 189 ++it; 190 191 HexagonPLT1* plt1 = 0; 192 HexagonPLT::iterator ie = end(); 193 while (it != ie) { 194 plt1 = &(llvm::cast<HexagonPLT1>(*it)); 195 memcpy(buffer + result, plt1->getValue(), HexagonPLT1::EntrySize); 196 result += HexagonPLT1::EntrySize; 197 ++it; 198 } 199 return result; 200} 201 202