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 
13 namespace {
14 
15 const 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 enum {
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 
31 namespace mcld {
32 
33 //===----------------------------------------------------------------------===//
34 // MipsLA25Stub
35 //===----------------------------------------------------------------------===//
36 
MipsLA25Stub(const MipsGNULDBackend & pTarget)37 MipsLA25Stub::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 
MipsLA25Stub(const MipsGNULDBackend & pTarget,const uint32_t * pData,size_t pSize,const_fixup_iterator pBegin,const_fixup_iterator pEnd)47 MipsLA25Stub::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 
isMyDuty(const Relocation & pReloc,uint64_t pSource,uint64_t pTargetSymValue) const57 bool 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 
name() const77 const std::string& MipsLA25Stub::name() const {
78   return m_Name;
79 }
80 
getContent() const81 const uint8_t* MipsLA25Stub::getContent() const {
82   return reinterpret_cast<const uint8_t*>(m_pData);
83 }
84 
size() const85 size_t MipsLA25Stub::size() const {
86   return m_Size;
87 }
88 
alignment() const89 size_t MipsLA25Stub::alignment() const {
90   return 4;
91 }
92 
doClone()93 Stub* MipsLA25Stub::doClone() {
94   return new MipsLA25Stub(
95       m_Target, m_pData, m_Size, fixup_begin(), fixup_end());
96 }
97 
98 }  // namespace mcld
99