1//===- SPARCV9.cpp --------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "RelocScan.h"
10#include "Symbols.h"
11#include "SyntheticSections.h"
12#include "Target.h"
13#include "llvm/Support/Endian.h"
14
15using namespace llvm;
16using namespace llvm::object;
17using namespace llvm::support::endian;
18using namespace llvm::ELF;
19using namespace lld;
20using namespace lld::elf;
21
22namespace {
23class SPARCV9 final : public TargetInfo {
24public:
25 SPARCV9(Ctx &);
26 RelExpr getRelExpr(RelType type, const Symbol &s,
27 const uint8_t *loc) const override;
28 RelType getDynRel(RelType type) const override;
29 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
30 void writeGotHeader(uint8_t *buf) const override;
31 void writePlt(uint8_t *buf, const Symbol &sym,
32 uint64_t pltEntryAddr) const override;
33 template <class ELFT, class RelTy>
34 void scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
35 unsigned shard);
36 void scanSection(InputSectionBase &sec, unsigned shard) override {
37 elf::scanSection1<SPARCV9, ELF64BE>(target&: *this, sec, shard);
38 }
39 void relocate(uint8_t *loc, const Relocation &rel,
40 uint64_t val) const override;
41};
42} // namespace
43
44SPARCV9::SPARCV9(Ctx &ctx) : TargetInfo(ctx) {
45 copyRel = R_SPARC_COPY;
46 gotRel = R_SPARC_GLOB_DAT;
47 pltRel = R_SPARC_JMP_SLOT;
48 relativeRel = R_SPARC_RELATIVE;
49 symbolicRel = R_SPARC_64;
50 tlsGotRel = R_SPARC_TLS_TPOFF64;
51 gotHeaderEntriesNum = 1;
52 pltEntrySize = 32;
53 pltHeaderSize = 4 * pltEntrySize;
54 usesGotPlt = false;
55
56 defaultCommonPageSize = 8192;
57 defaultMaxPageSize = 0x100000;
58 defaultImageBase = 0x100000;
59}
60
61// Only needed to support relocations used by relocateNonAlloc and
62// preprocessRelocs.
63RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
64 const uint8_t *loc) const {
65 switch (type) {
66 case R_SPARC_8:
67 case R_SPARC_16:
68 case R_SPARC_UA16:
69 case R_SPARC_32:
70 case R_SPARC_UA32:
71 case R_SPARC_64:
72 case R_SPARC_UA64:
73 return R_ABS;
74 case R_SPARC_DISP32:
75 return R_PC;
76 case R_SPARC_NONE:
77 return R_NONE;
78 default:
79 Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
80 << ") against symbol " << &s;
81 return R_NONE;
82 }
83}
84
85RelType SPARCV9::getDynRel(RelType type) const {
86 if (type == R_SPARC_64)
87 return type;
88 return R_SPARC_NONE;
89}
90
91int64_t SPARCV9::getImplicitAddend(const uint8_t *buf, RelType type) const {
92 switch (type) {
93 case R_SPARC_64:
94 case R_SPARC_GLOB_DAT:
95 return read64be(P: buf);
96 default:
97 InternalErr(ctx, buf) << "cannot read addend for relocation " << type;
98 return 0;
99 }
100}
101
102template <class ELFT, class RelTy>
103void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
104 unsigned shard) {
105 RelocScan rs(ctx, &sec, shard);
106 sec.relocations.reserve(N: rels.size());
107 for (auto it = rels.begin(); it != rels.end(); ++it) {
108 const RelTy &rel = *it;
109 uint32_t symIdx = rel.getSymbol(false);
110 Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);
111 uint64_t offset = rel.r_offset;
112 RelType type = rel.getType(false);
113 if (sym.isUndefined() && symIdx != 0 &&
114 rs.maybeReportUndefined(sym&: cast<Undefined>(Val&: sym), offset))
115 continue;
116 int64_t addend = rs.getAddend<ELFT>(rel, type);
117 RelExpr expr;
118 switch (type) {
119 case R_SPARC_NONE:
120 case R_SPARC_TLS_IE_ADD:
121 continue;
122
123 // Absolute relocations:
124 case R_SPARC_8:
125 case R_SPARC_16:
126 case R_SPARC_UA16:
127 case R_SPARC_32:
128 case R_SPARC_UA32:
129 case R_SPARC_64:
130 case R_SPARC_UA64:
131 case R_SPARC_H44:
132 case R_SPARC_M44:
133 case R_SPARC_L44:
134 case R_SPARC_HH22:
135 case R_SPARC_HM10:
136 case R_SPARC_LM22:
137 case R_SPARC_HI22:
138 case R_SPARC_13:
139 case R_SPARC_LO10:
140 case R_SPARC_HIX22:
141 case R_SPARC_LOX10:
142 expr = R_ABS;
143 break;
144
145 // PLT-generating relocations:
146 case R_SPARC_WPLT30:
147 rs.processR_PLT_PC(type, offset, addend, sym);
148 continue;
149
150 // PC-relative relocations:
151 case R_SPARC_DISP8:
152 case R_SPARC_DISP16:
153 case R_SPARC_DISP32:
154 case R_SPARC_DISP64:
155 case R_SPARC_PC10:
156 case R_SPARC_PC22:
157 case R_SPARC_WDISP16:
158 case R_SPARC_WDISP19:
159 case R_SPARC_WDISP22:
160 case R_SPARC_WDISP30:
161 rs.processR_PC(type, offset, addend, sym);
162 continue;
163
164 // GOT relocations:
165 case R_SPARC_GOT10:
166 case R_SPARC_GOT13:
167 case R_SPARC_GOT22:
168 expr = R_GOT_OFF;
169 break;
170
171 // Optimize the GOT load to an add of the symbol's GOT-relative address if
172 // applicable. Exclude absolute symbol, which can be arbitrarily far. %l7
173 // points at .got, which must be retained.
174 case R_SPARC_GOTDATA_OP_HIX22:
175 case R_SPARC_GOTDATA_OP_LOX10:
176 case R_SPARC_GOTDATA_OP:
177 if (sym.isPreemptible || isAbsolute(sym)) {
178 expr = R_GOT_OFF;
179 } else {
180 ctx.in.got->hasGotOffRel.store(i: true, m: std::memory_order_relaxed);
181 expr = R_GOTREL;
182 }
183 break;
184
185 // TLS LE relocations:
186 case R_SPARC_TLS_LE_HIX22:
187 case R_SPARC_TLS_LE_LOX10:
188 if (rs.checkTlsLe(offset, sym, type))
189 continue;
190 expr = R_TPREL;
191 break;
192
193 // TLS IE relocations. In an executable, a non-preemptible symbol is
194 // optimized to Local Exec: the add becomes an xor and the load becomes a
195 // register move.
196 case R_SPARC_TLS_IE_HI22:
197 case R_SPARC_TLS_IE_LO10:
198 rs.handleTlsIe(ieExpr: R_GOT_OFF, type, offset, addend, sym);
199 continue;
200 case R_SPARC_TLS_IE_LD:
201 case R_SPARC_TLS_IE_LDX:
202 if (!ctx.arg.shared && !sym.isPreemptible)
203 sec.addReloc(r: {.expr: R_TPREL, .type: type, .offset: offset, .addend: addend, .sym: &sym});
204 continue;
205
206 default:
207 Err(ctx) << getErrorLoc(ctx, loc: sec.content().data() + offset)
208 << "unknown relocation (" << type.v << ") against symbol "
209 << &sym;
210 continue;
211 }
212 rs.process(expr, type, offset, sym, addend);
213 }
214}
215
216void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
217 uint64_t val) const {
218 switch (rel.type) {
219 case R_SPARC_8:
220 // V-byte8
221 checkIntUInt(ctx, loc, v: val, n: 8, rel);
222 *loc = val;
223 break;
224 case R_SPARC_16:
225 case R_SPARC_UA16:
226 // V-half16
227 checkIntUInt(ctx, loc, v: val, n: 16, rel);
228 write16be(P: loc, V: val);
229 break;
230 case R_SPARC_32:
231 case R_SPARC_UA32:
232 // V-word32
233 checkUInt(ctx, loc, v: val, n: 32, rel);
234 write32be(P: loc, V: val);
235 break;
236 case R_SPARC_DISP8:
237 // V-byte8
238 checkInt(ctx, loc, v: val, n: 8, rel);
239 *loc = val;
240 break;
241 case R_SPARC_DISP16:
242 // V-half16
243 checkInt(ctx, loc, v: val, n: 16, rel);
244 write16be(P: loc, V: val);
245 break;
246 case R_SPARC_DISP32:
247 // V-disp32
248 checkInt(ctx, loc, v: val, n: 32, rel);
249 write32be(P: loc, V: val);
250 break;
251 case R_SPARC_WDISP30:
252 case R_SPARC_WPLT30:
253 // V-disp30
254 checkInt(ctx, loc, v: val, n: 32, rel);
255 write32be(P: loc, V: (read32be(P: loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
256 break;
257 case R_SPARC_22:
258 // V-imm22
259 checkUInt(ctx, loc, v: val, n: 22, rel);
260 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | (val & 0x003fffff));
261 break;
262 case R_SPARC_13:
263 // V-simm13
264 checkIntUInt(ctx, loc, v: val, n: 13, rel);
265 write32be(P: loc, V: (read32be(P: loc) & ~0x00001fff) | (val & 0x00001fff));
266 break;
267 case R_SPARC_GOT13:
268 // V-simm13
269 checkInt(ctx, loc, v: val, n: 13, rel);
270 write32be(P: loc, V: (read32be(P: loc) & ~0x00001fff) | (val & 0x00001fff));
271 break;
272 case R_SPARC_GOT22:
273 case R_SPARC_LM22:
274 // T-imm22
275 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
276 break;
277 case R_SPARC_PC22:
278 // V-disp22
279 checkIntUInt(ctx, loc, v: val, n: 32, rel);
280 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
281 break;
282 case R_SPARC_HI22:
283 // V-imm22
284 checkUInt(ctx, loc, v: val, n: 32, rel);
285 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
286 break;
287 case R_SPARC_WDISP22:
288 // V-disp22
289 checkInt(ctx, loc, v: val, n: 24, rel);
290 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((val >> 2) & 0x003fffff));
291 break;
292 case R_SPARC_WDISP19:
293 // V-disp19
294 checkInt(ctx, loc, v: val, n: 21, rel);
295 write32be(P: loc, V: (read32be(P: loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
296 break;
297 case R_SPARC_WDISP16:
298 // V-d2/disp14
299 checkInt(ctx, loc, v: val, n: 18, rel);
300 write32be(P: loc, V: (read32be(P: loc) & ~0x00303fff) |
301 (((val >> 2) & 0x0000c000) << 6) |
302 ((val >> 2) & 0x00003fff));
303 break;
304 case R_SPARC_GOT10:
305 case R_SPARC_PC10:
306 // T-simm10
307 write32be(P: loc, V: (read32be(P: loc) & ~0x000003ff) | (val & 0x000003ff));
308 break;
309 case R_SPARC_LO10:
310 // T-simm13
311 write32be(P: loc, V: (read32be(P: loc) & ~0x000003ff) | (val & 0x000003ff));
312 break;
313 case R_SPARC_64:
314 case R_SPARC_DISP64:
315 case R_SPARC_UA64:
316 // V-xword64
317 write64be(P: loc, V: val);
318 break;
319 case R_SPARC_HH22:
320 // V-imm22
321 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff));
322 break;
323 case R_SPARC_HM10:
324 // T-simm13
325 write32be(P: loc, V: (read32be(P: loc) & ~0x000003ff) | ((val >> 32) & 0x000003ff));
326 break;
327 case R_SPARC_H44:
328 // V-imm22
329 checkUInt(ctx, loc, v: val, n: 44, rel);
330 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));
331 break;
332 case R_SPARC_M44:
333 // T-imm10
334 write32be(P: loc, V: (read32be(P: loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));
335 break;
336 case R_SPARC_L44:
337 // T-imm13
338 write32be(P: loc, V: (read32be(P: loc) & ~0x00000fff) | (val & 0x00000fff));
339 break;
340 case R_SPARC_HIX22:
341 // V-imm22
342 checkUInt(ctx, loc, v: ~val, n: 32, rel);
343 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
344 break;
345 case R_SPARC_TLS_LE_HIX22:
346 // T-imm22
347 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
348 break;
349 case R_SPARC_LOX10:
350 case R_SPARC_TLS_LE_LOX10:
351 // T-simm13
352 write32be(P: loc, V: (read32be(P: loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);
353 break;
354 case R_SPARC_GOTDATA_OP_HIX22: {
355 // V-imm22. sethi encodes the complement of a negative value, which the
356 // paired xor undoes, so the encodable range is 33 bits.
357 checkInt(ctx, loc, v: val, n: 33, rel);
358 uint64_t v = int64_t(val) < 0 ? ~val : val;
359 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((v >> 10) & 0x003fffff));
360 break;
361 }
362 case R_SPARC_GOTDATA_OP_LOX10:
363 // T-simm13. Only a negative value needs the sign extension bits.
364 write32be(P: loc, V: (read32be(P: loc) & ~0x00001fff) | (val & 0x000003ff) |
365 (int64_t(val) < 0 ? 0x1c00 : 0));
366 break;
367 case R_SPARC_GOTDATA_OP:
368 // ldx [%rs1 + %rs2], %rd -> add %rs1, %rs2, %rd
369 if (rel.expr == R_GOTREL)
370 write32be(P: loc, V: (read32be(P: loc) & 0x3e07c01f) | 0x80000000);
371 break;
372 case R_SPARC_TLS_IE_HI22: {
373 // T-imm22. Local Exec encodes the complement, as R_SPARC_TLS_LE_HIX22 does.
374 uint64_t v = rel.expr == R_TPREL ? ~val : val;
375 write32be(P: loc, V: (read32be(P: loc) & ~0x003fffff) | ((v >> 10) & 0x003fffff));
376 break;
377 }
378 case R_SPARC_TLS_IE_LO10:
379 if (rel.expr == R_TPREL)
380 // add %rs1, imm, %rd -> xor %rs1, imm, %rd, T-simm13.
381 write32be(P: loc, V: (read32be(P: loc) & ~0x00001fff) | 0x80182000 |
382 (val & 0x000003ff) | 0x1c00);
383 else
384 // T-simm10
385 write32be(P: loc, V: (read32be(P: loc) & ~0x000003ff) | (val & 0x000003ff));
386 break;
387 case R_SPARC_TLS_IE_LD:
388 case R_SPARC_TLS_IE_LDX: {
389 // ld/ldx [%rs1 + %rs2], %rd -> mov %rs2, %rd, or nop if the move is
390 // redundant. Only reached when the sequence is optimized to Local Exec.
391 uint32_t insn = read32be(P: loc);
392 write32be(P: loc, V: ((insn >> 25) & 0x1f) == (insn & 0x1f)
393 ? 0x01000000
394 : 0x80100000 | (insn & 0x3e00001f));
395 break;
396 }
397 default:
398 llvm_unreachable("unknown relocation");
399 }
400}
401
402void SPARCV9::writeGotHeader(uint8_t *buf) const {
403 // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
404 write64be(P: buf, V: ctx.in.dynamic->getVA());
405}
406
407void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,
408 uint64_t pltEntryAddr) const {
409 const uint8_t pltData[] = {
410 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1
411 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1
412 0x01, 0x00, 0x00, 0x00, // nop
413 0x01, 0x00, 0x00, 0x00, // nop
414 0x01, 0x00, 0x00, 0x00, // nop
415 0x01, 0x00, 0x00, 0x00, // nop
416 0x01, 0x00, 0x00, 0x00, // nop
417 0x01, 0x00, 0x00, 0x00 // nop
418 };
419 memcpy(dest: buf, src: pltData, n: sizeof(pltData));
420
421 uint64_t off = pltEntryAddr - ctx.in.plt->getVA();
422 relocateNoSym(loc: buf, type: R_SPARC_22, val: off);
423 relocateNoSym(loc: buf + 4, type: R_SPARC_WDISP19, val: -(off + 4 - pltEntrySize));
424}
425
426void elf::setSPARCV9TargetInfo(Ctx &ctx) { ctx.target.reset(p: new SPARCV9(ctx)); }
427