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