• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
THMToTHMStub(bool pIsOutputPIC,bool pUsingThumb2)38 THMToTHMStub::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
THMToTHMStub(const uint32_t * pData,size_t pSize,const_fixup_iterator pBegin,const_fixup_iterator pEnd,bool pUsingThumb2)56 THMToTHMStub::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 
~THMToTHMStub()70 THMToTHMStub::~THMToTHMStub()
71 {
72 }
73 
isMyDuty(const class Relocation & pReloc,uint64_t pSource,uint64_t pTargetSymValue) const74 bool 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 
name() const109 const std::string& THMToTHMStub::name() const
110 {
111   return m_Name;
112 }
113 
getContent() const114 const uint8_t* THMToTHMStub::getContent() const
115 {
116   return reinterpret_cast<const uint8_t*>(m_pData);
117 }
118 
size() const119 size_t THMToTHMStub::size() const
120 {
121   return m_Size;
122 }
123 
alignment() const124 size_t THMToTHMStub::alignment() const
125 {
126   return 4u;
127 }
128 
initSymValue() const129 uint64_t THMToTHMStub::initSymValue() const
130 {
131   return 0x1;
132 }
133 
doClone()134 Stub* THMToTHMStub::doClone()
135 {
136   return new THMToTHMStub(m_pData,
137                           m_Size,
138                           fixup_begin(),
139                           fixup_end(),
140                           m_bUsingThumb2);
141 }
142