This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFC] (windows) GDB/MI crash when using "-list-thread-groups --available"
- From: Joel Brobecker <brobecker at adacore dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 10 May 2018 14:58:24 -0400
- Subject: [RFC] (windows) GDB/MI crash when using "-list-thread-groups --available"
Hello,
On Windows, using the "-list-thread-groups --available" GDB/MI command
before an inferior is being debugged:
% gdb -q -i=mi
=thread-group-added,id="i1"
=cmd-param-changed,param="auto-load safe-path",value="/"
(gdb)
-list-thread-groups --available
Segmentation fault
Ooops!
The SEGV happens because the -list-thread-groups --available command
triggers a windows_nat_target::xfer_partial call for a TARGET_OBJECT_OSDATA
object. Until a program is being debugged, the target_ops layer that
gets the call is the Windows "native" layer. Except for a couple of
specific objects (TARGET_OBJECT_MEMORY and TARGET_OBJECT_LIBRARIES),
this layer's xfer_partial method delegates the xfer of other objects
to the target beneath:
default:
return beneath->xfer_partial (object, annex,
readbuf, writebuf, offset, len,
xfered_len);
Unfortunately, there is no "beneath layer" in this case, so
beneath is NULL and dereferencing it leads to the SEGV.
This patch fixes the issue by checking beneath before trying
to delegate the request. But I am wondering whether this is
the right place to fix this issue, or whether we should expect
BENEATH to never be NULL. Ideas?
Also, The testcase I am proposing fails on the -list-thread-groups test
when run on GNU/Linux because, on that platform, the command returns
more output than the expect buffer can handle, resulting in an UNRESOLVED
status. How does one usually handle this? The only why I can think of
is a loop of gdb_test_multiple... Other ideas?
gdb/ChangeLog:
* windows-nat.c (windows_nat_target::xfer_partial): Return
TARGET_XFER_E_IO if we need to delegate to the target beneath
but BENEATH is NULL.
gdb/testsuite/ChangeLog:
* gdb.mi/mi-list-thread-groups-no-inferior.exp: New testcase.
Thanks!
--
Joel
---
.../gdb.mi/mi-list-thread-groups-no-inferior.exp | 32 ++++++++++++++++++++++
gdb/windows-nat.c | 7 +++++
2 files changed, 39 insertions(+)
create mode 100644 gdb/testsuite/gdb.mi/mi-list-thread-groups-no-inferior.exp
diff --git a/gdb/testsuite/gdb.mi/mi-list-thread-groups-no-inferior.exp b/gdb/testsuite/gdb.mi/mi-list-thread-groups-no-inferior.exp
new file mode 100644
index 0000000..bff6671
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-list-thread-groups-no-inferior.exp
@@ -0,0 +1,32 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+ continue
+}
+
+mi_gdb_test "-list-thread-groups --available" \
+ ".*^(done|error),.*"
+
+# Verify that GDB is still alive.
+
+mi_gdb_test "-data-evaluate-expression 1" \
+ ".*\\^done,value=\"1\"" \
+ "check GDB is still alive"
+
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 16ebd17..0d3a6cc 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2966,6 +2966,13 @@ windows_nat_target::xfer_partial (enum target_object object,
writebuf, offset, len, xfered_len);
default:
+ if (beneath == NULL)
+ {
+ /* This can happen when requesting the transfer of unsupported
+ objects before a program has been started (and therefore
+ with the current_target having no target beneath). */
+ return TARGET_XFER_E_IO;
+ }
return beneath->xfer_partial (object, annex,
readbuf, writebuf, offset, len,
xfered_len);
--
2.1.4