* Update PR28561 kfail. * Remove PR31015 kfail. * Remove PR30547 kfail. - Patches added (backport from master): * gdb-symtab-add-producer_is_gas.patch * gdb-symtab-work-around-gas-pr28629.patch * gdb-tdep-fix-nr-array-elements-in-ppc64_aggregate_ca.patch * gdb-testsuite-fix-gdb.python-py-breakpoint.exp-with-.patch * gdb-tui-fix-segfault-in-tui_find_disassembly_address.patch * gdb-tui-fix-wmaybe-uninitialized-in-tui_find_disasse.patch * gdb-testsuite-add-wait_for_msg-arg-to-term-resize-fi.patch - Patches added (backport from gdb-patches): * gdb-fix-segfault-in-for_each_block-part-2.patch * gdb-tui-allow-command-window-of-1-or-2-lines.patch * gdb-tui-fix-resizing-of-terminal-to-1-or-2-lines.patch OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=370
149 lines
4.5 KiB
Diff
149 lines
4.5 KiB
Diff
From 0f8f51e98c7f643b8ce32bc6f6d621ce902d7a66 Mon Sep 17 00:00:00 2001
|
|
From: Tom de Vries <tdevries@suse.de>
|
|
Date: Thu, 28 Sep 2023 20:17:33 +0200
|
|
Subject: [PATCH 2/6] [gdb/tui] Fix segfault in tui_find_disassembly_address
|
|
|
|
PR29040 describes a FAIL for test-case gdb.threads/next-fork-other-thread.exp
|
|
and target board unix/-m32.
|
|
|
|
The FAIL happens due to the test executable running into an assert, which is
|
|
caused by a forked child segfaulting, like so:
|
|
...
|
|
Program terminated with signal SIGSEGV, Segmentation fault.
|
|
#0 0x00000000 in ?? ()
|
|
...
|
|
|
|
I tried to reproduce the segfault with exec next-fork-other-thread-fork, using
|
|
TUI layout asm.
|
|
|
|
I set a breakpoint at fork and ran to the breakpoint, and somewhere during the
|
|
following session I ran into a gdb segfault here in
|
|
tui_find_disassembly_address:
|
|
...
|
|
/* Disassemble forward. */
|
|
next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
|
|
last_addr = asm_lines.back ().addr;
|
|
...
|
|
due to asm_lines being empty after the call to tui_disassemble, while
|
|
asm_lines.back () assumes that it's not empty.
|
|
|
|
I have not been able to reproduce that segfault in that original setting, I'm
|
|
not sure of the exact scenario (though looking back it probably involved
|
|
"set detach-on-fork off").
|
|
|
|
What likely happened is that I managed to reproduce PR29040, and TUI (attempted
|
|
to) display the disassembly for address 0, which led to the gdb segfault.
|
|
|
|
When gdb_print_insn encounters an insn it cannot print because it can't read
|
|
the memory, it throws a MEMORY_ERROR that is caught by tui_disassemble.
|
|
|
|
The specific bit that causes the gdb segfault is that if gdb_print_insn throws
|
|
a MEMORY_ERROR for the first insn in tui_disassemble, it returns an empty
|
|
asm_lines.
|
|
|
|
FWIW, I did manage to reproduce the gdb segfault as follows:
|
|
...
|
|
$ gdb -q \
|
|
-iex "set pagination off" \
|
|
/usr/bin/rustc \
|
|
-ex "set breakpoint pending on" \
|
|
-ex "b dl_main" \
|
|
-ex run \
|
|
-ex "up 4" \
|
|
-ex "layout asm" \
|
|
-ex "print \$pc"
|
|
...
|
|
<TUI>
|
|
...
|
|
$1 = (void (*)()) 0x1
|
|
(gdb)
|
|
...
|
|
Now press <up>, and the segfault triggers.
|
|
|
|
Fix the segfault by handling asm_lines.empty () results of tui_disassemble in
|
|
tui_find_disassembly_address.
|
|
|
|
I've written a unit test that exercises this scenario.
|
|
|
|
Tested on x86_64-linux.
|
|
|
|
Reviewed-by: Kevin Buettner <kevinb@redhat.com>
|
|
|
|
PR tui/30823
|
|
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30823
|
|
---
|
|
gdb/tui/tui-disasm.c | 39 +++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 39 insertions(+)
|
|
|
|
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
|
|
index f0b55769d71..03c78aa1291 100644
|
|
--- a/gdb/tui/tui-disasm.c
|
|
+++ b/gdb/tui/tui-disasm.c
|
|
@@ -41,6 +41,8 @@
|
|
#include "objfiles.h"
|
|
#include "cli/cli-style.h"
|
|
#include "tui/tui-location.h"
|
|
+#include "gdbsupport/selftest.h"
|
|
+#include "inferior.h"
|
|
|
|
#include "gdb_curses.h"
|
|
|
|
@@ -203,6 +205,8 @@ tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
|
|
instruction fails to disassemble we will take the address of the
|
|
previous instruction that did disassemble as the result. */
|
|
tui_disassemble (gdbarch, asm_lines, pc, max_lines + 1);
|
|
+ if (asm_lines.empty ())
|
|
+ return pc;
|
|
new_low = asm_lines.back ().addr;
|
|
}
|
|
else
|
|
@@ -244,6 +248,8 @@ tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
|
|
|
|
/* Disassemble forward. */
|
|
next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
|
|
+ if (asm_lines.empty ())
|
|
+ break;
|
|
last_addr = asm_lines.back ().addr;
|
|
|
|
/* If disassembling from the current value of NEW_LOW reached PC
|
|
@@ -522,3 +528,36 @@ tui_disasm_window::display_start_addr (struct gdbarch **gdbarch_p,
|
|
*gdbarch_p = m_gdbarch;
|
|
*addr_p = m_start_line_or_addr.u.addr;
|
|
}
|
|
+
|
|
+#if GDB_SELF_TEST
|
|
+namespace selftests {
|
|
+namespace tui {
|
|
+namespace disasm {
|
|
+
|
|
+static void
|
|
+run_tests ()
|
|
+{
|
|
+ if (current_inferior () != nullptr)
|
|
+ {
|
|
+ struct gdbarch *gdbarch = current_inferior ()->gdbarch;
|
|
+
|
|
+ /* Check that tui_find_disassembly_address robustly handles the case of
|
|
+ being passed a PC for which gdb_print_insn throws a MEMORY_ERROR. */
|
|
+ SELF_CHECK (tui_find_disassembly_address (gdbarch, 0, 1) == 0);
|
|
+ SELF_CHECK (tui_find_disassembly_address (gdbarch, 0, -1) == 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+} /* namespace disasm */
|
|
+} /* namespace tui */
|
|
+} /* namespace selftests */
|
|
+#endif /* GDB_SELF_TEST */
|
|
+
|
|
+void _initialize_tui_disasm ();
|
|
+void
|
|
+_initialize_tui_disasm ()
|
|
+{
|
|
+#if GDB_SELF_TEST
|
|
+ selftests::register_test ("tui-disasm", selftests::tui::disasm::run_tests);
|
|
+#endif
|
|
+}
|
|
--
|
|
2.35.3
|
|
|