[RFC PATCH 4/5] RISC-V: Mapping symbols with ISA string on disassembler
Tsukasa OI
research_trasio@irq.a4lg.com
Thu Aug 11 07:00:52 GMT 2022
The mapping symbols with ISA string is proposed to deal with so called
"ifunc issue". It enables disassembling a certain range of the code with
a different architecture than the rest, even if conflicting. This is useful
when there's "optimized" implementation is available but dynamically
switched only if a certain extension is available.
This commit implements the disassembler support to parse mapping symbols
with ISA string.
[1] Proposal: Extend .option directive for control enabled extensions on
specific code region,
https://github.com/riscv-non-isa/riscv-asm-manual/pull/67
[2] Proposal: Add mapping symbol,
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/196
This commit is based on Nelson Chu's proposal "RISC-V: Output mapping
symbols with ISA string once .option arch is used." but heavily modified to
reflect the intent of Kito's original proposal. It is also made smarter so
that it no longer requires MAP_INSN_ARCH.
gas/ChangeLog:
* testsuite/gas/riscv/option-arch-01a.d: Reflect the disassembler
support of mapping symbols with ISA string.
opcodes/ChangeLog:
* riscv-dis.c (initial_default_arch) Default architecture string if
no ELF attributes are available.
(default_arch): A copy of the default architecture string.
(is_arch_mapping): New variable to keep track of whether the current
architecture is deviced from a mapping symbol.
(riscv_disassemble_insn): Update FPR names when a mapping symbol
with ISA string is encountered.
(riscv_get_map_state): Support mapping symbols with ISA string.
Use `is_arch_mapping' to stop repeatedly parsing the default
architecture.
(riscv_get_disassembler): Safer architecture string handling.
Copy the string to switch to the default while disassembling.
---
gas/testsuite/gas/riscv/option-arch-01a.d | 2 +-
opcodes/riscv-dis.c | 44 ++++++++++++++++++++---
2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/gas/testsuite/gas/riscv/option-arch-01a.d b/gas/testsuite/gas/riscv/option-arch-01a.d
index aed4ca8e4d9..b9c260c9949 100644
--- a/gas/testsuite/gas/riscv/option-arch-01a.d
+++ b/gas/testsuite/gas/riscv/option-arch-01a.d
@@ -10,5 +10,5 @@ Disassembly of section .text:
0+000 <.text>:
[ ]+[0-9a-f]+:[ ]+952e[ ]+add[ ]+a0,a0,a1
[ ]+[0-9a-f]+:[ ]+00b50533[ ]+add[ ]+a0,a0,a1
-[ ]+[0-9a-f]+:[ ]+00302573[ ]+csrr[ ]+a0,fcsr
+[ ]+[0-9a-f]+:[ ]+00302573[ ]+frcsr[ ]+a0
#...
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 4b7b17235ee..c029c65827c 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -32,6 +32,16 @@
#include <stdint.h>
#include <ctype.h>
+/* Default architecture string (if not available). */
+static const char *initial_default_arch = "rv64gc";
+
+/* Default architecture string
+ (as specified by the ELF attributes or `initial_default_arch'). */
+static const char *default_arch = NULL;
+
+/* True if the architecture is set from a mapping symbol. */
+static bool is_arch_mapping = false;
+
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;
@@ -638,8 +648,12 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
}
/* If arch has ZFINX flags, use gpr for disassemble. */
- if(riscv_subset_supports (&riscv_rps_dis, "zfinx"))
+ if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
riscv_fpr_names = riscv_gpr_names;
+ else
+ riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi
+ ? riscv_fpr_names_abi
+ : riscv_fpr_names_numeric;
for (; op->name; op++)
{
@@ -750,8 +764,23 @@ riscv_get_map_state (int n,
return false;
name = bfd_asymbol_name(info->symtab[n]);
- if (strncmp (name, "$x", 2) == 0)
+ if (strncmp (name, "$xrv", 4) == 0)
+ {
*state = MAP_INSN;
+ riscv_release_subset_list (&riscv_subsets);
+ riscv_parse_subset (&riscv_rps_dis, name + 2);
+ is_arch_mapping = true;
+ }
+ else if (strcmp (name, "$x") == 0)
+ {
+ *state = MAP_INSN;
+ if (is_arch_mapping)
+ {
+ riscv_release_subset_list (&riscv_subsets);
+ riscv_parse_subset (&riscv_rps_dis, default_arch);
+ is_arch_mapping = false;
+ }
+ }
else if (strcmp (name, "$d") == 0)
*state = MAP_DATA;
else
@@ -1000,7 +1029,7 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
disassembler_ftype
riscv_get_disassembler (bfd *abfd)
{
- const char *default_arch = "rv64gc";
+ const char *default_arch_next = initial_default_arch;
if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
@@ -1015,12 +1044,19 @@ riscv_get_disassembler (bfd *abfd)
attr[Tag_b].i,
attr[Tag_c].i,
&default_priv_spec);
- default_arch = attr[Tag_RISCV_arch].s;
+ default_arch_next = attr[Tag_RISCV_arch].s;
+ /* For ELF files with (somehow) no architecture string
+ in the attributes, use the default value. */
+ if (!default_arch_next)
+ default_arch_next = initial_default_arch;
}
}
+ free ((void *) default_arch);
+ default_arch = xstrdup (default_arch_next);
riscv_release_subset_list (&riscv_subsets);
riscv_parse_subset (&riscv_rps_dis, default_arch);
+ is_arch_mapping = false;
return print_insn_riscv;
}
--
2.34.1
More information about the Binutils
mailing list