1//===- MipsLA25Stub.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#include "mcld/LD/ResolveInfo.h"
10#include "MipsLA25Stub.h"
11#include "MipsLDBackend.h"
12
13namespace {
14
15const uint32_t STUB[] = {
16    0x3c190000,  // lui $25,%hi(func)
17    0x08000000,  // j func
18    0x27390000,  // add $25,$25,%lo(func)
19    0x00000000   // nop
20};
21
22}  // anonymous namespace
23
24namespace mcld {
25
26//===----------------------------------------------------------------------===//
27// MipsLA25Stub
28//===----------------------------------------------------------------------===//
29
30MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget)
31    : m_Target(pTarget),
32      m_Name("MipsLA25_Prototype"),
33      m_pData(STUB),
34      m_Size(sizeof(STUB)) {
35  addFixup(0, 0x0, llvm::ELF::R_MIPS_HI16);
36  addFixup(4, 0x0, llvm::ELF::R_MIPS_26);
37  addFixup(8, 0x0, llvm::ELF::R_MIPS_LO16);
38}
39
40MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget,
41                           const uint32_t* pData,
42                           size_t pSize,
43                           const_fixup_iterator pBegin,
44                           const_fixup_iterator pEnd)
45    : m_Target(pTarget), m_Name("pic"), m_pData(pData), m_Size(pSize) {
46  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
47    addFixup(**it);
48}
49
50bool MipsLA25Stub::isMyDuty(const Relocation& pReloc,
51                            uint64_t pSource,
52                            uint64_t pTargetSymValue) const {
53  if (llvm::ELF::R_MIPS_26 != pReloc.type())
54    return false;
55
56  const ResolveInfo* rsym = pReloc.symInfo();
57
58  if (!rsym->isDefine())
59    return false;
60
61  if (rsym->isDyn() || rsym->isUndef())
62    return false;
63
64  if (!m_Target.hasNonPICBranch(rsym))
65    return false;
66
67  return true;
68}
69
70const std::string& MipsLA25Stub::name() const {
71  return m_Name;
72}
73
74const uint8_t* MipsLA25Stub::getContent() const {
75  return reinterpret_cast<const uint8_t*>(m_pData);
76}
77
78size_t MipsLA25Stub::size() const {
79  return m_Size;
80}
81
82size_t MipsLA25Stub::alignment() const {
83  return 4;
84}
85
86Stub* MipsLA25Stub::doClone() {
87  return new MipsLA25Stub(
88      m_Target, m_pData, m_Size, fixup_begin(), fixup_end());
89}
90
91}  // namespace mcld
92