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 //===----------------------------------------------------------------------===//
10 #include "SyntheticSections.h"
12 #include "lld/Common/ErrorHandler.h"
13 #include "llvm/Support/Endian.h"
16 using namespace llvm::support::endian
;
17 using namespace llvm::ELF
;
19 using namespace lld::elf
;
22 class SPARCV9 final
: public TargetInfo
{
25 RelExpr
getRelExpr(RelType type
, const Symbol
&s
,
26 const uint8_t *loc
) const override
;
27 void writePlt(uint8_t *buf
, const Symbol
&sym
,
28 uint64_t pltEntryAddr
) const override
;
29 void relocate(uint8_t *loc
, const Relocation
&rel
,
30 uint64_t val
) const override
;
35 copyRel
= R_SPARC_COPY
;
36 gotRel
= R_SPARC_GLOB_DAT
;
37 pltRel
= R_SPARC_JMP_SLOT
;
38 relativeRel
= R_SPARC_RELATIVE
;
39 symbolicRel
= R_SPARC_64
;
41 pltHeaderSize
= 4 * pltEntrySize
;
43 defaultCommonPageSize
= 8192;
44 defaultMaxPageSize
= 0x100000;
45 defaultImageBase
= 0x100000;
48 RelExpr
SPARCV9::getRelExpr(RelType type
, const Symbol
&s
,
49 const uint8_t *loc
) const {
77 case R_SPARC_TLS_LE_HIX22
:
78 case R_SPARC_TLS_LE_LOX10
:
81 error(getErrorLocation(loc
) + "unknown relocation (" + Twine(type
) +
82 ") against symbol " + toString(s
));
87 void SPARCV9::relocate(uint8_t *loc
, const Relocation
&rel
,
93 checkUInt(loc
, val
, 32, rel
);
98 checkInt(loc
, val
, 32, rel
);
101 case R_SPARC_WDISP30
:
104 checkInt(loc
, val
, 32, rel
);
105 write32be(loc
, (read32be(loc
) & ~0x3fffffff) | ((val
>> 2) & 0x3fffffff));
109 checkUInt(loc
, val
, 22, rel
);
110 write32be(loc
, (read32be(loc
) & ~0x003fffff) | (val
& 0x003fffff));
116 write32be(loc
, (read32be(loc
) & ~0x003fffff) | ((val
>> 10) & 0x003fffff));
120 checkUInt(loc
, val
>> 10, 22, rel
);
121 write32be(loc
, (read32be(loc
) & ~0x003fffff) | ((val
>> 10) & 0x003fffff));
123 case R_SPARC_WDISP19
:
125 checkInt(loc
, val
, 21, rel
);
126 write32be(loc
, (read32be(loc
) & ~0x0007ffff) | ((val
>> 2) & 0x0007ffff));
131 write32be(loc
, (read32be(loc
) & ~0x000003ff) | (val
& 0x000003ff));
135 write32be(loc
, (read32be(loc
) & ~0x00001fff) | (val
& 0x000003ff));
144 checkUInt(loc
, val
>> 42, 22, rel
);
145 write32be(loc
, (read32be(loc
) & ~0x003fffff) | ((val
>> 42) & 0x003fffff));
149 write32be(loc
, (read32be(loc
) & ~0x00001fff) | ((val
>> 32) & 0x000003ff));
153 checkUInt(loc
, val
>> 22, 22, rel
);
154 write32be(loc
, (read32be(loc
) & ~0x003fffff) | ((val
>> 22) & 0x003fffff));
158 write32be(loc
, (read32be(loc
) & ~0x000003ff) | ((val
>> 12) & 0x000003ff));
162 write32be(loc
, (read32be(loc
) & ~0x00001fff) | (val
& 0x00000fff));
164 case R_SPARC_TLS_LE_HIX22
:
166 write32be(loc
, (read32be(loc
) & ~0x003fffff) | ((~val
>> 10) & 0x003fffff));
168 case R_SPARC_TLS_LE_LOX10
:
170 write32be(loc
, (read32be(loc
) & ~0x00001fff) | (val
& 0x000003ff) | 0x1C00);
173 llvm_unreachable("unknown relocation");
177 void SPARCV9::writePlt(uint8_t *buf
, const Symbol
& /*sym*/,
178 uint64_t pltEntryAddr
) const {
179 const uint8_t pltData
[] = {
180 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1
181 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1
182 0x01, 0x00, 0x00, 0x00, // nop
183 0x01, 0x00, 0x00, 0x00, // nop
184 0x01, 0x00, 0x00, 0x00, // nop
185 0x01, 0x00, 0x00, 0x00, // nop
186 0x01, 0x00, 0x00, 0x00, // nop
187 0x01, 0x00, 0x00, 0x00 // nop
189 memcpy(buf
, pltData
, sizeof(pltData
));
191 uint64_t off
= pltEntryAddr
- in
.plt
->getVA();
192 relocateNoSym(buf
, R_SPARC_22
, off
);
193 relocateNoSym(buf
+ 4, R_SPARC_WDISP19
, -(off
+ 4 - pltEntrySize
));
196 TargetInfo
*elf::getSPARCV9TargetInfo() {
197 static SPARCV9 target
;