2016-11-02 00:45:57 +08:00
|
|
|
/* tc-riscv.h -- header file for tc-riscv.c.
|
2024-01-04 19:52:08 +08:00
|
|
|
Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
2016-11-02 00:45:57 +08:00
|
|
|
|
|
|
|
Contributed by Andrew Waterman (andrew@sifive.com).
|
|
|
|
Based on MIPS target.
|
|
|
|
|
|
|
|
This file is part of GAS.
|
|
|
|
|
|
|
|
GAS is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
GAS is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; see the file COPYING3. If not,
|
|
|
|
see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#ifndef TC_RISCV
|
|
|
|
#define TC_RISCV
|
|
|
|
|
|
|
|
#include "opcode/riscv.h"
|
|
|
|
|
|
|
|
struct frag;
|
|
|
|
struct expressionS;
|
|
|
|
|
RISC-V: Implement support for big endian targets.
RISC-V instruction/code is always little endian, but data might be
big-endian. Therefore, we can not use the original bfd_get/bfd_put
to get/put the code for big endian targets. Add new riscv_get_insn
and riscv_put_insn to always get/put code as little endian can resolve
the problem. Just remember to update them once we have supported
the 48-bit/128-bit instructions in the future patches.
bfd/
* config.bfd: Added targets riscv64be*-*-*, riscv32be*-*-* and
riscvbe*-*-*. Also added riscv_elf[32|64]_be_vec.
* configure.ac: Handle riscv_elf[32|64]_be_vec.
* configure: Regenerate.
* elfnn-riscv.c: Include <limits.h> and define CHAR_BIT for
riscv_is_insn_reloc.
(riscv_get_insn): RISC-V instructions are always little endian, but
bfd_get may be used for big-endian, so add new riscv_get_insn to handle
the insturctions.
(riscv_put_insn): Likewsie.
(riscv_is_insn_reloc): Check if we are relocaing an instruction.
(perform_relocation): Call riscv_is_insn_reloc to decide if we should
use riscv_[get|put]_insn or bfd_[get|put].
(riscv_zero_pcrel_hi_reloc): Use riscv_[get|put]_insn, bfd_[get|put]l32
or bfd_[get|put]l16 for code.
(riscv_elf_relocate_section): Likewise.
(riscv_elf_finish_dynamic_symbol): Likewise.
(riscv_elf_finish_dynamic_sections): Likewise.
(_bfd_riscv_relax_call): Likewise.
(_bfd_riscv_relax_lui): Likewise.
(_bfd_riscv_relax_align): Likewise.
(_bfd_riscv_relax_pc): Likewise.
(riscv_elf_object_p): Handled for big endian.
(TARGET_BIG_SYM, TARGET_BIG_NAME): Defined.
* targets.c: Add riscv_elf[32|64]_be_vec.
(_bfd_target_vector): Likewise.
gas/
* config/tc-riscv.c (riscv_target_format): Add elf64-bigriscv and
elf32-bigriscv.
(install_insn): Always write instructions as little endian.
(riscv_make_nops): Likewise.
(md_convert_frag_branch): Likewise.
(md_number_to_chars): Write data in target endianness.
(options, md_longopts): Add -mbig-endian and -mlittle-endian options.
(md_parse_option): Handle the endian options.
* config/tc-riscv.h: Only define TARGET_BYTES_BIG_ENDIAN if not
already defined.
* configure.tgt: Added riscv64be*, riscv32be*, riscvbe*.
ld/
* configure.tgt: Added riscvbe-*-*, riscv32be*-*-*, riscv64be*-*-*,
riscv32be*-*-linux*, and riscv64be*-*-linux*.
* Makefile.am: Added eelf32briscv.c, eelf32briscv_ilp32f.c and
eelf32briscv_ilp32.c.
* Makefile.in: Regenerate.
* emulparams/elf32briscv.sh: Added.
* emulparams/elf32briscv_ilp32.sh: Likewise.
* emulparams/elf32briscv_ilp32f.sh: Likewise.
* emulparams/elf64briscv.sh: Likewise.
* emulparams/elf64briscv_lp64.sh: Likewise.
* emulparams/elf64briscv_lp64f.sh: Likewise.
2021-01-06 05:50:32 +08:00
|
|
|
#ifndef TARGET_BYTES_BIG_ENDIAN
|
2016-11-02 00:45:57 +08:00
|
|
|
#define TARGET_BYTES_BIG_ENDIAN 0
|
RISC-V: Implement support for big endian targets.
RISC-V instruction/code is always little endian, but data might be
big-endian. Therefore, we can not use the original bfd_get/bfd_put
to get/put the code for big endian targets. Add new riscv_get_insn
and riscv_put_insn to always get/put code as little endian can resolve
the problem. Just remember to update them once we have supported
the 48-bit/128-bit instructions in the future patches.
bfd/
* config.bfd: Added targets riscv64be*-*-*, riscv32be*-*-* and
riscvbe*-*-*. Also added riscv_elf[32|64]_be_vec.
* configure.ac: Handle riscv_elf[32|64]_be_vec.
* configure: Regenerate.
* elfnn-riscv.c: Include <limits.h> and define CHAR_BIT for
riscv_is_insn_reloc.
(riscv_get_insn): RISC-V instructions are always little endian, but
bfd_get may be used for big-endian, so add new riscv_get_insn to handle
the insturctions.
(riscv_put_insn): Likewsie.
(riscv_is_insn_reloc): Check if we are relocaing an instruction.
(perform_relocation): Call riscv_is_insn_reloc to decide if we should
use riscv_[get|put]_insn or bfd_[get|put].
(riscv_zero_pcrel_hi_reloc): Use riscv_[get|put]_insn, bfd_[get|put]l32
or bfd_[get|put]l16 for code.
(riscv_elf_relocate_section): Likewise.
(riscv_elf_finish_dynamic_symbol): Likewise.
(riscv_elf_finish_dynamic_sections): Likewise.
(_bfd_riscv_relax_call): Likewise.
(_bfd_riscv_relax_lui): Likewise.
(_bfd_riscv_relax_align): Likewise.
(_bfd_riscv_relax_pc): Likewise.
(riscv_elf_object_p): Handled for big endian.
(TARGET_BIG_SYM, TARGET_BIG_NAME): Defined.
* targets.c: Add riscv_elf[32|64]_be_vec.
(_bfd_target_vector): Likewise.
gas/
* config/tc-riscv.c (riscv_target_format): Add elf64-bigriscv and
elf32-bigriscv.
(install_insn): Always write instructions as little endian.
(riscv_make_nops): Likewise.
(md_convert_frag_branch): Likewise.
(md_number_to_chars): Write data in target endianness.
(options, md_longopts): Add -mbig-endian and -mlittle-endian options.
(md_parse_option): Handle the endian options.
* config/tc-riscv.h: Only define TARGET_BYTES_BIG_ENDIAN if not
already defined.
* configure.tgt: Added riscv64be*, riscv32be*, riscvbe*.
ld/
* configure.tgt: Added riscvbe-*-*, riscv32be*-*-*, riscv64be*-*-*,
riscv32be*-*-linux*, and riscv64be*-*-linux*.
* Makefile.am: Added eelf32briscv.c, eelf32briscv_ilp32f.c and
eelf32briscv_ilp32.c.
* Makefile.in: Regenerate.
* emulparams/elf32briscv.sh: Added.
* emulparams/elf32briscv_ilp32.sh: Likewise.
* emulparams/elf32briscv_ilp32f.sh: Likewise.
* emulparams/elf64briscv.sh: Likewise.
* emulparams/elf64briscv_lp64.sh: Likewise.
* emulparams/elf64briscv_lp64f.sh: Likewise.
2021-01-06 05:50:32 +08:00
|
|
|
#endif
|
2016-11-02 00:45:57 +08:00
|
|
|
|
|
|
|
#define TARGET_ARCH bfd_arch_riscv
|
|
|
|
|
|
|
|
#define WORKING_DOT_WORD 1
|
|
|
|
#define LOCAL_LABELS_FB 1
|
|
|
|
|
|
|
|
/* Symbols named FAKE_LABEL_NAME are emitted when generating DWARF, so make
|
|
|
|
sure FAKE_LABEL_NAME is printable. It still must be distinct from any
|
|
|
|
real label name. So, append a space, which other labels can't contain. */
|
opcodes/riscv: Hide '.L0 ' fake symbols
The RISC-V assembler generates fake labels with the name '.L0 ' as
part of the debug information (see
gas/config/tc-riscv.h:FAKE_LABEL_NAME).
The problem is that currently, when disassembling an object file, the
output looks like this (this is an example from the GDB testsuite, but
is pretty representative of anything with debug information):
000000000000001e <main>:
1e: 7179 addi sp,sp,-48
20: f406 sd ra,40(sp)
22: f022 sd s0,32(sp)
24: 1800 addi s0,sp,48
0000000000000026 <.L0 >:
26: 87aa mv a5,a0
28: feb43023 sd a1,-32(s0)
2c: fcc43c23 sd a2,-40(s0)
30: fef42623 sw a5,-20(s0)
0000000000000034 <.L0 >:
34: fec42783 lw a5,-20(s0)
38: 0007871b sext.w a4,a5
3c: 678d lui a5,0x3
3e: 03978793 addi a5,a5,57 # 3039 <.LASF30+0x2a9d>
42: 02f71463 bne a4,a5,6a <.L0 >
0000000000000046 <.L0 >:
46: 000007b7 lui a5,0x0
4a: 0007b783 ld a5,0(a5) # 0 <need_malloc>
4e: 6f9c ld a5,24(a5)
0000000000000050 <.L0 >:
50: 86be mv a3,a5
52: 466d li a2,27
54: 4585 li a1,1
56: 000007b7 lui a5,0x0
5a: 00078513 mv a0,a5
5e: 00000097 auipc ra,0x0
62: 000080e7 jalr ra # 5e <.L0 +0xe>
0000000000000066 <.L0 >:
66: 4785 li a5,1
68: a869 j 102 <.L0 >
000000000000006a <.L0 >:
6a: 000007b7 lui a5,0x0
6e: 00078513 mv a0,a5
72: 00000097 auipc ra,0x0
76: 000080e7 jalr ra # 72 <.L0 +0x8>
The frequent repeated '.L0 ' labels are pointless, as they are
non-unique there's no way to match a use of '.L0 ' to its appearence
in the output, so we'd be better off just not printing it at all.
That's what this patch does by defining a 'symbol_is_valid' method for
RISC-V. With this commit, the same disassembly now looks like this:
000000000000001e <main>:
1e: 7179 addi sp,sp,-48
20: f406 sd ra,40(sp)
22: f022 sd s0,32(sp)
24: 1800 addi s0,sp,48
26: 87aa mv a5,a0
28: feb43023 sd a1,-32(s0)
2c: fcc43c23 sd a2,-40(s0)
30: fef42623 sw a5,-20(s0)
34: fec42783 lw a5,-20(s0)
38: 0007871b sext.w a4,a5
3c: 678d lui a5,0x3
3e: 03978793 addi a5,a5,57 # 3039 <.LASF30+0x2a9d>
42: 02f71463 bne a4,a5,6a <.L4>
46: 000007b7 lui a5,0x0
4a: 0007b783 ld a5,0(a5) # 0 <need_malloc>
4e: 6f9c ld a5,24(a5)
50: 86be mv a3,a5
52: 466d li a2,27
54: 4585 li a1,1
56: 000007b7 lui a5,0x0
5a: 00078513 mv a0,a5
5e: 00000097 auipc ra,0x0
62: 000080e7 jalr ra # 5e <main+0x40>
66: 4785 li a5,1
68: a869 j 102 <.L5>
000000000000006a <.L4>:
6a: 000007b7 lui a5,0x0
6e: 00078513 mv a0,a5
72: 00000097 auipc ra,0x0
76: 000080e7 jalr ra # 72 <.L4+0x8>
In order to share the fake label between the assembler and the
libopcodes library, I've added some new defines RISCV_FAKE_LABEL_NAME
and RISCV_FAKE_LABEL_CHAR in include/opcode/riscv.h. I could have
just moved FAKE_LABEL_NAME to the include file, however, I thnk this
would be confusing, someone working on the assembler would likely not
expect to find FAKE_LABEL_NAME defined outside of the assembler source
tree. By introducing the RISCV_FAKE_LABEL_* defines I can leave the
assembler standard FAKE_LABEL_ defines in the assembler source, but
still share the RISCV_FAKE_LABEL_* with libopcodes.
gas/ChangeLog:
* config/tc-riscv.h (FAKE_LABEL_NAME): Define as
RISCV_FAKE_LABEL_NAME.
(FAKE_LABEL_CHAR): Define as RISCV_FAKE_LABEL_CHAR.
include/ChangeLog:
* dis-asm.h (riscv_symbol_is_valid): Declare.
* opcode/riscv.h (RISCV_FAKE_LABEL_NAME): Define.
(RISCV_FAKE_LABEL_CHAR): Define.
opcodes/ChangeLog:
* disassembler.c (disassemble_init_for_target): Add RISC-V
initialisation.
* riscv-dis.c (riscv_symbol_is_valid): New function.
2018-12-03 22:46:18 +08:00
|
|
|
#define FAKE_LABEL_NAME RISCV_FAKE_LABEL_NAME
|
2017-11-23 03:20:48 +08:00
|
|
|
/* Changing the special character in FAKE_LABEL_NAME requires changing
|
|
|
|
FAKE_LABEL_CHAR too. */
|
opcodes/riscv: Hide '.L0 ' fake symbols
The RISC-V assembler generates fake labels with the name '.L0 ' as
part of the debug information (see
gas/config/tc-riscv.h:FAKE_LABEL_NAME).
The problem is that currently, when disassembling an object file, the
output looks like this (this is an example from the GDB testsuite, but
is pretty representative of anything with debug information):
000000000000001e <main>:
1e: 7179 addi sp,sp,-48
20: f406 sd ra,40(sp)
22: f022 sd s0,32(sp)
24: 1800 addi s0,sp,48
0000000000000026 <.L0 >:
26: 87aa mv a5,a0
28: feb43023 sd a1,-32(s0)
2c: fcc43c23 sd a2,-40(s0)
30: fef42623 sw a5,-20(s0)
0000000000000034 <.L0 >:
34: fec42783 lw a5,-20(s0)
38: 0007871b sext.w a4,a5
3c: 678d lui a5,0x3
3e: 03978793 addi a5,a5,57 # 3039 <.LASF30+0x2a9d>
42: 02f71463 bne a4,a5,6a <.L0 >
0000000000000046 <.L0 >:
46: 000007b7 lui a5,0x0
4a: 0007b783 ld a5,0(a5) # 0 <need_malloc>
4e: 6f9c ld a5,24(a5)
0000000000000050 <.L0 >:
50: 86be mv a3,a5
52: 466d li a2,27
54: 4585 li a1,1
56: 000007b7 lui a5,0x0
5a: 00078513 mv a0,a5
5e: 00000097 auipc ra,0x0
62: 000080e7 jalr ra # 5e <.L0 +0xe>
0000000000000066 <.L0 >:
66: 4785 li a5,1
68: a869 j 102 <.L0 >
000000000000006a <.L0 >:
6a: 000007b7 lui a5,0x0
6e: 00078513 mv a0,a5
72: 00000097 auipc ra,0x0
76: 000080e7 jalr ra # 72 <.L0 +0x8>
The frequent repeated '.L0 ' labels are pointless, as they are
non-unique there's no way to match a use of '.L0 ' to its appearence
in the output, so we'd be better off just not printing it at all.
That's what this patch does by defining a 'symbol_is_valid' method for
RISC-V. With this commit, the same disassembly now looks like this:
000000000000001e <main>:
1e: 7179 addi sp,sp,-48
20: f406 sd ra,40(sp)
22: f022 sd s0,32(sp)
24: 1800 addi s0,sp,48
26: 87aa mv a5,a0
28: feb43023 sd a1,-32(s0)
2c: fcc43c23 sd a2,-40(s0)
30: fef42623 sw a5,-20(s0)
34: fec42783 lw a5,-20(s0)
38: 0007871b sext.w a4,a5
3c: 678d lui a5,0x3
3e: 03978793 addi a5,a5,57 # 3039 <.LASF30+0x2a9d>
42: 02f71463 bne a4,a5,6a <.L4>
46: 000007b7 lui a5,0x0
4a: 0007b783 ld a5,0(a5) # 0 <need_malloc>
4e: 6f9c ld a5,24(a5)
50: 86be mv a3,a5
52: 466d li a2,27
54: 4585 li a1,1
56: 000007b7 lui a5,0x0
5a: 00078513 mv a0,a5
5e: 00000097 auipc ra,0x0
62: 000080e7 jalr ra # 5e <main+0x40>
66: 4785 li a5,1
68: a869 j 102 <.L5>
000000000000006a <.L4>:
6a: 000007b7 lui a5,0x0
6e: 00078513 mv a0,a5
72: 00000097 auipc ra,0x0
76: 000080e7 jalr ra # 72 <.L4+0x8>
In order to share the fake label between the assembler and the
libopcodes library, I've added some new defines RISCV_FAKE_LABEL_NAME
and RISCV_FAKE_LABEL_CHAR in include/opcode/riscv.h. I could have
just moved FAKE_LABEL_NAME to the include file, however, I thnk this
would be confusing, someone working on the assembler would likely not
expect to find FAKE_LABEL_NAME defined outside of the assembler source
tree. By introducing the RISCV_FAKE_LABEL_* defines I can leave the
assembler standard FAKE_LABEL_ defines in the assembler source, but
still share the RISCV_FAKE_LABEL_* with libopcodes.
gas/ChangeLog:
* config/tc-riscv.h (FAKE_LABEL_NAME): Define as
RISCV_FAKE_LABEL_NAME.
(FAKE_LABEL_CHAR): Define as RISCV_FAKE_LABEL_CHAR.
include/ChangeLog:
* dis-asm.h (riscv_symbol_is_valid): Declare.
* opcode/riscv.h (RISCV_FAKE_LABEL_NAME): Define.
(RISCV_FAKE_LABEL_CHAR): Define.
opcodes/ChangeLog:
* disassembler.c (disassemble_init_for_target): Add RISC-V
initialisation.
* riscv-dis.c (riscv_symbol_is_valid): New function.
2018-12-03 22:46:18 +08:00
|
|
|
#define FAKE_LABEL_CHAR RISCV_FAKE_LABEL_CHAR
|
2016-11-02 00:45:57 +08:00
|
|
|
|
|
|
|
#define md_relax_frag(segment, fragp, stretch) \
|
|
|
|
riscv_relax_frag (segment, fragp, stretch)
|
|
|
|
extern int riscv_relax_frag (asection *, struct frag *, long);
|
|
|
|
|
|
|
|
#define md_section_align(seg,size) (size)
|
|
|
|
#define md_undefined_symbol(name) (0)
|
|
|
|
#define md_operand(x)
|
|
|
|
|
Use bool in gas
* as.h (POISON_BFD_BOOLEAN): Define.
* as.c, * as.h, * atof-generic.c, * config/atof-ieee.c,
* config/bfin-aux.h, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-elf.h, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arc.h, * config/tc-arm.c, * config/tc-arm.h,
* config/tc-avr.c, * config/tc-avr.h, * config/tc-bfin.c,
* config/tc-bfin.h, * config/tc-bpf.c, * config/tc-cris.c,
* config/tc-csky.c, * config/tc-csky.h, * config/tc-d10v.c,
* config/tc-d10v.h, * config/tc-d30v.c, * config/tc-d30v.h,
* config/tc-dlx.c, * config/tc-dlx.h, * config/tc-epiphany.c,
* config/tc-epiphany.h, * config/tc-fr30.c, * config/tc-fr30.h,
* config/tc-frv.c, * config/tc-frv.h, * config/tc-ft32.c,
* config/tc-ft32.h, * config/tc-h8300.c, * config/tc-hppa.c,
* config/tc-i386-intel.c, * config/tc-i386.c, * config/tc-ia64.c,
* config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-iq2000.h,
* config/tc-lm32.c, * config/tc-lm32.h, * config/tc-m32c.c,
* config/tc-m32c.h, * config/tc-m32r.c, * config/tc-m32r.h,
* config/tc-m68hc11.c, * config/tc-m68k.c, * config/tc-mcore.c,
* config/tc-mcore.h, * config/tc-mep.c, * config/tc-mep.h,
* config/tc-metag.c, * config/tc-metag.h,
* config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c,
* config/tc-mn10300.h, * config/tc-moxie.c, * config/tc-msp430.c,
* config/tc-msp430.h, * config/tc-mt.c, * config/tc-mt.h,
* config/tc-nds32.c, * config/tc-nds32.h, * config/tc-nios2.c,
* config/tc-ns32k.c, * config/tc-or1k.c, * config/tc-or1k.h,
* config/tc-pdp11.c, * config/tc-ppc.c, * config/tc-pru.c,
* config/tc-pru.h, * config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-rx.c, * config/tc-rx.h, * config/tc-s12z.c,
* config/tc-s12z.h, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score.h, * config/tc-score7.c, * config/tc-sh.c,
* config/tc-sh.h, * config/tc-spu.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tic6x.h, * config/tc-tilegx.c,
* config/tc-tilepro.c, * config/tc-v850.c, * config/tc-v850.h,
* config/tc-visium.c, * config/tc-visium.h, * config/tc-wasm32.c,
* config/tc-wasm32.h, * config/tc-xc16x.c, * config/tc-xgate.c,
* config/tc-xstormy16.c, * config/tc-xstormy16.h,
* config/tc-xtensa.c, * config/tc-xtensa.h, * config/tc-z80.c,
* config/tc-z8k.c, * config/xtensa-istack.h,
* config/xtensa-relax.c, * config/xtensa-relax.h, * dw2gencfi.c,
* dwarf2dbg.c, * dwarf2dbg.h, * expr.c, * expr.h, * frags.c,
* frags.h, * listing.c, * macro.c, * output-file.c, * read.c,
* read.h, * stabs.c, * symbols.c, * write.c: Replace bfd_boolean
with bool, FALSE with false, and TRUE with true.
2021-03-31 08:12:05 +08:00
|
|
|
extern bool riscv_frag_align_code (int);
|
2016-12-19 14:53:51 +08:00
|
|
|
#define md_do_align(N, FILL, LEN, MAX, LABEL) \
|
|
|
|
if ((N) != 0 && !(FILL) && !need_pass_2 && subseg_text_p (now_seg)) \
|
|
|
|
{ \
|
|
|
|
if (riscv_frag_align_code (N)) \
|
|
|
|
goto LABEL; \
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void riscv_handle_align (fragS *);
|
|
|
|
#define HANDLE_ALIGN riscv_handle_align
|
|
|
|
|
2018-05-25 01:35:59 +08:00
|
|
|
#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
|
2016-11-02 00:45:57 +08:00
|
|
|
|
|
|
|
/* The ISA of the target may change based on command-line arguments. */
|
2021-01-15 09:36:51 +08:00
|
|
|
#define TARGET_FORMAT riscv_target_format ()
|
2016-11-02 00:45:57 +08:00
|
|
|
extern const char * riscv_target_format (void);
|
|
|
|
|
2021-01-15 09:36:51 +08:00
|
|
|
#define md_after_parse_args() riscv_after_parse_args ()
|
2016-11-02 00:45:57 +08:00
|
|
|
extern void riscv_after_parse_args (void);
|
|
|
|
|
|
|
|
#define md_parse_long_option(arg) riscv_parse_long_option (arg)
|
|
|
|
extern int riscv_parse_long_option (const char *);
|
|
|
|
|
2021-01-15 09:36:51 +08:00
|
|
|
#define md_pre_output_hook riscv_pre_output_hook ()
|
2016-12-19 14:53:48 +08:00
|
|
|
extern void riscv_pre_output_hook (void);
|
2021-12-20 22:39:13 +08:00
|
|
|
#define GAS_SORT_RELOCS 1
|
2016-12-19 14:53:48 +08:00
|
|
|
|
RISC-V: Resolve PCREL_HI20/LO12_I/S fixups with local symbols while `-mno-relax'
In the scenario of generating .ko files, the kernel does not relax the .ko
files. However, due to the large amount of relax and local relocation
information, this increases the size of the .ko files. In this patch, it
will finish the fixup of the local relocations while with `-mno-relax' option.
This can reduce the size of the relocation table.
The implemntation is based on the code from bfd/elfnn-riscv.c. We probably
can move the code to bfd/elfxx-riscv.c, so that can reduce duplicate code,
just like what we did for the architecture parser.
Besides, maybe not only pcrel_hi/lo12 relocation with local symbols can be
resolved at assembler time. Other pc-relative relocation, like branch,
may also be able to perform related optimizations.
Passed the gcc/binutils regressions of riscv-gnu-toolchain.
gas/
* config/tc-riscv.c (riscv_pcrel_hi_reloc): New structure. Record all
PC-relative high-part relocation that we have encountered to help us
resolve the corresponding low-part relocation later.
(riscv_pcrel_hi_fixup_hash): The hash table to record pcrel_hi fixups.
(riscv_pcrel_fixup_hash): New function. Likewise.
(riscv_pcrel_fixup_eq): Likewise.
(riscv_record_pcrel_fixup): Likewise.
(md_begin): Init pcrel_hi hash table.
(md_apply_fix): For PCREL_HI20 relocation, do fixup and record
the pcrel_hi relocs, mark as done while with `-mno-relax'. For
PCREL_LO12_I/S relocation, do fixup and mark as done while with
`-mno-relax'.
(riscv_md_end): New function. Free pcrel_hi hash table.
* config/tc-riscv.h (md_end): Define md_end with riscv_md_end.
gas/
* testsuite/gas/riscv/fixup-local*: New tests.
2023-11-29 17:17:22 +08:00
|
|
|
#define md_end riscv_md_end
|
|
|
|
extern void riscv_md_end (void);
|
|
|
|
|
2016-11-02 00:45:57 +08:00
|
|
|
/* Let the linker resolve all the relocs due to relaxation. */
|
|
|
|
#define tc_fix_adjustable(fixp) 0
|
|
|
|
#define md_allow_local_subtract(l,r,s) 0
|
|
|
|
|
|
|
|
/* Values passed to md_apply_fix don't include symbol values. */
|
|
|
|
#define MD_APPLY_SYM_VALUE(FIX) 0
|
|
|
|
|
|
|
|
/* Global syms must not be resolved, to support ELF shared libraries. */
|
|
|
|
#define EXTERN_FORCE_RELOC \
|
|
|
|
(OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
|
|
|
|
|
|
|
/* Postpone text-section label subtraction calculation until linking, since
|
|
|
|
linker relaxations might change the deltas. */
|
2017-05-16 07:13:24 +08:00
|
|
|
#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \
|
|
|
|
(GENERIC_FORCE_RELOCATION_SUB_SAME (FIX, SEG) \
|
|
|
|
|| ((SEG)->flags & SEC_CODE) != 0)
|
2016-11-02 00:45:57 +08:00
|
|
|
#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
|
|
|
|
#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
|
|
|
|
#define TC_FORCE_RELOCATION_LOCAL(FIX) 1
|
|
|
|
#define DIFF_EXPR_OK 1
|
|
|
|
|
RISC-V: Emit R_RISCV_RELAX for the la/lga pseudo instruction
Some psABIs define a relaxation to turn a GOT load into a PC-relative
address materialization. For example, the AArch64's psABI allows
adrp+ldr to be rewritten to nop+adr to eliminate the memory load.
This patch is part of the effort to make such optimization possible
for RISC-V.
For RISC-V, we use the la assembly pseudo instruction to load a symbol
address from the GOT. The pseudo instruction is expanded to auipc+ld.
If the address loaded by the instruction pair is actually a PC-relative
link-time constant, we want the linker to rewrite the instruction pair
with auipc+addi.
We can't rewrite all existing auipc+ld pairs with auipc+addi in the
linker because there might be code that jumps to the middle of the
instruction pair. That should be extremely rare, if ever exists, but
you can at least in theory write a program in assembly that jumps to
the ld instruction of the instruction pair. We need a marker to
identify that an auipc+ld can be safely relaxed (i.e. they are emitted
for la).
This patch is to annotate R_RISCV_GOT_HI20 with R_RISCV_RELAX only
when the relocation is emitted for the la pseudo instruction. The
linker will use it as a signal that the instruction pair can be safely
relaxed.
Proposal to the RISC-V psABI:
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/397
gas/
* config/tc-riscv.c (source_macro): New static int variable.
The identifier of the assembler macro we are expanding, if any.
(append_insn): Updated source_macro to tc_fix_data, to record
which macro expands, if any.
(macro): Record which macro expands into source_macro. Reset
source_macro to -1 at the end.
(md_apply_fix): Apply R_RISCV_RELAX if pcrel_got_hi is expanded
from macro LA/LGA.
* config/tc-riscv.h (struct riscv_fix, TC_FIX_TYPE, TC_INIT_FIX_DATA):
Defined to record source_macro into fixups for riscv target.
* testsuite/gas/riscv/la-variants.d: Updated.
2023-09-20 16:31:26 +08:00
|
|
|
struct riscv_fix
|
|
|
|
{
|
|
|
|
int source_macro;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define TC_FIX_TYPE struct riscv_fix
|
|
|
|
#define TC_INIT_FIX_DATA(FIX) (FIX)->tc_fix_data.source_macro = -1
|
|
|
|
|
2016-11-02 00:45:57 +08:00
|
|
|
extern void riscv_pop_insert (void);
|
|
|
|
#define md_pop_insert() riscv_pop_insert ()
|
|
|
|
|
|
|
|
#define TARGET_USE_CFIPOP 1
|
|
|
|
|
|
|
|
#define tc_cfi_frame_initial_instructions riscv_cfi_frame_initial_instructions
|
|
|
|
extern void riscv_cfi_frame_initial_instructions (void);
|
|
|
|
|
|
|
|
#define tc_regname_to_dw2regnum tc_riscv_regname_to_dw2regnum
|
|
|
|
extern int tc_riscv_regname_to_dw2regnum (char *);
|
|
|
|
|
|
|
|
#define DWARF2_DEFAULT_RETURN_COLUMN X_RA
|
2016-12-19 14:53:48 +08:00
|
|
|
|
|
|
|
/* Even on RV64, use 4-byte alignment, as F registers may be only 32 bits. */
|
|
|
|
#define DWARF2_CIE_DATA_ALIGNMENT -4
|
2016-11-02 00:45:57 +08:00
|
|
|
|
|
|
|
#define elf_tc_final_processing riscv_elf_final_processing
|
|
|
|
extern void riscv_elf_final_processing (void);
|
|
|
|
|
2017-03-02 14:54:32 +08:00
|
|
|
/* Adjust debug_line after relaxation. */
|
|
|
|
#define DWARF2_USE_FIXED_ADVANCE_PC 1
|
|
|
|
|
2023-04-25 17:19:18 +08:00
|
|
|
#define md_parse_name(name, exp, mode, c) \
|
|
|
|
riscv_parse_name (name, exp, mode)
|
|
|
|
bool riscv_parse_name (const char *, struct expressionS *, enum expr_mode);
|
|
|
|
|
gas: rename md_end to md_finish
Currently md_end is typically used for some final actions rather than
freeing memory like other *_end functions. Rename it to md_finish,
and rename target implementation. The renaming of target functions
makes it possible to find them all with "grep md_finish",
eg. md_mips_end is renamed to mips_md_finish, not md_mips_finish.
This patch leaves a number of md_end functions unchanged, those that
either do nothing or deallocate memory, and calls them late.
The idea here is that target maintainers implement md_end functions to
tidy memory, if anyone cares. Freeing persistent memory in gas is
not at all important, except that it can hide more important memory
leaks, those that happen once per some frequent gas operation, amongst
these unimportant memory leaks.
* as.c (main): Rename md_end to md_finish.
* config/tc-alpha.c, * config/tc-alpha.h,
* config/tc-arc.c, * config/tc-arc.h,
* config/tc-arm.c, * config/tc-arm.h,
* config/tc-csky.c, * config/tc-csky.h,
* config/tc-ia64.c, * config/tc-ia64.h,
* config/tc-mcore.c, * config/tc-mcore.h,
* config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mmix.h,
* config/tc-msp430.c, * config/tc-msp430.h,
* config/tc-nds32.c, * config/tc-nds32.h,
* config/tc-ppc.c, * config/tc-ppc.h,
* config/tc-pru.c, * config/tc-pru.h,
* config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-s390.c, * config/tc-s390.h,
* config/tc-sparc.c, * config/tc-sparc.h,
* config/tc-tic4x.c, * config/tc-tic4x.h,
* config/tc-tic6x.c, * config/tc-tic6x.h,
* config/tc-v850.c, * config/tc-v850.h,
* config/tc-xtensa.c, * config/tc-xtensa.h,
* config/tc-z80.c, * config/tc-z80.h: Similarly.
* output-file.c (output_file_close): Call md_end.
2022-07-05 11:56:38 +08:00
|
|
|
#define md_finish riscv_md_finish
|
2019-01-17 05:14:59 +08:00
|
|
|
#define CONVERT_SYMBOLIC_ATTRIBUTE riscv_convert_symbolic_attribute
|
|
|
|
|
gas: rename md_end to md_finish
Currently md_end is typically used for some final actions rather than
freeing memory like other *_end functions. Rename it to md_finish,
and rename target implementation. The renaming of target functions
makes it possible to find them all with "grep md_finish",
eg. md_mips_end is renamed to mips_md_finish, not md_mips_finish.
This patch leaves a number of md_end functions unchanged, those that
either do nothing or deallocate memory, and calls them late.
The idea here is that target maintainers implement md_end functions to
tidy memory, if anyone cares. Freeing persistent memory in gas is
not at all important, except that it can hide more important memory
leaks, those that happen once per some frequent gas operation, amongst
these unimportant memory leaks.
* as.c (main): Rename md_end to md_finish.
* config/tc-alpha.c, * config/tc-alpha.h,
* config/tc-arc.c, * config/tc-arc.h,
* config/tc-arm.c, * config/tc-arm.h,
* config/tc-csky.c, * config/tc-csky.h,
* config/tc-ia64.c, * config/tc-ia64.h,
* config/tc-mcore.c, * config/tc-mcore.h,
* config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mmix.h,
* config/tc-msp430.c, * config/tc-msp430.h,
* config/tc-nds32.c, * config/tc-nds32.h,
* config/tc-ppc.c, * config/tc-ppc.h,
* config/tc-pru.c, * config/tc-pru.h,
* config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-s390.c, * config/tc-s390.h,
* config/tc-sparc.c, * config/tc-sparc.h,
* config/tc-tic4x.c, * config/tc-tic4x.h,
* config/tc-tic6x.c, * config/tc-tic6x.h,
* config/tc-v850.c, * config/tc-v850.h,
* config/tc-xtensa.c, * config/tc-xtensa.h,
* config/tc-z80.c, * config/tc-z80.h: Similarly.
* output-file.c (output_file_close): Call md_end.
2022-07-05 11:56:38 +08:00
|
|
|
extern void riscv_md_finish (void);
|
2019-01-17 05:14:59 +08:00
|
|
|
extern int riscv_convert_symbolic_attribute (const char *);
|
|
|
|
|
RISC-V: PR27916, Support mapping symbols.
Similar to ARM/AARCH64, we add mapping symbols in the symbol table,
to mark the start addresses of data and instructions. The $d means
data, and the $x means instruction. Then the disassembler uses these
symbols to decide whether we should dump data or instruction.
Consider the mapping-04 test case,
$ cat tmp.s
.text
.option norelax
.option norvc
.fill 2, 4, 0x1001
.byte 1
.word 0
.balign 8
add a0, a0, a0
.fill 5, 2, 0x2002
add a1, a1, a1
.data
.word 0x1 # No need to add mapping symbols.
.word 0x2
$ riscv64-unknown-elf-as tmp.s -o tmp.o
$ riscv64-unknown-elf-objdump -d tmp.o
Disassembly of section .text:
0000000000000000 <.text>:
0: 00001001 .word 0x00001001 # Marked $d, .fill directive.
4: 00001001 .word 0x00001001
8: 00000001 .word 0x00000001 # .byte + part of .word.
c: 00 .byte 0x00 # remaining .word.
d: 00 .byte 0x00 # Marked $d, odd byte of alignment.
e: 0001 nop # Marked $x, nops for alignment.
10: 00a50533 add a0,a0,a0
14: 20022002 .word 0x20022002 # Marked $d, .fill directive.
18: 20022002 .word 0x20022002
1c: 2002 .short 0x2002
1e: 00b585b3 add a1,a1,a1 # Marked $x.
22: 0001 nop # Section tail alignment.
24: 00000013 nop
* Use $d and $x to mark the distribution of data and instructions.
Alignments of code are recognized as instructions, since we usually
fill nops for them.
* If the alignment have odd bytes, then we cannot just fill the nops
into the spaces. We always fill an odd byte 0x00 at the start of
the spaces. Therefore, add a $d mapping symbol for the odd byte,
to tell disassembler that it isn't an instruction. The behavior
is same as Arm and Aarch64.
The elf/linux toolchain regressions all passed. Besides, I also
disable the mapping symbols internally, but use the new objudmp, the
regressions passed, too. Therefore, the new objudmp should dump
the objects corretly, even if they don't have any mapping symbols.
bfd/
pr 27916
* cpu-riscv.c (riscv_elf_is_mapping_symbols): Define mapping symbols.
* cpu-riscv.h: extern riscv_elf_is_mapping_symbols.
* elfnn-riscv.c (riscv_maybe_function_sym): Do not choose mapping
symbols as a function name.
(riscv_elf_is_target_special_symbol): Add mapping symbols.
binutils/
pr 27916
* testsuite/binutils-all/readelf.s: Updated.
* testsuite/binutils-all/readelf.s-64: Likewise.
* testsuite/binutils-all/readelf.s-64-unused: Likewise.
* testsuite/binutils-all/readelf.ss: Likewise.
* testsuite/binutils-all/readelf.ss-64: Likewise.
* testsuite/binutils-all/readelf.ss-64-unused: Likewise.
gas/
pr 27916
* config/tc-riscv.c (make_mapping_symbol): Create a new mapping symbol.
(riscv_mapping_state): Decide whether to create mapping symbol for
frag_now. Only add the mapping symbols to text sections.
(riscv_add_odd_padding_symbol): Add the mapping symbols for the
riscv_handle_align, which have odd bytes spaces.
(riscv_check_mapping_symbols): Remove any excess mapping symbols.
(md_assemble): Marked as MAP_INSN.
(riscv_frag_align_code): Marked as MAP_INSN.
(riscv_init_frag): Add mapping symbols for frag, it usually called
by frag_var. Marked as MAP_DATA for rs_align and rs_fill, and
marked as MAP_INSN for rs_align_code.
(s_riscv_insn): Marked as MAP_INSN.
(riscv_adjust_symtab): Call riscv_check_mapping_symbols.
* config/tc-riscv.h (md_cons_align): Defined to riscv_mapping_state
with MAP_DATA.
(TC_SEGMENT_INFO_TYPE): Record mapping state for each segment.
(TC_FRAG_TYPE): Record the first and last mapping symbols for the
fragments. The first mapping symbol must be placed at the start
of the fragment.
(TC_FRAG_INIT): Defined to riscv_init_frag.
* testsuite/gas/riscv/mapping-01.s: New testcase.
* testsuite/gas/riscv/mapping-01a.d: Likewise.
* testsuite/gas/riscv/mapping-01b.d: Likewise.
* testsuite/gas/riscv/mapping-02.s: Likewise.
* testsuite/gas/riscv/mapping-02a.d: Likewise.
* testsuite/gas/riscv/mapping-02b.d: Likewise.
* testsuite/gas/riscv/mapping-03.s: Likewise.
* testsuite/gas/riscv/mapping-03a.d: Likewise.
* testsuite/gas/riscv/mapping-03b.d: Likewise.
* testsuite/gas/riscv/mapping-04.s: Likewise.
* testsuite/gas/riscv/mapping-04a.d: Likewise.
* testsuite/gas/riscv/mapping-04b.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04a.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04b.d: Likewise.
* testsuite/gas/riscv/no-relax-align.d: Updated.
* testsuite/gas/riscv/no-relax-align-2.d: Likewise.
include/
pr 27916
* opcode/riscv.h (enum riscv_seg_mstate): Added.
opcodes/
pr 27916
* riscv-dis.c (last_map_symbol, last_stop_offset, last_map_state):
Added to dump sections with mapping symbols.
(riscv_get_map_state): Get the mapping state from the symbol.
(riscv_search_mapping_symbol): Check the sorted symbol table, and
then find the suitable mapping symbol.
(riscv_data_length): Decide which data size we should print.
(riscv_disassemble_data): Dump the data contents.
(print_insn_riscv): Handle the mapping symbols.
(riscv_symbol_is_valid): Marked mapping symbols as invalid.
2021-07-13 18:09:38 +08:00
|
|
|
/* Set mapping symbol states. */
|
RISC-V: Output mapping symbols with ISA string.
RISC-V Psabi pr196,
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/196
bfd/
* elfxx-riscv.c (riscv_release_subset_list): Free arch_str if needed.
(riscv_copy_subset_list): Copy arch_str as well.
* elfxx-riscv.h (riscv_subset_list_t): Store arch_str for each subset list.
gas/
* config/tc-riscv.c (riscv_reset_subsets_list_arch_str): Update the
architecture string in the subset_list.
(riscv_set_arch): Call riscv_reset_subsets_list_arch_str after parsing new
architecture string.
(s_riscv_option): Likewise.
(need_arch_map_symbol): New boolean, used to indicate if .option
directives do affect instructions.
(make_mapping_symbol): New boolean parameter reset_seg_arch_str. Need to
generate $x+arch for MAP_INSN, and then store it into tc_segment_info_data
if reset_seg_arch_str is true.
(riscv_mapping_state): Decide if we need to add $x+arch for MAP_INSN. For
now, only add $x+arch if the architecture strings in subset list and segment
are different. Besides, always add $x+arch at the start of section, and do
not add $x+arch for code alignment, since rvc for alignment can be judged
from addend of R_RISCV_ALIGN.
(riscv_remove_mapping_symbol): If current and previous mapping symbol have
same value, then remove the current $x only if the previous is $x+arch;
Otherwise, always remove previous.
(riscv_add_odd_padding_symbol): Updated.
(riscv_check_mapping_symbols): Don't need to add any $x+arch if
need_arch_map_symbol is false, so changed them to $x.
(riscv_frag_align_code): Updated since riscv_mapping_state is changed.
(riscv_init_frag): Likewise.
(s_riscv_insn): Likewise.
(riscv_elf_final_processing): Call riscv_release_subset_list to release
subset_list of riscv_rps_as, rather than only release arch_str in the
riscv_write_out_attrs.
(riscv_write_out_attrs): No need to call riscv_arch_str, just get arch_str
from subset_list of riscv_rps_as.
* config/tc-riscv.h (riscv_segment_info_type): Record current $x+arch mapping
symbol of each segment.
* testsuite/gas/riscv/mapping-0*: Merged and replaced by mapping.s.
* testsuite/gas/riscv/mapping.s: New testcase, to test most of the cases in
one file.
* testsuite/gas/riscv/mapping-symbols.d: Likewise.
* testsuite/gas/riscv/mapping-dis.d: Likewise.
* testsuite/gas/riscv/mapping-non-arch.s: New testcase for the case that
does need any $x+arch.
* testsuite/gas/riscv/mapping-non-arch.d: Likewise.
* testsuite/gas/riscv/option-arch-01a.d: Updated.
opcodes/
* riscv-dis.c (riscv_disassemble_insn): Set riscv_fpr_names back to
riscv_fpr_names_abi or riscv_fpr_names_numeric when zfinx is disabled
for some specfic code region.
(riscv_get_map_state): Recognized mapping symbols $x+arch, and then reset
the architecture string once the ISA is different.
2022-09-29 19:07:46 +08:00
|
|
|
#define md_cons_align(nbytes) riscv_mapping_state (MAP_DATA, 0, 0)
|
|
|
|
void riscv_mapping_state (enum riscv_seg_mstate, int, bool);
|
RISC-V: PR27916, Support mapping symbols.
Similar to ARM/AARCH64, we add mapping symbols in the symbol table,
to mark the start addresses of data and instructions. The $d means
data, and the $x means instruction. Then the disassembler uses these
symbols to decide whether we should dump data or instruction.
Consider the mapping-04 test case,
$ cat tmp.s
.text
.option norelax
.option norvc
.fill 2, 4, 0x1001
.byte 1
.word 0
.balign 8
add a0, a0, a0
.fill 5, 2, 0x2002
add a1, a1, a1
.data
.word 0x1 # No need to add mapping symbols.
.word 0x2
$ riscv64-unknown-elf-as tmp.s -o tmp.o
$ riscv64-unknown-elf-objdump -d tmp.o
Disassembly of section .text:
0000000000000000 <.text>:
0: 00001001 .word 0x00001001 # Marked $d, .fill directive.
4: 00001001 .word 0x00001001
8: 00000001 .word 0x00000001 # .byte + part of .word.
c: 00 .byte 0x00 # remaining .word.
d: 00 .byte 0x00 # Marked $d, odd byte of alignment.
e: 0001 nop # Marked $x, nops for alignment.
10: 00a50533 add a0,a0,a0
14: 20022002 .word 0x20022002 # Marked $d, .fill directive.
18: 20022002 .word 0x20022002
1c: 2002 .short 0x2002
1e: 00b585b3 add a1,a1,a1 # Marked $x.
22: 0001 nop # Section tail alignment.
24: 00000013 nop
* Use $d and $x to mark the distribution of data and instructions.
Alignments of code are recognized as instructions, since we usually
fill nops for them.
* If the alignment have odd bytes, then we cannot just fill the nops
into the spaces. We always fill an odd byte 0x00 at the start of
the spaces. Therefore, add a $d mapping symbol for the odd byte,
to tell disassembler that it isn't an instruction. The behavior
is same as Arm and Aarch64.
The elf/linux toolchain regressions all passed. Besides, I also
disable the mapping symbols internally, but use the new objudmp, the
regressions passed, too. Therefore, the new objudmp should dump
the objects corretly, even if they don't have any mapping symbols.
bfd/
pr 27916
* cpu-riscv.c (riscv_elf_is_mapping_symbols): Define mapping symbols.
* cpu-riscv.h: extern riscv_elf_is_mapping_symbols.
* elfnn-riscv.c (riscv_maybe_function_sym): Do not choose mapping
symbols as a function name.
(riscv_elf_is_target_special_symbol): Add mapping symbols.
binutils/
pr 27916
* testsuite/binutils-all/readelf.s: Updated.
* testsuite/binutils-all/readelf.s-64: Likewise.
* testsuite/binutils-all/readelf.s-64-unused: Likewise.
* testsuite/binutils-all/readelf.ss: Likewise.
* testsuite/binutils-all/readelf.ss-64: Likewise.
* testsuite/binutils-all/readelf.ss-64-unused: Likewise.
gas/
pr 27916
* config/tc-riscv.c (make_mapping_symbol): Create a new mapping symbol.
(riscv_mapping_state): Decide whether to create mapping symbol for
frag_now. Only add the mapping symbols to text sections.
(riscv_add_odd_padding_symbol): Add the mapping symbols for the
riscv_handle_align, which have odd bytes spaces.
(riscv_check_mapping_symbols): Remove any excess mapping symbols.
(md_assemble): Marked as MAP_INSN.
(riscv_frag_align_code): Marked as MAP_INSN.
(riscv_init_frag): Add mapping symbols for frag, it usually called
by frag_var. Marked as MAP_DATA for rs_align and rs_fill, and
marked as MAP_INSN for rs_align_code.
(s_riscv_insn): Marked as MAP_INSN.
(riscv_adjust_symtab): Call riscv_check_mapping_symbols.
* config/tc-riscv.h (md_cons_align): Defined to riscv_mapping_state
with MAP_DATA.
(TC_SEGMENT_INFO_TYPE): Record mapping state for each segment.
(TC_FRAG_TYPE): Record the first and last mapping symbols for the
fragments. The first mapping symbol must be placed at the start
of the fragment.
(TC_FRAG_INIT): Defined to riscv_init_frag.
* testsuite/gas/riscv/mapping-01.s: New testcase.
* testsuite/gas/riscv/mapping-01a.d: Likewise.
* testsuite/gas/riscv/mapping-01b.d: Likewise.
* testsuite/gas/riscv/mapping-02.s: Likewise.
* testsuite/gas/riscv/mapping-02a.d: Likewise.
* testsuite/gas/riscv/mapping-02b.d: Likewise.
* testsuite/gas/riscv/mapping-03.s: Likewise.
* testsuite/gas/riscv/mapping-03a.d: Likewise.
* testsuite/gas/riscv/mapping-03b.d: Likewise.
* testsuite/gas/riscv/mapping-04.s: Likewise.
* testsuite/gas/riscv/mapping-04a.d: Likewise.
* testsuite/gas/riscv/mapping-04b.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04a.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04b.d: Likewise.
* testsuite/gas/riscv/no-relax-align.d: Updated.
* testsuite/gas/riscv/no-relax-align-2.d: Likewise.
include/
pr 27916
* opcode/riscv.h (enum riscv_seg_mstate): Added.
opcodes/
pr 27916
* riscv-dis.c (last_map_symbol, last_stop_offset, last_map_state):
Added to dump sections with mapping symbols.
(riscv_get_map_state): Get the mapping state from the symbol.
(riscv_search_mapping_symbol): Check the sorted symbol table, and
then find the suitable mapping symbol.
(riscv_data_length): Decide which data size we should print.
(riscv_disassemble_data): Dump the data contents.
(print_insn_riscv): Handle the mapping symbols.
(riscv_symbol_is_valid): Marked mapping symbols as invalid.
2021-07-13 18:09:38 +08:00
|
|
|
|
|
|
|
/* Define target segment type. */
|
|
|
|
#define TC_SEGMENT_INFO_TYPE struct riscv_segment_info_type
|
|
|
|
struct riscv_segment_info_type
|
|
|
|
{
|
|
|
|
enum riscv_seg_mstate map_state;
|
RISC-V: Output mapping symbols with ISA string.
RISC-V Psabi pr196,
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/196
bfd/
* elfxx-riscv.c (riscv_release_subset_list): Free arch_str if needed.
(riscv_copy_subset_list): Copy arch_str as well.
* elfxx-riscv.h (riscv_subset_list_t): Store arch_str for each subset list.
gas/
* config/tc-riscv.c (riscv_reset_subsets_list_arch_str): Update the
architecture string in the subset_list.
(riscv_set_arch): Call riscv_reset_subsets_list_arch_str after parsing new
architecture string.
(s_riscv_option): Likewise.
(need_arch_map_symbol): New boolean, used to indicate if .option
directives do affect instructions.
(make_mapping_symbol): New boolean parameter reset_seg_arch_str. Need to
generate $x+arch for MAP_INSN, and then store it into tc_segment_info_data
if reset_seg_arch_str is true.
(riscv_mapping_state): Decide if we need to add $x+arch for MAP_INSN. For
now, only add $x+arch if the architecture strings in subset list and segment
are different. Besides, always add $x+arch at the start of section, and do
not add $x+arch for code alignment, since rvc for alignment can be judged
from addend of R_RISCV_ALIGN.
(riscv_remove_mapping_symbol): If current and previous mapping symbol have
same value, then remove the current $x only if the previous is $x+arch;
Otherwise, always remove previous.
(riscv_add_odd_padding_symbol): Updated.
(riscv_check_mapping_symbols): Don't need to add any $x+arch if
need_arch_map_symbol is false, so changed them to $x.
(riscv_frag_align_code): Updated since riscv_mapping_state is changed.
(riscv_init_frag): Likewise.
(s_riscv_insn): Likewise.
(riscv_elf_final_processing): Call riscv_release_subset_list to release
subset_list of riscv_rps_as, rather than only release arch_str in the
riscv_write_out_attrs.
(riscv_write_out_attrs): No need to call riscv_arch_str, just get arch_str
from subset_list of riscv_rps_as.
* config/tc-riscv.h (riscv_segment_info_type): Record current $x+arch mapping
symbol of each segment.
* testsuite/gas/riscv/mapping-0*: Merged and replaced by mapping.s.
* testsuite/gas/riscv/mapping.s: New testcase, to test most of the cases in
one file.
* testsuite/gas/riscv/mapping-symbols.d: Likewise.
* testsuite/gas/riscv/mapping-dis.d: Likewise.
* testsuite/gas/riscv/mapping-non-arch.s: New testcase for the case that
does need any $x+arch.
* testsuite/gas/riscv/mapping-non-arch.d: Likewise.
* testsuite/gas/riscv/option-arch-01a.d: Updated.
opcodes/
* riscv-dis.c (riscv_disassemble_insn): Set riscv_fpr_names back to
riscv_fpr_names_abi or riscv_fpr_names_numeric when zfinx is disabled
for some specfic code region.
(riscv_get_map_state): Recognized mapping symbols $x+arch, and then reset
the architecture string once the ISA is different.
2022-09-29 19:07:46 +08:00
|
|
|
/* The current mapping symbol with architecture string. */
|
|
|
|
symbolS *arch_map_symbol;
|
RISC-V: PR27916, Support mapping symbols.
Similar to ARM/AARCH64, we add mapping symbols in the symbol table,
to mark the start addresses of data and instructions. The $d means
data, and the $x means instruction. Then the disassembler uses these
symbols to decide whether we should dump data or instruction.
Consider the mapping-04 test case,
$ cat tmp.s
.text
.option norelax
.option norvc
.fill 2, 4, 0x1001
.byte 1
.word 0
.balign 8
add a0, a0, a0
.fill 5, 2, 0x2002
add a1, a1, a1
.data
.word 0x1 # No need to add mapping symbols.
.word 0x2
$ riscv64-unknown-elf-as tmp.s -o tmp.o
$ riscv64-unknown-elf-objdump -d tmp.o
Disassembly of section .text:
0000000000000000 <.text>:
0: 00001001 .word 0x00001001 # Marked $d, .fill directive.
4: 00001001 .word 0x00001001
8: 00000001 .word 0x00000001 # .byte + part of .word.
c: 00 .byte 0x00 # remaining .word.
d: 00 .byte 0x00 # Marked $d, odd byte of alignment.
e: 0001 nop # Marked $x, nops for alignment.
10: 00a50533 add a0,a0,a0
14: 20022002 .word 0x20022002 # Marked $d, .fill directive.
18: 20022002 .word 0x20022002
1c: 2002 .short 0x2002
1e: 00b585b3 add a1,a1,a1 # Marked $x.
22: 0001 nop # Section tail alignment.
24: 00000013 nop
* Use $d and $x to mark the distribution of data and instructions.
Alignments of code are recognized as instructions, since we usually
fill nops for them.
* If the alignment have odd bytes, then we cannot just fill the nops
into the spaces. We always fill an odd byte 0x00 at the start of
the spaces. Therefore, add a $d mapping symbol for the odd byte,
to tell disassembler that it isn't an instruction. The behavior
is same as Arm and Aarch64.
The elf/linux toolchain regressions all passed. Besides, I also
disable the mapping symbols internally, but use the new objudmp, the
regressions passed, too. Therefore, the new objudmp should dump
the objects corretly, even if they don't have any mapping symbols.
bfd/
pr 27916
* cpu-riscv.c (riscv_elf_is_mapping_symbols): Define mapping symbols.
* cpu-riscv.h: extern riscv_elf_is_mapping_symbols.
* elfnn-riscv.c (riscv_maybe_function_sym): Do not choose mapping
symbols as a function name.
(riscv_elf_is_target_special_symbol): Add mapping symbols.
binutils/
pr 27916
* testsuite/binutils-all/readelf.s: Updated.
* testsuite/binutils-all/readelf.s-64: Likewise.
* testsuite/binutils-all/readelf.s-64-unused: Likewise.
* testsuite/binutils-all/readelf.ss: Likewise.
* testsuite/binutils-all/readelf.ss-64: Likewise.
* testsuite/binutils-all/readelf.ss-64-unused: Likewise.
gas/
pr 27916
* config/tc-riscv.c (make_mapping_symbol): Create a new mapping symbol.
(riscv_mapping_state): Decide whether to create mapping symbol for
frag_now. Only add the mapping symbols to text sections.
(riscv_add_odd_padding_symbol): Add the mapping symbols for the
riscv_handle_align, which have odd bytes spaces.
(riscv_check_mapping_symbols): Remove any excess mapping symbols.
(md_assemble): Marked as MAP_INSN.
(riscv_frag_align_code): Marked as MAP_INSN.
(riscv_init_frag): Add mapping symbols for frag, it usually called
by frag_var. Marked as MAP_DATA for rs_align and rs_fill, and
marked as MAP_INSN for rs_align_code.
(s_riscv_insn): Marked as MAP_INSN.
(riscv_adjust_symtab): Call riscv_check_mapping_symbols.
* config/tc-riscv.h (md_cons_align): Defined to riscv_mapping_state
with MAP_DATA.
(TC_SEGMENT_INFO_TYPE): Record mapping state for each segment.
(TC_FRAG_TYPE): Record the first and last mapping symbols for the
fragments. The first mapping symbol must be placed at the start
of the fragment.
(TC_FRAG_INIT): Defined to riscv_init_frag.
* testsuite/gas/riscv/mapping-01.s: New testcase.
* testsuite/gas/riscv/mapping-01a.d: Likewise.
* testsuite/gas/riscv/mapping-01b.d: Likewise.
* testsuite/gas/riscv/mapping-02.s: Likewise.
* testsuite/gas/riscv/mapping-02a.d: Likewise.
* testsuite/gas/riscv/mapping-02b.d: Likewise.
* testsuite/gas/riscv/mapping-03.s: Likewise.
* testsuite/gas/riscv/mapping-03a.d: Likewise.
* testsuite/gas/riscv/mapping-03b.d: Likewise.
* testsuite/gas/riscv/mapping-04.s: Likewise.
* testsuite/gas/riscv/mapping-04a.d: Likewise.
* testsuite/gas/riscv/mapping-04b.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04a.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04b.d: Likewise.
* testsuite/gas/riscv/no-relax-align.d: Updated.
* testsuite/gas/riscv/no-relax-align-2.d: Likewise.
include/
pr 27916
* opcode/riscv.h (enum riscv_seg_mstate): Added.
opcodes/
pr 27916
* riscv-dis.c (last_map_symbol, last_stop_offset, last_map_state):
Added to dump sections with mapping symbols.
(riscv_get_map_state): Get the mapping state from the symbol.
(riscv_search_mapping_symbol): Check the sorted symbol table, and
then find the suitable mapping symbol.
(riscv_data_length): Decide which data size we should print.
(riscv_disassemble_data): Dump the data contents.
(print_insn_riscv): Handle the mapping symbols.
(riscv_symbol_is_valid): Marked mapping symbols as invalid.
2021-07-13 18:09:38 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Define target fragment type. */
|
|
|
|
#define TC_FRAG_TYPE struct riscv_frag_type
|
|
|
|
struct riscv_frag_type
|
|
|
|
{
|
|
|
|
symbolS *first_map_symbol, *last_map_symbol;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define TC_FRAG_INIT(fragp, max_bytes) riscv_init_frag (fragp, max_bytes)
|
|
|
|
extern void riscv_init_frag (struct frag *, int);
|
|
|
|
|
|
|
|
#define obj_adjust_symtab() riscv_adjust_symtab ()
|
|
|
|
extern void riscv_adjust_symtab (void);
|
|
|
|
|
RISC-V: Support STO_RISCV_VARIANT_CC and DT_RISCV_VARIANT_CC.
This is the original discussion,
https://github.com/riscv/riscv-elf-psabi-doc/pull/190
And here is the glibc part,
https://sourceware.org/pipermail/libc-alpha/2021-August/129931.html
For binutils part, we need to support a new direcitve: .variant_cc.
The function symbol marked by .variant_cc means it need to be resolved
directly without resolver for dynamic linker. We also add a new dynamic
entry, STO_RISCV_VARIANT_CC, to indicate there are symbols with the
special attribute in the dynamic symbol table of the object.
I heard that llvm already have supported this in their mainline, so
I think it's time to commit this.
bfd/
* elfnn-riscv.c (riscv_elf_link_hash_table): Added variant_cc
flag. It is used to check if relocations for variant CC symbols
may be present.
(allocate_dynrelocs): If the symbol has STO_RISCV_VARIANT_CC
flag, then raise the variant_cc flag of riscv_elf_link_hash_table.
(riscv_elf_size_dynamic_sections): Added dynamic entry for
variant_cc.
(riscv_elf_merge_symbol_attribute): New function, used to merge
non-visibility st_other attributes, including STO_RISCV_VARIANT_CC.
binutils/
* readelf.c (get_riscv_dynamic_type): New function.
(get_dynamic_type): Called get_riscv_dynamic_type for riscv targets.
(get_riscv_symbol_other): New function.
(get_symbol_other): Called get_riscv_symbol_other for riscv targets.
gas/
* config/tc-riscv.c (s_variant_cc): Marked symbol that it follows a
variant CC convention.
(riscv_elf_copy_symbol_attributes): Same as elf_copy_symbol_attributes,
but without copying st_other. If a function symbol has special st_other
value set via directives, then attaching an IFUNC resolver to that symbol
should not override the st_other setting.
(riscv_pseudo_table): Support variant_cc diretive.
* config/tc-riscv.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Defined.
* testsuite/gas/riscv/variant_cc-set.d: New testcase.
* testsuite/gas/riscv/variant_cc-set.s: Likewise.
* testsuite/gas/riscv/variant_cc.d: Likewise.
* testsuite/gas/riscv/variant_cc.s: Likewise.
include/
* elf/riscv.h (DT_RISCV_VARIANT_CC): Defined to (DT_LOPROC + 1).
(STO_RISCV_VARIANT_CC): Defined to 0x80.
ld/
* testsuite/ld-riscv-elf/variant_cc-1.s: New testcase.
* testsuite/ld-riscv-elf/variant_cc-2.s: Likewise.
* testsuite/ld-riscv-elf/variant_cc-now.d: Likewise.
* testsuite/ld-riscv-elf/variant_cc-r.d: Likewise.
* testsuite/ld-riscv-elf/variant_cc-shared.d: Likewise.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
2021-08-11 16:26:39 +08:00
|
|
|
void riscv_elf_copy_symbol_attributes (symbolS *, symbolS *);
|
|
|
|
#define OBJ_COPY_SYMBOL_ATTRIBUTES(DEST, SRC) \
|
|
|
|
riscv_elf_copy_symbol_attributes (DEST, SRC)
|
|
|
|
|
2016-11-02 00:45:57 +08:00
|
|
|
#endif /* TC_RISCV */
|