Home | History | Annotate | Download | only in ARM
      1 //===- ARMToARMStub.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 "ARMToARMStub.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 // ARMToARMStub
     22 //===----------------------------------------------------------------------===//
     23 const uint32_t ARMToARMStub::PIC_TEMPLATE[] = {
     24   0xe59fc000, // ldr   r12, [pc]
     25   0xe08ff00c, // add   pc, pc, ip
     26   0x0         // dcd   R_ARM_REL32(X-4)
     27 };
     28 
     29 const uint32_t ARMToARMStub::TEMPLATE[] = {
     30   0xe51ff004, // ldr   pc, [pc, #-4]
     31   0x0         // dcd   R_ARM_ABS32(X)
     32 };
     33 
     34 ARMToARMStub::ARMToARMStub(bool pIsOutputPIC)
     35  : Stub(), m_Name("A2A_prototype"), m_pData(NULL), m_Size(0x0)
     36 {
     37   if (pIsOutputPIC) {
     38     m_pData = PIC_TEMPLATE;
     39     m_Size = sizeof(PIC_TEMPLATE);
     40     addFixup(8u, -4, llvm::ELF::R_ARM_REL32);
     41   }
     42   else {
     43     m_pData = TEMPLATE;
     44     m_Size = sizeof(TEMPLATE);
     45     addFixup(4u, 0x0, llvm::ELF::R_ARM_ABS32);
     46   }
     47 }
     48 
     49 /// for doClone
     50 ARMToARMStub::ARMToARMStub(const uint32_t* pData,
     51                            size_t pSize,
     52                            const_fixup_iterator pBegin,
     53                            const_fixup_iterator pEnd)
     54  : Stub(), m_Name("A2A_veneer"), m_pData(pData), m_Size(pSize)
     55 {
     56   for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
     57     addFixup(**it);
     58 }
     59 
     60 ARMToARMStub::~ARMToARMStub()
     61 {
     62 }
     63 
     64 bool ARMToARMStub::isMyDuty(const class Relocation& pReloc,
     65                             uint64_t pSource,
     66                             uint64_t pTargetSymValue) const
     67 {
     68   bool result = false;
     69   // Check if the branch target is ARM
     70   if ((pTargetSymValue & 0x1) == 0x0) {
     71     switch (pReloc.type()) {
     72       case llvm::ELF::R_ARM_CALL:
     73       case llvm::ELF::R_ARM_JUMP24:
     74       case llvm::ELF::R_ARM_PLT32: {
     75         // Check if the branch target is too far
     76         uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
     77         int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
     78         if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
     79             (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
     80           result =  true;
     81         }
     82         break;
     83       }
     84       default:
     85         break;
     86     }
     87   }
     88   return result;
     89 }
     90 
     91 const std::string& ARMToARMStub::name() const
     92 {
     93   return m_Name;
     94 }
     95 
     96 const uint8_t* ARMToARMStub::getContent() const
     97 {
     98   return reinterpret_cast<const uint8_t*>(m_pData);
     99 }
    100 
    101 size_t ARMToARMStub::size() const
    102 {
    103   return m_Size;
    104 }
    105 
    106 size_t ARMToARMStub::alignment() const
    107 {
    108   return 4u;
    109 }
    110 
    111 Stub* ARMToARMStub::doClone()
    112 {
    113   return new ARMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
    114 }
    115 
    116