1//===- SystemZ.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 "OutputSections.h"
10#include "Symbols.h"
11#include "SyntheticSections.h"
12#include "Target.h"
13#include "llvm/BinaryFormat/ELF.h"
14#include "llvm/Support/Endian.h"
15
16using namespace llvm;
17using namespace llvm::support::endian;
18using namespace llvm::ELF;
19using namespace lld;
20using namespace lld::elf;
21
22namespace {
23class SystemZ : public TargetInfo {
24public:
25 SystemZ(Ctx &);
26 int getTlsGdRelaxSkip(RelType type) const override;
27 RelExpr getRelExpr(RelType type, const Symbol &s,
28 const uint8_t *loc) const override;
29 RelType getDynRel(RelType type) const override;
30 void writeGotHeader(uint8_t *buf) const override;
31 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
32 void writeIgotPlt(uint8_t *buf, const Symbol &s) const override;
33 void writePltHeader(uint8_t *buf) const override;
34 void addPltHeaderSymbols(InputSection &isd) const override;
35 void writePlt(uint8_t *buf, const Symbol &sym,
36 uint64_t pltEntryAddr) const override;
37 RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
38 RelExpr adjustGotPcExpr(RelType type, int64_t addend,
39 const uint8_t *loc) const override;
40 bool relaxOnce(int pass) const override;
41 void relocate(uint8_t *loc, const Relocation &rel,
42 uint64_t val) const override;
43 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
44
45private:
46 void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const;
47 void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
48 void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
49 void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
50};
51} // namespace
52
53SystemZ::SystemZ(Ctx &ctx) : TargetInfo(ctx) {
54 copyRel = R_390_COPY;
55 gotRel = R_390_GLOB_DAT;
56 pltRel = R_390_JMP_SLOT;
57 relativeRel = R_390_RELATIVE;
58 iRelativeRel = R_390_IRELATIVE;
59 symbolicRel = R_390_64;
60 tlsGotRel = R_390_TLS_TPOFF;
61 tlsModuleIndexRel = R_390_TLS_DTPMOD;
62 tlsOffsetRel = R_390_TLS_DTPOFF;
63 gotHeaderEntriesNum = 3;
64 gotPltHeaderEntriesNum = 0;
65 gotEntrySize = 8;
66 pltHeaderSize = 32;
67 pltEntrySize = 32;
68 ipltEntrySize = 32;
69
70 // This "trap instruction" is used to fill gaps between sections.
71 // On SystemZ, the behavior of the GNU ld is to fill those gaps
72 // with nop instructions instead - and unfortunately the default
73 // glibc crt object files (used to) rely on that behavior since
74 // they use an alignment on the .init section fragments that causes
75 // gaps which must be filled with nops as they are being executed.
76 // Therefore, we provide a nop instruction as "trapInstr" here.
77 trapInstr = {0x07, 0x07, 0x07, 0x07};
78
79 defaultImageBase = 0x1000000;
80}
81
82RelExpr SystemZ::getRelExpr(RelType type, const Symbol &s,
83 const uint8_t *loc) const {
84 switch (type) {
85 case R_390_NONE:
86 return R_NONE;
87 // Relocations targeting the symbol value.
88 case R_390_8:
89 case R_390_12:
90 case R_390_16:
91 case R_390_20:
92 case R_390_32:
93 case R_390_64:
94 return R_ABS;
95 case R_390_PC16:
96 case R_390_PC32:
97 case R_390_PC64:
98 case R_390_PC12DBL:
99 case R_390_PC16DBL:
100 case R_390_PC24DBL:
101 case R_390_PC32DBL:
102 return R_PC;
103 case R_390_GOTOFF16:
104 case R_390_GOTOFF: // a.k.a. R_390_GOTOFF32
105 case R_390_GOTOFF64:
106 return R_GOTREL;
107 // Relocations targeting the PLT associated with the symbol.
108 case R_390_PLT32:
109 case R_390_PLT64:
110 case R_390_PLT12DBL:
111 case R_390_PLT16DBL:
112 case R_390_PLT24DBL:
113 case R_390_PLT32DBL:
114 return R_PLT_PC;
115 case R_390_PLTOFF16:
116 case R_390_PLTOFF32:
117 case R_390_PLTOFF64:
118 return R_PLT_GOTREL;
119 // Relocations targeting the GOT entry associated with the symbol.
120 case R_390_GOTENT:
121 return R_GOT_PC;
122 case R_390_GOT12:
123 case R_390_GOT16:
124 case R_390_GOT20:
125 case R_390_GOT32:
126 case R_390_GOT64:
127 return R_GOT_OFF;
128 // Relocations targeting the GOTPLT entry associated with the symbol.
129 case R_390_GOTPLTENT:
130 return R_GOTPLT_PC;
131 case R_390_GOTPLT12:
132 case R_390_GOTPLT16:
133 case R_390_GOTPLT20:
134 case R_390_GOTPLT32:
135 case R_390_GOTPLT64:
136 return R_GOTPLT_GOTREL;
137 // Relocations targeting _GLOBAL_OFFSET_TABLE_.
138 case R_390_GOTPC:
139 case R_390_GOTPCDBL:
140 return R_GOTONLY_PC;
141 // TLS-related relocations.
142 case R_390_TLS_LOAD:
143 return R_NONE;
144 case R_390_TLS_GDCALL:
145 return R_TLSGD_PC;
146 case R_390_TLS_LDCALL:
147 return R_TLSLD_PC;
148 case R_390_TLS_GD32:
149 case R_390_TLS_GD64:
150 return R_TLSGD_GOT;
151 case R_390_TLS_LDM32:
152 case R_390_TLS_LDM64:
153 return R_TLSLD_GOT;
154 case R_390_TLS_LDO32:
155 case R_390_TLS_LDO64:
156 return R_DTPREL;
157 case R_390_TLS_LE32:
158 case R_390_TLS_LE64:
159 return R_TPREL;
160 case R_390_TLS_IE32:
161 case R_390_TLS_IE64:
162 return R_GOT;
163 case R_390_TLS_GOTIE12:
164 case R_390_TLS_GOTIE20:
165 case R_390_TLS_GOTIE32:
166 case R_390_TLS_GOTIE64:
167 return R_GOT_OFF;
168 case R_390_TLS_IEENT:
169 return R_GOT_PC;
170
171 default:
172 Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
173 << ") against symbol " << &s;
174 return R_NONE;
175 }
176}
177
178void SystemZ::writeGotHeader(uint8_t *buf) const {
179 // _GLOBAL_OFFSET_TABLE_[0] holds the value of _DYNAMIC.
180 // _GLOBAL_OFFSET_TABLE_[1] and [2] are reserved.
181 write64be(P: buf, V: ctx.mainPart->dynamic->getVA());
182}
183
184void SystemZ::writeGotPlt(uint8_t *buf, const Symbol &s) const {
185 write64be(P: buf, V: s.getPltVA(ctx) + 14);
186}
187
188void SystemZ::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
189 if (ctx.arg.writeAddends)
190 write64be(P: buf, V: s.getVA(ctx));
191}
192
193void SystemZ::writePltHeader(uint8_t *buf) const {
194 const uint8_t pltData[] = {
195 0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, // stg %r1,56(%r15)
196 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1,_GLOBAL_OFFSET_TABLE_
197 0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, // mvc 48(8,%r15),8(%r1)
198 0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, // lg %r1,16(%r1)
199 0x07, 0xf1, // br %r1
200 0x07, 0x00, // nopr
201 0x07, 0x00, // nopr
202 0x07, 0x00, // nopr
203 };
204 memcpy(dest: buf, src: pltData, n: sizeof(pltData));
205 uint64_t got = ctx.in.got->getVA();
206 uint64_t plt = ctx.in.plt->getVA();
207 write32be(P: buf + 8, V: (got - plt - 6) >> 1);
208}
209
210void SystemZ::addPltHeaderSymbols(InputSection &isec) const {
211 // The PLT header needs a reference to _GLOBAL_OFFSET_TABLE_, so we
212 // must ensure the .got section is created even if otherwise unused.
213 ctx.in.got->hasGotOffRel.store(i: true, m: std::memory_order_relaxed);
214}
215
216void SystemZ::writePlt(uint8_t *buf, const Symbol &sym,
217 uint64_t pltEntryAddr) const {
218 const uint8_t inst[] = {
219 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1,<.got.plt slot>
220 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, // lg %r1,0(%r1)
221 0x07, 0xf1, // br %r1
222 0x0d, 0x10, // basr %r1,%r0
223 0xe3, 0x10, 0x10, 0x0c, 0x00, 0x14, // lgf %r1,12(%r1)
224 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, // jg <plt header>
225 0x00, 0x00, 0x00, 0x00, // <relocation offset>
226 };
227 memcpy(dest: buf, src: inst, n: sizeof(inst));
228
229 write32be(P: buf + 2, V: (sym.getGotPltVA(ctx) - pltEntryAddr) >> 1);
230 write32be(P: buf + 24, V: (ctx.in.plt->getVA() - pltEntryAddr - 22) >> 1);
231 write32be(P: buf + 28, V: ctx.in.relaPlt->entsize * sym.getPltIdx(ctx));
232}
233
234int64_t SystemZ::getImplicitAddend(const uint8_t *buf, RelType type) const {
235 switch (type) {
236 case R_390_8:
237 return SignExtend64<8>(x: *buf);
238 case R_390_16:
239 case R_390_PC16:
240 return SignExtend64<16>(x: read16be(P: buf));
241 case R_390_PC16DBL:
242 return SignExtend64<16>(x: read16be(P: buf)) << 1;
243 case R_390_32:
244 case R_390_PC32:
245 return SignExtend64<32>(x: read32be(P: buf));
246 case R_390_PC32DBL:
247 return SignExtend64<32>(x: read32be(P: buf)) << 1;
248 case R_390_64:
249 case R_390_PC64:
250 case R_390_TLS_DTPMOD:
251 case R_390_TLS_DTPOFF:
252 case R_390_TLS_TPOFF:
253 case R_390_GLOB_DAT:
254 case R_390_RELATIVE:
255 case R_390_IRELATIVE:
256 return read64be(P: buf);
257 case R_390_COPY:
258 case R_390_JMP_SLOT:
259 case R_390_NONE:
260 // These relocations are defined as not having an implicit addend.
261 return 0;
262 default:
263 InternalErr(ctx, buf) << "cannot read addend for relocation " << type;
264 return 0;
265 }
266}
267
268RelType SystemZ::getDynRel(RelType type) const {
269 if (type == R_390_64 || type == R_390_PC64)
270 return type;
271 return R_390_NONE;
272}
273
274RelExpr SystemZ::adjustTlsExpr(RelType type, RelExpr expr) const {
275 if (expr == R_RELAX_TLS_GD_TO_IE)
276 return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
277 return expr;
278}
279
280int SystemZ::getTlsGdRelaxSkip(RelType type) const {
281 // A __tls_get_offset call instruction is marked with 2 relocations:
282 //
283 // R_390_TLS_GDCALL / R_390_TLS_LDCALL: marker relocation
284 // R_390_PLT32DBL: __tls_get_offset
285 //
286 // After the relaxation we no longer call __tls_get_offset and should skip
287 // both relocations to not create a false dependence on __tls_get_offset
288 // being defined.
289 //
290 // Note that this mechanism only works correctly if the R_390_TLS_[GL]DCALL
291 // is seen immediately *before* the R_390_PLT32DBL. Unfortunately, current
292 // compilers on the platform will typically generate the inverse sequence.
293 // To fix this, we sort relocations by offset in RelocationScanner::scan;
294 // this ensures the correct sequence as the R_390_TLS_[GL]DCALL applies to
295 // the first byte of the brasl instruction, while the R_390_PLT32DBL applies
296 // to its third byte (the relative displacement).
297
298 if (type == R_390_TLS_GDCALL || type == R_390_TLS_LDCALL)
299 return 2;
300 return 1;
301}
302
303void SystemZ::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
304 uint64_t val) const {
305 // The general-dynamic code sequence for a global `x`:
306 //
307 // Instruction Relocation Symbol
308 // ear %rX,%a0
309 // sllg %rX,%rX,32
310 // ear %rX,%a1
311 // larl %r12,_GLOBAL_OFFSET_TABLE_ R_390_GOTPCDBL _GLOBAL_OFFSET_TABLE_
312 // lgrl %r2,.LC0 R_390_PC32DBL .LC0
313 // brasl %r14,__tls_get_offset@plt R_390_TLS_GDCALL x
314 // :tls_gdcall:x R_390_PLT32DBL __tls_get_offset
315 // la %r2,0(%r2,%rX)
316 //
317 // .LC0:
318 // .quad x@TLSGD R_390_TLS_GD64 x
319 //
320 // Relaxing to initial-exec entails:
321 // 1) Replacing the call by a load from the GOT.
322 // 2) Replacing the relocation on the constant LC0 by R_390_TLS_GOTIE64.
323
324 switch (rel.type) {
325 case R_390_TLS_GDCALL:
326 // brasl %r14,__tls_get_offset@plt -> lg %r2,0(%r2,%r12)
327 write16be(P: loc, V: 0xe322);
328 write32be(P: loc + 2, V: 0xc0000004);
329 break;
330 case R_390_TLS_GD64:
331 relocateNoSym(loc, type: R_390_TLS_GOTIE64, val);
332 break;
333 default:
334 llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
335 }
336}
337
338void SystemZ::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
339 uint64_t val) const {
340 // The general-dynamic code sequence for a global `x`:
341 //
342 // Instruction Relocation Symbol
343 // ear %rX,%a0
344 // sllg %rX,%rX,32
345 // ear %rX,%a1
346 // larl %r12,_GLOBAL_OFFSET_TABLE_ R_390_GOTPCDBL _GLOBAL_OFFSET_TABLE_
347 // lgrl %r2,.LC0 R_390_PC32DBL .LC0
348 // brasl %r14,__tls_get_offset@plt R_390_TLS_GDCALL x
349 // :tls_gdcall:x R_390_PLT32DBL __tls_get_offset
350 // la %r2,0(%r2,%rX)
351 //
352 // .LC0:
353 // .quad x@tlsgd R_390_TLS_GD64 x
354 //
355 // Relaxing to local-exec entails:
356 // 1) Replacing the call by a nop.
357 // 2) Replacing the relocation on the constant LC0 by R_390_TLS_LE64.
358
359 switch (rel.type) {
360 case R_390_TLS_GDCALL:
361 // brasl %r14,__tls_get_offset@plt -> brcl 0,.
362 write16be(P: loc, V: 0xc004);
363 write32be(P: loc + 2, V: 0x00000000);
364 break;
365 case R_390_TLS_GD64:
366 relocateNoSym(loc, type: R_390_TLS_LE64, val);
367 break;
368 default:
369 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
370 }
371}
372
373void SystemZ::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
374 uint64_t val) const {
375 // The local-dynamic code sequence for a global `x`:
376 //
377 // Instruction Relocation Symbol
378 // ear %rX,%a0
379 // sllg %rX,%rX,32
380 // ear %rX,%a1
381 // larl %r12,_GLOBAL_OFFSET_TABLE_ R_390_GOTPCDBL _GLOBAL_OFFSET_TABLE_
382 // lgrl %r2,.LC0 R_390_PC32DBL .LC0
383 // brasl %r14,__tls_get_offset@plt R_390_TLS_LDCALL <sym>
384 // :tls_ldcall:<sym> R_390_PLT32DBL __tls_get_offset
385 // la %r2,0(%r2,%rX)
386 // lgrl %rY,.LC1 R_390_PC32DBL .LC1
387 // la %r2,0(%r2,%rY)
388 //
389 // .LC0:
390 // .quad <sym>@tlsldm R_390_TLS_LDM64 <sym>
391 // .LC1:
392 // .quad x@dtpoff R_390_TLS_LDO64 x
393 //
394 // Relaxing to local-exec entails:
395 // 1) Replacing the call by a nop.
396 // 2) Replacing the constant LC0 by 0 (i.e. ignoring the relocation).
397 // 3) Replacing the relocation on the constant LC1 by R_390_TLS_LE64.
398
399 switch (rel.type) {
400 case R_390_TLS_LDCALL:
401 // brasl %r14,__tls_get_offset@plt -> brcl 0,.
402 write16be(P: loc, V: 0xc004);
403 write32be(P: loc + 2, V: 0x00000000);
404 break;
405 case R_390_TLS_LDM64:
406 break;
407 case R_390_TLS_LDO64:
408 relocateNoSym(loc, type: R_390_TLS_LE64, val);
409 break;
410 default:
411 llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
412 }
413}
414
415RelExpr SystemZ::adjustGotPcExpr(RelType type, int64_t addend,
416 const uint8_t *loc) const {
417 // Only R_390_GOTENT with addend 2 can be relaxed.
418 if (!ctx.arg.relax || addend != 2 || type != R_390_GOTENT)
419 return R_GOT_PC;
420 const uint16_t op = read16be(P: loc - 2);
421
422 // lgrl rx,sym@GOTENT -> larl rx, sym
423 // This relaxation is legal if "sym" binds locally (which was already
424 // verified by our caller) and is in-range and properly aligned for a
425 // LARL instruction. We cannot verify the latter constraint here, so
426 // we assume it is true and revert the decision later on in relaxOnce
427 // if necessary.
428 if ((op & 0xff0f) == 0xc408)
429 return R_RELAX_GOT_PC;
430
431 return R_GOT_PC;
432}
433
434bool SystemZ::relaxOnce(int pass) const {
435 // If we decided in adjustGotPcExpr to relax a R_390_GOTENT,
436 // we need to validate the target symbol is in-range and aligned.
437 SmallVector<InputSection *, 0> storage;
438 bool changed = false;
439 for (OutputSection *osec : ctx.outputSections) {
440 if (!(osec->flags & SHF_EXECINSTR))
441 continue;
442 for (InputSection *sec : getInputSections(os: *osec, storage)) {
443 for (Relocation &rel : sec->relocs()) {
444 if (rel.expr != R_RELAX_GOT_PC)
445 continue;
446
447 uint64_t v = sec->getRelocTargetVA(
448 ctx, r: rel, p: sec->getOutputSection()->addr + rel.offset);
449 if (isInt<33>(x: v) && !(v & 1))
450 continue;
451 if (rel.sym->auxIdx == 0) {
452 rel.sym->allocateAux(ctx);
453 addGotEntry(ctx, sym&: *rel.sym);
454 changed = true;
455 }
456 rel.expr = R_GOT_PC;
457 }
458 }
459 }
460 return changed;
461}
462
463void SystemZ::relaxGot(uint8_t *loc, const Relocation &rel,
464 uint64_t val) const {
465 assert(isInt<33>(val) &&
466 "R_390_GOTENT should not have been relaxed if it overflows");
467 assert(!(val & 1) &&
468 "R_390_GOTENT should not have been relaxed if it is misaligned");
469 const uint16_t op = read16be(P: loc - 2);
470
471 // lgrl rx,sym@GOTENT -> larl rx, sym
472 if ((op & 0xff0f) == 0xc408) {
473 write16be(P: loc - 2, V: 0xc000 | (op & 0x00f0));
474 write32be(P: loc, V: val >> 1);
475 }
476}
477
478void SystemZ::relocate(uint8_t *loc, const Relocation &rel,
479 uint64_t val) const {
480 switch (rel.expr) {
481 case R_RELAX_GOT_PC:
482 return relaxGot(loc, rel, val);
483 case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
484 return relaxTlsGdToIe(loc, rel, val);
485 case R_RELAX_TLS_GD_TO_LE:
486 return relaxTlsGdToLe(loc, rel, val);
487 case R_RELAX_TLS_LD_TO_LE:
488 return relaxTlsLdToLe(loc, rel, val);
489 default:
490 break;
491 }
492 switch (rel.type) {
493 case R_390_8:
494 checkIntUInt(ctx, loc, v: val, n: 8, rel);
495 *loc = val;
496 break;
497 case R_390_12:
498 case R_390_GOT12:
499 case R_390_GOTPLT12:
500 case R_390_TLS_GOTIE12:
501 checkUInt(ctx, loc, v: val, n: 12, rel);
502 write16be(P: loc, V: (read16be(P: loc) & 0xF000) | val);
503 break;
504 case R_390_PC12DBL:
505 case R_390_PLT12DBL:
506 checkInt(ctx, loc, v: val, n: 13, rel);
507 checkAlignment(ctx, loc, v: val, n: 2, rel);
508 write16be(P: loc, V: (read16be(P: loc) & 0xF000) | ((val >> 1) & 0x0FFF));
509 break;
510 case R_390_16:
511 case R_390_GOT16:
512 case R_390_GOTPLT16:
513 case R_390_GOTOFF16:
514 case R_390_PLTOFF16:
515 checkIntUInt(ctx, loc, v: val, n: 16, rel);
516 write16be(P: loc, V: val);
517 break;
518 case R_390_PC16:
519 checkInt(ctx, loc, v: val, n: 16, rel);
520 write16be(P: loc, V: val);
521 break;
522 case R_390_PC16DBL:
523 case R_390_PLT16DBL:
524 checkInt(ctx, loc, v: val, n: 17, rel);
525 checkAlignment(ctx, loc, v: val, n: 2, rel);
526 write16be(P: loc, V: val >> 1);
527 break;
528 case R_390_20:
529 case R_390_GOT20:
530 case R_390_GOTPLT20:
531 case R_390_TLS_GOTIE20:
532 checkInt(ctx, loc, v: val, n: 20, rel);
533 write32be(P: loc, V: (read32be(P: loc) & 0xF00000FF) | ((val & 0xFFF) << 16) |
534 ((val & 0xFF000) >> 4));
535 break;
536 case R_390_PC24DBL:
537 case R_390_PLT24DBL:
538 checkInt(ctx, loc, v: val, n: 25, rel);
539 checkAlignment(ctx, loc, v: val, n: 2, rel);
540 loc[0] = val >> 17;
541 loc[1] = val >> 9;
542 loc[2] = val >> 1;
543 break;
544 case R_390_32:
545 case R_390_GOT32:
546 case R_390_GOTPLT32:
547 case R_390_GOTOFF:
548 case R_390_PLTOFF32:
549 case R_390_TLS_IE32:
550 case R_390_TLS_GOTIE32:
551 case R_390_TLS_GD32:
552 case R_390_TLS_LDM32:
553 case R_390_TLS_LDO32:
554 case R_390_TLS_LE32:
555 checkIntUInt(ctx, loc, v: val, n: 32, rel);
556 write32be(P: loc, V: val);
557 break;
558 case R_390_PC32:
559 case R_390_PLT32:
560 checkInt(ctx, loc, v: val, n: 32, rel);
561 write32be(P: loc, V: val);
562 break;
563 case R_390_PC32DBL:
564 case R_390_PLT32DBL:
565 case R_390_GOTPCDBL:
566 case R_390_GOTENT:
567 case R_390_GOTPLTENT:
568 case R_390_TLS_IEENT:
569 checkInt(ctx, loc, v: val, n: 33, rel);
570 checkAlignment(ctx, loc, v: val, n: 2, rel);
571 write32be(P: loc, V: val >> 1);
572 break;
573 case R_390_64:
574 case R_390_PC64:
575 case R_390_PLT64:
576 case R_390_GOT64:
577 case R_390_GOTPLT64:
578 case R_390_GOTOFF64:
579 case R_390_PLTOFF64:
580 case R_390_GOTPC:
581 case R_390_TLS_IE64:
582 case R_390_TLS_GOTIE64:
583 case R_390_TLS_GD64:
584 case R_390_TLS_LDM64:
585 case R_390_TLS_LDO64:
586 case R_390_TLS_LE64:
587 case R_390_TLS_DTPMOD:
588 case R_390_TLS_DTPOFF:
589 case R_390_TLS_TPOFF:
590 write64be(P: loc, V: val);
591 break;
592 case R_390_TLS_LOAD:
593 case R_390_TLS_GDCALL:
594 case R_390_TLS_LDCALL:
595 break;
596 default:
597 llvm_unreachable("unknown relocation");
598 }
599}
600
601void elf::setSystemZTargetInfo(Ctx &ctx) { ctx.target.reset(p: new SystemZ(ctx)); }
602