This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC/PATCH] New convenience variable $_exitsignal


This patch was proposed by Pedro at:

<http://sourceware.org/ml/gdb-patches/2013-06/msg00337.html>

It adds a new convenience variable called "$_exitsignal", which will
hold the signal number when the inferior terminates due to the uncaught
signal.

I've made modifications on infrun.c:handle_inferior_event such that
$_exitcode gets cleared when the inferior signalled, and vice-versa.
This assumption was made because IMO the variables are mutually
exclusive, i.e., when the inferior terminates because of an uncaught
signal it is not possible for it to return.  Anyway, Pedro's explanation
seems to follow the same logic.

The patch also adds a NEWS entry, documentation bits, and a testcase.

OK to apply?

-- 
Sergio

gdb/ChangeLog:
2013-06-16  Sergio Durigan Junior  <sergiodj@redhat.com>

	* NEWS: Mention new convenience variable "$_exitsignal".
	* infrun.c (handle_inferior_event): Set internal variable
	"$_exitsignal" for TARGET_WAITKIND_SIGNALLED and clear
	"$_exitcode", vice-versa for TARGET_WAITKIND_STOPPED.

gdb/testsuite/ChangeLog:
2013-06-16  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.base/exitsignal.exp: New file.
	* gdb.base/segv.c: Likewise.

gdb/doc/ChangeLog:
2013-06-16  Sergio Durigan Junior  <sergiodj@redhat.com>

	* gdb.texinfo (Convenience Variables): Document "$_exitsignal".

diff --git a/gdb/NEWS b/gdb/NEWS
index eea9917..e9e81b3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -69,6 +69,10 @@ show range-stepping
 * The exception-related catchpoints, like "catch throw", now accept a
   regular expression which can be used to filter exceptions by type.
 
+* The new convenience variable $_exitsignal is automatically set to
+  the signal number when the program being debugged dies due to an
+  uncaught signal.
+
 * MI changes
 
   ** The -trace-save MI command can optionally save trace buffer in Common
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e6ec4ff..2025f15 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9735,7 +9735,12 @@ to match the format in which the data was printed.
 @item $_exitcode
 @vindex $_exitcode@r{, convenience variable}
 The variable @code{$_exitcode} is automatically set to the exit code when
-the program being debugged terminates.
+the program being debugged terminates normally.
+
+@item $_exitsignal
+@vindex $_exitsignal@r{, convenience variable}
+The variable @code{$_exitsignal} is automatically set to the signal
+number when the program being debugged dies due to an uncaught signal.
 
 @item $_exception
 The variable @code{$_exception} is set to the exception object being
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 51a032b..f4ed1ac 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3455,6 +3455,12 @@ handle_inferior_event (struct execution_control_state *ecs)
 	  set_internalvar_integer (lookup_internalvar ("_exitcode"),
 				   (LONGEST) ecs->ws.value.integer);
 
+	  /* Clear the internal variable, since if we are here chances
+	     are the inferior has not been terminated by a signal.
+	     And even if it has, then GDB will get to
+	     TARGET_WAITKIND_SIGNALLED in time...  */
+	  clear_internalvar (lookup_internalvar ("_exitsignal"));
+
 	  /* Also record this in the inferior itself.  */
 	  current_inferior ()->has_exit_code = 1;
 	  current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
@@ -3462,7 +3468,17 @@ handle_inferior_event (struct execution_control_state *ecs)
 	  print_exited_reason (ecs->ws.value.integer);
 	}
       else
-	print_signal_exited_reason (ecs->ws.value.sig);
+	{
+	  print_signal_exited_reason (ecs->ws.value.sig);
+	  /* Set the value of the internal variable $_exitsignal,
+	     which holds the signal uncaught by the inferior.  */
+	  set_internalvar_integer (lookup_internalvar ("_exitsignal"),
+				   (LONGEST) ecs->ws.value.sig);
+
+	  /* Clear the $_exitcode internal variable, because if the
+	     inferior signalled then its return code does not exist.  */
+	  clear_internalvar (lookup_internalvar ("_exitcode"));
+	}
 
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
diff --git a/gdb/testsuite/gdb.base/exitsignal.exp b/gdb/testsuite/gdb.base/exitsignal.exp
new file mode 100644
index 0000000..aa041d5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/exitsignal.exp
@@ -0,0 +1,49 @@
+# Copyright 2013 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/>.
+
+standard_testfile segv.c
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+# Run to main
+if { ![runto_main] } {
+    return -1
+}
+
+# Print $_exitsignal.  It should be void now, because nothing
+# happened.
+gdb_test "print \$_exitsignal" " = void" \
+    "\$_exitsignal is void before running"
+
+# Trigger SIGSEGV.
+gdb_test "continue" "Program received signal SIGSEGV.*" "trigger SIGSEGV"
+
+# Continue until the end.
+gdb_test "continue" "Program terminated with signal SIGSEGV.*" \
+    "program terminated with SIGSEGV"
+
+# Now, print $_exitsignal again.  It should be 11 (SIGSEGV).
+gdb_test "print \$_exitsignal" " = 11"
+
+# Re-run to main, i.e., restart the executable.
+if { ![rerun_to_main] } {
+    return -1
+}
+
+# Print the $_exitsignal again.  Even in this normal scenario, it
+# should still contain the signal triggered in the other run.
+gdb_test "print \$_exitsignal" " = 11"
diff --git a/gdb/testsuite/gdb.base/segv.c b/gdb/testsuite/gdb.base/segv.c
new file mode 100644
index 0000000..dddbd4c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/segv.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 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/>.
+
+*/
+
+/* This test can be used just to generate a SIGSEGV.  */
+
+#include <stdio.h>
+
+int
+main (int argc, char *argv[])
+{
+  char *p = NULL;
+
+  /* Generating a SIGSEGV.  */
+  *p = 1;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]