122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===- ARMToTHMStub.cpp ---------------------------------------------------===//
222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//
322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//                     The MCLinker Project
422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//
522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// This file is distributed under the University of Illinois Open Source
622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// License. See LICENSE.TXT for details.
722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//
822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARMToTHMStub.h"
1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARMLDBackend.h"
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/ELF.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/ResolveInfo.h>
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSymbol.h>
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Relocation.h>
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaousing namespace mcld;
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ARMToTHMStub
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoconst uint32_t ARMToTHMStub::PIC_TEMPLATE[] = {
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0xe59fc004, // ldr   r12, [pc, #4]
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0xe08fc00c, // add   ip, pc, ip
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0xe12fff1c, // bx    ip
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0x0         // dcd   R_ARM_REL32(X)
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao};
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoconst uint32_t ARMToTHMStub::TEMPLATE[] = {
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0xe59fc000, // ldr   ip, [pc, #0]
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0xe12fff1c, // bx    ip
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  0x0         // dcd   R_ARM_ABS32(X)
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao};
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMToTHMStub::ARMToTHMStub(bool pIsOutputPIC)
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao : Stub(), m_Name("A2T_prototype"), m_pData(NULL), m_Size(0x0)
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pIsOutputPIC) {
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_pData = PIC_TEMPLATE;
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Size = sizeof(PIC_TEMPLATE);
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    addFixup(12u, 0x0, llvm::ELF::R_ARM_REL32);
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_pData = TEMPLATE;
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Size = sizeof(TEMPLATE);
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    addFixup(8u, 0x0, llvm::ELF::R_ARM_ABS32);
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// for doClone
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMToTHMStub::ARMToTHMStub(const uint32_t* pData,
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                           size_t pSize,
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                           const_fixup_iterator pBegin,
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                           const_fixup_iterator pEnd)
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao : Stub(), m_Name("A2T_veneer"), m_pData(pData), m_Size(pSize)
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    addFixup(**it);
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMToTHMStub::~ARMToTHMStub()
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMToTHMStub::isMyDuty(const class Relocation& pReloc,
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                            uint64_t pSource,
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                            uint64_t pTargetSymValue) const
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool result = false;
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // Check if the branch target is THUMB
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if ((pTargetSymValue & 0x1) != 0x0) {
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    switch (pReloc.type()) {
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::R_ARM_CALL: {
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // FIXME: Assuming blx is available (i.e., target is armv5 or above!)
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // then, we do not need a stub unless the branch target is too far.
7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          result = true;
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          break;
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        }
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      }
86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      case llvm::ELF::R_ARM_PC24:
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::R_ARM_JUMP24:
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::R_ARM_PLT32: {
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // always need a stub to switch mode
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        result = true;
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      }
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      default:
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoconst std::string& ARMToTHMStub::name() const
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return m_Name;
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoconst uint8_t* ARMToTHMStub::getContent() const
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return reinterpret_cast<const uint8_t*>(m_pData);
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaosize_t ARMToTHMStub::size() const
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return m_Size;
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaosize_t ARMToTHMStub::alignment() const
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return 4u;
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* ARMToTHMStub::doClone()
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return new ARMToTHMStub(m_pData, m_Size, fixup_begin(), fixup_end());
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
125