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]

[PATCH v2] Add convenience variable $_exitsignal


Hi,

This is the second version of the patch which adds the convenience
variable "$_exitsignal".  You can look at the first version here:

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

I have made the proposed modifications suggested by Eli, Doug and
Pedro.

Doug, please take a look at tell me what you think.  Eli, I have
rewritten the doc entry for $_exitcode in order to make it explain which
variable is set and which is cleared depending on the situation.  And
Pedro, I've made the test more complete.

Hope it is fine now.  When talking to Pedro on IRC, he proposed that I
make $_exitcode a lazy variable.  I will do it after I get the $_signo
patch in (still working on it).

OK to apply?

-- 
Sergio

gdb/ChangeLog:
2013-06-18  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-18  Sergio Durigan Junior  <sergiodj@redhat.com>

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

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

	* gdb.texinfo (Convenience Variables): Document "$_exitsignal".
	Update entry for "$_exitcode".

diff --git a/gdb/NEWS b/gdb/NEWS
index eea9917..3b5efaf 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 terminating 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..a445b1a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9734,8 +9734,15 @@ 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.
+When the program being debugged terminates normally, @value{GDBN}
+automatically sets this variable to the exit code of the program, and
+clears @code{$_exitsignal}.
+
+@item $_exitsignal
+@vindex $_exitsignal@r{, convenience variable}
+When the program being debugged dies due to an uncaught signal,
+@value{GDBN} automatically sets this variable to that signal's number,
+and clears @code{$_exitcode}.
 
 @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..8d12300 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3455,6 +3455,10 @@ handle_inferior_event (struct execution_control_state *ecs)
 	  set_internalvar_integer (lookup_internalvar ("_exitcode"),
 				   (LONGEST) ecs->ws.value.integer);
 
+	  /* Clear the $_exitsignal internal variable, since if we are
+	     here the inferior has not been terminated by a signal.  */
+	  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 +3466,18 @@ 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 died with a signal 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.c b/gdb/testsuite/gdb.base/exitsignal.c
new file mode 100644
index 0000000..d2b479b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/exitsignal.c
@@ -0,0 +1,37 @@
+/* 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;
+
+#ifdef GENSEGV
+  /* Generating a SIGSEGV.  */
+  *p = 1;
+#else
+  /* Just do a normal return.  */
+  (void) p;
+  return 0;
+#endif
+}
diff --git a/gdb/testsuite/gdb.base/exitsignal.exp b/gdb/testsuite/gdb.base/exitsignal.exp
new file mode 100644
index 0000000..2f8836f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/exitsignal.exp
@@ -0,0 +1,97 @@
+# 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 checks both $_exitcode and $_exitsignal variables.  The
+# purpose of this checking is to ensure that the variables are
+# mutually exclusive, i.e., that when $_exitsignal is set, $_exitcode
+# is not, and vice-versa.  This mutual exclusion happens because if an
+# inferior exited (either successfuly or not), it certainly was not
+# killed by a signal.  However, if it was killed by an uncaught
+# signal, then there is no way for it to have exited.
+
+standard_testfile
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
+    [list additional_flags=-DGENSEGV]] } {
+    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"
+
+# Just to guarantee, making sure that $_exitcode is also void.
+gdb_test "print \$_exitcode" " = void" \
+    "\$_exitcode 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" \
+    "\$_exitsignal is 11 (SIGSEGV) after SIGSEGV."
+
+# And $_exitcode should still be void, since the inferior died because
+# of a signal, and did not return.
+gdb_test "print \$_exitcode" " = void" \
+    "\$_exitcode is still void after SIGSEGV"
+
+# Re-run to main, i.e., restart the executable.
+rerun_to_main
+
+# 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" \
+    "\$_exitsignal is 11 (SIGSEGV) after restarting the inferior"
+
+# And, again, print $_exitcode.
+gdb_test "print \$_exitcode" " = void" \
+    "\$_exitcode is still void after restarting the inferior"
+
+# Now we test the behaviour of $_exit{code,signal} during a normal
+# inferior execution.
+gdb_rename_execfile $binfile ${binfile}x
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+# Checking $_exitsignal and $_exitcode, both should be void before the
+# inferior is executed.
+gdb_test "print \$_exitsignal" " = void" \
+    "\$_exitsignal is void before normal inferior is executed"
+gdb_test "print \$_exitcode" " = void" \
+    "\$_exitcode is void before normal inferior is executed"
+
+# Running until the end.
+gdb_test "run" "\\\[Inferior .* exited normally\\\]" "Run inferior until the end"
+
+# Checking $_exitcode.  It should be 0.
+gdb_test "print \$_exitcode" " = 0" \
+    "\$_exitcode is zero after normal inferior is executed"
+
+# Checking $_exitsignal.  It should still be void, since the inferior
+# has not received any signal.
+gdb_test "print \$_exitsignal" " = void" \
+    "\$_exitsignal is still void after normal inferior is executed"


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