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_PC24:
     73       case llvm::ELF::R_ARM_CALL:
     74       case llvm::ELF::R_ARM_JUMP24:
     75       case llvm::ELF::R_ARM_PLT32: {
     76         // Check if the branch target is too far
     77         uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
     78         int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
     79         if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
     80             (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
     81           result =  true;
     82         }
     83         break;
     84       }
     85       default:
     86         break;
     87     }
     88   }
     89   return result;
     90 }
     91 
     92 const std::string& ARMToARMStub::name() const
     93 {
     94   return m_Name;
     95 }
     96 
     97 const uint8_t* ARMToARMStub::getContent() const
     98 {
     99   return reinterpret_cast<const uint8_t*>(m_pData);
    100 }
    101 
    102 size_t ARMToARMStub::size() const
    103 {
    104   return m_Size;
    105 }
    106 
    107 size_t ARMToARMStub::alignment() const
    108 {
    109   return 4u;
    110 }
    111 
    112 Stub* ARMToARMStub::doClone()
    113 {
    114   return new ARMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
    115 }
    116 
    117