196 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Symbols.h"10#include "SyntheticSections.h"11#include "Target.h"12#include "llvm/Support/Endian.h"13 14using namespace llvm;15using namespace llvm::support::endian;16using namespace llvm::ELF;17using namespace lld;18using namespace lld::elf;19 20namespace {21class SPARCV9 final : public TargetInfo {22public: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} // namespace32 33SPARCV9::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 47RelExpr 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.v81 << ") against symbol " << &s;82 return R_NONE;83 }84}85 86void 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-word3292 checkUInt(ctx, loc, val, 32, rel);93 write32be(loc, val);94 break;95 case R_SPARC_DISP32:96 // V-disp3297 checkInt(ctx, loc, val, 32, rel);98 write32be(loc, val);99 break;100 case R_SPARC_WDISP30:101 case R_SPARC_WPLT30:102 // V-disp30103 checkInt(ctx, loc, val, 32, rel);104 write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));105 break;106 case R_SPARC_22:107 // V-imm22108 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-imm22115 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));116 break;117 case R_SPARC_HI22:118 // V-imm22119 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-disp19124 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-simm10130 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));131 break;132 case R_SPARC_LO10:133 // T-simm13134 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));135 break;136 case R_SPARC_64:137 case R_SPARC_UA64:138 // V-xword64139 write64be(loc, val);140 break;141 case R_SPARC_HH22:142 // V-imm22143 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-simm13148 write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff));149 break;150 case R_SPARC_H44:151 // V-imm22152 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-imm10157 write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));158 break;159 case R_SPARC_L44:160 // T-imm13161 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));162 break;163 case R_SPARC_TLS_LE_HIX22:164 // T-imm22165 write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));166 break;167 case R_SPARC_TLS_LE_LOX10:168 // T-simm13169 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);170 break;171 default:172 llvm_unreachable("unknown relocation");173 }174}175 176void 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), %g1180 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1181 0x01, 0x00, 0x00, 0x00, // nop182 0x01, 0x00, 0x00, 0x00, // nop183 0x01, 0x00, 0x00, 0x00, // nop184 0x01, 0x00, 0x00, 0x00, // nop185 0x01, 0x00, 0x00, 0x00, // nop186 0x01, 0x00, 0x00, 0x00 // nop187 };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 195void elf::setSPARCV9TargetInfo(Ctx &ctx) { ctx.target.reset(new SPARCV9(ctx)); }196