Home | History | Annotate | Download | only in Hexagon
      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