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   case R_SPARC_H44:
59   case R_SPARC_M44:
60   case R_SPARC_L44:
61   case R_SPARC_HH22:
62   case R_SPARC_HM10:
63   case R_SPARC_LM22:
64   case R_SPARC_HI22:
65   case R_SPARC_LO10:
66     return R_ABS;
67   case R_SPARC_PC10:
68   case R_SPARC_PC22:
69   case R_SPARC_DISP32:
70   case R_SPARC_WDISP30:
71     return R_PC;
72   case R_SPARC_GOT10:
73     return R_GOT_OFF;
74   case R_SPARC_GOT22:
75     return R_GOT_OFF;
76   case R_SPARC_WPLT30:
77     return R_PLT_PC;
78   case R_SPARC_NONE:
79     return R_NONE;
80   case R_SPARC_TLS_LE_HIX22:
81   case R_SPARC_TLS_LE_LOX10:
82     return R_TLS;
83   default:
84     error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
85           ") against symbol " + toString(s));
86     return R_NONE;
87   }
88 }
89 
90 void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
91                        uint64_t val) const {
92   switch (rel.type) {
93   case R_SPARC_32:
94   case R_SPARC_UA32:
95     // V-word32
96     checkUInt(loc, val, 32, rel);
97     write32be(loc, val);
98     break;
99   case R_SPARC_DISP32:
100     // V-disp32
101     checkInt(loc, val, 32, rel);
102     write32be(loc, val);
103     break;
104   case R_SPARC_WDISP30:
105   case R_SPARC_WPLT30:
106     // V-disp30
107     checkInt(loc, val, 32, rel);
108     write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
109     break;
110   case R_SPARC_22:
111     // V-imm22
112     checkUInt(loc, val, 22, rel);
113     write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
114     break;
115   case R_SPARC_GOT22:
116   case R_SPARC_PC22:
117   case R_SPARC_LM22:
118     // T-imm22
119     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
120     break;
121   case R_SPARC_HI22:
122     // V-imm22
123     checkUInt(loc, val >> 10, 22, rel);
124     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
125     break;
126   case R_SPARC_WDISP19:
127     // V-disp19
128     checkInt(loc, val, 21, rel);
129     write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
130     break;
131   case R_SPARC_GOT10:
132   case R_SPARC_PC10:
133     // T-simm10
134     write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
135     break;
136   case R_SPARC_LO10:
137     // T-simm13
138     write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));
139     break;
140   case R_SPARC_64:
141   case R_SPARC_UA64:
142     // V-xword64
143     write64be(loc, val);
144     break;
145   case R_SPARC_HH22:
146     // V-imm22
147     checkUInt(loc, val >> 42, 22, rel);
148     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff));
149     break;
150   case R_SPARC_HM10:
151     // T-simm13
152     write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff));
153     break;
154   case R_SPARC_H44:
155     // V-imm22
156     checkUInt(loc, val >> 22, 22, rel);
157     write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));
158     break;
159   case R_SPARC_M44:
160     // T-imm10
161     write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));
162     break;
163   case R_SPARC_L44:
164     // T-imm13
165     write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));
166     break;
167   case R_SPARC_TLS_LE_HIX22:
168     // T-imm22
169     write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
170     break;
171   case R_SPARC_TLS_LE_LOX10:
172     // T-simm13
173     write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);
174     break;
175   default:
176     llvm_unreachable("unknown relocation");
177   }
178 }
179 
180 void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,
181                        uint64_t pltEntryAddr) const {
182   const uint8_t pltData[] = {
183       0x03, 0x00, 0x00, 0x00, // sethi   (. - .PLT0), %g1
184       0x30, 0x68, 0x00, 0x00, // ba,a    %xcc, .PLT1
185       0x01, 0x00, 0x00, 0x00, // nop
186       0x01, 0x00, 0x00, 0x00, // nop
187       0x01, 0x00, 0x00, 0x00, // nop
188       0x01, 0x00, 0x00, 0x00, // nop
189       0x01, 0x00, 0x00, 0x00, // nop
190       0x01, 0x00, 0x00, 0x00  // nop
191   };
192   memcpy(buf, pltData, sizeof(pltData));
193 
194   uint64_t off = pltEntryAddr - in.plt->getVA();
195   relocateNoSym(buf, R_SPARC_22, off);
196   relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
197 }
198 
199 TargetInfo *getSPARCV9TargetInfo() {
200   static SPARCV9 target;
201   return ⌖
202 }
203 
204 } // namespace elf
205 } // namespace lld
206