Home | History | Annotate | Download | only in Hexagon
      1 //===- HexagonAbsoluteStub.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 
     10 #include "HexagonAbsoluteStub.h"
     11 #include "HexagonLDBackend.h"
     12 
     13 #include <llvm/Support/ELF.h>
     14 #include <mcld/LD/ResolveInfo.h>
     15 #include <mcld/LD/LDSymbol.h>
     16 #include <mcld/Fragment/Relocation.h>
     17 
     18 using namespace mcld;
     19 
     20 //===----------------------------------------------------------------------===//
     21 // HexagonAbsoluteStub
     22 //===----------------------------------------------------------------------===//
     23 
     24 const uint32_t HexagonAbsoluteStub::TEMPLATE[] = {
     25   0xbffd7f1d, /* { sp = add (sp, #-8)      */
     26   0xa79dfcfe, /*   memw (sp + #-8) = r28 } */
     27   0x723cc000, /* r28.h = #HI (foo)         */
     28   0x713cc000, /* r28.l = #LO (foo)         */
     29   0xb01d411d, /* { sp = add (sp, #8)       */
     30   0x529c4000, /*   jumpr r28               */
     31   0x919dc01c  /*   r28 = memw (sp) }       */
     32 };
     33 
     34 #define FITS_IN_NBITS(D, B) \
     35     ((int64_t) abs (D) < (~(~(int64_t) 0 << ((B) - 1)) & -(4 * 4)))
     36 
     37 HexagonAbsoluteStub::HexagonAbsoluteStub(bool pIsOutputPIC)
     38  : Stub(), m_Name("HexagonTrampoline"), m_pData(NULL), m_Size(0x0)
     39 {
     40   m_pData = TEMPLATE;
     41   m_Size = sizeof(TEMPLATE);
     42   addFixup(8u, 0x0, llvm::ELF::R_HEX_HI16);
     43   addFixup(12u, 0x0, llvm::ELF::R_HEX_LO16);
     44 }
     45 
     46 /// for doClone
     47 HexagonAbsoluteStub::HexagonAbsoluteStub(const uint32_t* pData,
     48                            size_t pSize,
     49                            const_fixup_iterator pBegin,
     50                            const_fixup_iterator pEnd)
     51  : Stub(), m_Name("AbsVeneer"), m_pData(pData), m_Size(pSize)
     52 {
     53   for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
     54     addFixup(**it);
     55 }
     56 
     57 HexagonAbsoluteStub::~HexagonAbsoluteStub()
     58 {
     59 }
     60 
     61 bool HexagonAbsoluteStub::isMyDuty(const class Relocation& pReloc,
     62                             uint64_t pSource,
     63                             uint64_t pTargetSymValue) const
     64 {
     65   int nbits = 0;
     66   switch (pReloc.type()) {
     67     case llvm::ELF::R_HEX_B22_PCREL:
     68       nbits = 24;
     69       break;
     70     case llvm::ELF::R_HEX_B15_PCREL:
     71       nbits = 17;
     72       break;
     73     case llvm::ELF::R_HEX_B7_PCREL:
     74       nbits = 9;
     75       break;
     76     case llvm::ELF::R_HEX_B13_PCREL:
     77       nbits = 15;
     78       break;
     79     case llvm::ELF::R_HEX_B9_PCREL:
     80       nbits = 17;
     81       break;
     82     default:
     83       return false;
     84   }
     85 
     86   int64_t offset = pTargetSymValue - pSource;
     87   // if offset is going to fit in nbits then we dont
     88   // need a stub to be created
     89   if (FITS_IN_NBITS(offset, nbits))
     90     return false;
     91   return true;
     92 }
     93 
     94 const std::string& HexagonAbsoluteStub::name() const
     95 {
     96   return m_Name;
     97 }
     98 
     99 const uint8_t* HexagonAbsoluteStub::getContent() const
    100 {
    101   return reinterpret_cast<const uint8_t*>(m_pData);
    102 }
    103 
    104 size_t HexagonAbsoluteStub::size() const
    105 {
    106   return m_Size;
    107 }
    108 
    109 size_t HexagonAbsoluteStub::alignment() const
    110 {
    111   return 4u;
    112 }
    113 
    114 Stub* HexagonAbsoluteStub::doClone()
    115 {
    116   return new HexagonAbsoluteStub(m_pData, m_Size, fixup_begin(), fixup_end());
    117 }
    118