122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===- ARMToARMStub.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 "ARMToARMStub.h"
1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARMLDBackend.h"
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/ELF.h>
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ARMToARMStub
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoconst uint32_t ARMToARMStub::PIC_TEMPLATE[] = {
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    0xe59fc000,  // ldr   r12, [pc]
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    0xe08ff00c,  // add   pc, pc, ip
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    0x0          // dcd   R_ARM_REL32(X-4)
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao};
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoconst uint32_t ARMToARMStub::TEMPLATE[] = {
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    0xe51ff004,  // ldr   pc, [pc, #-4]
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    0x0          // dcd   R_ARM_ABS32(X)
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao};
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMToARMStub::ARMToARMStub(bool pIsOutputPIC)
3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_pData(NULL), m_Name("A2A_prototype"), m_Size(0x0) {
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pIsOutputPIC) {
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_pData = PIC_TEMPLATE;
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Size = sizeof(PIC_TEMPLATE);
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    addFixup(8u, -4, llvm::ELF::R_ARM_REL32);
4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_pData = TEMPLATE;
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Size = sizeof(TEMPLATE);
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    addFixup(4u, 0x0, llvm::ELF::R_ARM_ABS32);
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// for doClone
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMToARMStub::ARMToARMStub(const uint32_t* pData,
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                           size_t pSize,
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                           const_fixup_iterator pBegin,
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                           const_fixup_iterator pEnd)
5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_pData(pData), m_Name("A2A_veneer"), m_Size(pSize) {
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    addFixup(**it);
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5837b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMToARMStub::~ARMToARMStub() {
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMToARMStub::isMyDuty(const class Relocation& pReloc,
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                            uint64_t pSource,
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                            uint64_t pTargetSymValue) const {
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool result = false;
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // Check if the branch target is ARM
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if ((pTargetSymValue & 0x1) == 0x0) {
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    switch (pReloc.type()) {
68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      case llvm::ELF::R_ARM_PC24:
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::R_ARM_CALL:
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::R_ARM_JUMP24:
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::R_ARM_PLT32: {
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // Check if the branch target is too far
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          result = true;
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        }
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      }
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      default:
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst std::string& ARMToARMStub::name() const {
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return m_Name;
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst uint8_t* ARMToARMStub::getContent() const {
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return reinterpret_cast<const uint8_t*>(m_pData);
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ARMToARMStub::size() const {
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return m_Size;
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ARMToARMStub::alignment() const {
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return 4u;
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10437b74a387bb3993387029859c2d9d051c41c724eStephen HinesStub* ARMToARMStub::doClone() {
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return new ARMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines
10837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
109