MipsLA25Stub.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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
22enum {
23  // Fake relocations for patching LA25 stubs.
24  R_MIPS_LA25_LUI = 200,
25  R_MIPS_LA25_J = 201,
26  R_MIPS_LA25_ADD = 202
27};
28
29}  // anonymous namespace
30
31namespace mcld {
32
33//===----------------------------------------------------------------------===//
34// MipsLA25Stub
35//===----------------------------------------------------------------------===//
36
37MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget)
38    : m_Target(pTarget),
39      m_Name("MipsLA25_Prototype"),
40      m_pData(STUB),
41      m_Size(sizeof(STUB)) {
42  addFixup(0, 0x0, R_MIPS_LA25_LUI);
43  addFixup(4, 0x0, R_MIPS_LA25_J);
44  addFixup(8, 0x0, R_MIPS_LA25_ADD);
45}
46
47MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget,
48                           const uint32_t* pData,
49                           size_t pSize,
50                           const_fixup_iterator pBegin,
51                           const_fixup_iterator pEnd)
52    : m_Target(pTarget), m_Name("pic"), m_pData(pData), m_Size(pSize) {
53  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
54    addFixup(**it);
55}
56
57bool MipsLA25Stub::isMyDuty(const Relocation& pReloc,
58                            uint64_t pSource,
59                            uint64_t pTargetSymValue) const {
60  if (llvm::ELF::R_MIPS_26 != pReloc.type())
61    return false;
62
63  const ResolveInfo* rsym = pReloc.symInfo();
64
65  if (!rsym->isDefine())
66    return false;
67
68  if (rsym->isDyn() || rsym->isUndef())
69    return false;
70
71  if (!m_Target.hasNonPICBranch(rsym))
72    return false;
73
74  return true;
75}
76
77const std::string& MipsLA25Stub::name() const {
78  return m_Name;
79}
80
81const uint8_t* MipsLA25Stub::getContent() const {
82  return reinterpret_cast<const uint8_t*>(m_pData);
83}
84
85size_t MipsLA25Stub::size() const {
86  return m_Size;
87}
88
89size_t MipsLA25Stub::alignment() const {
90  return 4;
91}
92
93Stub* MipsLA25Stub::doClone() {
94  return new MipsLA25Stub(
95      m_Target, m_pData, m_Size, fixup_begin(), fixup_end());
96}
97
98}  // namespace mcld
99