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