binutils-gdb/bfd/elfxx-riscv.h
Nelson Chu f786c359c1 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.
2021-11-11 16:59:13 +08:00

108 lines
2.8 KiB
C

/* RISC-V ELF specific backend routines.
Copyright (C) 2011-2021 Free Software Foundation, Inc.
Contributed by Andrew Waterman (andrew@sifive.com).
Based on MIPS target.
This file is part of BFD, the Binary File Descriptor library.
This program 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 of the License, or
(at your option) any later version.
This program 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/>. */
#include "elf/common.h"
#include "elf/internal.h"
#include "opcode/riscv.h"
#include "cpu-riscv.h"
#define RISCV_UNKNOWN_VERSION -1
extern reloc_howto_type *
riscv_reloc_name_lookup (bfd *, const char *);
extern reloc_howto_type *
riscv_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
extern reloc_howto_type *
riscv_elf_rtype_to_howto (bfd *, unsigned int r_type);
/* The information of architecture attribute. */
struct riscv_subset_t
{
const char *name;
int major_version;
int minor_version;
struct riscv_subset_t *next;
};
typedef struct riscv_subset_t riscv_subset_t;
typedef struct
{
riscv_subset_t *head;
riscv_subset_t *tail;
} riscv_subset_list_t;
extern void
riscv_release_subset_list (riscv_subset_list_t *);
extern void
riscv_add_subset (riscv_subset_list_t *,
const char *,
int, int);
extern bool
riscv_lookup_subset (const riscv_subset_list_t *,
const char *,
riscv_subset_t **);
typedef struct
{
riscv_subset_list_t *subset_list;
void (*error_handler) (const char *,
...) ATTRIBUTE_PRINTF_1;
unsigned *xlen;
enum riscv_spec_class *isa_spec;
bool check_unknown_prefixed_ext;
} riscv_parse_subset_t;
extern bool
riscv_parse_subset (riscv_parse_subset_t *,
const char *);
extern void
riscv_release_subset_list (riscv_subset_list_t *);
extern char *
riscv_arch_str (unsigned, const riscv_subset_list_t *);
extern size_t
riscv_estimate_digit (unsigned);
extern int
riscv_compare_subsets (const char *, const char *);
extern bool
riscv_update_subset (riscv_parse_subset_t *, const char *, bool);
extern bool
riscv_subset_supports (riscv_parse_subset_t *, const char *);
extern bool
riscv_multi_subset_supports (riscv_parse_subset_t *, enum riscv_insn_class);
extern void
bfd_elf32_riscv_set_data_segment_info (struct bfd_link_info *, int *);
extern void
bfd_elf64_riscv_set_data_segment_info (struct bfd_link_info *, int *);