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