150
|
1 //===- RISCV.cpp ----------------------------------------------------------===//
|
|
2 //
|
|
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
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8
|
|
9 #include "InputFiles.h"
|
|
10 #include "Symbols.h"
|
|
11 #include "SyntheticSections.h"
|
|
12 #include "Target.h"
|
|
13
|
|
14 using namespace llvm;
|
|
15 using namespace llvm::object;
|
|
16 using namespace llvm::support::endian;
|
|
17 using namespace llvm::ELF;
|
173
|
18 using namespace lld;
|
|
19 using namespace lld::elf;
|
150
|
20
|
|
21 namespace {
|
|
22
|
|
23 class RISCV final : public TargetInfo {
|
|
24 public:
|
|
25 RISCV();
|
|
26 uint32_t calcEFlags() const override;
|
|
27 void writeGotHeader(uint8_t *buf) const override;
|
|
28 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
|
|
29 void writePltHeader(uint8_t *buf) const override;
|
|
30 void writePlt(uint8_t *buf, const Symbol &sym,
|
|
31 uint64_t pltEntryAddr) const override;
|
|
32 RelType getDynRel(RelType type) const override;
|
|
33 RelExpr getRelExpr(RelType type, const Symbol &s,
|
|
34 const uint8_t *loc) const override;
|
|
35 void relocate(uint8_t *loc, const Relocation &rel,
|
|
36 uint64_t val) const override;
|
|
37 };
|
|
38
|
|
39 } // end anonymous namespace
|
|
40
|
|
41 const uint64_t dtpOffset = 0x800;
|
|
42
|
|
43 enum Op {
|
|
44 ADDI = 0x13,
|
|
45 AUIPC = 0x17,
|
|
46 JALR = 0x67,
|
|
47 LD = 0x3003,
|
|
48 LW = 0x2003,
|
|
49 SRLI = 0x5013,
|
|
50 SUB = 0x40000033,
|
|
51 };
|
|
52
|
|
53 enum Reg {
|
|
54 X_RA = 1,
|
|
55 X_T0 = 5,
|
|
56 X_T1 = 6,
|
|
57 X_T2 = 7,
|
|
58 X_T3 = 28,
|
|
59 };
|
|
60
|
|
61 static uint32_t hi20(uint32_t val) { return (val + 0x800) >> 12; }
|
|
62 static uint32_t lo12(uint32_t val) { return val & 4095; }
|
|
63
|
|
64 static uint32_t itype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t imm) {
|
|
65 return op | (rd << 7) | (rs1 << 15) | (imm << 20);
|
|
66 }
|
|
67 static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
|
|
68 return op | (rd << 7) | (rs1 << 15) | (rs2 << 20);
|
|
69 }
|
|
70 static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
|
|
71 return op | (rd << 7) | (imm << 12);
|
|
72 }
|
|
73
|
|
74 RISCV::RISCV() {
|
|
75 copyRel = R_RISCV_COPY;
|
|
76 noneRel = R_RISCV_NONE;
|
|
77 pltRel = R_RISCV_JUMP_SLOT;
|
|
78 relativeRel = R_RISCV_RELATIVE;
|
|
79 iRelativeRel = R_RISCV_IRELATIVE;
|
|
80 if (config->is64) {
|
|
81 symbolicRel = R_RISCV_64;
|
|
82 tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64;
|
|
83 tlsOffsetRel = R_RISCV_TLS_DTPREL64;
|
|
84 tlsGotRel = R_RISCV_TLS_TPREL64;
|
|
85 } else {
|
|
86 symbolicRel = R_RISCV_32;
|
|
87 tlsModuleIndexRel = R_RISCV_TLS_DTPMOD32;
|
|
88 tlsOffsetRel = R_RISCV_TLS_DTPREL32;
|
|
89 tlsGotRel = R_RISCV_TLS_TPREL32;
|
|
90 }
|
|
91 gotRel = symbolicRel;
|
|
92
|
|
93 // .got[0] = _DYNAMIC
|
|
94 gotBaseSymInGotPlt = false;
|
|
95 gotHeaderEntriesNum = 1;
|
|
96
|
|
97 // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map
|
|
98 gotPltHeaderEntriesNum = 2;
|
|
99
|
|
100 pltHeaderSize = 32;
|
|
101 pltEntrySize = 16;
|
|
102 ipltEntrySize = 16;
|
|
103 }
|
|
104
|
|
105 static uint32_t getEFlags(InputFile *f) {
|
|
106 if (config->is64)
|
|
107 return cast<ObjFile<ELF64LE>>(f)->getObj().getHeader()->e_flags;
|
|
108 return cast<ObjFile<ELF32LE>>(f)->getObj().getHeader()->e_flags;
|
|
109 }
|
|
110
|
|
111 uint32_t RISCV::calcEFlags() const {
|
|
112 // If there are only binary input files (from -b binary), use a
|
|
113 // value of 0 for the ELF header flags.
|
|
114 if (objectFiles.empty())
|
|
115 return 0;
|
|
116
|
|
117 uint32_t target = getEFlags(objectFiles.front());
|
|
118
|
|
119 for (InputFile *f : objectFiles) {
|
|
120 uint32_t eflags = getEFlags(f);
|
|
121 if (eflags & EF_RISCV_RVC)
|
|
122 target |= EF_RISCV_RVC;
|
|
123
|
|
124 if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI))
|
|
125 error(toString(f) +
|
|
126 ": cannot link object files with different floating-point ABI");
|
|
127
|
|
128 if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE))
|
|
129 error(toString(f) +
|
|
130 ": cannot link object files with different EF_RISCV_RVE");
|
|
131 }
|
|
132
|
|
133 return target;
|
|
134 }
|
|
135
|
|
136 void RISCV::writeGotHeader(uint8_t *buf) const {
|
|
137 if (config->is64)
|
|
138 write64le(buf, mainPart->dynamic->getVA());
|
|
139 else
|
|
140 write32le(buf, mainPart->dynamic->getVA());
|
|
141 }
|
|
142
|
|
143 void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const {
|
|
144 if (config->is64)
|
|
145 write64le(buf, in.plt->getVA());
|
|
146 else
|
|
147 write32le(buf, in.plt->getVA());
|
|
148 }
|
|
149
|
|
150 void RISCV::writePltHeader(uint8_t *buf) const {
|
|
151 // 1: auipc t2, %pcrel_hi(.got.plt)
|
|
152 // sub t1, t1, t3
|
|
153 // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
|
|
154 // addi t1, t1, -pltHeaderSize-12; t1 = &.plt[i] - &.plt[0]
|
|
155 // addi t0, t2, %pcrel_lo(1b)
|
|
156 // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
|
|
157 // l[wd] t0, Wordsize(t0); t0 = link_map
|
|
158 // jr t3
|
|
159 uint32_t offset = in.gotPlt->getVA() - in.plt->getVA();
|
|
160 uint32_t load = config->is64 ? LD : LW;
|
|
161 write32le(buf + 0, utype(AUIPC, X_T2, hi20(offset)));
|
|
162 write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T3));
|
|
163 write32le(buf + 8, itype(load, X_T3, X_T2, lo12(offset)));
|
|
164 write32le(buf + 12, itype(ADDI, X_T1, X_T1, -target->pltHeaderSize - 12));
|
|
165 write32le(buf + 16, itype(ADDI, X_T0, X_T2, lo12(offset)));
|
|
166 write32le(buf + 20, itype(SRLI, X_T1, X_T1, config->is64 ? 1 : 2));
|
|
167 write32le(buf + 24, itype(load, X_T0, X_T0, config->wordsize));
|
|
168 write32le(buf + 28, itype(JALR, 0, X_T3, 0));
|
|
169 }
|
|
170
|
|
171 void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
|
|
172 uint64_t pltEntryAddr) const {
|
|
173 // 1: auipc t3, %pcrel_hi(f@.got.plt)
|
|
174 // l[wd] t3, %pcrel_lo(1b)(t3)
|
|
175 // jalr t1, t3
|
|
176 // nop
|
|
177 uint32_t offset = sym.getGotPltVA() - pltEntryAddr;
|
|
178 write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
|
|
179 write32le(buf + 4, itype(config->is64 ? LD : LW, X_T3, X_T3, lo12(offset)));
|
|
180 write32le(buf + 8, itype(JALR, X_T1, X_T3, 0));
|
|
181 write32le(buf + 12, itype(ADDI, 0, 0, 0));
|
|
182 }
|
|
183
|
|
184 RelType RISCV::getDynRel(RelType type) const {
|
|
185 return type == target->symbolicRel ? type
|
|
186 : static_cast<RelType>(R_RISCV_NONE);
|
|
187 }
|
|
188
|
|
189 RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
|
|
190 const uint8_t *loc) const {
|
|
191 switch (type) {
|
|
192 case R_RISCV_NONE:
|
|
193 return R_NONE;
|
|
194 case R_RISCV_32:
|
|
195 case R_RISCV_64:
|
|
196 case R_RISCV_HI20:
|
|
197 case R_RISCV_LO12_I:
|
|
198 case R_RISCV_LO12_S:
|
|
199 case R_RISCV_RVC_LUI:
|
|
200 return R_ABS;
|
|
201 case R_RISCV_ADD8:
|
|
202 case R_RISCV_ADD16:
|
|
203 case R_RISCV_ADD32:
|
|
204 case R_RISCV_ADD64:
|
|
205 case R_RISCV_SET6:
|
|
206 case R_RISCV_SET8:
|
|
207 case R_RISCV_SET16:
|
|
208 case R_RISCV_SET32:
|
|
209 case R_RISCV_SUB6:
|
|
210 case R_RISCV_SUB8:
|
|
211 case R_RISCV_SUB16:
|
|
212 case R_RISCV_SUB32:
|
|
213 case R_RISCV_SUB64:
|
|
214 return R_RISCV_ADD;
|
|
215 case R_RISCV_JAL:
|
|
216 case R_RISCV_BRANCH:
|
|
217 case R_RISCV_PCREL_HI20:
|
|
218 case R_RISCV_RVC_BRANCH:
|
|
219 case R_RISCV_RVC_JUMP:
|
|
220 case R_RISCV_32_PCREL:
|
|
221 return R_PC;
|
|
222 case R_RISCV_CALL:
|
|
223 case R_RISCV_CALL_PLT:
|
|
224 return R_PLT_PC;
|
|
225 case R_RISCV_GOT_HI20:
|
|
226 return R_GOT_PC;
|
|
227 case R_RISCV_PCREL_LO12_I:
|
|
228 case R_RISCV_PCREL_LO12_S:
|
|
229 return R_RISCV_PC_INDIRECT;
|
|
230 case R_RISCV_TLS_GD_HI20:
|
|
231 return R_TLSGD_PC;
|
|
232 case R_RISCV_TLS_GOT_HI20:
|
|
233 config->hasStaticTlsModel = true;
|
|
234 return R_GOT_PC;
|
|
235 case R_RISCV_TPREL_HI20:
|
|
236 case R_RISCV_TPREL_LO12_I:
|
|
237 case R_RISCV_TPREL_LO12_S:
|
|
238 return R_TLS;
|
|
239 case R_RISCV_RELAX:
|
|
240 case R_RISCV_TPREL_ADD:
|
|
241 return R_NONE;
|
|
242 case R_RISCV_ALIGN:
|
|
243 // Not just a hint; always padded to the worst-case number of NOPs, so may
|
|
244 // not currently be aligned, and without linker relaxation support we can't
|
|
245 // delete NOPs to realign.
|
|
246 errorOrWarn(getErrorLocation(loc) + "relocation R_RISCV_ALIGN requires "
|
|
247 "unimplemented linker relaxation; recompile with -mno-relax");
|
|
248 return R_NONE;
|
|
249 default:
|
|
250 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
|
|
251 ") against symbol " + toString(s));
|
|
252 return R_NONE;
|
|
253 }
|
|
254 }
|
|
255
|
|
256 // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.
|
|
257 static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
|
|
258 return (v & ((1ULL << (begin + 1)) - 1)) >> end;
|
|
259 }
|
|
260
|
|
261 void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
|
262 const unsigned bits = config->wordsize * 8;
|
|
263
|
|
264 switch (rel.type) {
|
|
265 case R_RISCV_32:
|
|
266 write32le(loc, val);
|
|
267 return;
|
|
268 case R_RISCV_64:
|
|
269 write64le(loc, val);
|
|
270 return;
|
|
271
|
|
272 case R_RISCV_RVC_BRANCH: {
|
|
273 checkInt(loc, static_cast<int64_t>(val) >> 1, 8, rel);
|
|
274 checkAlignment(loc, val, 2, rel);
|
|
275 uint16_t insn = read16le(loc) & 0xE383;
|
|
276 uint16_t imm8 = extractBits(val, 8, 8) << 12;
|
|
277 uint16_t imm4_3 = extractBits(val, 4, 3) << 10;
|
|
278 uint16_t imm7_6 = extractBits(val, 7, 6) << 5;
|
|
279 uint16_t imm2_1 = extractBits(val, 2, 1) << 3;
|
|
280 uint16_t imm5 = extractBits(val, 5, 5) << 2;
|
|
281 insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5;
|
|
282
|
|
283 write16le(loc, insn);
|
|
284 return;
|
|
285 }
|
|
286
|
|
287 case R_RISCV_RVC_JUMP: {
|
|
288 checkInt(loc, static_cast<int64_t>(val) >> 1, 11, rel);
|
|
289 checkAlignment(loc, val, 2, rel);
|
|
290 uint16_t insn = read16le(loc) & 0xE003;
|
|
291 uint16_t imm11 = extractBits(val, 11, 11) << 12;
|
|
292 uint16_t imm4 = extractBits(val, 4, 4) << 11;
|
|
293 uint16_t imm9_8 = extractBits(val, 9, 8) << 9;
|
|
294 uint16_t imm10 = extractBits(val, 10, 10) << 8;
|
|
295 uint16_t imm6 = extractBits(val, 6, 6) << 7;
|
|
296 uint16_t imm7 = extractBits(val, 7, 7) << 6;
|
|
297 uint16_t imm3_1 = extractBits(val, 3, 1) << 3;
|
|
298 uint16_t imm5 = extractBits(val, 5, 5) << 2;
|
|
299 insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5;
|
|
300
|
|
301 write16le(loc, insn);
|
|
302 return;
|
|
303 }
|
|
304
|
|
305 case R_RISCV_RVC_LUI: {
|
|
306 int64_t imm = SignExtend64(val + 0x800, bits) >> 12;
|
|
307 checkInt(loc, imm, 6, rel);
|
|
308 if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
|
|
309 write16le(loc, (read16le(loc) & 0x0F83) | 0x4000);
|
|
310 } else {
|
|
311 uint16_t imm17 = extractBits(val + 0x800, 17, 17) << 12;
|
|
312 uint16_t imm16_12 = extractBits(val + 0x800, 16, 12) << 2;
|
|
313 write16le(loc, (read16le(loc) & 0xEF83) | imm17 | imm16_12);
|
|
314 }
|
|
315 return;
|
|
316 }
|
|
317
|
|
318 case R_RISCV_JAL: {
|
|
319 checkInt(loc, static_cast<int64_t>(val) >> 1, 20, rel);
|
|
320 checkAlignment(loc, val, 2, rel);
|
|
321
|
|
322 uint32_t insn = read32le(loc) & 0xFFF;
|
|
323 uint32_t imm20 = extractBits(val, 20, 20) << 31;
|
|
324 uint32_t imm10_1 = extractBits(val, 10, 1) << 21;
|
|
325 uint32_t imm11 = extractBits(val, 11, 11) << 20;
|
|
326 uint32_t imm19_12 = extractBits(val, 19, 12) << 12;
|
|
327 insn |= imm20 | imm10_1 | imm11 | imm19_12;
|
|
328
|
|
329 write32le(loc, insn);
|
|
330 return;
|
|
331 }
|
|
332
|
|
333 case R_RISCV_BRANCH: {
|
|
334 checkInt(loc, static_cast<int64_t>(val) >> 1, 12, rel);
|
|
335 checkAlignment(loc, val, 2, rel);
|
|
336
|
|
337 uint32_t insn = read32le(loc) & 0x1FFF07F;
|
|
338 uint32_t imm12 = extractBits(val, 12, 12) << 31;
|
|
339 uint32_t imm10_5 = extractBits(val, 10, 5) << 25;
|
|
340 uint32_t imm4_1 = extractBits(val, 4, 1) << 8;
|
|
341 uint32_t imm11 = extractBits(val, 11, 11) << 7;
|
|
342 insn |= imm12 | imm10_5 | imm4_1 | imm11;
|
|
343
|
|
344 write32le(loc, insn);
|
|
345 return;
|
|
346 }
|
|
347
|
|
348 // auipc + jalr pair
|
|
349 case R_RISCV_CALL:
|
|
350 case R_RISCV_CALL_PLT: {
|
|
351 int64_t hi = SignExtend64(val + 0x800, bits) >> 12;
|
|
352 checkInt(loc, hi, 20, rel);
|
|
353 if (isInt<20>(hi)) {
|
|
354 relocateNoSym(loc, R_RISCV_PCREL_HI20, val);
|
|
355 relocateNoSym(loc + 4, R_RISCV_PCREL_LO12_I, val);
|
|
356 }
|
|
357 return;
|
|
358 }
|
|
359
|
|
360 case R_RISCV_GOT_HI20:
|
|
361 case R_RISCV_PCREL_HI20:
|
|
362 case R_RISCV_TLS_GD_HI20:
|
|
363 case R_RISCV_TLS_GOT_HI20:
|
|
364 case R_RISCV_TPREL_HI20:
|
|
365 case R_RISCV_HI20: {
|
|
366 uint64_t hi = val + 0x800;
|
|
367 checkInt(loc, SignExtend64(hi, bits) >> 12, 20, rel);
|
|
368 write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
|
|
369 return;
|
|
370 }
|
|
371
|
|
372 case R_RISCV_PCREL_LO12_I:
|
|
373 case R_RISCV_TPREL_LO12_I:
|
|
374 case R_RISCV_LO12_I: {
|
|
375 uint64_t hi = (val + 0x800) >> 12;
|
|
376 uint64_t lo = val - (hi << 12);
|
|
377 write32le(loc, (read32le(loc) & 0xFFFFF) | ((lo & 0xFFF) << 20));
|
|
378 return;
|
|
379 }
|
|
380
|
|
381 case R_RISCV_PCREL_LO12_S:
|
|
382 case R_RISCV_TPREL_LO12_S:
|
|
383 case R_RISCV_LO12_S: {
|
|
384 uint64_t hi = (val + 0x800) >> 12;
|
|
385 uint64_t lo = val - (hi << 12);
|
|
386 uint32_t imm11_5 = extractBits(lo, 11, 5) << 25;
|
|
387 uint32_t imm4_0 = extractBits(lo, 4, 0) << 7;
|
|
388 write32le(loc, (read32le(loc) & 0x1FFF07F) | imm11_5 | imm4_0);
|
|
389 return;
|
|
390 }
|
|
391
|
|
392 case R_RISCV_ADD8:
|
|
393 *loc += val;
|
|
394 return;
|
|
395 case R_RISCV_ADD16:
|
|
396 write16le(loc, read16le(loc) + val);
|
|
397 return;
|
|
398 case R_RISCV_ADD32:
|
|
399 write32le(loc, read32le(loc) + val);
|
|
400 return;
|
|
401 case R_RISCV_ADD64:
|
|
402 write64le(loc, read64le(loc) + val);
|
|
403 return;
|
|
404 case R_RISCV_SUB6:
|
|
405 *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f);
|
|
406 return;
|
|
407 case R_RISCV_SUB8:
|
|
408 *loc -= val;
|
|
409 return;
|
|
410 case R_RISCV_SUB16:
|
|
411 write16le(loc, read16le(loc) - val);
|
|
412 return;
|
|
413 case R_RISCV_SUB32:
|
|
414 write32le(loc, read32le(loc) - val);
|
|
415 return;
|
|
416 case R_RISCV_SUB64:
|
|
417 write64le(loc, read64le(loc) - val);
|
|
418 return;
|
|
419 case R_RISCV_SET6:
|
|
420 *loc = (*loc & 0xc0) | (val & 0x3f);
|
|
421 return;
|
|
422 case R_RISCV_SET8:
|
|
423 *loc = val;
|
|
424 return;
|
|
425 case R_RISCV_SET16:
|
|
426 write16le(loc, val);
|
|
427 return;
|
|
428 case R_RISCV_SET32:
|
|
429 case R_RISCV_32_PCREL:
|
|
430 write32le(loc, val);
|
|
431 return;
|
|
432
|
|
433 case R_RISCV_TLS_DTPREL32:
|
|
434 write32le(loc, val - dtpOffset);
|
|
435 break;
|
|
436 case R_RISCV_TLS_DTPREL64:
|
|
437 write64le(loc, val - dtpOffset);
|
|
438 break;
|
|
439
|
|
440 case R_RISCV_RELAX:
|
|
441 return; // Ignored (for now)
|
|
442
|
|
443 default:
|
|
444 llvm_unreachable("unknown relocation");
|
|
445 }
|
|
446 }
|
|
447
|
173
|
448 TargetInfo *elf::getRISCVTargetInfo() {
|
150
|
449 static RISCV target;
|
|
450 return ⌖
|
|
451 }
|