Skip to content

Commit

Permalink
RISC-V: Add "arch" disassembler option
Browse files Browse the repository at this point in the history
This commit adds new disassembler option "arch" to override architecture
string.  Existing implementations is helpful on regular ELF files but
for instance, when debugging a binary with OpenOCD + GDB, there's a case
where such information is not available.

Also, there's a case where changing the architecture to disassemble is
helpful, even on ELF files.  For instance, Linux kernel is the prime
example.

On recent Linux kernel on RISC-V, it utilizes "alternatives" feature, which
patches the kernel on the fly, depending on the implemented extensions.  For
instance, it utilizes the 'Zicboz' extension to clear the entire page and
the 'Zbb' extension for efficient string handling.  Note that those
extension uses are determined by the runtime and at least ELF attributes
don't have such information.  Some of which (uses of 'Zicboz') are even
invisible from mapping symbols.

This commit enables objdump and GDB to use custom architecture string
instead of ELF attributes and mapping symbols (e.g. even if OpenSBI is
compiled with -march=rv64gc, we can enable H extension when disassembling
OpenSBI by specifying an architecture string: rv64gch).

It can be also helpful to test overwrapping encodings (e.g. standard hints).

gas/ChangeLog:

	* testsuite/gas/riscv/dis-arch-override.s: New arch override tests.
	* testsuite/gas/riscv/dis-arch-override-1.d: Likewise.
	* testsuite/gas/riscv/dis-arch-override-2.d: Likewise.
	* testsuite/gas/riscv/dis-arch-override-3.d: Likewise.

opcodes/ChangeLog:

	* riscv-dis.c (is_custom_arch) New.
	(update_riscv_dis_xlen): Update XLEN precedence rules.
	(set_default_riscv_dis_options): Initialize "arch".
	(parse_riscv_dis_option): Add the "arch" option.
	(riscv_get_map_state): Ignore ISA string from mapping symbols if
	custom "arch" is specified.
	(riscv_get_disassembler): Update the architecture depending on the
	custom "arch" option.
	(riscv_option_arg_t) Add RISCV_OPTION_ARG_ARCH.
	(riscv_options): Add the "arch" option.
	(disassembler_options_riscv): Add the "arch" option.
  • Loading branch information
a4lg committed Aug 3, 2023
1 parent 83f8214 commit 8bfb149
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 3 deletions.
13 changes: 13 additions & 0 deletions gas/testsuite/gas/riscv/dis-arch-override-1.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#as: -march=rv64imfd_zbb
#source: dis-arch-override.s
#objdump: -d

.*:[ ]+file format .*

Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+00c5f053[ ]+fadd\.s[ ]+ft0,fa1,fa2
[ ]+[0-9a-f]+:[ ]+02c5f053[ ]+fadd\.d[ ]+ft0,fa1,fa2
[ ]+[0-9a-f]+:[ ]+30102573[ ]+csrr[ ]+a0,misa
[ ]+[0-9a-f]+:[ ]+0805c53b[ ]+zext\.h[ ]+a0,a1
13 changes: 13 additions & 0 deletions gas/testsuite/gas/riscv/dis-arch-override-2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#as: -march=rv64imfd_zbb
#source: dis-arch-override.s
#objdump: -d -M arch=rv32im_zfinx_zbkb

.*:[ ]+file format .*

Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+00c5f053[ ]+fadd\.s[ ]+zero,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5f053[ ]+\.insn[ ]+4, 0x02c5f053
[ ]+[0-9a-f]+:[ ]+30102573[ ]+csrr[ ]+a0,misa
[ ]+[0-9a-f]+:[ ]+0805c53b[ ]+packw[ ]+a0,a1,zero
13 changes: 13 additions & 0 deletions gas/testsuite/gas/riscv/dis-arch-override-3.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#as: -march=rv64imfd_zbb
#source: dis-arch-override.s
#objdump: -d -m riscv -M arch=rv32im_zfinx_zbkb,numeric

.*:[ ]+file format .*

Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+00c5f053[ ]+fadd\.s[ ]+x0,x11,x12
[ ]+[0-9a-f]+:[ ]+02c5f053[ ]+\.insn[ ]+4, 0x02c5f053
[ ]+[0-9a-f]+:[ ]+30102573[ ]+csrr[ ]+x10,misa
[ ]+[0-9a-f]+:[ ]+0805c53b[ ]+\.insn[ ]+4, 0x0805c53b
45 changes: 45 additions & 0 deletions gas/testsuite/gas/riscv/dis-arch-override.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Assembler configuration:
# -march=rv64imfd_zbb
# Disassembler configurations:
# Test 1: -d
# Test 2: -d -M arch=rv32im_zfinx_zbkb
# Test 3: -d -m riscv -M arch=rv32im_zfinx_zbkb,numeric

target:
# Assembler : fadd.s (F)
# Disassembler (test 2/3) : fadd.s (Zfinx)
# Test that all three operands point to GPRs.
fadd.s ft0, fa1, fa2

# Assembler : fadd.d (D)
# Disassembler (test 2/3) : (invalid)
# On disassembler option on test 2, Zdinx is not present. So,
# it should be disassembled as an invalid instruction.
fadd.d ft0, fa1, fa2

# Assembler : csrr (Zicsr)
# Disassembler (test 2/3) : csrr (Zicsr)
# When assembling, Zicsr is implied by F. When disassembling,
# Zicsr is implied by Zfinx. On both cases, csrr should be
# disassembled as csrr.
csrr a0, misa

# Assembler : zext.h (Zbb)
# Disassembler (test 2) : packw (Zbkb)
# Disassembler (test 3) : (invalid)
# Since zext.h specialized instruction does not exist in Zbkb
# and we disassemble the output with Zbkb, this instruction
# should be disassembled as a packw instruction (on RV64).
#
# We specify arch=rv32im_zfinx_zbkb on disassembling on test
# 2 and 3. But, XLEN part of the ISA string is effective
# only if XLEN-neutral machine is specified by `-m riscv' option
# (because we are disassembling 64-bit RISC-V ELF file, BFD
# architecture is set to `riscv:rv64' unless `-m' option
# is specified).
#
# As a result, test 3 (with `-m riscv' option) disassembles with
# RV32 but test 2 (without it) does with RV64.
# It changes the result of disassembling since packw instruction
# is invalid on RV32.
zext.h a0, a1
30 changes: 27 additions & 3 deletions opcodes/riscv-dis.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
/* Default architecture string (if not available). */
static const char *const initial_default_arch = "rv64gc";

/* If set, a custom architecture string is specified. */
static bool is_custom_arch = false;

/* Current XLEN for the disassembler. */
static unsigned xlen = 0;

Expand Down Expand Up @@ -197,8 +200,10 @@ update_riscv_dis_xlen (struct disassemble_info *info)
This is only effective if XLEN-specific BFD machine architecture is
chosen. If XLEN-neutral (like riscv), BFD machine architecture is
ignored on XLEN selection.
2. Non-default RISC-V architecture string set by either an ELF
attribute or a mapping symbol with ISA string.
2. Non-default RISC-V architecture string set by either:
a. -M arch=... option (GDB: set disassembler-options arch=...),
b. A mapping symbol with ISA string or
c. An ELF attribute
3. ELF class in dummy ELF header. */
if (xlen_by_mach != 0)
xlen = xlen_by_mach;
Expand Down Expand Up @@ -308,6 +313,7 @@ set_default_riscv_dis_options (void)
no_aliases = false;
is_numeric = false;
is_custom_priv_spec = false;
is_custom_arch = false;
}

/* Parse RISC-V disassembler option (without arguments). */
Expand Down Expand Up @@ -369,6 +375,11 @@ parse_riscv_dis_option (const char *option)
priv_spec = priv_spec_new;
}
}
else if (strcmp (option, "arch") == 0)
{
is_custom_arch = true;
update_riscv_dis_arch (&dis_arch_context_override, value);
}
else
{
/* xgettext:c-format */
Expand Down Expand Up @@ -1082,6 +1093,9 @@ riscv_get_map_state (int n,
*state = newstate;
if (newstate == MAP_INSN && update)
{
/* Skip if a custom architecture is specified. */
if (is_custom_arch)
return true;
if (arch)
{
/* Override the architecture. */
Expand Down Expand Up @@ -1408,7 +1422,10 @@ riscv_get_disassembler (bfd *abfd)
}
}

update_riscv_dis_arch (&dis_arch_context_default, default_arch);
if (is_custom_arch)
set_riscv_dis_arch_context (&dis_arch_context_default, default_arch);
else
update_riscv_dis_arch (&dis_arch_context_default, default_arch);
return print_insn_riscv;
}

Expand Down Expand Up @@ -1459,6 +1476,7 @@ riscv_symbol_is_valid (asymbol * sym,
typedef enum
{
RISCV_OPTION_ARG_NONE = -1,
RISCV_OPTION_ARG_ARCH,
RISCV_OPTION_ARG_PRIV_SPEC,

RISCV_OPTION_ARG_COUNT
Expand All @@ -1476,6 +1494,9 @@ static struct
{ "numeric",
N_("Print numeric register names, rather than ABI names."),
RISCV_OPTION_ARG_NONE },
{ "arch=",
N_("Disassemble using specified ISA and extensions."),
RISCV_OPTION_ARG_ARCH },
{ "no-aliases",
N_("Disassemble only into canonical instructions."),
RISCV_OPTION_ARG_NONE },
Expand Down Expand Up @@ -1503,6 +1524,9 @@ disassembler_options_riscv (void)

args = XNEWVEC (disasm_option_arg_t, num_args + 1);

args[RISCV_OPTION_ARG_ARCH].name = "ARCH";
args[RISCV_OPTION_ARG_ARCH].values = NULL;

args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC";
priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_CLASS_NONE - 1;
args[RISCV_OPTION_ARG_PRIV_SPEC].values
Expand Down

0 comments on commit 8bfb149

Please sign in to comment.