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. */
878 bfd_reloc_code_real_type bfd_val
;
879 enum elf_riscv_reloc_type elf_val
;
882 static const struct elf_reloc_map riscv_reloc_map
[] =
884 { BFD_RELOC_NONE
, R_RISCV_NONE
},
885 { BFD_RELOC_32
, R_RISCV_32
},
886 { BFD_RELOC_64
, R_RISCV_64
},
887 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
888 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
889 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
890 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
891 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
892 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
893 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
894 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
895 { BFD_RELOC_CTOR
, R_RISCV_64
},
896 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
897 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
898 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
899 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
900 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
901 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
902 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
903 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
904 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
905 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
906 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
907 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
908 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
909 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
910 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
911 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
912 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
913 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
914 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
915 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
916 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
917 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
918 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
919 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
920 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
921 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
922 { BFD_RELOC_RISCV_RVC_LUI
, R_RISCV_RVC_LUI
},
923 { BFD_RELOC_RISCV_GPREL_I
, R_RISCV_GPREL_I
},
924 { BFD_RELOC_RISCV_GPREL_S
, R_RISCV_GPREL_S
},
925 { BFD_RELOC_RISCV_TPREL_I
, R_RISCV_TPREL_I
},
926 { BFD_RELOC_RISCV_TPREL_S
, R_RISCV_TPREL_S
},
927 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
928 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
929 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
930 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
931 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
932 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
933 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
936 /* Given a BFD reloc type, return a howto structure. */
939 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
940 bfd_reloc_code_real_type code
)
944 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
945 if (riscv_reloc_map
[i
].bfd_val
== code
)
946 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
948 bfd_set_error (bfd_error_bad_value
);
953 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
957 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
958 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
959 return &howto_table
[i
];
965 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
967 if (r_type
>= ARRAY_SIZE (howto_table
))
969 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
971 bfd_set_error (bfd_error_bad_value
);
974 return &howto_table
[r_type
];
977 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
979 static bfd_reloc_status_type
980 riscv_elf_add_sub_reloc (bfd
*abfd
,
981 arelent
*reloc_entry
,
984 asection
*input_section
,
986 char **error_message ATTRIBUTE_UNUSED
)
988 reloc_howto_type
*howto
= reloc_entry
->howto
;
991 if (output_bfd
!= NULL
992 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
993 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
995 reloc_entry
->address
+= input_section
->output_offset
;
999 if (output_bfd
!= NULL
)
1000 return bfd_reloc_continue
;
1002 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
1003 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
1004 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
1005 data
+ reloc_entry
->address
);
1007 switch (howto
->type
)
1013 relocation
= old_value
+ relocation
;
1020 relocation
= old_value
- relocation
;
1023 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1025 return bfd_reloc_ok
;
1028 /* Array is used to compare the all extensions' order quickly.
1030 Zero number means it is a preserved keyword.
1031 Negative number means it is a prefix keyword (s, h, x, z).
1032 Positive number means it is a standard extension. */
1034 static int riscv_ext_order
[26] = {0};
1036 /* Similar to the strcmp. It returns an integer less than, equal to,
1037 or greater than zero if `subset2` is found, respectively, to be less
1038 than, to match, or be greater than `subset1`. */
1041 riscv_compare_subsets (const char *subset1
, const char *subset2
)
1043 int order1
= riscv_ext_order
[(*subset1
- 'a')];
1044 int order2
= riscv_ext_order
[(*subset2
- 'a')];
1046 /* Compare the standard extension first. */
1047 if (order1
> 0 && order2
> 0)
1048 return order1
- order2
;
1050 if (order1
== order2
&& order1
< 0)
1052 /* Compare the standard addition z extensions. */
1053 if (*subset1
== 'z')
1055 order1
= riscv_ext_order
[(*++subset1
- 'a')];
1056 order2
= riscv_ext_order
[(*++subset2
- 'a')];
1057 if (order1
!= order2
)
1058 return order1
- order2
;
1060 return strcasecmp (++subset1
, ++subset2
);
1063 return order2
- order1
;
1066 /* Find subset in the list. Return TRUE and set `current` to the subset
1067 if it is found. Otherwise, return FALSE and set `current` to the place
1068 where we should insert the subset. However, return FALSE with the NULL
1069 `current` means we should insert the subset at the head of subset list,
1073 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1075 riscv_subset_t
**current
)
1077 riscv_subset_t
*s
, *pre_s
= NULL
;
1079 for (s
= subset_list
->head
;
1081 pre_s
= s
, s
= s
->next
)
1083 int cmp
= riscv_compare_subsets (s
->name
, subset
);
1096 /* Add arch string extension to the last of the subset list. */
1099 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1104 riscv_subset_t
*s
= xmalloc (sizeof *s
);
1106 if (subset_list
->head
== NULL
)
1107 subset_list
->head
= s
;
1109 s
->name
= xstrdup (subset
);
1110 s
->major_version
= major
;
1111 s
->minor_version
= minor
;
1114 if (subset_list
->tail
!= NULL
)
1115 subset_list
->tail
->next
= s
;
1116 subset_list
->tail
= s
;
1119 /* Add the implicit extension to the subset list. Search the
1120 list first, and then find the right place to add. */
1123 riscv_add_implicit_subset (riscv_subset_list_t
*subset_list
,
1128 riscv_subset_t
*current
, *new;
1130 if (riscv_lookup_subset (subset_list
, subset
, ¤t
))
1133 new = xmalloc (sizeof *new);
1134 new->name
= xstrdup (subset
);
1135 new->major_version
= major
;
1136 new->minor_version
= minor
;
1139 if (current
!= NULL
)
1141 new->next
= current
->next
;
1142 current
->next
= new;
1146 new->next
= subset_list
->head
;
1147 subset_list
->head
= new;
1151 /* These extensions are added to the subset list for special purposes,
1152 with the explicit versions or the RISCV_UNKNOWN_VERSION versions.
1153 Therefore, we won't output them to the output arch string in the
1154 riscv_arch_str1, if the versions are unknown. */
1157 riscv_ext_dont_care_version (const char *subset
)
1159 if (strcmp (subset
, "g") == 0
1160 || strcmp (subset
, "zicsr") == 0
1161 || strcmp (subset
, "zifencei") == 0)
1166 /* We have to add all arch string extensions first, and then start to
1167 add their implicit extensions. The arch string extensions must be
1168 set in order, so we can add them to the last of the subset list
1169 directly, without searching.
1171 Find the default versions for the extension before adding them to
1172 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1173 Afterwards, report errors if we can not find their default versions. */
1176 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1180 bfd_boolean implicit
)
1182 int major_version
= major
;
1183 int minor_version
= minor
;
1185 if ((major_version
== RISCV_UNKNOWN_VERSION
1186 || minor_version
== RISCV_UNKNOWN_VERSION
)
1187 && rps
->get_default_version
!= NULL
)
1188 rps
->get_default_version (subset
, &major_version
, &minor_version
);
1190 if (!riscv_ext_dont_care_version (subset
)
1191 && (major_version
== RISCV_UNKNOWN_VERSION
1192 || minor_version
== RISCV_UNKNOWN_VERSION
))
1194 /* We only add the implicit extension if it is supported in the
1199 if (subset
[0] == 'x')
1201 (_("x ISA extension `%s' must be set with the versions"),
1205 (_("cannot find default versions of the ISA extension `%s'"),
1211 riscv_add_subset (rps
->subset_list
, subset
,
1212 major_version
, minor_version
);
1214 riscv_add_implicit_subset (rps
->subset_list
, subset
,
1215 major_version
, minor_version
);
1218 /* Release subset list. */
1221 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1223 while (subset_list
->head
!= NULL
)
1225 riscv_subset_t
*next
= subset_list
->head
->next
;
1226 free ((void *)subset_list
->head
->name
);
1227 free (subset_list
->head
);
1228 subset_list
->head
= next
;
1231 subset_list
->tail
= NULL
;
1234 /* Parsing extension version.
1237 Points to the end of version
1240 `rps`: Hooks and status for parsing extensions.
1241 `march`: Full arch string.
1242 `p`: Curent parsing position.
1243 `major_version`: Parsed major version.
1244 `minor_version`: Parsed minor version.
1245 `std_ext_p`: True if parsing standard extension. */
1248 riscv_parsing_subset_version (riscv_parse_subset_t
*rps
,
1253 bfd_boolean std_ext_p
)
1255 bfd_boolean major_p
= TRUE
;
1269 /* Might be beginning of `p` extension. */
1272 *major_version
= version
;
1279 (_("-march=%s: expect number after `%dp'"),
1285 *major_version
= version
;
1289 else if (ISDIGIT (*p
))
1290 version
= (version
* 10) + (*p
- '0');
1296 *major_version
= version
;
1298 *minor_version
= version
;
1300 /* We can not find any version in string. */
1301 if (*major_version
== 0 && *minor_version
== 0)
1303 *major_version
= RISCV_UNKNOWN_VERSION
;
1304 *minor_version
= RISCV_UNKNOWN_VERSION
;
1310 /* Return string which contain all supported standard extensions in
1314 riscv_supported_std_ext (void)
1316 return "mafdqlcbjtpvn";
1319 /* Parsing function for standard extensions.
1322 Points to the end of extensions.
1325 `rps`: Hooks and status for parsing extensions.
1326 `march`: Full arch string.
1327 `p`: Curent parsing position. */
1330 riscv_parse_std_ext (riscv_parse_subset_t
*rps
,
1334 const char *all_std_exts
= riscv_supported_std_ext ();
1335 const char *std_exts
= all_std_exts
;
1338 char subset
[2] = {0, 0};
1340 /* First letter must start with i, e or g. */
1344 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1346 &minor_version
, TRUE
);
1347 riscv_parse_add_subset (rps
, "i",
1349 minor_version
, FALSE
);
1353 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1355 &minor_version
, TRUE
);
1356 riscv_parse_add_subset (rps
, "e",
1358 minor_version
, FALSE
);
1359 /* i-ext must be enabled. */
1360 riscv_parse_add_subset (rps
, "i",
1361 RISCV_UNKNOWN_VERSION
,
1362 RISCV_UNKNOWN_VERSION
, FALSE
);
1364 if (*rps
->xlen
> 32)
1367 (_("-march=%s: rv%de is not a valid base ISA"),
1374 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1376 &minor_version
, TRUE
);
1377 /* i-ext must be enabled. */
1378 riscv_parse_add_subset (rps
, "i",
1379 RISCV_UNKNOWN_VERSION
,
1380 RISCV_UNKNOWN_VERSION
, FALSE
);
1381 /* g-ext is used to add the implicit extensions, but will
1382 not be output to the arch string. */
1383 riscv_parse_add_subset (rps
, "g",
1385 minor_version
, FALSE
);
1386 for ( ; *std_exts
!= 'q'; std_exts
++)
1388 subset
[0] = *std_exts
;
1389 riscv_parse_add_subset (rps
, subset
,
1390 RISCV_UNKNOWN_VERSION
,
1391 RISCV_UNKNOWN_VERSION
, FALSE
);
1397 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1402 while (p
!= NULL
&& *p
!= '\0')
1404 if (*p
== 'x' || *p
== 's' || *p
== 'h' || *p
== 'z')
1413 /* Checking canonical order. */
1415 while (*std_exts
&& std_ext
!= *std_exts
)
1418 if (std_ext
!= *std_exts
)
1420 if (strchr (all_std_exts
, std_ext
) == NULL
)
1422 (_("-march=%s: unknown standard ISA extension `%c'"),
1426 (_("-march=%s: standard ISA extension `%c' is not "
1427 "in canonical order"), march
, std_ext
);
1432 subset
[0] = std_ext
;
1433 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1435 &minor_version
, TRUE
);
1436 riscv_parse_add_subset (rps
, subset
,
1438 minor_version
, FALSE
);
1444 /* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1446 riscv_isa_ext_class_t
1447 riscv_get_prefix_class (const char *arch
)
1451 case 's': return RV_ISA_CLASS_S
;
1452 case 'h': return RV_ISA_CLASS_H
;
1453 case 'x': return RV_ISA_CLASS_X
;
1454 case 'z': return RV_ISA_CLASS_Z
;
1455 default: return RV_ISA_CLASS_UNKNOWN
;
1459 /* Structure describing parameters to use when parsing a particular
1460 riscv_isa_ext_class_t. One of these should be provided for each
1461 possible class, except RV_ISA_CLASS_UNKNOWN. */
1463 typedef struct riscv_parse_config
1465 /* Class of the extension. */
1466 riscv_isa_ext_class_t
class;
1468 /* Prefix string for error printing and internal parser usage. */
1471 /* Predicate which is used for checking whether this is a "known"
1472 extension. For 'x', it always returns true since they are by
1473 definition non-standard and cannot be known. */
1474 bfd_boolean (*ext_valid_p
) (const char *);
1475 } riscv_parse_config_t
;
1477 /* Parsing function for prefixed extensions.
1480 Points to the end of extension.
1483 `rps`: Hooks and status for parsing extensions.
1484 `march`: Full architecture string.
1485 `p`: Curent parsing position.
1486 `config`: What class and predicate function to use for the
1490 riscv_parse_prefixed_ext (riscv_parse_subset_t
*rps
,
1493 const riscv_parse_config_t
*config
)
1497 const char *last_name
;
1498 riscv_isa_ext_class_t
class;
1508 /* Assert that the current extension specifier matches our parsing
1510 class = riscv_get_prefix_class (p
);
1511 if (class != config
->class
1512 || class == RV_ISA_CLASS_UNKNOWN
)
1515 char *subset
= xstrdup (p
);
1517 const char *end_of_version
;
1519 while (*++q
!= '\0' && *q
!= '_' && !ISDIGIT (*q
))
1523 riscv_parsing_subset_version (rps
, march
, q
,
1525 &minor_version
, FALSE
);
1528 if (end_of_version
== NULL
)
1534 /* Check that the prefix extension is known.
1535 For 'x', anything goes but it cannot simply be 'x'.
1536 For 's', it must be known from a list and cannot simply be 's'.
1537 For 'h', it must be known from a list and cannot simply be 'h'.
1538 For 'z', it must be known from a list and cannot simply be 'z'. */
1540 /* Check that the extension name is well-formed. */
1541 if (!config
->ext_valid_p (subset
))
1544 (_("-march=%s: unknown %s ISA extension `%s'"),
1545 march
, config
->prefix
, subset
);
1550 /* Check that the extension isn't duplicate. */
1551 last_name
= rps
->subset_list
->tail
->name
;
1552 if (!strcasecmp (last_name
, subset
))
1555 (_("-march=%s: duplicate %s ISA extension `%s'"),
1556 march
, config
->prefix
, subset
);
1561 /* Check that the extension is in alphabetical order. */
1562 if (riscv_compare_subsets (last_name
, subset
) > 0)
1565 (_("-march=%s: %s ISA extension `%s' is not in alphabetical "
1566 "order. It must come before `%s'"),
1567 march
, config
->prefix
, subset
, last_name
);
1572 riscv_parse_add_subset (rps
, subset
,
1574 minor_version
, FALSE
);
1575 p
+= end_of_version
- subset
;
1578 if (*p
!= '\0' && *p
!= '_')
1581 (_("-march=%s: %s ISA extension must separate with _"),
1582 march
, config
->prefix
);
1590 /* Lists of prefixed class extensions that binutils should know about.
1591 Whether or not a particular entry is in these lists will dictate if
1592 gas/ld will accept its presence in the architecture string.
1594 Please add the extensions to the lists in lower case. However, keep
1595 these subsets in alphabetical order in these tables is recommended,
1596 although there is no impact on the current implementation. */
1598 static const char * const riscv_std_z_ext_strtab
[] =
1600 "zicsr", "zifencei", "zihintpause", "zba", "zbb", "zbc", NULL
1603 static const char * const riscv_std_s_ext_strtab
[] =
1608 static const char * const riscv_std_h_ext_strtab
[] =
1613 /* For the extension `ext`, search through the list of known extensions
1614 `known_exts` for a match, and return TRUE if found. */
1617 riscv_multi_letter_ext_valid_p (const char *ext
,
1618 const char *const *known_exts
)
1622 for (i
= 0; known_exts
[i
]; ++i
)
1623 if (!strcmp (ext
, known_exts
[i
]))
1629 /* Predicator function for x-prefixed extensions.
1630 Anything goes, except the literal 'x'. */
1633 riscv_ext_x_valid_p (const char *arg
)
1635 if (!strcasecmp (arg
, "x"))
1641 /* Predicator functions for z-prefixed extensions.
1642 Only known z-extensions are permitted. */
1645 riscv_ext_z_valid_p (const char *arg
)
1647 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_z_ext_strtab
);
1650 /* Predicator function for 's' prefixed extensions.
1651 Only known s-extensions are permitted. */
1654 riscv_ext_s_valid_p (const char *arg
)
1656 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_s_ext_strtab
);
1659 /* Predicator function for 'h' prefixed extensions.
1660 Only known h-extensions are permitted. */
1663 riscv_ext_h_valid_p (const char *arg
)
1665 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_h_ext_strtab
);
1668 /* Parsing order of the prefixed extensions that is specified by
1671 static const riscv_parse_config_t parse_config
[] =
1673 {RV_ISA_CLASS_S
, "s", riscv_ext_s_valid_p
},
1674 {RV_ISA_CLASS_H
, "h", riscv_ext_h_valid_p
},
1675 {RV_ISA_CLASS_Z
, "z", riscv_ext_z_valid_p
},
1676 {RV_ISA_CLASS_X
, "x", riscv_ext_x_valid_p
},
1677 {RV_ISA_CLASS_UNKNOWN
, NULL
, NULL
}
1680 /* Init the riscv_ext_order array. */
1683 riscv_init_ext_order (void)
1685 static bfd_boolean inited
= FALSE
;
1686 const char *std_base_exts
= "eig";
1687 const char *std_remain_exts
= riscv_supported_std_ext ();
1695 /* All standard extensions' orders are positive numbers. */
1698 /* Init the standard base extensions first. */
1699 for (ext
= std_base_exts
; *ext
; ext
++)
1700 riscv_ext_order
[(*ext
- 'a')] = order
++;
1702 /* Init the standard remaining extensions. */
1703 for (ext
= std_remain_exts
; *ext
; ext
++)
1704 riscv_ext_order
[(*ext
- 'a')] = order
++;
1706 /* Init the order for prefixed keywords. The orders are
1707 negative numbers. */
1709 for (i
= 0; parse_config
[i
].class != RV_ISA_CLASS_UNKNOWN
; i
++)
1711 ext
= parse_config
[i
].prefix
;
1712 riscv_ext_order
[(*ext
- 'a')] = order
--;
1718 /* Add the implicit extensions according to the arch string extensions. */
1721 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1723 riscv_subset_t
*subset
= NULL
;
1725 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
1726 if ((riscv_lookup_subset (rps
->subset_list
, "i", &subset
))
1727 && (subset
->major_version
< 2
1728 || (subset
->major_version
== 2
1729 && subset
->minor_version
< 1)))
1731 riscv_parse_add_subset (rps
, "zicsr",
1732 RISCV_UNKNOWN_VERSION
,
1733 RISCV_UNKNOWN_VERSION
, TRUE
);
1734 riscv_parse_add_subset (rps
, "zifencei",
1735 RISCV_UNKNOWN_VERSION
,
1736 RISCV_UNKNOWN_VERSION
, TRUE
);
1739 if ((riscv_lookup_subset (rps
->subset_list
, "q", &subset
)))
1741 riscv_parse_add_subset (rps
, "d",
1742 RISCV_UNKNOWN_VERSION
,
1743 RISCV_UNKNOWN_VERSION
, TRUE
);
1744 riscv_parse_add_subset (rps
, "f",
1745 RISCV_UNKNOWN_VERSION
,
1746 RISCV_UNKNOWN_VERSION
, TRUE
);
1747 riscv_parse_add_subset (rps
, "zicsr",
1748 RISCV_UNKNOWN_VERSION
,
1749 RISCV_UNKNOWN_VERSION
, TRUE
);
1751 else if ((riscv_lookup_subset (rps
->subset_list
, "d", &subset
)))
1753 riscv_parse_add_subset (rps
, "f",
1754 RISCV_UNKNOWN_VERSION
,
1755 RISCV_UNKNOWN_VERSION
, TRUE
);
1756 riscv_parse_add_subset (rps
, "zicsr",
1757 RISCV_UNKNOWN_VERSION
,
1758 RISCV_UNKNOWN_VERSION
, TRUE
);
1760 else if ((riscv_lookup_subset (rps
->subset_list
, "f", &subset
)))
1761 riscv_parse_add_subset (rps
, "zicsr",
1762 RISCV_UNKNOWN_VERSION
,
1763 RISCV_UNKNOWN_VERSION
, TRUE
);
1765 if ((riscv_lookup_subset (rps
->subset_list
, "g", &subset
)))
1767 riscv_parse_add_subset (rps
, "zicsr",
1768 RISCV_UNKNOWN_VERSION
,
1769 RISCV_UNKNOWN_VERSION
, TRUE
);
1770 riscv_parse_add_subset (rps
, "zifencei",
1771 RISCV_UNKNOWN_VERSION
,
1772 RISCV_UNKNOWN_VERSION
, TRUE
);
1776 /* Function for parsing arch string.
1779 Return TRUE on success.
1782 `rps`: Hooks and status for parsing extensions.
1783 `arch`: Full arch string. */
1786 riscv_parse_subset (riscv_parse_subset_t
*rps
,
1789 riscv_subset_t
*subset
= NULL
;
1792 bfd_boolean no_conflict
= TRUE
;
1794 for (p
= arch
; *p
!= '\0'; p
++)
1799 (_("-march=%s: ISA string cannot contain uppercase letters"),
1806 if (strncmp (p
, "rv32", 4) == 0)
1811 else if (strncmp (p
, "rv64", 4) == 0)
1818 /* Arch string shouldn't be NULL or empty here. However,
1819 it might be empty only when we failed to merge the arch
1820 string in the riscv_merge_attributes. We have already
1821 issued the correct error message in another side, so do
1822 not issue this error when the arch string is empty. */
1824 rps
->error_handler (
1825 _("-march=%s: ISA string must begin with rv32 or rv64"),
1830 /* Init the riscv_ext_order array to compare the order of extensions
1832 riscv_init_ext_order ();
1834 /* Parsing standard extension. */
1835 p
= riscv_parse_std_ext (rps
, arch
, p
);
1840 /* Parse the different classes of extensions in the specified order. */
1841 for (i
= 0; i
< ARRAY_SIZE (parse_config
); ++i
)
1843 p
= riscv_parse_prefixed_ext (rps
, arch
, p
, &parse_config
[i
]);
1851 rps
->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1856 /* Finally add implicit extensions according to the current
1858 riscv_parse_add_implicit_subsets (rps
);
1860 /* Check the conflicts. */
1861 if (riscv_lookup_subset (rps
->subset_list
, "e", &subset
)
1862 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1865 (_("-march=%s: rv32e does not support the `f' extension"),
1867 no_conflict
= FALSE
;
1869 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1873 (_("-march=%s: rv32 does not support the `q' extension"),
1875 no_conflict
= FALSE
;
1880 /* Return the number of digits for the input. */
1883 riscv_estimate_digit (unsigned num
)
1889 for (digit
= 0; num
; num
/= 10)
1895 /* Auxiliary function to estimate string length of subset list. */
1898 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
1901 return 6; /* For rv32/rv64/rv128 and string terminator. */
1903 return riscv_estimate_arch_strlen1 (subset
->next
)
1904 + strlen (subset
->name
)
1905 + riscv_estimate_digit (subset
->major_version
)
1906 + 1 /* For version seperator: 'p'. */
1907 + riscv_estimate_digit (subset
->minor_version
)
1908 + 1 /* For underscore. */;
1911 /* Estimate the string length of this subset list. */
1914 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
1916 return riscv_estimate_arch_strlen1 (subset_list
->head
);
1919 /* Auxiliary function to convert subset info to string. */
1922 riscv_arch_str1 (riscv_subset_t
*subset
,
1923 char *attr_str
, char *buf
, size_t bufsz
)
1925 const char *underline
= "_";
1926 riscv_subset_t
*subset_t
= subset
;
1928 if (subset_t
== NULL
)
1931 /* No underline between rvXX and i/e. */
1932 if ((strcasecmp (subset_t
->name
, "i") == 0)
1933 || (strcasecmp (subset_t
->name
, "e") == 0))
1936 snprintf (buf
, bufsz
, "%s%s%dp%d",
1939 subset_t
->major_version
,
1940 subset_t
->minor_version
);
1942 strncat (attr_str
, buf
, bufsz
);
1944 /* Skip 'i' extension after 'e', or skip extensions which
1945 versions are unknown. */
1946 while (subset_t
->next
1947 && ((strcmp (subset_t
->name
, "e") == 0
1948 && strcmp (subset_t
->next
->name
, "i") == 0)
1949 || subset_t
->next
->major_version
== RISCV_UNKNOWN_VERSION
1950 || subset_t
->next
->minor_version
== RISCV_UNKNOWN_VERSION
))
1951 subset_t
= subset_t
->next
;
1953 riscv_arch_str1 (subset_t
->next
, attr_str
, buf
, bufsz
);
1956 /* Convert subset info to string with explicit version info. */
1959 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
1961 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
1962 char *attr_str
= xmalloc (arch_str_len
);
1963 char *buf
= xmalloc (arch_str_len
);
1965 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
1967 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);