From 3f61a38b5e81569357bd15fbcf7fcb1dab3ee2db Mon Sep 17 00:00:00 2001 From: Nelson Chu Date: Thu, 6 Feb 2025 21:47:37 +0800 Subject: [PATCH] RISC-V: Move all global static target stuff into private data for disassembler. I got a request said that the JDK multi-thread compiler may be broken if two or more threads are trying to print/disassemble stuff, and filling the disassemble_info, setting callbacks, and grabbing the function pointer to disasm at the same time. Since such as the target global static stuff, including subset of extensions and mapping symbol stuff, seems to only be one globally. Ideally, for dis-assembler, all global static target stuff should/can be better to be defined into the target private data, since they are target-dependency. opcodes/ * riscv-dis.c: Moved all global static target-dependency stuff into riscv_private_data, including architecture and mapping symbol stuff. (set_default_riscv_dis_options): Updated since global static target- dependency stuff are moved into riscv_private_data. (parse_riscv_dis_option_without_args): Likewise. (parse_riscv_dis_option): Likewise. (parse_riscv_dis_options): Likewise. (maybe_print_address): Likewise. (print_reg_list): Likewise. (riscv_get_spimm): Likewise. (print_insn_args): Likewise. (riscv_disassemble_insn): Likewise. (riscv_update_map_state): Likewise. (riscv_search_mapping_symbol): Likewise. (riscv_data_length): Likewise. (print_insn_riscv): Likewise. Call the riscv_init_disasm_info before parsing any disassembler options, since the related stuff are moved into riscv_private_data. (riscv_init_disasm_info): Likewise. Parse and set the architecture string and privileged spec version since riscv_get_disassembler is no longer needed. (riscv_get_disassembler): Removed. (disassemble_free_riscv): Only free the subset_list if riscv_private_data exsits. * disassemble.c (disassembler): Since riscv_get_disassembler is removed, call to print_insn_riscv. * disassemble.h: Removed extern riscv_get_disassembler. --- opcodes/disassemble.c | 2 +- opcodes/disassemble.h | 1 - opcodes/riscv-dis.c | 336 ++++++++++++++++++++++-------------------- 3 files changed, 178 insertions(+), 161 deletions(-) diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 98de1a772f9..53ee1ecf38b 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -382,7 +382,7 @@ disassembler (enum bfd_architecture a, #endif #ifdef ARCH_riscv case bfd_arch_riscv: - disassemble = riscv_get_disassembler (abfd); + disassemble = print_insn_riscv; break; #endif #ifdef ARCH_rl78 diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h index 5fcd45ea5ae..a6c7d8fb756 100644 --- a/opcodes/disassemble.h +++ b/opcodes/disassemble.h @@ -102,7 +102,6 @@ extern int print_insn_loongarch (bfd_vma, disassemble_info *); extern disassembler_ftype csky_get_disassembler (bfd *); extern disassembler_ftype rl78_get_disassembler (bfd *); -extern disassembler_ftype riscv_get_disassembler (bfd *); extern void disassemble_free_riscv (disassemble_info *); extern void disassemble_free_powerpc (disassemble_info *); diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 367004d3341..d67b2c2aaf0 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -37,26 +37,6 @@ disassemble_info::fprintf_func which is for unstyled output. */ #define fprintf_func please_use_fprintf_styled_func_instead -/* Current XLEN for the disassembler. */ -static unsigned xlen = 0; - -/* Default ISA specification version (constant as of now). */ -static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; - -/* Default privileged specification - (as specified by the ELF attributes or the `priv-spec' option). */ -static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE; - -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; @@ -64,50 +44,57 @@ struct riscv_private_data bfd_vma hi_addr[OP_MASK_RD + 1]; bool to_print_addr; bool has_gp; + /* Current XLEN for the disassembler. */ + unsigned xlen; + /* Default ISA specification version. */ + enum riscv_spec_class default_isa_spec; + /* Default privileged specification. */ + enum riscv_spec_class default_priv_spec; + /* Used for architecture parser. */ + riscv_parse_subset_t riscv_rps_dis; + /* Used for mapping symbols. */ + int last_map_symbol; + bfd_vma last_stop_offset; + bfd_vma last_map_symbol_boundary; + enum riscv_seg_mstate last_map_state; + asection *last_map_section; + /* Register names as used by the disassembler. */ + const char (*riscv_gpr_names)[NRC]; + const char (*riscv_fpr_names)[NRC]; + /* If set, disassemble as most general instruction. */ + bool no_aliases; + /* If set, disassemble without checking architectire string, just like what + we did at the beginning. */ + bool all_ext; }; -/* Used for mapping symbols. */ -static int last_map_symbol = -1; -static bfd_vma last_stop_offset = 0; -static bfd_vma last_map_symbol_boundary = 0; -static enum riscv_seg_mstate last_map_state = MAP_NONE; -static asection *last_map_section = NULL; - -/* Register names as used by the disassembler. */ -static const char (*riscv_gpr_names)[NRC]; -static const char (*riscv_fpr_names)[NRC]; - -/* If set, disassemble as most general instruction. */ -static bool no_aliases = false; - -/* If set, disassemble without checking architectire string, just like what - we did at the beginning. */ -static bool all_ext = false; - /* Set default RISC-V disassembler options. */ static void -set_default_riscv_dis_options (void) +set_default_riscv_dis_options (struct disassemble_info *info) { - riscv_gpr_names = riscv_gpr_names_abi; - riscv_fpr_names = riscv_fpr_names_abi; - no_aliases = false; + struct riscv_private_data *pd = info->private_data; + pd->riscv_gpr_names = riscv_gpr_names_abi; + pd->riscv_fpr_names = riscv_fpr_names_abi; + pd->no_aliases = false; } /* Parse RISC-V disassembler option (without arguments). */ static bool -parse_riscv_dis_option_without_args (const char *option) +parse_riscv_dis_option_without_args (const char *option, + struct disassemble_info *info) { + struct riscv_private_data *pd = info->private_data; if (strcmp (option, "no-aliases") == 0) - no_aliases = true; + pd->no_aliases = true; else if (strcmp (option, "numeric") == 0) { - riscv_gpr_names = riscv_gpr_names_numeric; - riscv_fpr_names = riscv_fpr_names_numeric; + pd->riscv_gpr_names = riscv_gpr_names_numeric; + pd->riscv_fpr_names = riscv_fpr_names_numeric; } else if (strcmp (option, "max") == 0) - all_ext = true; + pd->all_ext = true; else return false; return true; @@ -116,11 +103,11 @@ parse_riscv_dis_option_without_args (const char *option) /* Parse RISC-V disassembler option (possibly with arguments). */ static void -parse_riscv_dis_option (const char *option) +parse_riscv_dis_option (const char *option, struct disassemble_info *info) { char *equal, *value; - if (parse_riscv_dis_option_without_args (option)) + if (parse_riscv_dis_option_without_args (option, info)) return; equal = strchr (option, '='); @@ -144,6 +131,7 @@ parse_riscv_dis_option (const char *option) value = equal + 1; if (strcmp (option, "priv-spec") == 0) { + struct riscv_private_data *pd = info->private_data; enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE; const char *name = NULL; @@ -151,11 +139,11 @@ parse_riscv_dis_option (const char *option) if (priv_spec == 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) + else if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE) + pd->default_priv_spec = priv_spec; + else if (pd->default_priv_spec != priv_spec) { - RISCV_GET_PRIV_SPEC_NAME (name, default_priv_spec); + RISCV_GET_PRIV_SPEC_NAME (name, pd->default_priv_spec); opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, " "the elf privilege attribute is %s"), option, value, name); @@ -171,17 +159,17 @@ parse_riscv_dis_option (const char *option) /* Parse RISC-V disassembler options. */ static void -parse_riscv_dis_options (const char *opts_in) +parse_riscv_dis_options (const char *opts_in, struct disassemble_info *info) { char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts; - set_default_riscv_dis_options (); + set_default_riscv_dis_options (info); for ( ; opt_end != NULL; opt = opt_end + 1) { if ((opt_end = strchr (opt, ',')) != NULL) *opt_end = 0; - parse_riscv_dis_option (opt); + parse_riscv_dis_option (opt, info); } free (opts); @@ -221,7 +209,7 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset, pd->print_addr = (bfd_vma)(int32_t) pd->print_addr; /* Fit into a 32-bit value on RV32. */ - if (xlen == 32) + if (pd->xlen == 32) pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr; } @@ -230,60 +218,61 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset, static void print_reg_list (disassemble_info *info, insn_t l) { - bool numeric = riscv_gpr_names == riscv_gpr_names_numeric; + struct riscv_private_data *pd = info->private_data; + bool numeric = pd->riscv_gpr_names == riscv_gpr_names_numeric; unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l); unsigned r_start = numeric ? X_S2 : X_S0; info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[X_RA]); + "%s", pd->riscv_gpr_names[X_RA]); if (reg_list == 5) { info->fprintf_styled_func (info->stream, dis_style_text, ","); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[X_S0]); + "%s", pd->riscv_gpr_names[X_S0]); } else if (reg_list == 6 || (numeric && reg_list > 6)) { info->fprintf_styled_func (info->stream, dis_style_text, ","); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[X_S0]); + "%s", pd->riscv_gpr_names[X_S0]); info->fprintf_styled_func (info->stream, dis_style_text, "-"); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[X_S1]); + "%s", pd->riscv_gpr_names[X_S1]); } if (reg_list == 15) { info->fprintf_styled_func (info->stream, dis_style_text, ","); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[r_start]); + "%s", pd->riscv_gpr_names[r_start]); info->fprintf_styled_func (info->stream, dis_style_text, "-"); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[X_S11]); + "%s", pd->riscv_gpr_names[X_S11]); } else if (reg_list == 7 && numeric) { info->fprintf_styled_func (info->stream, dis_style_text, ","); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[X_S2]); + "%s", pd->riscv_gpr_names[X_S2]); } else if (reg_list > 6) { info->fprintf_styled_func (info->stream, dis_style_text, ","); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[r_start]); + "%s", pd->riscv_gpr_names[r_start]); info->fprintf_styled_func (info->stream, dis_style_text, "-"); info->fprintf_styled_func (info->stream, dis_style_register, - "%s", riscv_gpr_names[reg_list + 11]); + "%s", pd->riscv_gpr_names[reg_list + 11]); } } /* Get Zcmp sp adjustment immediate. */ static int -riscv_get_spimm (insn_t l) +riscv_get_spimm (insn_t l, int xlen) { - int spimm = riscv_get_sp_base(l, *riscv_rps_dis.xlen); + int spimm = riscv_get_sp_base(l, xlen); spimm += EXTRACT_ZCMP_SPIMM (l); if (((l ^ MATCH_CM_PUSH) & MASK_CM_PUSH) == 0) spimm *= -1; @@ -326,24 +315,24 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info case 's': /* RS1 x8-x15. */ case 'w': /* RS1 x8-x15. */ print (info->stream, dis_style_register, "%s", - riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]); + pd->riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]); break; case 't': /* RS2 x8-x15. */ case 'x': /* RS2 x8-x15. */ print (info->stream, dis_style_register, "%s", - riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); + pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); break; case 'U': /* RS1, constrained to equal RD. */ print (info->stream, dis_style_register, - "%s", riscv_gpr_names[rd]); + "%s", pd->riscv_gpr_names[rd]); break; case 'c': /* RS1, constrained to equal sp. */ print (info->stream, dis_style_register, "%s", - riscv_gpr_names[X_SP]); + pd->riscv_gpr_names[X_SP]); break; case 'V': /* RS2 */ print (info->stream, dis_style_register, "%s", - riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]); + pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]); break; case 'o': case 'j': @@ -409,11 +398,11 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info break; case 'T': /* Floating-point RS2. */ print (info->stream, dis_style_register, "%s", - riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]); + pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]); break; case 'D': /* Floating-point RS2 x8-x15. */ print (info->stream, dis_style_register, "%s", - riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); + pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); break; } break; @@ -429,7 +418,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info case 'e': if (!EXTRACT_OPERAND (VWD, l)) print (info->stream, dis_style_register, "%s", - riscv_gpr_names[0]); + pd->riscv_gpr_names[0]); else print (info->stream, dis_style_register, "%s", riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]); @@ -520,12 +509,13 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info case 's': if ((l & MASK_JALR) == MATCH_JALR) maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0); - print (info->stream, dis_style_register, "%s", riscv_gpr_names[rs1]); + print (info->stream, dis_style_register, "%s", + pd->riscv_gpr_names[rs1]); break; case 't': print (info->stream, dis_style_register, "%s", - riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]); + pd->riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]); break; case 'u': @@ -585,7 +575,8 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l); else if ((l & MASK_C_LUI) == MATCH_C_LUI) pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l); - print (info->stream, dis_style_register, "%s", riscv_gpr_names[rd]); + print (info->stream, dis_style_register, "%s", + pd->riscv_gpr_names[rd]); break; case 'y': @@ -594,7 +585,8 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info break; case 'z': - print (info->stream, dis_style_register, "%s", riscv_gpr_names[0]); + print (info->stream, dis_style_register, "%s", + pd->riscv_gpr_names[0]); break; case '>': @@ -609,21 +601,23 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info case 'S': case 'U': - print (info->stream, dis_style_register, "%s", riscv_fpr_names[rs1]); + print (info->stream, dis_style_register, "%s", + pd->riscv_fpr_names[rs1]); break; case 'T': print (info->stream, dis_style_register, "%s", - riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]); + pd->riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]); break; case 'D': - print (info->stream, dis_style_register, "%s", riscv_fpr_names[rd]); + print (info->stream, dis_style_register, "%s", + pd->riscv_fpr_names[rd]); break; case 'R': print (info->stream, dis_style_register, "%s", - riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]); + pd->riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]); break; case 'E': @@ -639,15 +633,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 (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE) + pd->default_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))) \ + || (pd->default_priv_spec >= define_version \ + && pd->default_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) @@ -656,7 +650,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info } if (riscv_csr_hash[csr] != NULL) - if (riscv_subset_supports (&riscv_rps_dis, "xtheadvector") + if (riscv_subset_supports (&pd->riscv_rps_dis, "xtheadvector") && (csr == CSR_VSTART || csr == CSR_VXSAT || csr == CSR_VXRM @@ -716,11 +710,11 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info { case '1': print (info->stream, dis_style_register, "%s", - riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]); + pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]); break; case '2': print (info->stream, dis_style_register, "%s", - riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]); + pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]); break; case 'b': print (info->stream, dis_style_immediate, "%d", @@ -735,7 +729,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info break; case 'p': print (info->stream, dis_style_immediate, "%d", - riscv_get_spimm (l)); + riscv_get_spimm (l, pd->xlen)); break; case 'i': case 'I': @@ -947,21 +941,21 @@ riscv_disassemble_insn (bfd_vma memaddr, { /* If XLEN is not known, get its value from the ELF class. */ if (info->mach == bfd_mach_riscv64) - xlen = 64; + pd->xlen = 64; else if (info->mach == bfd_mach_riscv32) - xlen = 32; + pd->xlen = 32; else if (info->section != NULL) { Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); - xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; + pd->xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; } /* If arch has the Zfinx extension, replace FPR with GPR. */ - if (riscv_subset_supports (&riscv_rps_dis, "zfinx")) - riscv_fpr_names = riscv_gpr_names; + if (riscv_subset_supports (&pd->riscv_rps_dis, "zfinx")) + pd->riscv_fpr_names = pd->riscv_gpr_names; else - riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi ? - riscv_fpr_names_abi : riscv_fpr_names_numeric; + pd->riscv_fpr_names = pd->riscv_gpr_names == riscv_gpr_names_abi ? + riscv_fpr_names_abi : riscv_fpr_names_numeric; for (; op->name; op++) { @@ -972,14 +966,16 @@ riscv_disassemble_insn (bfd_vma memaddr, if (! (op->match_func) (op, word)) continue; /* Is this a pseudo-instruction and may we print it as such? */ - if (no_aliases && (op->pinfo & INSN_ALIAS)) + if (pd->no_aliases && (op->pinfo & INSN_ALIAS)) continue; /* Is this instruction restricted to a certain value of XLEN? */ - if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen)) + if ((op->xlen_requirement != 0) + && (op->xlen_requirement != pd->xlen)) continue; /* Is this instruction supported by the current architecture? */ - if (!all_ext - && !riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class)) + if (!pd->all_ext + && !riscv_multi_subset_supports (&pd->riscv_rps_dis, + op->insn_class)) continue; /* It's a match. */ @@ -1060,6 +1056,7 @@ riscv_update_map_state (int n, enum riscv_seg_mstate *state, struct disassemble_info *info) { + struct riscv_private_data *pd = info->private_data; const char *name; /* If the symbol is in a different section, ignore it. */ @@ -1075,7 +1072,7 @@ riscv_update_map_state (int n, else if (strncmp (name, "$xrv", 4) == 0) { *state = MAP_INSN; - riscv_release_subset_list (&riscv_subsets); + riscv_release_subset_list (pd->riscv_rps_dis.subset_list); /* ISA mapping string may be numbered, suffixed with '.n'. Do not consider this as part of the ISA string. */ @@ -1086,11 +1083,11 @@ riscv_update_map_state (int n, char *name_substr = xmalloc (suffix_index + 1); strncpy (name_substr, name, suffix_index); name_substr[suffix_index] = '\0'; - riscv_parse_subset (&riscv_rps_dis, name_substr + 2); + riscv_parse_subset (&pd->riscv_rps_dis, name_substr + 2); free (name_substr); } else - riscv_parse_subset (&riscv_rps_dis, name + 2); + riscv_parse_subset (&pd->riscv_rps_dis, name + 2); } } @@ -1119,6 +1116,7 @@ static enum riscv_seg_mstate riscv_search_mapping_symbol (bfd_vma memaddr, struct disassemble_info *info) { + struct riscv_private_data *pd = info->private_data; enum riscv_seg_mstate mstate; bool from_last_map_symbol; bool found = false; @@ -1127,11 +1125,11 @@ riscv_search_mapping_symbol (bfd_vma memaddr, /* Return the last map state if the address is still within the range of the last mapping symbol. */ - if (last_map_section == info->section - && (memaddr < last_map_symbol_boundary)) - return last_map_state; + if (pd->last_map_section == info->section + && (memaddr < pd->last_map_symbol_boundary)) + return pd->last_map_state; - last_map_section = info->section; + pd->last_map_section = info->section; /* Decide whether to print the data or instruction by default, in case we can not find the corresponding mapping symbols. */ @@ -1147,17 +1145,17 @@ riscv_search_mapping_symbol (bfd_vma memaddr, /* Reset the last_map_symbol if we start to dump a new section. */ if (memaddr <= 0) - last_map_symbol = -1; + pd->last_map_symbol = -1; /* If the last stop offset is different from the current one, then don't use the last_map_symbol to search. We usually reset the info->stop_offset when handling a new section. */ - from_last_map_symbol = (last_map_symbol >= 0 - && info->stop_offset == last_stop_offset); + from_last_map_symbol = (pd->last_map_symbol >= 0 + && info->stop_offset == pd->last_stop_offset); /* Start scanning from wherever we finished last time, or the start of the function. */ - n = from_last_map_symbol ? last_map_symbol : info->symtab_pos + 1; + n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos + 1; /* Find the suitable mapping symbol to dump. */ for (; n < info->symtab_size; n++) @@ -1182,7 +1180,7 @@ riscv_search_mapping_symbol (bfd_vma memaddr, can pick up a text mapping symbol of a preceeding section. */ if (!found) { - n = from_last_map_symbol ? last_map_symbol : info->symtab_pos; + n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos; for (; n >= 0; n--) { @@ -1221,7 +1219,7 @@ riscv_search_mapping_symbol (bfd_vma memaddr, /* The next mapping symbol has been found, and it represents the boundary of this mapping symbol. */ found_next = true; - last_map_symbol_boundary = addr; + pd->last_map_symbol_boundary = addr; break; } } @@ -1229,12 +1227,13 @@ riscv_search_mapping_symbol (bfd_vma memaddr, /* No further mapping symbol has been found, indicating that the boundary of the current mapping symbol is the end of this section. */ if (!found_next) - last_map_symbol_boundary = info->section->vma + info->section->size; + pd->last_map_symbol_boundary = info->section->vma + + info->section->size; } /* Save the information for next use. */ - last_map_symbol = symbol; - last_stop_offset = info->stop_offset; + pd->last_map_symbol = symbol; + pd->last_stop_offset = info->stop_offset; return mstate; } @@ -1245,17 +1244,18 @@ static bfd_vma riscv_data_length (bfd_vma memaddr, disassemble_info *info) { + struct riscv_private_data *pd = info->private_data; bfd_vma length; bool found = false; length = 4; if (info->symtab_size != 0 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour - && last_map_symbol >= 0) + && pd->last_map_symbol >= 0) { int n; enum riscv_seg_mstate m = MAP_NONE; - for (n = last_map_symbol + 1; n < info->symtab_size; n++) + for (n = pd->last_map_symbol + 1; n < info->symtab_size; n++) { bfd_vma addr = bfd_asymbol_value (info->symtab[n]); if (addr > memaddr @@ -1344,7 +1344,6 @@ static bool riscv_init_disasm_info (struct disassemble_info *info) { int i; - struct riscv_private_data *pd = xcalloc (1, sizeof (struct riscv_private_data)); pd->gp = 0; @@ -1352,8 +1351,8 @@ riscv_init_disasm_info (struct disassemble_info *info) for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++) pd->hi_addr[i] = -1; pd->to_print_addr = false; - pd->has_gp = false; + pd->has_gp = false; for (i = 0; i < info->symtab_size; i++) { asymbol *sym = info->symtab[i]; @@ -1364,6 +1363,50 @@ riscv_init_disasm_info (struct disassemble_info *info) } } + pd->xlen = 0; + pd->default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; + pd->default_priv_spec = PRIV_SPEC_CLASS_NONE; + + pd->riscv_rps_dis.subset_list = xcalloc (1, sizeof (riscv_parse_subset_t)); + pd->riscv_rps_dis.error_handler = opcodes_error_handler; + pd->riscv_rps_dis.xlen = &pd->xlen; + pd->riscv_rps_dis.isa_spec = &pd->default_isa_spec; + pd->riscv_rps_dis.check_unknown_prefixed_ext = false; + const char *default_arch = "rv64gc"; + if (info->section != NULL) + { + bfd *abfd = info->section->owner; + if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour) + { + const char *sec_name = + get_elf_backend_data (abfd)->obj_attrs_section; + if (bfd_get_section_by_name (abfd, sec_name) != NULL) + { + obj_attribute *attr = elf_known_obj_attributes_proc (abfd); + unsigned int Tag_a = Tag_RISCV_priv_spec; + unsigned int Tag_b = Tag_RISCV_priv_spec_minor; + unsigned int Tag_c = Tag_RISCV_priv_spec_revision; + riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i, + attr[Tag_b].i, + attr[Tag_c].i, + &pd->default_priv_spec); + default_arch = attr[Tag_RISCV_arch].s; + } + } + } + riscv_release_subset_list (pd->riscv_rps_dis.subset_list); + riscv_parse_subset (&pd->riscv_rps_dis, default_arch); + + pd->last_map_symbol = -1; + pd->last_stop_offset = 0; + pd->last_map_symbol_boundary = 0; + pd->last_map_state = MAP_NONE; + pd->last_map_section = NULL; + pd->riscv_gpr_names = NULL; + pd->riscv_fpr_names = NULL; + pd->no_aliases = false; + pd->all_ext = false; + info->private_data = pd; return true; } @@ -1398,21 +1441,21 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info) int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *, struct disassemble_info *); + if (info->private_data == NULL && !riscv_init_disasm_info (info)) + return -1; + if (info->disassembler_options != NULL) { - parse_riscv_dis_options (info->disassembler_options); + parse_riscv_dis_options (info->disassembler_options, info); /* Avoid repeatedly parsing the options. */ info->disassembler_options = NULL; } - else if (riscv_gpr_names == NULL) - set_default_riscv_dis_options (); - - if (info->private_data == NULL && !riscv_init_disasm_info (info)) - return -1; + else if (((struct riscv_private_data *) info->private_data)->riscv_gpr_names == NULL) + set_default_riscv_dis_options (info); mstate = riscv_search_mapping_symbol (memaddr, info); /* Save the last mapping state. */ - last_map_state = mstate; + ((struct riscv_private_data *) info->private_data)->last_map_state = mstate; /* Set the size to dump. */ if (mstate == MAP_DATA @@ -1466,33 +1509,6 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info) return (*riscv_disassembler) (memaddr, insn, packet, info); } -disassembler_ftype -riscv_get_disassembler (bfd *abfd) -{ - const char *default_arch = "rv64gc"; - - if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour) - { - const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section; - if (bfd_get_section_by_name (abfd, sec_name) != NULL) - { - obj_attribute *attr = elf_known_obj_attributes_proc (abfd); - unsigned int Tag_a = Tag_RISCV_priv_spec; - unsigned int Tag_b = Tag_RISCV_priv_spec_minor; - unsigned int Tag_c = Tag_RISCV_priv_spec_revision; - riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i, - attr[Tag_b].i, - attr[Tag_c].i, - &default_priv_spec); - default_arch = attr[Tag_RISCV_arch].s; - } - } - - 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 and for relaxable relocations in the assembler. */ @@ -1665,5 +1681,7 @@ with the -M switch (multiple options should be separated by commas):\n")); void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED) { - riscv_release_subset_list (&riscv_subsets); + struct riscv_private_data *pd = info->private_data; + if (pd) + riscv_release_subset_list (pd->riscv_rps_dis.subset_list); } -- 2.39.5