Add `set print repeats' tests for C/C++ arrays
[binutils-gdb.git] / gdb / disasm.c
index c045dfc94a68e7241b688838c058e8c7a47c9ab7..724040faa9267628f7ae25c8b4cffe26fa187fed 100644 (file)
@@ -1,6 +1,6 @@
 /* Disassemble support for GDB.
 
-   Copyright (C) 2000-2021 Free Software Foundation, Inc.
+   Copyright (C) 2000-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -270,8 +270,40 @@ gdb_pretty_print_disassembler::pretty_print_insn (const struct disasm_insn *insn
     else
       m_uiout->text (":\t");
 
+    /* Clear the buffer into which we will disassemble the instruction.  */
     m_insn_stb.clear ();
 
+    /* A helper function to write the M_INSN_STB buffer, followed by a
+       newline.  This can be called in a couple of situations.  */
+    auto write_out_insn_buffer = [&] ()
+    {
+      m_uiout->field_stream ("inst", m_insn_stb);
+      m_uiout->text ("\n");
+    };
+
+    try
+      {
+       /* Now we can disassemble the instruction.  If the disassembler
+          returns a negative value this indicates an error and is handled
+          within the print_insn call, resulting in an exception being
+          thrown.  Returning zero makes no sense, as this indicates we
+          disassembled something successfully, but it was something of no
+          size?  */
+       size = m_di.print_insn (pc);
+       gdb_assert (size > 0);
+      }
+    catch (const gdb_exception &ex)
+      {
+       /* An exception was thrown while disassembling the instruction.
+          However, the disassembler might still have written something
+          out, so ensure that we flush the instruction buffer before
+          rethrowing the exception.  We can't perform this write from an
+          object destructor as the write itself might throw an exception
+          if the pager kicks in, and the user selects quit.  */
+       write_out_insn_buffer ();
+       throw ex;
+      }
+
     if (flags & DISASSEMBLY_RAW_INSN)
       {
        CORE_ADDR end_pc;
@@ -282,7 +314,6 @@ gdb_pretty_print_disassembler::pretty_print_insn (const struct disasm_insn *insn
           write them out in a single go for the MI.  */
        m_opcode_stb.clear ();
 
-       size = m_di.print_insn (pc);
        end_pc = pc + size;
 
        for (;pc < end_pc; ++pc)
@@ -295,12 +326,10 @@ gdb_pretty_print_disassembler::pretty_print_insn (const struct disasm_insn *insn
        m_uiout->field_stream ("opcodes", m_opcode_stb);
        m_uiout->text ("\t");
       }
-    else
-      size = m_di.print_insn (pc);
 
-    m_uiout->field_stream ("inst", m_insn_stb);
+    /* Disassembly was a success, write out the instruction buffer.  */
+    write_out_insn_buffer ();
   }
-  m_uiout->text ("\n");
 
   return size;
 }