1 /* RISC-V-specific support for ELF.
2 Copyright (C) 2011-2018 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 "opcode/riscv.h"
29 #include "libiberty.h"
30 #include "elfxx-riscv.h"
31 #include "safe-ctype.h"
34 #define MINUS_ONE ((bfd_vma)0 - 1)
36 /* Special handler for ADD/SUB relocations that allows them to be filled out
37 both in the pre-linked and post-linked file. This is necessary to make
38 pre-linked debug info work, as due to linker relaxations we need to emit
39 relocations for the debug info. */
40 static bfd_reloc_status_type riscv_elf_add_sub_reloc
41 (bfd
*, arelent
*, asymbol
*, void *, asection
*, bfd
*, char **);
43 /* The relocation table used for SHT_RELA sections. */
45 static reloc_howto_type howto_table
[] =
48 HOWTO (R_RISCV_NONE
, /* type */
52 FALSE
, /* pc_relative */
54 complain_overflow_dont
, /* complain_on_overflow */
55 bfd_elf_generic_reloc
, /* special_function */
56 "R_RISCV_NONE", /* name */
57 FALSE
, /* partial_inplace */
60 FALSE
), /* pcrel_offset */
62 /* 32 bit relocation. */
63 HOWTO (R_RISCV_32
, /* type */
67 FALSE
, /* pc_relative */
69 complain_overflow_dont
, /* complain_on_overflow */
70 bfd_elf_generic_reloc
, /* special_function */
71 "R_RISCV_32", /* name */
72 FALSE
, /* partial_inplace */
74 MINUS_ONE
, /* dst_mask */
75 FALSE
), /* pcrel_offset */
77 /* 64 bit relocation. */
78 HOWTO (R_RISCV_64
, /* type */
82 FALSE
, /* pc_relative */
84 complain_overflow_dont
, /* complain_on_overflow */
85 bfd_elf_generic_reloc
, /* special_function */
86 "R_RISCV_64", /* name */
87 FALSE
, /* partial_inplace */
89 MINUS_ONE
, /* dst_mask */
90 FALSE
), /* pcrel_offset */
92 /* Relocation against a local symbol in a shared object. */
93 HOWTO (R_RISCV_RELATIVE
, /* type */
97 FALSE
, /* pc_relative */
99 complain_overflow_dont
, /* complain_on_overflow */
100 bfd_elf_generic_reloc
, /* special_function */
101 "R_RISCV_RELATIVE", /* name */
102 FALSE
, /* partial_inplace */
104 MINUS_ONE
, /* dst_mask */
105 FALSE
), /* pcrel_offset */
107 HOWTO (R_RISCV_COPY
, /* type */
109 0, /* this one is variable size */
111 FALSE
, /* pc_relative */
113 complain_overflow_bitfield
, /* complain_on_overflow */
114 bfd_elf_generic_reloc
, /* special_function */
115 "R_RISCV_COPY", /* name */
116 FALSE
, /* partial_inplace */
119 FALSE
), /* pcrel_offset */
121 HOWTO (R_RISCV_JUMP_SLOT
, /* type */
125 FALSE
, /* pc_relative */
127 complain_overflow_bitfield
, /* complain_on_overflow */
128 bfd_elf_generic_reloc
, /* special_function */
129 "R_RISCV_JUMP_SLOT", /* name */
130 FALSE
, /* partial_inplace */
133 FALSE
), /* pcrel_offset */
135 /* Dynamic TLS relocations. */
136 HOWTO (R_RISCV_TLS_DTPMOD32
, /* type */
140 FALSE
, /* pc_relative */
142 complain_overflow_dont
, /* complain_on_overflow */
143 bfd_elf_generic_reloc
, /* special_function */
144 "R_RISCV_TLS_DTPMOD32", /* name */
145 FALSE
, /* partial_inplace */
147 MINUS_ONE
, /* dst_mask */
148 FALSE
), /* pcrel_offset */
150 HOWTO (R_RISCV_TLS_DTPMOD64
, /* type */
154 FALSE
, /* pc_relative */
156 complain_overflow_dont
, /* complain_on_overflow */
157 bfd_elf_generic_reloc
, /* special_function */
158 "R_RISCV_TLS_DTPMOD64", /* name */
159 FALSE
, /* partial_inplace */
161 MINUS_ONE
, /* dst_mask */
162 FALSE
), /* pcrel_offset */
164 HOWTO (R_RISCV_TLS_DTPREL32
, /* type */
168 FALSE
, /* pc_relative */
170 complain_overflow_dont
, /* complain_on_overflow */
171 bfd_elf_generic_reloc
, /* special_function */
172 "R_RISCV_TLS_DTPREL32", /* name */
173 TRUE
, /* partial_inplace */
175 MINUS_ONE
, /* dst_mask */
176 FALSE
), /* pcrel_offset */
178 HOWTO (R_RISCV_TLS_DTPREL64
, /* type */
182 FALSE
, /* pc_relative */
184 complain_overflow_dont
, /* complain_on_overflow */
185 bfd_elf_generic_reloc
, /* special_function */
186 "R_RISCV_TLS_DTPREL64", /* name */
187 TRUE
, /* partial_inplace */
189 MINUS_ONE
, /* dst_mask */
190 FALSE
), /* pcrel_offset */
192 HOWTO (R_RISCV_TLS_TPREL32
, /* type */
196 FALSE
, /* pc_relative */
198 complain_overflow_dont
, /* complain_on_overflow */
199 bfd_elf_generic_reloc
, /* special_function */
200 "R_RISCV_TLS_TPREL32", /* name */
201 FALSE
, /* partial_inplace */
203 MINUS_ONE
, /* dst_mask */
204 FALSE
), /* pcrel_offset */
206 HOWTO (R_RISCV_TLS_TPREL64
, /* type */
210 FALSE
, /* pc_relative */
212 complain_overflow_dont
, /* complain_on_overflow */
213 bfd_elf_generic_reloc
, /* special_function */
214 "R_RISCV_TLS_TPREL64", /* name */
215 FALSE
, /* partial_inplace */
217 MINUS_ONE
, /* dst_mask */
218 FALSE
), /* pcrel_offset */
220 /* Reserved for future relocs that the dynamic linker must understand. */
226 /* 12-bit PC-relative branch offset. */
227 HOWTO (R_RISCV_BRANCH
, /* type */
231 TRUE
, /* pc_relative */
233 complain_overflow_signed
, /* complain_on_overflow */
234 bfd_elf_generic_reloc
, /* special_function */
235 "R_RISCV_BRANCH", /* name */
236 FALSE
, /* partial_inplace */
238 ENCODE_SBTYPE_IMM (-1U), /* dst_mask */
239 TRUE
), /* pcrel_offset */
241 /* 20-bit PC-relative jump offset. */
242 HOWTO (R_RISCV_JAL
, /* type */
246 TRUE
, /* pc_relative */
248 complain_overflow_dont
, /* complain_on_overflow */
249 bfd_elf_generic_reloc
, /* special_function */
250 "R_RISCV_JAL", /* name */
251 FALSE
, /* partial_inplace */
253 ENCODE_UJTYPE_IMM (-1U), /* dst_mask */
254 TRUE
), /* pcrel_offset */
256 /* 32-bit PC-relative function call (AUIPC/JALR). */
257 HOWTO (R_RISCV_CALL
, /* type */
261 TRUE
, /* pc_relative */
263 complain_overflow_dont
, /* complain_on_overflow */
264 bfd_elf_generic_reloc
, /* special_function */
265 "R_RISCV_CALL", /* name */
266 FALSE
, /* partial_inplace */
268 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
270 TRUE
), /* pcrel_offset */
272 /* Like R_RISCV_CALL, but not locally binding. */
273 HOWTO (R_RISCV_CALL_PLT
, /* type */
277 TRUE
, /* pc_relative */
279 complain_overflow_dont
, /* complain_on_overflow */
280 bfd_elf_generic_reloc
, /* special_function */
281 "R_RISCV_CALL_PLT", /* name */
282 FALSE
, /* partial_inplace */
284 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma
) ENCODE_ITYPE_IMM (-1U) << 32),
286 TRUE
), /* pcrel_offset */
288 /* High 20 bits of 32-bit PC-relative GOT access. */
289 HOWTO (R_RISCV_GOT_HI20
, /* type */
293 TRUE
, /* pc_relative */
295 complain_overflow_dont
, /* complain_on_overflow */
296 bfd_elf_generic_reloc
, /* special_function */
297 "R_RISCV_GOT_HI20", /* name */
298 FALSE
, /* partial_inplace */
300 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
301 FALSE
), /* pcrel_offset */
303 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */
304 HOWTO (R_RISCV_TLS_GOT_HI20
, /* type */
308 TRUE
, /* pc_relative */
310 complain_overflow_dont
, /* complain_on_overflow */
311 bfd_elf_generic_reloc
, /* special_function */
312 "R_RISCV_TLS_GOT_HI20", /* name */
313 FALSE
, /* partial_inplace */
315 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
316 FALSE
), /* pcrel_offset */
318 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */
319 HOWTO (R_RISCV_TLS_GD_HI20
, /* type */
323 TRUE
, /* pc_relative */
325 complain_overflow_dont
, /* complain_on_overflow */
326 bfd_elf_generic_reloc
, /* special_function */
327 "R_RISCV_TLS_GD_HI20", /* name */
328 FALSE
, /* partial_inplace */
330 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
331 FALSE
), /* pcrel_offset */
333 /* High 20 bits of 32-bit PC-relative reference. */
334 HOWTO (R_RISCV_PCREL_HI20
, /* type */
338 TRUE
, /* pc_relative */
340 complain_overflow_dont
, /* complain_on_overflow */
341 bfd_elf_generic_reloc
, /* special_function */
342 "R_RISCV_PCREL_HI20", /* name */
343 FALSE
, /* partial_inplace */
345 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
346 TRUE
), /* pcrel_offset */
348 /* Low 12 bits of a 32-bit PC-relative load or add. */
349 HOWTO (R_RISCV_PCREL_LO12_I
, /* type */
353 FALSE
, /* pc_relative */
355 complain_overflow_dont
, /* complain_on_overflow */
356 bfd_elf_generic_reloc
, /* special_function */
357 "R_RISCV_PCREL_LO12_I", /* name */
358 FALSE
, /* partial_inplace */
360 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
361 FALSE
), /* pcrel_offset */
363 /* Low 12 bits of a 32-bit PC-relative store. */
364 HOWTO (R_RISCV_PCREL_LO12_S
, /* type */
368 FALSE
, /* pc_relative */
370 complain_overflow_dont
, /* complain_on_overflow */
371 bfd_elf_generic_reloc
, /* special_function */
372 "R_RISCV_PCREL_LO12_S", /* name */
373 FALSE
, /* partial_inplace */
375 ENCODE_STYPE_IMM (-1U), /* dst_mask */
376 FALSE
), /* pcrel_offset */
378 /* High 20 bits of 32-bit absolute address. */
379 HOWTO (R_RISCV_HI20
, /* type */
383 FALSE
, /* pc_relative */
385 complain_overflow_dont
, /* complain_on_overflow */
386 bfd_elf_generic_reloc
, /* special_function */
387 "R_RISCV_HI20", /* name */
388 FALSE
, /* partial_inplace */
390 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
391 FALSE
), /* pcrel_offset */
393 /* High 12 bits of 32-bit load or add. */
394 HOWTO (R_RISCV_LO12_I
, /* type */
398 FALSE
, /* pc_relative */
400 complain_overflow_dont
, /* complain_on_overflow */
401 bfd_elf_generic_reloc
, /* special_function */
402 "R_RISCV_LO12_I", /* name */
403 FALSE
, /* partial_inplace */
405 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
406 FALSE
), /* pcrel_offset */
408 /* High 12 bits of 32-bit store. */
409 HOWTO (R_RISCV_LO12_S
, /* type */
413 FALSE
, /* pc_relative */
415 complain_overflow_dont
, /* complain_on_overflow */
416 bfd_elf_generic_reloc
, /* special_function */
417 "R_RISCV_LO12_S", /* name */
418 FALSE
, /* partial_inplace */
420 ENCODE_STYPE_IMM (-1U), /* dst_mask */
421 FALSE
), /* pcrel_offset */
423 /* High 20 bits of TLS LE thread pointer offset. */
424 HOWTO (R_RISCV_TPREL_HI20
, /* type */
428 FALSE
, /* pc_relative */
430 complain_overflow_signed
, /* complain_on_overflow */
431 bfd_elf_generic_reloc
, /* special_function */
432 "R_RISCV_TPREL_HI20", /* name */
433 TRUE
, /* partial_inplace */
435 ENCODE_UTYPE_IMM (-1U), /* dst_mask */
436 FALSE
), /* pcrel_offset */
438 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */
439 HOWTO (R_RISCV_TPREL_LO12_I
, /* type */
443 FALSE
, /* pc_relative */
445 complain_overflow_signed
, /* complain_on_overflow */
446 bfd_elf_generic_reloc
, /* special_function */
447 "R_RISCV_TPREL_LO12_I", /* name */
448 FALSE
, /* partial_inplace */
450 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
451 FALSE
), /* pcrel_offset */
453 /* Low 12 bits of TLS LE thread pointer offset for stores. */
454 HOWTO (R_RISCV_TPREL_LO12_S
, /* type */
458 FALSE
, /* pc_relative */
460 complain_overflow_signed
, /* complain_on_overflow */
461 bfd_elf_generic_reloc
, /* special_function */
462 "R_RISCV_TPREL_LO12_S", /* name */
463 FALSE
, /* partial_inplace */
465 ENCODE_STYPE_IMM (-1U), /* dst_mask */
466 FALSE
), /* pcrel_offset */
468 /* TLS LE thread pointer usage. May be relaxed. */
469 HOWTO (R_RISCV_TPREL_ADD
, /* type */
473 FALSE
, /* pc_relative */
475 complain_overflow_dont
, /* complain_on_overflow */
476 bfd_elf_generic_reloc
, /* special_function */
477 "R_RISCV_TPREL_ADD", /* name */
478 TRUE
, /* partial_inplace */
481 FALSE
), /* pcrel_offset */
483 /* 8-bit in-place addition, for local label subtraction. */
484 HOWTO (R_RISCV_ADD8
, /* type */
488 FALSE
, /* pc_relative */
490 complain_overflow_dont
, /* complain_on_overflow */
491 riscv_elf_add_sub_reloc
, /* special_function */
492 "R_RISCV_ADD8", /* name */
493 FALSE
, /* partial_inplace */
495 MINUS_ONE
, /* dst_mask */
496 FALSE
), /* pcrel_offset */
498 /* 16-bit in-place addition, for local label subtraction. */
499 HOWTO (R_RISCV_ADD16
, /* type */
503 FALSE
, /* pc_relative */
505 complain_overflow_dont
, /* complain_on_overflow */
506 riscv_elf_add_sub_reloc
, /* special_function */
507 "R_RISCV_ADD16", /* name */
508 FALSE
, /* partial_inplace */
510 MINUS_ONE
, /* dst_mask */
511 FALSE
), /* pcrel_offset */
513 /* 32-bit in-place addition, for local label subtraction. */
514 HOWTO (R_RISCV_ADD32
, /* type */
518 FALSE
, /* pc_relative */
520 complain_overflow_dont
, /* complain_on_overflow */
521 riscv_elf_add_sub_reloc
, /* special_function */
522 "R_RISCV_ADD32", /* name */
523 FALSE
, /* partial_inplace */
525 MINUS_ONE
, /* dst_mask */
526 FALSE
), /* pcrel_offset */
528 /* 64-bit in-place addition, for local label subtraction. */
529 HOWTO (R_RISCV_ADD64
, /* type */
533 FALSE
, /* pc_relative */
535 complain_overflow_dont
, /* complain_on_overflow */
536 riscv_elf_add_sub_reloc
, /* special_function */
537 "R_RISCV_ADD64", /* name */
538 FALSE
, /* partial_inplace */
540 MINUS_ONE
, /* dst_mask */
541 FALSE
), /* pcrel_offset */
543 /* 8-bit in-place addition, for local label subtraction. */
544 HOWTO (R_RISCV_SUB8
, /* type */
548 FALSE
, /* pc_relative */
550 complain_overflow_dont
, /* complain_on_overflow */
551 riscv_elf_add_sub_reloc
, /* special_function */
552 "R_RISCV_SUB8", /* name */
553 FALSE
, /* partial_inplace */
555 MINUS_ONE
, /* dst_mask */
556 FALSE
), /* pcrel_offset */
558 /* 16-bit in-place addition, for local label subtraction. */
559 HOWTO (R_RISCV_SUB16
, /* type */
563 FALSE
, /* pc_relative */
565 complain_overflow_dont
, /* complain_on_overflow */
566 riscv_elf_add_sub_reloc
, /* special_function */
567 "R_RISCV_SUB16", /* name */
568 FALSE
, /* partial_inplace */
570 MINUS_ONE
, /* dst_mask */
571 FALSE
), /* pcrel_offset */
573 /* 32-bit in-place addition, for local label subtraction. */
574 HOWTO (R_RISCV_SUB32
, /* type */
578 FALSE
, /* pc_relative */
580 complain_overflow_dont
, /* complain_on_overflow */
581 riscv_elf_add_sub_reloc
, /* special_function */
582 "R_RISCV_SUB32", /* name */
583 FALSE
, /* partial_inplace */
585 MINUS_ONE
, /* dst_mask */
586 FALSE
), /* pcrel_offset */
588 /* 64-bit in-place addition, for local label subtraction. */
589 HOWTO (R_RISCV_SUB64
, /* type */
593 FALSE
, /* pc_relative */
595 complain_overflow_dont
, /* complain_on_overflow */
596 riscv_elf_add_sub_reloc
, /* special_function */
597 "R_RISCV_SUB64", /* name */
598 FALSE
, /* partial_inplace */
600 MINUS_ONE
, /* dst_mask */
601 FALSE
), /* pcrel_offset */
603 /* GNU extension to record C++ vtable hierarchy */
604 HOWTO (R_RISCV_GNU_VTINHERIT
, /* type */
608 FALSE
, /* pc_relative */
610 complain_overflow_dont
, /* complain_on_overflow */
611 NULL
, /* special_function */
612 "R_RISCV_GNU_VTINHERIT", /* name */
613 FALSE
, /* partial_inplace */
616 FALSE
), /* pcrel_offset */
618 /* GNU extension to record C++ vtable member usage */
619 HOWTO (R_RISCV_GNU_VTENTRY
, /* type */
623 FALSE
, /* pc_relative */
625 complain_overflow_dont
, /* complain_on_overflow */
626 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
627 "R_RISCV_GNU_VTENTRY", /* name */
628 FALSE
, /* partial_inplace */
631 FALSE
), /* pcrel_offset */
633 /* Indicates an alignment statement. The addend field encodes how many
634 bytes of NOPs follow the statement. The desired alignment is the
635 addend rounded up to the next power of two. */
636 HOWTO (R_RISCV_ALIGN
, /* type */
640 FALSE
, /* pc_relative */
642 complain_overflow_dont
, /* complain_on_overflow */
643 bfd_elf_generic_reloc
, /* special_function */
644 "R_RISCV_ALIGN", /* name */
645 FALSE
, /* partial_inplace */
648 TRUE
), /* pcrel_offset */
650 /* 8-bit PC-relative branch offset. */
651 HOWTO (R_RISCV_RVC_BRANCH
, /* type */
655 TRUE
, /* pc_relative */
657 complain_overflow_signed
, /* complain_on_overflow */
658 bfd_elf_generic_reloc
, /* special_function */
659 "R_RISCV_RVC_BRANCH", /* name */
660 FALSE
, /* partial_inplace */
662 ENCODE_RVC_B_IMM (-1U), /* dst_mask */
663 TRUE
), /* pcrel_offset */
665 /* 11-bit PC-relative jump offset. */
666 HOWTO (R_RISCV_RVC_JUMP
, /* type */
670 TRUE
, /* pc_relative */
672 complain_overflow_dont
, /* complain_on_overflow */
673 bfd_elf_generic_reloc
, /* special_function */
674 "R_RISCV_RVC_JUMP", /* name */
675 FALSE
, /* partial_inplace */
677 ENCODE_RVC_J_IMM (-1U), /* dst_mask */
678 TRUE
), /* pcrel_offset */
680 /* High 6 bits of 18-bit absolute address. */
681 HOWTO (R_RISCV_RVC_LUI
, /* type */
685 FALSE
, /* pc_relative */
687 complain_overflow_dont
, /* complain_on_overflow */
688 bfd_elf_generic_reloc
, /* special_function */
689 "R_RISCV_RVC_LUI", /* name */
690 FALSE
, /* partial_inplace */
692 ENCODE_RVC_IMM (-1U), /* dst_mask */
693 FALSE
), /* pcrel_offset */
695 /* GP-relative load. */
696 HOWTO (R_RISCV_GPREL_I
, /* type */
700 FALSE
, /* pc_relative */
702 complain_overflow_dont
, /* complain_on_overflow */
703 bfd_elf_generic_reloc
, /* special_function */
704 "R_RISCV_GPREL_I", /* name */
705 FALSE
, /* partial_inplace */
707 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
708 FALSE
), /* pcrel_offset */
710 /* GP-relative store. */
711 HOWTO (R_RISCV_GPREL_S
, /* type */
715 FALSE
, /* pc_relative */
717 complain_overflow_dont
, /* complain_on_overflow */
718 bfd_elf_generic_reloc
, /* special_function */
719 "R_RISCV_GPREL_S", /* name */
720 FALSE
, /* partial_inplace */
722 ENCODE_STYPE_IMM (-1U), /* dst_mask */
723 FALSE
), /* pcrel_offset */
725 /* TP-relative TLS LE load. */
726 HOWTO (R_RISCV_TPREL_I
, /* type */
730 FALSE
, /* pc_relative */
732 complain_overflow_signed
, /* complain_on_overflow */
733 bfd_elf_generic_reloc
, /* special_function */
734 "R_RISCV_TPREL_I", /* name */
735 FALSE
, /* partial_inplace */
737 ENCODE_ITYPE_IMM (-1U), /* dst_mask */
738 FALSE
), /* pcrel_offset */
740 /* TP-relative TLS LE store. */
741 HOWTO (R_RISCV_TPREL_S
, /* type */
745 FALSE
, /* pc_relative */
747 complain_overflow_signed
, /* complain_on_overflow */
748 bfd_elf_generic_reloc
, /* special_function */
749 "R_RISCV_TPREL_S", /* name */
750 FALSE
, /* partial_inplace */
752 ENCODE_STYPE_IMM (-1U), /* dst_mask */
753 FALSE
), /* pcrel_offset */
755 /* The paired relocation may be relaxed. */
756 HOWTO (R_RISCV_RELAX
, /* type */
760 FALSE
, /* pc_relative */
762 complain_overflow_dont
, /* complain_on_overflow */
763 bfd_elf_generic_reloc
, /* special_function */
764 "R_RISCV_RELAX", /* name */
765 FALSE
, /* partial_inplace */
768 FALSE
), /* pcrel_offset */
770 /* 6-bit in-place addition, for local label subtraction. */
771 HOWTO (R_RISCV_SUB6
, /* type */
775 FALSE
, /* pc_relative */
777 complain_overflow_dont
, /* complain_on_overflow */
778 riscv_elf_add_sub_reloc
, /* special_function */
779 "R_RISCV_SUB6", /* name */
780 FALSE
, /* partial_inplace */
783 FALSE
), /* pcrel_offset */
785 /* 6-bit in-place setting, for local label subtraction. */
786 HOWTO (R_RISCV_SET6
, /* type */
790 FALSE
, /* pc_relative */
792 complain_overflow_dont
, /* complain_on_overflow */
793 bfd_elf_generic_reloc
, /* special_function */
794 "R_RISCV_SET6", /* name */
795 FALSE
, /* partial_inplace */
798 FALSE
), /* pcrel_offset */
800 /* 8-bit in-place setting, for local label subtraction. */
801 HOWTO (R_RISCV_SET8
, /* type */
805 FALSE
, /* pc_relative */
807 complain_overflow_dont
, /* complain_on_overflow */
808 bfd_elf_generic_reloc
, /* special_function */
809 "R_RISCV_SET8", /* name */
810 FALSE
, /* partial_inplace */
812 MINUS_ONE
, /* dst_mask */
813 FALSE
), /* pcrel_offset */
815 /* 16-bit in-place setting, for local label subtraction. */
816 HOWTO (R_RISCV_SET16
, /* type */
820 FALSE
, /* pc_relative */
822 complain_overflow_dont
, /* complain_on_overflow */
823 bfd_elf_generic_reloc
, /* special_function */
824 "R_RISCV_SET16", /* name */
825 FALSE
, /* partial_inplace */
827 MINUS_ONE
, /* dst_mask */
828 FALSE
), /* pcrel_offset */
830 /* 32-bit in-place setting, for local label subtraction. */
831 HOWTO (R_RISCV_SET32
, /* type */
835 FALSE
, /* pc_relative */
837 complain_overflow_dont
, /* complain_on_overflow */
838 bfd_elf_generic_reloc
, /* special_function */
839 "R_RISCV_SET32", /* name */
840 FALSE
, /* partial_inplace */
842 MINUS_ONE
, /* dst_mask */
843 FALSE
), /* pcrel_offset */
845 /* 32-bit PC relative. */
846 HOWTO (R_RISCV_32_PCREL
, /* type */
850 TRUE
, /* pc_relative */
852 complain_overflow_dont
, /* complain_on_overflow */
853 bfd_elf_generic_reloc
, /* special_function */
854 "R_RISCV_32_PCREL", /* name */
855 FALSE
, /* partial_inplace */
857 MINUS_ONE
, /* dst_mask */
858 FALSE
), /* pcrel_offset */
861 /* A mapping from BFD reloc types to RISC-V ELF reloc types. */
865 bfd_reloc_code_real_type bfd_val
;
866 enum elf_riscv_reloc_type elf_val
;
869 static const struct elf_reloc_map riscv_reloc_map
[] =
871 { BFD_RELOC_NONE
, R_RISCV_NONE
},
872 { BFD_RELOC_32
, R_RISCV_32
},
873 { BFD_RELOC_64
, R_RISCV_64
},
874 { BFD_RELOC_RISCV_ADD8
, R_RISCV_ADD8
},
875 { BFD_RELOC_RISCV_ADD16
, R_RISCV_ADD16
},
876 { BFD_RELOC_RISCV_ADD32
, R_RISCV_ADD32
},
877 { BFD_RELOC_RISCV_ADD64
, R_RISCV_ADD64
},
878 { BFD_RELOC_RISCV_SUB8
, R_RISCV_SUB8
},
879 { BFD_RELOC_RISCV_SUB16
, R_RISCV_SUB16
},
880 { BFD_RELOC_RISCV_SUB32
, R_RISCV_SUB32
},
881 { BFD_RELOC_RISCV_SUB64
, R_RISCV_SUB64
},
882 { BFD_RELOC_CTOR
, R_RISCV_64
},
883 { BFD_RELOC_12_PCREL
, R_RISCV_BRANCH
},
884 { BFD_RELOC_RISCV_HI20
, R_RISCV_HI20
},
885 { BFD_RELOC_RISCV_LO12_I
, R_RISCV_LO12_I
},
886 { BFD_RELOC_RISCV_LO12_S
, R_RISCV_LO12_S
},
887 { BFD_RELOC_RISCV_PCREL_LO12_I
, R_RISCV_PCREL_LO12_I
},
888 { BFD_RELOC_RISCV_PCREL_LO12_S
, R_RISCV_PCREL_LO12_S
},
889 { BFD_RELOC_RISCV_CALL
, R_RISCV_CALL
},
890 { BFD_RELOC_RISCV_CALL_PLT
, R_RISCV_CALL_PLT
},
891 { BFD_RELOC_RISCV_PCREL_HI20
, R_RISCV_PCREL_HI20
},
892 { BFD_RELOC_RISCV_JMP
, R_RISCV_JAL
},
893 { BFD_RELOC_RISCV_GOT_HI20
, R_RISCV_GOT_HI20
},
894 { BFD_RELOC_RISCV_TLS_DTPMOD32
, R_RISCV_TLS_DTPMOD32
},
895 { BFD_RELOC_RISCV_TLS_DTPREL32
, R_RISCV_TLS_DTPREL32
},
896 { BFD_RELOC_RISCV_TLS_DTPMOD64
, R_RISCV_TLS_DTPMOD64
},
897 { BFD_RELOC_RISCV_TLS_DTPREL64
, R_RISCV_TLS_DTPREL64
},
898 { BFD_RELOC_RISCV_TLS_TPREL32
, R_RISCV_TLS_TPREL32
},
899 { BFD_RELOC_RISCV_TLS_TPREL64
, R_RISCV_TLS_TPREL64
},
900 { BFD_RELOC_RISCV_TPREL_HI20
, R_RISCV_TPREL_HI20
},
901 { BFD_RELOC_RISCV_TPREL_ADD
, R_RISCV_TPREL_ADD
},
902 { BFD_RELOC_RISCV_TPREL_LO12_S
, R_RISCV_TPREL_LO12_S
},
903 { BFD_RELOC_RISCV_TPREL_LO12_I
, R_RISCV_TPREL_LO12_I
},
904 { BFD_RELOC_RISCV_TLS_GOT_HI20
, R_RISCV_TLS_GOT_HI20
},
905 { BFD_RELOC_RISCV_TLS_GD_HI20
, R_RISCV_TLS_GD_HI20
},
906 { BFD_RELOC_RISCV_ALIGN
, R_RISCV_ALIGN
},
907 { BFD_RELOC_RISCV_RVC_BRANCH
, R_RISCV_RVC_BRANCH
},
908 { BFD_RELOC_RISCV_RVC_JUMP
, R_RISCV_RVC_JUMP
},
909 { BFD_RELOC_RISCV_RVC_LUI
, R_RISCV_RVC_LUI
},
910 { BFD_RELOC_RISCV_GPREL_I
, R_RISCV_GPREL_I
},
911 { BFD_RELOC_RISCV_GPREL_S
, R_RISCV_GPREL_S
},
912 { BFD_RELOC_RISCV_TPREL_I
, R_RISCV_TPREL_I
},
913 { BFD_RELOC_RISCV_TPREL_S
, R_RISCV_TPREL_S
},
914 { BFD_RELOC_RISCV_RELAX
, R_RISCV_RELAX
},
915 { BFD_RELOC_RISCV_SUB6
, R_RISCV_SUB6
},
916 { BFD_RELOC_RISCV_SET6
, R_RISCV_SET6
},
917 { BFD_RELOC_RISCV_SET8
, R_RISCV_SET8
},
918 { BFD_RELOC_RISCV_SET16
, R_RISCV_SET16
},
919 { BFD_RELOC_RISCV_SET32
, R_RISCV_SET32
},
920 { BFD_RELOC_RISCV_32_PCREL
, R_RISCV_32_PCREL
},
923 /* Given a BFD reloc type, return a howto structure. */
926 riscv_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
927 bfd_reloc_code_real_type code
)
931 for (i
= 0; i
< ARRAY_SIZE (riscv_reloc_map
); i
++)
932 if (riscv_reloc_map
[i
].bfd_val
== code
)
933 return &howto_table
[(int) riscv_reloc_map
[i
].elf_val
];
935 bfd_set_error (bfd_error_bad_value
);
940 riscv_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
944 for (i
= 0; i
< ARRAY_SIZE (howto_table
); i
++)
945 if (howto_table
[i
].name
&& strcasecmp (howto_table
[i
].name
, r_name
) == 0)
946 return &howto_table
[i
];
952 riscv_elf_rtype_to_howto (bfd
*abfd
, unsigned int r_type
)
954 if (r_type
>= ARRAY_SIZE (howto_table
))
956 (*_bfd_error_handler
) (_("%pB: unsupported relocation type %#x"),
958 bfd_set_error (bfd_error_bad_value
);
961 return &howto_table
[r_type
];
964 /* Special_function of RISCV_ADD and RISCV_SUB relocations. */
966 static bfd_reloc_status_type
967 riscv_elf_add_sub_reloc (bfd
*abfd
,
968 arelent
*reloc_entry
,
971 asection
*input_section
,
973 char **error_message ATTRIBUTE_UNUSED
)
975 reloc_howto_type
*howto
= reloc_entry
->howto
;
978 if (output_bfd
!= NULL
979 && (symbol
->flags
& BSF_SECTION_SYM
) == 0
980 && (!reloc_entry
->howto
->partial_inplace
|| reloc_entry
->addend
== 0))
982 reloc_entry
->address
+= input_section
->output_offset
;
986 if (output_bfd
!= NULL
)
987 return bfd_reloc_continue
;
989 relocation
= symbol
->value
+ symbol
->section
->output_section
->vma
990 + symbol
->section
->output_offset
+ reloc_entry
->addend
;
991 bfd_vma old_value
= bfd_get (howto
->bitsize
, abfd
,
992 data
+ reloc_entry
->address
);
1000 relocation
= old_value
+ relocation
;
1007 relocation
= old_value
- relocation
;
1010 bfd_put (howto
->bitsize
, abfd
, relocation
, data
+ reloc_entry
->address
);
1012 return bfd_reloc_ok
;
1015 /* Parsing subset version.
1018 Points to the end of version
1021 `rps`: Hooks and status for parsing subset.
1022 `march`: Full arch string.
1023 `p`: Curent parsing position.
1024 `major_version`: Parsing result of major version, using
1025 default_major_version if version is not present in arch string.
1026 `minor_version`: Parsing result of minor version, set to 0 if version is
1027 not present in arch string, but set to `default_minor_version` if
1028 `major_version` using default_major_version.
1029 `default_major_version`: Default major version.
1030 `default_minor_version`: Default minor version.
1031 `std_ext_p`: True if parsing std extension. */
1034 riscv_parsing_subset_version (riscv_parse_subset_t
*rps
,
1037 unsigned *major_version
,
1038 unsigned *minor_version
,
1039 unsigned default_major_version
,
1040 unsigned default_minor_version
,
1041 bfd_boolean std_ext_p
)
1043 bfd_boolean major_p
= TRUE
;
1044 unsigned version
= 0;
1057 /* Might be beginning of `p` extension. */
1060 *major_version
= version
;
1066 rps
->error_handler ("-march=%s: Expect number after `%dp'.",
1076 else if (ISDIGIT (*p
))
1077 version
= (version
* 10) + (*p
- '0');
1087 if (major
== 0 && minor
== 0)
1089 /* We don't found any version string, use default version. */
1090 *major_version
= default_major_version
;
1091 *minor_version
= default_minor_version
;
1095 *major_version
= major
;
1096 *minor_version
= minor
;
1101 /* Return string which contain all supported standard extensions in
1105 riscv_supported_std_ext (void)
1107 return "mafdqlcbjtpvn";
1110 /* Parsing function for standard extensions.
1113 Points to the end of extensions.
1116 `rps`: Hooks and status for parsing subset.
1117 `march`: Full arch string.
1118 `p`: Curent parsing position. */
1121 riscv_parse_std_ext (riscv_parse_subset_t
*rps
,
1122 const char *march
, const char *p
)
1124 const char *all_std_exts
= riscv_supported_std_ext ();
1125 const char *std_exts
= all_std_exts
;
1127 unsigned major_version
= 0;
1128 unsigned minor_version
= 0;
1129 char std_ext
= '\0';
1131 /* First letter must start with i, e or g. */
1136 p
= riscv_parsing_subset_version (
1139 p
, &major_version
, &minor_version
,
1140 /* default_major_version= */ 2,
1141 /* default_minor_version= */ 0,
1142 /* std_ext_p= */TRUE
);
1143 riscv_add_subset (rps
->subset_list
, "i", major_version
, minor_version
);
1148 p
= riscv_parsing_subset_version (
1151 p
, &major_version
, &minor_version
,
1152 /* default_major_version= */ 1,
1153 /* default_minor_version= */ 9,
1154 /* std_ext_p= */TRUE
);
1156 riscv_add_subset (rps
->subset_list
, "e", major_version
, minor_version
);
1157 riscv_add_subset (rps
->subset_list
, "i", 2, 0);
1159 if (*rps
->xlen
> 32)
1161 rps
->error_handler ("-march=%s: rv%de is not a valid base ISA",
1170 p
= riscv_parsing_subset_version (
1173 p
, &major_version
, &minor_version
,
1174 /* default_major_version= */ 2,
1175 /* default_minor_version= */ 0,
1176 /* std_ext_p= */TRUE
);
1177 riscv_add_subset (rps
->subset_list
, "i", major_version
, minor_version
);
1179 for ( ; *std_exts
!= 'q'; std_exts
++)
1181 const char subset
[] = {*std_exts
, '\0'};
1183 rps
->subset_list
, subset
, major_version
, minor_version
);
1188 rps
->error_handler (
1189 "-march=%s: first ISA subset must be `e', `i' or `g'", march
);
1195 char subset
[2] = {0, 0};
1197 if (*p
== 'x' || *p
== 's')
1208 /* Checking canonical order. */
1209 while (*std_exts
&& std_ext
!= *std_exts
) std_exts
++;
1211 if (std_ext
!= *std_exts
)
1213 if (strchr (all_std_exts
, std_ext
) == NULL
)
1214 rps
->error_handler (
1215 "-march=%s: unsupported ISA subset `%c'", march
, *p
);
1217 rps
->error_handler (
1218 "-march=%s: ISA string is not in canonical order. `%c'",
1226 p
= riscv_parsing_subset_version (
1229 p
, &major_version
, &minor_version
,
1230 /* default_major_version= */ 2,
1231 /* default_minor_version= */ 0,
1232 /* std_ext_p= */TRUE
);
1234 subset
[0] = std_ext
;
1236 riscv_add_subset (rps
->subset_list
, subset
, major_version
, minor_version
);
1241 /* Parsing function for non-standard and supervisor extensions.
1244 Points to the end of extensions.
1247 `rps`: Hooks and status for parsing subset.
1248 `march`: Full arch string.
1249 `p`: Curent parsing position.
1250 `ext_type`: What kind of extensions, 'x', 's' or 'sx'.
1251 `ext_type_str`: Full name for kind of extension. */
1254 riscv_parse_sv_or_non_std_ext (riscv_parse_subset_t
*rps
,
1257 const char *ext_type
,
1258 const char *ext_type_str
)
1260 unsigned major_version
= 0;
1261 unsigned minor_version
= 0;
1262 size_t ext_type_len
= strlen (ext_type
);
1272 if (strncmp (p
, ext_type
, ext_type_len
) != 0)
1275 /* It's non-standard supervisor extension if it prefix with sx. */
1276 if ((ext_type
[0] == 's') && (ext_type_len
== 1)
1277 && (*(p
+ 1) == 'x'))
1280 char *subset
= xstrdup (p
);
1282 const char *end_of_version
;
1284 while (*++q
!= '\0' && *q
!= '_' && !ISDIGIT (*q
))
1288 riscv_parsing_subset_version (
1291 q
, &major_version
, &minor_version
,
1292 /* default_major_version= */ 2,
1293 /* default_minor_version= */ 0,
1294 /* std_ext_p= */FALSE
);
1298 riscv_add_subset (rps
->subset_list
, subset
, major_version
, minor_version
);
1300 p
+= end_of_version
- subset
;
1302 if (*p
!= '\0' && *p
!= '_')
1304 rps
->error_handler ("-march=%s: %s must seperate with _",
1305 march
, ext_type_str
);
1313 /* Function for parsing arch string.
1316 Return TRUE on success.
1319 `rps`: Hooks and status for parsing subset.
1320 `arch`: Arch string. */
1323 riscv_parse_subset (riscv_parse_subset_t
*rps
,
1326 const char *p
= arch
;
1328 if (strncmp (p
, "rv32", 4) == 0)
1333 else if (strncmp (p
, "rv64", 4) == 0)
1340 rps
->error_handler ("-march=%s: ISA string must begin with rv32 or rv64",
1345 /* Parsing standard extension. */
1346 p
= riscv_parse_std_ext (rps
, arch
, p
);
1351 /* Parsing non-standard extension. */
1352 p
= riscv_parse_sv_or_non_std_ext (
1353 rps
, arch
, p
, "x", "non-standard extension");
1358 /* Parsing supervisor extension. */
1359 p
= riscv_parse_sv_or_non_std_ext (
1360 rps
, arch
, p
, "s", "supervisor extension");
1365 /* Parsing non-standard supervisor extension. */
1366 p
= riscv_parse_sv_or_non_std_ext (
1367 rps
, arch
, p
, "sx", "non-standard supervisor extension");
1374 rps
->error_handler ("-march=%s: unexpected ISA string at end: %s",
1379 if (riscv_lookup_subset (rps
->subset_list
, "e")
1380 && riscv_lookup_subset (rps
->subset_list
, "f"))
1382 rps
->error_handler ("-march=%s: rv32e does not support the `f' extension",
1387 if (riscv_lookup_subset (rps
->subset_list
, "d")
1388 && !riscv_lookup_subset (rps
->subset_list
, "f"))
1390 rps
->error_handler ("-march=%s: `d' extension requires `f' extension",
1395 if (riscv_lookup_subset (rps
->subset_list
, "q")
1396 && !riscv_lookup_subset (rps
->subset_list
, "d"))
1398 rps
->error_handler ("-march=%s: `q' extension requires `d' extension",
1403 if (riscv_lookup_subset (rps
->subset_list
, "q") && *rps
->xlen
< 64)
1405 rps
->error_handler ("-march=%s: rv32 does not support the `q' extension",
1412 /* Add new subset to list. */
1415 riscv_add_subset (riscv_subset_list_t
*subset_list
,
1417 int major
, int minor
)
1419 riscv_subset_t
*s
= xmalloc (sizeof *s
);
1421 if (subset_list
->head
== NULL
)
1422 subset_list
->head
= s
;
1424 s
->name
= xstrdup (subset
);
1425 s
->major_version
= major
;
1426 s
->minor_version
= minor
;
1429 if (subset_list
->tail
!= NULL
)
1430 subset_list
->tail
->next
= s
;
1432 subset_list
->tail
= s
;
1435 /* Find subset in list without version checking, return NULL if not found. */
1438 riscv_lookup_subset (const riscv_subset_list_t
*subset_list
,
1441 return riscv_lookup_subset_version (
1442 subset_list
, subset
,
1443 RISCV_DONT_CARE_VERSION
,
1444 RISCV_DONT_CARE_VERSION
);
1447 /* Find subset in list with version checking, return NULL if not found. */
1450 riscv_lookup_subset_version (const riscv_subset_list_t
*subset_list
,
1452 int major
, int minor
)
1456 for (s
= subset_list
->head
; s
!= NULL
; s
= s
->next
)
1457 if (strcasecmp (s
->name
, subset
) == 0)
1459 if ((major
!= RISCV_DONT_CARE_VERSION
)
1460 && (s
->major_version
!= major
))
1463 if ((minor
!= RISCV_DONT_CARE_VERSION
)
1464 && (s
->minor_version
!= minor
))
1473 /* Release subset list. */
1476 riscv_release_subset_list (riscv_subset_list_t
*subset_list
)
1478 while (subset_list
->head
!= NULL
)
1480 riscv_subset_t
*next
= subset_list
->head
->next
;
1481 free ((void *)subset_list
->head
->name
);
1482 free (subset_list
->head
);
1483 subset_list
->head
= next
;
1486 subset_list
->tail
= NULL
;