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