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