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 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 83*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 179*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 185*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 189*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 194*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 211*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 217*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 235*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 270*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 276*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 282*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 305*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 340*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 375*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 417*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 436*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 466*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 481*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 604*74626c16SDimitry Andric TargetInfo *elf::getSystemZTargetInfo() { 605*74626c16SDimitry Andric static SystemZ t; 606*74626c16SDimitry Andric return &t; 607*74626c16SDimitry Andric } 608