X86PLT.cpp revision d0fbbb227051be16931a1aa9b4a7722ac039c698
1//===- X86PLT.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 "X86GOTPLT.h" 10#include "X86PLT.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//===----------------------------------------------------------------------===// 24X86DynPLT0::X86DynPLT0(SectionData& pParent) 25 : PLT::Entry<sizeof(x86_dyn_plt0)>(pParent) 26{ 27} 28 29X86DynPLT1::X86DynPLT1(SectionData& pParent) 30 : PLT::Entry<sizeof(x86_dyn_plt1)>(pParent) 31{ 32} 33 34X86ExecPLT0::X86ExecPLT0(SectionData& pParent) 35 : PLT::Entry<sizeof(x86_exec_plt0)>(pParent) 36{ 37} 38 39X86ExecPLT1::X86ExecPLT1(SectionData& pParent) 40 : PLT::Entry<sizeof(x86_exec_plt1)>(pParent) 41{ 42} 43 44//===----------------------------------------------------------------------===// 45// X86PLT 46//===----------------------------------------------------------------------===// 47X86PLT::X86PLT(LDSection& pSection, 48 X86GOTPLT &pGOTPLT, 49 const LinkerConfig& pConfig) 50 : PLT(pSection), 51 m_GOTPLT(pGOTPLT), 52 m_Config(pConfig) 53{ 54 assert(LinkerConfig::DynObj == m_Config.codeGenType() || 55 LinkerConfig::Exec == m_Config.codeGenType() || 56 LinkerConfig::Binary == m_Config.codeGenType()); 57 58 if (LinkerConfig::DynObj == m_Config.codeGenType()) { 59 m_PLT0 = x86_dyn_plt0; 60 m_PLT1 = x86_dyn_plt1; 61 m_PLT0Size = sizeof (x86_dyn_plt0); 62 m_PLT1Size = sizeof (x86_dyn_plt1); 63 // create PLT0 64 new X86DynPLT0(*m_SectionData); 65 } 66 else { 67 m_PLT0 = x86_exec_plt0; 68 m_PLT1 = x86_exec_plt1; 69 m_PLT0Size = sizeof (x86_exec_plt0); 70 m_PLT1Size = sizeof (x86_exec_plt1); 71 // create PLT0 72 new X86ExecPLT0(*m_SectionData); 73 } 74 m_Last = m_SectionData->begin(); 75} 76 77X86PLT::~X86PLT() 78{ 79} 80 81void X86PLT::finalizeSectionSize() 82{ 83 uint64_t size = 0; 84 // plt0 size 85 size = getPLT0()->size(); 86 87 // get first plt1 entry 88 X86PLT::iterator it = begin(); 89 ++it; 90 if (end() != it) { 91 // plt1 size 92 PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it)); 93 size += (m_SectionData->size() - 1) * plt1->size(); 94 } 95 m_Section.setSize(size); 96 97 uint32_t offset = 0; 98 SectionData::iterator frag, fragEnd = m_SectionData->end(); 99 for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) { 100 frag->setOffset(offset); 101 offset += frag->size(); 102 } 103} 104 105bool X86PLT::hasPLT1() const 106{ 107 return (m_SectionData->size() > 1); 108} 109 110void X86PLT::reserveEntry(size_t pNum) 111{ 112 PLTEntryBase* plt1_entry = NULL; 113 114 for (size_t i = 0; i < pNum; ++i) { 115 116 if (LinkerConfig::DynObj == m_Config.codeGenType()) 117 plt1_entry = new X86DynPLT1(*m_SectionData); 118 else 119 plt1_entry = new X86ExecPLT1(*m_SectionData); 120 121 if (NULL == plt1_entry) 122 fatal(diag::fail_allocate_memory_plt); 123 } 124} 125 126PLTEntryBase* X86PLT::consume() 127{ 128 // This will skip PLT0. 129 ++m_Last; 130 assert(m_Last != m_SectionData->end() && 131 "The number of PLT Entries and ResolveInfo doesn't match"); 132 return llvm::cast<PLTEntryBase>(&(*m_Last)); 133} 134 135PLTEntryBase* X86PLT::getPLT0() const 136{ 137 iterator first = m_SectionData->getFragmentList().begin(); 138 139 assert(first != m_SectionData->getFragmentList().end() && 140 "FragmentList is empty, getPLT0 failed!"); 141 142 PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first)); 143 144 return plt0; 145} 146 147// FIXME: It only works on little endian machine. 148void X86PLT::applyPLT0() 149{ 150 PLTEntryBase* plt0 = getPLT0(); 151 152 unsigned char* data = 0; 153 data = static_cast<unsigned char*>(malloc(plt0->size())); 154 155 if (!data) 156 fatal(diag::fail_allocate_memory_plt); 157 158 memcpy(data, m_PLT0, plt0->size()); 159 160 if (m_PLT0 == x86_exec_plt0) { 161 uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2); 162 *offset = m_GOTPLT.addr() + 4; 163 offset = reinterpret_cast<uint32_t*>(data + 8); 164 *offset = m_GOTPLT.addr() + 8; 165 } 166 167 plt0->setValue(data); 168} 169 170// FIXME: It only works on little endian machine. 171void X86PLT::applyPLT1() 172{ 173 assert(m_Section.addr() && ".plt base address is NULL!"); 174 175 X86PLT::iterator it = m_SectionData->begin(); 176 X86PLT::iterator ie = m_SectionData->end(); 177 assert(it != ie && "FragmentList is empty, applyPLT1 failed!"); 178 179 uint64_t GOTEntrySize = X86GOTPLTEntry::EntrySize; 180 181 // Skip GOT0 182 uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num; 183 if (LinkerConfig::Exec == m_Config.codeGenType()) 184 GOTEntryOffset += m_GOTPLT.addr(); 185 186 //skip PLT0 187 uint64_t PLTEntryOffset = m_PLT0Size; 188 ++it; 189 190 PLTEntryBase* plt1 = 0; 191 192 uint64_t PLTRelOffset = 0; 193 194 while (it != ie) { 195 plt1 = &(llvm::cast<PLTEntryBase>(*it)); 196 unsigned char *data; 197 data = static_cast<unsigned char*>(malloc(plt1->size())); 198 199 if (!data) 200 fatal(diag::fail_allocate_memory_plt); 201 202 memcpy(data, m_PLT1, plt1->size()); 203 204 uint32_t* offset; 205 206 offset = reinterpret_cast<uint32_t*>(data + 2); 207 *offset = GOTEntryOffset; 208 GOTEntryOffset += GOTEntrySize; 209 210 offset = reinterpret_cast<uint32_t*>(data + 7); 211 *offset = PLTRelOffset; 212 PLTRelOffset += sizeof (llvm::ELF::Elf32_Rel); 213 214 offset = reinterpret_cast<uint32_t*>(data + 12); 215 *offset = -(PLTEntryOffset + 12 + 4); 216 PLTEntryOffset += m_PLT1Size; 217 218 plt1->setValue(data); 219 ++it; 220 } 221} 222 223