1ece8a530Spatrick //===- SPARCV9.cpp --------------------------------------------------------===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick
9ece8a530Spatrick #include "Symbols.h"
10ece8a530Spatrick #include "SyntheticSections.h"
11ece8a530Spatrick #include "Target.h"
12ece8a530Spatrick #include "lld/Common/ErrorHandler.h"
13ece8a530Spatrick #include "llvm/Support/Endian.h"
14ece8a530Spatrick
15ece8a530Spatrick using namespace llvm;
16ece8a530Spatrick using namespace llvm::support::endian;
17ece8a530Spatrick using namespace llvm::ELF;
18bb684c34Spatrick using namespace lld;
19bb684c34Spatrick using namespace lld::elf;
20ece8a530Spatrick
21ece8a530Spatrick namespace {
22ece8a530Spatrick class SPARCV9 final : public TargetInfo {
23ece8a530Spatrick public:
24ece8a530Spatrick SPARCV9();
25ece8a530Spatrick RelExpr getRelExpr(RelType type, const Symbol &s,
26ece8a530Spatrick const uint8_t *loc) const override;
27ece8a530Spatrick void writePlt(uint8_t *buf, const Symbol &sym,
28ece8a530Spatrick uint64_t pltEntryAddr) const override;
29bb684c34Spatrick void relocate(uint8_t *loc, const Relocation &rel,
30bb684c34Spatrick uint64_t val) const override;
31ece8a530Spatrick };
32ece8a530Spatrick } // namespace
33ece8a530Spatrick
SPARCV9()34ece8a530Spatrick SPARCV9::SPARCV9() {
35ece8a530Spatrick copyRel = R_SPARC_COPY;
36ece8a530Spatrick gotRel = R_SPARC_GLOB_DAT;
37ece8a530Spatrick pltRel = R_SPARC_JMP_SLOT;
38ece8a530Spatrick relativeRel = R_SPARC_RELATIVE;
39ece8a530Spatrick symbolicRel = R_SPARC_64;
40ece8a530Spatrick pltEntrySize = 32;
41ece8a530Spatrick pltHeaderSize = 4 * pltEntrySize;
42ece8a530Spatrick
43ece8a530Spatrick defaultCommonPageSize = 8192;
44ece8a530Spatrick defaultMaxPageSize = 0x100000;
45ece8a530Spatrick defaultImageBase = 0x100000;
46ece8a530Spatrick }
47ece8a530Spatrick
getRelExpr(RelType type,const Symbol & s,const uint8_t * loc) const48ece8a530Spatrick RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
49ece8a530Spatrick const uint8_t *loc) const {
50ece8a530Spatrick switch (type) {
51ece8a530Spatrick case R_SPARC_32:
52ece8a530Spatrick case R_SPARC_UA32:
53ece8a530Spatrick case R_SPARC_64:
54ece8a530Spatrick case R_SPARC_UA64:
55bb684c34Spatrick case R_SPARC_H44:
56bb684c34Spatrick case R_SPARC_M44:
57bb684c34Spatrick case R_SPARC_L44:
58bb684c34Spatrick case R_SPARC_HH22:
59bb684c34Spatrick case R_SPARC_HM10:
60bb684c34Spatrick case R_SPARC_LM22:
61bb684c34Spatrick case R_SPARC_HI22:
62bb684c34Spatrick case R_SPARC_LO10:
63ece8a530Spatrick return R_ABS;
64ece8a530Spatrick case R_SPARC_PC10:
65ece8a530Spatrick case R_SPARC_PC22:
66ece8a530Spatrick case R_SPARC_DISP32:
67ece8a530Spatrick case R_SPARC_WDISP30:
68ece8a530Spatrick return R_PC;
69ece8a530Spatrick case R_SPARC_GOT10:
70ece8a530Spatrick return R_GOT_OFF;
71ece8a530Spatrick case R_SPARC_GOT22:
72ece8a530Spatrick return R_GOT_OFF;
73ece8a530Spatrick case R_SPARC_WPLT30:
74ece8a530Spatrick return R_PLT_PC;
75ece8a530Spatrick case R_SPARC_NONE:
76ece8a530Spatrick return R_NONE;
77bb684c34Spatrick case R_SPARC_TLS_LE_HIX22:
78bb684c34Spatrick case R_SPARC_TLS_LE_LOX10:
79*1cf9926bSpatrick return R_TPREL;
80ece8a530Spatrick default:
81ece8a530Spatrick error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
82ece8a530Spatrick ") against symbol " + toString(s));
83ece8a530Spatrick return R_NONE;
84ece8a530Spatrick }
85ece8a530Spatrick }
86ece8a530Spatrick
relocate(uint8_t * loc,const Relocation & rel,uint64_t val) const87bb684c34Spatrick void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
88bb684c34Spatrick uint64_t val) const {
89bb684c34Spatrick switch (rel.type) {
90ece8a530Spatrick case R_SPARC_32:
91ece8a530Spatrick case R_SPARC_UA32:
92ece8a530Spatrick // V-word32
93bb684c34Spatrick checkUInt(loc, val, 32, rel);
94ece8a530Spatrick write32be(loc, val);
95ece8a530Spatrick break;
96ece8a530Spatrick case R_SPARC_DISP32:
97ece8a530Spatrick // V-disp32
98bb684c34Spatrick checkInt(loc, val, 32, rel);
99ece8a530Spatrick write32be(loc, val);
100ece8a530Spatrick break;
101ece8a530Spatrick case R_SPARC_WDISP30:
102ece8a530Spatrick case R_SPARC_WPLT30:
103ece8a530Spatrick // V-disp30
104bb684c34Spatrick checkInt(loc, val, 32, rel);
105ece8a530Spatrick write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
106ece8a530Spatrick break;
107ece8a530Spatrick case R_SPARC_22:
108ece8a530Spatrick // V-imm22
109bb684c34Spatrick checkUInt(loc, val, 22, rel);
110ece8a530Spatrick write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
111ece8a530Spatrick break;
112ece8a530Spatrick case R_SPARC_GOT22:
113ece8a530Spatrick case R_SPARC_PC22:
114bb684c34Spatrick case R_SPARC_LM22:
115ece8a530Spatrick // T-imm22
116ece8a530Spatrick write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
117ece8a530Spatrick break;
118bb684c34Spatrick case R_SPARC_HI22:
119bb684c34Spatrick // V-imm22
120bb684c34Spatrick checkUInt(loc, val >> 10, 22, rel);
121bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
122bb684c34Spatrick break;
123ece8a530Spatrick case R_SPARC_WDISP19:
124ece8a530Spatrick // V-disp19
125bb684c34Spatrick checkInt(loc, val, 21, rel);
126ece8a530Spatrick write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
127ece8a530Spatrick break;
128ece8a530Spatrick case R_SPARC_GOT10:
129ece8a530Spatrick case R_SPARC_PC10:
130ece8a530Spatrick // T-simm10
131ece8a530Spatrick write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
132ece8a530Spatrick break;
133bb684c34Spatrick case R_SPARC_LO10:
134bb684c34Spatrick // T-simm13
135bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));
136bb684c34Spatrick break;
137ece8a530Spatrick case R_SPARC_64:
138ece8a530Spatrick case R_SPARC_UA64:
139ece8a530Spatrick // V-xword64
140ece8a530Spatrick write64be(loc, val);
141ece8a530Spatrick break;
142bb684c34Spatrick case R_SPARC_HH22:
143bb684c34Spatrick // V-imm22
144bb684c34Spatrick checkUInt(loc, val >> 42, 22, rel);
145bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff));
146bb684c34Spatrick break;
147bb684c34Spatrick case R_SPARC_HM10:
148bb684c34Spatrick // T-simm13
149bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff));
150bb684c34Spatrick break;
151bb684c34Spatrick case R_SPARC_H44:
152bb684c34Spatrick // V-imm22
153bb684c34Spatrick checkUInt(loc, val >> 22, 22, rel);
154bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));
155bb684c34Spatrick break;
156bb684c34Spatrick case R_SPARC_M44:
157bb684c34Spatrick // T-imm10
158bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));
159bb684c34Spatrick break;
160bb684c34Spatrick case R_SPARC_L44:
161bb684c34Spatrick // T-imm13
162bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));
163bb684c34Spatrick break;
164bb684c34Spatrick case R_SPARC_TLS_LE_HIX22:
165bb684c34Spatrick // T-imm22
166bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));
167bb684c34Spatrick break;
168bb684c34Spatrick case R_SPARC_TLS_LE_LOX10:
169bb684c34Spatrick // T-simm13
170bb684c34Spatrick write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);
171bb684c34Spatrick break;
172ece8a530Spatrick default:
173ece8a530Spatrick llvm_unreachable("unknown relocation");
174ece8a530Spatrick }
175ece8a530Spatrick }
176ece8a530Spatrick
writePlt(uint8_t * buf,const Symbol &,uint64_t pltEntryAddr) const177ece8a530Spatrick void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,
178ece8a530Spatrick uint64_t pltEntryAddr) const {
179ece8a530Spatrick const uint8_t pltData[] = {
180ece8a530Spatrick 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1
181ece8a530Spatrick 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1
182ece8a530Spatrick 0x01, 0x00, 0x00, 0x00, // nop
183ece8a530Spatrick 0x01, 0x00, 0x00, 0x00, // nop
184ece8a530Spatrick 0x01, 0x00, 0x00, 0x00, // nop
185ece8a530Spatrick 0x01, 0x00, 0x00, 0x00, // nop
186ece8a530Spatrick 0x01, 0x00, 0x00, 0x00, // nop
187ece8a530Spatrick 0x01, 0x00, 0x00, 0x00 // nop
188ece8a530Spatrick };
189ece8a530Spatrick memcpy(buf, pltData, sizeof(pltData));
190ece8a530Spatrick
191ece8a530Spatrick uint64_t off = pltEntryAddr - in.plt->getVA();
192bb684c34Spatrick relocateNoSym(buf, R_SPARC_22, off);
193bb684c34Spatrick relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
194ece8a530Spatrick }
195ece8a530Spatrick
getSPARCV9TargetInfo()196bb684c34Spatrick TargetInfo *elf::getSPARCV9TargetInfo() {
197ece8a530Spatrick static SPARCV9 target;
198ece8a530Spatrick return ⌖
199ece8a530Spatrick }
200