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, uint64_t gotEntryAddr, uint64_t pltEntryAddr,
29 int32_t index, unsigned relOff) const override;
30 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
35 copyRel = R_SPARC_COPY;
36 gotRel = R_SPARC_GLOB_DAT;
37 noneRel = R_SPARC_NONE;
38 pltRel = R_SPARC_JMP_SLOT;
39 relativeRel = R_SPARC_RELATIVE;
40 symbolicRel = R_SPARC_64;
42 pltHeaderSize = 4 * pltEntrySize;
44 defaultCommonPageSize = 8192;
45 defaultMaxPageSize = 0x100000;
46 defaultImageBase = 0x100000;
49 RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
50 const uint8_t *loc) const {
71 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
72 ") against symbol " + toString(s));
77 void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
82 checkUInt(loc, val, 32, type);
87 checkInt(loc, val, 32, type);
93 checkInt(loc, val, 32, type);
94 write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
98 checkUInt(loc, val, 22, type);
99 write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
104 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
106 case R_SPARC_WDISP19:
108 checkInt(loc, val, 21, type);
109 write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
114 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
122 llvm_unreachable("unknown relocation");
126 void SPARCV9::writePlt(uint8_t *buf, uint64_t gotEntryAddr,
127 uint64_t pltEntryAddr, int32_t index,
128 unsigned relOff) const {
129 const uint8_t pltData[] = {
130 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1
131 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1
132 0x01, 0x00, 0x00, 0x00, // nop
133 0x01, 0x00, 0x00, 0x00, // nop
134 0x01, 0x00, 0x00, 0x00, // nop
135 0x01, 0x00, 0x00, 0x00, // nop
136 0x01, 0x00, 0x00, 0x00, // nop
137 0x01, 0x00, 0x00, 0x00 // nop
139 memcpy(buf, pltData, sizeof(pltData));
141 uint64_t off = pltHeaderSize + pltEntrySize * index;
142 relocateOne(buf, R_SPARC_22, off);
143 relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
146 TargetInfo *elf::getSPARCV9TargetInfo() {
147 static SPARCV9 target;