Home | History | Annotate | Download | only in ARM
      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 "mcld/Fragment/Relocation.h"
     14 #include "mcld/LD/LDSymbol.h"
     15 #include "mcld/LD/ResolveInfo.h"
     16 
     17 #include <llvm/Support/ELF.h>
     18 
     19 namespace mcld {
     20 
     21 //===----------------------------------------------------------------------===//
     22 // THMToTHMStub
     23 //===----------------------------------------------------------------------===//
     24 const uint32_t THMToTHMStub::PIC_TEMPLATE[] = {
     25     0x46c04778,  // bx    pc ... nop
     26     0xe59fc004,  // ldr   r12, [pc, #4]
     27     0xe08fc00c,  // add   ip, pc, ip
     28     0xe12fff1c,  // bx    ip
     29     0x0          // dcd   R_ARM_REL32(X)
     30 };
     31 
     32 const uint32_t THMToTHMStub::TEMPLATE[] = {
     33     0x46c04778,  // bx    pc ... nop
     34     0xe59fc000,  // ldr   ip, [pc, #0]
     35     0xe12fff1c,  // bx    ip
     36     0x0          // dcd   R_ARM_ABS32(X)
     37 };
     38 
     39 THMToTHMStub::THMToTHMStub(bool pIsOutputPIC, bool pUsingThumb2)
     40     : m_pData(NULL),
     41       m_Name("T2T_prototype"),
     42       m_Size(0x0),
     43       m_bUsingThumb2(pUsingThumb2) {
     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
     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   for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
     66     addFixup(**it);
     67 }
     68 
     69 THMToTHMStub::~THMToTHMStub() {
     70 }
     71 
     72 bool THMToTHMStub::isMyDuty(const class Relocation& pReloc,
     73                             uint64_t pSource,
     74                             uint64_t pTargetSymValue) const {
     75   bool result = false;
     76   // Check if the branch target is THUMB
     77   if ((pTargetSymValue & 0x1) != 0x0) {
     78     switch (pReloc.type()) {
     79       case llvm::ELF::R_ARM_THM_CALL:
     80       case llvm::ELF::R_ARM_THM_JUMP24: {
     81         // Check if the branch target is too far
     82         uint64_t dest = pTargetSymValue + pReloc.addend() + 4u;
     83         int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
     84         if (m_bUsingThumb2) {
     85           if ((branch_offset > ARMGNULDBackend::THM2_MAX_FWD_BRANCH_OFFSET) ||
     86               (branch_offset < ARMGNULDBackend::THM2_MAX_BWD_BRANCH_OFFSET)) {
     87             result = true;
     88             break;
     89           }
     90         } else {
     91           if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) ||
     92               (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET)) {
     93             result = true;
     94             break;
     95           }
     96         }
     97         break;
     98       }
     99       default:
    100         break;
    101     }
    102   }
    103   return result;
    104 }
    105 
    106 const std::string& THMToTHMStub::name() const {
    107   return m_Name;
    108 }
    109 
    110 const uint8_t* THMToTHMStub::getContent() const {
    111   return reinterpret_cast<const uint8_t*>(m_pData);
    112 }
    113 
    114 size_t THMToTHMStub::size() const {
    115   return m_Size;
    116 }
    117 
    118 size_t THMToTHMStub::alignment() const {
    119   return 4u;
    120 }
    121 
    122 uint64_t THMToTHMStub::initSymValue() const {
    123   return 0x1;
    124 }
    125 
    126 Stub* THMToTHMStub::doClone() {
    127   return new THMToTHMStub(
    128       m_pData, m_Size, fixup_begin(), fixup_end(), m_bUsingThumb2);
    129 }
    130 
    131 }  // namespace mcld
    132