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_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