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_SectionData); 52 m_Last = m_SectionData->begin(); 53 pSection.setAlign(16); 54 } 55 56 HexagonPLT::~HexagonPLT() 57 { 58 } 59 60 PLTEntryBase* HexagonPLT::getPLT0() const 61 { 62 iterator first = m_SectionData->getFragmentList().begin(); 63 64 assert(first != m_SectionData->getFragmentList().end() && 65 "FragmentList is empty, getPLT0 failed!"); 66 67 PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first)); 68 69 return plt0; 70 } 71 72 void HexagonPLT::finalizeSectionSize() 73 { 74 uint64_t size = 0; 75 // plt0 size 76 size = getPLT0()->size(); 77 78 // get first plt1 entry 79 HexagonPLT::iterator it = begin(); 80 ++it; 81 if (end() != it) { 82 // plt1 size 83 PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it)); 84 size += (m_SectionData->size() - 1) * plt1->size(); 85 } 86 m_Section.setSize(size); 87 88 uint32_t offset = 0; 89 SectionData::iterator frag, fragEnd = m_SectionData->end(); 90 for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) { 91 frag->setOffset(offset); 92 offset += frag->size(); 93 } 94 } 95 96 bool HexagonPLT::hasPLT1() const 97 { 98 return (m_SectionData->size() > 1); 99 } 100 101 void HexagonPLT::reserveEntry(size_t pNum) 102 { 103 PLTEntryBase* plt1_entry = NULL; 104 105 for (size_t i = 0; i < pNum; ++i) { 106 plt1_entry = new HexagonPLT1(*m_SectionData); 107 108 if (NULL == plt1_entry) 109 fatal(diag::fail_allocate_memory_plt); 110 } 111 } 112 113 HexagonPLT1* HexagonPLT::consume() 114 { 115 ++m_Last; 116 assert(m_Last != m_SectionData->end() && 117 "The number of PLT Entries and ResolveInfo doesn't match"); 118 119 return llvm::cast<HexagonPLT1>(&(*m_Last)); 120 } 121 122 void HexagonPLT::applyPLT0() 123 { 124 PLTEntryBase* plt0 = getPLT0(); 125 uint64_t pltBase = m_Section.addr(); 126 127 unsigned char* data = 0; 128 data = static_cast<unsigned char*>(malloc(plt0->size())); 129 130 if (!data) 131 fatal(diag::fail_allocate_memory_plt); 132 133 memcpy(data, m_PLT0, plt0->size()); 134 uint32_t gotpltAddr = m_GOTPLT.addr(); 135 136 int32_t *dest = (int32_t *)data; 137 int32_t result = ((gotpltAddr - pltBase ) >> 6); 138 *dest |= ApplyMask<int32_t>(0xfff3fff, result); 139 dest = dest + 1; 140 // Already calculated using pltBase 141 result = (gotpltAddr - pltBase); 142 *(dest) |= ApplyMask<int32_t>(0x1f80, result); 143 144 plt0->setValue(data); 145 } 146 147 void HexagonPLT::applyPLT1() { 148 149 uint64_t plt_base = m_Section.addr(); 150 assert(plt_base && ".plt base address is NULL!"); 151 152 uint64_t got_base = m_GOTPLT.addr(); 153 assert(got_base && ".got base address is NULL!"); 154 155 HexagonPLT::iterator it = m_SectionData->begin(); 156 HexagonPLT::iterator ie = m_SectionData->end(); 157 assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 158 159 uint32_t GOTEntrySize = HexagonGOTEntry::EntrySize; 160 uint32_t GOTEntryAddress = 161 got_base + GOTEntrySize * 4; 162 163 uint64_t PLTEntryAddress = 164 plt_base + HexagonPLT0::EntrySize; //Offset of PLT0 165 166 ++it; //skip PLT0 167 uint64_t PLT1EntrySize = HexagonPLT1::EntrySize; 168 HexagonPLT1* plt1 = NULL; 169 170 uint32_t* Out = NULL; 171 while (it != ie) { 172 plt1 = &(llvm::cast<HexagonPLT1>(*it)); 173 Out = static_cast<uint32_t*>(malloc(HexagonPLT1::EntrySize)); 174 175 if (!Out) 176 fatal(diag::fail_allocate_memory_plt); 177 178 memcpy(Out, hexagon_plt1, plt1->size()); 179 180 int32_t *dest = (int32_t *)Out; 181 int32_t result = ((GOTEntryAddress - PLTEntryAddress ) >> 6); 182 *dest |= ApplyMask<int32_t>(0xfff3fff, result); 183 dest = dest + 1; 184 result = (GOTEntryAddress - PLTEntryAddress); 185 *(dest) |= ApplyMask<int32_t>(0x1f80, result); 186 187 // Address in the PLT entries point to the corresponding GOT entries 188 // TODO: Fixup plt to point to the corresponding GOTEntryAddress 189 // We need to borrow the same relocation code to fix the relocation 190 plt1->setValue(reinterpret_cast<unsigned char*>(Out)); 191 ++it; 192 193 GOTEntryAddress += GOTEntrySize; 194 PLTEntryAddress += PLT1EntrySize; 195 } 196 } 197 198 uint64_t HexagonPLT::emit(MemoryRegion& pRegion) 199 { 200 uint64_t result = 0x0; 201 iterator it = begin(); 202 203 unsigned char* buffer = pRegion.getBuffer(); 204 memcpy(buffer, llvm::cast<HexagonPLT0>((*it)).getValue(), HexagonPLT0::EntrySize); 205 result += HexagonPLT0::EntrySize; 206 ++it; 207 208 HexagonPLT1* plt1 = 0; 209 HexagonPLT::iterator ie = end(); 210 while (it != ie) { 211 plt1 = &(llvm::cast<HexagonPLT1>(*it)); 212 memcpy(buffer + result, plt1->getValue(), HexagonPLT1::EntrySize); 213 result += HexagonPLT1::EntrySize; 214 ++it; 215 } 216 return result; 217 } 218 219