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

source code of lld/ELF/Arch/SystemZ.cpp