1 //===- SPARCV9.cpp --------------------------------------------------------===//
2 //
3 // The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "InputFiles.h"
11 #include "Symbols.h"
12 #include "SyntheticSections.h"
13 #include "Target.h"
14 #include "lld/Common/ErrorHandler.h"
15 #include "llvm/Support/Endian.h"
16
17 using namespace llvm;
18 using namespace llvm::support::endian;
19 using namespace llvm::ELF;
20 using namespace lld;
21 using namespace lld::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, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
30 int32_t Index, unsigned RelOff) const override;
31 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
32 };
33 } // namespace
34
SPARCV9()35 SPARCV9::SPARCV9() {
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 GotEntrySize = 8;
42 PltEntrySize = 32;
43 PltHeaderSize = 4 * PltEntrySize;
44
45 PageSize = 8192;
46 DefaultMaxPageSize = 0x100000;
47 DefaultImageBase = 0x100000;
48 }
49
getRelExpr(RelType Type,const Symbol & S,const uint8_t * Loc) const50 RelExpr SPARCV9::getRelExpr(RelType Type, const Symbol &S,
51 const uint8_t *Loc) const {
52 switch (Type) {
53 case R_SPARC_32:
54 case R_SPARC_UA32:
55 case R_SPARC_64:
56 case R_SPARC_UA64:
57 return R_ABS;
58 case R_SPARC_PC10:
59 case R_SPARC_PC22:
60 case R_SPARC_DISP32:
61 case R_SPARC_WDISP30:
62 return R_PC;
63 case R_SPARC_GOT10:
64 return R_GOT_OFF;
65 case R_SPARC_GOT22:
66 return R_GOT_OFF;
67 case R_SPARC_WPLT30:
68 return R_PLT_PC;
69 case R_SPARC_NONE:
70 return R_NONE;
71 default:
72 return R_INVALID;
73 }
74 }
75
relocateOne(uint8_t * Loc,RelType Type,uint64_t Val) const76 void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
77 switch (Type) {
78 case R_SPARC_32:
79 case R_SPARC_UA32:
80 // V-word32
81 checkUInt(Loc, Val, 32, Type);
82 write32be(Loc, Val);
83 break;
84 case R_SPARC_DISP32:
85 // V-disp32
86 checkInt(Loc, Val, 32, Type);
87 write32be(Loc, Val);
88 break;
89 case R_SPARC_WDISP30:
90 case R_SPARC_WPLT30:
91 // V-disp30
92 checkInt(Loc, Val, 32, Type);
93 write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff));
94 break;
95 case R_SPARC_22:
96 // V-imm22
97 checkUInt(Loc, Val, 22, Type);
98 write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff));
99 break;
100 case R_SPARC_GOT22:
101 case R_SPARC_PC22:
102 // T-imm22
103 write32be(Loc, (read32be(Loc) & ~0x003fffff) | ((Val >> 10) & 0x003fffff));
104 break;
105 case R_SPARC_WDISP19:
106 // V-disp19
107 checkInt(Loc, Val, 21, Type);
108 write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff));
109 break;
110 case R_SPARC_GOT10:
111 case R_SPARC_PC10:
112 // T-simm10
113 write32be(Loc, (read32be(Loc) & ~0x000003ff) | (Val & 0x000003ff));
114 break;
115 case R_SPARC_64:
116 case R_SPARC_UA64:
117 case R_SPARC_GLOB_DAT:
118 // V-xword64
119 write64be(Loc, Val);
120 break;
121 default:
122 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
123 }
124 }
125
writePlt(uint8_t * Buf,uint64_t GotEntryAddr,uint64_t PltEntryAddr,int32_t Index,unsigned RelOff) const126 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
138 };
139 memcpy(Buf, PltData, sizeof(PltData));
140
141 uint64_t Off = getPltEntryOffset(Index);
142 relocateOne(Buf, R_SPARC_22, Off);
143 relocateOne(Buf + 4, R_SPARC_WDISP19, -(Off + 4 - PltEntrySize));
144 }
145
getSPARCV9TargetInfo()146 TargetInfo *elf::getSPARCV9TargetInfo() {
147 static SPARCV9 Target;
148 return &Target;
149 }
150