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 18 using namespace mcld; 19 20 //===----------------------------------------------------------------------===// 21 // THMToTHMStub 22 //===----------------------------------------------------------------------===// 23 const 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 31 const 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 38 THMToTHMStub::THMToTHMStub(bool pIsOutputPIC) 39 : Stub(), m_Name("T2T_prototype"), m_pData(NULL), m_Size(0x0) 40 { 41 if (pIsOutputPIC) { 42 m_pData = PIC_TEMPLATE; 43 m_Size = sizeof(PIC_TEMPLATE); 44 addFixup(16u, 0x0, llvm::ELF::R_ARM_REL32); 45 } 46 else { 47 m_pData = TEMPLATE; 48 m_Size = sizeof(TEMPLATE); 49 addFixup(12u, 0x0, llvm::ELF::R_ARM_ABS32); 50 } 51 } 52 53 /// for doClone 54 THMToTHMStub::THMToTHMStub(const uint32_t* pData, 55 size_t pSize, 56 const_fixup_iterator pBegin, 57 const_fixup_iterator pEnd) 58 : Stub(), m_Name("T2T_veneer"), m_pData(pData), m_Size(pSize) 59 { 60 for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it) 61 addFixup(**it); 62 } 63 64 THMToTHMStub::~THMToTHMStub() 65 { 66 } 67 68 bool THMToTHMStub::isMyDuty(const class Relocation& pReloc, 69 uint64_t pSource, 70 uint64_t pTargetSymValue) const 71 { 72 bool result = false; 73 // Check if the branch target is THUMB 74 if ((pTargetSymValue & 0x1) != 0x0) { 75 switch (pReloc.type()) { 76 case llvm::ELF::R_ARM_THM_CALL: 77 case llvm::ELF::R_ARM_THM_JUMP24: { 78 // Check if the branch target is too far 79 uint64_t dest = pTargetSymValue + pReloc.addend() + 4u; 80 int64_t branch_offset = static_cast<int64_t>(dest) - pSource; 81 if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) || 82 (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET)) 83 result = true; 84 break; 85 } 86 default: 87 break; 88 } 89 } 90 return result; 91 } 92 93 const std::string& THMToTHMStub::name() const 94 { 95 return m_Name; 96 } 97 98 const uint8_t* THMToTHMStub::getContent() const 99 { 100 return reinterpret_cast<const uint8_t*>(m_pData); 101 } 102 103 size_t THMToTHMStub::size() const 104 { 105 return m_Size; 106 } 107 108 size_t THMToTHMStub::alignment() const 109 { 110 return 4u; 111 } 112 113 uint64_t THMToTHMStub::initSymValue() const 114 { 115 return 0x1; 116 } 117 118 Stub* THMToTHMStub::doClone() 119 { 120 return new THMToTHMStub(m_pData, m_Size, fixup_begin(), fixup_end()); 121 } 122 123