fa46b06f8df9ddb12cff822d14885dbbf4a5b2e8
[deliverable/binutils-gdb.git] / bfd / elfxx-riscv.c
1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf/riscv.h"
28 #include "libiberty.h"
29 #include "elfxx-riscv.h"
30 #include "safe-ctype.h"
31
32 #define MINUS_ONE ((bfd_vma)0 - 1)
33
34 /* Special handler for ADD/SUB relocations that allows them to be filled out
35 both in the pre-linked and post-linked file. This is necessary to make
36 pre-linked debug info work, as due to linker relaxations we need to emit
37 relocations for the debug info. */
38 static bfd_reloc_status_type riscv_elf_add_sub_reloc
39 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
40
41 /* The relocation table used for SHT_RELA sections. */
42
43 static reloc_howto_type howto_table[] =
44 {
45 /* No relocation. */
46 HOWTO (R_RISCV_NONE, /* type */
47 0, /* rightshift */
48 3, /* size */
49 0, /* bitsize */
50 FALSE, /* pc_relative */
51 0, /* bitpos */
52 complain_overflow_dont, /* complain_on_overflow */
53 bfd_elf_generic_reloc, /* special_function */
54 "R_RISCV_NONE", /* name */
55 FALSE, /* partial_inplace */
56 0, /* src_mask */
57 0, /* dst_mask */
58 FALSE), /* pcrel_offset */
59
60 /* 32 bit relocation. */
61 HOWTO (R_RISCV_32, /* type */
62 0, /* rightshift */
63 2, /* size */
64 32, /* bitsize */
65 FALSE, /* pc_relative */
66 0, /* bitpos */
67 complain_overflow_dont, /* complain_on_overflow */
68 bfd_elf_generic_reloc, /* special_function */
69 "R_RISCV_32", /* name */
70 FALSE, /* partial_inplace */
71 0, /* src_mask */
72 MINUS_ONE, /* dst_mask */
73 FALSE), /* pcrel_offset */
74
75 /* 64 bit relocation. */
76 HOWTO (R_RISCV_64, /* type */
77 0, /* rightshift */
78 4, /* size */
79 64, /* bitsize */
80 FALSE, /* pc_relative */
81 0, /* bitpos */
82 complain_overflow_dont, /* complain_on_overflow */
83 bfd_elf_generic_reloc, /* special_function */
84 "R_RISCV_64", /* name */
85 FALSE, /* partial_inplace */
86 0, /* src_mask */
87 MINUS_ONE, /* dst_mask */
88 FALSE), /* pcrel_offset */
89
90 /* Relocation against a local symbol in a shared object. */
91 HOWTO (R_RISCV_RELATIVE, /* type */
92 0, /* rightshift */
93 2, /* size */
94 32, /* bitsize */
95 FALSE, /* pc_relative */
96 0, /* bitpos */
97 complain_overflow_dont, /* complain_on_overflow */
98 bfd_elf_generic_reloc, /* special_function */
99 "R_RISCV_RELATIVE", /* name */
100 FALSE, /* partial_inplace */
101 0, /* src_mask */
102 MINUS_ONE, /* dst_mask */
103 FALSE), /* pcrel_offset */
104
105 HOWTO (R_RISCV_COPY, /* type */
106 0, /* rightshift */
107 0, /* this one is variable size */
108 0, /* bitsize */
109 FALSE, /* pc_relative */
110 0, /* bitpos */
111 complain_overflow_bitfield, /* complain_on_overflow */
112 bfd_elf_generic_reloc, /* special_function */
113 "R_RISCV_COPY", /* name */
114 FALSE, /* partial_inplace */
115 0, /* src_mask */
116 0, /* dst_mask */
117 FALSE), /* pcrel_offset */
118
119 HOWTO (R_RISCV_JUMP_SLOT, /* type */
120 0, /* rightshift */
121 4, /* size */
122 64, /* bitsize */
123 FALSE, /* pc_relative */
124 0, /* bitpos */
125 complain_overflow_bitfield, /* complain_on_overflow */
126 bfd_elf_generic_reloc, /* special_function */
127 "R_RISCV_JUMP_SLOT", /* name */
128 FALSE, /* partial_inplace */
129 0, /* src_mask */
130 0, /* dst_mask */
131 FALSE), /* pcrel_offset */
132
133 /* Dynamic TLS relocations. */
134 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
135 0, /* rightshift */
136 4, /* size */
137 32, /* bitsize */
138 FALSE, /* pc_relative */
139 0, /* bitpos */
140 complain_overflow_dont, /* complain_on_overflow */
141 bfd_elf_generic_reloc, /* special_function */
142 "R_RISCV_TLS_DTPMOD32", /* name */
143 FALSE, /* partial_inplace */
144 0, /* src_mask */
145 MINUS_ONE, /* dst_mask */
146 FALSE), /* pcrel_offset */
147
148 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
149 0, /* rightshift */
150 4, /* size */
151 64, /* bitsize */
152 FALSE, /* pc_relative */
153 0, /* bitpos */
154 complain_overflow_dont, /* complain_on_overflow */
155 bfd_elf_generic_reloc, /* special_function */
156 "R_RISCV_TLS_DTPMOD64", /* name */
157 FALSE, /* partial_inplace */
158 0, /* src_mask */
159 MINUS_ONE, /* dst_mask */
160 FALSE), /* pcrel_offset */
161
162 HOWTO (R_RISCV_TLS_DTPREL32, /* type */
163 0, /* rightshift */
164 4, /* size */
165 32, /* bitsize */
166 FALSE, /* pc_relative */
167 0, /* bitpos */
168 complain_overflow_dont, /* complain_on_overflow */
169 bfd_elf_generic_reloc, /* special_function */
170 "R_RISCV_TLS_DTPREL32", /* name */
171 TRUE, /* partial_inplace */
172 0, /* src_mask */
173 MINUS_ONE, /* dst_mask */
174 FALSE), /* pcrel_offset */
175
176 HOWTO (R_RISCV_TLS_DTPREL64, /* type */
177 0, /* rightshift */
178 4, /* size */
179 64, /* bitsize */
180 FALSE, /* pc_relative */
181 0, /* bitpos */
182 complain_overflow_dont, /* complain_on_overflow */
183 bfd_elf_generic_reloc, /* special_function */
184 "R_RISCV_TLS_DTPREL64", /* name */
185 TRUE, /* partial_inplace */
186 0, /* src_mask */
187 MINUS_ONE, /* dst_mask */
188 FALSE), /* pcrel_offset */
189
190 HOWTO (R_RISCV_TLS_TPREL32, /* type */
191 0, /* rightshift */
192 2, /* size */
193 32, /* bitsize */
194 FALSE, /* pc_relative */
195 0, /* bitpos */
196 complain_overflow_dont, /* complain_on_overflow */
197 bfd_elf_generic_reloc, /* special_function */
198 "R_RISCV_TLS_TPREL32", /* name */
199 FALSE, /* partial_inplace */
200 0, /* src_mask */
201 MINUS_ONE, /* dst_mask */
202 FALSE), /* pcrel_offset */
203
204 HOWTO (R_RISCV_TLS_TPREL64, /* type */
205 0, /* rightshift */
206 4, /* size */
207 64, /* bitsize */
208 FALSE, /* pc_relative */
209 0, /* bitpos */
210 complain_overflow_dont, /* complain_on_overflow */
211 bfd_elf_generic_reloc, /* special_function */
212 "R_RISCV_TLS_TPREL64", /* name */
213 FALSE, /* partial_inplace */
214 0, /* src_mask */
215 MINUS_ONE, /* dst_mask */
216 FALSE), /* pcrel_offset */
217
218 /* Reserved for future relocs that the dynamic linker must understand. */
219 EMPTY_HOWTO (12),
220 EMPTY_HOWTO (13),
221 EMPTY_HOWTO (14),
222 EMPTY_HOWTO (15),
223
224 /* 12-bit PC-relative branch offset. */
225 HOWTO (R_RISCV_BRANCH, /* type */
226 0, /* rightshift */
227 2, /* size */
228 32, /* bitsize */
229 TRUE, /* pc_relative */
230 0, /* bitpos */
231 complain_overflow_signed, /* complain_on_overflow */
232 bfd_elf_generic_reloc, /* special_function */
233 "R_RISCV_BRANCH", /* name */
234 FALSE, /* partial_inplace */
235 0, /* src_mask */
236 ENCODE_SBTYPE_IMM (-1U), /* dst_mask */
237 TRUE), /* pcrel_offset */
238
239 /* 20-bit PC-relative jump offset. */
240 HOWTO (R_RISCV_JAL, /* type */
241 0, /* rightshift */
242 2, /* size */
243 32, /* bitsize */
244 TRUE, /* pc_relative */
245 0, /* bitpos */
246 complain_overflow_dont, /* complain_on_overflow */
247 bfd_elf_generic_reloc, /* special_function */
248 "R_RISCV_JAL", /* name */
249 FALSE, /* partial_inplace */
250 0, /* src_mask */
251 ENCODE_UJTYPE_IMM (-1U), /* dst_mask */
252 TRUE), /* pcrel_offset */
253
254 /* 32-bit PC-relative function call (AUIPC/JALR). */
255 HOWTO (R_RISCV_CALL, /* type */
256 0, /* rightshift */
257 2, /* size */
258 64, /* bitsize */
259 TRUE, /* pc_relative */
260 0, /* bitpos */
261 complain_overflow_dont, /* complain_on_overflow */
262 bfd_elf_generic_reloc, /* special_function */
263 "R_RISCV_CALL", /* name */
264 FALSE, /* partial_inplace */
265 0, /* src_mask */
266 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
267 /* dst_mask */
268 TRUE), /* pcrel_offset */
269
270 /* Like R_RISCV_CALL, but not locally binding. */
271 HOWTO (R_RISCV_CALL_PLT, /* type */
272 0, /* rightshift */
273 2, /* size */
274 64, /* bitsize */
275 TRUE, /* pc_relative */
276 0, /* bitpos */
277 complain_overflow_dont, /* complain_on_overflow */
278 bfd_elf_generic_reloc, /* special_function */
279 "R_RISCV_CALL_PLT", /* name */
280 FALSE, /* partial_inplace */
281 0, /* src_mask */
282 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
283 /* dst_mask */
284 TRUE), /* pcrel_offset */
285
286 /* High 20 bits of 32-bit PC-relative GOT access. */
287 HOWTO (R_RISCV_GOT_HI20, /* type */
288 0, /* rightshift */
289 2, /* size */
290 32, /* bitsize */
291 TRUE, /* pc_relative */
292 0, /* bitpos */
293 complain_overflow_dont, /* complain_on_overflow */
294 bfd_elf_generic_reloc, /* special_function */
295 "R_RISCV_GOT_HI20", /* name */
296 FALSE, /* partial_inplace */
297 0, /* src_mask */
298 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
299 FALSE), /* pcrel_offset */
300
301 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
302 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */
303 0, /* rightshift */
304 2, /* size */
305 32, /* bitsize */
306 TRUE, /* pc_relative */
307 0, /* bitpos */
308 complain_overflow_dont, /* complain_on_overflow */
309 bfd_elf_generic_reloc, /* special_function */
310 "R_RISCV_TLS_GOT_HI20", /* name */
311 FALSE, /* partial_inplace */
312 0, /* src_mask */
313 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
314 FALSE), /* pcrel_offset */
315
316 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
317 HOWTO (R_RISCV_TLS_GD_HI20, /* type */
318 0, /* rightshift */
319 2, /* size */
320 32, /* bitsize */
321 TRUE, /* pc_relative */
322 0, /* bitpos */
323 complain_overflow_dont, /* complain_on_overflow */
324 bfd_elf_generic_reloc, /* special_function */
325 "R_RISCV_TLS_GD_HI20", /* name */
326 FALSE, /* partial_inplace */
327 0, /* src_mask */
328 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
329 FALSE), /* pcrel_offset */
330
331 /* High 20 bits of 32-bit PC-relative reference. */
332 HOWTO (R_RISCV_PCREL_HI20, /* type */
333 0, /* rightshift */
334 2, /* size */
335 32, /* bitsize */
336 TRUE, /* pc_relative */
337 0, /* bitpos */
338 complain_overflow_dont, /* complain_on_overflow */
339 bfd_elf_generic_reloc, /* special_function */
340 "R_RISCV_PCREL_HI20", /* name */
341 FALSE, /* partial_inplace */
342 0, /* src_mask */
343 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
344 TRUE), /* pcrel_offset */
345
346 /* Low 12 bits of a 32-bit PC-relative load or add. */
347 HOWTO (R_RISCV_PCREL_LO12_I, /* type */
348 0, /* rightshift */
349 2, /* size */
350 32, /* bitsize */
351 FALSE, /* pc_relative */
352 0, /* bitpos */
353 complain_overflow_dont, /* complain_on_overflow */
354 bfd_elf_generic_reloc, /* special_function */
355 "R_RISCV_PCREL_LO12_I", /* name */
356 FALSE, /* partial_inplace */
357 0, /* src_mask */
358 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
359 FALSE), /* pcrel_offset */
360
361 /* Low 12 bits of a 32-bit PC-relative store. */
362 HOWTO (R_RISCV_PCREL_LO12_S, /* type */
363 0, /* rightshift */
364 2, /* size */
365 32, /* bitsize */
366 FALSE, /* pc_relative */
367 0, /* bitpos */
368 complain_overflow_dont, /* complain_on_overflow */
369 bfd_elf_generic_reloc, /* special_function */
370 "R_RISCV_PCREL_LO12_S", /* name */
371 FALSE, /* partial_inplace */
372 0, /* src_mask */
373 ENCODE_STYPE_IMM (-1U), /* dst_mask */
374 FALSE), /* pcrel_offset */
375
376 /* High 20 bits of 32-bit absolute address. */
377 HOWTO (R_RISCV_HI20, /* type */
378 0, /* rightshift */
379 2, /* size */
380 32, /* bitsize */
381 FALSE, /* pc_relative */
382 0, /* bitpos */
383 complain_overflow_dont, /* complain_on_overflow */
384 bfd_elf_generic_reloc, /* special_function */
385 "R_RISCV_HI20", /* name */
386 FALSE, /* partial_inplace */
387 0, /* src_mask */
388 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
389 FALSE), /* pcrel_offset */
390
391 /* High 12 bits of 32-bit load or add. */
392 HOWTO (R_RISCV_LO12_I, /* type */
393 0, /* rightshift */
394 2, /* size */
395 32, /* bitsize */
396 FALSE, /* pc_relative */
397 0, /* bitpos */
398 complain_overflow_dont, /* complain_on_overflow */
399 bfd_elf_generic_reloc, /* special_function */
400 "R_RISCV_LO12_I", /* name */
401 FALSE, /* partial_inplace */
402 0, /* src_mask */
403 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
404 FALSE), /* pcrel_offset */
405
406 /* High 12 bits of 32-bit store. */
407 HOWTO (R_RISCV_LO12_S, /* type */
408 0, /* rightshift */
409 2, /* size */
410 32, /* bitsize */
411 FALSE, /* pc_relative */
412 0, /* bitpos */
413 complain_overflow_dont, /* complain_on_overflow */
414 bfd_elf_generic_reloc, /* special_function */
415 "R_RISCV_LO12_S", /* name */
416 FALSE, /* partial_inplace */
417 0, /* src_mask */
418 ENCODE_STYPE_IMM (-1U), /* dst_mask */
419 FALSE), /* pcrel_offset */
420
421 /* High 20 bits of TLS LE thread pointer offset. */
422 HOWTO (R_RISCV_TPREL_HI20, /* type */
423 0, /* rightshift */
424 2, /* size */
425 32, /* bitsize */
426 FALSE, /* pc_relative */
427 0, /* bitpos */
428 complain_overflow_signed, /* complain_on_overflow */
429 bfd_elf_generic_reloc, /* special_function */
430 "R_RISCV_TPREL_HI20", /* name */
431 TRUE, /* partial_inplace */
432 0, /* src_mask */
433 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
434 FALSE), /* pcrel_offset */
435
436 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
437 HOWTO (R_RISCV_TPREL_LO12_I, /* type */
438 0, /* rightshift */
439 2, /* size */
440 32, /* bitsize */
441 FALSE, /* pc_relative */
442 0, /* bitpos */
443 complain_overflow_signed, /* complain_on_overflow */
444 bfd_elf_generic_reloc, /* special_function */
445 "R_RISCV_TPREL_LO12_I", /* name */
446 FALSE, /* partial_inplace */
447 0, /* src_mask */
448 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
449 FALSE), /* pcrel_offset */
450
451 /* Low 12 bits of TLS LE thread pointer offset for stores. */
452 HOWTO (R_RISCV_TPREL_LO12_S, /* type */
453 0, /* rightshift */
454 2, /* size */
455 32, /* bitsize */
456 FALSE, /* pc_relative */
457 0, /* bitpos */
458 complain_overflow_signed, /* complain_on_overflow */
459 bfd_elf_generic_reloc, /* special_function */
460 "R_RISCV_TPREL_LO12_S", /* name */
461 FALSE, /* partial_inplace */
462 0, /* src_mask */
463 ENCODE_STYPE_IMM (-1U), /* dst_mask */
464 FALSE), /* pcrel_offset */
465
466 /* TLS LE thread pointer usage. May be relaxed. */
467 HOWTO (R_RISCV_TPREL_ADD, /* type */
468 0, /* rightshift */
469 2, /* size */
470 32, /* bitsize */
471 FALSE, /* pc_relative */
472 0, /* bitpos */
473 complain_overflow_dont, /* complain_on_overflow */
474 bfd_elf_generic_reloc, /* special_function */
475 "R_RISCV_TPREL_ADD", /* name */
476 TRUE, /* partial_inplace */
477 0, /* src_mask */
478 0, /* dst_mask */
479 FALSE), /* pcrel_offset */
480
481 /* 8-bit in-place addition, for local label subtraction. */
482 HOWTO (R_RISCV_ADD8, /* type */
483 0, /* rightshift */
484 0, /* size */
485 8, /* bitsize */
486 FALSE, /* pc_relative */
487 0, /* bitpos */
488 complain_overflow_dont, /* complain_on_overflow */
489 riscv_elf_add_sub_reloc, /* special_function */
490 "R_RISCV_ADD8", /* name */
491 FALSE, /* partial_inplace */
492 0, /* src_mask */
493 MINUS_ONE, /* dst_mask */
494 FALSE), /* pcrel_offset */
495
496 /* 16-bit in-place addition, for local label subtraction. */
497 HOWTO (R_RISCV_ADD16, /* type */
498 0, /* rightshift */
499 1, /* size */
500 16, /* bitsize */
501 FALSE, /* pc_relative */
502 0, /* bitpos */
503 complain_overflow_dont, /* complain_on_overflow */
504 riscv_elf_add_sub_reloc, /* special_function */
505 "R_RISCV_ADD16", /* name */
506 FALSE, /* partial_inplace */
507 0, /* src_mask */
508 MINUS_ONE, /* dst_mask */
509 FALSE), /* pcrel_offset */
510
511 /* 32-bit in-place addition, for local label subtraction. */
512 HOWTO (R_RISCV_ADD32, /* type */
513 0, /* rightshift */
514 2, /* size */
515 32, /* bitsize */
516 FALSE, /* pc_relative */
517 0, /* bitpos */
518 complain_overflow_dont, /* complain_on_overflow */
519 riscv_elf_add_sub_reloc, /* special_function */
520 "R_RISCV_ADD32", /* name */
521 FALSE, /* partial_inplace */
522 0, /* src_mask */
523 MINUS_ONE, /* dst_mask */
524 FALSE), /* pcrel_offset */
525
526 /* 64-bit in-place addition, for local label subtraction. */
527 HOWTO (R_RISCV_ADD64, /* type */
528 0, /* rightshift */
529 4, /* size */
530 64, /* bitsize */
531 FALSE, /* pc_relative */
532 0, /* bitpos */
533 complain_overflow_dont, /* complain_on_overflow */
534 riscv_elf_add_sub_reloc, /* special_function */
535 "R_RISCV_ADD64", /* name */
536 FALSE, /* partial_inplace */
537 0, /* src_mask */
538 MINUS_ONE, /* dst_mask */
539 FALSE), /* pcrel_offset */
540
541 /* 8-bit in-place addition, for local label subtraction. */
542 HOWTO (R_RISCV_SUB8, /* type */
543 0, /* rightshift */
544 0, /* size */
545 8, /* bitsize */
546 FALSE, /* pc_relative */
547 0, /* bitpos */
548 complain_overflow_dont, /* complain_on_overflow */
549 riscv_elf_add_sub_reloc, /* special_function */
550 "R_RISCV_SUB8", /* name */
551 FALSE, /* partial_inplace */
552 0, /* src_mask */
553 MINUS_ONE, /* dst_mask */
554 FALSE), /* pcrel_offset */
555
556 /* 16-bit in-place addition, for local label subtraction. */
557 HOWTO (R_RISCV_SUB16, /* type */
558 0, /* rightshift */
559 1, /* size */
560 16, /* bitsize */
561 FALSE, /* pc_relative */
562 0, /* bitpos */
563 complain_overflow_dont, /* complain_on_overflow */
564 riscv_elf_add_sub_reloc, /* special_function */
565 "R_RISCV_SUB16", /* name */
566 FALSE, /* partial_inplace */
567 0, /* src_mask */
568 MINUS_ONE, /* dst_mask */
569 FALSE), /* pcrel_offset */
570
571 /* 32-bit in-place addition, for local label subtraction. */
572 HOWTO (R_RISCV_SUB32, /* type */
573 0, /* rightshift */
574 2, /* size */
575 32, /* bitsize */
576 FALSE, /* pc_relative */
577 0, /* bitpos */
578 complain_overflow_dont, /* complain_on_overflow */
579 riscv_elf_add_sub_reloc, /* special_function */
580 "R_RISCV_SUB32", /* name */
581 FALSE, /* partial_inplace */
582 0, /* src_mask */
583 MINUS_ONE, /* dst_mask */
584 FALSE), /* pcrel_offset */
585
586 /* 64-bit in-place addition, for local label subtraction. */
587 HOWTO (R_RISCV_SUB64, /* type */
588 0, /* rightshift */
589 4, /* size */
590 64, /* bitsize */
591 FALSE, /* pc_relative */
592 0, /* bitpos */
593 complain_overflow_dont, /* complain_on_overflow */
594 riscv_elf_add_sub_reloc, /* special_function */
595 "R_RISCV_SUB64", /* name */
596 FALSE, /* partial_inplace */
597 0, /* src_mask */
598 MINUS_ONE, /* dst_mask */
599 FALSE), /* pcrel_offset */
600
601 /* GNU extension to record C++ vtable hierarchy */
602 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
603 0, /* rightshift */
604 4, /* size */
605 0, /* bitsize */
606 FALSE, /* pc_relative */
607 0, /* bitpos */
608 complain_overflow_dont, /* complain_on_overflow */
609 NULL, /* special_function */
610 "R_RISCV_GNU_VTINHERIT", /* name */
611 FALSE, /* partial_inplace */
612 0, /* src_mask */
613 0, /* dst_mask */
614 FALSE), /* pcrel_offset */
615
616 /* GNU extension to record C++ vtable member usage */
617 HOWTO (R_RISCV_GNU_VTENTRY, /* type */
618 0, /* rightshift */
619 4, /* size */
620 0, /* bitsize */
621 FALSE, /* pc_relative */
622 0, /* bitpos */
623 complain_overflow_dont, /* complain_on_overflow */
624 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
625 "R_RISCV_GNU_VTENTRY", /* name */
626 FALSE, /* partial_inplace */
627 0, /* src_mask */
628 0, /* dst_mask */
629 FALSE), /* pcrel_offset */
630
631 /* Indicates an alignment statement. The addend field encodes how many
632 bytes of NOPs follow the statement. The desired alignment is the
633 addend rounded up to the next power of two. */
634 HOWTO (R_RISCV_ALIGN, /* type */
635 0, /* rightshift */
636 2, /* size */
637 0, /* bitsize */
638 FALSE, /* pc_relative */
639 0, /* bitpos */
640 complain_overflow_dont, /* complain_on_overflow */
641 bfd_elf_generic_reloc, /* special_function */
642 "R_RISCV_ALIGN", /* name */
643 FALSE, /* partial_inplace */
644 0, /* src_mask */
645 0, /* dst_mask */
646 TRUE), /* pcrel_offset */
647
648 /* 8-bit PC-relative branch offset. */
649 HOWTO (R_RISCV_RVC_BRANCH, /* type */
650 0, /* rightshift */
651 2, /* size */
652 32, /* bitsize */
653 TRUE, /* pc_relative */
654 0, /* bitpos */
655 complain_overflow_signed, /* complain_on_overflow */
656 bfd_elf_generic_reloc, /* special_function */
657 "R_RISCV_RVC_BRANCH", /* name */
658 FALSE, /* partial_inplace */
659 0, /* src_mask */
660 ENCODE_RVC_B_IMM (-1U), /* dst_mask */
661 TRUE), /* pcrel_offset */
662
663 /* 11-bit PC-relative jump offset. */
664 HOWTO (R_RISCV_RVC_JUMP, /* type */
665 0, /* rightshift */
666 2, /* size */
667 32, /* bitsize */
668 TRUE, /* pc_relative */
669 0, /* bitpos */
670 complain_overflow_dont, /* complain_on_overflow */
671 bfd_elf_generic_reloc, /* special_function */
672 "R_RISCV_RVC_JUMP", /* name */
673 FALSE, /* partial_inplace */
674 0, /* src_mask */
675 ENCODE_RVC_J_IMM (-1U), /* dst_mask */
676 TRUE), /* pcrel_offset */
677
678 /* High 6 bits of 18-bit absolute address. */
679 HOWTO (R_RISCV_RVC_LUI, /* type */
680 0, /* rightshift */
681 2, /* size */
682 32, /* bitsize */
683 FALSE, /* pc_relative */
684 0, /* bitpos */
685 complain_overflow_dont, /* complain_on_overflow */
686 bfd_elf_generic_reloc, /* special_function */
687 "R_RISCV_RVC_LUI", /* name */
688 FALSE, /* partial_inplace */
689 0, /* src_mask */
690 ENCODE_RVC_IMM (-1U), /* dst_mask */
691 FALSE), /* pcrel_offset */
692
693 /* GP-relative load. */
694 HOWTO (R_RISCV_GPREL_I, /* type */
695 0, /* rightshift */
696 2, /* size */
697 32, /* bitsize */
698 FALSE, /* pc_relative */
699 0, /* bitpos */
700 complain_overflow_dont, /* complain_on_overflow */
701 bfd_elf_generic_reloc, /* special_function */
702 "R_RISCV_GPREL_I", /* name */
703 FALSE, /* partial_inplace */
704 0, /* src_mask */
705 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
706 FALSE), /* pcrel_offset */
707
708 /* GP-relative store. */
709 HOWTO (R_RISCV_GPREL_S, /* type */
710 0, /* rightshift */
711 2, /* size */
712 32, /* bitsize */
713 FALSE, /* pc_relative */
714 0, /* bitpos */
715 complain_overflow_dont, /* complain_on_overflow */
716 bfd_elf_generic_reloc, /* special_function */
717 "R_RISCV_GPREL_S", /* name */
718 FALSE, /* partial_inplace */
719 0, /* src_mask */
720 ENCODE_STYPE_IMM (-1U), /* dst_mask */
721 FALSE), /* pcrel_offset */
722
723 /* TP-relative TLS LE load. */
724 HOWTO (R_RISCV_TPREL_I, /* type */
725 0, /* rightshift */
726 2, /* size */
727 32, /* bitsize */
728 FALSE, /* pc_relative */
729 0, /* bitpos */
730 complain_overflow_signed, /* complain_on_overflow */
731 bfd_elf_generic_reloc, /* special_function */
732 "R_RISCV_TPREL_I", /* name */
733 FALSE, /* partial_inplace */
734 0, /* src_mask */
735 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
736 FALSE), /* pcrel_offset */
737
738 /* TP-relative TLS LE store. */
739 HOWTO (R_RISCV_TPREL_S, /* type */
740 0, /* rightshift */
741 2, /* size */
742 32, /* bitsize */
743 FALSE, /* pc_relative */
744 0, /* bitpos */
745 complain_overflow_signed, /* complain_on_overflow */
746 bfd_elf_generic_reloc, /* special_function */
747 "R_RISCV_TPREL_S", /* name */
748 FALSE, /* partial_inplace */
749 0, /* src_mask */
750 ENCODE_STYPE_IMM (-1U), /* dst_mask */
751 FALSE), /* pcrel_offset */
752
753 /* The paired relocation may be relaxed. */
754 HOWTO (R_RISCV_RELAX, /* type */
755 0, /* rightshift */
756 3, /* size */
757 0, /* bitsize */
758 FALSE, /* pc_relative */
759 0, /* bitpos */
760 complain_overflow_dont, /* complain_on_overflow */
761 bfd_elf_generic_reloc, /* special_function */
762 "R_RISCV_RELAX", /* name */
763 FALSE, /* partial_inplace */
764 0, /* src_mask */
765 0, /* dst_mask */
766 FALSE), /* pcrel_offset */
767
768 /* 6-bit in-place addition, for local label subtraction. */
769 HOWTO (R_RISCV_SUB6, /* type */
770 0, /* rightshift */
771 0, /* size */
772 8, /* bitsize */
773 FALSE, /* pc_relative */
774 0, /* bitpos */
775 complain_overflow_dont, /* complain_on_overflow */
776 riscv_elf_add_sub_reloc, /* special_function */
777 "R_RISCV_SUB6", /* name */
778 FALSE, /* partial_inplace */
779 0, /* src_mask */
780 0x3f, /* dst_mask */
781 FALSE), /* pcrel_offset */
782
783 /* 6-bit in-place setting, for local label subtraction. */
784 HOWTO (R_RISCV_SET6, /* type */
785 0, /* rightshift */
786 0, /* size */
787 8, /* bitsize */
788 FALSE, /* pc_relative */
789 0, /* bitpos */
790 complain_overflow_dont, /* complain_on_overflow */
791 bfd_elf_generic_reloc, /* special_function */
792 "R_RISCV_SET6", /* name */
793 FALSE, /* partial_inplace */
794 0, /* src_mask */
795 0x3f, /* dst_mask */
796 FALSE), /* pcrel_offset */
797
798 /* 8-bit in-place setting, for local label subtraction. */
799 HOWTO (R_RISCV_SET8, /* type */
800 0, /* rightshift */
801 0, /* size */
802 8, /* bitsize */
803 FALSE, /* pc_relative */
804 0, /* bitpos */
805 complain_overflow_dont, /* complain_on_overflow */
806 bfd_elf_generic_reloc, /* special_function */
807 "R_RISCV_SET8", /* name */
808 FALSE, /* partial_inplace */
809 0, /* src_mask */
810 MINUS_ONE, /* dst_mask */
811 FALSE), /* pcrel_offset */
812
813 /* 16-bit in-place setting, for local label subtraction. */
814 HOWTO (R_RISCV_SET16, /* type */
815 0, /* rightshift */
816 1, /* size */
817 16, /* bitsize */
818 FALSE, /* pc_relative */
819 0, /* bitpos */
820 complain_overflow_dont, /* complain_on_overflow */
821 bfd_elf_generic_reloc, /* special_function */
822 "R_RISCV_SET16", /* name */
823 FALSE, /* partial_inplace */
824 0, /* src_mask */
825 MINUS_ONE, /* dst_mask */
826 FALSE), /* pcrel_offset */
827
828 /* 32-bit in-place setting, for local label subtraction. */
829 HOWTO (R_RISCV_SET32, /* type */
830 0, /* rightshift */
831 2, /* size */
832 32, /* bitsize */
833 FALSE, /* pc_relative */
834 0, /* bitpos */
835 complain_overflow_dont, /* complain_on_overflow */
836 bfd_elf_generic_reloc, /* special_function */
837 "R_RISCV_SET32", /* name */
838 FALSE, /* partial_inplace */
839 0, /* src_mask */
840 MINUS_ONE, /* dst_mask */
841 FALSE), /* pcrel_offset */
842
843 /* 32-bit PC relative. */
844 HOWTO (R_RISCV_32_PCREL, /* type */
845 0, /* rightshift */
846 2, /* size */
847 32, /* bitsize */
848 TRUE, /* pc_relative */
849 0, /* bitpos */
850 complain_overflow_dont, /* complain_on_overflow */
851 bfd_elf_generic_reloc, /* special_function */
852 "R_RISCV_32_PCREL", /* name */
853 FALSE, /* partial_inplace */
854 0, /* src_mask */
855 MINUS_ONE, /* dst_mask */
856 FALSE), /* pcrel_offset */
857 };
858
859 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
860
861 struct elf_reloc_map
862 {
863 bfd_reloc_code_real_type bfd_val;
864 enum elf_riscv_reloc_type elf_val;
865 };
866
867 static const struct elf_reloc_map riscv_reloc_map[] =
868 {
869 { BFD_RELOC_NONE, R_RISCV_NONE },
870 { BFD_RELOC_32, R_RISCV_32 },
871 { BFD_RELOC_64, R_RISCV_64 },
872 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
873 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
874 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
875 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
876 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
877 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
878 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
879 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
880 { BFD_RELOC_CTOR, R_RISCV_64 },
881 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
882 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
883 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
884 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
885 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
886 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
887 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
888 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
889 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
890 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
891 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
892 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
893 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
894 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
895 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
896 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
897 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
898 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
899 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
900 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
901 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
902 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
903 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
904 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
905 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
906 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
907 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
908 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
909 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
910 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
911 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
912 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
913 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
914 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
915 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
916 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
917 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
918 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
919 };
920
921 /* Given a BFD reloc type, return a howto structure. */
922
923 reloc_howto_type *
924 riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
925 bfd_reloc_code_real_type code)
926 {
927 unsigned int i;
928
929 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
930 if (riscv_reloc_map[i].bfd_val == code)
931 return &howto_table[(int) riscv_reloc_map[i].elf_val];
932
933 bfd_set_error (bfd_error_bad_value);
934 return NULL;
935 }
936
937 reloc_howto_type *
938 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
939 {
940 unsigned int i;
941
942 for (i = 0; i < ARRAY_SIZE (howto_table); i++)
943 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
944 return &howto_table[i];
945
946 return NULL;
947 }
948
949 reloc_howto_type *
950 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
951 {
952 if (r_type >= ARRAY_SIZE (howto_table))
953 {
954 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
955 abfd, r_type);
956 bfd_set_error (bfd_error_bad_value);
957 return NULL;
958 }
959 return &howto_table[r_type];
960 }
961
962 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
963
964 static bfd_reloc_status_type
965 riscv_elf_add_sub_reloc (bfd *abfd,
966 arelent *reloc_entry,
967 asymbol *symbol,
968 void *data,
969 asection *input_section,
970 bfd *output_bfd,
971 char **error_message ATTRIBUTE_UNUSED)
972 {
973 reloc_howto_type *howto = reloc_entry->howto;
974 bfd_vma relocation;
975
976 if (output_bfd != NULL
977 && (symbol->flags & BSF_SECTION_SYM) == 0
978 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
979 {
980 reloc_entry->address += input_section->output_offset;
981 return bfd_reloc_ok;
982 }
983
984 if (output_bfd != NULL)
985 return bfd_reloc_continue;
986
987 relocation = symbol->value + symbol->section->output_section->vma
988 + symbol->section->output_offset + reloc_entry->addend;
989 bfd_vma old_value = bfd_get (howto->bitsize, abfd,
990 data + reloc_entry->address);
991
992 switch (howto->type)
993 {
994 case R_RISCV_ADD8:
995 case R_RISCV_ADD16:
996 case R_RISCV_ADD32:
997 case R_RISCV_ADD64:
998 relocation = old_value + relocation;
999 break;
1000 case R_RISCV_SUB6:
1001 case R_RISCV_SUB8:
1002 case R_RISCV_SUB16:
1003 case R_RISCV_SUB32:
1004 case R_RISCV_SUB64:
1005 relocation = old_value - relocation;
1006 break;
1007 }
1008 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
1009
1010 return bfd_reloc_ok;
1011 }
1012
1013 /* Parsing subset version.
1014
1015 Return Value:
1016 Points to the end of version
1017
1018 Arguments:
1019 `rps`: Hooks and status for parsing subset.
1020 `march`: Full arch string.
1021 `p`: Curent parsing position.
1022 `major_version`: Parsing result of major version, using
1023 default_major_version if version is not present in arch string.
1024 `minor_version`: Parsing result of minor version, set to 0 if version is
1025 not present in arch string, but set to `default_minor_version` if
1026 `major_version` using default_major_version.
1027 `std_ext_p`: True if parsing std extension.
1028 `use_default_version`: Set it to True if we need the default version. */
1029
1030 static const char *
1031 riscv_parsing_subset_version (riscv_parse_subset_t *rps,
1032 const char *march,
1033 const char *p,
1034 unsigned *major_version,
1035 unsigned *minor_version,
1036 bfd_boolean std_ext_p,
1037 bfd_boolean *use_default_version)
1038 {
1039 bfd_boolean major_p = TRUE;
1040 unsigned version = 0;
1041 char np;
1042
1043 *major_version = 0;
1044 *minor_version = 0;
1045 for (; *p; ++p)
1046 {
1047 if (*p == 'p')
1048 {
1049 np = *(p + 1);
1050
1051 if (!ISDIGIT (np))
1052 {
1053 /* Might be beginning of `p` extension. */
1054 if (std_ext_p)
1055 {
1056 *major_version = version;
1057 *minor_version = 0;
1058 return p;
1059 }
1060 else
1061 {
1062 rps->error_handler
1063 (_("-march=%s: Expect number after `%dp'."),
1064 march, version);
1065 return NULL;
1066 }
1067 }
1068
1069 *major_version = version;
1070 major_p = FALSE;
1071 version = 0;
1072 }
1073 else if (ISDIGIT (*p))
1074 version = (version * 10) + (*p - '0');
1075 else
1076 break;
1077 }
1078
1079 if (major_p)
1080 *major_version = version;
1081 else
1082 *minor_version = version;
1083
1084 /* We can not find any version in string, need to parse default version. */
1085 if (use_default_version != NULL
1086 && *major_version == 0
1087 && *minor_version == 0)
1088 *use_default_version = TRUE;
1089 return p;
1090 }
1091
1092 /* Return string which contain all supported standard extensions in
1093 canonical order. */
1094
1095 const char *
1096 riscv_supported_std_ext (void)
1097 {
1098 return "mafdqlcbjtpvn";
1099 }
1100
1101 /* Parsing function for standard extensions.
1102
1103 Return Value:
1104 Points to the end of extensions.
1105
1106 Arguments:
1107 `rps`: Hooks and status for parsing subset.
1108 `march`: Full arch string.
1109 `p`: Curent parsing position. */
1110
1111 static const char *
1112 riscv_parse_std_ext (riscv_parse_subset_t *rps,
1113 const char *march,
1114 const char *p)
1115 {
1116 const char *all_std_exts = riscv_supported_std_ext ();
1117 const char *std_exts = all_std_exts;
1118 unsigned major_version = 0;
1119 unsigned minor_version = 0;
1120 char std_ext = '\0';
1121 bfd_boolean use_default_version = FALSE;
1122
1123 /* First letter must start with i, e or g. */
1124 switch (*p)
1125 {
1126 case 'i':
1127 p = riscv_parsing_subset_version (rps,
1128 march,
1129 ++p,
1130 &major_version,
1131 &minor_version,
1132 /* std_ext_p= */TRUE,
1133 &use_default_version);
1134
1135 /* Find the default version if needed. */
1136 if (use_default_version
1137 && rps->get_default_version != NULL)
1138 rps->get_default_version ("i",
1139 &major_version,
1140 &minor_version);
1141 riscv_add_subset (rps->subset_list, "i",
1142 major_version, minor_version);
1143 break;
1144
1145 case 'e':
1146 p = riscv_parsing_subset_version (rps,
1147 march,
1148 ++p,
1149 &major_version,
1150 &minor_version,
1151 /* std_ext_p= */TRUE,
1152 &use_default_version);
1153
1154 /* Find the default version if needed. */
1155 if (use_default_version
1156 && rps->get_default_version != NULL)
1157 rps->get_default_version ("e",
1158 &major_version,
1159 &minor_version);
1160 riscv_add_subset (rps->subset_list, "e",
1161 major_version, minor_version);
1162
1163 /* i-ext must be enabled. */
1164 if (rps->get_default_version != NULL)
1165 rps->get_default_version ("i",
1166 &major_version,
1167 &minor_version);
1168 riscv_add_subset (rps->subset_list, "i",
1169 major_version, minor_version);
1170
1171 if (*rps->xlen > 32)
1172 {
1173 rps->error_handler
1174 (_("-march=%s: rv%de is not a valid base ISA"),
1175 march, *rps->xlen);
1176 return NULL;
1177 }
1178 break;
1179
1180 case 'g':
1181 /* The g-ext shouldn't has the version, so we just
1182 skip the setting if user set a version to it. */
1183 p = riscv_parsing_subset_version (rps,
1184 march,
1185 ++p,
1186 &major_version,
1187 &minor_version,
1188 TRUE,
1189 &use_default_version);
1190
1191 /* i-ext must be enabled. */
1192 if (rps->get_default_version != NULL)
1193 rps->get_default_version ("i",
1194 &major_version,
1195 &minor_version);
1196 riscv_add_subset (rps->subset_list, "i",
1197 major_version, minor_version);
1198
1199 for ( ; *std_exts != 'q'; std_exts++)
1200 {
1201 const char subset[] = {*std_exts, '\0'};
1202
1203 if (rps->get_default_version != NULL)
1204 rps->get_default_version (subset,
1205 &major_version,
1206 &minor_version);
1207 riscv_add_subset (rps->subset_list, subset,
1208 major_version, minor_version);
1209 }
1210 break;
1211
1212 default:
1213 rps->error_handler
1214 (_("-march=%s: first ISA subset must be `e', `i' or `g'"), march);
1215 return NULL;
1216 }
1217
1218 /* The riscv_parsing_subset_version may set `p` to NULL, so I think we should
1219 skip parsing the string if `p` is NULL or value of `p` is `\0`. */
1220 while (p != NULL && *p != '\0')
1221 {
1222 char subset[2] = {0, 0};
1223
1224 if (*p == 'x' || *p == 's' || *p == 'z')
1225 break;
1226
1227 if (*p == '_')
1228 {
1229 p++;
1230 continue;
1231 }
1232
1233 std_ext = *p;
1234
1235 /* Checking canonical order. */
1236 while (*std_exts && std_ext != *std_exts) std_exts++;
1237
1238 if (std_ext != *std_exts)
1239 {
1240 if (strchr (all_std_exts, std_ext) == NULL)
1241 rps->error_handler
1242 (_("-march=%s: unsupported ISA subset `%c'"), march, *p);
1243 else
1244 rps->error_handler
1245 (_("-march=%s: ISA string is not in canonical order. `%c'"),
1246 march, *p);
1247 return NULL;
1248 }
1249
1250 std_exts++;
1251
1252 use_default_version = FALSE;
1253 subset[0] = std_ext;
1254 p = riscv_parsing_subset_version (rps,
1255 march,
1256 ++p,
1257 &major_version,
1258 &minor_version,
1259 TRUE,
1260 &use_default_version);
1261
1262 /* Find the default version if needed. */
1263 if (use_default_version
1264 && rps->get_default_version != NULL)
1265 rps->get_default_version (subset,
1266 &major_version,
1267 &minor_version);
1268 riscv_add_subset (rps->subset_list, subset,
1269 major_version, minor_version);
1270 }
1271 return p;
1272 }
1273
1274 /* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1275
1276 riscv_isa_ext_class_t
1277 riscv_get_prefix_class (const char *arch)
1278 {
1279 switch (*arch)
1280 {
1281 case 's': return RV_ISA_CLASS_S;
1282 case 'x': return RV_ISA_CLASS_X;
1283 case 'z': return RV_ISA_CLASS_Z;
1284 default: return RV_ISA_CLASS_UNKNOWN;
1285 }
1286 }
1287
1288 /* Structure describing parameters to use when parsing a particular
1289 riscv_isa_ext_class_t. One of these should be provided for each
1290 possible class, except RV_ISA_CLASS_UNKNOWN. */
1291
1292 typedef struct riscv_parse_config
1293 {
1294 /* Class of the extension. */
1295 riscv_isa_ext_class_t class;
1296
1297 /* Lower-case prefix string for error printing
1298 and internal parser usage, e.g. "z", "x". */
1299 const char *prefix;
1300
1301 /* Predicate which is used for checking whether
1302 this is a "known" extension. For 'x',
1303 it always returns true (since they are by
1304 definition non-standard and cannot be known. */
1305 bfd_boolean (*ext_valid_p) (const char *);
1306 } riscv_parse_config_t;
1307
1308 /* Parse a generic prefixed extension.
1309 `rps`: Hooks and status for parsing subset.
1310 `march`: The full architecture string as passed in by "-march=...".
1311 `p`: Point from which to start parsing the -march string.
1312 `config`: What class of extensions to parse, predicate funcs,
1313 and strings to use in error reporting. */
1314
1315 static const char *
1316 riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
1317 const char *march,
1318 const char *p,
1319 const riscv_parse_config_t *config)
1320 {
1321 unsigned major_version = 0;
1322 unsigned minor_version = 0;
1323 const char *last_name;
1324 riscv_isa_ext_class_t class;
1325 bfd_boolean use_default_version;
1326
1327 while (*p)
1328 {
1329 if (*p == '_')
1330 {
1331 p++;
1332 continue;
1333 }
1334
1335 /* Assert that the current extension specifier matches our parsing
1336 class. */
1337 class = riscv_get_prefix_class (p);
1338 if (class != config->class)
1339 break;
1340
1341 char *subset = xstrdup (p);
1342 char *q = subset;
1343 const char *end_of_version;
1344
1345 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
1346 ;
1347
1348 use_default_version = FALSE;
1349 end_of_version =
1350 riscv_parsing_subset_version (rps, march, q, &major_version,
1351 &minor_version, FALSE,
1352 &use_default_version);
1353 *q = '\0';
1354
1355 /* Check that the name is valid.
1356 For 'x', anything goes but it cannot simply be 'x'.
1357 For 's', it must be known from a list and cannot simply be 's'.
1358 For 'z', it must be known from a list and cannot simply be 'z'. */
1359
1360 /* Check that the extension name is well-formed. */
1361 if (!config->ext_valid_p (subset))
1362 {
1363 rps->error_handler
1364 (_("-march=%s: Invalid or unknown %s ISA extension: '%s'"),
1365 march, config->prefix, subset);
1366 free (subset);
1367 return NULL;
1368 }
1369
1370 /* Check that the last item is not the same as this. */
1371 last_name = rps->subset_list->tail->name;
1372 if (!strcasecmp (last_name, subset))
1373 {
1374 rps->error_handler
1375 (_("-march=%s: Duplicate %s ISA extension: \'%s\'"),
1376 march, config->prefix, subset);
1377 free (subset);
1378 return NULL;
1379 }
1380
1381 /* Check that we are in alphabetical order within the subset. */
1382 if (!strncasecmp (last_name, config->prefix, 1)
1383 && strcasecmp (last_name, subset) > 0)
1384 {
1385 rps->error_handler
1386 (_("\
1387 -march=%s: %s ISA extension not in alphabetical order: \'%s\' must come before \'%s\'."),
1388 march, config->prefix, subset, last_name);
1389 free (subset);
1390 return NULL;
1391 }
1392
1393 /* Find the default version if needed. */
1394 if (use_default_version
1395 && rps->get_default_version != NULL)
1396 rps->get_default_version (subset,
1397 &major_version,
1398 &minor_version);
1399 riscv_add_subset (rps->subset_list, subset,
1400 major_version, minor_version);
1401
1402 free (subset);
1403 p += end_of_version - subset;
1404
1405 if (*p != '\0' && *p != '_')
1406 {
1407 rps->error_handler (_("-march=%s: %s must separate with _"),
1408 march, config->prefix);
1409 return NULL;
1410 }
1411 }
1412
1413 return p;
1414 }
1415
1416 /* List of Z-class extensions that binutils should know about.
1417 Whether or not a particular entry is in this list will
1418 dictate if gas/ld will accept its presence in the -march
1419 string.
1420
1421 Example: To add an extension called "Zbb" (bitmanip base extension),
1422 add "zbb" string to the list (all lowercase).
1423
1424 Keep this list alphabetically ordered. */
1425
1426 static const char * const riscv_std_z_ext_strtab[] =
1427 {
1428 "zicsr", NULL
1429 };
1430
1431 /* Same as `riscv_std_z_ext_strtab', but for S-class extensions. */
1432
1433 static const char * const riscv_std_s_ext_strtab[] =
1434 {
1435 NULL
1436 };
1437
1438 /* For the extension EXT, search through the list of known extensions
1439 KNOWN_EXTS for a match, and return TRUE if found. */
1440
1441 static bfd_boolean
1442 riscv_multi_letter_ext_valid_p (const char *ext,
1443 const char *const *known_exts)
1444 {
1445 size_t i;
1446
1447 for (i = 0; known_exts[i]; ++i)
1448 if (!strcmp (ext, known_exts[i]))
1449 return TRUE;
1450
1451 return FALSE;
1452 }
1453
1454 /* Predicator function for x-prefixed extensions.
1455 Anything goes, except the literal 'x'. */
1456
1457 static bfd_boolean
1458 riscv_ext_x_valid_p (const char *arg)
1459 {
1460 if (!strcasecmp (arg, "x"))
1461 return FALSE;
1462
1463 return TRUE;
1464 }
1465
1466 /* Predicator functions for z-prefixed extensions.
1467 Only known z-extensions are permitted. */
1468
1469 static bfd_boolean
1470 riscv_ext_z_valid_p (const char *arg)
1471 {
1472 return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
1473 }
1474
1475 /* Predicator function for 's' prefixed extensions.
1476 Must be either literal 's', or a known s-prefixed extension. */
1477
1478 static bfd_boolean
1479 riscv_ext_s_valid_p (const char *arg)
1480 {
1481 return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
1482 }
1483
1484 /* Parsing order that is specified by the ISA manual. */
1485
1486 static const riscv_parse_config_t parse_config[] =
1487 {
1488 {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
1489 {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
1490 {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
1491 {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
1492 };
1493
1494 /* Function for parsing arch string.
1495
1496 Return Value:
1497 Return TRUE on success.
1498
1499 Arguments:
1500 `rps`: Hooks and status for parsing subset.
1501 `arch`: Arch string. */
1502
1503 bfd_boolean
1504 riscv_parse_subset (riscv_parse_subset_t *rps,
1505 const char *arch)
1506 {
1507 const char *p = arch;
1508 size_t i;
1509
1510 if (strncmp (p, "rv32", 4) == 0)
1511 {
1512 *rps->xlen = 32;
1513 p += 4;
1514 }
1515 else if (strncmp (p, "rv64", 4) == 0)
1516 {
1517 *rps->xlen = 64;
1518 p += 4;
1519 }
1520 else
1521 {
1522 rps->error_handler
1523 (_("-march=%s: ISA string must begin with rv32 or rv64"),
1524 arch);
1525 return FALSE;
1526 }
1527
1528 /* Parsing standard extension. */
1529 p = riscv_parse_std_ext (rps, arch, p);
1530
1531 if (p == NULL)
1532 return FALSE;
1533
1534 /* Parse the different classes of extensions in the specified order. */
1535 for (i = 0; i < ARRAY_SIZE (parse_config); ++i) {
1536 p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
1537
1538 if (p == NULL)
1539 return FALSE;
1540 }
1541
1542 if (*p != '\0')
1543 {
1544 rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1545 arch, p);
1546 return FALSE;
1547 }
1548
1549 if (riscv_lookup_subset (rps->subset_list, "e")
1550 && riscv_lookup_subset (rps->subset_list, "f"))
1551 {
1552 rps->error_handler
1553 (_("-march=%s: rv32e does not support the `f' extension"),
1554 arch);
1555 return FALSE;
1556 }
1557
1558 if (riscv_lookup_subset (rps->subset_list, "d")
1559 && !riscv_lookup_subset (rps->subset_list, "f"))
1560 {
1561 rps->error_handler
1562 (_("-march=%s: `d' extension requires `f' extension"),
1563 arch);
1564 return FALSE;
1565 }
1566
1567 if (riscv_lookup_subset (rps->subset_list, "q")
1568 && !riscv_lookup_subset (rps->subset_list, "d"))
1569 {
1570 rps->error_handler
1571 (_("-march=%s: `q' extension requires `d' extension"),
1572 arch);
1573 return FALSE;
1574 }
1575
1576 if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
1577 {
1578 rps->error_handler
1579 (_("-march=%s: rv32 does not support the `q' extension"),
1580 arch);
1581 return FALSE;
1582 }
1583 return TRUE;
1584 }
1585
1586 /* Add new subset to list. */
1587
1588 void
1589 riscv_add_subset (riscv_subset_list_t *subset_list,
1590 const char *subset,
1591 int major,
1592 int minor)
1593 {
1594 riscv_subset_t *s = xmalloc (sizeof *s);
1595
1596 if (subset_list->head == NULL)
1597 subset_list->head = s;
1598
1599 s->name = xstrdup (subset);
1600 s->major_version = major;
1601 s->minor_version = minor;
1602 s->next = NULL;
1603
1604 if (subset_list->tail != NULL)
1605 subset_list->tail->next = s;
1606
1607 subset_list->tail = s;
1608 }
1609
1610 /* Find subset in list without version checking, return NULL if not found. */
1611
1612 riscv_subset_t *
1613 riscv_lookup_subset (const riscv_subset_list_t *subset_list,
1614 const char *subset)
1615 {
1616 return riscv_lookup_subset_version
1617 (subset_list, subset,
1618 RISCV_DONT_CARE_VERSION,
1619 RISCV_DONT_CARE_VERSION);
1620 }
1621
1622 /* Find subset in list with version checking, return NULL if not found. */
1623
1624 riscv_subset_t *
1625 riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
1626 const char *subset,
1627 int major, int minor)
1628 {
1629 riscv_subset_t *s;
1630
1631 for (s = subset_list->head; s != NULL; s = s->next)
1632 if (strcasecmp (s->name, subset) == 0)
1633 {
1634 if ((major != RISCV_DONT_CARE_VERSION)
1635 && (s->major_version != major))
1636 return NULL;
1637
1638 if ((minor != RISCV_DONT_CARE_VERSION)
1639 && (s->minor_version != minor))
1640 return NULL;
1641
1642 return s;
1643 }
1644
1645 return NULL;
1646 }
1647
1648 /* Release subset list. */
1649
1650 void
1651 riscv_release_subset_list (riscv_subset_list_t *subset_list)
1652 {
1653 while (subset_list->head != NULL)
1654 {
1655 riscv_subset_t *next = subset_list->head->next;
1656 free ((void *)subset_list->head->name);
1657 free (subset_list->head);
1658 subset_list->head = next;
1659 }
1660
1661 subset_list->tail = NULL;
1662 }
1663
1664 /* Return the number of digits for the input. */
1665
1666 size_t
1667 riscv_estimate_digit (unsigned num)
1668 {
1669 size_t digit = 0;
1670 if (num == 0)
1671 return 1;
1672
1673 for (digit = 0; num ; num /= 10)
1674 digit++;
1675
1676 return digit;
1677 }
1678
1679 /* Auxiliary function to estimate string length of subset list. */
1680
1681 static size_t
1682 riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
1683 {
1684 if (subset == NULL)
1685 return 6; /* For rv32/rv64/rv128 and string terminator. */
1686
1687 return riscv_estimate_arch_strlen1 (subset->next)
1688 + strlen (subset->name)
1689 + riscv_estimate_digit (subset->major_version)
1690 + 1 /* For version seperator: 'p'. */
1691 + riscv_estimate_digit (subset->minor_version)
1692 + 1 /* For underscore. */;
1693 }
1694
1695 /* Estimate the string length of this subset list. */
1696
1697 static size_t
1698 riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
1699 {
1700 return riscv_estimate_arch_strlen1 (subset_list->head);
1701 }
1702
1703 /* Auxiliary function to convert subset info to string. */
1704
1705 static void
1706 riscv_arch_str1 (riscv_subset_t *subset,
1707 char *attr_str, char *buf, size_t bufsz)
1708 {
1709 const char *underline = "_";
1710
1711 if (subset == NULL)
1712 return;
1713
1714 /* No underline between rvXX and i/e. */
1715 if ((strcasecmp (subset->name, "i") == 0)
1716 || (strcasecmp (subset->name, "e") == 0))
1717 underline = "";
1718
1719 snprintf (buf, bufsz, "%s%s%dp%d",
1720 underline,
1721 subset->name,
1722 subset->major_version,
1723 subset->minor_version);
1724
1725 strncat (attr_str, buf, bufsz);
1726
1727 /* Skip 'i' extension after 'e'. */
1728 if ((strcasecmp (subset->name, "e") == 0)
1729 && subset->next
1730 && (strcasecmp (subset->next->name, "i") == 0))
1731 riscv_arch_str1 (subset->next->next, attr_str, buf, bufsz);
1732 else
1733 riscv_arch_str1 (subset->next, attr_str, buf, bufsz);
1734 }
1735
1736 /* Convert subset info to string with explicit version info. */
1737
1738 char *
1739 riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
1740 {
1741 size_t arch_str_len = riscv_estimate_arch_strlen (subset);
1742 char *attr_str = xmalloc (arch_str_len);
1743 char *buf = xmalloc (arch_str_len);
1744
1745 snprintf (attr_str, arch_str_len, "rv%u", xlen);
1746
1747 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
1748 free (buf);
1749
1750 return attr_str;
1751 }
1752
1753 /* Record the priv spec version string and the corresponding class. */
1754
1755 struct priv_spec_t
1756 {
1757 const char *name;
1758 enum riscv_priv_spec_class class;
1759 };
1760
1761 /* List for all supported privilege versions. */
1762
1763 static const struct priv_spec_t priv_specs[] =
1764 {
1765 {"1.9.1", PRIV_SPEC_CLASS_1P9P1},
1766 {"1.10", PRIV_SPEC_CLASS_1P10},
1767 {"1.11", PRIV_SPEC_CLASS_1P11},
1768
1769 /* Terminate the list. */
1770 {NULL, 0}
1771 };
1772
1773 /* Get the corresponding CSR version class by giving a privilege
1774 version string. */
1775
1776 int
1777 riscv_get_priv_spec_class (const char *s,
1778 enum riscv_priv_spec_class *class)
1779 {
1780 const struct priv_spec_t *version;
1781
1782 if (s == NULL)
1783 return 0;
1784
1785 for (version = &priv_specs[0]; version->name != NULL; ++version)
1786 if (strcmp (version->name, s) == 0)
1787 {
1788 *class = version->class;
1789 return 1;
1790 }
1791
1792 /* Can not find the supported privilege version. */
1793 return 0;
1794 }
1795
1796 /* Get the corresponding CSR version class by giving privilege
1797 version numbers. It is usually used to convert the priv
1798 attribute numbers into the corresponding class. */
1799
1800 int
1801 riscv_get_priv_spec_class_from_numbers (unsigned int major,
1802 unsigned int minor,
1803 unsigned int revision,
1804 enum riscv_priv_spec_class *class)
1805 {
1806 size_t buf_size;
1807 char *buf;
1808 int result = 1;
1809
1810 if (major == 0 && minor == 0 && revision == 0)
1811 {
1812 *class = PRIV_SPEC_CLASS_NONE;
1813 return result;
1814 }
1815
1816 buf_size = riscv_estimate_digit (major)
1817 + 1 /* '.' */
1818 + riscv_estimate_digit (minor)
1819 + 1; /* string terminator */
1820 if (revision != 0)
1821 {
1822 buf_size += 1 /* '.' */
1823 + riscv_estimate_digit (revision);
1824 buf = xmalloc (buf_size);
1825 snprintf (buf, buf_size, "%d.%d.%d", major, minor, revision);
1826 }
1827 else
1828 {
1829 buf = xmalloc (buf_size);
1830 snprintf (buf, buf_size, "%d.%d", major, minor);
1831 }
1832
1833 result = riscv_get_priv_spec_class (buf, class);
1834 free (buf);
1835 return result;
1836 }
1837
1838 /* Get the corresponding privilege version string by giving a CSR
1839 version class. */
1840
1841 const char *
1842 riscv_get_priv_spec_name (enum riscv_priv_spec_class class)
1843 {
1844 /* The first enum is PRIV_SPEC_CLASS_NONE. */
1845 return priv_specs[class - 1].name;
1846 }
This page took 0.064851 seconds and 3 git commands to generate.