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, uint64_t gotEntryAddr, uint64_t pltEntryAddr, 29 int32_t index, unsigned relOff) const override; 30 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; 31 }; 32 } // namespace 33 34 SPARCV9::SPARCV9() { 35 copyRel = R_SPARC_COPY; 36 gotRel = R_SPARC_GLOB_DAT; 37 noneRel = R_SPARC_NONE; 38 pltRel = R_SPARC_JMP_SLOT; 39 relativeRel = R_SPARC_RELATIVE; 40 symbolicRel = R_SPARC_64; 41 pltEntrySize = 32; 42 pltHeaderSize = 4 * pltEntrySize; 43 44 defaultCommonPageSize = 8192; 45 defaultMaxPageSize = 0x100000; 46 defaultImageBase = 0x100000; 47 } 48 49 RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, 50 const uint8_t *loc) const { 51 switch (type) { 52 case R_SPARC_32: 53 case R_SPARC_UA32: 54 case R_SPARC_64: 55 case R_SPARC_UA64: 56 return R_ABS; 57 case R_SPARC_PC10: 58 case R_SPARC_PC22: 59 case R_SPARC_DISP32: 60 case R_SPARC_WDISP30: 61 return R_PC; 62 case R_SPARC_GOT10: 63 return R_GOT_OFF; 64 case R_SPARC_GOT22: 65 return R_GOT_OFF; 66 case R_SPARC_WPLT30: 67 return R_PLT_PC; 68 case R_SPARC_NONE: 69 return R_NONE; 70 default: 71 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 72 ") against symbol " + toString(s)); 73 return R_NONE; 74 } 75 } 76 77 void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { 78 switch (type) { 79 case R_SPARC_32: 80 case R_SPARC_UA32: 81 // V-word32 82 checkUInt(loc, val, 32, type); 83 write32be(loc, val); 84 break; 85 case R_SPARC_DISP32: 86 // V-disp32 87 checkInt(loc, val, 32, type); 88 write32be(loc, val); 89 break; 90 case R_SPARC_WDISP30: 91 case R_SPARC_WPLT30: 92 // V-disp30 93 checkInt(loc, val, 32, type); 94 write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); 95 break; 96 case R_SPARC_22: 97 // V-imm22 98 checkUInt(loc, val, 22, type); 99 write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); 100 break; 101 case R_SPARC_GOT22: 102 case R_SPARC_PC22: 103 // T-imm22 104 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); 105 break; 106 case R_SPARC_WDISP19: 107 // V-disp19 108 checkInt(loc, val, 21, type); 109 write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); 110 break; 111 case R_SPARC_GOT10: 112 case R_SPARC_PC10: 113 // T-simm10 114 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); 115 break; 116 case R_SPARC_64: 117 case R_SPARC_UA64: 118 // V-xword64 119 write64be(loc, val); 120 break; 121 default: 122 llvm_unreachable("unknown relocation"); 123 } 124 } 125 126 void SPARCV9::writePlt(uint8_t *buf, uint64_t gotEntryAddr, 127 uint64_t pltEntryAddr, int32_t index, 128 unsigned relOff) const { 129 const uint8_t pltData[] = { 130 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1 131 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1 132 0x01, 0x00, 0x00, 0x00, // nop 133 0x01, 0x00, 0x00, 0x00, // nop 134 0x01, 0x00, 0x00, 0x00, // nop 135 0x01, 0x00, 0x00, 0x00, // nop 136 0x01, 0x00, 0x00, 0x00, // nop 137 0x01, 0x00, 0x00, 0x00 // nop 138 }; 139 memcpy(buf, pltData, sizeof(pltData)); 140 141 uint64_t off = pltHeaderSize + pltEntrySize * index; 142 relocateOne(buf, R_SPARC_22, off); 143 relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); 144 } 145 146 TargetInfo *elf::getSPARCV9TargetInfo() { 147 static SPARCV9 target; 148 return ⌖ 149 } 150