1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2021 Free Software Foundation, Inc.
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on TILE-Gx and MIPS targets.
7 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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/>. */
27 #include "elf/riscv.h"
28 #include "libiberty.h"
29 #include "elfxx-riscv.h"
30 #include "safe-ctype.h"
32 #define MINUS_ONE ((bfd_vma)0 - 1)
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 **);
41 /* The relocation table used for SHT_RELA sections. */
43 static reloc_howto_type howto_table
[] =
46 HOWTO (R_RISCV_NONE
, /* type */
50 FALSE
, /* pc_relative */
52 complain_overflow_dont
, /* complain_on_overflow */
53 bfd_elf_generic_reloc
, /* special_function */
54 "R_RISCV_NONE", /* name */
55 FALSE
, /* partial_inplace */
58 FALSE
), /* pcrel_offset */
60 /* 32 bit relocation. */
61 HOWTO (R_RISCV_32
, /* type */
65 FALSE
, /* pc_relative */
67 complain_overflow_dont
, /* complain_on_overflow */
68 bfd_elf_generic_reloc
, /* special_function */
69 "R_RISCV_32", /* name */
70 FALSE
, /* partial_inplace */
72 0xffffffff, /* dst_mask */
73 FALSE
), /* pcrel_offset */
75 /* 64 bit relocation. */
76 HOWTO (R_RISCV_64
, /* type */
80 FALSE
, /* pc_relative */
82 complain_overflow_dont
, /* complain_on_overflow */
83 bfd_elf_generic_reloc
, /* special_function */
84 "R_RISCV_64", /* name */
85 FALSE
, /* partial_inplace */
87 MINUS_ONE
, /* dst_mask */
88 FALSE
), /* pcrel_offset */
90 /* Relocation against a local symbol in a shared object. */
91 HOWTO (R_RISCV_RELATIVE
, /* type */
95 FALSE
, /* pc_relative */
97 complain_overflow_dont
, /* complain_on_overflow */
98 bfd_elf_generic_reloc
, /* special_function */
99 "R_RISCV_RELATIVE", /* name */
100 FALSE
, /* partial_inplace */
102 0xffffffff, /* dst_mask */
103 FALSE
), /* pcrel_offset */
105 HOWTO (R_RISCV_COPY
, /* type */
107 0, /* this one is variable size */
109 FALSE
, /* pc_relative */
111 complain_overflow_bitfield
, /* complain_on_overflow */
112 bfd_elf_generic_reloc
, /* special_function */
113 "R_RISCV_COPY", /* name */
114 FALSE
, /* partial_inplace */
117 FALSE
), /* pcrel_offset */
119 HOWTO (R_RISCV_JUMP_SLOT
, /* type */
123 FALSE
, /* pc_relative */
125 complain_overflow_bitfield
, /* complain_on_overflow */
126 bfd_elf_generic_reloc
, /* special_function */
127 "R_RISCV_JUMP_SLOT", /* name */
128 FALSE
, /* partial_inplace */
131 FALSE
), /* pcrel_offset */
133 /* Dynamic TLS relocations. */
134 HOWTO (R_RISCV_TLS_DTPMOD32
, /* type */
138 FALSE
, /* pc_relative */
140 complain_overflow_dont
, /* complain_on_overflow */
141 bfd_elf_generic_reloc
, /* special_function */
142 "R_RISCV_TLS_DTPMOD32", /* name */
143 FALSE
, /* partial_inplace */
145 0xffffffff, /* dst_mask */
146 FALSE
), /* pcrel_offset */
148 HOWTO (R_RISCV_TLS_DTPMOD64
, /* type */
152 FALSE
, /* pc_relative */
154 complain_overflow_dont
, /* complain_on_overflow */
155 bfd_elf_generic_reloc
, /* special_function */
156 "R_RISCV_TLS_DTPMOD64", /* name */
157 FALSE
, /* partial_inplace */
159 MINUS_ONE
, /* dst_mask */
160 FALSE
), /* pcrel_offset */
162 HOWTO (R_RISCV_TLS_DTPREL32
, /* type */
166 FALSE
, /* pc_relative */
168 complain_overflow_dont
, /* complain_on_overflow */
169 bfd_elf_generic_reloc
, /* special_function */
170 "R_RISCV_TLS_DTPREL32", /* name */
171 TRUE
, /* partial_inplace */
173 0xffffffff, /* dst_mask */
174 FALSE
), /* pcrel_offset */
176 HOWTO (R_RISCV_TLS_DTPREL64
, /* type */
180 FALSE
, /* pc_relative */
182 complain_overflow_dont
, /* complain_on_overflow */
183 bfd_elf_generic_reloc
, /* special_function */
184 "R_RISCV_TLS_DTPREL64", /* name */
185 TRUE
, /* partial_inplace */
187 MINUS_ONE
, /* dst_mask */
188 FALSE
), /* pcrel_offset */
190 HOWTO (R_RISCV_TLS_TPREL32
, /* type */
194 FALSE
, /* pc_relative */
196 complain_overflow_dont
, /* complain_on_overflow */
197 bfd_elf_generic_reloc
, /* special_function */
198 "R_RISCV_TLS_TPREL32", /* name */
199 FALSE
, /* partial_inplace */
201 0xffffffff, /* dst_mask */
202 FALSE
), /* pcrel_offset */
204 HOWTO (R_RISCV_TLS_TPREL64
, /* type */
208 FALSE
, /* pc_relative */
210 complain_overflow_dont
, /* complain_on_overflow */
211 bfd_elf_generic_reloc
, /* special_function */
212 "R_RISCV_TLS_TPREL64", /* name */
213 FALSE
, /* partial_inplace */
215 MINUS_ONE
, /* dst_mask */
216 FALSE
), /* pcrel_offset */
218 /* Reserved for future relocs that the dynamic linker must understand. */
224 /* 12-bit PC-relative branch offset. */
225 HOWTO (R_RISCV_BRANCH
, /* type */
229 TRUE
, /* pc_relative */
231 complain_overflow_signed
, /* complain_on_overflow */
232 bfd_elf_generic_reloc
, /* special_function */
233 "R_RISCV_BRANCH", /* name */
234 FALSE
, /* partial_inplace */
236 ENCODE_SBTYPE_IMM (-1U), /* dst_mask */
237 TRUE
), /* pcrel_offset */
239 /* 20-bit PC-relative jump offset. */
240 HOWTO (R_RISCV_JAL
, /* type */
244 TRUE
, /* pc_relative */
246 complain_overflow_dont
, /* complain_on_overflow */
247 bfd_elf_generic_reloc
, /* special_function */
248 "R_RISCV_JAL", /* name */
249 FALSE
, /* partial_inplace */
251 ENCODE_UJTYPE_IMM (-1U), /* dst_mask */
252 TRUE
), /* pcrel_offset */
254 /* 32-bit PC-relative function call (AUIPC/JALR). */
255 HOWTO (R_RISCV_CALL
, /* type */
259 TRUE
, /* pc_relative */
261 complain_overflow_dont
, /* complain_on_overflow */
262 bfd_elf_generic_reloc
, /* special_function */
263 "R_RISCV_CALL", /* name */
264 FALSE
, /* partial_inplace */
266 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
268 TRUE
), /* pcrel_offset */
270 /* Like R_RISCV_CALL, but not locally binding. */
271 HOWTO (R_RISCV_CALL_PLT
, /* type */
275 TRUE
, /* pc_relative */
277 complain_overflow_dont
, /* complain_on_overflow */
278 bfd_elf_generic_reloc
, /* special_function */
279 "R_RISCV_CALL_PLT", /* name */
280 FALSE
, /* partial_inplace */
282 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
284 TRUE
), /* pcrel_offset */
286 /* High 20 bits of 32-bit PC-relative GOT access. */
287 HOWTO (R_RISCV_GOT_HI20
, /* type */
291 TRUE
, /* pc_relative */
293 complain_overflow_dont
, /* complain_on_overflow */
294 bfd_elf_generic_reloc
, /* special_function */
295 "R_RISCV_GOT_HI20", /* name */
296 FALSE
, /* partial_inplace */
298 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
299 FALSE
), /* pcrel_offset */
301 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
302 HOWTO (R_RISCV_TLS_GOT_HI20
, /* type */
306 TRUE
, /* pc_relative */
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 */
313 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
314 FALSE
), /* pcrel_offset */
316 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
317 HOWTO (R_RISCV_TLS_GD_HI20
, /* type */
321 TRUE
, /* pc_relative */
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 */
328 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
329 FALSE
), /* pcrel_offset */
331 /* High 20 bits of 32-bit PC-relative reference. */
332 HOWTO (R_RISCV_PCREL_HI20
, /* type */
336 TRUE
, /* pc_relative */
338 complain_overflow_dont
, /* complain_on_overflow */
339 bfd_elf_generic_reloc
, /* special_function */
340 "R_RISCV_PCREL_HI20", /* name */
341 FALSE
, /* partial_inplace */
343 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
344 TRUE
), /* pcrel_offset */
346 /* Low 12 bits of a 32-bit PC-relative load or add. */
347 HOWTO (R_RISCV_PCREL_LO12_I
, /* type */
351 FALSE
, /* pc_relative */
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 */
358 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
359 FALSE
), /* pcrel_offset */
361 /* Low 12 bits of a 32-bit PC-relative store. */
362 HOWTO (R_RISCV_PCREL_LO12_S
, /* type */
366 FALSE
, /* pc_relative */
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 */
373 ENCODE_STYPE_IMM (-1U), /* dst_mask */
374 FALSE
), /* pcrel_offset */
376 /* High 20 bits of 32-bit absolute address. */
377 HOWTO (R_RISCV_HI20
, /* type */
381 FALSE
, /* pc_relative */
383 complain_overflow_dont
, /* complain_on_overflow */
384 bfd_elf_generic_reloc
, /* special_function */
385 "R_RISCV_HI20", /* name */
386 FALSE
, /* partial_inplace */
388 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
389 FALSE
), /* pcrel_offset */
391 /* High 12 bits of 32-bit load or add. */
392 HOWTO (R_RISCV_LO12_I
, /* type */
396 FALSE
, /* pc_relative */
398 complain_overflow_dont
, /* complain_on_overflow */
399 bfd_elf_generic_reloc
, /* special_function */
400 "R_RISCV_LO12_I", /* name */
401 FALSE
, /* partial_inplace */
403 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
404 FALSE
), /* pcrel_offset */
406 /* High 12 bits of 32-bit store. */
407 HOWTO (R_RISCV_LO12_S
, /* type */
411 FALSE
, /* pc_relative */
413 complain_overflow_dont
, /* complain_on_overflow */
414 bfd_elf_generic_reloc
, /* special_function */
415 "R_RISCV_LO12_S", /* name */
416 FALSE
, /* partial_inplace */
418 ENCODE_STYPE_IMM (-1U), /* dst_mask */
419 FALSE
), /* pcrel_offset */
421 /* High 20 bits of TLS LE thread pointer offset. */
422 HOWTO (R_RISCV_TPREL_HI20
, /* type */
426 FALSE
, /* pc_relative */
428 complain_overflow_signed
, /* complain_on_overflow */
429 bfd_elf_generic_reloc
, /* special_function */
430 "R_RISCV_TPREL_HI20", /* name */
431 TRUE
, /* partial_inplace */
433 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
434 FALSE
), /* pcrel_offset */
436 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
437 HOWTO (R_RISCV_TPREL_LO12_I
, /* type */
441 FALSE
, /* pc_relative */
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 */
448 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
449 FALSE
), /* pcrel_offset */
451 /* Low 12 bits of TLS LE thread pointer offset for stores. */
452 HOWTO (R_RISCV_TPREL_LO12_S
, /* type */
456 FALSE
, /* pc_relative */
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 */
463 ENCODE_STYPE_IMM (-1U), /* dst_mask */
464 FALSE
), /* pcrel_offset */
466 /* TLS LE thread pointer usage. May be relaxed. */
467 HOWTO (R_RISCV_TPREL_ADD
, /* type */
471 FALSE
, /* pc_relative */
473 complain_overflow_dont
, /* complain_on_overflow */
474 bfd_elf_generic_reloc
, /* special_function */
475 "R_RISCV_TPREL_ADD", /* name */
476 FALSE
, /* partial_inplace */
479 FALSE
), /* pcrel_offset */
481 /* 8-bit in-place addition, for local label subtraction. */
482 HOWTO (R_RISCV_ADD8
, /* type */
486 FALSE
, /* pc_relative */
488 complain_overflow_dont
, /* complain_on_overflow */
489 riscv_elf_add_sub_reloc
, /* special_function */
490 "R_RISCV_ADD8", /* name */
491 FALSE
, /* partial_inplace */
494 FALSE
), /* pcrel_offset */
496 /* 16-bit in-place addition, for local label subtraction. */
497 HOWTO (R_RISCV_ADD16
, /* type */
501 FALSE
, /* pc_relative */
503 complain_overflow_dont
, /* complain_on_overflow */
504 riscv_elf_add_sub_reloc
, /* special_function */
505 "R_RISCV_ADD16", /* name */
506 FALSE
, /* partial_inplace */
508 0xffff, /* dst_mask */
509 FALSE
), /* pcrel_offset */
511 /* 32-bit in-place addition, for local label subtraction. */
512 HOWTO (R_RISCV_ADD32
, /* type */
516 FALSE
, /* pc_relative */
518 complain_overflow_dont
, /* complain_on_overflow */
519 riscv_elf_add_sub_reloc
, /* special_function */
520 "R_RISCV_ADD32", /* name */
521 FALSE
, /* partial_inplace */
523 0xffffffff, /* dst_mask */
524 FALSE
), /* pcrel_offset */
526 /* 64-bit in-place addition, for local label subtraction. */
527 HOWTO (R_RISCV_ADD64
, /* type */
531 FALSE
, /* pc_relative */
533 complain_overflow_dont
, /* complain_on_overflow */
534 riscv_elf_add_sub_reloc
, /* special_function */
535 "R_RISCV_ADD64", /* name */
536 FALSE
, /* partial_inplace */
538 MINUS_ONE
, /* dst_mask */
539 FALSE
), /* pcrel_offset */
541 /* 8-bit in-place addition, for local label subtraction. */
542 HOWTO (R_RISCV_SUB8
, /* type */
546 FALSE
, /* pc_relative */
548 complain_overflow_dont
, /* complain_on_overflow */
549 riscv_elf_add_sub_reloc
, /* special_function */
550 "R_RISCV_SUB8", /* name */
551 FALSE
, /* partial_inplace */
554 FALSE
), /* pcrel_offset */
556 /* 16-bit in-place addition, for local label subtraction. */
557 HOWTO (R_RISCV_SUB16
, /* type */
561 FALSE
, /* pc_relative */
563 complain_overflow_dont
, /* complain_on_overflow */
564 riscv_elf_add_sub_reloc
, /* special_function */
565 "R_RISCV_SUB16", /* name */
566 FALSE
, /* partial_inplace */
568 0xffff, /* dst_mask */
569 FALSE
), /* pcrel_offset */
571 /* 32-bit in-place addition, for local label subtraction. */
572 HOWTO (R_RISCV_SUB32
, /* type */
576 FALSE
, /* pc_relative */
578 complain_overflow_dont
, /* complain_on_overflow */
579 riscv_elf_add_sub_reloc
, /* special_function */
580 "R_RISCV_SUB32", /* name */
581 FALSE
, /* partial_inplace */
583 0xffffffff, /* dst_mask */
584 FALSE
), /* pcrel_offset */
586 /* 64-bit in-place addition, for local label subtraction. */
587 HOWTO (R_RISCV_SUB64
, /* type */
591 FALSE
, /* pc_relative */
593 complain_overflow_dont
, /* complain_on_overflow */
594 riscv_elf_add_sub_reloc
, /* special_function */
595 "R_RISCV_SUB64", /* name */
596 FALSE
, /* partial_inplace */
598 MINUS_ONE
, /* dst_mask */
599 FALSE
), /* pcrel_offset */
601 /* GNU extension to record C++ vtable hierarchy */
602 HOWTO (R_RISCV_GNU_VTINHERIT
, /* type */
606 FALSE
, /* pc_relative */
608 complain_overflow_dont
, /* complain_on_overflow */
609 NULL
, /* special_function */
610 "R_RISCV_GNU_VTINHERIT", /* name */
611 FALSE
, /* partial_inplace */
614 FALSE
), /* pcrel_offset */
616 /* GNU extension to record C++ vtable member usage */
617 HOWTO (R_RISCV_GNU_VTENTRY
, /* type */
621 FALSE
, /* pc_relative */
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 */
629 FALSE
), /* pcrel_offset */
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 */
638 FALSE
, /* pc_relative */
640 complain_overflow_dont
, /* complain_on_overflow */
641 bfd_elf_generic_reloc
, /* special_function */
642 "R_RISCV_ALIGN", /* name */
643 FALSE
, /* partial_inplace */
646 FALSE
), /* pcrel_offset */
648 /* 8-bit PC-relative branch offset. */
649 HOWTO (R_RISCV_RVC_BRANCH
, /* type */
653 TRUE
, /* pc_relative */
655 complain_overflow_signed
, /* complain_on_overflow */
656 bfd_elf_generic_reloc
, /* special_function */
657 "R_RISCV_RVC_BRANCH", /* name */
658 FALSE
, /* partial_inplace */
660 ENCODE_RVC_B_IMM (-1U), /* dst_mask */
661 TRUE
), /* pcrel_offset */
663 /* 11-bit PC-relative jump offset. */
664 HOWTO (R_RISCV_RVC_JUMP
, /* type */
668 TRUE
, /* pc_relative */
670 complain_overflow_dont
, /* complain_on_overflow */
671 bfd_elf_generic_reloc
, /* special_function */
672 "R_RISCV_RVC_JUMP", /* name */
673 FALSE
, /* partial_inplace */
675 ENCODE_RVC_J_IMM (-1U), /* dst_mask */
676 TRUE
), /* pcrel_offset */
678 /* High 6 bits of 18-bit absolute address. */
679 HOWTO (R_RISCV_RVC_LUI
, /* type */
683 FALSE
, /* pc_relative */
685 complain_overflow_dont
, /* complain_on_overflow */
686 bfd_elf_generic_reloc
, /* special_function */
687 "R_RISCV_RVC_LUI", /* name */
688 FALSE
, /* partial_inplace */
690 ENCODE_RVC_IMM (-1U), /* dst_mask */
691 FALSE
), /* pcrel_offset */
693 /* GP-relative load. */
694 HOWTO (R_RISCV_GPREL_I
, /* type */
698 FALSE
, /* pc_relative */
700 complain_overflow_dont
, /* complain_on_overflow */
701 bfd_elf_generic_reloc
, /* special_function */
702 "R_RISCV_GPREL_I", /* name */
703 FALSE
, /* partial_inplace */
705 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
706 FALSE
), /* pcrel_offset */
708 /* GP-relative store. */
709 HOWTO (R_RISCV_GPREL_S
, /* type */
713 FALSE
, /* pc_relative */
715 complain_overflow_dont
, /* complain_on_overflow */
716 bfd_elf_generic_reloc
, /* special_function */
717 "R_RISCV_GPREL_S", /* name */
718 FALSE
, /* partial_inplace */
720 ENCODE_STYPE_IMM (-1U), /* dst_mask */
721 FALSE
), /* pcrel_offset */
723 /* TP-relative TLS LE load. */
724 HOWTO (R_RISCV_TPREL_I
, /* type */
728 FALSE
, /* pc_relative */
730 complain_overflow_signed
, /* complain_on_overflow */
731 bfd_elf_generic_reloc
, /* special_function */
732 "R_RISCV_TPREL_I", /* name */
733 FALSE
, /* partial_inplace */
735 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
736 FALSE
), /* pcrel_offset */
738 /* TP-relative TLS LE store. */
739 HOWTO (R_RISCV_TPREL_S
, /* type */
743 FALSE
, /* pc_relative */
745 complain_overflow_signed
, /* complain_on_overflow */
746 bfd_elf_generic_reloc
, /* special_function */
747 "R_RISCV_TPREL_S", /* name */
748 FALSE
, /* partial_inplace */
750 ENCODE_STYPE_IMM (-1U), /* dst_mask */
751 FALSE
), /* pcrel_offset */
753 /* The paired relocation may be relaxed. */
754 HOWTO (R_RISCV_RELAX
, /* type */
758 FALSE
, /* pc_relative */
760 complain_overflow_dont
, /* complain_on_overflow */
761 bfd_elf_generic_reloc
, /* special_function */
762 "R_RISCV_RELAX", /* name */
763 FALSE
, /* partial_inplace */
766 FALSE
), /* pcrel_offset */
768 /* 6-bit in-place addition, for local label subtraction. */
769 HOWTO (R_RISCV_SUB6
, /* type */
773 FALSE
, /* pc_relative */
775 complain_overflow_dont
, /* complain_on_overflow */
776 riscv_elf_add_sub_reloc
, /* special_function */
777 "R_RISCV_SUB6", /* name */
778 FALSE
, /* partial_inplace */
781 FALSE
), /* pcrel_offset */
783 /* 6-bit in-place setting, for local label subtraction. */
784 HOWTO (R_RISCV_SET6
, /* type */
788 FALSE
, /* pc_relative */
790 complain_overflow_dont
, /* complain_on_overflow */
791 bfd_elf_generic_reloc
, /* special_function */
792 "R_RISCV_SET6", /* name */
793 FALSE
, /* partial_inplace */
796 FALSE
), /* pcrel_offset */
798 /* 8-bit in-place setting, for local label subtraction. */
799 HOWTO (R_RISCV_SET8
, /* type */
803 FALSE
, /* pc_relative */
805 complain_overflow_dont
, /* complain_on_overflow */
806 bfd_elf_generic_reloc
, /* special_function */
807 "R_RISCV_SET8", /* name */
808 FALSE
, /* partial_inplace */
811 FALSE
), /* pcrel_offset */
813 /* 16-bit in-place setting, for local label subtraction. */
814 HOWTO (R_RISCV_SET16
, /* type */
818 FALSE
, /* pc_relative */
820 complain_overflow_dont
, /* complain_on_overflow */
821 bfd_elf_generic_reloc
, /* special_function */
822 "R_RISCV_SET16", /* name */
823 FALSE
, /* partial_inplace */
825 0xffff, /* dst_mask */
826 FALSE
), /* pcrel_offset */
828 /* 32-bit in-place setting, for local label subtraction. */
829 HOWTO (R_RISCV_SET32
, /* type */
833 FALSE
, /* pc_relative */
835 complain_overflow_dont
, /* complain_on_overflow */
836 bfd_elf_generic_reloc
, /* special_function */
837 "R_RISCV_SET32", /* name */
838 FALSE
, /* partial_inplace */
840 0xffffffff, /* dst_mask */
841 FALSE
), /* pcrel_offset */
843 /* 32-bit PC relative. */
844 HOWTO (R_RISCV_32_PCREL
, /* type */
848 TRUE
, /* pc_relative */
850 complain_overflow_dont
, /* complain_on_overflow */
851 bfd_elf_generic_reloc
, /* special_function */
852 "R_RISCV_32_PCREL", /* name */
853 FALSE
, /* partial_inplace */
855 0xffffffff, /* dst_mask */
856 FALSE
), /* pcrel_offset */
858 /* Relocation against a local ifunc symbol in a shared object. */
859 HOWTO (R_RISCV_IRELATIVE
, /* type */
863 FALSE
, /* pc_relative */
865 complain_overflow_dont
, /* complain_on_overflow */
866 bfd_elf_generic_reloc
, /* special_function */
867 "R_RISCV_IRELATIVE", /* name */
868 FALSE
, /* partial_inplace */
870 0xffffffff, /* dst_mask */
871 FALSE
), /* pcrel_offset */
874 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
877 bfd_reloc_code_real_type bfd_val
;
878 enum elf_riscv_reloc_type elf_val
;
881 static const struct elf_reloc_map riscv_reloc_map
[] =
883 { BFD_RELOC_NONE
, R_RISCV_NONE
},
884 { BFD_RELOC_32
, R_RISCV_32
},
885 { BFD_RELOC_64
, R_RISCV_64
},
886 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
887 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
888 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
889 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
890 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
891 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
892 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
893 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
894 { BFD_RELOC_CTOR
, R_RISCV_64
},
895 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
896 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
897 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
898 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
899 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
900 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
901 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
902 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
903 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
904 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
905 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
906 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
907 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
908 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
909 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
910 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
911 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
912 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
913 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
914 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
915 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
916 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
917 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
918 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
919 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
920 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
921 { BFD_RELOC_RISCV_RVC_LUI
, R_RISCV_RVC_LUI
},
922 { BFD_RELOC_RISCV_GPREL_I
, R_RISCV_GPREL_I
},
923 { BFD_RELOC_RISCV_GPREL_S
, R_RISCV_GPREL_S
},
924 { BFD_RELOC_RISCV_TPREL_I
, R_RISCV_TPREL_I
},
925 { BFD_RELOC_RISCV_TPREL_S
, R_RISCV_TPREL_S
},
926 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
927 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
928 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
929 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
930 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
931 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
932 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
935 /* Given a BFD reloc type, return a howto structure. */
938 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
939 bfd_reloc_code_real_type code
)
943 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
944 if (riscv_reloc_map
[i
].bfd_val
== code
)
945 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
947 bfd_set_error (bfd_error_bad_value
);
952 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
956 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
957 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
958 return &howto_table
[i
];
964 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
966 if (r_type
>= ARRAY_SIZE (howto_table
))
968 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
970 bfd_set_error (bfd_error_bad_value
);
973 return &howto_table
[r_type
];
976 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
978 static bfd_reloc_status_type
979 riscv_elf_add_sub_reloc (bfd
*abfd
,
980 arelent
*reloc_entry
,
983 asection
*input_section
,
985 char **error_message ATTRIBUTE_UNUSED
)
987 reloc_howto_type
*howto
= reloc_entry
->howto
;
990 if (output_bfd
!= NULL
991 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
992 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
994 reloc_entry
->address
+= input_section
->output_offset
;
998 if (output_bfd
!= NULL
)
999 return bfd_reloc_continue
;
1001 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
1002 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
1003 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
1004 data
+ reloc_entry
->address
);
1006 switch (howto
->type
)
1012 relocation
= old_value
+ relocation
;
1019 relocation
= old_value
- relocation
;
1022 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1024 return bfd_reloc_ok
;
1027 /* Array is used to compare the orders of all extensions quickly.
1029 Zero value: Preserved keyword.
1030 Negative value: Prefixed keyword (s, h, x, z).
1031 Positive value: Standard extension. */
1033 static int riscv_ext_order
[26] = {0};
1035 /* Similar to the strcmp. It returns an integer less than, equal to,
1036 or greater than zero if `subset2` is found, respectively, to be less
1037 than, to match, or be greater than `subset1`. */
1040 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1042 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1043 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1045 /* Compare the standard extension first. */
1046 if (order1
> 0 && order2
> 0)
1047 return order1
- order2
;
1049 if (order1
== order2
&& order1
< 0)
1051 /* Compare the standard addition z extensions. */
1052 if (*subset1
== 'z')
1054 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1055 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1056 if (order1
!= order2
)
1057 return order1
- order2
;
1059 return strcasecmp (++subset1
, ++subset2
);
1062 return order2
- order1
;
1065 /* Find subset in the list. Return TRUE and set `current` to the subset
1066 if it is found. Otherwise, return FALSE and set `current` to the place
1067 where we should insert the subset. However, return FALSE with the NULL
1068 `current` means we should insert the subset at the head of subset list,
1072 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1074 riscv_subset_t
**current
)
1076 riscv_subset_t
*s
, *pre_s
= NULL
;
1078 for (s
= subset_list
->head
;
1080 pre_s
= s
, s
= s
->next
)
1082 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1095 /* Add extension from ISA string to the last of the subset list. */
1098 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1103 riscv_subset_t
*s
= xmalloc (sizeof *s
);
1105 if (subset_list
->head
== NULL
)
1106 subset_list
->head
= s
;
1108 s
->name
= xstrdup (subset
);
1109 s
->major_version
= major
;
1110 s
->minor_version
= minor
;
1113 if (subset_list
->tail
!= NULL
)
1114 subset_list
->tail
->next
= s
;
1115 subset_list
->tail
= s
;
1118 /* Add the implicit extension to the subset list. Search the
1119 list first, and then find the right place to add. */
1122 riscv_add_implicit_subset (riscv_subset_list_t
*subset_list
,
1127 riscv_subset_t
*current
, *new;
1129 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1132 new = xmalloc (sizeof *new);
1133 new->name
= xstrdup (subset
);
1134 new->major_version
= major
;
1135 new->minor_version
= minor
;
1138 if (current
!= NULL
)
1140 new->next
= current
->next
;
1141 current
->next
= new;
1145 new->next
= subset_list
->head
;
1146 subset_list
->head
= new;
1150 /* These extensions are added to the subset list for special purposes,
1151 with the explicit versions or the RISCV_UNKNOWN_VERSION versions.
1152 Therefore, we won't output them to the output ISA string in the
1153 riscv_arch_str1, if the versions are unknown. */
1156 riscv_ext_dont_care_version (const char *subset
)
1158 if (strcmp (subset
, "g") == 0
1159 || strcmp (subset
, "zicsr") == 0
1160 || strcmp (subset
, "zifencei") == 0)
1165 /* We have to add all extensions from ISA string first, and then start to
1166 add their implicit extensions. The extensions from ISA string must be
1167 set in order, so we can add them to the last of the subset list
1168 directly, without searching.
1170 Find the default versions for the extension before adding them to
1171 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1172 Afterwards, report errors if we can not find their default versions. */
1175 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1179 bfd_boolean implicit
)
1181 int major_version
= major
;
1182 int minor_version
= minor
;
1184 if ((major_version
== RISCV_UNKNOWN_VERSION
1185 || minor_version
== RISCV_UNKNOWN_VERSION
)
1186 && rps
->get_default_version
!= NULL
)
1187 rps
->get_default_version (subset
, &major_version
, &minor_version
);
1189 if (!riscv_ext_dont_care_version (subset
)
1190 && (major_version
== RISCV_UNKNOWN_VERSION
1191 || minor_version
== RISCV_UNKNOWN_VERSION
))
1193 /* We only add the implicit extension if it is supported in the
1198 if (subset
[0] == 'x')
1200 (_("x ISA extension `%s' must be set with the versions"),
1204 (_("cannot find default versions of the ISA extension `%s'"),
1210 riscv_add_subset (rps
->subset_list
, subset
,
1211 major_version
, minor_version
);
1213 riscv_add_implicit_subset (rps
->subset_list
, subset
,
1214 major_version
, minor_version
);
1217 /* Release subset list. */
1220 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1222 while (subset_list
->head
!= NULL
)
1224 riscv_subset_t
*next
= subset_list
->head
->next
;
1225 free ((void *)subset_list
->head
->name
);
1226 free (subset_list
->head
);
1227 subset_list
->head
= next
;
1230 subset_list
->tail
= NULL
;
1233 /* Parsing extension version.
1236 Points to the end of version
1239 `rps`: Hooks and status for parsing extensions.
1240 `march`: Full ISA string.
1241 `p`: Curent parsing position.
1242 `major_version`: Parsed major version.
1243 `minor_version`: Parsed minor version.
1244 `std_ext_p`: True if parsing standard extension. */
1247 riscv_parsing_subset_version (riscv_parse_subset_t
*rps
,
1252 bfd_boolean std_ext_p
)
1254 bfd_boolean major_p
= TRUE
;
1268 /* Might be beginning of `p` extension. */
1271 *major_version
= version
;
1278 (_("-march=%s: expect number after `%dp'"),
1284 *major_version
= version
;
1288 else if (ISDIGIT (*p
))
1289 version
= (version
* 10) + (*p
- '0');
1295 *major_version
= version
;
1297 *minor_version
= version
;
1299 /* We can not find any version in string. */
1300 if (*major_version
== 0 && *minor_version
== 0)
1302 *major_version
= RISCV_UNKNOWN_VERSION
;
1303 *minor_version
= RISCV_UNKNOWN_VERSION
;
1309 /* Return string which contain all supported standard extensions in
1313 riscv_supported_std_ext (void)
1315 return "mafdqlcbjtpvn";
1318 /* Parsing function for standard extensions.
1321 Points to the end of extensions.
1324 `rps`: Hooks and status for parsing extensions.
1325 `march`: Full ISA string.
1326 `p`: Curent parsing position. */
1329 riscv_parse_std_ext (riscv_parse_subset_t
*rps
,
1333 const char *all_std_exts
= riscv_supported_std_ext ();
1334 const char *std_exts
= all_std_exts
;
1337 char subset
[2] = {0, 0};
1339 /* First letter must start with i, e or g. */
1343 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1345 &minor_version
, TRUE
);
1346 riscv_parse_add_subset (rps
, "i",
1348 minor_version
, FALSE
);
1352 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1354 &minor_version
, TRUE
);
1355 riscv_parse_add_subset (rps
, "e",
1357 minor_version
, FALSE
);
1358 /* i-ext must be enabled. */
1359 riscv_parse_add_subset (rps
, "i",
1360 RISCV_UNKNOWN_VERSION
,
1361 RISCV_UNKNOWN_VERSION
, FALSE
);
1363 if (*rps
->xlen
> 32)
1366 (_("-march=%s: rv%de is not a valid base ISA"),
1373 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1375 &minor_version
, TRUE
);
1376 /* i-ext must be enabled. */
1377 riscv_parse_add_subset (rps
, "i",
1378 RISCV_UNKNOWN_VERSION
,
1379 RISCV_UNKNOWN_VERSION
, FALSE
);
1380 /* g-ext is used to add the implicit extensions, but will
1381 not be output to the ISA string. */
1382 riscv_parse_add_subset (rps
, "g",
1384 minor_version
, FALSE
);
1385 for ( ; *std_exts
!= 'q'; std_exts
++)
1387 subset
[0] = *std_exts
;
1388 riscv_parse_add_subset (rps
, subset
,
1389 RISCV_UNKNOWN_VERSION
,
1390 RISCV_UNKNOWN_VERSION
, FALSE
);
1396 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1401 while (p
!= NULL
&& *p
!= '\0')
1403 if (*p
== 'x' || *p
== 's' || *p
== 'h' || *p
== 'z')
1412 /* Checking canonical order. */
1414 while (*std_exts
&& std_ext
!= *std_exts
)
1417 if (std_ext
!= *std_exts
)
1419 if (strchr (all_std_exts
, std_ext
) == NULL
)
1421 (_("-march=%s: unknown standard ISA extension `%c'"),
1425 (_("-march=%s: standard ISA extension `%c' is not "
1426 "in canonical order"), march
, std_ext
);
1431 subset
[0] = std_ext
;
1432 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1434 &minor_version
, TRUE
);
1435 riscv_parse_add_subset (rps
, subset
,
1437 minor_version
, FALSE
);
1443 /* Classify ARCH into one of riscv_isa_ext_class_t. */
1445 riscv_isa_ext_class_t
1446 riscv_get_prefix_class (const char *arch
)
1450 case 's': return RV_ISA_CLASS_S
;
1451 case 'h': return RV_ISA_CLASS_H
;
1452 case 'x': return RV_ISA_CLASS_X
;
1453 case 'z': return RV_ISA_CLASS_Z
;
1454 default: return RV_ISA_CLASS_UNKNOWN
;
1458 /* Structure describing parameters to use when parsing a particular
1459 riscv_isa_ext_class_t. One of these should be provided for each
1460 possible class, except RV_ISA_CLASS_UNKNOWN. */
1461 typedef struct riscv_parse_config
1463 /* Class of the extension. */
1464 riscv_isa_ext_class_t
class;
1466 /* Prefix string for error printing and internal parser usage. */
1469 /* Predicate which is used for checking whether this is a "known"
1470 extension. For 'x', it always returns true since they are by
1471 definition non-standard and cannot be known. */
1472 bfd_boolean (*ext_valid_p
) (const char *);
1473 } riscv_parse_config_t
;
1475 /* Parsing function for prefixed extensions.
1478 Points to the end of extension.
1481 `rps`: Hooks and status for parsing extensions.
1482 `march`: Full ISA string.
1483 `p`: Curent parsing position.
1484 `config`: What class and predicate function to use for the
1488 riscv_parse_prefixed_ext (riscv_parse_subset_t
*rps
,
1491 const riscv_parse_config_t
*config
)
1495 const char *last_name
;
1496 riscv_isa_ext_class_t
class;
1506 /* Assert that the current extension specifier matches our parsing
1508 class = riscv_get_prefix_class (p
);
1509 if (class != config
->class
1510 || class == RV_ISA_CLASS_UNKNOWN
)
1513 char *subset
= xstrdup (p
);
1515 const char *end_of_version
;
1517 while (*++q
!= '\0' && *q
!= '_' && !ISDIGIT (*q
))
1521 riscv_parsing_subset_version (rps
, march
, q
,
1523 &minor_version
, FALSE
);
1526 if (end_of_version
== NULL
)
1532 /* Check that the prefix extension is known.
1533 For 'x', anything goes but it cannot simply be 'x'.
1534 For 's', it must be known from a list and cannot simply be 's'.
1535 For 'h', it must be known from a list and cannot simply be 'h'.
1536 For 'z', it must be known from a list and cannot simply be 'z'. */
1538 /* Check that the extension name is well-formed. */
1539 if (!config
->ext_valid_p (subset
))
1542 (_("-march=%s: unknown %s ISA extension `%s'"),
1543 march
, config
->prefix
, subset
);
1548 /* Check that the extension isn't duplicate. */
1549 last_name
= rps
->subset_list
->tail
->name
;
1550 if (!strcasecmp (last_name
, subset
))
1553 (_("-march=%s: duplicate %s ISA extension `%s'"),
1554 march
, config
->prefix
, subset
);
1559 /* Check that the extension is in alphabetical order. */
1560 if (riscv_compare_subsets (last_name
, subset
) > 0)
1563 (_("-march=%s: %s ISA extension `%s' is not in alphabetical "
1564 "order. It must come before `%s'"),
1565 march
, config
->prefix
, subset
, last_name
);
1570 riscv_parse_add_subset (rps
, subset
,
1572 minor_version
, FALSE
);
1573 p
+= end_of_version
- subset
;
1576 if (*p
!= '\0' && *p
!= '_')
1579 (_("-march=%s: %s ISA extension must separate with _"),
1580 march
, config
->prefix
);
1588 /* Lists of prefixed class extensions that binutils should know about.
1589 Whether or not a particular entry is in these lists will dictate if
1590 gas/ld will accept its presence in the architecture string.
1592 Please add the extensions to the lists in lower case. However, keep
1593 these subsets in alphabetical order in these tables is recommended,
1594 although there is no impact on the current implementation. */
1596 static const char * const riscv_std_z_ext_strtab
[] =
1598 "zicsr", "zifencei", "zihintpause", NULL
1601 static const char * const riscv_std_s_ext_strtab
[] =
1606 static const char * const riscv_std_h_ext_strtab
[] =
1611 /* For the extension `ext`, search through the list of known extensions
1612 `known_exts` for a match, and return TRUE if found. */
1615 riscv_multi_letter_ext_valid_p (const char *ext
,
1616 const char *const *known_exts
)
1620 for (i
= 0; known_exts
[i
]; ++i
)
1621 if (!strcmp (ext
, known_exts
[i
]))
1627 /* Predicator function for x-prefixed extensions.
1628 Anything goes, except the literal 'x'. */
1631 riscv_ext_x_valid_p (const char *arg
)
1633 if (!strcasecmp (arg
, "x"))
1639 /* Predicator functions for z-prefixed extensions.
1640 Only known z-extensions are permitted. */
1643 riscv_ext_z_valid_p (const char *arg
)
1645 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_z_ext_strtab
);
1648 /* Predicator function for 's' prefixed extensions.
1649 Only known s-extensions are permitted. */
1652 riscv_ext_s_valid_p (const char *arg
)
1654 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_s_ext_strtab
);
1657 /* Predicator function for 'h' prefixed extensions.
1658 Only known h-extensions are permitted. */
1661 riscv_ext_h_valid_p (const char *arg
)
1663 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_h_ext_strtab
);
1666 /* Parsing order of the prefixed extensions that is specified by
1668 static const riscv_parse_config_t parse_config
[] =
1670 {RV_ISA_CLASS_S
, "s", riscv_ext_s_valid_p
},
1671 {RV_ISA_CLASS_H
, "h", riscv_ext_h_valid_p
},
1672 {RV_ISA_CLASS_Z
, "z", riscv_ext_z_valid_p
},
1673 {RV_ISA_CLASS_X
, "x", riscv_ext_x_valid_p
},
1674 {RV_ISA_CLASS_UNKNOWN
, NULL
, NULL
}
1677 /* Init the riscv_ext_order array. */
1680 riscv_init_ext_order (void)
1682 static bfd_boolean inited
= FALSE
;
1683 const char *std_base_exts
= "eig";
1684 const char *std_remain_exts
= riscv_supported_std_ext ();
1692 /* The orders of all standard extensions are positive. */
1695 /* Init the standard base extensions first. */
1696 for (ext
= std_base_exts
; *ext
; ext
++)
1697 riscv_ext_order
[(*ext
- 'a')] = order
++;
1699 /* Init the standard remaining extensions. */
1700 for (ext
= std_remain_exts
; *ext
; ext
++)
1701 riscv_ext_order
[(*ext
- 'a')] = order
++;
1703 /* Init the order for prefixed keywords. The orders are negative. */
1705 for (i
= 0; parse_config
[i
].class != RV_ISA_CLASS_UNKNOWN
; i
++)
1707 ext
= parse_config
[i
].prefix
;
1708 riscv_ext_order
[(*ext
- 'a')] = order
--;
1714 /* Add the implicit extensions. */
1717 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1719 riscv_subset_t
*subset
= NULL
;
1721 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
1722 if ((riscv_lookup_subset (rps
->subset_list
, "i", &subset
))
1723 && (subset
->major_version
< 2
1724 || (subset
->major_version
== 2
1725 && subset
->minor_version
< 1)))
1727 riscv_parse_add_subset (rps
, "zicsr",
1728 RISCV_UNKNOWN_VERSION
,
1729 RISCV_UNKNOWN_VERSION
, TRUE
);
1730 riscv_parse_add_subset (rps
, "zifencei",
1731 RISCV_UNKNOWN_VERSION
,
1732 RISCV_UNKNOWN_VERSION
, TRUE
);
1735 if ((riscv_lookup_subset (rps
->subset_list
, "q", &subset
)))
1737 riscv_parse_add_subset (rps
, "d",
1738 RISCV_UNKNOWN_VERSION
,
1739 RISCV_UNKNOWN_VERSION
, TRUE
);
1740 riscv_parse_add_subset (rps
, "f",
1741 RISCV_UNKNOWN_VERSION
,
1742 RISCV_UNKNOWN_VERSION
, TRUE
);
1743 riscv_parse_add_subset (rps
, "zicsr",
1744 RISCV_UNKNOWN_VERSION
,
1745 RISCV_UNKNOWN_VERSION
, TRUE
);
1747 else if ((riscv_lookup_subset (rps
->subset_list
, "d", &subset
)))
1749 riscv_parse_add_subset (rps
, "f",
1750 RISCV_UNKNOWN_VERSION
,
1751 RISCV_UNKNOWN_VERSION
, TRUE
);
1752 riscv_parse_add_subset (rps
, "zicsr",
1753 RISCV_UNKNOWN_VERSION
,
1754 RISCV_UNKNOWN_VERSION
, TRUE
);
1756 else if ((riscv_lookup_subset (rps
->subset_list
, "f", &subset
)))
1757 riscv_parse_add_subset (rps
, "zicsr",
1758 RISCV_UNKNOWN_VERSION
,
1759 RISCV_UNKNOWN_VERSION
, TRUE
);
1761 if ((riscv_lookup_subset (rps
->subset_list
, "g", &subset
)))
1763 riscv_parse_add_subset (rps
, "zicsr",
1764 RISCV_UNKNOWN_VERSION
,
1765 RISCV_UNKNOWN_VERSION
, TRUE
);
1766 riscv_parse_add_subset (rps
, "zifencei",
1767 RISCV_UNKNOWN_VERSION
,
1768 RISCV_UNKNOWN_VERSION
, TRUE
);
1772 /* Function for parsing ISA string.
1775 Return TRUE on success.
1778 `rps`: Hooks and status for parsing extensions.
1779 `arch`: Full ISA string. */
1782 riscv_parse_subset (riscv_parse_subset_t
*rps
,
1785 riscv_subset_t
*subset
= NULL
;
1788 bfd_boolean no_conflict
= TRUE
;
1790 for (p
= arch
; *p
!= '\0'; p
++)
1795 (_("-march=%s: ISA string cannot contain uppercase letters"),
1802 if (strncmp (p
, "rv32", 4) == 0)
1807 else if (strncmp (p
, "rv64", 4) == 0)
1814 /* ISA string shouldn't be NULL or empty here. However,
1815 it might be empty only when we failed to merge the ISA
1816 string in the riscv_merge_attributes. We have already
1817 issued the correct error message in another side, so do
1818 not issue this error when the ISA string is empty. */
1820 rps
->error_handler (
1821 _("-march=%s: ISA string must begin with rv32 or rv64"),
1826 /* Init the riscv_ext_order array to compare the order of extensions
1828 riscv_init_ext_order ();
1830 /* Parsing standard extension. */
1831 p
= riscv_parse_std_ext (rps
, arch
, p
);
1836 /* Parse the different classes of extensions in the specified order. */
1837 for (i
= 0; i
< ARRAY_SIZE (parse_config
); ++i
)
1839 p
= riscv_parse_prefixed_ext (rps
, arch
, p
, &parse_config
[i
]);
1847 rps
->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1852 /* Finally add implicit extensions according to the current
1854 riscv_parse_add_implicit_subsets (rps
);
1856 /* Check the conflicts. */
1857 if (riscv_lookup_subset (rps
->subset_list
, "e", &subset
)
1858 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1861 (_("-march=%s: rv32e does not support the `f' extension"),
1863 no_conflict
= FALSE
;
1865 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1869 (_("-march=%s: rv32 does not support the `q' extension"),
1871 no_conflict
= FALSE
;
1876 /* Return the number of digits for the input. */
1879 riscv_estimate_digit (unsigned num
)
1885 for (digit
= 0; num
; num
/= 10)
1891 /* Auxiliary function to estimate string length of subset list. */
1894 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
1897 return 6; /* For rv32/rv64/rv128 and string terminator. */
1899 return riscv_estimate_arch_strlen1 (subset
->next
)
1900 + strlen (subset
->name
)
1901 + riscv_estimate_digit (subset
->major_version
)
1902 + 1 /* For version seperator 'p'. */
1903 + riscv_estimate_digit (subset
->minor_version
)
1904 + 1 /* For underscore. */;
1907 /* Estimate the string length of this subset list. */
1910 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
1912 return riscv_estimate_arch_strlen1 (subset_list
->head
);
1915 /* Auxiliary function to convert subset info to string. */
1918 riscv_arch_str1 (riscv_subset_t
*subset
,
1919 char *attr_str
, char *buf
, size_t bufsz
)
1921 const char *underline
= "_";
1922 riscv_subset_t
*subset_t
= subset
;
1924 if (subset_t
== NULL
)
1927 /* No underline between rvXX and i/e. */
1928 if ((strcasecmp (subset_t
->name
, "i") == 0)
1929 || (strcasecmp (subset_t
->name
, "e") == 0))
1932 snprintf (buf
, bufsz
, "%s%s%dp%d",
1935 subset_t
->major_version
,
1936 subset_t
->minor_version
);
1938 strncat (attr_str
, buf
, bufsz
);
1940 /* Skip 'i' extension after 'e', or skip extensions which
1941 versions are unknown. */
1942 while (subset_t
->next
1943 && ((strcmp (subset_t
->name
, "e") == 0
1944 && strcmp (subset_t
->next
->name
, "i") == 0)
1945 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
1946 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
1947 subset_t
= subset_t
->next
;
1949 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
1952 /* Convert subset information into string with explicit versions. */
1955 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
1957 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
1958 char *attr_str
= xmalloc (arch_str_len
);
1959 char *buf
= xmalloc (arch_str_len
);
1961 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
1963 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);