gdb.mi/list-thread-groups-available.exp: read entries one by one instead of increasin...
[deliverable/binutils-gdb.git] / gdb / guile / scm-disasm.c
index 782d915f23192a5bda839fb0f65231c05ec63032..6b34a229942d8a63f35142b48fbd9392b476db74 100644 (file)
@@ -1,6 +1,6 @@
 /* Scheme interface to architecture.
 
-   Copyright (C) 2014-2015 Free Software Foundation, Inc.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -37,11 +37,13 @@ static SCM address_symbol;
 static SCM asm_symbol;
 static SCM length_symbol;
 
-/* Struct used to pass "application data" in disassemble_info.  */
-
-struct gdbscm_disasm_data
+class gdbscm_disassembler : public gdb_disassembler
 {
-  struct gdbarch *gdbarch;
+public:
+  gdbscm_disassembler (struct gdbarch *gdbarch,
+                      struct ui_file *stream,
+                      SCM port, ULONGEST offset);
+
   SCM port;
   /* The offset of the address of the first instruction in PORT.  */
   ULONGEST offset;
@@ -55,7 +57,7 @@ struct gdbscm_disasm_read_data
   bfd_vma memaddr;
   bfd_byte *myaddr;
   unsigned int length;
-  struct disassemble_info *dinfo;
+  gdbscm_disassembler *dinfo;
 };
 \f
 /* Subroutine of gdbscm_arch_disassemble to simplify it.
@@ -76,16 +78,16 @@ dascm_make_insn (CORE_ADDR pc, const char *assembly, int insn_len)
    Scheme port.  Called via gdbscm_call_guile.
    The result is a statically allocated error message or NULL if success.  */
 
-static void *
+static const char *
 gdbscm_disasm_read_memory_worker (void *datap)
 {
-  struct gdbscm_disasm_read_data *data = datap;
-  struct disassemble_info *dinfo = data->dinfo;
-  struct gdbscm_disasm_data *disasm_data = dinfo->application_data;
-  SCM seekto, newpos, port = disasm_data->port;
+  struct gdbscm_disasm_read_data *data
+    = (struct gdbscm_disasm_read_data *) datap;
+  gdbscm_disassembler *dinfo = data->dinfo;
+  SCM seekto, newpos, port = dinfo->port;
   size_t bytes_read;
 
-  seekto = gdbscm_scm_from_ulongest (data->memaddr - disasm_data->offset);
+  seekto = gdbscm_scm_from_ulongest (data->memaddr - dinfo->offset);
   newpos = scm_seek (port, seekto, scm_from_int (SEEK_SET));
   if (!scm_is_eq (seekto, newpos))
     return "seek error";
@@ -106,45 +108,29 @@ gdbscm_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
                           unsigned int length,
                           struct disassemble_info *dinfo)
 {
+  gdbscm_disassembler *self
+    = static_cast<gdbscm_disassembler *> (dinfo->application_data);
   struct gdbscm_disasm_read_data data;
-  void *status;
+  const char *status;
 
   data.memaddr = memaddr;
   data.myaddr = myaddr;
   data.length = length;
-  data.dinfo = dinfo;
+  data.dinfo = self;
 
   status = gdbscm_with_guile (gdbscm_disasm_read_memory_worker, &data);
 
   /* TODO: IWBN to distinguish problems reading target memory versus problems
-     with the port (e.g., EOF).
-     We return TARGET_XFER_E_IO here as that's what memory_error looks for.  */
-  return status != NULL ? TARGET_XFER_E_IO : 0;
+     with the port (e.g., EOF).  */
+  return status != NULL ? -1 : 0;
 }
 
-/* disassemble_info.memory_error_func for gdbscm_print_insn_from_port.
-   Technically speaking, we don't need our own memory_error_func,
-   but to not provide one would leave a subtle dependency in the code.
-   This function exists to keep a clear boundary.  */
-
-static void
-gdbscm_disasm_memory_error (int status, bfd_vma memaddr,
-                           struct disassemble_info *info)
+gdbscm_disassembler::gdbscm_disassembler (struct gdbarch *gdbarch,
+                                         struct ui_file *stream,
+                                         SCM port_, ULONGEST offset_)
+  : gdb_disassembler (gdbarch, stream, gdbscm_disasm_read_memory),
+    port (port_), offset (offset_)
 {
-  memory_error (status, memaddr);
-}
-
-/* disassemble_info.print_address_func for gdbscm_print_insn_from_port.
-   Since we need to use our own application_data value, we need to supply
-   this routine as well.  */
-
-static void
-gdbscm_disasm_print_address (bfd_vma addr, struct disassemble_info *info)
-{
-  struct gdbscm_disasm_data *data = info->application_data;
-  struct gdbarch *gdbarch = data->gdbarch;
-
-  print_address (gdbarch, addr, info->stream);
 }
 
 /* Subroutine of gdbscm_arch_disassemble to simplify it.
@@ -160,32 +146,11 @@ gdbscm_disasm_print_address (bfd_vma addr, struct disassemble_info *info)
 static int
 gdbscm_print_insn_from_port (struct gdbarch *gdbarch,
                             SCM port, ULONGEST offset, CORE_ADDR memaddr,
-                            struct ui_file *stream, int *branch_delay_insns)
+                            string_file *stream, int *branch_delay_insns)
 {
-  struct disassemble_info di;
-  int length;
-  struct gdbscm_disasm_data data;
-
-  di = gdb_disassemble_info (gdbarch, stream);
-  data.gdbarch = gdbarch;
-  data.port = port;
-  data.offset = offset;
-  di.application_data = &data;
-  di.read_memory_func = gdbscm_disasm_read_memory;
-  di.memory_error_func = gdbscm_disasm_memory_error;
-  di.print_address_func = gdbscm_disasm_print_address;
-
-  length = gdbarch_print_insn (gdbarch, memaddr, &di);
-
-  if (branch_delay_insns)
-    {
-      if (di.insn_info_valid)
-       *branch_delay_insns = di.branch_delay_insns;
-      else
-       *branch_delay_insns = 0;
-    }
+  gdbscm_disassembler di (gdbarch, stream, port, offset);
 
-  return length;
+  return di.print_insn (memaddr, branch_delay_insns);
 }
 
 /* (arch-disassemble <gdb:arch> address
@@ -280,35 +245,30 @@ gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
   for (pc = start, i = 0; pc <= end && i < count; )
     {
       int insn_len = 0;
-      char *as = NULL;
-      struct ui_file *memfile = mem_fileopen ();
-      struct cleanup *cleanups = make_cleanup_ui_file_delete (memfile);
+      string_file buf;
 
-      TRY
+      gdbscm_gdb_exception exc {};
+      try
        {
          if (using_port)
            {
              insn_len = gdbscm_print_insn_from_port (gdbarch, port, offset,
-                                                     pc, memfile, NULL);
+                                                     pc, &buf, NULL);
            }
          else
-           insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
+           insn_len = gdb_print_insn (gdbarch, pc, &buf, NULL);
        }
-      CATCH (except, RETURN_MASK_ALL)
+      catch (const gdb_exception &except)
        {
-         GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
+         exc = unpack (except);
        }
-      END_CATCH
-
-      as = ui_file_xstrdup (memfile, NULL);
 
-      result = scm_cons (dascm_make_insn (pc, as, insn_len),
+      GDBSCM_HANDLE_GDB_EXCEPTION (exc);
+      result = scm_cons (dascm_make_insn (pc, buf.c_str (), insn_len),
                         result);
 
       pc += insn_len;
       i++;
-      do_cleanups (cleanups);
-      xfree (as);
     }
 
   return scm_reverse_x (result, SCM_EOL);
@@ -318,7 +278,7 @@ gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
 
 static const scheme_function disasm_functions[] =
 {
-  { "arch-disassemble", 2, 0, 1, gdbscm_arch_disassemble,
+  { "arch-disassemble", 2, 0, 1, as_a_scm_t_subr (gdbscm_arch_disassemble),
     "\
 Return list of disassembled instructions in memory.\n\
 \n\
This page took 0.027072 seconds and 4 git commands to generate.