10b57cec5SDimitry Andric //===- PPC64.cpp ----------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 981ad6265SDimitry Andric #include "InputFiles.h" 10bdd1243dSDimitry Andric #include "OutputSections.h" 115ffd83dbSDimitry Andric #include "SymbolTable.h" 120b57cec5SDimitry Andric #include "Symbols.h" 130b57cec5SDimitry Andric #include "SyntheticSections.h" 140b57cec5SDimitry Andric #include "Target.h" 15480093f4SDimitry Andric #include "Thunks.h" 1604eeddc0SDimitry Andric #include "lld/Common/CommonLinkerContext.h" 170b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric using namespace llvm::object; 210b57cec5SDimitry Andric using namespace llvm::support::endian; 220b57cec5SDimitry Andric using namespace llvm::ELF; 235ffd83dbSDimitry Andric using namespace lld; 245ffd83dbSDimitry Andric using namespace lld::elf; 250b57cec5SDimitry Andric 26e8d8bef9SDimitry Andric constexpr uint64_t ppc64TocOffset = 0x8000; 27e8d8bef9SDimitry Andric constexpr uint64_t dynamicThreadPointerOffset = 0x8000; 280b57cec5SDimitry Andric 29439352acSDimitry Andric namespace { 300b57cec5SDimitry Andric // The instruction encoding of bits 21-30 from the ISA for the Xform and Dform 310b57cec5SDimitry Andric // instructions that can be used as part of the initial exec TLS sequence. 320b57cec5SDimitry Andric enum XFormOpcd { 330b57cec5SDimitry Andric LBZX = 87, 340b57cec5SDimitry Andric LHZX = 279, 350b57cec5SDimitry Andric LWZX = 23, 360b57cec5SDimitry Andric LDX = 21, 370b57cec5SDimitry Andric STBX = 215, 380b57cec5SDimitry Andric STHX = 407, 390b57cec5SDimitry Andric STWX = 151, 400b57cec5SDimitry Andric STDX = 149, 418a4dda33SDimitry Andric LHAX = 343, 428a4dda33SDimitry Andric LWAX = 341, 438a4dda33SDimitry Andric LFSX = 535, 448a4dda33SDimitry Andric LFDX = 599, 458a4dda33SDimitry Andric STFSX = 663, 468a4dda33SDimitry Andric STFDX = 727, 470b57cec5SDimitry Andric ADD = 266, 480b57cec5SDimitry Andric }; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric enum DFormOpcd { 510b57cec5SDimitry Andric LBZ = 34, 520b57cec5SDimitry Andric LBZU = 35, 530b57cec5SDimitry Andric LHZ = 40, 540b57cec5SDimitry Andric LHZU = 41, 550b57cec5SDimitry Andric LHAU = 43, 560b57cec5SDimitry Andric LWZ = 32, 570b57cec5SDimitry Andric LWZU = 33, 580b57cec5SDimitry Andric LFSU = 49, 590b57cec5SDimitry Andric LFDU = 51, 600b57cec5SDimitry Andric STB = 38, 610b57cec5SDimitry Andric STBU = 39, 620b57cec5SDimitry Andric STH = 44, 630b57cec5SDimitry Andric STHU = 45, 640b57cec5SDimitry Andric STW = 36, 650b57cec5SDimitry Andric STWU = 37, 660b57cec5SDimitry Andric STFSU = 53, 670b57cec5SDimitry Andric STFDU = 55, 688a4dda33SDimitry Andric LHA = 42, 698a4dda33SDimitry Andric LFS = 48, 708a4dda33SDimitry Andric LFD = 50, 718a4dda33SDimitry Andric STFS = 52, 728a4dda33SDimitry Andric STFD = 54, 730b57cec5SDimitry Andric ADDI = 14 740b57cec5SDimitry Andric }; 750b57cec5SDimitry Andric 768a4dda33SDimitry Andric enum DSFormOpcd { 778a4dda33SDimitry Andric LD = 58, 788a4dda33SDimitry Andric LWA = 58, 798a4dda33SDimitry Andric STD = 62 808a4dda33SDimitry Andric }; 818a4dda33SDimitry Andric 82e8d8bef9SDimitry Andric constexpr uint32_t NOP = 0x60000000; 83e8d8bef9SDimitry Andric 84e8d8bef9SDimitry Andric enum class PPCLegacyInsn : uint32_t { 85e8d8bef9SDimitry Andric NOINSN = 0, 86e8d8bef9SDimitry Andric // Loads. 87e8d8bef9SDimitry Andric LBZ = 0x88000000, 88e8d8bef9SDimitry Andric LHZ = 0xa0000000, 89e8d8bef9SDimitry Andric LWZ = 0x80000000, 90e8d8bef9SDimitry Andric LHA = 0xa8000000, 91e8d8bef9SDimitry Andric LWA = 0xe8000002, 92e8d8bef9SDimitry Andric LD = 0xe8000000, 93e8d8bef9SDimitry Andric LFS = 0xC0000000, 94e8d8bef9SDimitry Andric LXSSP = 0xe4000003, 95e8d8bef9SDimitry Andric LFD = 0xc8000000, 96e8d8bef9SDimitry Andric LXSD = 0xe4000002, 97e8d8bef9SDimitry Andric LXV = 0xf4000001, 98e8d8bef9SDimitry Andric LXVP = 0x18000000, 99e8d8bef9SDimitry Andric 100e8d8bef9SDimitry Andric // Stores. 101e8d8bef9SDimitry Andric STB = 0x98000000, 102e8d8bef9SDimitry Andric STH = 0xb0000000, 103e8d8bef9SDimitry Andric STW = 0x90000000, 104e8d8bef9SDimitry Andric STD = 0xf8000000, 105e8d8bef9SDimitry Andric STFS = 0xd0000000, 106e8d8bef9SDimitry Andric STXSSP = 0xf4000003, 107e8d8bef9SDimitry Andric STFD = 0xd8000000, 108e8d8bef9SDimitry Andric STXSD = 0xf4000002, 109e8d8bef9SDimitry Andric STXV = 0xf4000005, 110e8d8bef9SDimitry Andric STXVP = 0x18000001 111e8d8bef9SDimitry Andric }; 112e8d8bef9SDimitry Andric enum class PPCPrefixedInsn : uint64_t { 113e8d8bef9SDimitry Andric NOINSN = 0, 114e8d8bef9SDimitry Andric PREFIX_MLS = 0x0610000000000000, 115e8d8bef9SDimitry Andric PREFIX_8LS = 0x0410000000000000, 116e8d8bef9SDimitry Andric 117e8d8bef9SDimitry Andric // Loads. 118e8d8bef9SDimitry Andric PLBZ = PREFIX_MLS, 119e8d8bef9SDimitry Andric PLHZ = PREFIX_MLS, 120e8d8bef9SDimitry Andric PLWZ = PREFIX_MLS, 121e8d8bef9SDimitry Andric PLHA = PREFIX_MLS, 122e8d8bef9SDimitry Andric PLWA = PREFIX_8LS | 0xa4000000, 123e8d8bef9SDimitry Andric PLD = PREFIX_8LS | 0xe4000000, 124e8d8bef9SDimitry Andric PLFS = PREFIX_MLS, 125e8d8bef9SDimitry Andric PLXSSP = PREFIX_8LS | 0xac000000, 126e8d8bef9SDimitry Andric PLFD = PREFIX_MLS, 127e8d8bef9SDimitry Andric PLXSD = PREFIX_8LS | 0xa8000000, 128e8d8bef9SDimitry Andric PLXV = PREFIX_8LS | 0xc8000000, 129e8d8bef9SDimitry Andric PLXVP = PREFIX_8LS | 0xe8000000, 130e8d8bef9SDimitry Andric 131e8d8bef9SDimitry Andric // Stores. 132e8d8bef9SDimitry Andric PSTB = PREFIX_MLS, 133e8d8bef9SDimitry Andric PSTH = PREFIX_MLS, 134e8d8bef9SDimitry Andric PSTW = PREFIX_MLS, 135e8d8bef9SDimitry Andric PSTD = PREFIX_8LS | 0xf4000000, 136e8d8bef9SDimitry Andric PSTFS = PREFIX_MLS, 137e8d8bef9SDimitry Andric PSTXSSP = PREFIX_8LS | 0xbc000000, 138e8d8bef9SDimitry Andric PSTFD = PREFIX_MLS, 139e8d8bef9SDimitry Andric PSTXSD = PREFIX_8LS | 0xb8000000, 140e8d8bef9SDimitry Andric PSTXV = PREFIX_8LS | 0xd8000000, 141e8d8bef9SDimitry Andric PSTXVP = PREFIX_8LS | 0xf8000000 142e8d8bef9SDimitry Andric }; 143439352acSDimitry Andric 144e8d8bef9SDimitry Andric static bool checkPPCLegacyInsn(uint32_t encoding) { 145e8d8bef9SDimitry Andric PPCLegacyInsn insn = static_cast<PPCLegacyInsn>(encoding); 146e8d8bef9SDimitry Andric if (insn == PPCLegacyInsn::NOINSN) 147e8d8bef9SDimitry Andric return false; 148e8d8bef9SDimitry Andric #define PCREL_OPT(Legacy, PCRel, InsnMask) \ 149e8d8bef9SDimitry Andric if (insn == PPCLegacyInsn::Legacy) \ 150e8d8bef9SDimitry Andric return true; 151e8d8bef9SDimitry Andric #include "PPCInsns.def" 152e8d8bef9SDimitry Andric #undef PCREL_OPT 153e8d8bef9SDimitry Andric return false; 154e8d8bef9SDimitry Andric } 155e8d8bef9SDimitry Andric 156e8d8bef9SDimitry Andric // Masks to apply to legacy instructions when converting them to prefixed, 157e8d8bef9SDimitry Andric // pc-relative versions. For the most part, the primary opcode is shared 158e8d8bef9SDimitry Andric // between the legacy instruction and the suffix of its prefixed version. 159e8d8bef9SDimitry Andric // However, there are some instances where that isn't the case (DS-Form and 160e8d8bef9SDimitry Andric // DQ-form instructions). 161e8d8bef9SDimitry Andric enum class LegacyToPrefixMask : uint64_t { 162e8d8bef9SDimitry Andric NOMASK = 0x0, 163e8d8bef9SDimitry Andric OPC_AND_RST = 0xffe00000, // Primary opc (0-5) and R[ST] (6-10). 164e8d8bef9SDimitry Andric ONLY_RST = 0x3e00000, // [RS]T (6-10). 165e8d8bef9SDimitry Andric ST_STX28_TO5 = 166e8d8bef9SDimitry Andric 0x8000000003e00000, // S/T (6-10) - The [S/T]X bit moves from 28 to 5. 167e8d8bef9SDimitry Andric }; 168e8d8bef9SDimitry Andric 169bdd1243dSDimitry Andric class PPC64 final : public TargetInfo { 170bdd1243dSDimitry Andric public: 171bdd1243dSDimitry Andric PPC64(); 172bdd1243dSDimitry Andric int getTlsGdRelaxSkip(RelType type) const override; 173bdd1243dSDimitry Andric uint32_t calcEFlags() const override; 174bdd1243dSDimitry Andric RelExpr getRelExpr(RelType type, const Symbol &s, 175bdd1243dSDimitry Andric const uint8_t *loc) const override; 176bdd1243dSDimitry Andric RelType getDynRel(RelType type) const override; 177bdd1243dSDimitry Andric int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; 178bdd1243dSDimitry Andric void writePltHeader(uint8_t *buf) const override; 179bdd1243dSDimitry Andric void writePlt(uint8_t *buf, const Symbol &sym, 180bdd1243dSDimitry Andric uint64_t pltEntryAddr) const override; 181bdd1243dSDimitry Andric void writeIplt(uint8_t *buf, const Symbol &sym, 182bdd1243dSDimitry Andric uint64_t pltEntryAddr) const override; 183bdd1243dSDimitry Andric void relocate(uint8_t *loc, const Relocation &rel, 184bdd1243dSDimitry Andric uint64_t val) const override; 185bdd1243dSDimitry Andric void writeGotHeader(uint8_t *buf) const override; 186bdd1243dSDimitry Andric bool needsThunk(RelExpr expr, RelType type, const InputFile *file, 187bdd1243dSDimitry Andric uint64_t branchAddr, const Symbol &s, 188bdd1243dSDimitry Andric int64_t a) const override; 189bdd1243dSDimitry Andric uint32_t getThunkSectionSpacing() const override; 190bdd1243dSDimitry Andric bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; 191bdd1243dSDimitry Andric RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; 192bdd1243dSDimitry Andric RelExpr adjustGotPcExpr(RelType type, int64_t addend, 193bdd1243dSDimitry Andric const uint8_t *loc) const override; 194bdd1243dSDimitry Andric void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const; 195bdd1243dSDimitry Andric void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; 196bdd1243dSDimitry Andric 197bdd1243dSDimitry Andric bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, 198bdd1243dSDimitry Andric uint8_t stOther) const override; 199bdd1243dSDimitry Andric 200bdd1243dSDimitry Andric private: 201bdd1243dSDimitry Andric void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const; 202bdd1243dSDimitry Andric void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; 203bdd1243dSDimitry Andric void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; 204bdd1243dSDimitry Andric void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; 205bdd1243dSDimitry Andric }; 206bdd1243dSDimitry Andric } // namespace 207bdd1243dSDimitry Andric 2085ffd83dbSDimitry Andric uint64_t elf::getPPC64TocBase() { 2090b57cec5SDimitry Andric // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The 2100b57cec5SDimitry Andric // TOC starts where the first of these sections starts. We always create a 2110b57cec5SDimitry Andric // .got when we see a relocation that uses it, so for us the start is always 2120b57cec5SDimitry Andric // the .got. 2130b57cec5SDimitry Andric uint64_t tocVA = in.got->getVA(); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 2160b57cec5SDimitry Andric // thus permitting a full 64 Kbytes segment. Note that the glibc startup 2170b57cec5SDimitry Andric // code (crt1.o) assumes that you can get from the TOC base to the 2180b57cec5SDimitry Andric // start of the .toc section with only a single (signed) 16-bit relocation. 2190b57cec5SDimitry Andric return tocVA + ppc64TocOffset; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2225ffd83dbSDimitry Andric unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) { 2230b57cec5SDimitry Andric // The offset is encoded into the 3 most significant bits of the st_other 2240b57cec5SDimitry Andric // field, with some special values described in section 3.4.1 of the ABI: 2250b57cec5SDimitry Andric // 0 --> Zero offset between the GEP and LEP, and the function does NOT use 2260b57cec5SDimitry Andric // the TOC pointer (r2). r2 will hold the same value on returning from 2270b57cec5SDimitry Andric // the function as it did on entering the function. 2280b57cec5SDimitry Andric // 1 --> Zero offset between the GEP and LEP, and r2 should be treated as a 2290b57cec5SDimitry Andric // caller-saved register for all callers. 2300b57cec5SDimitry Andric // 2-6 --> The binary logarithm of the offset eg: 2310b57cec5SDimitry Andric // 2 --> 2^2 = 4 bytes --> 1 instruction. 2320b57cec5SDimitry Andric // 6 --> 2^6 = 64 bytes --> 16 instructions. 2330b57cec5SDimitry Andric // 7 --> Reserved. 2340b57cec5SDimitry Andric uint8_t gepToLep = (stOther >> 5) & 7; 2350b57cec5SDimitry Andric if (gepToLep < 2) 2360b57cec5SDimitry Andric return 0; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric // The value encoded in the st_other bits is the 2390b57cec5SDimitry Andric // log-base-2(offset). 2400b57cec5SDimitry Andric if (gepToLep < 7) 2410b57cec5SDimitry Andric return 1 << gepToLep; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric error("reserved value of 7 in the 3 most-significant-bits of st_other"); 2440b57cec5SDimitry Andric return 0; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 247e8d8bef9SDimitry Andric void elf::writePrefixedInstruction(uint8_t *loc, uint64_t insn) { 248e8d8bef9SDimitry Andric insn = config->isLE ? insn << 32 | insn >> 32 : insn; 249e8d8bef9SDimitry Andric write64(loc, insn); 250e8d8bef9SDimitry Andric } 251e8d8bef9SDimitry Andric 2525ffd83dbSDimitry Andric static bool addOptional(StringRef name, uint64_t value, 2535ffd83dbSDimitry Andric std::vector<Defined *> &defined) { 254bdd1243dSDimitry Andric Symbol *sym = symtab.find(name); 2555ffd83dbSDimitry Andric if (!sym || sym->isDefined()) 2565ffd83dbSDimitry Andric return false; 2577a6dacacSDimitry Andric sym->resolve(Defined{ctx.internalFile, StringRef(), STB_GLOBAL, STV_HIDDEN, 25881ad6265SDimitry Andric STT_FUNC, value, 2595ffd83dbSDimitry Andric /*size=*/0, /*section=*/nullptr}); 2605ffd83dbSDimitry Andric defined.push_back(cast<Defined>(sym)); 2615ffd83dbSDimitry Andric return true; 2625ffd83dbSDimitry Andric } 2635ffd83dbSDimitry Andric 2645ffd83dbSDimitry Andric // If from is 14, write ${prefix}14: firstInsn; ${prefix}15: 2655ffd83dbSDimitry Andric // firstInsn+0x200008; ...; ${prefix}31: firstInsn+(31-14)*0x200008; $tail 2665ffd83dbSDimitry Andric // The labels are defined only if they exist in the symbol table. 2675ffd83dbSDimitry Andric static void writeSequence(MutableArrayRef<uint32_t> buf, const char *prefix, 2685ffd83dbSDimitry Andric int from, uint32_t firstInsn, 2695ffd83dbSDimitry Andric ArrayRef<uint32_t> tail) { 2705ffd83dbSDimitry Andric std::vector<Defined *> defined; 2715ffd83dbSDimitry Andric char name[16]; 2725ffd83dbSDimitry Andric int first; 2735ffd83dbSDimitry Andric uint32_t *ptr = buf.data(); 2745ffd83dbSDimitry Andric for (int r = from; r < 32; ++r) { 2755ffd83dbSDimitry Andric format("%s%d", prefix, r).snprint(name, sizeof(name)); 2765ffd83dbSDimitry Andric if (addOptional(name, 4 * (r - from), defined) && defined.size() == 1) 2775ffd83dbSDimitry Andric first = r - from; 2785ffd83dbSDimitry Andric write32(ptr++, firstInsn + 0x200008 * (r - from)); 2795ffd83dbSDimitry Andric } 2805ffd83dbSDimitry Andric for (uint32_t insn : tail) 2815ffd83dbSDimitry Andric write32(ptr++, insn); 2825ffd83dbSDimitry Andric assert(ptr == &*buf.end()); 2835ffd83dbSDimitry Andric 2845ffd83dbSDimitry Andric if (defined.empty()) 2855ffd83dbSDimitry Andric return; 2865ffd83dbSDimitry Andric // The full section content has the extent of [begin, end). We drop unused 2875ffd83dbSDimitry Andric // instructions and write [first,end). 2885ffd83dbSDimitry Andric auto *sec = make<InputSection>( 289*0fca6ea1SDimitry Andric ctx.internalFile, SHF_ALLOC, SHT_PROGBITS, 4, 290bdd1243dSDimitry Andric ArrayRef(reinterpret_cast<uint8_t *>(buf.data() + first), 2915ffd83dbSDimitry Andric 4 * (buf.size() - first)), 2925ffd83dbSDimitry Andric ".text"); 293bdd1243dSDimitry Andric ctx.inputSections.push_back(sec); 2945ffd83dbSDimitry Andric for (Defined *sym : defined) { 2955ffd83dbSDimitry Andric sym->section = sec; 2965ffd83dbSDimitry Andric sym->value -= 4 * first; 2975ffd83dbSDimitry Andric } 2985ffd83dbSDimitry Andric } 2995ffd83dbSDimitry Andric 3005ffd83dbSDimitry Andric // Implements some save and restore functions as described by ELF V2 ABI to be 3015ffd83dbSDimitry Andric // compatible with GCC. With GCC -Os, when the number of call-saved registers 3025ffd83dbSDimitry Andric // exceeds a certain threshold, GCC generates _savegpr0_* _restgpr0_* calls and 3035ffd83dbSDimitry Andric // expects the linker to define them. See 3045ffd83dbSDimitry Andric // https://sourceware.org/pipermail/binutils/2002-February/017444.html and 3055ffd83dbSDimitry Andric // https://sourceware.org/pipermail/binutils/2004-August/036765.html . This is 3065ffd83dbSDimitry Andric // weird because libgcc.a would be the natural place. The linker generation 3075ffd83dbSDimitry Andric // approach has the advantage that the linker can generate multiple copies to 3085ffd83dbSDimitry Andric // avoid long branch thunks. However, we don't consider the advantage 3095ffd83dbSDimitry Andric // significant enough to complicate our trunk implementation, so we take the 3105ffd83dbSDimitry Andric // simple approach and synthesize .text sections providing the implementation. 3115ffd83dbSDimitry Andric void elf::addPPC64SaveRestore() { 3125ffd83dbSDimitry Andric static uint32_t savegpr0[20], restgpr0[21], savegpr1[19], restgpr1[19]; 3135ffd83dbSDimitry Andric constexpr uint32_t blr = 0x4e800020, mtlr_0 = 0x7c0803a6; 3145ffd83dbSDimitry Andric 3155ffd83dbSDimitry Andric // _restgpr0_14: ld 14, -144(1); _restgpr0_15: ld 15, -136(1); ... 3165ffd83dbSDimitry Andric // Tail: ld 0, 16(1); mtlr 0; blr 3175ffd83dbSDimitry Andric writeSequence(restgpr0, "_restgpr0_", 14, 0xe9c1ff70, 3185ffd83dbSDimitry Andric {0xe8010010, mtlr_0, blr}); 3195ffd83dbSDimitry Andric // _restgpr1_14: ld 14, -144(12); _restgpr1_15: ld 15, -136(12); ... 3205ffd83dbSDimitry Andric // Tail: blr 3215ffd83dbSDimitry Andric writeSequence(restgpr1, "_restgpr1_", 14, 0xe9ccff70, {blr}); 3225ffd83dbSDimitry Andric // _savegpr0_14: std 14, -144(1); _savegpr0_15: std 15, -136(1); ... 3235ffd83dbSDimitry Andric // Tail: std 0, 16(1); blr 3245ffd83dbSDimitry Andric writeSequence(savegpr0, "_savegpr0_", 14, 0xf9c1ff70, {0xf8010010, blr}); 3255ffd83dbSDimitry Andric // _savegpr1_14: std 14, -144(12); _savegpr1_15: std 15, -136(12); ... 3265ffd83dbSDimitry Andric // Tail: blr 3275ffd83dbSDimitry Andric writeSequence(savegpr1, "_savegpr1_", 14, 0xf9ccff70, {blr}); 3285ffd83dbSDimitry Andric } 3295ffd83dbSDimitry Andric 3300b57cec5SDimitry Andric // Find the R_PPC64_ADDR64 in .rela.toc with matching offset. 3310b57cec5SDimitry Andric template <typename ELFT> 3320b57cec5SDimitry Andric static std::pair<Defined *, int64_t> 3330b57cec5SDimitry Andric getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) { 3340b57cec5SDimitry Andric // .rela.toc contains exclusively R_PPC64_ADDR64 relocations sorted by 3350b57cec5SDimitry Andric // r_offset: 0, 8, 16, etc. For a given Offset, Offset / 8 gives us the 3360b57cec5SDimitry Andric // relocation index in most cases. 3370b57cec5SDimitry Andric // 3380b57cec5SDimitry Andric // In rare cases a TOC entry may store a constant that doesn't need an 3390b57cec5SDimitry Andric // R_PPC64_ADDR64, the corresponding r_offset is therefore missing. Offset / 8 3400b57cec5SDimitry Andric // points to a relocation with larger r_offset. Do a linear probe then. 3410b57cec5SDimitry Andric // Constants are extremely uncommon in .toc and the extra number of array 3420b57cec5SDimitry Andric // accesses can be seen as a small constant. 343349cc55cSDimitry Andric ArrayRef<typename ELFT::Rela> relas = 344349cc55cSDimitry Andric tocSec->template relsOrRelas<ELFT>().relas; 345349cc55cSDimitry Andric if (relas.empty()) 346349cc55cSDimitry Andric return {}; 3470b57cec5SDimitry Andric uint64_t index = std::min<uint64_t>(offset / 8, relas.size() - 1); 3480b57cec5SDimitry Andric for (;;) { 3490b57cec5SDimitry Andric if (relas[index].r_offset == offset) { 350*0fca6ea1SDimitry Andric Symbol &sym = tocSec->file->getRelocTargetSym(relas[index]); 3510b57cec5SDimitry Andric return {dyn_cast<Defined>(&sym), getAddend<ELFT>(relas[index])}; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric if (relas[index].r_offset < offset || index == 0) 3540b57cec5SDimitry Andric break; 3550b57cec5SDimitry Andric --index; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric return {}; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric // When accessing a symbol defined in another translation unit, compilers 3610b57cec5SDimitry Andric // reserve a .toc entry, allocate a local label and generate toc-indirect 3625ffd83dbSDimitry Andric // instructions: 3630b57cec5SDimitry Andric // 3640b57cec5SDimitry Andric // addis 3, 2, .LC0@toc@ha # R_PPC64_TOC16_HA 3650b57cec5SDimitry Andric // ld 3, .LC0@toc@l(3) # R_PPC64_TOC16_LO_DS, load the address from a .toc entry 3660b57cec5SDimitry Andric // ld/lwa 3, 0(3) # load the value from the address 3670b57cec5SDimitry Andric // 3680b57cec5SDimitry Andric // .section .toc,"aw",@progbits 3690b57cec5SDimitry Andric // .LC0: .tc var[TC],var 3700b57cec5SDimitry Andric // 3710b57cec5SDimitry Andric // If var is defined, non-preemptable and addressable with a 32-bit signed 3720b57cec5SDimitry Andric // offset from the toc base, the address of var can be computed by adding an 3730b57cec5SDimitry Andric // offset to the toc base, saving a load. 3740b57cec5SDimitry Andric // 3750b57cec5SDimitry Andric // addis 3,2,var@toc@ha # this may be relaxed to a nop, 3760b57cec5SDimitry Andric // addi 3,3,var@toc@l # then this becomes addi 3,2,var@toc 3770b57cec5SDimitry Andric // ld/lwa 3, 0(3) # load the value from the address 3780b57cec5SDimitry Andric // 3790b57cec5SDimitry Andric // Returns true if the relaxation is performed. 380bdd1243dSDimitry Andric static bool tryRelaxPPC64TocIndirection(const Relocation &rel, 381bdd1243dSDimitry Andric uint8_t *bufLoc) { 3820b57cec5SDimitry Andric assert(config->tocOptimize); 3830b57cec5SDimitry Andric if (rel.addend < 0) 3840b57cec5SDimitry Andric return false; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric // If the symbol is not the .toc section, this isn't a toc-indirection. 3870b57cec5SDimitry Andric Defined *defSym = dyn_cast<Defined>(rel.sym); 3880b57cec5SDimitry Andric if (!defSym || !defSym->isSection() || defSym->section->name != ".toc") 3890b57cec5SDimitry Andric return false; 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric Defined *d; 3920b57cec5SDimitry Andric int64_t addend; 3930b57cec5SDimitry Andric auto *tocISB = cast<InputSectionBase>(defSym->section); 3940b57cec5SDimitry Andric std::tie(d, addend) = 3950b57cec5SDimitry Andric config->isLE ? getRelaTocSymAndAddend<ELF64LE>(tocISB, rel.addend) 3960b57cec5SDimitry Andric : getRelaTocSymAndAddend<ELF64BE>(tocISB, rel.addend); 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric // Only non-preemptable defined symbols can be relaxed. 3990b57cec5SDimitry Andric if (!d || d->isPreemptible) 4000b57cec5SDimitry Andric return false; 4010b57cec5SDimitry Andric 40285868e8aSDimitry Andric // R_PPC64_ADDR64 should have created a canonical PLT for the non-preemptable 40385868e8aSDimitry Andric // ifunc and changed its type to STT_FUNC. 40485868e8aSDimitry Andric assert(!d->isGnuIFunc()); 40585868e8aSDimitry Andric 4060b57cec5SDimitry Andric // Two instructions can materialize a 32-bit signed offset from the toc base. 4070b57cec5SDimitry Andric uint64_t tocRelative = d->getVA(addend) - getPPC64TocBase(); 4080b57cec5SDimitry Andric if (!isInt<32>(tocRelative)) 4090b57cec5SDimitry Andric return false; 4100b57cec5SDimitry Andric 4115ffd83dbSDimitry Andric // Add PPC64TocOffset that will be subtracted by PPC64::relocate(). 412bdd1243dSDimitry Andric static_cast<const PPC64 &>(*target).relaxGot(bufLoc, rel, 413bdd1243dSDimitry Andric tocRelative + ppc64TocOffset); 4140b57cec5SDimitry Andric return true; 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // Relocation masks following the #lo(value), #hi(value), #ha(value), 4180b57cec5SDimitry Andric // #higher(value), #highera(value), #highest(value), and #highesta(value) 4190b57cec5SDimitry Andric // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi 4200b57cec5SDimitry Andric // document. 4210b57cec5SDimitry Andric static uint16_t lo(uint64_t v) { return v; } 4220b57cec5SDimitry Andric static uint16_t hi(uint64_t v) { return v >> 16; } 423e8d8bef9SDimitry Andric static uint64_t ha(uint64_t v) { return (v + 0x8000) >> 16; } 4240b57cec5SDimitry Andric static uint16_t higher(uint64_t v) { return v >> 32; } 4250b57cec5SDimitry Andric static uint16_t highera(uint64_t v) { return (v + 0x8000) >> 32; } 4260b57cec5SDimitry Andric static uint16_t highest(uint64_t v) { return v >> 48; } 4270b57cec5SDimitry Andric static uint16_t highesta(uint64_t v) { return (v + 0x8000) >> 48; } 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric // Extracts the 'PO' field of an instruction encoding. 4300b57cec5SDimitry Andric static uint8_t getPrimaryOpCode(uint32_t encoding) { return (encoding >> 26); } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric static bool isDQFormInstruction(uint32_t encoding) { 4330b57cec5SDimitry Andric switch (getPrimaryOpCode(encoding)) { 4340b57cec5SDimitry Andric default: 4350b57cec5SDimitry Andric return false; 436e8d8bef9SDimitry Andric case 6: // Power10 paired loads/stores (lxvp, stxvp). 4370b57cec5SDimitry Andric case 56: 4380b57cec5SDimitry Andric // The only instruction with a primary opcode of 56 is `lq`. 4390b57cec5SDimitry Andric return true; 4400b57cec5SDimitry Andric case 61: 4410b57cec5SDimitry Andric // There are both DS and DQ instruction forms with this primary opcode. 4420b57cec5SDimitry Andric // Namely `lxv` and `stxv` are the DQ-forms that use it. 4430b57cec5SDimitry Andric // The DS 'XO' bits being set to 01 is restricted to DQ form. 4440b57cec5SDimitry Andric return (encoding & 3) == 0x1; 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 448e8d8bef9SDimitry Andric static bool isDSFormInstruction(PPCLegacyInsn insn) { 449e8d8bef9SDimitry Andric switch (insn) { 450e8d8bef9SDimitry Andric default: 451e8d8bef9SDimitry Andric return false; 452e8d8bef9SDimitry Andric case PPCLegacyInsn::LWA: 453e8d8bef9SDimitry Andric case PPCLegacyInsn::LD: 454e8d8bef9SDimitry Andric case PPCLegacyInsn::LXSD: 455e8d8bef9SDimitry Andric case PPCLegacyInsn::LXSSP: 456e8d8bef9SDimitry Andric case PPCLegacyInsn::STD: 457e8d8bef9SDimitry Andric case PPCLegacyInsn::STXSD: 458e8d8bef9SDimitry Andric case PPCLegacyInsn::STXSSP: 459e8d8bef9SDimitry Andric return true; 460e8d8bef9SDimitry Andric } 461e8d8bef9SDimitry Andric } 462e8d8bef9SDimitry Andric 463e8d8bef9SDimitry Andric static PPCLegacyInsn getPPCLegacyInsn(uint32_t encoding) { 464e8d8bef9SDimitry Andric uint32_t opc = encoding & 0xfc000000; 465e8d8bef9SDimitry Andric 466e8d8bef9SDimitry Andric // If the primary opcode is shared between multiple instructions, we need to 467e8d8bef9SDimitry Andric // fix it up to match the actual instruction we are after. 468e8d8bef9SDimitry Andric if ((opc == 0xe4000000 || opc == 0xe8000000 || opc == 0xf4000000 || 469e8d8bef9SDimitry Andric opc == 0xf8000000) && 470e8d8bef9SDimitry Andric !isDQFormInstruction(encoding)) 471e8d8bef9SDimitry Andric opc = encoding & 0xfc000003; 472e8d8bef9SDimitry Andric else if (opc == 0xf4000000) 473e8d8bef9SDimitry Andric opc = encoding & 0xfc000007; 474e8d8bef9SDimitry Andric else if (opc == 0x18000000) 475e8d8bef9SDimitry Andric opc = encoding & 0xfc00000f; 476e8d8bef9SDimitry Andric 477e8d8bef9SDimitry Andric // If the value is not one of the enumerators in PPCLegacyInsn, we want to 478e8d8bef9SDimitry Andric // return PPCLegacyInsn::NOINSN. 479e8d8bef9SDimitry Andric if (!checkPPCLegacyInsn(opc)) 480e8d8bef9SDimitry Andric return PPCLegacyInsn::NOINSN; 481e8d8bef9SDimitry Andric return static_cast<PPCLegacyInsn>(opc); 482e8d8bef9SDimitry Andric } 483e8d8bef9SDimitry Andric 484e8d8bef9SDimitry Andric static PPCPrefixedInsn getPCRelativeForm(PPCLegacyInsn insn) { 485e8d8bef9SDimitry Andric switch (insn) { 486e8d8bef9SDimitry Andric #define PCREL_OPT(Legacy, PCRel, InsnMask) \ 487e8d8bef9SDimitry Andric case PPCLegacyInsn::Legacy: \ 488e8d8bef9SDimitry Andric return PPCPrefixedInsn::PCRel 489e8d8bef9SDimitry Andric #include "PPCInsns.def" 490e8d8bef9SDimitry Andric #undef PCREL_OPT 491e8d8bef9SDimitry Andric } 492e8d8bef9SDimitry Andric return PPCPrefixedInsn::NOINSN; 493e8d8bef9SDimitry Andric } 494e8d8bef9SDimitry Andric 495e8d8bef9SDimitry Andric static LegacyToPrefixMask getInsnMask(PPCLegacyInsn insn) { 496e8d8bef9SDimitry Andric switch (insn) { 497e8d8bef9SDimitry Andric #define PCREL_OPT(Legacy, PCRel, InsnMask) \ 498e8d8bef9SDimitry Andric case PPCLegacyInsn::Legacy: \ 499e8d8bef9SDimitry Andric return LegacyToPrefixMask::InsnMask 500e8d8bef9SDimitry Andric #include "PPCInsns.def" 501e8d8bef9SDimitry Andric #undef PCREL_OPT 502e8d8bef9SDimitry Andric } 503e8d8bef9SDimitry Andric return LegacyToPrefixMask::NOMASK; 504e8d8bef9SDimitry Andric } 505e8d8bef9SDimitry Andric static uint64_t getPCRelativeForm(uint32_t encoding) { 506e8d8bef9SDimitry Andric PPCLegacyInsn origInsn = getPPCLegacyInsn(encoding); 507e8d8bef9SDimitry Andric PPCPrefixedInsn pcrelInsn = getPCRelativeForm(origInsn); 508e8d8bef9SDimitry Andric if (pcrelInsn == PPCPrefixedInsn::NOINSN) 509e8d8bef9SDimitry Andric return UINT64_C(-1); 510e8d8bef9SDimitry Andric LegacyToPrefixMask origInsnMask = getInsnMask(origInsn); 511e8d8bef9SDimitry Andric uint64_t pcrelEncoding = 512e8d8bef9SDimitry Andric (uint64_t)pcrelInsn | (encoding & (uint64_t)origInsnMask); 513e8d8bef9SDimitry Andric 514e8d8bef9SDimitry Andric // If the mask requires moving bit 28 to bit 5, do that now. 515e8d8bef9SDimitry Andric if (origInsnMask == LegacyToPrefixMask::ST_STX28_TO5) 516e8d8bef9SDimitry Andric pcrelEncoding |= (encoding & 0x8) << 23; 517e8d8bef9SDimitry Andric return pcrelEncoding; 518e8d8bef9SDimitry Andric } 519e8d8bef9SDimitry Andric 5200b57cec5SDimitry Andric static bool isInstructionUpdateForm(uint32_t encoding) { 5210b57cec5SDimitry Andric switch (getPrimaryOpCode(encoding)) { 5220b57cec5SDimitry Andric default: 5230b57cec5SDimitry Andric return false; 5240b57cec5SDimitry Andric case LBZU: 5250b57cec5SDimitry Andric case LHAU: 5260b57cec5SDimitry Andric case LHZU: 5270b57cec5SDimitry Andric case LWZU: 5280b57cec5SDimitry Andric case LFSU: 5290b57cec5SDimitry Andric case LFDU: 5300b57cec5SDimitry Andric case STBU: 5310b57cec5SDimitry Andric case STHU: 5320b57cec5SDimitry Andric case STWU: 5330b57cec5SDimitry Andric case STFSU: 5340b57cec5SDimitry Andric case STFDU: 5350b57cec5SDimitry Andric return true; 5360b57cec5SDimitry Andric // LWA has the same opcode as LD, and the DS bits is what differentiates 5370b57cec5SDimitry Andric // between LD/LDU/LWA 5380b57cec5SDimitry Andric case LD: 5390b57cec5SDimitry Andric case STD: 5400b57cec5SDimitry Andric return (encoding & 3) == 1; 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 544e8d8bef9SDimitry Andric // Compute the total displacement between the prefixed instruction that gets 545e8d8bef9SDimitry Andric // to the start of the data and the load/store instruction that has the offset 546e8d8bef9SDimitry Andric // into the data structure. 547e8d8bef9SDimitry Andric // For example: 548e8d8bef9SDimitry Andric // paddi 3, 0, 1000, 1 549e8d8bef9SDimitry Andric // lwz 3, 20(3) 550e8d8bef9SDimitry Andric // Should add up to 1020 for total displacement. 551e8d8bef9SDimitry Andric static int64_t getTotalDisp(uint64_t prefixedInsn, uint32_t accessInsn) { 552e8d8bef9SDimitry Andric int64_t disp34 = llvm::SignExtend64( 553e8d8bef9SDimitry Andric ((prefixedInsn & 0x3ffff00000000) >> 16) | (prefixedInsn & 0xffff), 34); 554e8d8bef9SDimitry Andric int32_t disp16 = llvm::SignExtend32(accessInsn & 0xffff, 16); 555e8d8bef9SDimitry Andric // For DS and DQ form instructions, we need to mask out the XO bits. 556e8d8bef9SDimitry Andric if (isDQFormInstruction(accessInsn)) 557e8d8bef9SDimitry Andric disp16 &= ~0xf; 558e8d8bef9SDimitry Andric else if (isDSFormInstruction(getPPCLegacyInsn(accessInsn))) 559e8d8bef9SDimitry Andric disp16 &= ~0x3; 560e8d8bef9SDimitry Andric return disp34 + disp16; 561e8d8bef9SDimitry Andric } 562e8d8bef9SDimitry Andric 5630b57cec5SDimitry Andric // There are a number of places when we either want to read or write an 5640b57cec5SDimitry Andric // instruction when handling a half16 relocation type. On big-endian the buffer 5650b57cec5SDimitry Andric // pointer is pointing into the middle of the word we want to extract, and on 5660b57cec5SDimitry Andric // little-endian it is pointing to the start of the word. These 2 helpers are to 5670b57cec5SDimitry Andric // simplify reading and writing in that context. 5680b57cec5SDimitry Andric static void writeFromHalf16(uint8_t *loc, uint32_t insn) { 5690b57cec5SDimitry Andric write32(config->isLE ? loc : loc - 2, insn); 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric static uint32_t readFromHalf16(const uint8_t *loc) { 5730b57cec5SDimitry Andric return read32(config->isLE ? loc : loc - 2); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5765ffd83dbSDimitry Andric static uint64_t readPrefixedInstruction(const uint8_t *loc) { 5775ffd83dbSDimitry Andric uint64_t fullInstr = read64(loc); 5785ffd83dbSDimitry Andric return config->isLE ? (fullInstr << 32 | fullInstr >> 32) : fullInstr; 5795ffd83dbSDimitry Andric } 5805ffd83dbSDimitry Andric 5810b57cec5SDimitry Andric PPC64::PPC64() { 58255e4f9d5SDimitry Andric copyRel = R_PPC64_COPY; 5830b57cec5SDimitry Andric gotRel = R_PPC64_GLOB_DAT; 5840b57cec5SDimitry Andric pltRel = R_PPC64_JMP_SLOT; 5850b57cec5SDimitry Andric relativeRel = R_PPC64_RELATIVE; 5860b57cec5SDimitry Andric iRelativeRel = R_PPC64_IRELATIVE; 5870b57cec5SDimitry Andric symbolicRel = R_PPC64_ADDR64; 588480093f4SDimitry Andric pltHeaderSize = 60; 5890b57cec5SDimitry Andric pltEntrySize = 4; 590480093f4SDimitry Andric ipltEntrySize = 16; // PPC64PltCallStub::size 5910b57cec5SDimitry Andric gotHeaderEntriesNum = 1; 5920b57cec5SDimitry Andric gotPltHeaderEntriesNum = 2; 5930b57cec5SDimitry Andric needsThunks = true; 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric tlsModuleIndexRel = R_PPC64_DTPMOD64; 5960b57cec5SDimitry Andric tlsOffsetRel = R_PPC64_DTPREL64; 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric tlsGotRel = R_PPC64_TPREL64; 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric needsMoreStackNonSplit = false; 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric // We need 64K pages (at least under glibc/Linux, the loader won't 6030b57cec5SDimitry Andric // set different permissions on a finer granularity than that). 6040b57cec5SDimitry Andric defaultMaxPageSize = 65536; 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric // The PPC64 ELF ABI v1 spec, says: 6070b57cec5SDimitry Andric // 6080b57cec5SDimitry Andric // It is normally desirable to put segments with different characteristics 6090b57cec5SDimitry Andric // in separate 256 Mbyte portions of the address space, to give the 6100b57cec5SDimitry Andric // operating system full paging flexibility in the 64-bit address space. 6110b57cec5SDimitry Andric // 6120b57cec5SDimitry Andric // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers 6130b57cec5SDimitry Andric // use 0x10000000 as the starting address. 6140b57cec5SDimitry Andric defaultImageBase = 0x10000000; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric write32(trapInstr.data(), 0x7fe00008); 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric int PPC64::getTlsGdRelaxSkip(RelType type) const { 6200b57cec5SDimitry Andric // A __tls_get_addr call instruction is marked with 2 relocations: 6210b57cec5SDimitry Andric // 6220b57cec5SDimitry Andric // R_PPC64_TLSGD / R_PPC64_TLSLD: marker relocation 6230b57cec5SDimitry Andric // R_PPC64_REL24: __tls_get_addr 6240b57cec5SDimitry Andric // 6250b57cec5SDimitry Andric // After the relaxation we no longer call __tls_get_addr and should skip both 6260b57cec5SDimitry Andric // relocations to not create a false dependence on __tls_get_addr being 6270b57cec5SDimitry Andric // defined. 6280b57cec5SDimitry Andric if (type == R_PPC64_TLSGD || type == R_PPC64_TLSLD) 6290b57cec5SDimitry Andric return 2; 6300b57cec5SDimitry Andric return 1; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric static uint32_t getEFlags(InputFile *file) { 634bdd1243dSDimitry Andric if (file->ekind == ELF64BEKind) 635e8d8bef9SDimitry Andric return cast<ObjFile<ELF64BE>>(file)->getObj().getHeader().e_flags; 636e8d8bef9SDimitry Andric return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader().e_flags; 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric // This file implements v2 ABI. This function makes sure that all 6400b57cec5SDimitry Andric // object files have v2 or an unspecified version as an ABI version. 6410b57cec5SDimitry Andric uint32_t PPC64::calcEFlags() const { 642bdd1243dSDimitry Andric for (InputFile *f : ctx.objectFiles) { 6430b57cec5SDimitry Andric uint32_t flag = getEFlags(f); 6440b57cec5SDimitry Andric if (flag == 1) 6450b57cec5SDimitry Andric error(toString(f) + ": ABI version 1 is not supported"); 6460b57cec5SDimitry Andric else if (flag > 2) 6470b57cec5SDimitry Andric error(toString(f) + ": unrecognized e_flags: " + Twine(flag)); 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric return 2; 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 6525ffd83dbSDimitry Andric void PPC64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const { 6535ffd83dbSDimitry Andric switch (rel.type) { 6540b57cec5SDimitry Andric case R_PPC64_TOC16_HA: 6550b57cec5SDimitry Andric // Convert "addis reg, 2, .LC0@toc@h" to "addis reg, 2, var@toc@h" or "nop". 6565ffd83dbSDimitry Andric relocate(loc, rel, val); 6570b57cec5SDimitry Andric break; 6580b57cec5SDimitry Andric case R_PPC64_TOC16_LO_DS: { 6590b57cec5SDimitry Andric // Convert "ld reg, .LC0@toc@l(reg)" to "addi reg, reg, var@toc@l" or 6600b57cec5SDimitry Andric // "addi reg, 2, var@toc". 6610b57cec5SDimitry Andric uint32_t insn = readFromHalf16(loc); 6620b57cec5SDimitry Andric if (getPrimaryOpCode(insn) != LD) 6630b57cec5SDimitry Andric error("expected a 'ld' for got-indirect to toc-relative relaxing"); 6640b57cec5SDimitry Andric writeFromHalf16(loc, (insn & 0x03ffffff) | 0x38000000); 6655ffd83dbSDimitry Andric relocateNoSym(loc, R_PPC64_TOC16_LO, val); 6660b57cec5SDimitry Andric break; 6670b57cec5SDimitry Andric } 668e8d8bef9SDimitry Andric case R_PPC64_GOT_PCREL34: { 669e8d8bef9SDimitry Andric // Clear the first 8 bits of the prefix and the first 6 bits of the 670e8d8bef9SDimitry Andric // instruction (the primary opcode). 671e8d8bef9SDimitry Andric uint64_t insn = readPrefixedInstruction(loc); 672e8d8bef9SDimitry Andric if ((insn & 0xfc000000) != 0xe4000000) 673e8d8bef9SDimitry Andric error("expected a 'pld' for got-indirect to pc-relative relaxing"); 674e8d8bef9SDimitry Andric insn &= ~0xff000000fc000000; 675e8d8bef9SDimitry Andric 676e8d8bef9SDimitry Andric // Replace the cleared bits with the values for PADDI (0x600000038000000); 677e8d8bef9SDimitry Andric insn |= 0x600000038000000; 678e8d8bef9SDimitry Andric writePrefixedInstruction(loc, insn); 679e8d8bef9SDimitry Andric relocate(loc, rel, val); 680e8d8bef9SDimitry Andric break; 681e8d8bef9SDimitry Andric } 682e8d8bef9SDimitry Andric case R_PPC64_PCREL_OPT: { 683e8d8bef9SDimitry Andric // We can only relax this if the R_PPC64_GOT_PCREL34 at this offset can 684e8d8bef9SDimitry Andric // be relaxed. The eligibility for the relaxation needs to be determined 685e8d8bef9SDimitry Andric // on that relocation since this one does not relocate a symbol. 686e8d8bef9SDimitry Andric uint64_t insn = readPrefixedInstruction(loc); 687e8d8bef9SDimitry Andric uint32_t accessInsn = read32(loc + rel.addend); 688e8d8bef9SDimitry Andric uint64_t pcRelInsn = getPCRelativeForm(accessInsn); 689e8d8bef9SDimitry Andric 690e8d8bef9SDimitry Andric // This error is not necessary for correctness but is emitted for now 691e8d8bef9SDimitry Andric // to ensure we don't miss these opportunities in real code. It can be 692e8d8bef9SDimitry Andric // removed at a later date. 693e8d8bef9SDimitry Andric if (pcRelInsn == UINT64_C(-1)) { 694e8d8bef9SDimitry Andric errorOrWarn( 695e8d8bef9SDimitry Andric "unrecognized instruction for R_PPC64_PCREL_OPT relaxation: 0x" + 696e8d8bef9SDimitry Andric Twine::utohexstr(accessInsn)); 697e8d8bef9SDimitry Andric break; 698e8d8bef9SDimitry Andric } 699e8d8bef9SDimitry Andric 700e8d8bef9SDimitry Andric int64_t totalDisp = getTotalDisp(insn, accessInsn); 701e8d8bef9SDimitry Andric if (!isInt<34>(totalDisp)) 702e8d8bef9SDimitry Andric break; // Displacement doesn't fit. 703e8d8bef9SDimitry Andric // Convert the PADDI to the prefixed version of accessInsn and convert 704e8d8bef9SDimitry Andric // accessInsn to a nop. 705e8d8bef9SDimitry Andric writePrefixedInstruction(loc, pcRelInsn | 706e8d8bef9SDimitry Andric ((totalDisp & 0x3ffff0000) << 16) | 707e8d8bef9SDimitry Andric (totalDisp & 0xffff)); 708e8d8bef9SDimitry Andric write32(loc + rel.addend, NOP); // nop accessInsn. 709e8d8bef9SDimitry Andric break; 710e8d8bef9SDimitry Andric } 7110b57cec5SDimitry Andric default: 7120b57cec5SDimitry Andric llvm_unreachable("unexpected relocation type"); 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric 7165ffd83dbSDimitry Andric void PPC64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, 7175ffd83dbSDimitry Andric uint64_t val) const { 7180b57cec5SDimitry Andric // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement. 7190b57cec5SDimitry Andric // The general dynamic code sequence for a global `x` will look like: 7200b57cec5SDimitry Andric // Instruction Relocation Symbol 7210b57cec5SDimitry Andric // addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x 7220b57cec5SDimitry Andric // addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x 7230b57cec5SDimitry Andric // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x 7240b57cec5SDimitry Andric // R_PPC64_REL24 __tls_get_addr 7250b57cec5SDimitry Andric // nop None None 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric // Relaxing to local exec entails converting: 7280b57cec5SDimitry Andric // addis r3, r2, x@got@tlsgd@ha into nop 7290b57cec5SDimitry Andric // addi r3, r3, x@got@tlsgd@l into addis r3, r13, x@tprel@ha 7300b57cec5SDimitry Andric // bl __tls_get_addr(x@tlsgd) into nop 7310b57cec5SDimitry Andric // nop into addi r3, r3, x@tprel@l 7320b57cec5SDimitry Andric 7335ffd83dbSDimitry Andric switch (rel.type) { 7340b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_HA: 735e8d8bef9SDimitry Andric writeFromHalf16(loc, NOP); 7360b57cec5SDimitry Andric break; 7370b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16: 7380b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_LO: 7390b57cec5SDimitry Andric writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13 7405ffd83dbSDimitry Andric relocateNoSym(loc, R_PPC64_TPREL16_HA, val); 7410b57cec5SDimitry Andric break; 742e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSGD_PCREL34: 743e8d8bef9SDimitry Andric // Relax from paddi r3, 0, x@got@tlsgd@pcrel, 1 to 744e8d8bef9SDimitry Andric // paddi r3, r13, x@tprel, 0 745e8d8bef9SDimitry Andric writePrefixedInstruction(loc, 0x06000000386d0000); 746e8d8bef9SDimitry Andric relocateNoSym(loc, R_PPC64_TPREL34, val); 747e8d8bef9SDimitry Andric break; 748e8d8bef9SDimitry Andric case R_PPC64_TLSGD: { 749e8d8bef9SDimitry Andric // PC Relative Relaxation: 750e8d8bef9SDimitry Andric // Relax from bl __tls_get_addr@notoc(x@tlsgd) to 751e8d8bef9SDimitry Andric // nop 752e8d8bef9SDimitry Andric // TOC Relaxation: 753e8d8bef9SDimitry Andric // Relax from bl __tls_get_addr(x@tlsgd) 754e8d8bef9SDimitry Andric // nop 755e8d8bef9SDimitry Andric // to 756e8d8bef9SDimitry Andric // nop 757e8d8bef9SDimitry Andric // addi r3, r3, x@tprel@l 758e8d8bef9SDimitry Andric const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc); 759e8d8bef9SDimitry Andric if (locAsInt % 4 == 0) { 760e8d8bef9SDimitry Andric write32(loc, NOP); // nop 7610b57cec5SDimitry Andric write32(loc + 4, 0x38630000); // addi r3, r3 7620b57cec5SDimitry Andric // Since we are relocating a half16 type relocation and Loc + 4 points to 7630b57cec5SDimitry Andric // the start of an instruction we need to advance the buffer by an extra 7640b57cec5SDimitry Andric // 2 bytes on BE. 7655ffd83dbSDimitry Andric relocateNoSym(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0), 7660b57cec5SDimitry Andric R_PPC64_TPREL16_LO, val); 767e8d8bef9SDimitry Andric } else if (locAsInt % 4 == 1) { 768e8d8bef9SDimitry Andric write32(loc - 1, NOP); 769e8d8bef9SDimitry Andric } else { 770e8d8bef9SDimitry Andric errorOrWarn("R_PPC64_TLSGD has unexpected byte alignment"); 771e8d8bef9SDimitry Andric } 7720b57cec5SDimitry Andric break; 773e8d8bef9SDimitry Andric } 7740b57cec5SDimitry Andric default: 7750b57cec5SDimitry Andric llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7795ffd83dbSDimitry Andric void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, 7805ffd83dbSDimitry Andric uint64_t val) const { 7810b57cec5SDimitry Andric // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement. 7820b57cec5SDimitry Andric // The local dynamic code sequence for a global `x` will look like: 7830b57cec5SDimitry Andric // Instruction Relocation Symbol 7840b57cec5SDimitry Andric // addis r3, r2, x@got@tlsld@ha R_PPC64_GOT_TLSLD16_HA x 7850b57cec5SDimitry Andric // addi r3, r3, x@got@tlsld@l R_PPC64_GOT_TLSLD16_LO x 7860b57cec5SDimitry Andric // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSLD x 7870b57cec5SDimitry Andric // R_PPC64_REL24 __tls_get_addr 7880b57cec5SDimitry Andric // nop None None 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric // Relaxing to local exec entails converting: 7910b57cec5SDimitry Andric // addis r3, r2, x@got@tlsld@ha into nop 7920b57cec5SDimitry Andric // addi r3, r3, x@got@tlsld@l into addis r3, r13, 0 7930b57cec5SDimitry Andric // bl __tls_get_addr(x@tlsgd) into nop 7940b57cec5SDimitry Andric // nop into addi r3, r3, 4096 7950b57cec5SDimitry Andric 7965ffd83dbSDimitry Andric switch (rel.type) { 7970b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_HA: 798e8d8bef9SDimitry Andric writeFromHalf16(loc, NOP); 7990b57cec5SDimitry Andric break; 8000b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_LO: 8010b57cec5SDimitry Andric writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13, 0 8020b57cec5SDimitry Andric break; 803e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSLD_PCREL34: 804e8d8bef9SDimitry Andric // Relax from paddi r3, 0, x1@got@tlsld@pcrel, 1 to 805e8d8bef9SDimitry Andric // paddi r3, r13, 0x1000, 0 806e8d8bef9SDimitry Andric writePrefixedInstruction(loc, 0x06000000386d1000); 8070b57cec5SDimitry Andric break; 808e8d8bef9SDimitry Andric case R_PPC64_TLSLD: { 809e8d8bef9SDimitry Andric // PC Relative Relaxation: 810e8d8bef9SDimitry Andric // Relax from bl __tls_get_addr@notoc(x@tlsld) 811e8d8bef9SDimitry Andric // to 812e8d8bef9SDimitry Andric // nop 813e8d8bef9SDimitry Andric // TOC Relaxation: 814e8d8bef9SDimitry Andric // Relax from bl __tls_get_addr(x@tlsld) 815e8d8bef9SDimitry Andric // nop 816e8d8bef9SDimitry Andric // to 817e8d8bef9SDimitry Andric // nop 818e8d8bef9SDimitry Andric // addi r3, r3, 4096 819e8d8bef9SDimitry Andric const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc); 820e8d8bef9SDimitry Andric if (locAsInt % 4 == 0) { 821e8d8bef9SDimitry Andric write32(loc, NOP); 822e8d8bef9SDimitry Andric write32(loc + 4, 0x38631000); // addi r3, r3, 4096 823e8d8bef9SDimitry Andric } else if (locAsInt % 4 == 1) { 824e8d8bef9SDimitry Andric write32(loc - 1, NOP); 825e8d8bef9SDimitry Andric } else { 826e8d8bef9SDimitry Andric errorOrWarn("R_PPC64_TLSLD has unexpected byte alignment"); 827e8d8bef9SDimitry Andric } 828e8d8bef9SDimitry Andric break; 829e8d8bef9SDimitry Andric } 8300b57cec5SDimitry Andric case R_PPC64_DTPREL16: 8310b57cec5SDimitry Andric case R_PPC64_DTPREL16_HA: 8320b57cec5SDimitry Andric case R_PPC64_DTPREL16_HI: 8330b57cec5SDimitry Andric case R_PPC64_DTPREL16_DS: 8340b57cec5SDimitry Andric case R_PPC64_DTPREL16_LO: 8350b57cec5SDimitry Andric case R_PPC64_DTPREL16_LO_DS: 836e8d8bef9SDimitry Andric case R_PPC64_DTPREL34: 8375ffd83dbSDimitry Andric relocate(loc, rel, val); 8380b57cec5SDimitry Andric break; 8390b57cec5SDimitry Andric default: 8400b57cec5SDimitry Andric llvm_unreachable("unsupported relocation for TLS LD to LE relaxation"); 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 8448a4dda33SDimitry Andric // Map X-Form instructions to their DS-Form counterparts, if applicable. 8458a4dda33SDimitry Andric // The full encoding is returned here to distinguish between the different 8468a4dda33SDimitry Andric // DS-Form instructions. 8478a4dda33SDimitry Andric unsigned elf::getPPCDSFormOp(unsigned secondaryOp) { 8488a4dda33SDimitry Andric switch (secondaryOp) { 8498a4dda33SDimitry Andric case LWAX: 8508a4dda33SDimitry Andric return (LWA << 26) | 0x2; 8518a4dda33SDimitry Andric case LDX: 8528a4dda33SDimitry Andric return LD << 26; 8538a4dda33SDimitry Andric case STDX: 8548a4dda33SDimitry Andric return STD << 26; 8558a4dda33SDimitry Andric default: 8568a4dda33SDimitry Andric return 0; 8578a4dda33SDimitry Andric } 8588a4dda33SDimitry Andric } 8598a4dda33SDimitry Andric 8605ffd83dbSDimitry Andric unsigned elf::getPPCDFormOp(unsigned secondaryOp) { 8610b57cec5SDimitry Andric switch (secondaryOp) { 8620b57cec5SDimitry Andric case LBZX: 8638a4dda33SDimitry Andric return LBZ << 26; 8640b57cec5SDimitry Andric case LHZX: 8658a4dda33SDimitry Andric return LHZ << 26; 8660b57cec5SDimitry Andric case LWZX: 8678a4dda33SDimitry Andric return LWZ << 26; 8680b57cec5SDimitry Andric case STBX: 8698a4dda33SDimitry Andric return STB << 26; 8700b57cec5SDimitry Andric case STHX: 8718a4dda33SDimitry Andric return STH << 26; 8720b57cec5SDimitry Andric case STWX: 8738a4dda33SDimitry Andric return STW << 26; 8748a4dda33SDimitry Andric case LHAX: 8758a4dda33SDimitry Andric return LHA << 26; 8768a4dda33SDimitry Andric case LFSX: 8778a4dda33SDimitry Andric return LFS << 26; 8788a4dda33SDimitry Andric case LFDX: 8798a4dda33SDimitry Andric return LFD << 26; 8808a4dda33SDimitry Andric case STFSX: 8818a4dda33SDimitry Andric return STFS << 26; 8828a4dda33SDimitry Andric case STFDX: 8838a4dda33SDimitry Andric return STFD << 26; 8840b57cec5SDimitry Andric case ADD: 8858a4dda33SDimitry Andric return ADDI << 26; 8860b57cec5SDimitry Andric default: 8870b57cec5SDimitry Andric return 0; 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8915ffd83dbSDimitry Andric void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, 8925ffd83dbSDimitry Andric uint64_t val) const { 8930b57cec5SDimitry Andric // The initial exec code sequence for a global `x` will look like: 8940b57cec5SDimitry Andric // Instruction Relocation Symbol 8950b57cec5SDimitry Andric // addis r9, r2, x@got@tprel@ha R_PPC64_GOT_TPREL16_HA x 8960b57cec5SDimitry Andric // ld r9, x@got@tprel@l(r9) R_PPC64_GOT_TPREL16_LO_DS x 8970b57cec5SDimitry Andric // add r9, r9, x@tls R_PPC64_TLS x 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric // Relaxing to local exec entails converting: 9000b57cec5SDimitry Andric // addis r9, r2, x@got@tprel@ha into nop 9010b57cec5SDimitry Andric // ld r9, x@got@tprel@l(r9) into addis r9, r13, x@tprel@ha 9020b57cec5SDimitry Andric // add r9, r9, x@tls into addi r9, r9, x@tprel@l 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric // x@tls R_PPC64_TLS is a relocation which does not compute anything, 9050b57cec5SDimitry Andric // it is replaced with r13 (thread pointer). 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // The add instruction in the initial exec sequence has multiple variations 9080b57cec5SDimitry Andric // that need to be handled. If we are building an address it will use an add 9090b57cec5SDimitry Andric // instruction, if we are accessing memory it will use any of the X-form 9100b57cec5SDimitry Andric // indexed load or store instructions. 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric unsigned offset = (config->ekind == ELF64BEKind) ? 2 : 0; 9135ffd83dbSDimitry Andric switch (rel.type) { 9140b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_HA: 915e8d8bef9SDimitry Andric write32(loc - offset, NOP); 9160b57cec5SDimitry Andric break; 9170b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_LO_DS: 9180b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_DS: { 9190b57cec5SDimitry Andric uint32_t regNo = read32(loc - offset) & 0x03E00000; // bits 6-10 9200b57cec5SDimitry Andric write32(loc - offset, 0x3C0D0000 | regNo); // addis RegNo, r13 9215ffd83dbSDimitry Andric relocateNoSym(loc, R_PPC64_TPREL16_HA, val); 9220b57cec5SDimitry Andric break; 9230b57cec5SDimitry Andric } 924e8d8bef9SDimitry Andric case R_PPC64_GOT_TPREL_PCREL34: { 925e8d8bef9SDimitry Andric const uint64_t pldRT = readPrefixedInstruction(loc) & 0x0000000003e00000; 926e8d8bef9SDimitry Andric // paddi RT(from pld), r13, symbol@tprel, 0 927e8d8bef9SDimitry Andric writePrefixedInstruction(loc, 0x06000000380d0000 | pldRT); 928e8d8bef9SDimitry Andric relocateNoSym(loc, R_PPC64_TPREL34, val); 929e8d8bef9SDimitry Andric break; 930e8d8bef9SDimitry Andric } 9310b57cec5SDimitry Andric case R_PPC64_TLS: { 932e8d8bef9SDimitry Andric const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc); 933e8d8bef9SDimitry Andric if (locAsInt % 4 == 0) { 9340b57cec5SDimitry Andric uint32_t primaryOp = getPrimaryOpCode(read32(loc)); 9350b57cec5SDimitry Andric if (primaryOp != 31) 9360b57cec5SDimitry Andric error("unrecognized instruction for IE to LE R_PPC64_TLS"); 9370b57cec5SDimitry Andric uint32_t secondaryOp = (read32(loc) & 0x000007FE) >> 1; // bits 21-30 9380b57cec5SDimitry Andric uint32_t dFormOp = getPPCDFormOp(secondaryOp); 9398a4dda33SDimitry Andric uint32_t finalReloc; 9408a4dda33SDimitry Andric if (dFormOp == 0) { // Expecting a DS-Form instruction. 9418a4dda33SDimitry Andric dFormOp = getPPCDSFormOp(secondaryOp); 9420b57cec5SDimitry Andric if (dFormOp == 0) 9430b57cec5SDimitry Andric error("unrecognized instruction for IE to LE R_PPC64_TLS"); 9448a4dda33SDimitry Andric finalReloc = R_PPC64_TPREL16_LO_DS; 9458a4dda33SDimitry Andric } else 9468a4dda33SDimitry Andric finalReloc = R_PPC64_TPREL16_LO; 9478a4dda33SDimitry Andric write32(loc, dFormOp | (read32(loc) & 0x03ff0000)); 9488a4dda33SDimitry Andric relocateNoSym(loc + offset, finalReloc, val); 949e8d8bef9SDimitry Andric } else if (locAsInt % 4 == 1) { 950e8d8bef9SDimitry Andric // If the offset is not 4 byte aligned then we have a PCRel type reloc. 951e8d8bef9SDimitry Andric // This version of the relocation is offset by one byte from the 952e8d8bef9SDimitry Andric // instruction it references. 953e8d8bef9SDimitry Andric uint32_t tlsInstr = read32(loc - 1); 954e8d8bef9SDimitry Andric uint32_t primaryOp = getPrimaryOpCode(tlsInstr); 955e8d8bef9SDimitry Andric if (primaryOp != 31) 956e8d8bef9SDimitry Andric errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS"); 957e8d8bef9SDimitry Andric uint32_t secondaryOp = (tlsInstr & 0x000007FE) >> 1; // bits 21-30 958e8d8bef9SDimitry Andric // The add is a special case and should be turned into a nop. The paddi 959e8d8bef9SDimitry Andric // that comes before it will already have computed the address of the 960e8d8bef9SDimitry Andric // symbol. 961e8d8bef9SDimitry Andric if (secondaryOp == 266) { 962fe6060f1SDimitry Andric // Check if the add uses the same result register as the input register. 963fe6060f1SDimitry Andric uint32_t rt = (tlsInstr & 0x03E00000) >> 21; // bits 6-10 964fe6060f1SDimitry Andric uint32_t ra = (tlsInstr & 0x001F0000) >> 16; // bits 11-15 965fe6060f1SDimitry Andric if (ra == rt) { 966e8d8bef9SDimitry Andric write32(loc - 1, NOP); 967e8d8bef9SDimitry Andric } else { 968fe6060f1SDimitry Andric // mr rt, ra 969fe6060f1SDimitry Andric write32(loc - 1, 0x7C000378 | (rt << 16) | (ra << 21) | (ra << 11)); 970fe6060f1SDimitry Andric } 971fe6060f1SDimitry Andric } else { 972e8d8bef9SDimitry Andric uint32_t dFormOp = getPPCDFormOp(secondaryOp); 9738a4dda33SDimitry Andric if (dFormOp == 0) { // Expecting a DS-Form instruction. 9748a4dda33SDimitry Andric dFormOp = getPPCDSFormOp(secondaryOp); 975e8d8bef9SDimitry Andric if (dFormOp == 0) 976e8d8bef9SDimitry Andric errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS"); 9778a4dda33SDimitry Andric } 9788a4dda33SDimitry Andric write32(loc - 1, (dFormOp | (tlsInstr & 0x03ff0000))); 979e8d8bef9SDimitry Andric } 980e8d8bef9SDimitry Andric } else { 981e8d8bef9SDimitry Andric errorOrWarn("R_PPC64_TLS must be either 4 byte aligned or one byte " 982e8d8bef9SDimitry Andric "offset from 4 byte aligned"); 983e8d8bef9SDimitry Andric } 9840b57cec5SDimitry Andric break; 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric default: 9870b57cec5SDimitry Andric llvm_unreachable("unknown relocation for IE to LE"); 9880b57cec5SDimitry Andric break; 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, 9930b57cec5SDimitry Andric const uint8_t *loc) const { 9940b57cec5SDimitry Andric switch (type) { 9950b57cec5SDimitry Andric case R_PPC64_NONE: 9960b57cec5SDimitry Andric return R_NONE; 9970b57cec5SDimitry Andric case R_PPC64_ADDR16: 9980b57cec5SDimitry Andric case R_PPC64_ADDR16_DS: 9990b57cec5SDimitry Andric case R_PPC64_ADDR16_HA: 10000b57cec5SDimitry Andric case R_PPC64_ADDR16_HI: 1001e8d8bef9SDimitry Andric case R_PPC64_ADDR16_HIGH: 10020b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHER: 10030b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHERA: 10040b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHEST: 10050b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHESTA: 10060b57cec5SDimitry Andric case R_PPC64_ADDR16_LO: 10070b57cec5SDimitry Andric case R_PPC64_ADDR16_LO_DS: 10080b57cec5SDimitry Andric case R_PPC64_ADDR32: 10090b57cec5SDimitry Andric case R_PPC64_ADDR64: 10100b57cec5SDimitry Andric return R_ABS; 10110b57cec5SDimitry Andric case R_PPC64_GOT16: 10120b57cec5SDimitry Andric case R_PPC64_GOT16_DS: 10130b57cec5SDimitry Andric case R_PPC64_GOT16_HA: 10140b57cec5SDimitry Andric case R_PPC64_GOT16_HI: 10150b57cec5SDimitry Andric case R_PPC64_GOT16_LO: 10160b57cec5SDimitry Andric case R_PPC64_GOT16_LO_DS: 10170b57cec5SDimitry Andric return R_GOT_OFF; 10180b57cec5SDimitry Andric case R_PPC64_TOC16: 10190b57cec5SDimitry Andric case R_PPC64_TOC16_DS: 10200b57cec5SDimitry Andric case R_PPC64_TOC16_HI: 10210b57cec5SDimitry Andric case R_PPC64_TOC16_LO: 10220b57cec5SDimitry Andric return R_GOTREL; 10235ffd83dbSDimitry Andric case R_PPC64_GOT_PCREL34: 1024e8d8bef9SDimitry Andric case R_PPC64_GOT_TPREL_PCREL34: 1025e8d8bef9SDimitry Andric case R_PPC64_PCREL_OPT: 10265ffd83dbSDimitry Andric return R_GOT_PC; 10270b57cec5SDimitry Andric case R_PPC64_TOC16_HA: 10280b57cec5SDimitry Andric case R_PPC64_TOC16_LO_DS: 10290b57cec5SDimitry Andric return config->tocOptimize ? R_PPC64_RELAX_TOC : R_GOTREL; 10300b57cec5SDimitry Andric case R_PPC64_TOC: 10310b57cec5SDimitry Andric return R_PPC64_TOCBASE; 10320b57cec5SDimitry Andric case R_PPC64_REL14: 10330b57cec5SDimitry Andric case R_PPC64_REL24: 10340b57cec5SDimitry Andric return R_PPC64_CALL_PLT; 10355ffd83dbSDimitry Andric case R_PPC64_REL24_NOTOC: 10365ffd83dbSDimitry Andric return R_PLT_PC; 10370b57cec5SDimitry Andric case R_PPC64_REL16_LO: 10380b57cec5SDimitry Andric case R_PPC64_REL16_HA: 10390b57cec5SDimitry Andric case R_PPC64_REL16_HI: 10400b57cec5SDimitry Andric case R_PPC64_REL32: 10410b57cec5SDimitry Andric case R_PPC64_REL64: 10425ffd83dbSDimitry Andric case R_PPC64_PCREL34: 10430b57cec5SDimitry Andric return R_PC; 10440b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16: 10450b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_HA: 10460b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_HI: 10470b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_LO: 10480b57cec5SDimitry Andric return R_TLSGD_GOT; 1049e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSGD_PCREL34: 1050e8d8bef9SDimitry Andric return R_TLSGD_PC; 10510b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16: 10520b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_HA: 10530b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_HI: 10540b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_LO: 10550b57cec5SDimitry Andric return R_TLSLD_GOT; 1056e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSLD_PCREL34: 1057e8d8bef9SDimitry Andric return R_TLSLD_PC; 10580b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_HA: 10590b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_LO_DS: 10600b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_DS: 10610b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_HI: 10620b57cec5SDimitry Andric return R_GOT_OFF; 10630b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_HA: 10640b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_LO_DS: 10650b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_DS: 10660b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_HI: 10670b57cec5SDimitry Andric return R_TLSLD_GOT_OFF; 10680b57cec5SDimitry Andric case R_PPC64_TPREL16: 10690b57cec5SDimitry Andric case R_PPC64_TPREL16_HA: 10700b57cec5SDimitry Andric case R_PPC64_TPREL16_LO: 10710b57cec5SDimitry Andric case R_PPC64_TPREL16_HI: 10720b57cec5SDimitry Andric case R_PPC64_TPREL16_DS: 10730b57cec5SDimitry Andric case R_PPC64_TPREL16_LO_DS: 10740b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHER: 10750b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHERA: 10760b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHEST: 10770b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHESTA: 1078e8d8bef9SDimitry Andric case R_PPC64_TPREL34: 1079e8d8bef9SDimitry Andric return R_TPREL; 10800b57cec5SDimitry Andric case R_PPC64_DTPREL16: 10810b57cec5SDimitry Andric case R_PPC64_DTPREL16_DS: 10820b57cec5SDimitry Andric case R_PPC64_DTPREL16_HA: 10830b57cec5SDimitry Andric case R_PPC64_DTPREL16_HI: 10840b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHER: 10850b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHERA: 10860b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHEST: 10870b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHESTA: 10880b57cec5SDimitry Andric case R_PPC64_DTPREL16_LO: 10890b57cec5SDimitry Andric case R_PPC64_DTPREL16_LO_DS: 10900b57cec5SDimitry Andric case R_PPC64_DTPREL64: 1091e8d8bef9SDimitry Andric case R_PPC64_DTPREL34: 10920b57cec5SDimitry Andric return R_DTPREL; 10930b57cec5SDimitry Andric case R_PPC64_TLSGD: 10940b57cec5SDimitry Andric return R_TLSDESC_CALL; 10950b57cec5SDimitry Andric case R_PPC64_TLSLD: 10960b57cec5SDimitry Andric return R_TLSLD_HINT; 10970b57cec5SDimitry Andric case R_PPC64_TLS: 10980b57cec5SDimitry Andric return R_TLSIE_HINT; 10990b57cec5SDimitry Andric default: 11000b57cec5SDimitry Andric error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 11010b57cec5SDimitry Andric ") against symbol " + toString(s)); 11020b57cec5SDimitry Andric return R_NONE; 11030b57cec5SDimitry Andric } 11040b57cec5SDimitry Andric } 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric RelType PPC64::getDynRel(RelType type) const { 11070b57cec5SDimitry Andric if (type == R_PPC64_ADDR64 || type == R_PPC64_TOC) 11080b57cec5SDimitry Andric return R_PPC64_ADDR64; 11090b57cec5SDimitry Andric return R_PPC64_NONE; 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 1112298c3e8dSDimitry Andric int64_t PPC64::getImplicitAddend(const uint8_t *buf, RelType type) const { 1113298c3e8dSDimitry Andric switch (type) { 1114298c3e8dSDimitry Andric case R_PPC64_NONE: 1115bdd1243dSDimitry Andric case R_PPC64_GLOB_DAT: 1116bdd1243dSDimitry Andric case R_PPC64_JMP_SLOT: 1117298c3e8dSDimitry Andric return 0; 1118298c3e8dSDimitry Andric case R_PPC64_REL32: 1119298c3e8dSDimitry Andric return SignExtend64<32>(read32(buf)); 1120298c3e8dSDimitry Andric case R_PPC64_ADDR64: 1121298c3e8dSDimitry Andric case R_PPC64_REL64: 1122bdd1243dSDimitry Andric case R_PPC64_RELATIVE: 1123bdd1243dSDimitry Andric case R_PPC64_IRELATIVE: 1124bdd1243dSDimitry Andric case R_PPC64_DTPMOD64: 1125bdd1243dSDimitry Andric case R_PPC64_DTPREL64: 1126bdd1243dSDimitry Andric case R_PPC64_TPREL64: 1127298c3e8dSDimitry Andric return read64(buf); 1128298c3e8dSDimitry Andric default: 1129298c3e8dSDimitry Andric internalLinkerError(getErrorLocation(buf), 1130298c3e8dSDimitry Andric "cannot read addend for relocation " + toString(type)); 1131298c3e8dSDimitry Andric return 0; 1132298c3e8dSDimitry Andric } 1133298c3e8dSDimitry Andric } 1134298c3e8dSDimitry Andric 11350b57cec5SDimitry Andric void PPC64::writeGotHeader(uint8_t *buf) const { 11360b57cec5SDimitry Andric write64(buf, getPPC64TocBase()); 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric 11390b57cec5SDimitry Andric void PPC64::writePltHeader(uint8_t *buf) const { 11400b57cec5SDimitry Andric // The generic resolver stub goes first. 11410b57cec5SDimitry Andric write32(buf + 0, 0x7c0802a6); // mflr r0 11420b57cec5SDimitry Andric write32(buf + 4, 0x429f0005); // bcl 20,4*cr7+so,8 <_glink+0x8> 11430b57cec5SDimitry Andric write32(buf + 8, 0x7d6802a6); // mflr r11 11440b57cec5SDimitry Andric write32(buf + 12, 0x7c0803a6); // mtlr r0 11450b57cec5SDimitry Andric write32(buf + 16, 0x7d8b6050); // subf r12, r11, r12 11460b57cec5SDimitry Andric write32(buf + 20, 0x380cffcc); // subi r0,r12,52 11470b57cec5SDimitry Andric write32(buf + 24, 0x7800f082); // srdi r0,r0,62,2 11480b57cec5SDimitry Andric write32(buf + 28, 0xe98b002c); // ld r12,44(r11) 11490b57cec5SDimitry Andric write32(buf + 32, 0x7d6c5a14); // add r11,r12,r11 11500b57cec5SDimitry Andric write32(buf + 36, 0xe98b0000); // ld r12,0(r11) 11510b57cec5SDimitry Andric write32(buf + 40, 0xe96b0008); // ld r11,8(r11) 11520b57cec5SDimitry Andric write32(buf + 44, 0x7d8903a6); // mtctr r12 11530b57cec5SDimitry Andric write32(buf + 48, 0x4e800420); // bctr 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric // The 'bcl' instruction will set the link register to the address of the 11560b57cec5SDimitry Andric // following instruction ('mflr r11'). Here we store the offset from that 11570b57cec5SDimitry Andric // instruction to the first entry in the GotPlt section. 11580b57cec5SDimitry Andric int64_t gotPltOffset = in.gotPlt->getVA() - (in.plt->getVA() + 8); 11590b57cec5SDimitry Andric write64(buf + 52, gotPltOffset); 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric 1162480093f4SDimitry Andric void PPC64::writePlt(uint8_t *buf, const Symbol &sym, 1163480093f4SDimitry Andric uint64_t /*pltEntryAddr*/) const { 116404eeddc0SDimitry Andric int32_t offset = pltHeaderSize + sym.getPltIdx() * pltEntrySize; 11650b57cec5SDimitry Andric // bl __glink_PLTresolve 11660b57cec5SDimitry Andric write32(buf, 0x48000000 | ((-offset) & 0x03FFFFFc)); 11670b57cec5SDimitry Andric } 11680b57cec5SDimitry Andric 1169480093f4SDimitry Andric void PPC64::writeIplt(uint8_t *buf, const Symbol &sym, 1170480093f4SDimitry Andric uint64_t /*pltEntryAddr*/) const { 1171480093f4SDimitry Andric writePPC64LoadAndBranch(buf, sym.getGotPltVA() - getPPC64TocBase()); 1172480093f4SDimitry Andric } 1173480093f4SDimitry Andric 11740b57cec5SDimitry Andric static std::pair<RelType, uint64_t> toAddr16Rel(RelType type, uint64_t val) { 11750b57cec5SDimitry Andric // Relocations relative to the toc-base need to be adjusted by the Toc offset. 11760b57cec5SDimitry Andric uint64_t tocBiasedVal = val - ppc64TocOffset; 11770b57cec5SDimitry Andric // Relocations relative to dtv[dtpmod] need to be adjusted by the DTP offset. 11780b57cec5SDimitry Andric uint64_t dtpBiasedVal = val - dynamicThreadPointerOffset; 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric switch (type) { 11810b57cec5SDimitry Andric // TOC biased relocation. 11820b57cec5SDimitry Andric case R_PPC64_GOT16: 11830b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16: 11840b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16: 11850b57cec5SDimitry Andric case R_PPC64_TOC16: 11860b57cec5SDimitry Andric return {R_PPC64_ADDR16, tocBiasedVal}; 11870b57cec5SDimitry Andric case R_PPC64_GOT16_DS: 11880b57cec5SDimitry Andric case R_PPC64_TOC16_DS: 11890b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_DS: 11900b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_DS: 11910b57cec5SDimitry Andric return {R_PPC64_ADDR16_DS, tocBiasedVal}; 11920b57cec5SDimitry Andric case R_PPC64_GOT16_HA: 11930b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_HA: 11940b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_HA: 11950b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_HA: 11960b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_HA: 11970b57cec5SDimitry Andric case R_PPC64_TOC16_HA: 11980b57cec5SDimitry Andric return {R_PPC64_ADDR16_HA, tocBiasedVal}; 11990b57cec5SDimitry Andric case R_PPC64_GOT16_HI: 12000b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_HI: 12010b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_HI: 12020b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_HI: 12030b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_HI: 12040b57cec5SDimitry Andric case R_PPC64_TOC16_HI: 12050b57cec5SDimitry Andric return {R_PPC64_ADDR16_HI, tocBiasedVal}; 12060b57cec5SDimitry Andric case R_PPC64_GOT16_LO: 12070b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_LO: 12080b57cec5SDimitry Andric case R_PPC64_GOT_TLSLD16_LO: 12090b57cec5SDimitry Andric case R_PPC64_TOC16_LO: 12100b57cec5SDimitry Andric return {R_PPC64_ADDR16_LO, tocBiasedVal}; 12110b57cec5SDimitry Andric case R_PPC64_GOT16_LO_DS: 12120b57cec5SDimitry Andric case R_PPC64_TOC16_LO_DS: 12130b57cec5SDimitry Andric case R_PPC64_GOT_TPREL16_LO_DS: 12140b57cec5SDimitry Andric case R_PPC64_GOT_DTPREL16_LO_DS: 12150b57cec5SDimitry Andric return {R_PPC64_ADDR16_LO_DS, tocBiasedVal}; 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric // Dynamic Thread pointer biased relocation types. 12180b57cec5SDimitry Andric case R_PPC64_DTPREL16: 12190b57cec5SDimitry Andric return {R_PPC64_ADDR16, dtpBiasedVal}; 12200b57cec5SDimitry Andric case R_PPC64_DTPREL16_DS: 12210b57cec5SDimitry Andric return {R_PPC64_ADDR16_DS, dtpBiasedVal}; 12220b57cec5SDimitry Andric case R_PPC64_DTPREL16_HA: 12230b57cec5SDimitry Andric return {R_PPC64_ADDR16_HA, dtpBiasedVal}; 12240b57cec5SDimitry Andric case R_PPC64_DTPREL16_HI: 12250b57cec5SDimitry Andric return {R_PPC64_ADDR16_HI, dtpBiasedVal}; 12260b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHER: 12270b57cec5SDimitry Andric return {R_PPC64_ADDR16_HIGHER, dtpBiasedVal}; 12280b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHERA: 12290b57cec5SDimitry Andric return {R_PPC64_ADDR16_HIGHERA, dtpBiasedVal}; 12300b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHEST: 12310b57cec5SDimitry Andric return {R_PPC64_ADDR16_HIGHEST, dtpBiasedVal}; 12320b57cec5SDimitry Andric case R_PPC64_DTPREL16_HIGHESTA: 12330b57cec5SDimitry Andric return {R_PPC64_ADDR16_HIGHESTA, dtpBiasedVal}; 12340b57cec5SDimitry Andric case R_PPC64_DTPREL16_LO: 12350b57cec5SDimitry Andric return {R_PPC64_ADDR16_LO, dtpBiasedVal}; 12360b57cec5SDimitry Andric case R_PPC64_DTPREL16_LO_DS: 12370b57cec5SDimitry Andric return {R_PPC64_ADDR16_LO_DS, dtpBiasedVal}; 12380b57cec5SDimitry Andric case R_PPC64_DTPREL64: 12390b57cec5SDimitry Andric return {R_PPC64_ADDR64, dtpBiasedVal}; 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric default: 12420b57cec5SDimitry Andric return {type, val}; 12430b57cec5SDimitry Andric } 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric static bool isTocOptType(RelType type) { 12470b57cec5SDimitry Andric switch (type) { 12480b57cec5SDimitry Andric case R_PPC64_GOT16_HA: 12490b57cec5SDimitry Andric case R_PPC64_GOT16_LO_DS: 12500b57cec5SDimitry Andric case R_PPC64_TOC16_HA: 12510b57cec5SDimitry Andric case R_PPC64_TOC16_LO_DS: 12520b57cec5SDimitry Andric case R_PPC64_TOC16_LO: 12530b57cec5SDimitry Andric return true; 12540b57cec5SDimitry Andric default: 12550b57cec5SDimitry Andric return false; 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric 12595ffd83dbSDimitry Andric void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { 12605ffd83dbSDimitry Andric RelType type = rel.type; 12610b57cec5SDimitry Andric bool shouldTocOptimize = isTocOptType(type); 12620b57cec5SDimitry Andric // For dynamic thread pointer relative, toc-relative, and got-indirect 12630b57cec5SDimitry Andric // relocations, proceed in terms of the corresponding ADDR16 relocation type. 12640b57cec5SDimitry Andric std::tie(type, val) = toAddr16Rel(type, val); 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric switch (type) { 12670b57cec5SDimitry Andric case R_PPC64_ADDR14: { 12685ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 12690b57cec5SDimitry Andric // Preserve the AA/LK bits in the branch instruction 12700b57cec5SDimitry Andric uint8_t aalk = loc[3]; 12710b57cec5SDimitry Andric write16(loc + 2, (aalk & 3) | (val & 0xfffc)); 12720b57cec5SDimitry Andric break; 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric case R_PPC64_ADDR16: 12755ffd83dbSDimitry Andric checkIntUInt(loc, val, 16, rel); 12760b57cec5SDimitry Andric write16(loc, val); 12770b57cec5SDimitry Andric break; 12780b57cec5SDimitry Andric case R_PPC64_ADDR32: 12795ffd83dbSDimitry Andric checkIntUInt(loc, val, 32, rel); 12800b57cec5SDimitry Andric write32(loc, val); 12810b57cec5SDimitry Andric break; 12820b57cec5SDimitry Andric case R_PPC64_ADDR16_DS: 12830b57cec5SDimitry Andric case R_PPC64_TPREL16_DS: { 12845ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 12850b57cec5SDimitry Andric // DQ-form instructions use bits 28-31 as part of the instruction encoding 12860b57cec5SDimitry Andric // DS-form instructions only use bits 30-31. 12870b57cec5SDimitry Andric uint16_t mask = isDQFormInstruction(readFromHalf16(loc)) ? 0xf : 0x3; 12885ffd83dbSDimitry Andric checkAlignment(loc, lo(val), mask + 1, rel); 12890b57cec5SDimitry Andric write16(loc, (read16(loc) & mask) | lo(val)); 12900b57cec5SDimitry Andric } break; 12910b57cec5SDimitry Andric case R_PPC64_ADDR16_HA: 12920b57cec5SDimitry Andric case R_PPC64_REL16_HA: 12930b57cec5SDimitry Andric case R_PPC64_TPREL16_HA: 12940b57cec5SDimitry Andric if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) 1295e8d8bef9SDimitry Andric writeFromHalf16(loc, NOP); 1296e8d8bef9SDimitry Andric else { 1297e8d8bef9SDimitry Andric checkInt(loc, val + 0x8000, 32, rel); 12980b57cec5SDimitry Andric write16(loc, ha(val)); 1299e8d8bef9SDimitry Andric } 13000b57cec5SDimitry Andric break; 13010b57cec5SDimitry Andric case R_PPC64_ADDR16_HI: 13020b57cec5SDimitry Andric case R_PPC64_REL16_HI: 13030b57cec5SDimitry Andric case R_PPC64_TPREL16_HI: 1304e8d8bef9SDimitry Andric checkInt(loc, val, 32, rel); 1305e8d8bef9SDimitry Andric write16(loc, hi(val)); 1306e8d8bef9SDimitry Andric break; 1307e8d8bef9SDimitry Andric case R_PPC64_ADDR16_HIGH: 13080b57cec5SDimitry Andric write16(loc, hi(val)); 13090b57cec5SDimitry Andric break; 13100b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHER: 13110b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHER: 13120b57cec5SDimitry Andric write16(loc, higher(val)); 13130b57cec5SDimitry Andric break; 13140b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHERA: 13150b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHERA: 13160b57cec5SDimitry Andric write16(loc, highera(val)); 13170b57cec5SDimitry Andric break; 13180b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHEST: 13190b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHEST: 13200b57cec5SDimitry Andric write16(loc, highest(val)); 13210b57cec5SDimitry Andric break; 13220b57cec5SDimitry Andric case R_PPC64_ADDR16_HIGHESTA: 13230b57cec5SDimitry Andric case R_PPC64_TPREL16_HIGHESTA: 13240b57cec5SDimitry Andric write16(loc, highesta(val)); 13250b57cec5SDimitry Andric break; 13260b57cec5SDimitry Andric case R_PPC64_ADDR16_LO: 13270b57cec5SDimitry Andric case R_PPC64_REL16_LO: 13280b57cec5SDimitry Andric case R_PPC64_TPREL16_LO: 1329480093f4SDimitry Andric // When the high-adjusted part of a toc relocation evaluates to 0, it is 13300b57cec5SDimitry Andric // changed into a nop. The lo part then needs to be updated to use the 13310b57cec5SDimitry Andric // toc-pointer register r2, as the base register. 13320b57cec5SDimitry Andric if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) { 13330b57cec5SDimitry Andric uint32_t insn = readFromHalf16(loc); 13340b57cec5SDimitry Andric if (isInstructionUpdateForm(insn)) 13350b57cec5SDimitry Andric error(getErrorLocation(loc) + 13360b57cec5SDimitry Andric "can't toc-optimize an update instruction: 0x" + 13370b57cec5SDimitry Andric utohexstr(insn)); 13380b57cec5SDimitry Andric writeFromHalf16(loc, (insn & 0xffe00000) | 0x00020000 | lo(val)); 13390b57cec5SDimitry Andric } else { 13400b57cec5SDimitry Andric write16(loc, lo(val)); 13410b57cec5SDimitry Andric } 13420b57cec5SDimitry Andric break; 13430b57cec5SDimitry Andric case R_PPC64_ADDR16_LO_DS: 13440b57cec5SDimitry Andric case R_PPC64_TPREL16_LO_DS: { 13450b57cec5SDimitry Andric // DQ-form instructions use bits 28-31 as part of the instruction encoding 13460b57cec5SDimitry Andric // DS-form instructions only use bits 30-31. 13470b57cec5SDimitry Andric uint32_t insn = readFromHalf16(loc); 13480b57cec5SDimitry Andric uint16_t mask = isDQFormInstruction(insn) ? 0xf : 0x3; 13495ffd83dbSDimitry Andric checkAlignment(loc, lo(val), mask + 1, rel); 13500b57cec5SDimitry Andric if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) { 1351480093f4SDimitry Andric // When the high-adjusted part of a toc relocation evaluates to 0, it is 13520b57cec5SDimitry Andric // changed into a nop. The lo part then needs to be updated to use the toc 13530b57cec5SDimitry Andric // pointer register r2, as the base register. 13540b57cec5SDimitry Andric if (isInstructionUpdateForm(insn)) 13550b57cec5SDimitry Andric error(getErrorLocation(loc) + 13560b57cec5SDimitry Andric "Can't toc-optimize an update instruction: 0x" + 13570b57cec5SDimitry Andric Twine::utohexstr(insn)); 13580b57cec5SDimitry Andric insn &= 0xffe00000 | mask; 13590b57cec5SDimitry Andric writeFromHalf16(loc, insn | 0x00020000 | lo(val)); 13600b57cec5SDimitry Andric } else { 13610b57cec5SDimitry Andric write16(loc, (read16(loc) & mask) | lo(val)); 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric } break; 13640b57cec5SDimitry Andric case R_PPC64_TPREL16: 13655ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 13660b57cec5SDimitry Andric write16(loc, val); 13670b57cec5SDimitry Andric break; 13680b57cec5SDimitry Andric case R_PPC64_REL32: 13695ffd83dbSDimitry Andric checkInt(loc, val, 32, rel); 13700b57cec5SDimitry Andric write32(loc, val); 13710b57cec5SDimitry Andric break; 13720b57cec5SDimitry Andric case R_PPC64_ADDR64: 13730b57cec5SDimitry Andric case R_PPC64_REL64: 13740b57cec5SDimitry Andric case R_PPC64_TOC: 13750b57cec5SDimitry Andric write64(loc, val); 13760b57cec5SDimitry Andric break; 13770b57cec5SDimitry Andric case R_PPC64_REL14: { 13780b57cec5SDimitry Andric uint32_t mask = 0x0000FFFC; 13795ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 13805ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 13810b57cec5SDimitry Andric write32(loc, (read32(loc) & ~mask) | (val & mask)); 13820b57cec5SDimitry Andric break; 13830b57cec5SDimitry Andric } 13845ffd83dbSDimitry Andric case R_PPC64_REL24: 13855ffd83dbSDimitry Andric case R_PPC64_REL24_NOTOC: { 13860b57cec5SDimitry Andric uint32_t mask = 0x03FFFFFC; 13875ffd83dbSDimitry Andric checkInt(loc, val, 26, rel); 13885ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 13890b57cec5SDimitry Andric write32(loc, (read32(loc) & ~mask) | (val & mask)); 13900b57cec5SDimitry Andric break; 13910b57cec5SDimitry Andric } 13920b57cec5SDimitry Andric case R_PPC64_DTPREL64: 13930b57cec5SDimitry Andric write64(loc, val - dynamicThreadPointerOffset); 13940b57cec5SDimitry Andric break; 1395e8d8bef9SDimitry Andric case R_PPC64_DTPREL34: 1396e8d8bef9SDimitry Andric // The Dynamic Thread Vector actually points 0x8000 bytes past the start 1397e8d8bef9SDimitry Andric // of the TLS block. Therefore, in the case of R_PPC64_DTPREL34 we first 1398e8d8bef9SDimitry Andric // need to subtract that value then fallthrough to the general case. 1399e8d8bef9SDimitry Andric val -= dynamicThreadPointerOffset; 1400bdd1243dSDimitry Andric [[fallthrough]]; 1401e8d8bef9SDimitry Andric case R_PPC64_PCREL34: 1402e8d8bef9SDimitry Andric case R_PPC64_GOT_PCREL34: 1403e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSGD_PCREL34: 1404e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSLD_PCREL34: 1405e8d8bef9SDimitry Andric case R_PPC64_GOT_TPREL_PCREL34: 1406e8d8bef9SDimitry Andric case R_PPC64_TPREL34: { 14075ffd83dbSDimitry Andric const uint64_t si0Mask = 0x00000003ffff0000; 14085ffd83dbSDimitry Andric const uint64_t si1Mask = 0x000000000000ffff; 14095ffd83dbSDimitry Andric const uint64_t fullMask = 0x0003ffff0000ffff; 14105ffd83dbSDimitry Andric checkInt(loc, val, 34, rel); 14115ffd83dbSDimitry Andric 14125ffd83dbSDimitry Andric uint64_t instr = readPrefixedInstruction(loc) & ~fullMask; 14135ffd83dbSDimitry Andric writePrefixedInstruction(loc, instr | ((val & si0Mask) << 16) | 14145ffd83dbSDimitry Andric (val & si1Mask)); 14155ffd83dbSDimitry Andric break; 14165ffd83dbSDimitry Andric } 1417e8d8bef9SDimitry Andric // If we encounter a PCREL_OPT relocation that we won't optimize. 1418e8d8bef9SDimitry Andric case R_PPC64_PCREL_OPT: 14195ffd83dbSDimitry Andric break; 14200b57cec5SDimitry Andric default: 14210b57cec5SDimitry Andric llvm_unreachable("unknown relocation"); 14220b57cec5SDimitry Andric } 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file, 1426480093f4SDimitry Andric uint64_t branchAddr, const Symbol &s, int64_t a) const { 14275ffd83dbSDimitry Andric if (type != R_PPC64_REL14 && type != R_PPC64_REL24 && 14285ffd83dbSDimitry Andric type != R_PPC64_REL24_NOTOC) 14290b57cec5SDimitry Andric return false; 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric // If a function is in the Plt it needs to be called with a call-stub. 14320b57cec5SDimitry Andric if (s.isInPlt()) 14330b57cec5SDimitry Andric return true; 14340b57cec5SDimitry Andric 14355ffd83dbSDimitry Andric // This check looks at the st_other bits of the callee with relocation 14365ffd83dbSDimitry Andric // R_PPC64_REL14 or R_PPC64_REL24. If the value is 1, then the callee 14375ffd83dbSDimitry Andric // clobbers the TOC and we need an R2 save stub. 14385ffd83dbSDimitry Andric if (type != R_PPC64_REL24_NOTOC && (s.stOther >> 5) == 1) 14395ffd83dbSDimitry Andric return true; 14405ffd83dbSDimitry Andric 1441e8d8bef9SDimitry Andric if (type == R_PPC64_REL24_NOTOC && (s.stOther >> 5) > 1) 1442e8d8bef9SDimitry Andric return true; 1443e8d8bef9SDimitry Andric 1444d56accc7SDimitry Andric // An undefined weak symbol not in a PLT does not need a thunk. If it is 1445d56accc7SDimitry Andric // hidden, its binding has been converted to local, so we just check 1446d56accc7SDimitry Andric // isUndefined() here. A undefined non-weak symbol has been errored. 1447d56accc7SDimitry Andric if (s.isUndefined()) 14480b57cec5SDimitry Andric return false; 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric // If the offset exceeds the range of the branch type then it will need 14510b57cec5SDimitry Andric // a range-extending thunk. 14520b57cec5SDimitry Andric // See the comment in getRelocTargetVA() about R_PPC64_CALL. 14530b57cec5SDimitry Andric return !inBranchRange(type, branchAddr, 1454480093f4SDimitry Andric s.getVA(a) + 14550b57cec5SDimitry Andric getPPC64GlobalEntryToLocalEntryOffset(s.stOther)); 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric uint32_t PPC64::getThunkSectionSpacing() const { 14590b57cec5SDimitry Andric // See comment in Arch/ARM.cpp for a more detailed explanation of 14600b57cec5SDimitry Andric // getThunkSectionSpacing(). For PPC64 we pick the constant here based on 14610b57cec5SDimitry Andric // R_PPC64_REL24, which is used by unconditional branch instructions. 14620b57cec5SDimitry Andric // 0x2000000 = (1 << 24-1) * 4 14630b57cec5SDimitry Andric return 0x2000000; 14640b57cec5SDimitry Andric } 14650b57cec5SDimitry Andric 14660b57cec5SDimitry Andric bool PPC64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { 14670b57cec5SDimitry Andric int64_t offset = dst - src; 14680b57cec5SDimitry Andric if (type == R_PPC64_REL14) 14690b57cec5SDimitry Andric return isInt<16>(offset); 14705ffd83dbSDimitry Andric if (type == R_PPC64_REL24 || type == R_PPC64_REL24_NOTOC) 14710b57cec5SDimitry Andric return isInt<26>(offset); 14720b57cec5SDimitry Andric llvm_unreachable("unsupported relocation type used in branch"); 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric 1475e8d8bef9SDimitry Andric RelExpr PPC64::adjustTlsExpr(RelType type, RelExpr expr) const { 1476e8d8bef9SDimitry Andric if (type != R_PPC64_GOT_TLSGD_PCREL34 && expr == R_RELAX_TLS_GD_TO_IE) 14770b57cec5SDimitry Andric return R_RELAX_TLS_GD_TO_IE_GOT_OFF; 14780b57cec5SDimitry Andric if (expr == R_RELAX_TLS_LD_TO_LE) 14790b57cec5SDimitry Andric return R_RELAX_TLS_LD_TO_LE_ABS; 14800b57cec5SDimitry Andric return expr; 14810b57cec5SDimitry Andric } 14820b57cec5SDimitry Andric 1483e8d8bef9SDimitry Andric RelExpr PPC64::adjustGotPcExpr(RelType type, int64_t addend, 1484e8d8bef9SDimitry Andric const uint8_t *loc) const { 1485e8d8bef9SDimitry Andric if ((type == R_PPC64_GOT_PCREL34 || type == R_PPC64_PCREL_OPT) && 1486e8d8bef9SDimitry Andric config->pcRelOptimize) { 1487e8d8bef9SDimitry Andric // It only makes sense to optimize pld since paddi means that the address 1488e8d8bef9SDimitry Andric // of the object in the GOT is required rather than the object itself. 1489e8d8bef9SDimitry Andric if ((readPrefixedInstruction(loc) & 0xfc000000) == 0xe4000000) 1490e8d8bef9SDimitry Andric return R_PPC64_RELAX_GOT_PC; 1491e8d8bef9SDimitry Andric } 1492e8d8bef9SDimitry Andric return R_GOT_PC; 1493e8d8bef9SDimitry Andric } 1494e8d8bef9SDimitry Andric 14950b57cec5SDimitry Andric // Reference: 3.7.4.1 of the 64-bit ELF V2 abi supplement. 14960b57cec5SDimitry Andric // The general dynamic code sequence for a global `x` uses 4 instructions. 14970b57cec5SDimitry Andric // Instruction Relocation Symbol 14980b57cec5SDimitry Andric // addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x 14990b57cec5SDimitry Andric // addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x 15000b57cec5SDimitry Andric // bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x 15010b57cec5SDimitry Andric // R_PPC64_REL24 __tls_get_addr 15020b57cec5SDimitry Andric // nop None None 15030b57cec5SDimitry Andric // 15040b57cec5SDimitry Andric // Relaxing to initial-exec entails: 15050b57cec5SDimitry Andric // 1) Convert the addis/addi pair that builds the address of the tls_index 15060b57cec5SDimitry Andric // struct for 'x' to an addis/ld pair that loads an offset from a got-entry. 15070b57cec5SDimitry Andric // 2) Convert the call to __tls_get_addr to a nop. 15080b57cec5SDimitry Andric // 3) Convert the nop following the call to an add of the loaded offset to the 15090b57cec5SDimitry Andric // thread pointer. 15100b57cec5SDimitry Andric // Since the nop must directly follow the call, the R_PPC64_TLSGD relocation is 15110b57cec5SDimitry Andric // used as the relaxation hint for both steps 2 and 3. 15125ffd83dbSDimitry Andric void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, 15135ffd83dbSDimitry Andric uint64_t val) const { 15145ffd83dbSDimitry Andric switch (rel.type) { 15150b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_HA: 15160b57cec5SDimitry Andric // This is relaxed from addis rT, r2, sym@got@tlsgd@ha to 15170b57cec5SDimitry Andric // addis rT, r2, sym@got@tprel@ha. 15185ffd83dbSDimitry Andric relocateNoSym(loc, R_PPC64_GOT_TPREL16_HA, val); 15190b57cec5SDimitry Andric return; 15200b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16: 15210b57cec5SDimitry Andric case R_PPC64_GOT_TLSGD16_LO: { 15220b57cec5SDimitry Andric // Relax from addi r3, rA, sym@got@tlsgd@l to 15230b57cec5SDimitry Andric // ld r3, sym@got@tprel@l(rA) 15240b57cec5SDimitry Andric uint32_t ra = (readFromHalf16(loc) & (0x1f << 16)); 15250b57cec5SDimitry Andric writeFromHalf16(loc, 0xe8600000 | ra); 15265ffd83dbSDimitry Andric relocateNoSym(loc, R_PPC64_GOT_TPREL16_LO_DS, val); 15270b57cec5SDimitry Andric return; 15280b57cec5SDimitry Andric } 1529e8d8bef9SDimitry Andric case R_PPC64_GOT_TLSGD_PCREL34: { 1530e8d8bef9SDimitry Andric // Relax from paddi r3, 0, sym@got@tlsgd@pcrel, 1 to 1531e8d8bef9SDimitry Andric // pld r3, sym@got@tprel@pcrel 1532e8d8bef9SDimitry Andric writePrefixedInstruction(loc, 0x04100000e4600000); 1533e8d8bef9SDimitry Andric relocateNoSym(loc, R_PPC64_GOT_TPREL_PCREL34, val); 15340b57cec5SDimitry Andric return; 1535e8d8bef9SDimitry Andric } 1536e8d8bef9SDimitry Andric case R_PPC64_TLSGD: { 1537e8d8bef9SDimitry Andric // PC Relative Relaxation: 1538e8d8bef9SDimitry Andric // Relax from bl __tls_get_addr@notoc(x@tlsgd) to 1539e8d8bef9SDimitry Andric // nop 1540e8d8bef9SDimitry Andric // TOC Relaxation: 1541e8d8bef9SDimitry Andric // Relax from bl __tls_get_addr(x@tlsgd) 1542e8d8bef9SDimitry Andric // nop 1543e8d8bef9SDimitry Andric // to 1544e8d8bef9SDimitry Andric // nop 1545e8d8bef9SDimitry Andric // add r3, r3, r13 1546e8d8bef9SDimitry Andric const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc); 1547e8d8bef9SDimitry Andric if (locAsInt % 4 == 0) { 1548e8d8bef9SDimitry Andric write32(loc, NOP); // bl __tls_get_addr(sym@tlsgd) --> nop 1549e8d8bef9SDimitry Andric write32(loc + 4, 0x7c636A14); // nop --> add r3, r3, r13 1550e8d8bef9SDimitry Andric } else if (locAsInt % 4 == 1) { 1551e8d8bef9SDimitry Andric // bl __tls_get_addr(sym@tlsgd) --> add r3, r3, r13 1552e8d8bef9SDimitry Andric write32(loc - 1, 0x7c636a14); 1553e8d8bef9SDimitry Andric } else { 1554e8d8bef9SDimitry Andric errorOrWarn("R_PPC64_TLSGD has unexpected byte alignment"); 1555e8d8bef9SDimitry Andric } 1556e8d8bef9SDimitry Andric return; 1557e8d8bef9SDimitry Andric } 15580b57cec5SDimitry Andric default: 15590b57cec5SDimitry Andric llvm_unreachable("unsupported relocation for TLS GD to IE relaxation"); 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric 1563bdd1243dSDimitry Andric void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { 1564bdd1243dSDimitry Andric uint64_t secAddr = sec.getOutputSection()->addr; 1565bdd1243dSDimitry Andric if (auto *s = dyn_cast<InputSection>(&sec)) 1566bdd1243dSDimitry Andric secAddr += s->outSecOff; 15675f757f3fSDimitry Andric else if (auto *ehIn = dyn_cast<EhInputSection>(&sec)) 15685f757f3fSDimitry Andric secAddr += ehIn->getParent()->outSecOff; 1569bdd1243dSDimitry Andric uint64_t lastPPCRelaxedRelocOff = -1; 1570bdd1243dSDimitry Andric for (const Relocation &rel : sec.relocs()) { 1571bdd1243dSDimitry Andric uint8_t *loc = buf + rel.offset; 1572bdd1243dSDimitry Andric const uint64_t val = 1573bdd1243dSDimitry Andric sec.getRelocTargetVA(sec.file, rel.type, rel.addend, 1574bdd1243dSDimitry Andric secAddr + rel.offset, *rel.sym, rel.expr); 1575bdd1243dSDimitry Andric switch (rel.expr) { 1576bdd1243dSDimitry Andric case R_PPC64_RELAX_GOT_PC: { 1577bdd1243dSDimitry Andric // The R_PPC64_PCREL_OPT relocation must appear immediately after 1578bdd1243dSDimitry Andric // R_PPC64_GOT_PCREL34 in the relocations table at the same offset. 1579bdd1243dSDimitry Andric // We can only relax R_PPC64_PCREL_OPT if we have also relaxed 1580bdd1243dSDimitry Andric // the associated R_PPC64_GOT_PCREL34 since only the latter has an 1581bdd1243dSDimitry Andric // associated symbol. So save the offset when relaxing R_PPC64_GOT_PCREL34 1582bdd1243dSDimitry Andric // and only relax the other if the saved offset matches. 1583bdd1243dSDimitry Andric if (rel.type == R_PPC64_GOT_PCREL34) 1584bdd1243dSDimitry Andric lastPPCRelaxedRelocOff = rel.offset; 1585bdd1243dSDimitry Andric if (rel.type == R_PPC64_PCREL_OPT && rel.offset != lastPPCRelaxedRelocOff) 1586bdd1243dSDimitry Andric break; 1587bdd1243dSDimitry Andric relaxGot(loc, rel, val); 1588bdd1243dSDimitry Andric break; 1589bdd1243dSDimitry Andric } 1590bdd1243dSDimitry Andric case R_PPC64_RELAX_TOC: 1591bdd1243dSDimitry Andric // rel.sym refers to the STT_SECTION symbol associated to the .toc input 1592bdd1243dSDimitry Andric // section. If an R_PPC64_TOC16_LO (.toc + addend) references the TOC 1593bdd1243dSDimitry Andric // entry, there may be R_PPC64_TOC16_HA not paired with 1594bdd1243dSDimitry Andric // R_PPC64_TOC16_LO_DS. Don't relax. This loses some relaxation 1595bdd1243dSDimitry Andric // opportunities but is safe. 1596bdd1243dSDimitry Andric if (ppc64noTocRelax.count({rel.sym, rel.addend}) || 1597bdd1243dSDimitry Andric !tryRelaxPPC64TocIndirection(rel, loc)) 1598bdd1243dSDimitry Andric relocate(loc, rel, val); 1599bdd1243dSDimitry Andric break; 1600bdd1243dSDimitry Andric case R_PPC64_CALL: 1601bdd1243dSDimitry Andric // If this is a call to __tls_get_addr, it may be part of a TLS 1602bdd1243dSDimitry Andric // sequence that has been relaxed and turned into a nop. In this 1603bdd1243dSDimitry Andric // case, we don't want to handle it as a call. 1604bdd1243dSDimitry Andric if (read32(loc) == 0x60000000) // nop 1605bdd1243dSDimitry Andric break; 1606bdd1243dSDimitry Andric 1607bdd1243dSDimitry Andric // Patch a nop (0x60000000) to a ld. 16085f757f3fSDimitry Andric if (rel.sym->needsTocRestore()) { 1609bdd1243dSDimitry Andric // gcc/gfortran 5.4, 6.3 and earlier versions do not add nop for 1610bdd1243dSDimitry Andric // recursive calls even if the function is preemptible. This is not 1611bdd1243dSDimitry Andric // wrong in the common case where the function is not preempted at 1612bdd1243dSDimitry Andric // runtime. Just ignore. 1613bdd1243dSDimitry Andric if ((rel.offset + 8 > sec.content().size() || 1614bdd1243dSDimitry Andric read32(loc + 4) != 0x60000000) && 1615bdd1243dSDimitry Andric rel.sym->file != sec.file) { 1616bdd1243dSDimitry Andric // Use substr(6) to remove the "__plt_" prefix. 1617bdd1243dSDimitry Andric errorOrWarn(getErrorLocation(loc) + "call to " + 1618bdd1243dSDimitry Andric lld::toString(*rel.sym).substr(6) + 1619bdd1243dSDimitry Andric " lacks nop, can't restore toc"); 1620bdd1243dSDimitry Andric break; 1621bdd1243dSDimitry Andric } 1622bdd1243dSDimitry Andric write32(loc + 4, 0xe8410018); // ld %r2, 24(%r1) 1623bdd1243dSDimitry Andric } 1624bdd1243dSDimitry Andric relocate(loc, rel, val); 1625bdd1243dSDimitry Andric break; 1626bdd1243dSDimitry Andric case R_RELAX_TLS_GD_TO_IE: 1627bdd1243dSDimitry Andric case R_RELAX_TLS_GD_TO_IE_GOT_OFF: 1628bdd1243dSDimitry Andric relaxTlsGdToIe(loc, rel, val); 1629bdd1243dSDimitry Andric break; 1630bdd1243dSDimitry Andric case R_RELAX_TLS_GD_TO_LE: 1631bdd1243dSDimitry Andric relaxTlsGdToLe(loc, rel, val); 1632bdd1243dSDimitry Andric break; 1633bdd1243dSDimitry Andric case R_RELAX_TLS_LD_TO_LE_ABS: 1634bdd1243dSDimitry Andric relaxTlsLdToLe(loc, rel, val); 1635bdd1243dSDimitry Andric break; 1636bdd1243dSDimitry Andric case R_RELAX_TLS_IE_TO_LE: 1637bdd1243dSDimitry Andric relaxTlsIeToLe(loc, rel, val); 1638bdd1243dSDimitry Andric break; 1639bdd1243dSDimitry Andric default: 1640bdd1243dSDimitry Andric relocate(loc, rel, val); 1641bdd1243dSDimitry Andric break; 1642bdd1243dSDimitry Andric } 1643bdd1243dSDimitry Andric } 1644bdd1243dSDimitry Andric } 1645bdd1243dSDimitry Andric 16460b57cec5SDimitry Andric // The prologue for a split-stack function is expected to look roughly 16470b57cec5SDimitry Andric // like this: 16480b57cec5SDimitry Andric // .Lglobal_entry_point: 1649480093f4SDimitry Andric // # TOC pointer initialization. 16500b57cec5SDimitry Andric // ... 16510b57cec5SDimitry Andric // .Llocal_entry_point: 16520b57cec5SDimitry Andric // # load the __private_ss member of the threads tcbhead. 16530b57cec5SDimitry Andric // ld r0,-0x7000-64(r13) 16540b57cec5SDimitry Andric // # subtract the functions stack size from the stack pointer. 16550b57cec5SDimitry Andric // addis r12, r1, ha(-stack-frame size) 16560b57cec5SDimitry Andric // addi r12, r12, l(-stack-frame size) 16570b57cec5SDimitry Andric // # compare needed to actual and branch to allocate_more_stack if more 16580b57cec5SDimitry Andric // # space is needed, otherwise fallthrough to 'normal' function body. 16590b57cec5SDimitry Andric // cmpld cr7,r12,r0 16600b57cec5SDimitry Andric // blt- cr7, .Lallocate_more_stack 16610b57cec5SDimitry Andric // 16620b57cec5SDimitry Andric // -) The allocate_more_stack block might be placed after the split-stack 16630b57cec5SDimitry Andric // prologue and the `blt-` replaced with a `bge+ .Lnormal_func_body` 16640b57cec5SDimitry Andric // instead. 16650b57cec5SDimitry Andric // -) If either the addis or addi is not needed due to the stack size being 16660b57cec5SDimitry Andric // smaller then 32K or a multiple of 64K they will be replaced with a nop, 16670b57cec5SDimitry Andric // but there will always be 2 instructions the linker can overwrite for the 16680b57cec5SDimitry Andric // adjusted stack size. 16690b57cec5SDimitry Andric // 16700b57cec5SDimitry Andric // The linkers job here is to increase the stack size used in the addis/addi 16710b57cec5SDimitry Andric // pair by split-stack-size-adjust. 16720b57cec5SDimitry Andric // addis r12, r1, ha(-stack-frame size - split-stack-adjust-size) 16730b57cec5SDimitry Andric // addi r12, r12, l(-stack-frame size - split-stack-adjust-size) 16740b57cec5SDimitry Andric bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, 16750b57cec5SDimitry Andric uint8_t stOther) const { 16760b57cec5SDimitry Andric // If the caller has a global entry point adjust the buffer past it. The start 16770b57cec5SDimitry Andric // of the split-stack prologue will be at the local entry point. 16780b57cec5SDimitry Andric loc += getPPC64GlobalEntryToLocalEntryOffset(stOther); 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric // At the very least we expect to see a load of some split-stack data from the 16810b57cec5SDimitry Andric // tcb, and 2 instructions that calculate the ending stack address this 16820b57cec5SDimitry Andric // function will require. If there is not enough room for at least 3 16830b57cec5SDimitry Andric // instructions it can't be a split-stack prologue. 16840b57cec5SDimitry Andric if (loc + 12 >= end) 16850b57cec5SDimitry Andric return false; 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric // First instruction must be `ld r0, -0x7000-64(r13)` 16880b57cec5SDimitry Andric if (read32(loc) != 0xe80d8fc0) 16890b57cec5SDimitry Andric return false; 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric int16_t hiImm = 0; 16920b57cec5SDimitry Andric int16_t loImm = 0; 16930b57cec5SDimitry Andric // First instruction can be either an addis if the frame size is larger then 16940b57cec5SDimitry Andric // 32K, or an addi if the size is less then 32K. 16950b57cec5SDimitry Andric int32_t firstInstr = read32(loc + 4); 16960b57cec5SDimitry Andric if (getPrimaryOpCode(firstInstr) == 15) { 16970b57cec5SDimitry Andric hiImm = firstInstr & 0xFFFF; 16980b57cec5SDimitry Andric } else if (getPrimaryOpCode(firstInstr) == 14) { 16990b57cec5SDimitry Andric loImm = firstInstr & 0xFFFF; 17000b57cec5SDimitry Andric } else { 17010b57cec5SDimitry Andric return false; 17020b57cec5SDimitry Andric } 17030b57cec5SDimitry Andric 17040b57cec5SDimitry Andric // Second instruction is either an addi or a nop. If the first instruction was 17050b57cec5SDimitry Andric // an addi then LoImm is set and the second instruction must be a nop. 17060b57cec5SDimitry Andric uint32_t secondInstr = read32(loc + 8); 17070b57cec5SDimitry Andric if (!loImm && getPrimaryOpCode(secondInstr) == 14) { 17080b57cec5SDimitry Andric loImm = secondInstr & 0xFFFF; 1709e8d8bef9SDimitry Andric } else if (secondInstr != NOP) { 17100b57cec5SDimitry Andric return false; 17110b57cec5SDimitry Andric } 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric // The register operands of the first instruction should be the stack-pointer 17140b57cec5SDimitry Andric // (r1) as the input (RA) and r12 as the output (RT). If the second 17150b57cec5SDimitry Andric // instruction is not a nop, then it should use r12 as both input and output. 17160b57cec5SDimitry Andric auto checkRegOperands = [](uint32_t instr, uint8_t expectedRT, 17170b57cec5SDimitry Andric uint8_t expectedRA) { 17180b57cec5SDimitry Andric return ((instr & 0x3E00000) >> 21 == expectedRT) && 17190b57cec5SDimitry Andric ((instr & 0x1F0000) >> 16 == expectedRA); 17200b57cec5SDimitry Andric }; 17210b57cec5SDimitry Andric if (!checkRegOperands(firstInstr, 12, 1)) 17220b57cec5SDimitry Andric return false; 1723e8d8bef9SDimitry Andric if (secondInstr != NOP && !checkRegOperands(secondInstr, 12, 12)) 17240b57cec5SDimitry Andric return false; 17250b57cec5SDimitry Andric 17260b57cec5SDimitry Andric int32_t stackFrameSize = (hiImm * 65536) + loImm; 17270b57cec5SDimitry Andric // Check that the adjusted size doesn't overflow what we can represent with 2 17280b57cec5SDimitry Andric // instructions. 17290b57cec5SDimitry Andric if (stackFrameSize < config->splitStackAdjustSize + INT32_MIN) { 17300b57cec5SDimitry Andric error(getErrorLocation(loc) + "split-stack prologue adjustment overflows"); 17310b57cec5SDimitry Andric return false; 17320b57cec5SDimitry Andric } 17330b57cec5SDimitry Andric 17340b57cec5SDimitry Andric int32_t adjustedStackFrameSize = 17350b57cec5SDimitry Andric stackFrameSize - config->splitStackAdjustSize; 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric loImm = adjustedStackFrameSize & 0xFFFF; 17380b57cec5SDimitry Andric hiImm = (adjustedStackFrameSize + 0x8000) >> 16; 17390b57cec5SDimitry Andric if (hiImm) { 17400b57cec5SDimitry Andric write32(loc + 4, 0x3D810000 | (uint16_t)hiImm); 17410b57cec5SDimitry Andric // If the low immediate is zero the second instruction will be a nop. 1742e8d8bef9SDimitry Andric secondInstr = loImm ? 0x398C0000 | (uint16_t)loImm : NOP; 17430b57cec5SDimitry Andric write32(loc + 8, secondInstr); 17440b57cec5SDimitry Andric } else { 17450b57cec5SDimitry Andric // addi r12, r1, imm 17460b57cec5SDimitry Andric write32(loc + 4, (0x39810000) | (uint16_t)loImm); 1747e8d8bef9SDimitry Andric write32(loc + 8, NOP); 17480b57cec5SDimitry Andric } 17490b57cec5SDimitry Andric 17500b57cec5SDimitry Andric return true; 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric 17535ffd83dbSDimitry Andric TargetInfo *elf::getPPC64TargetInfo() { 17540b57cec5SDimitry Andric static PPC64 target; 17550b57cec5SDimitry Andric return ⌖ 17560b57cec5SDimitry Andric } 1757