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