]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb] Handle ^C during disassembly
authorTom de Vries <tdevries@suse.de>
Thu, 8 Aug 2024 21:52:00 +0000 (23:52 +0200)
committerTom de Vries <tdevries@suse.de>
Thu, 8 Aug 2024 21:52:00 +0000 (23:52 +0200)
In PR gdb/32025, a fatal error was reported when sending a SIGINT to gdb while
disassembling.

I managed to reproduce this on aarch64-linux in a Leap 15.5 container using
this trigger patch:
...
 gdb_disassembler_memory_reader::dis_asm_read_memory
   (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
    struct disassemble_info *info) noexcept
 {
+  set_quit_flag ();
   return target_read_code (memaddr, myaddr, len);
 }
...
and a simple gdb command line calling the disassemble command:
...
$ gdb -q -batch a.out -ex "disassemble main"
...

The following scenario leads to the fatal error:
- the disassemble command is executed,
- set_quit_flag is called in
  gdb_disassembler_memory_reader::dis_asm_read_memory, pretending that a
  user pressed ^C,
- target_read_code calls QUIT, which throws a
  gdb_exception_quit,
- the exception propagation mechanism reaches c code in libopcodes and a fatal
  error triggers because the c code is not compiled with -fexception.

Fix this by:
- wrapping the body of gdb_disassembler_memory_reader::dis_asm_read_memory in
  catch_exceptions (which consequently needs moving to a header file), and
- reraising the caught exception in default_print_insn using QUIT.

Tested on aarch64-linux.

Approved-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32025

gdb/arch-utils.c
gdb/disasm.c
gdb/event-top.h
gdb/gdb_bfd.c

index 13984eb972e82ae80a4986977073115fdb7fe58a..3247c363e8659a41376b2b7bdcd76e2eac37b62c 100644 (file)
@@ -37,6 +37,7 @@
 #include "auxv.h"
 #include "observable.h"
 #include "solib-target.h"
+#include "event-top.h"
 
 #include "gdbsupport/version.h"
 
@@ -1040,7 +1041,11 @@ default_print_insn (bfd_vma memaddr, disassemble_info *info)
                                 info->mach, current_program_space->exec_bfd ());
 
   gdb_assert (disassemble_fn != NULL);
-  return (*disassemble_fn) (memaddr, info);
+  int res = (*disassemble_fn) (memaddr, info);
+
+  QUIT;
+
+  return res;
 }
 
 /* See arch-utils.h.  */
index 16736e549977b97d9c8ccc9586ea96663fa65100..7209cfc227b6e2da66ed7814291a625eac7a8401 100644 (file)
@@ -197,7 +197,12 @@ gdb_disassembler_memory_reader::dis_asm_read_memory
   (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
    struct disassemble_info *info) noexcept
 {
-  return target_read_code (memaddr, myaddr, len);
+  auto res = catch_exceptions<int, -1> ([&]
+    {
+      return target_read_code (memaddr, myaddr, len);
+    });
+
+  return res;
 }
 
 /* Wrapper of memory_error.  */
index 846d1e48289314d114d9847ac07a338a90426629..d5905527c2abcadd64edbe4b477db9560f88e33d 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <signal.h>
 
+#include "extension.h"
+
 struct cmd_list_element;
 
 /* The current quit handler (and its type).  This is called from the
@@ -81,6 +83,29 @@ extern void quit_serial_event_set ();
 
 extern void quit_serial_event_clear ();
 
+/* Wrap f (args) and handle exceptions by:
+   - returning val, and
+   - calling set_quit_flag or set_force_quit_flag, if needed.  */
+
+template <typename R, R val, typename F, typename... Args>
+static R
+catch_exceptions (F &&f, Args&&... args)
+{
+   try
+     {
+       return f (std::forward<Args> (args)...);
+     }
+   catch (const gdb_exception &ex)
+     {
+       if (ex.reason == RETURN_QUIT)
+        set_quit_flag ();
+       else if (ex.reason == RETURN_FORCED_QUIT)
+        set_force_quit_flag ();
+     }
+
+   return val;
+}
+
 extern void display_gdb_prompt (const char *new_prompt);
 extern void gdb_setup_readline (int);
 extern void gdb_disable_readline (void);
index 7e272c719c3fcb7eda6b3052c0004d7451d68d33..0854d571ecf9f5a56e7249de54cd641a7c9ec005 100644 (file)
@@ -930,29 +930,6 @@ gdb_bfd_openw (const char *filename, const char *target)
   return gdb_bfd_ref_ptr::new_reference (result);
 }
 
-/* Wrap f (args) and handle exceptions by:
-   - returning val, and
-   - calling set_quit_flag or set_force_quit_flag, if needed.  */
-
-template <typename R, R val, typename F, typename... Args>
-static R
-catch_exceptions (F &&f, Args&&... args)
-{
-   try
-     {
-       return f (std::forward<Args> (args)...);
-     }
-   catch (const gdb_exception &ex)
-     {
-       if (ex.reason == RETURN_QUIT)
-        set_quit_flag ();
-       else if (ex.reason == RETURN_FORCED_QUIT)
-        set_force_quit_flag ();
-     }
-
-   return val;
-}
-
 /* See gdb_bfd.h.  */
 
 gdb_bfd_ref_ptr