THMToTHMStub.cpp revision a790f0a8f3175183bea088389b3e4ae41813e192
1//===- THMToTHMStub.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 "THMToTHMStub.h" 11#include "ARMLDBackend.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 18using namespace mcld; 19 20//===----------------------------------------------------------------------===// 21// THMToTHMStub 22//===----------------------------------------------------------------------===// 23const uint32_t THMToTHMStub::PIC_TEMPLATE[] = { 24 0x46c04778, // bx pc ... nop 25 0xe59fc004, // ldr r12, [pc, #4] 26 0xe08fc00c, // add ip, pc, ip 27 0xe12fff1c, // bx ip 28 0x0 // dcd R_ARM_REL32(X) 29}; 30 31const uint32_t THMToTHMStub::TEMPLATE[] = { 32 0x46c04778, // bx pc ... nop 33 0xe59fc000, // ldr ip, [pc, #0] 34 0xe12fff1c, // bx ip 35 0x0 // dcd R_ARM_ABS32(X) 36}; 37 38THMToTHMStub::THMToTHMStub(bool pIsOutputPIC, bool pUsingThumb2) 39 : m_pData(NULL), 40 m_Name("T2T_prototype"), 41 m_Size(0x0), 42 m_bUsingThumb2(pUsingThumb2) 43{ 44 if (pIsOutputPIC) { 45 m_pData = PIC_TEMPLATE; 46 m_Size = sizeof(PIC_TEMPLATE); 47 addFixup(16u, 0x0, llvm::ELF::R_ARM_REL32); 48 } else { 49 m_pData = TEMPLATE; 50 m_Size = sizeof(TEMPLATE); 51 addFixup(12u, 0x0, llvm::ELF::R_ARM_ABS32); 52 } 53} 54 55/// for doClone 56THMToTHMStub::THMToTHMStub(const uint32_t* pData, 57 size_t pSize, 58 const_fixup_iterator pBegin, 59 const_fixup_iterator pEnd, 60 bool pUsingThumb2) 61 : m_pData(pData), 62 m_Name("T2T_veneer"), 63 m_Size(pSize), 64 m_bUsingThumb2(pUsingThumb2) 65{ 66 for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it) 67 addFixup(**it); 68} 69 70THMToTHMStub::~THMToTHMStub() 71{ 72} 73 74bool THMToTHMStub::isMyDuty(const class Relocation& pReloc, 75 uint64_t pSource, 76 uint64_t pTargetSymValue) const 77{ 78 bool result = false; 79 // Check if the branch target is THUMB 80 if ((pTargetSymValue & 0x1) != 0x0) { 81 switch (pReloc.type()) { 82 case llvm::ELF::R_ARM_THM_CALL: 83 case llvm::ELF::R_ARM_THM_JUMP24: { 84 // Check if the branch target is too far 85 uint64_t dest = pTargetSymValue + pReloc.addend() + 4u; 86 int64_t branch_offset = static_cast<int64_t>(dest) - pSource; 87 if (m_bUsingThumb2) { 88 if ((branch_offset > ARMGNULDBackend::THM2_MAX_FWD_BRANCH_OFFSET) || 89 (branch_offset < ARMGNULDBackend::THM2_MAX_BWD_BRANCH_OFFSET)) { 90 result = true; 91 break; 92 } 93 } else { 94 if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) || 95 (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET)) { 96 result = true; 97 break; 98 } 99 } 100 break; 101 } 102 default: 103 break; 104 } 105 } 106 return result; 107} 108 109const std::string& THMToTHMStub::name() const 110{ 111 return m_Name; 112} 113 114const uint8_t* THMToTHMStub::getContent() const 115{ 116 return reinterpret_cast<const uint8_t*>(m_pData); 117} 118 119size_t THMToTHMStub::size() const 120{ 121 return m_Size; 122} 123 124size_t THMToTHMStub::alignment() const 125{ 126 return 4u; 127} 128 129uint64_t THMToTHMStub::initSymValue() const 130{ 131 return 0x1; 132} 133 134Stub* THMToTHMStub::doClone() 135{ 136 return new THMToTHMStub(m_pData, 137 m_Size, 138 fixup_begin(), 139 fixup_end(), 140 m_bUsingThumb2); 141} 142