xref: /llvm-project/lld/ELF/Arch/SPARCV9.cpp (revision c1a6defd9ff1540638d660888c5f32ea5cf4fa7d)
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