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