diff options
author | Tom de Vries <tdevries@suse.de> | 2024-08-08 23:52:00 +0200 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2024-08-08 23:52:00 +0200 |
commit | c45c3b4162148077765e94fd17d4481f18d6d44c (patch) | |
tree | 44d21a529dbe4bcee20f4fdf53a721a23096a03f | |
parent | 5b84cbc35ad574483781e62b7fddbcbf73cf2ad3 (diff) | |
download | binutils-c45c3b4162148077765e94fd17d4481f18d6d44c.zip binutils-c45c3b4162148077765e94fd17d4481f18d6d44c.tar.gz binutils-c45c3b4162148077765e94fd17d4481f18d6d44c.tar.bz2 |
[gdb] Handle ^C during disassembly
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
-rw-r--r-- | gdb/arch-utils.c | 7 | ||||
-rw-r--r-- | gdb/disasm.c | 7 | ||||
-rw-r--r-- | gdb/event-top.h | 25 | ||||
-rw-r--r-- | gdb/gdb_bfd.c | 23 |
4 files changed, 37 insertions, 25 deletions
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 13984eb..3247c36 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -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. */ diff --git a/gdb/disasm.c b/gdb/disasm.c index 16736e5..7209cfc 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -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. */ diff --git a/gdb/event-top.h b/gdb/event-top.h index 846d1e4..d590552 100644 --- a/gdb/event-top.h +++ b/gdb/event-top.h @@ -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); diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c index 7e272c7..0854d57 100644 --- a/gdb/gdb_bfd.c +++ b/gdb/gdb_bfd.c @@ -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 |