• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- HexagonRelocator.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 <llvm/ADT/Twine.h>
11 #include <llvm/Support/DataTypes.h>
12 #include <llvm/Support/ELF.h>
13 #include <mcld/Support/MsgHandling.h>
14 
15 #include "HexagonRelocator.h"
16 #include "HexagonRelocationFunctions.h"
17 
18 using namespace mcld;
19 
20 //===--------------------------------------------------------------------===//
21 // Relocation Functions and Tables
22 //===--------------------------------------------------------------------===//
23 DECL_HEXAGON_APPLY_RELOC_FUNCS
24 
25 /// the prototype of applying function
26 typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
27                                                HexagonRelocator& pParent);
28 
29 // the table entry of applying functions
30 struct ApplyFunctionTriple
31 {
32   ApplyFunctionType func;
33   unsigned int type;
34   const char* name;
35 };
36 
37 // declare the table of applying functions
38 static const ApplyFunctionTriple ApplyFunctions[] = {
39   DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS
40 };
41 
42 //===--------------------------------------------------------------------===//
43 // HexagonRelocator
44 //===--------------------------------------------------------------------===//
HexagonRelocator(HexagonLDBackend & pParent)45 HexagonRelocator::HexagonRelocator(HexagonLDBackend& pParent)
46   : Relocator(),
47     m_Target(pParent) {
48 }
49 
~HexagonRelocator()50 HexagonRelocator::~HexagonRelocator()
51 {
52 }
53 
54 Relocator::Result
applyRelocation(Relocation & pRelocation)55 HexagonRelocator::applyRelocation(Relocation& pRelocation)
56 {
57   Relocation::Type type = pRelocation.type();
58 
59   if (type > 85) { // 86-255 relocs do not exists for Hexagon
60     return Relocator::Unknown;
61   }
62 
63   // apply the relocation
64   return ApplyFunctions[type].func(pRelocation, *this);
65 }
66 
getName(Relocation::Type pType) const67 const char* HexagonRelocator::getName(Relocation::Type pType) const
68 {
69   return ApplyFunctions[pType].name;
70 }
71 
getSize(Relocation::Type pType) const72 Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const
73 {
74   return 32;
75 }
76 //===--------------------------------------------------------------------===//
77 // Relocation helper function
78 //===--------------------------------------------------------------------===//
79 template<typename T1, typename T2>
ApplyMask(T2 pMask,T1 pData)80 T1 ApplyMask(T2 pMask, T1 pData) {
81   T1 result = 0;
82   size_t off = 0;
83 
84   for (size_t bit = 0; bit != sizeof (T1) * 8; ++bit) {
85     const bool valBit = (pData >> off) & 1;
86     const bool maskBit = (pMask >> bit) & 1;
87     if (maskBit) {
88       result |= static_cast<T1>(valBit) << bit;
89       ++off;
90     }
91   }
92   return result;
93 }
94 
95 //=========================================//
96 // Each relocation function implementation //
97 //=========================================//
98 
99 // R_HEX_NONE
none(Relocation & pReloc,HexagonRelocator & pParent)100 HexagonRelocator::Result none(Relocation& pReloc, HexagonRelocator& pParent)
101 {
102   return HexagonRelocator::OK;
103 }
104 
105 // R_HEX_B22_PCREL: Word32_B22 : 0x01ff3ffe  (S + A - P) >> 2 : Signed Verify
relocB22PCREL(Relocation & pReloc,HexagonRelocator & pParent)106 HexagonRelocator::Result relocB22PCREL(Relocation& pReloc,
107                                        HexagonRelocator& pParent)
108 {
109   HexagonRelocator::Address S = pReloc.symValue();
110   HexagonRelocator::DWord   A = pReloc.addend();
111   HexagonRelocator::DWord   P = pReloc.place();
112 
113   int32_t result = (int32_t) ((S + A - P) >> 2);
114   int32_t range = 1 << 21;
115 
116   if ( (result < range) && (result > -range)) {
117     pReloc.target() = pReloc.target() | ApplyMask(0x01ff3ffe, result);
118     return HexagonRelocator::OK;
119   }
120   return HexagonRelocator::Overflow;
121 }
122 
123 // R_HEX_B15_PCREL: Word32_B15 : 0x00df20fe  (S + A - P) >> 2 : Signed Verify
relocB15PCREL(Relocation & pReloc,HexagonRelocator & pParent)124 HexagonRelocator::Result relocB15PCREL(Relocation& pReloc,
125                                        HexagonRelocator& pParent)
126 {
127   HexagonRelocator::Address S = pReloc.symValue();
128   HexagonRelocator::DWord   A = pReloc.addend();
129   HexagonRelocator::DWord   P = pReloc.place();
130 
131   int32_t result = (int32_t) ((S + A - P) >> 2);
132   int32_t range = 1 << 14;
133   if ( (result < range) && (result > -range)) {
134     pReloc.target() = pReloc.target() | ApplyMask(0x00df20fe,result);
135     return HexagonRelocator::OK;
136   }
137   return HexagonRelocator::Overflow;
138 }
139 
140 // R_HEX_B7_PCREL: Word32_B7 : 0x0001f18  (S + A - P) >> 2 : Signed Verify
relocB7PCREL(Relocation & pReloc,HexagonRelocator & pParent)141 HexagonRelocator::Result relocB7PCREL(Relocation& pReloc,
142                                       HexagonRelocator& pParent)
143 {
144   HexagonRelocator::Address S = pReloc.symValue();
145   HexagonRelocator::DWord   A = pReloc.addend();
146   HexagonRelocator::DWord   P = pReloc.place();
147 
148   int32_t result = (int32_t) ((S + A - P) >> 2);
149   int32_t range = 1 << 6;
150   if ( (result < range) && (result > -range)) {
151     pReloc.target() = pReloc.target() | ApplyMask(0x00001f18, result);
152     return HexagonRelocator::OK;
153   }
154   return HexagonRelocator::Overflow;
155 }
156 
157 // R_HEX_LO16: Word32_LO : 0x00c03fff  (S + A) : Unsigned Truncate
relocLO16(Relocation & pReloc,HexagonRelocator & pParent)158 HexagonRelocator::Result relocLO16(Relocation& pReloc,
159                                    HexagonRelocator& pParent)
160 {
161   HexagonRelocator::Address S = pReloc.symValue();
162   HexagonRelocator::DWord   A = pReloc.addend();
163 
164   uint32_t result = (uint32_t) (S + A);
165   pReloc.target() = pReloc.target() | ApplyMask(0x00c03fff, result);
166   return HexagonRelocator::OK;
167 }
168 
169 // R_HEX_HI16: Word32_LO : 0x00c03fff  (S + A) >> 16 : Unsigned Truncate
relocHI16(Relocation & pReloc,HexagonRelocator & pParent)170 HexagonRelocator::Result relocHI16(Relocation& pReloc,
171                                    HexagonRelocator& pParent)
172 {
173   HexagonRelocator::Address S = pReloc.symValue();
174   HexagonRelocator::DWord   A = pReloc.addend();
175 
176   uint32_t result = (uint32_t) ((S + A) >> 16);
177   pReloc.target() = pReloc.target() | ApplyMask(0x00c03fff, result);
178   return HexagonRelocator::OK;
179 }
180 
181 // R_HEX_32: Word32 : 0xffffffff : (S + A) : Unsigned Truncate
reloc32(Relocation & pReloc,HexagonRelocator & pParent)182 HexagonRelocator::Result reloc32(Relocation& pReloc, HexagonRelocator& pParent)
183 {
184   HexagonRelocator::DWord A = pReloc.addend();
185   HexagonRelocator::DWord S = pReloc.symValue();
186 
187   uint32_t result = (uint32_t) (S + A);
188 
189   pReloc.target() = result | pReloc.target();
190   return HexagonRelocator::OK;
191 }
192 
193 // R_HEX_16: Word32 : 0xffff : (S + A) : Unsigned Truncate
reloc16(Relocation & pReloc,HexagonRelocator & pParent)194 HexagonRelocator::Result reloc16(Relocation& pReloc, HexagonRelocator& pParent)
195 {
196   HexagonRelocator::DWord A = pReloc.addend();
197   HexagonRelocator::DWord S = pReloc.symValue();
198 
199   uint32_t result = (uint32_t) (S + A);
200   pReloc.target() = pReloc.target() | ApplyMask(0x0000ffff, result);
201 
202   return HexagonRelocator::OK;
203 }
204 
205 // R_HEX_8: Word32 : 0xff : (S + A) : Unsigned Truncate
reloc8(Relocation & pReloc,HexagonRelocator & pParent)206 HexagonRelocator::Result reloc8(Relocation& pReloc, HexagonRelocator& pParent)
207 {
208   HexagonRelocator::DWord A = pReloc.addend();
209   HexagonRelocator::DWord S = pReloc.symValue();
210 
211   uint32_t result = (uint32_t) (S + A);
212   pReloc.target() = pReloc.target() | ApplyMask(0x000000ff, result);
213 
214   return HexagonRelocator::OK;
215 }
216 
217 // R_HEX_B13_PCREL : Word32_B13 : 0x00202ffe  (S + A - P)>>2 : Signed Verify
relocB13PCREL(Relocation & pReloc,HexagonRelocator & pParent)218 HexagonRelocator::Result relocB13PCREL(Relocation& pReloc,
219                                        HexagonRelocator& pParent)
220 {
221   HexagonRelocator::Address S = pReloc.symValue();
222   HexagonRelocator::DWord   A = pReloc.addend();
223   HexagonRelocator::DWord   P = pReloc.place();
224 
225   int32_t result = ((S + A - P) >> 2);
226   int32_t range = 1L << 12;
227   if (result < range && result > -range) {
228     pReloc.target() = pReloc.target() | ApplyMask(0x00202ffe, result);
229     return HexagonRelocator::OK;
230   }
231   return HexagonRelocator::Overflow;
232 }
233 
unsupport(Relocation & pReloc,HexagonRelocator & pParent)234 HexagonRelocator::Result unsupport(Relocation& pReloc,
235                                    HexagonRelocator& pParent)
236 {
237   return HexagonRelocator::Unsupport;
238 }
239 
240 
241 
242 // R_HEX_32_PCREL : Word32 : 0xffffffff  (S + A - P) : Signed Verify
reloc32PCREL(Relocation & pReloc,HexagonRelocator & pParent)243 HexagonRelocator::Result reloc32PCREL(Relocation& pReloc,
244                                       HexagonRelocator& pParent)
245 {
246   HexagonRelocator::Address S = pReloc.symValue();
247   HexagonRelocator::DWord   A = pReloc.addend();
248   HexagonRelocator::DWord   P = pReloc.place();
249 
250   int64_t result = S + A - P;
251   int32_t range = 1 << 31;
252 
253   if (result < range && result > -range)  {
254     pReloc.target() = pReloc.target() | ApplyMask(0xffffffff, result);
255     return HexagonRelocator::OK;
256   }
257 
258   return HexagonRelocator::Overflow;
259 }
260