1 //===- SPARCV9.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "InputFiles.h"
11 #include "SyntheticSections.h"
13 #include "lld/Common/ErrorHandler.h"
14 #include "llvm/Support/Endian.h"
17 using namespace llvm::support::endian;
18 using namespace llvm::ELF;
20 using namespace lld::elf;
23 class SPARCV9 final : public TargetInfo {
26 RelExpr getRelExpr(RelType type, const Symbol &s,
27 const uint8_t *loc) const override;
28 void writePlt(uint8_t *buf, const Symbol &sym,
29 uint64_t pltEntryAddr) const override;
30 void relocate(uint8_t *loc, const Relocation &rel,
31 uint64_t val) const override;
36 copyRel = R_SPARC_COPY;
37 gotRel = R_SPARC_GLOB_DAT;
38 noneRel = R_SPARC_NONE;
39 pltRel = R_SPARC_JMP_SLOT;
40 relativeRel = R_SPARC_RELATIVE;
41 symbolicRel = R_SPARC_64;
43 pltHeaderSize = 4 * pltEntrySize;
45 defaultCommonPageSize = 8192;
46 defaultMaxPageSize = 0x100000;
47 defaultImageBase = 0x100000;
50 RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
51 const uint8_t *loc) const {
79 case R_SPARC_TLS_LE_HIX22:
80 case R_SPARC_TLS_LE_LOX10:
83 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
84 ") against symbol " + toString(s));
89 void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
95 checkUInt(loc, val, 32, rel);
100 checkInt(loc, val, 32, rel);
103 case R_SPARC_WDISP30:
106 checkInt(loc, val, 32, rel);
107 write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
111 checkUInt(loc, val, 22, rel);
112 write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
118 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
122 checkUInt(loc, val >> 10, 22, rel);
123 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
125 case R_SPARC_WDISP19:
127 checkInt(loc, val, 21, rel);
128 write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
133 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
137 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));
146 checkUInt(loc, val >> 42, 22, rel);
147 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff));
151 write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff));
155 checkUInt(loc, val >> 22, 22, rel);
156 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));
160 write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));
164 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));
166 case R_SPARC_TLS_LE_HIX22:
168 write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
170 case R_SPARC_TLS_LE_LOX10:
172 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);
175 llvm_unreachable("unknown relocation");
179 void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,
180 uint64_t pltEntryAddr) const {
181 const uint8_t pltData[] = {
182 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1
183 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1
184 0x01, 0x00, 0x00, 0x00, // nop
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
191 memcpy(buf, pltData, sizeof(pltData));
193 uint64_t off = pltEntryAddr - in.plt->getVA();
194 relocateNoSym(buf, R_SPARC_22, off);
195 relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
198 TargetInfo *elf::getSPARCV9TargetInfo() {
199 static SPARCV9 target;