C++程序  |  92行  |  2.37 KB

//===- MipsLA25Stub.cpp ---------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mcld/LD/ResolveInfo.h"
#include "MipsLA25Stub.h"
#include "MipsLDBackend.h"

namespace {

const uint32_t STUB[] = {
    0x3c190000,  // lui $25,%hi(func)
    0x08000000,  // j func
    0x27390000,  // add $25,$25,%lo(func)
    0x00000000   // nop
};

}  // anonymous namespace

namespace mcld {

//===----------------------------------------------------------------------===//
// MipsLA25Stub
//===----------------------------------------------------------------------===//

MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget)
    : m_Target(pTarget),
      m_Name("MipsLA25_Prototype"),
      m_pData(STUB),
      m_Size(sizeof(STUB)) {
  addFixup(0, 0x0, llvm::ELF::R_MIPS_HI16);
  addFixup(4, 0x0, llvm::ELF::R_MIPS_26);
  addFixup(8, 0x0, llvm::ELF::R_MIPS_LO16);
}

MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget,
                           const uint32_t* pData,
                           size_t pSize,
                           const_fixup_iterator pBegin,
                           const_fixup_iterator pEnd)
    : m_Target(pTarget), m_Name("pic"), m_pData(pData), m_Size(pSize) {
  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
    addFixup(**it);
}

bool MipsLA25Stub::isMyDuty(const Relocation& pReloc,
                            uint64_t pSource,
                            uint64_t pTargetSymValue) const {
  if (llvm::ELF::R_MIPS_26 != pReloc.type())
    return false;

  const ResolveInfo* rsym = pReloc.symInfo();

  if (!rsym->isDefine())
    return false;

  if (rsym->isDyn() || rsym->isUndef())
    return false;

  if (!m_Target.hasNonPICBranch(rsym))
    return false;

  return true;
}

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

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

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

size_t MipsLA25Stub::alignment() const {
  return 4;
}

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

}  // namespace mcld