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