C++程序  |  118行  |  3.08 KB

//===- HexagonAbsoluteStub.cpp ---------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "HexagonAbsoluteStub.h"
#include "HexagonLDBackend.h"

#include <llvm/Support/ELF.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/Fragment/Relocation.h>

using namespace mcld;

//===----------------------------------------------------------------------===//
// HexagonAbsoluteStub
//===----------------------------------------------------------------------===//

const uint32_t HexagonAbsoluteStub::TEMPLATE[] = {
  0xbffd7f1d, /* { sp = add (sp, #-8)      */
  0xa79dfcfe, /*   memw (sp + #-8) = r28 } */
  0x723cc000, /* r28.h = #HI (foo)         */
  0x713cc000, /* r28.l = #LO (foo)         */
  0xb01d411d, /* { sp = add (sp, #8)       */
  0x529c4000, /*   jumpr r28               */
  0x919dc01c  /*   r28 = memw (sp) }       */
};

#define FITS_IN_NBITS(D, B) \
    ((int64_t) abs (D) < (~(~(int64_t) 0 << ((B) - 1)) & -(4 * 4)))

HexagonAbsoluteStub::HexagonAbsoluteStub(bool pIsOutputPIC)
 : Stub(), m_Name("HexagonTrampoline"), m_pData(NULL), m_Size(0x0)
{
  m_pData = TEMPLATE;
  m_Size = sizeof(TEMPLATE);
  addFixup(8u, 0x0, llvm::ELF::R_HEX_HI16);
  addFixup(12u, 0x0, llvm::ELF::R_HEX_LO16);
}

/// for doClone
HexagonAbsoluteStub::HexagonAbsoluteStub(const uint32_t* pData,
                           size_t pSize,
                           const_fixup_iterator pBegin,
                           const_fixup_iterator pEnd)
 : Stub(), m_Name("AbsVeneer"), m_pData(pData), m_Size(pSize)
{
  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
    addFixup(**it);
}

HexagonAbsoluteStub::~HexagonAbsoluteStub()
{
}

bool HexagonAbsoluteStub::isMyDuty(const class Relocation& pReloc,
                            uint64_t pSource,
                            uint64_t pTargetSymValue) const
{
  int nbits = 0;
  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_B22_PCREL:
      nbits = 24;
      break;
    case llvm::ELF::R_HEX_B15_PCREL:
      nbits = 17;
      break;
    case llvm::ELF::R_HEX_B7_PCREL:
      nbits = 9;
      break;
    case llvm::ELF::R_HEX_B13_PCREL:
      nbits = 15;
      break;
    case llvm::ELF::R_HEX_B9_PCREL:
      nbits = 17;
      break;
    default:
      return false;
  }

  int64_t offset = pTargetSymValue - pSource;
  // if offset is going to fit in nbits then we dont
  // need a stub to be created
  if (FITS_IN_NBITS(offset, nbits))
    return false;
  return true;
}

const std::string& HexagonAbsoluteStub::name() const
{
  return m_Name;
}

const uint8_t* HexagonAbsoluteStub::getContent() const
{
  return reinterpret_cast<const uint8_t*>(m_pData);
}

size_t HexagonAbsoluteStub::size() const
{
  return m_Size;
}

size_t HexagonAbsoluteStub::alignment() const
{
  return 4u;
}

Stub* HexagonAbsoluteStub::doClone()
{
  return new HexagonAbsoluteStub(m_pData, m_Size, fixup_begin(), fixup_end());
}