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