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}
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{
43  addFixup(0, 0x0, R_MIPS_LA25_LUI);
44  addFixup(4, 0x0, R_MIPS_LA25_J);
45  addFixup(8, 0x0, R_MIPS_LA25_ADD);
46}
47
48MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget,
49                           const uint32_t* pData,
50                           size_t pSize,
51                           const_fixup_iterator pBegin,
52                           const_fixup_iterator pEnd)
53 : m_Target(pTarget),
54   m_Name("pic"),
55   m_pData(pData),
56   m_Size(pSize)
57{
58  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
59    addFixup(**it);
60}
61
62bool MipsLA25Stub::isMyDuty(const Relocation& pReloc,
63                            uint64_t pSource,
64                            uint64_t pTargetSymValue) const
65{
66  if (llvm::ELF::R_MIPS_26 != pReloc.type())
67    return false;
68
69  const ResolveInfo* rsym = pReloc.symInfo();
70
71  if (!rsym->isDefine())
72    return false;
73
74  if (rsym->isDyn() || rsym->isUndef())
75    return false;
76
77  if (!m_Target.hasNonPICBranch(rsym))
78    return false;
79
80  return true;
81}
82
83const std::string& MipsLA25Stub::name() const
84{
85  return m_Name;
86}
87
88const uint8_t* MipsLA25Stub::getContent() const
89{
90  return reinterpret_cast<const uint8_t*>(m_pData);
91}
92
93size_t MipsLA25Stub::size() const
94{
95  return m_Size;
96}
97
98size_t MipsLA25Stub::alignment() const
99{
100  return 4;
101}
102
103Stub* MipsLA25Stub::doClone()
104{
105  return new MipsLA25Stub(m_Target, m_pData, m_Size,
106                          fixup_begin(), fixup_end());
107}
108
109} //end mcld namespace
110