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 "RelocScan.h"
11#include "Symbols.h"
12#include "SyntheticSections.h"
13#include "Target.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(Ctx &);
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 template <class ELFT, class RelTy>
38 void scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels);
39 void scanSection(InputSectionBase &sec) override;
40 RelExpr adjustGotPcExpr(RelType type, int64_t addend,
41 const uint8_t *loc) const override;
42 bool relaxOnce(int pass) const override;
43 void relocate(uint8_t *loc, const Relocation &rel,
44 uint64_t val) const override;
45 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
46
47private:
48 void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const;
49 void relaxTlsGdCall(uint8_t *loc, const Relocation &rel) 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
82// Only handles relocations used by relocateNonAlloc and preprocessRelocs.
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 case R_390_32:
89 case R_390_64:
90 return R_ABS;
91 case R_390_TLS_LDO32:
92 case R_390_TLS_LDO64:
93 return R_DTPREL;
94 case R_390_PC32:
95 case R_390_PC64:
96 return R_PC;
97 default:
98 Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
99 << ") against symbol " << &s;
100 return R_NONE;
101 }
102}
103
104void SystemZ::writeGotHeader(uint8_t *buf) const {
105 // _GLOBAL_OFFSET_TABLE_[0] holds the value of _DYNAMIC.
106 // _GLOBAL_OFFSET_TABLE_[1] and [2] are reserved.
107 write64be(P: buf, V: ctx.mainPart->dynamic->getVA());
108}
109
110void SystemZ::writeGotPlt(uint8_t *buf, const Symbol &s) const {
111 write64be(P: buf, V: s.getPltVA(ctx) + 14);
112}
113
114void SystemZ::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
115 if (ctx.arg.writeAddends)
116 write64be(P: buf, V: s.getVA(ctx));
117}
118
119void SystemZ::writePltHeader(uint8_t *buf) const {
120 const uint8_t pltData[] = {
121 0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, // stg %r1,56(%r15)
122 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1,_GLOBAL_OFFSET_TABLE_
123 0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, // mvc 48(8,%r15),8(%r1)
124 0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, // lg %r1,16(%r1)
125 0x07, 0xf1, // br %r1
126 0x07, 0x00, // nopr
127 0x07, 0x00, // nopr
128 0x07, 0x00, // nopr
129 };
130 memcpy(dest: buf, src: pltData, n: sizeof(pltData));
131 uint64_t got = ctx.in.got->getVA();
132 uint64_t plt = ctx.in.plt->getVA();
133 write32be(P: buf + 8, V: (got - plt - 6) >> 1);
134}
135
136void SystemZ::addPltHeaderSymbols(InputSection &isec) const {
137 // The PLT header needs a reference to _GLOBAL_OFFSET_TABLE_, so we
138 // must ensure the .got section is created even if otherwise unused.
139 ctx.in.got->hasGotOffRel.store(i: true, m: std::memory_order_relaxed);
140}
141
142void SystemZ::writePlt(uint8_t *buf, const Symbol &sym,
143 uint64_t pltEntryAddr) const {
144 const uint8_t inst[] = {
145 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1,<.got.plt slot>
146 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, // lg %r1,0(%r1)
147 0x07, 0xf1, // br %r1
148 0x0d, 0x10, // basr %r1,%r0
149 0xe3, 0x10, 0x10, 0x0c, 0x00, 0x14, // lgf %r1,12(%r1)
150 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, // jg <plt header>
151 0x00, 0x00, 0x00, 0x00, // <relocation offset>
152 };
153 memcpy(dest: buf, src: inst, n: sizeof(inst));
154
155 write32be(P: buf + 2, V: (sym.getGotPltVA(ctx) - pltEntryAddr) >> 1);
156 write32be(P: buf + 24, V: (ctx.in.plt->getVA() - pltEntryAddr - 22) >> 1);
157 write32be(P: buf + 28, V: ctx.in.relaPlt->entsize * sym.getPltIdx(ctx));
158}
159
160int64_t SystemZ::getImplicitAddend(const uint8_t *buf, RelType type) const {
161 switch (type) {
162 case R_390_8:
163 return SignExtend64<8>(x: *buf);
164 case R_390_16:
165 case R_390_PC16:
166 return SignExtend64<16>(x: read16be(P: buf));
167 case R_390_PC16DBL:
168 return SignExtend64<16>(x: read16be(P: buf)) << 1;
169 case R_390_32:
170 case R_390_PC32:
171 return SignExtend64<32>(x: read32be(P: buf));
172 case R_390_PC32DBL:
173 return SignExtend64<32>(x: read32be(P: buf)) << 1;
174 case R_390_64:
175 case R_390_PC64:
176 case R_390_TLS_DTPMOD:
177 case R_390_TLS_DTPOFF:
178 case R_390_TLS_TPOFF:
179 case R_390_GLOB_DAT:
180 case R_390_RELATIVE:
181 case R_390_IRELATIVE:
182 return read64be(P: buf);
183 case R_390_COPY:
184 case R_390_JMP_SLOT:
185 case R_390_NONE:
186 // These relocations are defined as not having an implicit addend.
187 return 0;
188 default:
189 InternalErr(ctx, buf) << "cannot read addend for relocation " << type;
190 return 0;
191 }
192}
193
194template <class ELFT, class RelTy>
195void SystemZ::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
196 RelocScan rs(ctx, &sec);
197 sec.relocations.reserve(N: rels.size());
198
199 for (auto it = rels.begin(); it != rels.end(); ++it) {
200 RelType type = it->getType(false);
201
202 // The assembler emits R_390_PLT32DBL (at the displacement field) before
203 // R_390_TLS_GDCALL/LDCALL (at the instruction start) for the same brasl.
204 // When optimizing TLS, skip PLT32DBL before maybeReportUndefined would
205 // flag __tls_get_offset as undefined.
206 if (type == R_390_PLT32DBL && !ctx.arg.shared &&
207 std::next(it) != rels.end()) {
208 RelType nextType = std::next(it)->getType(false);
209 if (nextType == R_390_TLS_GDCALL || nextType == R_390_TLS_LDCALL)
210 continue;
211 }
212
213 uint32_t symIdx = it->getSymbol(false);
214 Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);
215 uint64_t offset = it->r_offset;
216 if (sym.isUndefined() && symIdx != 0 &&
217 rs.maybeReportUndefined(sym&: cast<Undefined>(Val&: sym), offset))
218 continue;
219 int64_t addend = rs.getAddend<ELFT>(*it, type);
220 RelExpr expr;
221 // Relocation types that only need a RelExpr set `expr` and break out of
222 // the switch to reach rs.process(). Types that need special handling
223 // (fast-path helpers, TLS) call a handler and use `continue`.
224 switch (type) {
225 case R_390_NONE:
226 case R_390_TLS_LOAD:
227 continue;
228
229 // Absolute relocations:
230 case R_390_8:
231 case R_390_12:
232 case R_390_16:
233 case R_390_20:
234 case R_390_32:
235 case R_390_64:
236 expr = R_ABS;
237 break;
238
239 // PC-relative relocations:
240 case R_390_PC16:
241 case R_390_PC32:
242 case R_390_PC64:
243 case R_390_PC12DBL:
244 case R_390_PC16DBL:
245 case R_390_PC24DBL:
246 case R_390_PC32DBL:
247 rs.processR_PC(type, offset, addend, sym);
248 continue;
249
250 // PLT-generating relocations:
251 case R_390_PLT32:
252 case R_390_PLT64:
253 case R_390_PLT12DBL:
254 case R_390_PLT16DBL:
255 case R_390_PLT24DBL:
256 case R_390_PLT32DBL:
257 rs.processR_PLT_PC(type, offset, addend, sym);
258 continue;
259 case R_390_PLTOFF16:
260 case R_390_PLTOFF32:
261 case R_390_PLTOFF64:
262 expr = R_PLT_GOTREL;
263 break;
264
265 // GOT-generating relocations:
266 case R_390_GOTOFF16:
267 case R_390_GOTOFF: // a.k.a. R_390_GOTOFF32
268 case R_390_GOTOFF64:
269 ctx.in.got->hasGotOffRel.store(i: true, m: std::memory_order_relaxed);
270 expr = R_GOTREL;
271 break;
272 case R_390_GOTENT:
273 expr = R_GOT_PC;
274 break;
275 case R_390_GOT12:
276 case R_390_GOT16:
277 case R_390_GOT20:
278 case R_390_GOT32:
279 case R_390_GOT64:
280 expr = R_GOT_OFF;
281 break;
282
283 case R_390_GOTPLTENT:
284 expr = R_GOTPLT_PC;
285 break;
286 case R_390_GOTPLT12:
287 case R_390_GOTPLT16:
288 case R_390_GOTPLT20:
289 case R_390_GOTPLT32:
290 case R_390_GOTPLT64:
291 expr = R_GOTPLT_GOTREL;
292 break;
293 case R_390_GOTPC:
294 case R_390_GOTPCDBL:
295 ctx.in.got->hasGotOffRel.store(i: true, m: std::memory_order_relaxed);
296 expr = R_GOTONLY_PC;
297 break;
298
299 // TLS relocations:
300 case R_390_TLS_LE32:
301 case R_390_TLS_LE64:
302 if (rs.checkTlsLe(offset, sym, type))
303 continue;
304 expr = R_TPREL;
305 break;
306 case R_390_TLS_IE32:
307 case R_390_TLS_IE64:
308 // There is no IE to LE optimization.
309 rs.handleTlsIe<false>(ieExpr: R_GOT, type, offset, addend, sym);
310 continue;
311 case R_390_TLS_GOTIE12:
312 case R_390_TLS_GOTIE20:
313 case R_390_TLS_GOTIE32:
314 case R_390_TLS_GOTIE64:
315 sym.setFlags(NEEDS_TLSIE);
316 sec.addReloc(r: {.expr: R_GOT_OFF, .type: type, .offset: offset, .addend: addend, .sym: &sym});
317 continue;
318 case R_390_TLS_IEENT:
319 sym.setFlags(NEEDS_TLSIE);
320 sec.addReloc(r: {.expr: R_GOT_PC, .type: type, .offset: offset, .addend: addend, .sym: &sym});
321 continue;
322 case R_390_TLS_GDCALL:
323 // Use dummy R_ABS for `sharedExpr` (no optimization), which is a no-op in
324 // relocate().
325 rs.handleTlsGd(sharedExpr: R_ABS, ieExpr: R_GOT_OFF, leExpr: R_TPREL, type, offset, addend, sym);
326 continue;
327 case R_390_TLS_GD32:
328 case R_390_TLS_GD64:
329 rs.handleTlsGd(sharedExpr: R_TLSGD_GOT, ieExpr: R_GOT_OFF, leExpr: R_TPREL, type, offset, addend,
330 sym);
331 continue;
332
333 case R_390_TLS_LDCALL:
334 // Use dummy R_ABS for `sharedExpr` (no optimization), which is a no-op in
335 // relocate().
336 rs.handleTlsLd(sharedExpr: R_ABS, type, offset, addend, sym);
337 continue;
338 // TLS LD GOT relocations:
339 case R_390_TLS_LDM32:
340 case R_390_TLS_LDM64:
341 rs.handleTlsLd(sharedExpr: R_TLSLD_GOT, type, offset, addend, sym);
342 continue;
343 // TLS DTPREL relocations:
344 case R_390_TLS_LDO32:
345 case R_390_TLS_LDO64:
346 if (ctx.arg.shared)
347 sec.addReloc(r: {.expr: R_DTPREL, .type: type, .offset: offset, .addend: addend, .sym: &sym});
348 else
349 sec.addReloc(r: {.expr: R_TPREL, .type: type, .offset: offset, .addend: addend, .sym: &sym});
350 continue;
351
352 default:
353 Err(ctx) << getErrorLoc(ctx, loc: sec.content().data() + offset)
354 << "unknown relocation (" << type.v << ") against symbol "
355 << &sym;
356 continue;
357 }
358 rs.process(expr, type, offset, sym, addend);
359 }
360}
361
362void SystemZ::scanSection(InputSectionBase &sec) {
363 elf::scanSection1<SystemZ, ELF64BE>(target&: *this, sec);
364}
365
366RelType SystemZ::getDynRel(RelType type) const {
367 if (type == R_390_64 || type == R_390_PC64)
368 return type;
369 return R_390_NONE;
370}
371
372// Rewrite the brasl instruction at loc for TLS GD/LD optimization.
373//
374// The general-dynamic code sequence for a global `x`:
375//
376// Instruction Relocation Symbol
377// ear %rX,%a0
378// sllg %rX,%rX,32
379// ear %rX,%a1
380// larl %r12,_GLOBAL_OFFSET_TABLE_ R_390_GOTPCDBL _GLOBAL_OFFSET_TABLE_
381// lgrl %r2,.LC0 R_390_PC32DBL .LC0
382// brasl %r14,__tls_get_offset@plt R_390_TLS_GDCALL x
383// :tls_gdcall:x R_390_PLT32DBL __tls_get_offset
384// la %r2,0(%r2,%rX)
385//
386// .LC0:
387// .quad x@TLSGD R_390_TLS_GD64 x
388//
389// GD -> IE: replacing the call by a GOT load and LC0 by R_390_TLS_GOTIE64.
390// GD -> LE: replacing the call by a nop and LC0 by R_390_TLS_LE64.
391//
392// The local-dynamic code sequence for a global `x`:
393//
394// Instruction Relocation Symbol
395// ear %rX,%a0
396// sllg %rX,%rX,32
397// ear %rX,%a1
398// larl %r12,_GLOBAL_OFFSET_TABLE_ R_390_GOTPCDBL _GLOBAL_OFFSET_TABLE_
399// lgrl %r2,.LC0 R_390_PC32DBL .LC0
400// brasl %r14,__tls_get_offset@plt R_390_TLS_LDCALL <sym>
401// :tls_ldcall:<sym> R_390_PLT32DBL __tls_get_offset
402// la %r2,0(%r2,%rX)
403// lgrl %rY,.LC1 R_390_PC32DBL .LC1
404// la %r2,0(%r2,%rY)
405//
406// .LC0:
407// .quad <sym>@tlsldm R_390_TLS_LDM64 <sym>
408// .LC1:
409// .quad x@dtpoff R_390_TLS_LDO64 x
410//
411// LD -> LE: replacing the call by a nop, LC0 by 0, LC1 by R_390_TLS_LE64.
412void SystemZ::relaxTlsGdCall(uint8_t *loc, const Relocation &rel) const {
413 if (rel.expr == R_GOT_OFF) {
414 // brasl %r14,__tls_get_offset@plt -> lg %r2,0(%r2,%r12)
415 write16be(P: loc, V: 0xe322);
416 write32be(P: loc + 2, V: 0xc0000004);
417 } else {
418 // brasl %r14,__tls_get_offset@plt -> brcl 0,.
419 write16be(P: loc, V: 0xc004);
420 write32be(P: loc + 2, V: 0x00000000);
421 }
422}
423
424RelExpr SystemZ::adjustGotPcExpr(RelType type, int64_t addend,
425 const uint8_t *loc) const {
426 // Only R_390_GOTENT with addend 2 can be relaxed.
427 if (!ctx.arg.relax || addend != 2 || type != R_390_GOTENT)
428 return R_GOT_PC;
429 const uint16_t op = read16be(P: loc - 2);
430
431 // lgrl rx,sym@GOTENT -> larl rx, sym
432 // This relaxation is legal if "sym" binds locally (which was already
433 // verified by our caller) and is in-range and properly aligned for a
434 // LARL instruction. We cannot verify the latter constraint here, so
435 // we assume it is true and revert the decision later on in relaxOnce
436 // if necessary.
437 if ((op & 0xff0f) == 0xc408)
438 return R_RELAX_GOT_PC;
439
440 return R_GOT_PC;
441}
442
443bool SystemZ::relaxOnce(int pass) const {
444 // If we decided in adjustGotPcExpr to relax a R_390_GOTENT,
445 // we need to validate the target symbol is in-range and aligned.
446 SmallVector<InputSection *, 0> storage;
447 bool changed = false;
448 for (OutputSection *osec : ctx.outputSections) {
449 if (!(osec->flags & SHF_EXECINSTR))
450 continue;
451 for (InputSection *sec : getInputSections(os: *osec, storage)) {
452 for (Relocation &rel : sec->relocs()) {
453 if (rel.expr != R_RELAX_GOT_PC)
454 continue;
455
456 uint64_t v = sec->getRelocTargetVA(
457 ctx, r: rel, p: sec->getOutputSection()->addr + rel.offset);
458 if (isInt<33>(x: v) && !(v & 1))
459 continue;
460 if (rel.sym->auxIdx == 0) {
461 rel.sym->allocateAux(ctx);
462 addGotEntry(ctx, sym&: *rel.sym);
463 changed = true;
464 }
465 rel.expr = R_GOT_PC;
466 }
467 }
468 }
469 return changed;
470}
471
472void SystemZ::relaxGot(uint8_t *loc, const Relocation &rel,
473 uint64_t val) const {
474 assert(isInt<33>(val) &&
475 "R_390_GOTENT should not have been relaxed if it overflows");
476 assert(!(val & 1) &&
477 "R_390_GOTENT should not have been relaxed if it is misaligned");
478 const uint16_t op = read16be(P: loc - 2);
479
480 // lgrl rx,sym@GOTENT -> larl rx, sym
481 if ((op & 0xff0f) == 0xc408) {
482 write16be(P: loc - 2, V: 0xc000 | (op & 0x00f0));
483 write32be(P: loc, V: val >> 1);
484 }
485}
486
487void SystemZ::relocate(uint8_t *loc, const Relocation &rel,
488 uint64_t val) const {
489 if (rel.expr == R_RELAX_GOT_PC)
490 return relaxGot(loc, rel, val);
491
492 // Handle TLS optimizations. GDCALL/LDCALL: rewrite the brasl instruction
493 // and return. LDM slots are zeroed when relaxed to LE. Other TLS data slot
494 // types (GD32/GD64, LDO) fall through to the normal type-based switch below.
495 switch (rel.type) {
496 case R_390_TLS_GDCALL:
497 case R_390_TLS_LDCALL:
498 if (rel.expr == R_ABS) // Shared: no optimization.
499 return;
500 relaxTlsGdCall(loc, rel);
501 return;
502 case R_390_TLS_LDM32:
503 case R_390_TLS_LDM64:
504 if (rel.expr == R_TPREL)
505 return; // LD -> LE: slot stays 0.
506 break;
507 default:
508 break;
509 }
510
511 switch (rel.type) {
512 case R_390_8:
513 checkIntUInt(ctx, loc, v: val, n: 8, rel);
514 *loc = val;
515 break;
516 case R_390_12:
517 case R_390_GOT12:
518 case R_390_GOTPLT12:
519 case R_390_TLS_GOTIE12:
520 checkUInt(ctx, loc, v: val, n: 12, rel);
521 write16be(P: loc, V: (read16be(P: loc) & 0xF000) | val);
522 break;
523 case R_390_PC12DBL:
524 case R_390_PLT12DBL:
525 checkInt(ctx, loc, v: val, n: 13, rel);
526 checkAlignment(ctx, loc, v: val, n: 2, rel);
527 write16be(P: loc, V: (read16be(P: loc) & 0xF000) | ((val >> 1) & 0x0FFF));
528 break;
529 case R_390_16:
530 case R_390_GOT16:
531 case R_390_GOTPLT16:
532 case R_390_GOTOFF16:
533 case R_390_PLTOFF16:
534 checkIntUInt(ctx, loc, v: val, n: 16, rel);
535 write16be(P: loc, V: val);
536 break;
537 case R_390_PC16:
538 checkInt(ctx, loc, v: val, n: 16, rel);
539 write16be(P: loc, V: val);
540 break;
541 case R_390_PC16DBL:
542 case R_390_PLT16DBL:
543 checkInt(ctx, loc, v: val, n: 17, rel);
544 checkAlignment(ctx, loc, v: val, n: 2, rel);
545 write16be(P: loc, V: val >> 1);
546 break;
547 case R_390_20:
548 case R_390_GOT20:
549 case R_390_GOTPLT20:
550 case R_390_TLS_GOTIE20:
551 checkInt(ctx, loc, v: val, n: 20, rel);
552 write32be(P: loc, V: (read32be(P: loc) & 0xF00000FF) | ((val & 0xFFF) << 16) |
553 ((val & 0xFF000) >> 4));
554 break;
555 case R_390_PC24DBL:
556 case R_390_PLT24DBL:
557 checkInt(ctx, loc, v: val, n: 25, rel);
558 checkAlignment(ctx, loc, v: val, n: 2, rel);
559 loc[0] = val >> 17;
560 loc[1] = val >> 9;
561 loc[2] = val >> 1;
562 break;
563 case R_390_32:
564 case R_390_GOT32:
565 case R_390_GOTPLT32:
566 case R_390_GOTOFF:
567 case R_390_PLTOFF32:
568 case R_390_TLS_IE32:
569 case R_390_TLS_GOTIE32:
570 case R_390_TLS_GD32:
571 case R_390_TLS_LDM32:
572 case R_390_TLS_LDO32:
573 case R_390_TLS_LE32:
574 checkIntUInt(ctx, loc, v: val, n: 32, rel);
575 write32be(P: loc, V: val);
576 break;
577 case R_390_PC32:
578 case R_390_PLT32:
579 checkInt(ctx, loc, v: val, n: 32, rel);
580 write32be(P: loc, V: val);
581 break;
582 case R_390_PC32DBL:
583 case R_390_PLT32DBL:
584 case R_390_GOTPCDBL:
585 case R_390_GOTENT:
586 case R_390_GOTPLTENT:
587 case R_390_TLS_IEENT:
588 checkInt(ctx, loc, v: val, n: 33, rel);
589 checkAlignment(ctx, loc, v: val, n: 2, rel);
590 write32be(P: loc, V: val >> 1);
591 break;
592 case R_390_64:
593 case R_390_PC64:
594 case R_390_PLT64:
595 case R_390_GOT64:
596 case R_390_GOTPLT64:
597 case R_390_GOTOFF64:
598 case R_390_PLTOFF64:
599 case R_390_GOTPC:
600 case R_390_TLS_IE64:
601 case R_390_TLS_GOTIE64:
602 case R_390_TLS_GD64:
603 case R_390_TLS_LDM64:
604 case R_390_TLS_LDO64:
605 case R_390_TLS_LE64:
606 case R_390_TLS_DTPMOD:
607 case R_390_TLS_DTPOFF:
608 case R_390_TLS_TPOFF:
609 write64be(P: loc, V: val);
610 break;
611 case R_390_TLS_LOAD:
612 break;
613 default:
614 llvm_unreachable("unknown relocation");
615 }
616}
617
618void elf::setSystemZTargetInfo(Ctx &ctx) { ctx.target.reset(p: new SystemZ(ctx)); }
619