10cc14835SRui Ueyama //===- SPARCV9.cpp --------------------------------------------------------===// 20cc14835SRui Ueyama // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60cc14835SRui Ueyama // 70cc14835SRui Ueyama //===----------------------------------------------------------------------===// 80cc14835SRui Ueyama 90cc14835SRui Ueyama #include "Symbols.h" 100cc14835SRui Ueyama #include "SyntheticSections.h" 110cc14835SRui Ueyama #include "Target.h" 12b8a59c8aSBob Haarman #include "lld/Common/ErrorHandler.h" 130cc14835SRui Ueyama #include "llvm/Support/Endian.h" 140cc14835SRui Ueyama 150cc14835SRui Ueyama using namespace llvm; 160cc14835SRui Ueyama using namespace llvm::support::endian; 170cc14835SRui Ueyama using namespace llvm::ELF; 1807837b8fSFangrui Song using namespace lld; 1907837b8fSFangrui Song using namespace lld::elf; 200cc14835SRui Ueyama 210cc14835SRui Ueyama namespace { 220cc14835SRui Ueyama class SPARCV9 final : public TargetInfo { 230cc14835SRui Ueyama public: 24c3e4998cSFangrui Song SPARCV9(Ctx &); 253837f427SRui Ueyama RelExpr getRelExpr(RelType type, const Symbol &s, 263837f427SRui Ueyama const uint8_t *loc) const override; 2737b28080SFangrui Song void writePlt(uint8_t *buf, const Symbol &sym, 2837b28080SFangrui Song uint64_t pltEntryAddr) const override; 29deb5819dSFangrui Song void relocate(uint8_t *loc, const Relocation &rel, 30deb5819dSFangrui Song uint64_t val) const override; 310cc14835SRui Ueyama }; 320cc14835SRui Ueyama } // namespace 330cc14835SRui Ueyama 34c3e4998cSFangrui Song SPARCV9::SPARCV9(Ctx &ctx) : TargetInfo(ctx) { 353837f427SRui Ueyama copyRel = R_SPARC_COPY; 363837f427SRui Ueyama gotRel = R_SPARC_GLOB_DAT; 373837f427SRui Ueyama pltRel = R_SPARC_JMP_SLOT; 383837f427SRui Ueyama relativeRel = R_SPARC_RELATIVE; 393837f427SRui Ueyama symbolicRel = R_SPARC_64; 403837f427SRui Ueyama pltEntrySize = 32; 413837f427SRui Ueyama pltHeaderSize = 4 * pltEntrySize; 420cc14835SRui Ueyama 433837f427SRui Ueyama defaultCommonPageSize = 8192; 443837f427SRui Ueyama defaultMaxPageSize = 0x100000; 453837f427SRui Ueyama defaultImageBase = 0x100000; 460cc14835SRui Ueyama } 470cc14835SRui Ueyama 483837f427SRui Ueyama RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, 493837f427SRui Ueyama const uint8_t *loc) const { 503837f427SRui Ueyama switch (type) { 510cc14835SRui Ueyama case R_SPARC_32: 520cc14835SRui Ueyama case R_SPARC_UA32: 530cc14835SRui Ueyama case R_SPARC_64: 540cc14835SRui Ueyama case R_SPARC_UA64: 55aff950e9SLemonBoy case R_SPARC_H44: 56aff950e9SLemonBoy case R_SPARC_M44: 57aff950e9SLemonBoy case R_SPARC_L44: 58aff950e9SLemonBoy case R_SPARC_HH22: 59aff950e9SLemonBoy case R_SPARC_HM10: 60aff950e9SLemonBoy case R_SPARC_LM22: 61aff950e9SLemonBoy case R_SPARC_HI22: 62aff950e9SLemonBoy case R_SPARC_LO10: 630cc14835SRui Ueyama return R_ABS; 640cc14835SRui Ueyama case R_SPARC_PC10: 650cc14835SRui Ueyama case R_SPARC_PC22: 660cc14835SRui Ueyama case R_SPARC_DISP32: 670cc14835SRui Ueyama case R_SPARC_WDISP30: 680cc14835SRui Ueyama return R_PC; 690cc14835SRui Ueyama case R_SPARC_GOT10: 700cc14835SRui Ueyama return R_GOT_OFF; 710cc14835SRui Ueyama case R_SPARC_GOT22: 720cc14835SRui Ueyama return R_GOT_OFF; 730cc14835SRui Ueyama case R_SPARC_WPLT30: 740cc14835SRui Ueyama return R_PLT_PC; 750cc14835SRui Ueyama case R_SPARC_NONE: 760cc14835SRui Ueyama return R_NONE; 77aff950e9SLemonBoy case R_SPARC_TLS_LE_HIX22: 78aff950e9SLemonBoy case R_SPARC_TLS_LE_LOX10: 7922c1bd57SFangrui Song return R_TPREL; 800cc14835SRui Ueyama default: 81*c1a6defdSFangrui Song Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v 8209c2c5e1SFangrui Song << ") against symbol " << &s; 83b8b81e9bSRui Ueyama return R_NONE; 840cc14835SRui Ueyama } 850cc14835SRui Ueyama } 860cc14835SRui Ueyama 87deb5819dSFangrui Song void SPARCV9::relocate(uint8_t *loc, const Relocation &rel, 88deb5819dSFangrui Song uint64_t val) const { 89deb5819dSFangrui Song switch (rel.type) { 900cc14835SRui Ueyama case R_SPARC_32: 910cc14835SRui Ueyama case R_SPARC_UA32: 920cc14835SRui Ueyama // V-word32 932c5dd03fSFangrui Song checkUInt(ctx, loc, val, 32, rel); 943837f427SRui Ueyama write32be(loc, val); 950cc14835SRui Ueyama break; 960cc14835SRui Ueyama case R_SPARC_DISP32: 970cc14835SRui Ueyama // V-disp32 982c5dd03fSFangrui Song checkInt(ctx, loc, val, 32, rel); 993837f427SRui Ueyama write32be(loc, val); 1000cc14835SRui Ueyama break; 1010cc14835SRui Ueyama case R_SPARC_WDISP30: 1020cc14835SRui Ueyama case R_SPARC_WPLT30: 1030cc14835SRui Ueyama // V-disp30 1042c5dd03fSFangrui Song checkInt(ctx, loc, val, 32, rel); 1053837f427SRui Ueyama write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); 1060cc14835SRui Ueyama break; 1070cc14835SRui Ueyama case R_SPARC_22: 1080cc14835SRui Ueyama // V-imm22 1092c5dd03fSFangrui Song checkUInt(ctx, loc, val, 22, rel); 1103837f427SRui Ueyama write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); 1110cc14835SRui Ueyama break; 1120cc14835SRui Ueyama case R_SPARC_GOT22: 1130cc14835SRui Ueyama case R_SPARC_PC22: 114aff950e9SLemonBoy case R_SPARC_LM22: 1150cc14835SRui Ueyama // T-imm22 1163837f427SRui Ueyama write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); 1170cc14835SRui Ueyama break; 118aff950e9SLemonBoy case R_SPARC_HI22: 119aff950e9SLemonBoy // V-imm22 1202c5dd03fSFangrui Song checkUInt(ctx, loc, val >> 10, 22, rel); 121aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); 122aff950e9SLemonBoy break; 1230cc14835SRui Ueyama case R_SPARC_WDISP19: 1240cc14835SRui Ueyama // V-disp19 1252c5dd03fSFangrui Song checkInt(ctx, loc, val, 21, rel); 1263837f427SRui Ueyama write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); 1270cc14835SRui Ueyama break; 1280cc14835SRui Ueyama case R_SPARC_GOT10: 1290cc14835SRui Ueyama case R_SPARC_PC10: 1300cc14835SRui Ueyama // T-simm10 1313837f427SRui Ueyama write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); 1320cc14835SRui Ueyama break; 133aff950e9SLemonBoy case R_SPARC_LO10: 134aff950e9SLemonBoy // T-simm13 135aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff)); 136aff950e9SLemonBoy break; 1370cc14835SRui Ueyama case R_SPARC_64: 1380cc14835SRui Ueyama case R_SPARC_UA64: 1390cc14835SRui Ueyama // V-xword64 1403837f427SRui Ueyama write64be(loc, val); 1410cc14835SRui Ueyama break; 142aff950e9SLemonBoy case R_SPARC_HH22: 143aff950e9SLemonBoy // V-imm22 1442c5dd03fSFangrui Song checkUInt(ctx, loc, val >> 42, 22, rel); 145aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff)); 146aff950e9SLemonBoy break; 147aff950e9SLemonBoy case R_SPARC_HM10: 148aff950e9SLemonBoy // T-simm13 149aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff)); 150aff950e9SLemonBoy break; 151aff950e9SLemonBoy case R_SPARC_H44: 152aff950e9SLemonBoy // V-imm22 1532c5dd03fSFangrui Song checkUInt(ctx, loc, val >> 22, 22, rel); 154aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff)); 155aff950e9SLemonBoy break; 156aff950e9SLemonBoy case R_SPARC_M44: 157aff950e9SLemonBoy // T-imm10 158aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff)); 159aff950e9SLemonBoy break; 160aff950e9SLemonBoy case R_SPARC_L44: 161aff950e9SLemonBoy // T-imm13 162aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff)); 163aff950e9SLemonBoy break; 164aff950e9SLemonBoy case R_SPARC_TLS_LE_HIX22: 165aff950e9SLemonBoy // T-imm22 166aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff)); 167aff950e9SLemonBoy break; 168aff950e9SLemonBoy case R_SPARC_TLS_LE_LOX10: 169aff950e9SLemonBoy // T-simm13 170aff950e9SLemonBoy write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00); 171aff950e9SLemonBoy break; 1720cc14835SRui Ueyama default: 173b8b81e9bSRui Ueyama llvm_unreachable("unknown relocation"); 1740cc14835SRui Ueyama } 1750cc14835SRui Ueyama } 1760cc14835SRui Ueyama 17737b28080SFangrui Song void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/, 17837b28080SFangrui Song uint64_t pltEntryAddr) const { 1793837f427SRui Ueyama const uint8_t pltData[] = { 1800cc14835SRui Ueyama 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1 1810cc14835SRui Ueyama 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1 1820cc14835SRui Ueyama 0x01, 0x00, 0x00, 0x00, // nop 1830cc14835SRui Ueyama 0x01, 0x00, 0x00, 0x00, // nop 1840cc14835SRui Ueyama 0x01, 0x00, 0x00, 0x00, // nop 1850cc14835SRui Ueyama 0x01, 0x00, 0x00, 0x00, // nop 1860cc14835SRui Ueyama 0x01, 0x00, 0x00, 0x00, // nop 1870cc14835SRui Ueyama 0x01, 0x00, 0x00, 0x00 // nop 1880cc14835SRui Ueyama }; 1893837f427SRui Ueyama memcpy(buf, pltData, sizeof(pltData)); 1900cc14835SRui Ueyama 191e88b7ff0SFangrui Song uint64_t off = pltEntryAddr - ctx.in.plt->getVA(); 192deb5819dSFangrui Song relocateNoSym(buf, R_SPARC_22, off); 193deb5819dSFangrui Song relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); 1940cc14835SRui Ueyama } 1950cc14835SRui Ueyama 196e1a073c9SFangrui Song void elf::setSPARCV9TargetInfo(Ctx &ctx) { ctx.target.reset(new SPARCV9(ctx)); } 197