diff options
author | Nelson Chu <nelson.chu@sifive.com> | 2021-11-08 16:35:25 +0800 |
---|---|---|
committer | Nelson Chu <nelson.chu@sifive.com> | 2021-11-11 16:59:13 +0800 |
commit | f786c359c1e3227fe8ecfcb2819bb3b80ed351ed (patch) | |
tree | 1127cc959b674da4128873b4bb4de8a3de84c2df /opcodes | |
parent | efe113047d765b26869c3170c43678dd561027b4 (diff) | |
download | binutils-f786c359c1e3227fe8ecfcb2819bb3b80ed351ed.zip binutils-f786c359c1e3227fe8ecfcb2819bb3b80ed351ed.tar.gz binutils-f786c359c1e3227fe8ecfcb2819bb3b80ed351ed.tar.bz2 |
RISC-V: Dump objects according to the elf architecture attribute.
For now we should always generate the elf architecture attribute both for
elf and linux toolchains, so that we could dump the objects correctly
according to the generated architecture string. This patch resolves the
problem that we probably dump an object with c.nop instructions, but
in fact the c extension isn't allowed. Consider the following case,
nelson@LAPTOP-QFSGI1F2:~/test$ cat temp.s
.option norvc
.option norelax
.text
add a0, a0, a0
.byte 0x1
.balign 16
nelson@LAPTOP-QFSGI1F2:~/test$ ~/binutils-dev/build-elf32-upstream/build-install/bin/riscv32-unknown-elf-as temp.s -o temp.o
nelson@LAPTOP-QFSGI1F2:~/test$ ~/binutils-dev/build-elf32-upstream/build-install/bin/riscv32-unknown-elf-objdump -d temp.o
temp.o: file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0: 00a50533 add a0,a0,a0
4: 01 .byte 0x01
5: 00 .byte 0x00
6: 0001 nop
8: 00000013 nop
c: 00000013 nop
nelson@LAPTOP-QFSGI1F2:~/test$ ~/binutils-dev/build-elf32-upstream/build-install/bin/riscv32-unknown-elf-readelf -A temp.o
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p0_m2p0_a2p0_f2p0_d2p0"
The c.nop at address 0x6 is generated for alignment, but since the rvc isn't
allowed for this object, dump it as a c.nop instruction looks wrong. After
applying this patch, I get the following result,
nelson@LAPTOP-QFSGI1F2:~/test$ ~/binutils-dev/build-elf32-upstream/build-install/bin/riscv32-unknown-elf-objdump -d temp.o
temp.o: file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0: 00a50533 add a0,a0,a0
4: 01 .byte 0x01
5: 00 .byte 0x00
6: 0001 .2byte 0x1
8: 00000013 nop
c: 00000013 nop
For the current objdump, we dump data to .byte/.short/.word/.dword, and
dump the unknown or unsupported instructions to .2byte/.4byte/.8byte, which
respectively are 2, 4 and 8 bytes instructions. Therefore, we shouldn't
dump the 0x0001 as a c.nop instruction in the above case, we should dump
it to .2byte 0x1 as a unknown instruction, since the rvc is disabled.
However, consider that some people may use the new objdump to dump the old
objects, which don't have any elf attributes. We usually set the default
architecture string to rv64g by bfd/elfxx-riscv.c:riscv_set_default_arch.
But this will cause rvc instructions to be unrecognized. Therefore, we
set the default architecture string to rv64gc for disassembler, to keep
the previous behavior.
This patch pass the riscv-gnu-toolchain gcc/binutils regressions for
rv32emc-elf, rv32gc-linux, rv32i-elf, rv64gc-elf and rv64gc-linux
toolchains. Also, tested by --enable-targets=all and can build
riscv-gdb successfully.
bfd/
* elfnn-riscv.c (riscv_merge_arch_attr_info): Tidy the
codes for riscv_parse_subset_t setting.
* elfxx-riscv.c (riscv_get_default_ext_version): Updated.
(riscv_subset_supports): Moved from gas/config/tc-riscv.c.
(riscv_multi_subset_supports): Likewise.
* elfxx-riscv.h: Added extern for riscv_subset_supports and
riscv_multi_subset_supports.
gas/
* config/tc-riscv.c (riscv_subset_supports): Moved to
bfd/elfxx-riscv.c.
(riscv_multi_subset_supports): Likewise.
(riscv_rps_as): Defined for architectrue parser.
(riscv_set_arch): Updated.
(riscv_set_abi_by_arch): Likewise.
(riscv_csr_address): Likewise.
(reg_lookup_internal): Likewise.
(riscv_ip): Likewise.
(s_riscv_option): Updated.
* testsuite/gas/riscv/mapping-04b.d: Updated.
* testsuite/gas/riscv/mapping-norelax-03b.d: Likewise.
* testsuite/gas/riscv/mapping-norelax-04b.d: Likewise.
opcodes/
* riscv-dis.c: Include elfxx-riscv.h since we need the
architecture parser. Also removed the cpu-riscv.h, it
is already included in elfxx-riscv.h.
(default_isa_spec): Defined since the parser need this
to set the default architecture string.
(xlen): Moved out from riscv_disassemble_insn as a global
variable, it is more convenient to initialize riscv_rps_dis.
(riscv_subsets): Defined to recoed the supported
extensions.
(riscv_rps_dis): Defined for architectrue parser.
(riscv_disassemble_insn): Call riscv_multi_subset_supports
to make sure if the instructions are valid or not.
(print_insn_riscv): Initialize the riscv_subsets by parsing
the elf architectrue attribute. Otherwise, set the default
architectrue string to rv64gc.
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/riscv-dis.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 1a09440..d097c16 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -27,13 +27,26 @@ #include "opintl.h" #include "elf-bfd.h" #include "elf/riscv.h" -#include "cpu-riscv.h" +#include "elfxx-riscv.h" #include <stdint.h> #include <ctype.h> +static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE; +unsigned xlen = 0; + +static riscv_subset_list_t riscv_subsets; +static riscv_parse_subset_t riscv_rps_dis = +{ + &riscv_subsets, /* subset_list. */ + opcodes_error_handler,/* error_handler. */ + &xlen, /* xlen. */ + &default_isa_spec, /* isa_spec. */ + false, /* check_unknown_prefixed_ext. */ +}; + struct riscv_private_data { bfd_vma gp; @@ -502,8 +515,6 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info) op = riscv_hash[OP_HASH_IDX (word)]; if (op != NULL) { - unsigned xlen = 0; - /* If XLEN is not known, get its value from the ELF class. */ if (info->mach == bfd_mach_riscv64) xlen = 64; @@ -527,6 +538,9 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info) if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen)) continue; + if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class)) + continue; + /* It's a match. */ (*info->fprintf_func) (info->stream, "%s", op->name); print_insn_args (op->args, word, memaddr, info); @@ -852,11 +866,13 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info) disassembler_ftype riscv_get_disassembler (bfd *abfd) { + const char *default_arch = "rv64gc"; + if (abfd) { const struct elf_backend_data *ebd = get_elf_backend_data (abfd); if (ebd) - { + { const char *sec_name = ebd->obj_attrs_section; if (bfd_get_section_by_name (abfd, sec_name) != NULL) { @@ -868,10 +884,14 @@ riscv_get_disassembler (bfd *abfd) attr[Tag_b].i, attr[Tag_c].i, &default_priv_spec); + default_arch = attr[Tag_RISCV_arch].s; } - } + } } - return print_insn_riscv; + + riscv_release_subset_list (&riscv_subsets); + riscv_parse_subset (&riscv_rps_dis, default_arch); + return print_insn_riscv; } /* Prevent use of the fake labels that are generated as part of the DWARF |