1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2020 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 /* We have to add all arch string extensions first, and then start to
1152 add their implicit extensions. The arch string extensions must be
1153 set in order, so we can add them to the last of the subset list
1154 directly, without searching.
1156 Find the default versions for the extension before adding them to
1157 the subset list, if their versions are RISCV_UNKNOWN_VERSION.
1158 Afterwards, report errors if we can not find their default versions. */
1161 riscv_parse_add_subset (riscv_parse_subset_t
*rps
,
1165 bfd_boolean implicit
)
1167 int major_version
= major
;
1168 int minor_version
= minor
;
1170 if ((major_version
== RISCV_UNKNOWN_VERSION
1171 || minor_version
== RISCV_UNKNOWN_VERSION
)
1172 && rps
->get_default_version
!= NULL
)
1173 rps
->get_default_version (subset
, &major_version
, &minor_version
);
1176 && strcmp (subset
, "g") != 0
1177 && (major_version
== RISCV_UNKNOWN_VERSION
1178 || minor_version
== RISCV_UNKNOWN_VERSION
))
1180 if (subset
[0] == 'x')
1182 (_("x ISA extension `%s' must be set with the versions"),
1186 (_("cannot find default versions of the ISA extension `%s'"),
1192 riscv_add_subset (rps
->subset_list
, subset
,
1193 major_version
, minor_version
);
1194 else if (major_version
!= RISCV_UNKNOWN_VERSION
1195 && minor_version
!= RISCV_UNKNOWN_VERSION
)
1196 /* We only add the implicit extension if it is supported in the
1198 riscv_add_implicit_subset (rps
->subset_list
, subset
,
1199 major_version
, minor_version
);
1202 /* Release subset list. */
1205 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1207 while (subset_list
->head
!= NULL
)
1209 riscv_subset_t
*next
= subset_list
->head
->next
;
1210 free ((void *)subset_list
->head
->name
);
1211 free (subset_list
->head
);
1212 subset_list
->head
= next
;
1215 subset_list
->tail
= NULL
;
1218 /* Parsing extension version.
1221 Points to the end of version
1224 `rps`: Hooks and status for parsing extensions.
1225 `march`: Full arch string.
1226 `p`: Curent parsing position.
1227 `major_version`: Parsed major version.
1228 `minor_version`: Parsed minor version.
1229 `std_ext_p`: True if parsing standard extension. */
1232 riscv_parsing_subset_version (riscv_parse_subset_t
*rps
,
1237 bfd_boolean std_ext_p
)
1239 bfd_boolean major_p
= TRUE
;
1253 /* Might be beginning of `p` extension. */
1256 *major_version
= version
;
1263 (_("-march=%s: expect number after `%dp'"),
1269 *major_version
= version
;
1273 else if (ISDIGIT (*p
))
1274 version
= (version
* 10) + (*p
- '0');
1280 *major_version
= version
;
1282 *minor_version
= version
;
1284 /* We can not find any version in string. */
1285 if (*major_version
== 0 && *minor_version
== 0)
1287 *major_version
= RISCV_UNKNOWN_VERSION
;
1288 *minor_version
= RISCV_UNKNOWN_VERSION
;
1294 /* Return string which contain all supported standard extensions in
1298 riscv_supported_std_ext (void)
1300 return "mafdqlcbjtpvn";
1303 /* Parsing function for standard extensions.
1306 Points to the end of extensions.
1309 `rps`: Hooks and status for parsing extensions.
1310 `march`: Full arch string.
1311 `p`: Curent parsing position. */
1314 riscv_parse_std_ext (riscv_parse_subset_t
*rps
,
1318 const char *all_std_exts
= riscv_supported_std_ext ();
1319 const char *std_exts
= all_std_exts
;
1322 char subset
[2] = {0, 0};
1324 /* First letter must start with i, e or g. */
1328 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1330 &minor_version
, TRUE
);
1331 riscv_parse_add_subset (rps
, "i",
1333 minor_version
, FALSE
);
1337 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1339 &minor_version
, TRUE
);
1340 riscv_parse_add_subset (rps
, "e",
1342 minor_version
, FALSE
);
1343 /* i-ext must be enabled. */
1344 riscv_parse_add_subset (rps
, "i",
1345 RISCV_UNKNOWN_VERSION
,
1346 RISCV_UNKNOWN_VERSION
, FALSE
);
1348 if (*rps
->xlen
> 32)
1351 (_("-march=%s: rv%de is not a valid base ISA"),
1358 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1360 &minor_version
, TRUE
);
1361 /* i-ext must be enabled. */
1362 riscv_parse_add_subset (rps
, "i",
1363 RISCV_UNKNOWN_VERSION
,
1364 RISCV_UNKNOWN_VERSION
, FALSE
);
1365 /* g-ext is used to add the implicit extensions, but will
1366 not be output to the arch string. */
1367 riscv_parse_add_subset (rps
, "g",
1369 minor_version
, FALSE
);
1370 for ( ; *std_exts
!= 'q'; std_exts
++)
1372 subset
[0] = *std_exts
;
1373 riscv_parse_add_subset (rps
, subset
,
1374 RISCV_UNKNOWN_VERSION
,
1375 RISCV_UNKNOWN_VERSION
, FALSE
);
1381 (_("-march=%s: first ISA extension must be `e', `i' or `g'"),
1386 while (p
!= NULL
&& *p
!= '\0')
1388 if (*p
== 'x' || *p
== 's' || *p
== 'h' || *p
== 'z')
1397 /* Checking canonical order. */
1399 while (*std_exts
&& std_ext
!= *std_exts
)
1402 if (std_ext
!= *std_exts
)
1404 if (strchr (all_std_exts
, std_ext
) == NULL
)
1406 (_("-march=%s: unknown standard ISA extension `%c'"),
1410 (_("-march=%s: standard ISA extension `%c' is not "
1411 "in canonical order"), march
, std_ext
);
1416 subset
[0] = std_ext
;
1417 p
= riscv_parsing_subset_version (rps
, march
, ++p
,
1419 &minor_version
, TRUE
);
1420 riscv_parse_add_subset (rps
, subset
,
1422 minor_version
, FALSE
);
1428 /* Classify the argument 'arch' into one of riscv_isa_ext_class_t. */
1430 riscv_isa_ext_class_t
1431 riscv_get_prefix_class (const char *arch
)
1435 case 's': return RV_ISA_CLASS_S
;
1436 case 'h': return RV_ISA_CLASS_H
;
1437 case 'x': return RV_ISA_CLASS_X
;
1438 case 'z': return RV_ISA_CLASS_Z
;
1439 default: return RV_ISA_CLASS_UNKNOWN
;
1443 /* Structure describing parameters to use when parsing a particular
1444 riscv_isa_ext_class_t. One of these should be provided for each
1445 possible class, except RV_ISA_CLASS_UNKNOWN. */
1447 typedef struct riscv_parse_config
1449 /* Class of the extension. */
1450 riscv_isa_ext_class_t
class;
1452 /* Prefix string for error printing and internal parser usage. */
1455 /* Predicate which is used for checking whether this is a "known"
1456 extension. For 'x', it always returns true since they are by
1457 definition non-standard and cannot be known. */
1458 bfd_boolean (*ext_valid_p
) (const char *);
1459 } riscv_parse_config_t
;
1461 /* Parsing function for prefixed extensions.
1464 Points to the end of extension.
1467 `rps`: Hooks and status for parsing extensions.
1468 `march`: Full architecture string.
1469 `p`: Curent parsing position.
1470 `config`: What class and predicate function to use for the
1474 riscv_parse_prefixed_ext (riscv_parse_subset_t
*rps
,
1477 const riscv_parse_config_t
*config
)
1481 const char *last_name
;
1482 riscv_isa_ext_class_t
class;
1492 /* Assert that the current extension specifier matches our parsing
1494 class = riscv_get_prefix_class (p
);
1495 if (class != config
->class
1496 || class == RV_ISA_CLASS_UNKNOWN
)
1499 char *subset
= xstrdup (p
);
1501 const char *end_of_version
;
1503 while (*++q
!= '\0' && *q
!= '_' && !ISDIGIT (*q
))
1507 riscv_parsing_subset_version (rps
, march
, q
,
1509 &minor_version
, FALSE
);
1512 if (end_of_version
== NULL
)
1518 /* Check that the prefix extension is known.
1519 For 'x', anything goes but it cannot simply be 'x'.
1520 For 's', it must be known from a list and cannot simply be 's'.
1521 For 'h', it must be known from a list and cannot simply be 'h'.
1522 For 'z', it must be known from a list and cannot simply be 'z'. */
1524 /* Check that the extension name is well-formed. */
1525 if (!config
->ext_valid_p (subset
))
1528 (_("-march=%s: unknown %s ISA extension `%s'"),
1529 march
, config
->prefix
, subset
);
1534 /* Check that the extension isn't duplicate. */
1535 last_name
= rps
->subset_list
->tail
->name
;
1536 if (!strcasecmp (last_name
, subset
))
1539 (_("-march=%s: duplicate %s ISA extension `%s'"),
1540 march
, config
->prefix
, subset
);
1545 /* Check that the extension is in alphabetical order. */
1546 if (!strncasecmp (last_name
, config
->prefix
, 1)
1547 && strcasecmp (last_name
, subset
) > 0)
1550 (_("-march=%s: %s ISA extension `%s' is not in alphabetical "
1551 "order. It must come before `%s'"),
1552 march
, config
->prefix
, subset
, last_name
);
1557 riscv_parse_add_subset (rps
, subset
,
1559 minor_version
, FALSE
);
1561 p
+= end_of_version
- subset
;
1563 if (*p
!= '\0' && *p
!= '_')
1566 (_("-march=%s: %s ISA extension must separate with _"),
1567 march
, config
->prefix
);
1575 /* Lists of prefixed class extensions that binutils should know about.
1576 Whether or not a particular entry is in these lists will dictate if
1577 gas/ld will accept its presence in the architecture string.
1579 Please add the extensions to the lists in lower case. However, keep
1580 these subsets in alphabetical order in these tables is recommended,
1581 although there is no impact on the current implementation. */
1583 static const char * const riscv_std_z_ext_strtab
[] =
1585 "zicsr", "zifencei", NULL
1588 static const char * const riscv_std_s_ext_strtab
[] =
1593 static const char * const riscv_std_h_ext_strtab
[] =
1598 /* For the extension `ext`, search through the list of known extensions
1599 `known_exts` for a match, and return TRUE if found. */
1602 riscv_multi_letter_ext_valid_p (const char *ext
,
1603 const char *const *known_exts
)
1607 for (i
= 0; known_exts
[i
]; ++i
)
1608 if (!strcmp (ext
, known_exts
[i
]))
1614 /* Predicator function for x-prefixed extensions.
1615 Anything goes, except the literal 'x'. */
1618 riscv_ext_x_valid_p (const char *arg
)
1620 if (!strcasecmp (arg
, "x"))
1626 /* Predicator functions for z-prefixed extensions.
1627 Only known z-extensions are permitted. */
1630 riscv_ext_z_valid_p (const char *arg
)
1632 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_z_ext_strtab
);
1635 /* Predicator function for 's' prefixed extensions.
1636 Only known s-extensions are permitted. */
1639 riscv_ext_s_valid_p (const char *arg
)
1641 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_s_ext_strtab
);
1644 /* Predicator function for 'h' prefixed extensions.
1645 Only known h-extensions are permitted. */
1648 riscv_ext_h_valid_p (const char *arg
)
1650 return riscv_multi_letter_ext_valid_p (arg
, riscv_std_h_ext_strtab
);
1653 /* Parsing order of the prefixed extensions that is specified by
1656 static const riscv_parse_config_t parse_config
[] =
1658 {RV_ISA_CLASS_S
, "s", riscv_ext_s_valid_p
},
1659 {RV_ISA_CLASS_H
, "h", riscv_ext_h_valid_p
},
1660 {RV_ISA_CLASS_Z
, "z", riscv_ext_z_valid_p
},
1661 {RV_ISA_CLASS_X
, "x", riscv_ext_x_valid_p
},
1662 {RV_ISA_CLASS_UNKNOWN
, NULL
, NULL
}
1665 /* Init the riscv_ext_order array. */
1668 riscv_init_ext_order (void)
1670 static bfd_boolean inited
= FALSE
;
1671 const char *std_base_exts
= "eig";
1672 const char *std_remain_exts
= riscv_supported_std_ext ();
1680 /* All standard extensions' orders are positive numbers. */
1683 /* Init the standard base extensions first. */
1684 for (ext
= std_base_exts
; *ext
; ext
++)
1685 riscv_ext_order
[(*ext
- 'a')] = order
++;
1687 /* Init the standard remaining extensions. */
1688 for (ext
= std_remain_exts
; *ext
; ext
++)
1689 riscv_ext_order
[(*ext
- 'a')] = order
++;
1691 /* Init the order for prefixed keywords. The orders are
1692 negative numbers. */
1694 for (i
= 0; parse_config
[i
].class != RV_ISA_CLASS_UNKNOWN
; i
++)
1696 ext
= parse_config
[i
].prefix
;
1697 riscv_ext_order
[(*ext
- 'a')] = order
--;
1703 /* Add the implicit extensions according to the arch string extensions. */
1706 riscv_parse_add_implicit_subsets (riscv_parse_subset_t
*rps
)
1708 riscv_subset_t
*subset
= NULL
;
1710 /* Add the zicsr and zifencei only when the i's version less than 2.1. */
1711 if ((riscv_lookup_subset (rps
->subset_list
, "i", &subset
))
1712 && (subset
->major_version
< 2
1713 || (subset
->major_version
== 2
1714 && subset
->minor_version
< 1)))
1716 riscv_parse_add_subset (rps
, "zicsr",
1717 RISCV_UNKNOWN_VERSION
,
1718 RISCV_UNKNOWN_VERSION
, TRUE
);
1719 riscv_parse_add_subset (rps
, "zifencei",
1720 RISCV_UNKNOWN_VERSION
,
1721 RISCV_UNKNOWN_VERSION
, TRUE
);
1724 if ((riscv_lookup_subset (rps
->subset_list
, "q", &subset
)))
1726 riscv_parse_add_subset (rps
, "d",
1727 RISCV_UNKNOWN_VERSION
,
1728 RISCV_UNKNOWN_VERSION
, TRUE
);
1729 riscv_parse_add_subset (rps
, "f",
1730 RISCV_UNKNOWN_VERSION
,
1731 RISCV_UNKNOWN_VERSION
, TRUE
);
1732 riscv_parse_add_subset (rps
, "zicsr",
1733 RISCV_UNKNOWN_VERSION
,
1734 RISCV_UNKNOWN_VERSION
, TRUE
);
1736 else if ((riscv_lookup_subset (rps
->subset_list
, "d", &subset
)))
1738 riscv_parse_add_subset (rps
, "f",
1739 RISCV_UNKNOWN_VERSION
,
1740 RISCV_UNKNOWN_VERSION
, TRUE
);
1741 riscv_parse_add_subset (rps
, "zicsr",
1742 RISCV_UNKNOWN_VERSION
,
1743 RISCV_UNKNOWN_VERSION
, TRUE
);
1745 else if ((riscv_lookup_subset (rps
->subset_list
, "f", &subset
)))
1746 riscv_parse_add_subset (rps
, "zicsr",
1747 RISCV_UNKNOWN_VERSION
,
1748 RISCV_UNKNOWN_VERSION
, TRUE
);
1750 if ((riscv_lookup_subset (rps
->subset_list
, "g", &subset
)))
1752 riscv_parse_add_subset (rps
, "zicsr",
1753 RISCV_UNKNOWN_VERSION
,
1754 RISCV_UNKNOWN_VERSION
, TRUE
);
1755 riscv_parse_add_subset (rps
, "zifencei",
1756 RISCV_UNKNOWN_VERSION
,
1757 RISCV_UNKNOWN_VERSION
, TRUE
);
1761 /* Function for parsing arch string.
1764 Return TRUE on success.
1767 `rps`: Hooks and status for parsing extensions.
1768 `arch`: Full arch string. */
1771 riscv_parse_subset (riscv_parse_subset_t
*rps
,
1774 riscv_subset_t
*subset
= NULL
;
1777 bfd_boolean no_conflict
= TRUE
;
1779 for (p
= arch
; *p
!= '\0'; p
++)
1784 (_("-march=%s: ISA string cannot contain uppercase letters"),
1791 if (strncmp (p
, "rv32", 4) == 0)
1796 else if (strncmp (p
, "rv64", 4) == 0)
1803 /* Arch string shouldn't be NULL or empty here. However,
1804 it might be empty only when we failed to merge the arch
1805 string in the riscv_merge_attributes. We have already
1806 issued the correct error message in another side, so do
1807 not issue this error when the arch string is empty. */
1809 rps
->error_handler (
1810 _("-march=%s: ISA string must begin with rv32 or rv64"),
1815 /* Init the riscv_ext_order array to compare the order of extensions
1817 riscv_init_ext_order ();
1819 /* Parsing standard extension. */
1820 p
= riscv_parse_std_ext (rps
, arch
, p
);
1825 /* Parse the different classes of extensions in the specified order. */
1826 for (i
= 0; i
< ARRAY_SIZE (parse_config
); ++i
)
1828 p
= riscv_parse_prefixed_ext (rps
, arch
, p
, &parse_config
[i
]);
1836 rps
->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
1841 /* Finally add implicit extensions according to the current
1843 riscv_parse_add_implicit_subsets (rps
);
1845 /* Check the conflicts. */
1846 if (riscv_lookup_subset (rps
->subset_list
, "e", &subset
)
1847 && riscv_lookup_subset (rps
->subset_list
, "f", &subset
))
1850 (_("-march=%s: rv32e does not support the `f' extension"),
1852 no_conflict
= FALSE
;
1854 if (riscv_lookup_subset (rps
->subset_list
, "q", &subset
)
1858 (_("-march=%s: rv32 does not support the `q' extension"),
1860 no_conflict
= FALSE
;
1865 /* Return the number of digits for the input. */
1868 riscv_estimate_digit (unsigned num
)
1874 for (digit
= 0; num
; num
/= 10)
1880 /* Auxiliary function to estimate string length of subset list. */
1883 riscv_estimate_arch_strlen1 (const riscv_subset_t
*subset
)
1886 return 6; /* For rv32/rv64/rv128 and string terminator. */
1888 return riscv_estimate_arch_strlen1 (subset
->next
)
1889 + strlen (subset
->name
)
1890 + riscv_estimate_digit (subset
->major_version
)
1891 + 1 /* For version seperator: 'p'. */
1892 + riscv_estimate_digit (subset
->minor_version
)
1893 + 1 /* For underscore. */;
1896 /* Estimate the string length of this subset list. */
1899 riscv_estimate_arch_strlen (const riscv_subset_list_t
*subset_list
)
1901 return riscv_estimate_arch_strlen1 (subset_list
->head
);
1904 /* Auxiliary function to convert subset info to string. */
1907 riscv_arch_str1 (riscv_subset_t
*subset
,
1908 char *attr_str
, char *buf
, size_t bufsz
)
1910 const char *underline
= "_";
1915 /* No underline between rvXX and i/e. */
1916 if ((strcasecmp (subset
->name
, "i") == 0)
1917 || (strcasecmp (subset
->name
, "e") == 0))
1920 snprintf (buf
, bufsz
, "%s%s%dp%d",
1923 subset
->major_version
,
1924 subset
->minor_version
);
1926 strncat (attr_str
, buf
, bufsz
);
1928 /* Skip 'i' extension after 'e', and skip 'g' extension. */
1930 && ((strcmp (subset
->name
, "e") == 0
1931 && strcmp (subset
->next
->name
, "i") == 0)
1932 || strcmp (subset
->next
->name
, "g") == 0))
1933 riscv_arch_str1 (subset
->next
->next
, attr_str
, buf
, bufsz
);
1935 riscv_arch_str1 (subset
->next
, attr_str
, buf
, bufsz
);
1938 /* Convert subset info to string with explicit version info. */
1941 riscv_arch_str (unsigned xlen
, const riscv_subset_list_t
*subset
)
1943 size_t arch_str_len
= riscv_estimate_arch_strlen (subset
);
1944 char *attr_str
= xmalloc (arch_str_len
);
1945 char *buf
= xmalloc (arch_str_len
);
1947 snprintf (attr_str
, arch_str_len
, "rv%u", xlen
);
1949 riscv_arch_str1 (subset
->head
, attr_str
, buf
, arch_str_len
);