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 19 using namespace mcld; 20 21 //===----------------------------------------------------------------------===// 22 // PLT entry data 23 //===----------------------------------------------------------------------===// 24 HexagonPLT0::HexagonPLT0(SectionData& pParent) 25 : PLT::Entry<sizeof(hexagon_plt0)>(pParent) 26 { 27 } 28 29 HexagonPLT1::HexagonPLT1(SectionData& pParent) 30 : PLT::Entry<sizeof(hexagon_plt1)>(pParent) 31 { 32 } 33 34 //===----------------------------------------------------------------------===// 35 // HexagonPLT 36 //===----------------------------------------------------------------------===// 37 HexagonPLT::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 55 HexagonPLT::~HexagonPLT() 56 { 57 } 58 59 PLTEntryBase* 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 71 void 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 95 bool HexagonPLT::hasPLT1() const 96 { 97 return (m_pSectionData->size() > 1); 98 } 99 100 HexagonPLT1* HexagonPLT::create() 101 { 102 return new HexagonPLT1(*m_pSectionData); 103 } 104 105 void 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 130 void 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 181 uint64_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