1 //===- HexagonAbsoluteStub.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
10 #include "HexagonAbsoluteStub.h"
11 #include "HexagonLDBackend.h"
12
13 #include <llvm/Support/ELF.h>
14 #include <llvm/Support/MathExtras.h>
15 #include <mcld/LD/ResolveInfo.h>
16 #include <mcld/LD/LDSymbol.h>
17 #include <mcld/Fragment/Relocation.h>
18
19 using namespace mcld;
20
21 //===----------------------------------------------------------------------===//
22 // HexagonAbsoluteStub
23 //===----------------------------------------------------------------------===//
24
25 const uint32_t HexagonAbsoluteStub::TEMPLATE[] = {
26 0xbffd7f1d, /* { sp = add (sp, #-8) */
27 0xa79dfcfe, /* memw (sp + #-8) = r28 } */
28 0x723cc000, /* r28.h = #HI (foo) */
29 0x713cc000, /* r28.l = #LO (foo) */
30 0xb01d411d, /* { sp = add (sp, #8) */
31 0x529c4000, /* jumpr r28 */
32 0x919dc01c /* r28 = memw (sp) } */
33 };
34
35 #define FITS_IN_NBITS(D, B) \
36 ( llvm::abs64(D) < (~(~(int64_t) 0 << ((B) - 1)) & -(4 * 4)))
37
HexagonAbsoluteStub(bool pIsOutputPIC)38 HexagonAbsoluteStub::HexagonAbsoluteStub(bool pIsOutputPIC)
39 : Stub(), m_Name("HexagonTrampoline"), m_pData(NULL), m_Size(0x0)
40 {
41 m_pData = TEMPLATE;
42 m_Size = sizeof(TEMPLATE);
43 addFixup(8u, 0x0, llvm::ELF::R_HEX_HI16);
44 addFixup(12u, 0x0, llvm::ELF::R_HEX_LO16);
45 }
46
47 /// for doClone
HexagonAbsoluteStub(const uint32_t * pData,size_t pSize,const_fixup_iterator pBegin,const_fixup_iterator pEnd)48 HexagonAbsoluteStub::HexagonAbsoluteStub(const uint32_t* pData,
49 size_t pSize,
50 const_fixup_iterator pBegin,
51 const_fixup_iterator pEnd)
52 : Stub(), m_Name("AbsVeneer"), m_pData(pData), m_Size(pSize)
53 {
54 for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
55 addFixup(**it);
56 }
57
~HexagonAbsoluteStub()58 HexagonAbsoluteStub::~HexagonAbsoluteStub()
59 {
60 }
61
isMyDuty(const class Relocation & pReloc,uint64_t pSource,uint64_t pTargetSymValue) const62 bool HexagonAbsoluteStub::isMyDuty(const class Relocation& pReloc,
63 uint64_t pSource,
64 uint64_t pTargetSymValue) const
65 {
66 int nbits = 0;
67 switch (pReloc.type()) {
68 case llvm::ELF::R_HEX_B22_PCREL:
69 nbits = 24;
70 break;
71 case llvm::ELF::R_HEX_B15_PCREL:
72 nbits = 17;
73 break;
74 case llvm::ELF::R_HEX_B7_PCREL:
75 nbits = 9;
76 break;
77 case llvm::ELF::R_HEX_B13_PCREL:
78 nbits = 15;
79 break;
80 case llvm::ELF::R_HEX_B9_PCREL:
81 nbits = 17;
82 break;
83 default:
84 return false;
85 }
86
87 int64_t offset = pTargetSymValue - pSource;
88 // if offset is going to fit in nbits then we dont
89 // need a stub to be created
90 if (FITS_IN_NBITS(offset, nbits))
91 return false;
92 return true;
93 }
94
name() const95 const std::string& HexagonAbsoluteStub::name() const
96 {
97 return m_Name;
98 }
99
getContent() const100 const uint8_t* HexagonAbsoluteStub::getContent() const
101 {
102 return reinterpret_cast<const uint8_t*>(m_pData);
103 }
104
size() const105 size_t HexagonAbsoluteStub::size() const
106 {
107 return m_Size;
108 }
109
alignment() const110 size_t HexagonAbsoluteStub::alignment() const
111 {
112 return 4u;
113 }
114
doClone()115 Stub* HexagonAbsoluteStub::doClone()
116 {
117 return new HexagonAbsoluteStub(m_pData, m_Size, fixup_begin(), fixup_end());
118 }
119