Skip to content

Commit

Permalink
RISC-V: Make ELF `priv-spec' overridable
Browse files Browse the repository at this point in the history
`priv-spec' disassembler option only allowed a privileged specification
matching the one that is specified on the ELF attributes.  This commit
removes this restriction (making privileged specification for the
disassembler overridable) for programs which uses future privileged
specification than the toolchain (e.g. OpenSBI).

opcodes/ChangeLog:

	* riscv-dis.c (init_riscv_dis_state_for_arch_and_options):
	Use `priv_spec' instead of `default_priv_spec'.
	(print_insn_args): Likewise.
	(set_default_riscv_dis_options): Add initialization.
	(riscv_get_disassembler): Likewise.
	(parse_riscv_dis_option): Make ELF `priv-spec' overridable.
	(parse_riscv_dis_options): Track custom `priv-spec' option.
  • Loading branch information
a4lg committed Jul 20, 2022
1 parent 7ad0299 commit 4866ccd
Showing 1 changed file with 25 additions and 22 deletions.
47 changes: 25 additions & 22 deletions opcodes/riscv-dis.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ static bool is_numeric = false;
/* Reset when either arch or option is changed. */
static bool is_init_csr = false;

/* Current privileged specification version. */
static enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE;

/* If set, a custom privileged specification is specified. */
static bool is_custom_priv_spec = false;


/* Initialization (for arch and options). */

Expand All @@ -102,25 +108,25 @@ static void
init_riscv_dis_state_for_arch_and_options (void)
{
static bool init = false;
static enum riscv_spec_class prev_default_priv_spec;
static enum riscv_spec_class prev_priv_spec;
if (!init)
{
set_default_riscv_dis_options ();
build_riscv_opcodes_hash_table ();
init = true;
/* Save initial options. */
prev_default_priv_spec = default_priv_spec;
prev_priv_spec = priv_spec;
}
riscv_gpr_names = is_numeric ? riscv_gpr_names_numeric : riscv_gpr_names_abi;
riscv_fpr_names = is_numeric ? riscv_fpr_names_numeric : riscv_fpr_names_abi;
/* If arch has Zfinx extension, use GPR to disassemble. */
if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
riscv_fpr_names = riscv_gpr_names;
/* Reset CSR hashtable if either `arch' or `priv-spec' option changes. */
if (is_arch_changed || prev_default_priv_spec != default_priv_spec)
if (is_arch_changed || prev_priv_spec != priv_spec)
is_init_csr = false;
/* Save previous options and mark them "unchanged". */
prev_default_priv_spec = default_priv_spec;
prev_priv_spec = priv_spec;
is_arch_changed = false;
}

Expand All @@ -129,6 +135,7 @@ set_default_riscv_dis_options (void)
{
no_aliases = false;
is_numeric = false;
is_custom_priv_spec = false;
}

/* Update current architecture string
Expand Down Expand Up @@ -206,22 +213,13 @@ parse_riscv_dis_option (const char *option)
value = equal + 1;
if (strcmp (option, "priv-spec") == 0)
{
enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE;
const char *name = NULL;

RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec);
if (priv_spec == PRIV_SPEC_CLASS_NONE)
is_custom_priv_spec = true;
enum riscv_spec_class priv_spec_new = PRIV_SPEC_CLASS_NONE;
RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec_new);
if (priv_spec_new == PRIV_SPEC_CLASS_NONE)
opcodes_error_handler (_("unknown privileged spec set by %s=%s"),
option, value);
else if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
default_priv_spec = priv_spec;
else if (default_priv_spec != priv_spec)
{
RISCV_GET_PRIV_SPEC_NAME (name, default_priv_spec);
opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, "
"the elf privilege attribute is %s"),
option, value, name);
}
priv_spec = priv_spec_new;
}
else
{
Expand All @@ -234,6 +232,7 @@ static void
parse_riscv_dis_options (const char *opts_in)
{
char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
bool prev_is_custom_priv_spec = is_custom_priv_spec;

set_default_riscv_dis_options ();

Expand All @@ -245,6 +244,8 @@ parse_riscv_dis_options (const char *opts_in)
}

free (opts);
if (prev_is_custom_priv_spec && !is_custom_priv_spec)
priv_spec = default_priv_spec;
}

/* Print one argument from an array. */
Expand Down Expand Up @@ -610,15 +611,15 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
riscv_csr_hash[i] = NULL;

/* Set to the newest privileged version. */
if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
if (priv_spec == PRIV_SPEC_CLASS_NONE)
priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;

#define DECLARE_CSR(name, num, class, define_version, abort_version) \
if (riscv_csr_hash[num] == NULL \
&& ((define_version == PRIV_SPEC_CLASS_NONE \
&& abort_version == PRIV_SPEC_CLASS_NONE) \
|| (default_priv_spec >= define_version \
&& default_priv_spec < abort_version))) \
|| (priv_spec >= define_version \
&& priv_spec < abort_version))) \
riscv_csr_hash[num] = #name;
#define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \
DECLARE_CSR (name, num, class, define_version, abort_version)
Expand Down Expand Up @@ -1156,6 +1157,8 @@ riscv_get_disassembler (bfd *abfd)

if (update_riscv_dis_default_arch (default_arch_next))
update_riscv_dis_current_arch (default_arch_next);
if (!is_custom_priv_spec)
priv_spec = default_priv_spec;
init_riscv_dis_state_for_arch_and_options ();
return print_insn_riscv;
}
Expand Down

0 comments on commit 4866ccd

Please sign in to comment.