[1/3] opcodes: Add bfd handles to disassemble_info

Message ID 20241210192434.336880-2-m.pikula@partner.samsung.com
State New
Headers
Series RISC-V: Fix disassembly for dynamic libraries |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed

Commit Message

Marek Pikula Dec. 10, 2024, 7:16 p.m. UTC
  As `abfd` and `obfd` handles are useful in multiple places, it's
reasonable to add them in `struct disassemble_info`. The current bfd
metadata stays as is, as bfd handles are not available in all contexts
(and don't need to be).

This change enables more unified disassembler function derivation,
moving the optional `abfd` handling to `print_insn_*` functions.

The `obfd` handle is a function (`get_obfd_for_addr`), which resolves
the object file bfd depending on the disassembled address. This enables
more granular information for the disassemblers, especially if the ELF
contains arch-specific information which can be used to provide better
disassembly output. A notable example is RISC-V, which can use shared
libraries built for a different subset of ISA extensions.

Signed-off-by: Marek Pikuła <m.pikula@partner.samsung.com>
---
 binutils/objdump.c            |  3 +-
 gdb/arch-utils.c              |  2 +-
 gdb/disasm.c                  | 14 +++++++++
 gprofng/libcollector/unwind.c |  9 ++++++
 gprofng/src/Disasm.cc         | 12 ++++++--
 include/dis-asm.h             | 20 +++++++------
 opcodes/arc-dis.c             | 31 ++++++++------------
 opcodes/cris-dis.c            |  9 +++++-
 opcodes/csky-dis.c            | 54 +++++++++++++++++------------------
 opcodes/dis-init.c            | 11 ++++++-
 opcodes/disassemble.c         | 13 ++++-----
 opcodes/disassemble.h         |  7 ++---
 opcodes/riscv-dis.c           | 48 ++++++++++++++-----------------
 opcodes/rl78-dis.c            | 12 ++++++--
 sim/arm/wrapper.c             |  3 +-
 sim/common/sim-trace.c        |  4 +--
 sim/cris/sim-if.c             |  9 +++---
 sim/m32c/trace.c              |  1 +
 sim/rl78/trace.c              |  3 +-
 sim/rx/trace.c                |  1 +
 20 files changed, 155 insertions(+), 111 deletions(-)
  

Comments

Tom Tromey Dec. 13, 2024, 4:02 p.m. UTC | #1
>>>>> "Marek" == Marek Pikuła <m.pikula@partner.samsung.com> writes:

Marek> As `abfd` and `obfd` handles are useful in multiple places, it's
Marek> reasonable to add them in `struct disassemble_info`. The current bfd
Marek> metadata stays as is, as bfd handles are not available in all contexts
Marek> (and don't need to be).

Marek> This change enables more unified disassembler function derivation,
Marek> moving the optional `abfd` handling to `print_insn_*` functions.

Changes to opcodes should go to the binutils list for review.

thanks,
Tom
  
Marek Pikula Dec. 13, 2024, 4:07 p.m. UTC | #2
> Changes to opcodes should go to the binutils list for review

Should I push there only the patch affecting opcodes with a reference to 
this patchset, or the entire patchset?
  
Tom Tromey Dec. 13, 2024, 4:54 p.m. UTC | #3
>>>>> "Marek" == Marek Pikula/Kernel (PLT) /SRPOL/Engineer/Samsung Electronics <m.pikula@partner.samsung.com> writes:

>> Changes to opcodes should go to the binutils list for review

Marek> Should I push there only the patch affecting opcodes with a reference to 
Marek> this patchset, or the entire patchset?

Anything touching bfd or opcodes should go there.
It's normally fine to CC gdb-patches on these things as well.
I'm not sure how they feel about seeing gdb patches but if the patches
are small (or combined) I wouldn't worry too much about it.

Tom
  

Patch

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 4980929d6ab..81ab451fc10 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -4204,7 +4204,7 @@  disassemble_data (bfd *abfd)
   /* Use libopcodes to locate a suitable disassembler.  */
   aux.disassemble_fn = disassembler (bfd_get_arch (abfd),
 				     bfd_big_endian (abfd),
-				     bfd_get_mach (abfd), abfd);
+				     bfd_get_mach (abfd));
   if (!aux.disassemble_fn)
     {
       non_fatal (_("can't disassemble for architecture %s\n"),
@@ -4217,6 +4217,7 @@  disassemble_data (bfd *abfd)
   disasm_info.flavour = bfd_get_flavour (abfd);
   disasm_info.arch = bfd_get_arch (abfd);
   disasm_info.mach = bfd_get_mach (abfd);
+  disasm_info.abfd = abfd;
   disasm_info.disassembler_options = disassembler_options;
   disasm_info.octets_per_byte = bfd_octets_per_byte (abfd, NULL);
   disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES;
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index a2ed2a2c011..e28c89b864f 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -1039,7 +1039,7 @@  default_print_insn (bfd_vma memaddr, disassemble_info *info)
   disassembler_ftype disassemble_fn;
 
   disassemble_fn = disassembler (info->arch, info->endian == BFD_ENDIAN_BIG,
-				 info->mach, current_program_space->exec_bfd ());
+				 info->mach);
 
   gdb_assert (disassemble_fn != NULL);
   int res = (*disassemble_fn) (memaddr, info);
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 11d6efd923a..2b8a4c209ae 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -944,6 +944,18 @@  get_all_disassembler_options (struct gdbarch *gdbarch)
   return string_printf ("%s%s%s", implicit, comma, options);
 }
 
+/* Get obfd for a given address.  If not available, fallback to abfd.  Mind
+   that depending on context, abfd might also be undefined (NULL).  */
+
+static bfd *
+get_obfd_for_address(bfd_vma memaddr, struct disassemble_info* info) {
+  struct objfile *ofile = current_program_space->objfile_for_address (memaddr);
+  if (ofile)
+    return ofile->obfd.get ();
+
+  return info->abfd;
+}
+
 gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
 				    struct ui_file *file,
 				    read_memory_ftype func)
@@ -1024,6 +1036,8 @@  gdb_disassemble_info::gdb_disassemble_info
   m_di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
   m_di.endian = gdbarch_byte_order (gdbarch);
   m_di.endian_code = gdbarch_byte_order_for_code (gdbarch);
+  m_di.abfd = current_program_space->exec_bfd ();
+  m_di.get_obfd_for_addr_func = get_obfd_for_address;
   m_di.application_data = this;
   m_disassembler_options_holder = get_all_disassembler_options (gdbarch);
   if (!m_disassembler_options_holder.empty ())
diff --git a/gprofng/libcollector/unwind.c b/gprofng/libcollector/unwind.c
index d101044bc9b..f6a07104404 100644
--- a/gprofng/libcollector/unwind.c
+++ b/gprofng/libcollector/unwind.c
@@ -122,6 +122,13 @@  fprintf_styled_func (void *arg ATTRIBUTE_UNUSED,
   return 0;
 }
 
+static bfd *
+get_obfd_for_addr_func (bfd_vma memaddr ATTRIBUTE_UNUSED,
+			     struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  return NULL;
+}
+
 /* Get LENGTH bytes from info's buffer, at target address memaddr.
    Transfer them to myaddr.  */
 static int
@@ -4363,6 +4370,8 @@  parse_x86_AVX_instruction (unsigned char *pc)
   dis_info.flavour = bfd_target_unknown_flavour;
   dis_info.endian = BFD_ENDIAN_UNKNOWN;
   dis_info.endian_code = dis_info.endian;
+  dis_info.abfd = NULL;
+  dis_info.get_obfd_for_addr_func = get_obfd_for_addr_func;
   dis_info.octets_per_byte = 1;
   dis_info.disassembler_needs_relocs = FALSE;
   dis_info.fprintf_func = fprintf_func;
diff --git a/gprofng/src/Disasm.cc b/gprofng/src/Disasm.cc
index 19f2174d536..e2df8ad1198 100644
--- a/gprofng/src/Disasm.cc
+++ b/gprofng/src/Disasm.cc
@@ -103,6 +103,14 @@  fprintf_styled_func (void *arg, enum disassembler_style st ATTRIBUTE_UNUSED,
   return cnt;
 }
 
+static bfd *
+get_obfd_for_addr_func (bfd_vma memaddr ATTRIBUTE_UNUSED,
+			     struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  /* Not applicable in this context. */
+  return NULL;
+}
+
 /* Get LENGTH bytes from info's buffer, at target address memaddr.
    Transfer them to myaddr.  */
 static int
@@ -220,6 +228,7 @@  Disasm::disasm_open ()
   dis_info.flavour = bfd_target_unknown_flavour;
   dis_info.endian = BFD_ENDIAN_UNKNOWN;
   dis_info.endian_code = dis_info.endian;
+  dis_info.get_obfd_for_addr_func = get_obfd_for_addr_func;
   dis_info.octets_per_byte = 1;
   dis_info.disassembler_needs_relocs = FALSE;
   dis_info.fprintf_func = fprintf_func;
@@ -319,9 +328,8 @@  Disasm::get_disasm (uint64_t inst_address, uint64_t end_address,
 		dis_info.buffer_length, dis_info.buffer);
 
   dis_str->setLength (0);
-  bfd abfd;
   disassembler_ftype disassemble = disassembler (dis_info.arch, dis_info.endian,
-						 dis_info.mach, &abfd);
+						 dis_info.mach);
   if (disassemble == NULL)
     {
       printf ("ERROR: unsupported disassemble\n");
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 3bdecd37a81..43db1abd865 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -141,9 +141,8 @@  typedef struct disassemble_info
   void *stream;
   void *application_data;
 
-  /* Target description.  We could replace this with a pointer to the bfd,
-     but that would require one.  There currently isn't any such requirement
-     so to avoid introducing one we record these explicitly.  */
+  /* Target description.  Not all contexts have abfd pointer defined, so we
+     record these explicitly.  */
   /* The bfd_flavour.  This can be bfd_target_unknown_flavour.  */
   enum bfd_flavour flavour;
   /* The bfd_arch value.  */
@@ -155,6 +154,12 @@  typedef struct disassemble_info
   /* Endianness of code, for mixed-endian situations such as ARM BE8.  */
   enum bfd_endian endian_code;
 
+  /* Optional abfd pointer.  In some contexts it might be undefined (NULL).  */
+  bfd *abfd;
+  /* Get object bfd for given address.  In some contexts obfd might be
+     undefined (NULL).  */
+  bfd *(*get_obfd_for_addr_func) (bfd_vma, struct disassemble_info*);
+
   /* Some targets need information about the current section to accurately
      display insns.  If this is NULL, the target disassembler function
      will have to make its best guess.  */
@@ -363,6 +368,8 @@  typedef struct
 typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
 
 /* Disassemblers used out side of opcodes library.  */
+extern int print_insn_arc		(bfd_vma, disassemble_info *);
+extern int print_insn_cris		(bfd_vma, disassemble_info *);
 extern int print_insn_m32c		(bfd_vma, disassemble_info *);
 extern int print_insn_mep		(bfd_vma, disassemble_info *);
 extern int print_insn_s12z		(bfd_vma, disassemble_info *);
@@ -370,13 +377,11 @@  extern int print_insn_sh		(bfd_vma, disassemble_info *);
 extern int print_insn_sparc		(bfd_vma, disassemble_info *);
 extern int print_insn_rx		(bfd_vma, disassemble_info *);
 extern int print_insn_rl78		(bfd_vma, disassemble_info *);
+extern int print_insn_rl78_default	(bfd_vma, disassemble_info *);
 extern int print_insn_rl78_g10		(bfd_vma, disassemble_info *);
 extern int print_insn_rl78_g13		(bfd_vma, disassemble_info *);
 extern int print_insn_rl78_g14		(bfd_vma, disassemble_info *);
 
-extern disassembler_ftype arc_get_disassembler (bfd *);
-extern disassembler_ftype cris_get_disassembler (bfd *);
-
 extern void print_aarch64_disassembler_options (FILE *);
 extern void print_i386_disassembler_options (FILE *);
 extern void print_mips_disassembler_options (FILE *);
@@ -409,8 +414,7 @@  extern const disasm_options_and_args_t *disassembler_options_s390 (void);
    endian if BIG is true), bfd_mach value MACH, and ABFD, if that support
    is available.  ABFD may be NULL.  */
 extern disassembler_ftype disassembler (enum bfd_architecture arc,
-					bool big, unsigned long mach,
-					bfd *abfd);
+					bool big, unsigned long mach);
 
 /* Amend the disassemble_info structure as necessary for the target architecture.
    Should only be called after initialising the info->arch field.  */
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index 16fbc8ab007..0c8b13bcc63 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -936,7 +936,7 @@  arc_opcode_to_insn_type (const struct arc_opcode *opcode)
 
 /* Disassemble ARC instructions.  */
 
-static int
+int
 print_insn_arc (bfd_vma memaddr,
 		struct disassemble_info *info)
 {
@@ -956,6 +956,17 @@  print_insn_arc (bfd_vma memaddr,
   struct arc_disassemble_info *arc_infop;
   bool rpcl = false, rset = false;
 
+  /* BFD my be absent, if opcodes is invoked from the debugger that
+     has connected to remote target and doesn't have an ELF file.  */
+  if (info->abfd != NULL)
+    {
+      /* Read the extension insns and registers, if any.  */
+      build_ARC_extmap (info->abfd);
+#ifdef DEBUG
+      dump_ARC_extmap ();
+#endif
+    }
+
   if (info->disassembler_options)
     {
       parse_disassembler_options (info->disassembler_options);
@@ -1451,24 +1462,6 @@  print_insn_arc (bfd_vma memaddr,
   return insn_len;
 }
 
-
-disassembler_ftype
-arc_get_disassembler (bfd *abfd)
-{
-  /* BFD my be absent, if opcodes is invoked from the debugger that
-     has connected to remote target and doesn't have an ELF file.  */
-  if (abfd != NULL)
-    {
-      /* Read the extension insns and registers, if any.  */
-      build_ARC_extmap (abfd);
-#ifdef DEBUG
-      dump_ARC_extmap ();
-#endif
-    }
-
-  return print_insn_arc;
-}
-
 /* Indices into option argument vector for options that do require
    an argument.  Use ARC_OPTION_ARG_NONE for options that don't
    expect an argument.  */
diff --git a/opcodes/cris-dis.c b/opcodes/cris-dis.c
index ef7e7a65882..52e2eee59bb 100644
--- a/opcodes/cris-dis.c
+++ b/opcodes/cris-dis.c
@@ -1637,7 +1637,7 @@  print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
    FIXME: We should improve the solution to avoid the multitude of
    functions seen above.  */
 
-disassembler_ftype
+static disassembler_ftype
 cris_get_disassembler (bfd *abfd)
 {
   /* If there's no bfd in sight, we return what is valid as input in all
@@ -1665,6 +1665,13 @@  cris_get_disassembler (bfd *abfd)
   return print_insn_cris_without_register_prefix;
 }
 
+
+int
+print_insn_cris (bfd_vma vma, disassemble_info *info)
+{
+  return cris_get_disassembler(info->abfd)(vma, info);
+}
+
 /* Local variables:
    eval: (c-set-style "gnu")
    indent-tabs-mode: t
diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c
index e9635bcf4be..ea7f7ab4537 100644
--- a/opcodes/csky-dis.c
+++ b/opcodes/csky-dis.c
@@ -234,34 +234,6 @@  csky_symbol_is_valid (asymbol *sym,
   return name && *name != '$';
 }
 
-disassembler_ftype
-csky_get_disassembler (bfd *abfd)
-{
-  obj_attribute *attr;
-  const char *sec_name = NULL;
-  if (!abfd || bfd_get_flavour (abfd) != bfd_target_elf_flavour)
-    dis_info.isa = CSKY_DEFAULT_ISA;
-  else
-    {
-      mach_flag = elf_elfheader (abfd)->e_flags;
-
-      sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
-      /* Skip any input that hasn't attribute section.
-         This enables to link object files without attribute section with
-         any others.  */
-      if (bfd_get_section_by_name (abfd, sec_name) != NULL)
-        {
-          attr = elf_known_obj_attributes_proc (abfd);
-          dis_info.isa = attr[Tag_CSKY_ISA_EXT_FLAGS].i;
-          dis_info.isa <<= 32;
-          dis_info.isa |= attr[Tag_CSKY_ISA_FLAGS].i;
-        }
-      else
-        dis_info.isa = CSKY_DEFAULT_ISA;
-    }
-
-   return print_insn_csky;
-}
 
 /* Parse the string of disassembler options.  */
 static void
@@ -1048,6 +1020,8 @@  print_insn_csky (bfd_vma memaddr, struct disassemble_info *info)
   int is_data = false;
   void (*printer) (bfd_vma, struct disassemble_info *, long);
   unsigned int  size = 4;
+  obj_attribute *attr;
+  const char *sec_name = NULL;
 
   memset (str, 0, sizeof (str));
   info->bytes_per_chunk = 0;
@@ -1056,6 +1030,30 @@  print_insn_csky (bfd_vma memaddr, struct disassemble_info *info)
   dis_info.info = info;
   dis_info.need_output_symbol = 0;
 
+  /* TODO: Evaluate if it would be better to use
+     info->get_obfd_for_addr_func() to detect extensions in disassembled
+     object file and not in abfd.  */
+  if (!info->abfd || bfd_get_flavour (info->abfd) != bfd_target_elf_flavour)
+    dis_info.isa = CSKY_DEFAULT_ISA;
+  else
+    {
+      mach_flag = elf_elfheader (info->abfd)->e_flags;
+
+      sec_name = get_elf_backend_data (info->abfd)->obj_attrs_section;
+      /* Skip any input that hasn't attribute section.
+         This enables to link object files without attribute section with
+         any others.  */
+      if (bfd_get_section_by_name (info->abfd, sec_name) != NULL)
+        {
+          attr = elf_known_obj_attributes_proc (info->abfd);
+          dis_info.isa = attr[Tag_CSKY_ISA_EXT_FLAGS].i;
+          dis_info.isa <<= 32;
+          dis_info.isa |= attr[Tag_CSKY_ISA_FLAGS].i;
+        }
+      else
+        dis_info.isa = CSKY_DEFAULT_ISA;
+    }
+
   if (info->disassembler_options)
     {
       parse_csky_dis_options (info->disassembler_options);
diff --git a/opcodes/dis-init.c b/opcodes/dis-init.c
index 66c4cac5b6a..d531ab1c33c 100644
--- a/opcodes/dis-init.c
+++ b/opcodes/dis-init.c
@@ -23,6 +23,14 @@ 
 #include "dis-asm.h"
 #include "bfd.h"
 
+static bfd *get_obfd_for_addr_default(bfd_vma memaddr ATTRIBUTE_UNUSED,
+				      struct disassemble_info* info)
+{
+  /* By default use abfd.  Mind that depending on the context, it might be
+     undefined (NULL).  */
+  return info->abfd;
+}
+
 void
 init_disassemble_info (struct disassemble_info *info, void *stream,
 		       fprintf_ftype fprintf_func,
@@ -34,6 +42,8 @@  init_disassemble_info (struct disassemble_info *info, void *stream,
   info->arch = bfd_arch_unknown;
   info->endian = BFD_ENDIAN_UNKNOWN;
   info->endian_code = info->endian;
+  info->abfd = NULL;
+  info->get_obfd_for_addr_func = get_obfd_for_addr_default;
   info->octets_per_byte = 1;
   info->fprintf_func = fprintf_func;
   info->fprintf_styled_func = fprintf_styled_func;
@@ -46,4 +56,3 @@  init_disassemble_info (struct disassemble_info *info, void *stream,
   info->display_endian = BFD_ENDIAN_UNKNOWN;
   info->created_styled_output = false;
 }
-
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 733a0c07aa6..2c1f011c9bb 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -111,8 +111,7 @@ 
 disassembler_ftype
 disassembler (enum bfd_architecture a,
 	      bool big ATTRIBUTE_UNUSED,
-	      unsigned long mach ATTRIBUTE_UNUSED,
-	      bfd *abfd ATTRIBUTE_UNUSED)
+	      unsigned long mach ATTRIBUTE_UNUSED)
 {
   disassembler_ftype disassemble;
 
@@ -132,7 +131,7 @@  disassembler (enum bfd_architecture a,
 #endif
 #ifdef ARCH_arc
     case bfd_arch_arc:
-      disassemble = arc_get_disassembler (abfd);
+      disassemble = print_insn_arc;
       break;
 #endif
 #ifdef ARCH_arm
@@ -160,7 +159,7 @@  disassembler (enum bfd_architecture a,
 #endif
 #ifdef ARCH_cris
     case bfd_arch_cris:
-      disassemble = cris_get_disassembler (abfd);
+      disassemble = print_insn_cris;
       break;
 #endif
 #ifdef ARCH_crx
@@ -170,7 +169,7 @@  disassembler (enum bfd_architecture a,
 #endif
 #ifdef ARCH_csky
     case bfd_arch_csky:
-      disassemble = csky_get_disassembler (abfd);
+      disassemble = print_insn_csky;
       break;
 #endif
 
@@ -382,12 +381,12 @@  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
     case bfd_arch_rl78:
-      disassemble = rl78_get_disassembler (abfd);
+      disassemble = print_insn_rl78;
       break;
 #endif
 #ifdef ARCH_rx
diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h
index 24a2a65ce7d..1963b04374a 100644
--- a/opcodes/disassemble.h
+++ b/opcodes/disassemble.h
@@ -23,6 +23,7 @@ 
 
 extern int print_insn_aarch64		(bfd_vma, disassemble_info *);
 extern int print_insn_alpha		(bfd_vma, disassemble_info *);
+extern int print_insn_arc		(bfd_vma, disassemble_info *);
 extern int print_insn_avr		(bfd_vma, disassemble_info *);
 extern int print_insn_bfin		(bfd_vma, disassemble_info *);
 extern int print_insn_big_arm		(bfd_vma, disassemble_info *);
@@ -30,6 +31,7 @@  extern int print_insn_big_mips		(bfd_vma, disassemble_info *);
 extern int print_insn_big_powerpc	(bfd_vma, disassemble_info *);
 extern int print_insn_big_score         (bfd_vma, disassemble_info *);
 extern int print_insn_cr16              (bfd_vma, disassemble_info *);
+extern int print_insn_cris              (bfd_vma, disassemble_info *);
 extern int print_insn_crx               (bfd_vma, disassemble_info *);
 extern int print_insn_csky		(bfd_vma, disassemble_info *);
 extern int print_insn_d10v		(bfd_vma, disassemble_info *);
@@ -51,6 +53,7 @@  extern int print_insn_ia64		(bfd_vma, disassemble_info *);
 extern int print_insn_ip2k		(bfd_vma, disassemble_info *);
 extern int print_insn_iq2000		(bfd_vma, disassemble_info *);
 extern int print_insn_riscv		(bfd_vma, disassemble_info *);
+extern int print_insn_rl78		(bfd_vma, disassemble_info *);
 extern int print_insn_kvx	        (bfd_vma, disassemble_info *);
 extern int print_insn_little_arm	(bfd_vma, disassemble_info *);
 extern int print_insn_little_mips	(bfd_vma, disassemble_info *);
@@ -100,10 +103,6 @@  extern int print_insn_z8001		(bfd_vma, disassemble_info *);
 extern int print_insn_z8002		(bfd_vma, disassemble_info *);
 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 ATTRIBUTE_NORETURN opcodes_assert (const char *, int);
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index c1212b14a05..f9cf9c5eed0 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -1370,6 +1370,7 @@  print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
   enum riscv_seg_mstate mstate;
   int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *,
 			     struct disassemble_info *);
+  const char *default_arch = "rv64gc";
 
   if (info->disassembler_options != NULL)
     {
@@ -1380,6 +1381,26 @@  print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
   else if (riscv_gpr_names == NULL)
     set_default_riscv_dis_options ();
 
+  if (info->abfd && bfd_get_flavour (info->abfd) == bfd_target_elf_flavour)
+    {
+      const char *sec_name = get_elf_backend_data (info->abfd)->obj_attrs_section;
+      if (bfd_get_section_by_name (info->abfd, sec_name) != NULL)
+	{
+	  obj_attribute *attr = elf_known_obj_attributes_proc (info->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);
+
   if (info->private_data == NULL && !riscv_init_disasm_info (info))
     return -1;
 
@@ -1421,33 +1442,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.  */
 
diff --git a/opcodes/rl78-dis.c b/opcodes/rl78-dis.c
index a0afe6cd6fe..d2bba6690b3 100644
--- a/opcodes/rl78-dis.c
+++ b/opcodes/rl78-dis.c
@@ -380,7 +380,7 @@  print_insn_rl78_common (bfd_vma addr, disassemble_info * dis, RL78_Dis_Isa isa)
 }
 
 int
-print_insn_rl78 (bfd_vma addr, disassemble_info * dis)
+print_insn_rl78_default (bfd_vma addr, disassemble_info * dis)
 {
   return print_insn_rl78_common (addr, dis, RL78_ISA_DEFAULT);
 }
@@ -403,7 +403,7 @@  print_insn_rl78_g14 (bfd_vma addr, disassemble_info * dis)
   return print_insn_rl78_common (addr, dis, RL78_ISA_G14);
 }
 
-disassembler_ftype
+static disassembler_ftype
 rl78_get_disassembler (bfd *abfd)
 {
   int cpu = E_FLAG_RL78_ANY_CPU;
@@ -420,6 +420,12 @@  rl78_get_disassembler (bfd *abfd)
     case E_FLAG_RL78_G14:
       return print_insn_rl78_g14;
     default:
-      return print_insn_rl78;
+      return print_insn_rl78_default;
     }
 }
+
+int
+print_insn_rl78 (bfd_vma addr, disassemble_info * dis)
+{
+  return rl78_get_disassembler(dis->abfd)(addr, dis);
+}
diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c
index 0a9986d9785..8f0def9326b 100644
--- a/sim/arm/wrapper.c
+++ b/sim/arm/wrapper.c
@@ -114,7 +114,7 @@  print_insn (ARMword instr)
 
   opbuf[0] = 0;
   info.application_data = & instr;
-  disassemble_fn = disassembler (bfd_arch_arm, 0, 0, NULL);
+  disassemble_fn = disassembler (bfd_arch_arm, 0, 0);
   size = disassemble_fn (0, & info);
   fprintf (stderr, " %*s\n", size, opbuf);
 }
@@ -344,6 +344,7 @@  sim_create_inferior (SIM_DESC sd ATTRIBUTE_UNUSED,
   info.endian_code = BFD_ENDIAN_LITTLE;
   if (info.mach == 0)
     info.arch = bfd_arch_arm;
+  info.abfd = abfd;
   disassemble_init_for_target (& info);
 
   if (argv != NULL)
diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c
index f5a8234adf3..737c5779b1c 100644
--- a/sim/common/sim-trace.c
+++ b/sim/common/sim-trace.c
@@ -932,12 +932,12 @@  trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr)
       trace_data->disassembler
 	= disassembler (bfd_get_arch (trace_data->dis_bfd),
 			bfd_big_endian (trace_data->dis_bfd),
-			bfd_get_mach (trace_data->dis_bfd),
-			trace_data->dis_bfd);
+			bfd_get_mach (trace_data->dis_bfd));
       INIT_DISASSEMBLE_INFO (*info, cpu, dis_printf, dis_styled_printf);
       info->read_memory_func = dis_read;
       info->arch = bfd_get_arch (bfd);
       info->mach = bfd_get_mach (bfd);
+      info->abfd = bfd;
       disassemble_init_for_target (info);
     }
 
diff --git a/sim/cris/sim-if.c b/sim/cris/sim-if.c
index f3a12e136c2..2b24653a30d 100644
--- a/sim/cris/sim-if.c
+++ b/sim/cris/sim-if.c
@@ -1012,7 +1012,6 @@  cris_disassemble_insn (SIM_CPU *cpu,
 		       const ARGBUF *abuf ATTRIBUTE_UNUSED,
 		       IADDR pc, char *buf)
 {
-  disassembler_ftype pinsn;
   struct disassemble_info disasm_info;
   SFILE sfile;
   SIM_DESC sd = CPU_STATE (cpu);
@@ -1022,9 +1021,9 @@  cris_disassemble_insn (SIM_CPU *cpu,
 			 (fprintf_ftype) sim_disasm_sprintf,
 			 (fprintf_styled_ftype) sim_disasm_styled_sprintf);
   disasm_info.endian = BFD_ENDIAN_LITTLE;
+  disasm_info.abfd = STATE_PROG_BFD (sd);
   disasm_info.read_memory_func = sim_disasm_read_memory;
   disasm_info.memory_error_func = sim_disasm_perror_memory;
   disasm_info.application_data = cpu;
-  pinsn = cris_get_disassembler (STATE_PROG_BFD (sd));
-  (*pinsn) (pc, &disasm_info);
+  print_insn_cris (pc, &disasm_info);
 }
diff --git a/sim/m32c/trace.c b/sim/m32c/trace.c
index b7725e45712..aee89354474 100644
--- a/sim/m32c/trace.c
+++ b/sim/m32c/trace.c
@@ -231,6 +231,7 @@  sim_disasm_one (void)
 	  info.arch = bfd_arch_m32c;
 	  info.mach = default_machine;
 	}
+      info.abfd = current_bfd;
       disassemble_init_for_target (&info);
 
       storage = bfd_get_symtab_upper_bound (current_bfd);
diff --git a/sim/rl78/trace.c b/sim/rl78/trace.c
index 592d1d69601..e303c0dbac6 100644
--- a/sim/rl78/trace.c
+++ b/sim/rl78/trace.c
@@ -223,6 +223,7 @@  sim_get_current_source_location (const char **  pfilename,
       info.mach = bfd_get_mach (current_bfd);
       if (info.mach == 0)
 	info.arch = bfd_arch_rl78;
+      info.abfd = current_bfd;
 
       disassemble_init_for_target (& info);
 
@@ -284,7 +285,7 @@  sim_disasm_one (void)
       else if (g13_multiply)
 	rl78_disasm_fn = print_insn_rl78_g13;
       else
-	rl78_disasm_fn = print_insn_rl78;
+	rl78_disasm_fn = print_insn_rl78_default;
     }
 
   if (filename && functionname && lineno)
diff --git a/sim/rx/trace.c b/sim/rx/trace.c
index 443a990c669..e83c61f3017 100644
--- a/sim/rx/trace.c
+++ b/sim/rx/trace.c
@@ -227,6 +227,7 @@  sim_get_current_source_location (const char **  pfilename,
       info.mach = bfd_get_mach (current_bfd);
       if (info.mach == 0)
 	info.arch = bfd_arch_rx;
+      info.abfd = current_bfd;
 
       disassemble_init_for_target (& info);