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