//===- 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(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