1 //===- SPARCV9.cpp --------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Symbols.h" 10 #include "SyntheticSections.h" 11 #include "Target.h" 12 #include "llvm/Support/Endian.h" 13 14 using namespace llvm; 15 using namespace llvm::support::endian; 16 using namespace llvm::ELF; 17 using namespace lld; 18 using namespace lld::elf; 19 20 namespace { 21 class SPARCV9 final : public TargetInfo { 22 public: 23 SPARCV9(Ctx &); 24 RelExpr getRelExpr(RelType type, const Symbol &s, 25 const uint8_t *loc) const override; 26 void writePlt(uint8_t *buf, const Symbol &sym, 27 uint64_t pltEntryAddr) const override; 28 void relocate(uint8_t *loc, const Relocation &rel, 29 uint64_t val) const override; 30 }; 31 } // namespace 32 33 SPARCV9::SPARCV9(Ctx &ctx) : TargetInfo(ctx) { 34 copyRel = R_SPARC_COPY; 35 gotRel = R_SPARC_GLOB_DAT; 36 pltRel = R_SPARC_JMP_SLOT; 37 relativeRel = R_SPARC_RELATIVE; 38 symbolicRel = R_SPARC_64; 39 pltEntrySize = 32; 40 pltHeaderSize = 4 * pltEntrySize; 41 42 defaultCommonPageSize = 8192; 43 defaultMaxPageSize = 0x100000; 44 defaultImageBase = 0x100000; 45 } 46 47 RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, 48 const uint8_t *loc) const { 49 switch (type) { 50 case R_SPARC_32: 51 case R_SPARC_UA32: 52 case R_SPARC_64: 53 case R_SPARC_UA64: 54 case R_SPARC_H44: 55 case R_SPARC_M44: 56 case R_SPARC_L44: 57 case R_SPARC_HH22: 58 case R_SPARC_HM10: 59 case R_SPARC_LM22: 60 case R_SPARC_HI22: 61 case R_SPARC_LO10: 62 return R_ABS; 63 case R_SPARC_PC10: 64 case R_SPARC_PC22: 65 case R_SPARC_DISP32: 66 case R_SPARC_WDISP30: 67 return R_PC; 68 case R_SPARC_GOT10: 69 return R_GOT_OFF; 70 case R_SPARC_GOT22: 71 return R_GOT_OFF; 72 case R_SPARC_WPLT30: 73 return R_PLT_PC; 74 case R_SPARC_NONE: 75 return R_NONE; 76 case R_SPARC_TLS_LE_HIX22: 77 case R_SPARC_TLS_LE_LOX10: 78 return R_TPREL; 79 default: 80 Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v 81 << ") against symbol " << &s; 82 return R_NONE; 83 } 84 } 85 86 void SPARCV9::relocate(uint8_t *loc, const Relocation &rel, 87 uint64_t val) const { 88 switch (rel.type) { 89 case R_SPARC_32: 90 case R_SPARC_UA32: 91 // V-word32 92 checkUInt(ctx, loc, val, 32, rel); 93 write32be(loc, val); 94 break; 95 case R_SPARC_DISP32: 96 // V-disp32 97 checkInt(ctx, loc, val, 32, rel); 98 write32be(loc, val); 99 break; 100 case R_SPARC_WDISP30: 101 case R_SPARC_WPLT30: 102 // V-disp30 103 checkInt(ctx, loc, val, 32, rel); 104 write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); 105 break; 106 case R_SPARC_22: 107 // V-imm22 108 checkUInt(ctx, loc, val, 22, rel); 109 write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); 110 break; 111 case R_SPARC_GOT22: 112 case R_SPARC_PC22: 113 case R_SPARC_LM22: 114 // T-imm22 115 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); 116 break; 117 case R_SPARC_HI22: 118 // V-imm22 119 checkUInt(ctx, loc, val >> 10, 22, rel); 120 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); 121 break; 122 case R_SPARC_WDISP19: 123 // V-disp19 124 checkInt(ctx, loc, val, 21, rel); 125 write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); 126 break; 127 case R_SPARC_GOT10: 128 case R_SPARC_PC10: 129 // T-simm10 130 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); 131 break; 132 case R_SPARC_LO10: 133 // T-simm13 134 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff)); 135 break; 136 case R_SPARC_64: 137 case R_SPARC_UA64: 138 // V-xword64 139 write64be(loc, val); 140 break; 141 case R_SPARC_HH22: 142 // V-imm22 143 checkUInt(ctx, loc, val >> 42, 22, rel); 144 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff)); 145 break; 146 case R_SPARC_HM10: 147 // T-simm13 148 write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff)); 149 break; 150 case R_SPARC_H44: 151 // V-imm22 152 checkUInt(ctx, loc, val >> 22, 22, rel); 153 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff)); 154 break; 155 case R_SPARC_M44: 156 // T-imm10 157 write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff)); 158 break; 159 case R_SPARC_L44: 160 // T-imm13 161 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff)); 162 break; 163 case R_SPARC_TLS_LE_HIX22: 164 // T-imm22 165 write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff)); 166 break; 167 case R_SPARC_TLS_LE_LOX10: 168 // T-simm13 169 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00); 170 break; 171 default: 172 llvm_unreachable("unknown relocation"); 173 } 174 } 175 176 void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/, 177 uint64_t pltEntryAddr) const { 178 const uint8_t pltData[] = { 179 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1 180 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1 181 0x01, 0x00, 0x00, 0x00, // nop 182 0x01, 0x00, 0x00, 0x00, // nop 183 0x01, 0x00, 0x00, 0x00, // nop 184 0x01, 0x00, 0x00, 0x00, // nop 185 0x01, 0x00, 0x00, 0x00, // nop 186 0x01, 0x00, 0x00, 0x00 // nop 187 }; 188 memcpy(buf, pltData, sizeof(pltData)); 189 190 uint64_t off = pltEntryAddr - ctx.in.plt->getVA(); 191 relocateNoSym(buf, R_SPARC_22, off); 192 relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); 193 } 194 195 void elf::setSPARCV9TargetInfo(Ctx &ctx) { ctx.target.reset(new SPARCV9(ctx)); } 196