//===- 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 "mcld/LD/ResolveInfo.h" #include "mcld/LD/LDSymbol.h" #include "mcld/Fragment/Relocation.h" #include <llvm/Support/ELF.h> #include <llvm/Support/MathExtras.h> 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) \ (std::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()); } } // namespace mcld