public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFAv2] (Ada) Add gdb-mi support for stopping at start of exception handler.
@ 2018-01-08  9:15 Xavier Roirand
  2018-01-08 18:38 ` Eli Zaretskii
  2018-01-23 11:43 ` Joel Brobecker
  0 siblings, 2 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-08  9:15 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, simon.marchi, brobecker

Following my previous commit which add support for stopping at start of
exception handler, this commit adds required gdb-mi support for this
feature.

gdb/ChangeLog:

        * ada-lang.c (catch_ada_exception_command_split,
        create_ada_exception_catchpoint, catch_ada_assert_command_split)
        <cond_string>: Change parameter type.  Update code accordingly.
        Update callers.
        (catch_ada_exception_command, catch_ada_handlers_command,
        catch_assert_command): Use std::string instead of char*.
        * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
        Update declaration.
        * mi/mi-cmd-catch.c (mi_cmd_catch_assert): Use std::string
        instead of char* for condition string.
        (mi_cmd_catch_exception): Use std::string instead of char* for
        condition string.  Remove uneeded xstrdup.
        (mi_cmd_catch_handlers): New function for -catch-handlers command.
        * mi/mi-cmds.c (struct mi_cmds): Add catch-handlers command.
        * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
        * NEWS: Document "-catch-handlers" command.

gdb/doc/ChangeLog:

        * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
        documentation for new "-catch-handlers" command.

gdb/testsuite/ChangeLog:

        * gdb.ada/mi_catch_ex_hand.exp: New testcase.
        * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

Tested on x86_64-linux.
---
 gdb/NEWS                                       |   4 +
 gdb/ada-lang.c                                 |  27 ++---
 gdb/ada-lang.h                                 |   4 +-
 gdb/doc/gdb.texinfo                            |  44 ++++++++
 gdb/mi/mi-cmd-catch.c                          |  91 +++++++++++++---
 gdb/mi/mi-cmds.c                               |   2 +
 gdb/mi/mi-cmds.h                               |   1 +
 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
 9 files changed, 314 insertions(+), 29 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb

diff --git a/gdb/NEWS b/gdb/NEWS
index 2f834c6..8d01b1a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -374,6 +374,10 @@ show disassembler-options
   List the shared libraries in the program.  This is
   equivalent to the CLI command "info shared".
 
+-catch-handlers
+  Catchpoints stopping the program when Ada exceptions are
+  handled.  This is equivalent to the CLI command "catch handlers".
+
 *** Changes in GDB 7.12
 
 * GDB and GDBserver now build with a C++ compiler by default.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 622cfd0..1303dad 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13129,7 +13129,7 @@ catch_ada_exception_command_split (const char *args,
 				   bool is_catch_handlers_cmd,
                                    enum ada_exception_catchpoint_kind *ex,
 				   char **excep_string,
-				   char **cond_string)
+				   std::string &cond_string)
 {
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   char *exception_name;
@@ -13196,7 +13196,8 @@ catch_ada_exception_command_split (const char *args,
       *ex = ada_catch_exception;
       *excep_string = exception_name;
     }
-  *cond_string = cond;
+  if (cond != NULL)
+    cond_string.assign(cond);
 }
 
 /* Return the name of the symbol on which we should break in order to
@@ -13387,7 +13388,7 @@ void
 create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 enum ada_exception_catchpoint_kind ex_kind,
 				 char *excep_string,
-				 char *cond_string,
+				 std::string &cond_string,
 				 int tempflag,
 				 int disabled,
 				 int from_tty)
@@ -13402,8 +13403,8 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 ops, tempflag, disabled, from_tty);
   c->excep_string = excep_string;
   create_excep_cond_exprs (c.get (), ex_kind);
-  if (cond_string != NULL)
-    set_breakpoint_condition (c.get (), cond_string, from_tty);
+  if (!cond_string.empty ())
+    set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
   install_breakpoint (0, std::move (c), 1);
 }
 
@@ -13418,14 +13419,14 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13443,14 +13444,14 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13466,7 +13467,7 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
    (the memory needs to be deallocated after use).  */
 
 static void
-catch_ada_assert_command_split (const char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string cond_string)
 {
   args = skip_spaces (args);
 
@@ -13478,7 +13479,7 @@ catch_ada_assert_command_split (const char *args, char **cond_string)
       args = skip_spaces (args);
       if (args[0] == '\0')
         error (_("condition missing after `if' keyword"));
-      *cond_string = xstrdup (args);
+      cond_string.assign (args);
     }
 
   /* Otherwise, there should be no other argument at the end of
@@ -13496,13 +13497,13 @@ catch_assert_command (const char *arg_entry, int from_tty,
   const char *arg = arg_entry;
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
-  catch_ada_assert_command_split (arg, &cond_string);
+  catch_ada_assert_command_split (arg, cond_string);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, cond_string,
 				   tempflag, 1 /* enabled */,
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index bac6c06..a3b2183 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -379,8 +379,8 @@ extern std::string ada_name_for_lookup (const char *name);
 
 extern void create_ada_exception_catchpoint
   (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
-   char *excep_string, char *cond_string, int tempflag, int disabled,
-   int from_tty);
+   char *excep_string, std::string &cond_string, int tempflag,
+   int disabled, int from_tty);
 
 /* Some information about a given Ada exception.  */
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8bdafb0..809dbcd 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28512,6 +28512,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
 (gdb)
 @end smallexample
 
+@subheading The @code{-catch-handlers} Command
+@findex -catch-handlers
+
+@subsubheading Synopsis
+
+@smallexample
+ -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
+    [ -t ]
+@end smallexample
+
+Add a catchpoint stopping when Ada exceptions are handled.
+By default, the command stops the program when any Ada exception
+gets handled.  But it is also possible, by using some of the
+optional parameters described below, to create more selective
+catchpoints.
+
+The possible optional parameters for this command are:
+
+@table @samp
+@item -c @var{condition}
+Make the catchpoint conditional on @var{condition}.
+@item -d
+Create a disabled catchpoint.
+@item -e @var{exception-name}
+Only stop when @var{exception-name} is handled.
+@item -t
+Create a temporary catchpoint.
+@end table
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{catch handlers}.
+
+@subsubheading Example
+
+@smallexample
+-catch-handlers -e Constraint_Error
+^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
+enabled="y",addr="0x0000000000402f68",
+what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
+times="0",original-location="__gnat_begin_handler"@}
+(gdb)
+@end smallexample
+
 @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 @node GDB/MI Program Context
 @section @sc{gdb/mi}  Program Context
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index 38b96cc..f124f56 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -32,7 +32,7 @@ void
 mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   int temp = 0;
 
@@ -62,7 +62,7 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -79,10 +79,6 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
     error (_("Invalid argument: %s"), argv[oind]);
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs CONDITION to be xstrdup'ed,
-     and will assume control of its lifetime.  */
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, condition, temp, enabled, 0);
 }
@@ -93,7 +89,7 @@ void
 mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   char *exception_name = NULL;
   int temp = 0;
@@ -128,7 +124,7 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -156,15 +152,82 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
     error (_("\"-e\" and \"-u\" are mutually exclusive"));
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs EXCEPTION_NAME and CONDITION
-     to be xstrdup'ed, and will assume control of their lifetime.  */
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
-				   exception_name, condition,
-				   temp, enabled, 0);
+				   exception_name,
+				   condition, temp, enabled, 0);
+}
+
+/* Handler for the -catch-handlers command.  */
+
+void
+mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
+{
+  struct gdbarch *gdbarch = get_current_arch ();
+  std::string condition;
+  int enabled = 1;
+  char *exception_name = NULL;
+  int temp = 0;
+  enum ada_exception_catchpoint_kind ex_kind = ada_catch_handlers;
+
+  int oind = 0;
+  char *oarg;
+
+  enum opt
+    {
+      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
+    };
+  static const struct mi_opt opts[] =
+    {
+      { "c", OPT_CONDITION, 1},
+      { "d", OPT_DISABLED, 0 },
+      { "e", OPT_EXCEPTION_NAME, 1 },
+      { "t", OPT_TEMP, 0 },
+      { 0, 0, 0 }
+    };
+
+  for (;;)
+    {
+      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
+			   &oind, &oarg);
+
+      if (opt < 0)
+        break;
+
+      switch ((enum opt) opt)
+        {
+	case OPT_CONDITION:
+	  condition.assign (oarg);
+	  break;
+	case OPT_DISABLED:
+	  enabled = 0;
+	  break;
+	case OPT_EXCEPTION_NAME:
+	  exception_name = oarg;
+	  break;
+	case OPT_TEMP:
+	  temp = 1;
+	  break;
+        }
+    }
+
+  /* This command does not accept any argument.  Make sure the user
+     did not provide any.  */
+  if (oind != argc)
+    error (_("Invalid argument: %s"), argv[oind]);
+
+  scoped_restore restore_breakpoint_reporting
+    = setup_breakpoint_reporting ();
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
+  if (exception_name != NULL)
+    exception_name = xstrdup (exception_name);
+  create_ada_exception_catchpoint (gdbarch, ex_kind,
+				   exception_name,
+				   condition, temp, enabled, 0);
 }
 
 /* Common path for the -catch-load and -catch-unload.  */
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index c9ffda1..51014ed 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
                    &mi_suppress_notification.breakpoint),
+  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
+                   &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index c27f3ba..af96585 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
 extern mi_cmd_argv_ftype mi_cmd_break_watch;
 extern mi_cmd_argv_ftype mi_cmd_catch_assert;
 extern mi_cmd_argv_ftype mi_cmd_catch_exception;
+extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
 extern mi_cmd_argv_ftype mi_cmd_catch_load;
 extern mi_cmd_argv_ftype mi_cmd_catch_unload;
 extern mi_cmd_argv_ftype mi_cmd_disassemble;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
new file mode 100644
index 0000000..0137add
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
@@ -0,0 +1,137 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# A global variable used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+
+# Before going any further, verify that we can insert exception
+# handlers catchpoints...  That way, we won't have to do this while
+# doing the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions handlers"
+gdb_test_multiple "catch handlers" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+#############################################
+# 1. Try catching all exceptions handlers.  #
+#############################################
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
+            "catch all exceptions handlers"
+
+# Continue to exception handler.
+
+proc continue_to_exception_handler { test line } {
+
+    global decimal
+
+    mi_send_resuming_command "exec-continue" "$test"
+
+    # Now MI stream output.
+    mi_expect_stop \
+	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+	"foo" "" ".*" "$line" \
+	".*" \
+        $test
+}
+
+# We don't have the exception name info when stopping at the exception handlers
+# breakpoint so we use source line to check if the inferior stops at the
+# right location.
+
+set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until CE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_ce_location"
+
+set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until PE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_pe_location"
+
+##########################################################
+# 2. Try catching only some of the exceptions handlers.  #
+##########################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#  - We'll catch only "Constraint_Error handlers"
+#  - continue, we should stop at the Constraint_Error exception handler
+#  - continue, we should not stop at the Program_Error exception handler
+#    but exit instead.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers -e Constraint_Error" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
+            "catch Constraint_Error"
+
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+              "foo" "" ".*" "$bp_ce_location" \
+              ".*" \
+              "continue to exception catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
new file mode 100644
index 0000000..da701a3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
@@ -0,0 +1,33 @@
+--  Copyright 2007-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/>.
+
+procedure Foo is
+begin
+
+   begin
+      raise Constraint_Error;
+   exception
+      when Constraint_Error => -- BREAK1
+         null;
+   end;
+
+   begin
+      raise Program_Error;
+   exception
+      when Program_Error => -- BREAK2
+         null;
+   end;
+
+end Foo;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFAv2] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-08  9:15 [RFAv2] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
@ 2018-01-08 18:38 ` Eli Zaretskii
  2018-01-23 11:43 ` Joel Brobecker
  1 sibling, 0 replies; 27+ messages in thread
From: Eli Zaretskii @ 2018-01-08 18:38 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches, simon.marchi, brobecker

> From: Xavier Roirand <roirand@adacore.com>
> Cc: Xavier Roirand <roirand@adacore.com>,	simon.marchi@ericsson.com,	brobecker@adacore.com
> Date: Mon,  8 Jan 2018 10:14:38 +0100
> 
> Following my previous commit which add support for stopping at start of
> exception handler, this commit adds required gdb-mi support for this
> feature.
> 
> gdb/ChangeLog:
> 
>         * ada-lang.c (catch_ada_exception_command_split,
>         create_ada_exception_catchpoint, catch_ada_assert_command_split)
>         <cond_string>: Change parameter type.  Update code accordingly.
>         Update callers.
>         (catch_ada_exception_command, catch_ada_handlers_command,
>         catch_assert_command): Use std::string instead of char*.
>         * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
>         Update declaration.
>         * mi/mi-cmd-catch.c (mi_cmd_catch_assert): Use std::string
>         instead of char* for condition string.
>         (mi_cmd_catch_exception): Use std::string instead of char* for
>         condition string.  Remove uneeded xstrdup.
>         (mi_cmd_catch_handlers): New function for -catch-handlers command.
>         * mi/mi-cmds.c (struct mi_cmds): Add catch-handlers command.
>         * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
>         * NEWS: Document "-catch-handlers" command.
> 
> gdb/doc/ChangeLog:
> 
>         * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
>         documentation for new "-catch-handlers" command.
> 
> gdb/testsuite/ChangeLog:
> 
>         * gdb.ada/mi_catch_ex_hand.exp: New testcase.
>         * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

The documentation parts of this patch are approved, with this single
comment:

> +@subsubheading @value{GDBN} Command
> +
> +The corresponding @value{GDBN} command is @samp{catch handlers}.

Please add here a cross-reference to where "catch handlers" is
described.

Thanks.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFAv2] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-08  9:15 [RFAv2] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
  2018-01-08 18:38 ` Eli Zaretskii
@ 2018-01-23 11:43 ` Joel Brobecker
  2018-01-29 12:46   ` [PATCH 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
                     ` (7 more replies)
  1 sibling, 8 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-23 11:43 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches, simon.marchi

Hi Xavier,

On Mon, Jan 08, 2018 at 10:14:38AM +0100, Xavier Roirand wrote:
> Following my previous commit which add support for stopping at start of
> exception handler, this commit adds required gdb-mi support for this
> feature.

Can you split this patch in two. It's better, IMO, as although
the -catch-handlers patch eventually depends on the the fact
that cond_string becomes an std::string reference in
catch_ada_exception_command_split, it's really two separate
patches.

Git makes it really easy to split a patch ("git reset", "git commit -p").
If you're not sure how to do it, please let me know.

> gdb/ChangeLog:
> 
>         * ada-lang.c (catch_ada_exception_command_split,
>         create_ada_exception_catchpoint, catch_ada_assert_command_split)

For symbol names between '(' and ')', we have to close them at
the end of the line, and then re-open them at the next:

       * ada-lang.c (catch_ada_exception_command_split)
       (create_ada_exception_catchpoint, catch_ada_assert_command_split)

Same for some other entries below.

In this case, however, I would like to ask that you list the changes
in the order they are made. Otherwise, this is turns the review of
this ChangeLog entry into a mental exercise, verifying that each
entry is correct, and then that nothing is missing.

>         <cond_string>: Change parameter type.  Update code accordingly.
>         Update callers.
>         (catch_ada_exception_command, catch_ada_handlers_command,
>         catch_assert_command): Use std::string instead of char*.
>         * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
>         Update declaration.
>         * mi/mi-cmd-catch.c (mi_cmd_catch_assert): Use std::string
>         instead of char* for condition string.
>         (mi_cmd_catch_exception): Use std::string instead of char* for
>         condition string.  Remove uneeded xstrdup.

uneeded -> unneeded

>         (mi_cmd_catch_handlers): New function for -catch-handlers command.

No need to change this here, but FYI: "New function" just good enough.

>         * mi/mi-cmds.c (struct mi_cmds): Add catch-handlers command.
>         * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
>         * NEWS: Document "-catch-handlers" command.
> 
> gdb/doc/ChangeLog:
> 
>         * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
>         documentation for new "-catch-handlers" command.
> 
> gdb/testsuite/ChangeLog:
> 
>         * gdb.ada/mi_catch_ex_hand.exp: New testcase.
>         * gdb.ada/mi_catch_ex_hand/foo.adb: New file.
> 
> Tested on x86_64-linux.
> ---
>  gdb/NEWS                                       |   4 +
>  gdb/ada-lang.c                                 |  27 ++---
>  gdb/ada-lang.h                                 |   4 +-
>  gdb/doc/gdb.texinfo                            |  44 ++++++++
>  gdb/mi/mi-cmd-catch.c                          |  91 +++++++++++++---
>  gdb/mi/mi-cmds.c                               |   2 +
>  gdb/mi/mi-cmds.h                               |   1 +
>  gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
>  gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
>  9 files changed, 314 insertions(+), 29 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 2f834c6..8d01b1a 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -374,6 +374,10 @@ show disassembler-options
>    List the shared libraries in the program.  This is
>    equivalent to the CLI command "info shared".
>  
> +-catch-handlers
> +  Catchpoints stopping the program when Ada exceptions are
> +  handled.  This is equivalent to the CLI command "catch handlers".
> +
>  *** Changes in GDB 7.12
>  
>  * GDB and GDBserver now build with a C++ compiler by default.
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 622cfd0..1303dad 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -13129,7 +13129,7 @@ catch_ada_exception_command_split (const char *args,
>  				   bool is_catch_handlers_cmd,
>                                     enum ada_exception_catchpoint_kind *ex,
>  				   char **excep_string,
> -				   char **cond_string)
> +				   std::string &cond_string)
>  {
>    struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
>    char *exception_name;
> @@ -13196,7 +13196,8 @@ catch_ada_exception_command_split (const char *args,
>        *ex = ada_catch_exception;
>        *excep_string = exception_name;
>      }
> -  *cond_string = cond;
> +  if (cond != NULL)
> +    cond_string.assign(cond);
>  }
>  
>  /* Return the name of the symbol on which we should break in order to
> @@ -13387,7 +13388,7 @@ void
>  create_ada_exception_catchpoint (struct gdbarch *gdbarch,
>  				 enum ada_exception_catchpoint_kind ex_kind,
>  				 char *excep_string,
> -				 char *cond_string,
> +				 std::string &cond_string,

Since we are not changing the cond_string, let's mark it "const".

>  				 int tempflag,
>  				 int disabled,
>  				 int from_tty)
> @@ -13402,8 +13403,8 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
>  				 ops, tempflag, disabled, from_tty);
>    c->excep_string = excep_string;
>    create_excep_cond_exprs (c.get (), ex_kind);
> -  if (cond_string != NULL)
> -    set_breakpoint_condition (c.get (), cond_string, from_tty);
> +  if (!cond_string.empty ())
> +    set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
>    install_breakpoint (0, std::move (c), 1);
>  }
>  
> @@ -13418,14 +13419,14 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
>    int tempflag;
>    enum ada_exception_catchpoint_kind ex_kind;
>    char *excep_string = NULL;
> -  char *cond_string = NULL;
> +  std::string cond_string;
>  
>    tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
>  
>    if (!arg)
>      arg = "";
>    catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
> -				     &cond_string);
> +				     cond_string);
>    create_ada_exception_catchpoint (gdbarch, ex_kind,
>  				   excep_string, cond_string,
>  				   tempflag, 1 /* enabled */,
> @@ -13443,14 +13444,14 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
>    int tempflag;
>    enum ada_exception_catchpoint_kind ex_kind;
>    char *excep_string = NULL;
> -  char *cond_string = NULL;
> +  std::string cond_string;
>  
>    tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
>  
>    if (!arg)
>      arg = "";
>    catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
> -				     &cond_string);
> +				     cond_string);
>    create_ada_exception_catchpoint (gdbarch, ex_kind,
>  				   excep_string, cond_string,
>  				   tempflag, 1 /* enabled */,
> @@ -13466,7 +13467,7 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
>     (the memory needs to be deallocated after use).  */
>  
>  static void
> -catch_ada_assert_command_split (const char *args, char **cond_string)
> +catch_ada_assert_command_split (const char *args, std::string cond_string)

Please make the cond_string parameter a reference (to avoid an
unnecessary copy of the parameter).

I suspect we might also need to add a test which verified "catch assert
if [...]" because ...

>  {
>    args = skip_spaces (args);
>  
> @@ -13478,7 +13479,7 @@ catch_ada_assert_command_split (const char *args, char **cond_string)
>        args = skip_spaces (args);
>        if (args[0] == '\0')
>          error (_("condition missing after `if' keyword"));
> -      *cond_string = xstrdup (args);
> +      cond_string.assign (args);

... I think that, before I asked you to pass the string by reference,
the above was doing the assignment to the copy, and therefore had
no effect on the string being given.

My guess based on reading the code is taht you would probably have seen
a regression if there was such a test in our testsuite. Can you add
such a test (as a separate patch, preliminary to this patch, for both
GDB/MI and GDB/CLI)?

No further comments past this point.

>      }
>  
>    /* Otherwise, there should be no other argument at the end of
> @@ -13496,13 +13497,13 @@ catch_assert_command (const char *arg_entry, int from_tty,
>    const char *arg = arg_entry;
>    struct gdbarch *gdbarch = get_current_arch ();
>    int tempflag;
> -  char *cond_string = NULL;
> +  std::string cond_string;
>  
>    tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
>  
>    if (!arg)
>      arg = "";
> -  catch_ada_assert_command_split (arg, &cond_string);
> +  catch_ada_assert_command_split (arg, cond_string);
>    create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
>  				   NULL, cond_string,
>  				   tempflag, 1 /* enabled */,
> diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
> index bac6c06..a3b2183 100644
> --- a/gdb/ada-lang.h
> +++ b/gdb/ada-lang.h
> @@ -379,8 +379,8 @@ extern std::string ada_name_for_lookup (const char *name);
>  
>  extern void create_ada_exception_catchpoint
>    (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
> -   char *excep_string, char *cond_string, int tempflag, int disabled,
> -   int from_tty);
> +   char *excep_string, std::string &cond_string, int tempflag,
> +   int disabled, int from_tty);
>  
>  /* Some information about a given Ada exception.  */
>  
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 8bdafb0..809dbcd 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -28512,6 +28512,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
>  (gdb)
>  @end smallexample
>  
> +@subheading The @code{-catch-handlers} Command
> +@findex -catch-handlers
> +
> +@subsubheading Synopsis
> +
> +@smallexample
> + -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
> +    [ -t ]
> +@end smallexample
> +
> +Add a catchpoint stopping when Ada exceptions are handled.
> +By default, the command stops the program when any Ada exception
> +gets handled.  But it is also possible, by using some of the
> +optional parameters described below, to create more selective
> +catchpoints.
> +
> +The possible optional parameters for this command are:
> +
> +@table @samp
> +@item -c @var{condition}
> +Make the catchpoint conditional on @var{condition}.
> +@item -d
> +Create a disabled catchpoint.
> +@item -e @var{exception-name}
> +Only stop when @var{exception-name} is handled.
> +@item -t
> +Create a temporary catchpoint.
> +@end table
> +
> +@subsubheading @value{GDBN} Command
> +
> +The corresponding @value{GDBN} command is @samp{catch handlers}.
> +
> +@subsubheading Example
> +
> +@smallexample
> +-catch-handlers -e Constraint_Error
> +^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
> +enabled="y",addr="0x0000000000402f68",
> +what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
> +times="0",original-location="__gnat_begin_handler"@}
> +(gdb)
> +@end smallexample
> +
>  @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>  @node GDB/MI Program Context
>  @section @sc{gdb/mi}  Program Context
> diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
> index 38b96cc..f124f56 100644
> --- a/gdb/mi/mi-cmd-catch.c
> +++ b/gdb/mi/mi-cmd-catch.c
> @@ -32,7 +32,7 @@ void
>  mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
>  {
>    struct gdbarch *gdbarch = get_current_arch();
> -  char *condition = NULL;
> +  std::string condition;
>    int enabled = 1;
>    int temp = 0;
>  
> @@ -62,7 +62,7 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
>        switch ((enum opt) opt)
>          {
>  	case OPT_CONDITION:
> -	  condition = oarg;
> +	  condition.assign (oarg);
>  	  break;
>  	case OPT_DISABLED:
>  	  enabled = 0;
> @@ -79,10 +79,6 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
>      error (_("Invalid argument: %s"), argv[oind]);
>  
>    scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
> -  /* create_ada_exception_catchpoint needs CONDITION to be xstrdup'ed,
> -     and will assume control of its lifetime.  */
> -  if (condition != NULL)
> -    condition = xstrdup (condition);
>    create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
>  				   NULL, condition, temp, enabled, 0);
>  }
> @@ -93,7 +89,7 @@ void
>  mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
>  {
>    struct gdbarch *gdbarch = get_current_arch();
> -  char *condition = NULL;
> +  std::string condition;
>    int enabled = 1;
>    char *exception_name = NULL;
>    int temp = 0;
> @@ -128,7 +124,7 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
>        switch ((enum opt) opt)
>          {
>  	case OPT_CONDITION:
> -	  condition = oarg;
> +	  condition.assign (oarg);
>  	  break;
>  	case OPT_DISABLED:
>  	  enabled = 0;
> @@ -156,15 +152,82 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
>      error (_("\"-e\" and \"-u\" are mutually exclusive"));
>  
>    scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
> -  /* create_ada_exception_catchpoint needs EXCEPTION_NAME and CONDITION
> -     to be xstrdup'ed, and will assume control of their lifetime.  */
> +  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
> +     xstrdup'ed, and will assume control of its lifetime.  */
>    if (exception_name != NULL)
>      exception_name = xstrdup (exception_name);
> -  if (condition != NULL)
> -    condition = xstrdup (condition);
>    create_ada_exception_catchpoint (gdbarch, ex_kind,
> -				   exception_name, condition,
> -				   temp, enabled, 0);
> +				   exception_name,
> +				   condition, temp, enabled, 0);
> +}
> +
> +/* Handler for the -catch-handlers command.  */
> +
> +void
> +mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
> +{
> +  struct gdbarch *gdbarch = get_current_arch ();
> +  std::string condition;
> +  int enabled = 1;
> +  char *exception_name = NULL;
> +  int temp = 0;
> +  enum ada_exception_catchpoint_kind ex_kind = ada_catch_handlers;
> +
> +  int oind = 0;
> +  char *oarg;
> +
> +  enum opt
> +    {
> +      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
> +    };
> +  static const struct mi_opt opts[] =
> +    {
> +      { "c", OPT_CONDITION, 1},
> +      { "d", OPT_DISABLED, 0 },
> +      { "e", OPT_EXCEPTION_NAME, 1 },
> +      { "t", OPT_TEMP, 0 },
> +      { 0, 0, 0 }
> +    };
> +
> +  for (;;)
> +    {
> +      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
> +			   &oind, &oarg);
> +
> +      if (opt < 0)
> +        break;
> +
> +      switch ((enum opt) opt)
> +        {
> +	case OPT_CONDITION:
> +	  condition.assign (oarg);
> +	  break;
> +	case OPT_DISABLED:
> +	  enabled = 0;
> +	  break;
> +	case OPT_EXCEPTION_NAME:
> +	  exception_name = oarg;
> +	  break;
> +	case OPT_TEMP:
> +	  temp = 1;
> +	  break;
> +        }
> +    }
> +
> +  /* This command does not accept any argument.  Make sure the user
> +     did not provide any.  */
> +  if (oind != argc)
> +    error (_("Invalid argument: %s"), argv[oind]);
> +
> +  scoped_restore restore_breakpoint_reporting
> +    = setup_breakpoint_reporting ();
> +  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
> +     xstrdup'ed, and will assume control of its lifetime.  */
> +  if (exception_name != NULL)
> +    exception_name = xstrdup (exception_name);
> +  create_ada_exception_catchpoint (gdbarch, ex_kind,
> +				   exception_name,
> +				   condition, temp, enabled, 0);
>  }
>  
>  /* Common path for the -catch-load and -catch-unload.  */
> diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
> index c9ffda1..51014ed 100644
> --- a/gdb/mi/mi-cmds.c
> +++ b/gdb/mi/mi-cmds.c
> @@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
>                     &mi_suppress_notification.breakpoint),
>    DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
>                     &mi_suppress_notification.breakpoint),
> +  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
> +                   &mi_suppress_notification.breakpoint),
>    DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
>                     &mi_suppress_notification.breakpoint),
>    DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
> diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
> index c27f3ba..af96585 100644
> --- a/gdb/mi/mi-cmds.h
> +++ b/gdb/mi/mi-cmds.h
> @@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
>  extern mi_cmd_argv_ftype mi_cmd_break_watch;
>  extern mi_cmd_argv_ftype mi_cmd_catch_assert;
>  extern mi_cmd_argv_ftype mi_cmd_catch_exception;
> +extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
>  extern mi_cmd_argv_ftype mi_cmd_catch_load;
>  extern mi_cmd_argv_ftype mi_cmd_catch_unload;
>  extern mi_cmd_argv_ftype mi_cmd_disassemble;
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
> new file mode 100644
> index 0000000..0137add
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
> @@ -0,0 +1,137 @@
> +# Copyright 2011-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 "ada.exp"
> +
> +standard_ada_testfile foo
> +
> +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
> +  return -1
> +}
> +
> +# A global variable used to simplify the maintenance of some of
> +# the regular expressions below.
> +set eol "\[\r\n\]+"
> +
> +# Before going any further, verify that we can insert exception
> +# handlers catchpoints...  That way, we won't have to do this while
> +# doing the actual GDB/MI testing.
> +
> +clean_restart ${testfile}
> +
> +if ![runto_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +set msg "insert catchpoint on all Ada exceptions handlers"
> +gdb_test_multiple "catch handlers" $msg {
> +    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
> +	pass $msg
> +    }
> +    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
> +	# If the runtime was not built with enough debug information,
> +	# or if it was stripped, we can not test exception
> +	# catchpoints.
> +	unsupported $msg
> +	return -1
> +    }
> +}
> +
> +# Now, we can start the GDB/MI testing itself...
> +
> +load_lib mi-support.exp
> +set MIFLAGS "-i=mi"
> +
> +gdb_exit
> +if [mi_gdb_start] {
> +    continue
> +}
> +
> +#############################################
> +# 1. Try catching all exceptions handlers.  #
> +#############################################
> +
> +if ![mi_run_to_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +mi_gdb_test "-catch-handlers" \
> +            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
> +            "catch all exceptions handlers"
> +
> +# Continue to exception handler.
> +
> +proc continue_to_exception_handler { test line } {
> +
> +    global decimal
> +
> +    mi_send_resuming_command "exec-continue" "$test"
> +
> +    # Now MI stream output.
> +    mi_expect_stop \
> +	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
> +	"foo" "" ".*" "$line" \
> +	".*" \
> +        $test
> +}
> +
> +# We don't have the exception name info when stopping at the exception handlers
> +# breakpoint so we use source line to check if the inferior stops at the
> +# right location.
> +
> +set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
> +continue_to_exception_handler \
> +    "continue until CE handling caught by all-exceptions handlers catchpoint" \
> +    "$bp_ce_location"
> +
> +set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
> +continue_to_exception_handler \
> +    "continue until PE handling caught by all-exceptions handlers catchpoint" \
> +    "$bp_pe_location"
> +
> +##########################################################
> +# 2. Try catching only some of the exceptions handlers.  #
> +##########################################################
> +
> +# Here is the scenario:
> +#  - Restart the debugger from scratch, runto_main
> +#  - We'll catch only "Constraint_Error handlers"
> +#  - continue, we should stop at the Constraint_Error exception handler
> +#  - continue, we should not stop at the Program_Error exception handler
> +#    but exit instead.
> +
> +if ![mi_run_to_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +mi_gdb_test "-catch-handlers -e Constraint_Error" \
> +            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
> +            "catch Constraint_Error"
> +
> +mi_execute_to "exec-continue" \
> +              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
> +              "foo" "" ".*" "$bp_ce_location" \
> +              ".*" \
> +              "continue to exception catchpoint hit"
> +
> +# Exit the inferior.
> +mi_send_resuming_command "exec-continue" "continuing to inferior exit"
> +mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
> +
> +mi_gdb_exit
> +return 0
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
> new file mode 100644
> index 0000000..da701a3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
> @@ -0,0 +1,33 @@
> +--  Copyright 2007-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/>.
> +
> +procedure Foo is
> +begin
> +
> +   begin
> +      raise Constraint_Error;
> +   exception
> +      when Constraint_Error => -- BREAK1
> +         null;
> +   end;
> +
> +   begin
> +      raise Program_Error;
> +   exception
> +      when Program_Error => -- BREAK2
> +         null;
> +   end;
> +
> +end Foo;
> -- 
> 2.7.4

-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 1/4] (Ada) Add testcase for catch assert with condition
  2018-01-23 11:43 ` Joel Brobecker
@ 2018-01-29 12:46   ` Xavier Roirand
  2018-01-30  4:41     ` Joel Brobecker
  2018-01-29 12:47   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-29 12:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

gdb/testsuite/ChangeLog:

    * gdb.ada/catch_assert_if.exp: New testcase.
    * gdb.ada/catch_assert_if/bla.adb: New file.
    * gdb.ada/catch_assert_if/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/catch_assert_if.exp     | 86 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb | 46 ++++++++++++++
 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads | 19 ++++++
 3 files changed, 151 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if.exp
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads

diff --git a/gdb/testsuite/gdb.ada/catch_assert_if.exp b/gdb/testsuite/gdb.ada/catch_assert_if.exp
new file mode 100644
index 0000000..9d00f1c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if.exp
@@ -0,0 +1,86 @@
+# 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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+   return -1
+}
+
+clean_restart ${testfile}
+
+######################################################################
+# 1. Try catching all exceptions to check that runtime supports it.  #
+######################################################################
+
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*$eol$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+###################################################
+# 2. Try catching conditionnal failed assertion.  #
+###################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+gdb_test "catch assert if Global_Var = 2" \
+         "Catchpoint $decimal: failed Ada assertions" \
+         "insert catchpoint on failed assertions with condition"
+
+# Check that condition is stored and properly displayed.
+
+set exp_bp ".*$decimal${sp}breakpoint${sp}keep${sp}y${sp}$hex failed Ada assertions$eol${sp}stop only if Global_Var = 2.*"
+gdb_test "info breakpoint" $exp_bp "Check catch handlers with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+
+set catchpoint_msg \
+  "Catchpoint $decimal, failed assertion at $hex in bla \\\(\\\).*at .*bla.adb:$decimal"
+gdb_test "continue" \
+         "Continuing\.$eol$catchpoint_msg$eol.*STOP" \
+         "continuing to expected failed assertion"
+
+gdb_test "continue" \
+         "Continuing\..*$inferior_exited_re.*" \
+         "continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition
  2018-01-23 11:43 ` Joel Brobecker
  2018-01-29 12:46   ` [PATCH 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
  2018-01-29 12:47   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
@ 2018-01-29 12:47   ` Xavier Roirand
  2018-01-30  4:49     ` Joel Brobecker
  2018-01-29 12:47   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-29 12:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_assert.exp: New testcase.
    * gdb.ada/mi_catch_assert/bla.adb: New file.
    * gdb.ada/mi_catch_assert/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/mi_catch_assert.exp     | 99 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb | 46 +++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads | 19 +++++
 3 files changed, 164 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads

diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert.exp b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
new file mode 100644
index 0000000..ff8943c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
@@ -0,0 +1,99 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# Some global variables used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+# Before going any further, verify that we can insert exception
+# catchpoints...  That way, we won't have to do this while doing
+# the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+###################################################
+# 2. Try catching conditionnal failed assertion.  #
+###################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-assert -c \"Global_Var = 2\"" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"failed Ada assertions\",.*}" \
+            "catch assert failures with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal" \
+              "bla" "" ".*" "$bp_location" \
+              ".*" \
+              "continue to assert failure catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-23 11:43 ` Joel Brobecker
                     ` (2 preceding siblings ...)
  2018-01-29 12:47   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
@ 2018-01-29 12:47   ` Xavier Roirand
  2018-01-29 15:57     ` Eli Zaretskii
  2018-01-30  7:13     ` Joel Brobecker
  2018-01-30  9:23   ` [PATCHv2 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
                     ` (3 subsequent siblings)
  7 siblings, 2 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-29 12:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

Following my previous commit which add support for stopping at start of
exception handler, this commit adds required gdb-mi support for this
feature.

gdb/ChangeLog:

    * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
    * mi/mi-cmds.c (struct mi_cmds): Add catch-handlers command.
    * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
    * NEWS: Document "-catch-handlers" command.

gdb/doc/ChangeLog:

    * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
    documentation for new "-catch-handlers" command.

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_ex_hand.exp: New testcase.
    * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

Tested on x86_64-linux.
---
 gdb/NEWS                                       |   4 +
 gdb/doc/gdb.texinfo                            |  44 ++++++++
 gdb/mi/mi-cmd-catch.c                          |  73 ++++++++++++-
 gdb/mi/mi-cmds.c                               |   2 +
 gdb/mi/mi-cmds.h                               |   1 +
 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
 7 files changed, 292 insertions(+), 2 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb

diff --git a/gdb/NEWS b/gdb/NEWS
index f69173a..9cd38f3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -377,6 +377,10 @@ show disassembler-options
   List the shared libraries in the program.  This is
   equivalent to the CLI command "info shared".
 
+-catch-handlers
+  Catchpoints stopping the program when Ada exceptions are
+  handled.  This is equivalent to the CLI command "catch handlers".
+
 *** Changes in GDB 7.12
 
 * GDB and GDBserver now build with a C++ compiler by default.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9ddfba5..4ed5f6b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28537,6 +28537,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
 (gdb)
 @end smallexample
 
+@subheading The @code{-catch-handlers} Command
+@findex -catch-handlers
+
+@subsubheading Synopsis
+
+@smallexample
+ -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
+    [ -t ]
+@end smallexample
+
+Add a catchpoint stopping when Ada exceptions are handled.
+By default, the command stops the program when any Ada exception
+gets handled.  But it is also possible, by using some of the
+optional parameters described below, to create more selective
+catchpoints.
+
+The possible optional parameters for this command are:
+
+@table @samp
+@item -c @var{condition}
+Make the catchpoint conditional on @var{condition}.
+@item -d
+Create a disabled catchpoint.
+@item -e @var{exception-name}
+Only stop when @var{exception-name} is handled.
+@item -t
+Create a temporary catchpoint.
+@end table
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{catch handlers}.
+
+@subsubheading Example
+
+@smallexample
+-catch-handlers -e Constraint_Error
+^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
+enabled="y",addr="0x0000000000402f68",
+what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
+times="0",original-location="__gnat_begin_handler"@}
+(gdb)
+@end smallexample
+
 @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 @node GDB/MI Program Context
 @section @sc{gdb/mi}  Program Context
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index a0f311a..f124f56 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -157,8 +157,77 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
-				   exception_name, condition,
-				   temp, enabled, 0);
+				   exception_name,
+				   condition, temp, enabled, 0);
+}
+
+/* Handler for the -catch-handlers command.  */
+
+void
+mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
+{
+  struct gdbarch *gdbarch = get_current_arch ();
+  std::string condition;
+  int enabled = 1;
+  char *exception_name = NULL;
+  int temp = 0;
+  enum ada_exception_catchpoint_kind ex_kind = ada_catch_handlers;
+
+  int oind = 0;
+  char *oarg;
+
+  enum opt
+    {
+      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
+    };
+  static const struct mi_opt opts[] =
+    {
+      { "c", OPT_CONDITION, 1},
+      { "d", OPT_DISABLED, 0 },
+      { "e", OPT_EXCEPTION_NAME, 1 },
+      { "t", OPT_TEMP, 0 },
+      { 0, 0, 0 }
+    };
+
+  for (;;)
+    {
+      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
+			   &oind, &oarg);
+
+      if (opt < 0)
+        break;
+
+      switch ((enum opt) opt)
+        {
+	case OPT_CONDITION:
+	  condition.assign (oarg);
+	  break;
+	case OPT_DISABLED:
+	  enabled = 0;
+	  break;
+	case OPT_EXCEPTION_NAME:
+	  exception_name = oarg;
+	  break;
+	case OPT_TEMP:
+	  temp = 1;
+	  break;
+        }
+    }
+
+  /* This command does not accept any argument.  Make sure the user
+     did not provide any.  */
+  if (oind != argc)
+    error (_("Invalid argument: %s"), argv[oind]);
+
+  scoped_restore restore_breakpoint_reporting
+    = setup_breakpoint_reporting ();
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
+  if (exception_name != NULL)
+    exception_name = xstrdup (exception_name);
+  create_ada_exception_catchpoint (gdbarch, ex_kind,
+				   exception_name,
+				   condition, temp, enabled, 0);
 }
 
 /* Common path for the -catch-load and -catch-unload.  */
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index c9ffda1..51014ed 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
                    &mi_suppress_notification.breakpoint),
+  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
+                   &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index c27f3ba..af96585 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
 extern mi_cmd_argv_ftype mi_cmd_break_watch;
 extern mi_cmd_argv_ftype mi_cmd_catch_assert;
 extern mi_cmd_argv_ftype mi_cmd_catch_exception;
+extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
 extern mi_cmd_argv_ftype mi_cmd_catch_load;
 extern mi_cmd_argv_ftype mi_cmd_catch_unload;
 extern mi_cmd_argv_ftype mi_cmd_disassemble;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
new file mode 100644
index 0000000..0137add
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
@@ -0,0 +1,137 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# A global variable used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+
+# Before going any further, verify that we can insert exception
+# handlers catchpoints...  That way, we won't have to do this while
+# doing the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions handlers"
+gdb_test_multiple "catch handlers" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+#############################################
+# 1. Try catching all exceptions handlers.  #
+#############################################
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
+            "catch all exceptions handlers"
+
+# Continue to exception handler.
+
+proc continue_to_exception_handler { test line } {
+
+    global decimal
+
+    mi_send_resuming_command "exec-continue" "$test"
+
+    # Now MI stream output.
+    mi_expect_stop \
+	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+	"foo" "" ".*" "$line" \
+	".*" \
+        $test
+}
+
+# We don't have the exception name info when stopping at the exception handlers
+# breakpoint so we use source line to check if the inferior stops at the
+# right location.
+
+set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until CE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_ce_location"
+
+set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until PE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_pe_location"
+
+##########################################################
+# 2. Try catching only some of the exceptions handlers.  #
+##########################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#  - We'll catch only "Constraint_Error handlers"
+#  - continue, we should stop at the Constraint_Error exception handler
+#  - continue, we should not stop at the Program_Error exception handler
+#    but exit instead.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers -e Constraint_Error" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
+            "catch Constraint_Error"
+
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+              "foo" "" ".*" "$bp_ce_location" \
+              ".*" \
+              "continue to exception catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
new file mode 100644
index 0000000..da701a3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
@@ -0,0 +1,33 @@
+--  Copyright 2007-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/>.
+
+procedure Foo is
+begin
+
+   begin
+      raise Constraint_Error;
+   exception
+      when Constraint_Error => -- BREAK1
+         null;
+   end;
+
+   begin
+      raise Program_Error;
+   exception
+      when Program_Error => -- BREAK2
+         null;
+   end;
+
+end Foo;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] (Ada) C++fy conditional string when catching exception.
  2018-01-23 11:43 ` Joel Brobecker
  2018-01-29 12:46   ` [PATCH 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
@ 2018-01-29 12:47   ` Xavier Roirand
  2018-01-30  4:57     ` Joel Brobecker
  2018-01-29 12:47   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-29 12:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

This commit C++fy the conditional string used when catching Ada exception.

gdb/ChangeLog:

        * ada-lang.c (catch_ada_exception_command_split)
        (create_ada_exception_catchpoint) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_ada_exception_command, catch_ada_handlers_command): Use
        C++ string instead of char* for conditional var.
        (catch_ada_assert_command_split) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_assert_command): Use C++ string instead of char* for
        conditional var.
        * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
        Update declaration.
        * mi/mi-cmd-catch.c (mi_cmd_catch_assert, mi_cmd_catch_exception:
        Use std::string instead of char* for condition string.

Tested on x86_64-linux.
---
 gdb/ada-lang.c        | 27 ++++++++++++++-------------
 gdb/ada-lang.h        |  4 ++--
 gdb/mi/mi-cmd-catch.c | 18 ++++++------------
 3 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3ff7169..0da58d9 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13142,7 +13142,7 @@ catch_ada_exception_command_split (const char *args,
 				   bool is_catch_handlers_cmd,
                                    enum ada_exception_catchpoint_kind *ex,
 				   char **excep_string,
-				   char **cond_string)
+				   std::string &cond_string)
 {
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   char *exception_name;
@@ -13209,7 +13209,8 @@ catch_ada_exception_command_split (const char *args,
       *ex = ada_catch_exception;
       *excep_string = exception_name;
     }
-  *cond_string = cond;
+  if (cond != NULL)
+    cond_string.assign (cond);
 }
 
 /* Return the name of the symbol on which we should break in order to
@@ -13400,7 +13401,7 @@ void
 create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 enum ada_exception_catchpoint_kind ex_kind,
 				 char *excep_string,
-				 char *cond_string,
+				 const std::string &cond_string,
 				 int tempflag,
 				 int disabled,
 				 int from_tty)
@@ -13415,8 +13416,8 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 ops, tempflag, disabled, from_tty);
   c->excep_string = excep_string;
   create_excep_cond_exprs (c.get (), ex_kind);
-  if (cond_string != NULL)
-    set_breakpoint_condition (c.get (), cond_string, from_tty);
+  if (!cond_string.empty ())
+    set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
   install_breakpoint (0, std::move (c), 1);
 }
 
@@ -13431,14 +13432,14 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13456,14 +13457,14 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13479,7 +13480,7 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
    (the memory needs to be deallocated after use).  */
 
 static void
-catch_ada_assert_command_split (const char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string &cond_string)
 {
   args = skip_spaces (args);
 
@@ -13491,7 +13492,7 @@ catch_ada_assert_command_split (const char *args, char **cond_string)
       args = skip_spaces (args);
       if (args[0] == '\0')
         error (_("condition missing after `if' keyword"));
-      *cond_string = xstrdup (args);
+      cond_string.assign (args);
     }
 
   /* Otherwise, there should be no other argument at the end of
@@ -13509,13 +13510,13 @@ catch_assert_command (const char *arg_entry, int from_tty,
   const char *arg = arg_entry;
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
-  catch_ada_assert_command_split (arg, &cond_string);
+  catch_ada_assert_command_split (arg, cond_string);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, cond_string,
 				   tempflag, 1 /* enabled */,
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index bac6c06..1f6ea77 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -379,8 +379,8 @@ extern std::string ada_name_for_lookup (const char *name);
 
 extern void create_ada_exception_catchpoint
   (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
-   char *excep_string, char *cond_string, int tempflag, int disabled,
-   int from_tty);
+   char *excep_string, const std::string &cond_string, int tempflag,
+   int disabled, int from_tty);
 
 /* Some information about a given Ada exception.  */
 
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index 38b96cc..a0f311a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -32,7 +32,7 @@ void
 mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   int temp = 0;
 
@@ -62,7 +62,7 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -79,10 +79,6 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
     error (_("Invalid argument: %s"), argv[oind]);
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs CONDITION to be xstrdup'ed,
-     and will assume control of its lifetime.  */
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, condition, temp, enabled, 0);
 }
@@ -93,7 +89,7 @@ void
 mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   char *exception_name = NULL;
   int temp = 0;
@@ -128,7 +124,7 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -156,12 +152,10 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
     error (_("\"-e\" and \"-u\" are mutually exclusive"));
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs EXCEPTION_NAME and CONDITION
-     to be xstrdup'ed, and will assume control of their lifetime.  */
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   exception_name, condition,
 				   temp, enabled, 0);
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-29 12:47   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
@ 2018-01-29 15:57     ` Eli Zaretskii
  2018-01-30  7:13     ` Joel Brobecker
  1 sibling, 0 replies; 27+ messages in thread
From: Eli Zaretskii @ 2018-01-29 15:57 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches, brobecker

> From: Xavier Roirand <roirand@adacore.com>
> Cc: Xavier Roirand <roirand@adacore.com>,	brobecker@adacore.com
> Date: Mon, 29 Jan 2018 13:47:06 +0100
> 
> Following my previous commit which add support for stopping at start of
> exception handler, this commit adds required gdb-mi support for this
> feature.
> 
> gdb/ChangeLog:
> 
>     * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
>     * mi/mi-cmds.c (struct mi_cmds): Add catch-handlers command.
>     * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
>     * NEWS: Document "-catch-handlers" command.
> 
> gdb/doc/ChangeLog:
> 
>     * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
>     documentation for new "-catch-handlers" command.
> 
> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/mi_catch_ex_hand.exp: New testcase.
>     * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

OK for the documentation parts.

Thanks.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 1/4] (Ada) Add testcase for catch assert with condition
  2018-01-29 12:46   ` [PATCH 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
@ 2018-01-30  4:41     ` Joel Brobecker
  0 siblings, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-30  4:41 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

On Mon, Jan 29, 2018 at 01:46:30PM +0100, Xavier Roirand wrote:
> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/catch_assert_if.exp: New testcase.
>     * gdb.ada/catch_assert_if/bla.adb: New file.
>     * gdb.ada/catch_assert_if/pck.ads: New file.
> 
> Tested on x86_64-linux.
> ---
>  gdb/testsuite/gdb.ada/catch_assert_if.exp     | 86 +++++++++++++++++++++++++++
>  gdb/testsuite/gdb.ada/catch_assert_if/bla.adb | 46 ++++++++++++++
>  gdb/testsuite/gdb.ada/catch_assert_if/pck.ads | 19 ++++++
>  3 files changed, 151 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if.exp
>  create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
>  create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
> 
> diff --git a/gdb/testsuite/gdb.ada/catch_assert_if.exp b/gdb/testsuite/gdb.ada/catch_assert_if.exp
> new file mode 100644
> index 0000000..9d00f1c
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/catch_assert_if.exp
> @@ -0,0 +1,86 @@
> +# 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 "ada.exp"
> +
> +standard_ada_testfile bla
> +
> +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
> +   return -1
> +}
> +
> +clean_restart ${testfile}
> +
> +######################################################################
> +# 1. Try catching all exceptions to check that runtime supports it.  #
> +######################################################################
> +
> +set eol "\[\r\n\]+"
> +set sp "\[ \t\]*"
> +
> +if ![runto_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +set msg "insert catchpoint on all Ada exceptions"
> +gdb_test_multiple "catch exception" $msg {
> +    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
> +	pass $msg
> +    }
> +    -re "Your Ada runtime appears to be missing some debugging information.*$eol$gdb_prompt $" {
> +	# If the runtime was not built with enough debug information,
> +	# or if it was stripped, we can not test exception
> +	# catchpoints.
> +	unsupported $msg
> +	return -1
> +    }
> +}
> +
> +###################################################
> +# 2. Try catching conditionnal failed assertion.  #

conditionnal -> conditional


> +###################################################
> +
> +# Here is the scenario:
> +#  - Restart the debugger from scratch, runto_main
> +#    We'll catch assertions if Global_Var = 2
> +#  - continue, we should see the second failed assertion
> +#  - continue, the program exits.
> +
> +if ![runto_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +gdb_test "catch assert if Global_Var = 2" \
> +         "Catchpoint $decimal: failed Ada assertions" \
> +         "insert catchpoint on failed assertions with condition"

FYI: adding the test's name ("insert catchpoint [...]") is always
completely fine. It is not absolutely necessary in this case,
because the default test name is the command being sent, and
since it is unique in this case, it can be used as such.

> +# Check that condition is stored and properly displayed.
> +
> +set exp_bp ".*$decimal${sp}breakpoint${sp}keep${sp}y${sp}$hex failed Ada assertions$eol${sp}stop only if Global_Var = 2.*"
> +gdb_test "info breakpoint" $exp_bp "Check catch handlers with condition"

Did you mean "assertions" instead of "handlers"?

> +set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]

This seems unused. You could have used it in catchpoint_msg, but
you're already checking which sound line we're stopping on, so...

> +set catchpoint_msg \
> +  "Catchpoint $decimal, failed assertion at $hex in bla \\\(\\\).*at .*bla.adb:$decimal"
> +gdb_test "continue" \
> +         "Continuing\.$eol$catchpoint_msg$eol.*STOP" \

If it were me, I would check the contents of the entire line of
source code, rather than just "STOP", as it makes it clearer what
the intent is. But feel free to ignore,  this is good enough.

No further comment past this point.

> +         "continuing to expected failed assertion"
> +
> +gdb_test "continue" \
> +         "Continuing\..*$inferior_exited_re.*" \
> +         "continuing to program completion"
> diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
> new file mode 100644
> index 0000000..6b3b2e7
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
> @@ -0,0 +1,46 @@
> +--  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/>.
> +
> +with Pck; use Pck;
> +
> +procedure Bla is
> +begin
> +   Global_Var := 1;
> +   declare
> +   begin
> +      pragma Assert (Global_Var /= 1, "Error #1");
> +   exception
> +      when others =>
> +         null;
> +   end;
> +
> +   Global_Var := 2;
> +   declare
> +   begin
> +      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
> +   exception
> +      when others =>
> +         null;
> +   end;
> +
> +   Global_Var := 3;
> +   declare
> +   begin
> +      pragma Assert (Global_Var = 2, "Error #3");
> +   exception
> +      when others =>
> +         null;
> +   end;
> +end Bla;
> diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
> new file mode 100644
> index 0000000..f00f5b3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
> @@ -0,0 +1,19 @@
> +--  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/>.
> +
> +package Pck is
> +   Global_Var : Integer := 0;
> +end Pck;
> +
> -- 
> 2.7.4

-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition
  2018-01-29 12:47   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
@ 2018-01-30  4:49     ` Joel Brobecker
  0 siblings, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-30  4:49 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

On Mon, Jan 29, 2018 at 01:46:52PM +0100, Xavier Roirand wrote:
> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/mi_catch_assert.exp: New testcase.
>     * gdb.ada/mi_catch_assert/bla.adb: New file.
>     * gdb.ada/mi_catch_assert/pck.ads: New file.
> 
> Tested on x86_64-linux.
> ---
>  gdb/testsuite/gdb.ada/mi_catch_assert.exp     | 99 +++++++++++++++++++++++++++
>  gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb | 46 +++++++++++++
>  gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads | 19 +++++
>  3 files changed, 164 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert.exp
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
> 
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert.exp b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
> new file mode 100644
> index 0000000..ff8943c
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
> @@ -0,0 +1,99 @@
> +# Copyright 2011-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 "ada.exp"
> +
> +standard_ada_testfile bla
> +
> +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
> +  return -1
> +}
> +
> +# Some global variables used to simplify the maintenance of some of
> +# the regular expressions below.
> +set eol "\[\r\n\]+"
> +set sp "\[ \t\]*"
> +
> +# Before going any further, verify that we can insert exception
> +# catchpoints...  That way, we won't have to do this while doing
> +# the actual GDB/MI testing.
> +
> +clean_restart ${testfile}
> +
> +if ![runto_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +set msg "insert catchpoint on all Ada exceptions"
> +gdb_test_multiple "catch exception" $msg {
> +    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
> +	pass $msg
> +    }
> +    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
> +	# If the runtime was not built with enough debug information,
> +	# or if it was stripped, we can not test exception
> +	# catchpoints.
> +	unsupported $msg
> +	return -1
> +    }
> +}
> +
> +# Now, we can start the GDB/MI testing itself...
> +
> +load_lib mi-support.exp
> +set MIFLAGS "-i=mi"
> +
> +gdb_exit
> +if [mi_gdb_start] {
> +    continue
> +}
> +
> +mi_delete_breakpoints
> +mi_gdb_reinitialize_dir $srcdir/$subdir
> +mi_gdb_load ${binfile}
> +
> +###################################################
> +# 2. Try catching conditionnal failed assertion.  #
> +###################################################
> +
> +# Here is the scenario:
> +#  - Restart the debugger from scratch, runto_main
> +#    We'll catch assertions if Global_Var = 2
> +#  - continue, we should see the second failed assertion
> +#  - continue, the program exits.
> +
> +if ![mi_run_to_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +mi_gdb_test "-catch-assert -c \"Global_Var = 2\"" \
> +            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"failed Ada assertions\",.*}" \
> +            "catch assert failures with condition"

Can you also verify the condition in the "done" message?

> +set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
> +mi_execute_to "exec-continue" \
> +              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal" \
> +              "bla" "" ".*" "$bp_location" \
> +              ".*" \
> +              "continue to assert failure catchpoint hit"
> +
> +# Exit the inferior.
> +mi_send_resuming_command "exec-continue" "continuing to inferior exit"
> +mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
> +
> +mi_gdb_exit
> +return 0

The "return 0" is not necessary; can you remove it? I'm not sure
about the necessity of "mi_gdb_exit", but we don't have it in any
of the gdb.ada tests, so how about we skip it for now?

No further comments past this point.

> diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
> new file mode 100644
> index 0000000..6b3b2e7
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
> @@ -0,0 +1,46 @@
> +--  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/>.
> +
> +with Pck; use Pck;
> +
> +procedure Bla is
> +begin
> +   Global_Var := 1;
> +   declare
> +   begin
> +      pragma Assert (Global_Var /= 1, "Error #1");
> +   exception
> +      when others =>
> +         null;
> +   end;
> +
> +   Global_Var := 2;
> +   declare
> +   begin
> +      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
> +   exception
> +      when others =>
> +         null;
> +   end;
> +
> +   Global_Var := 3;
> +   declare
> +   begin
> +      pragma Assert (Global_Var = 2, "Error #3");
> +   exception
> +      when others =>
> +         null;
> +   end;
> +end Bla;
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
> new file mode 100644
> index 0000000..f00f5b3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
> @@ -0,0 +1,19 @@
> +--  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/>.
> +
> +package Pck is
> +   Global_Var : Integer := 0;
> +end Pck;
> +
> -- 
> 2.7.4

-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/4] (Ada) C++fy conditional string when catching exception.
  2018-01-29 12:47   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
@ 2018-01-30  4:57     ` Joel Brobecker
  0 siblings, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-30  4:57 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

On Mon, Jan 29, 2018 at 01:46:59PM +0100, Xavier Roirand wrote:
> This commit C++fy the conditional string used when catching Ada exception.
> 
> gdb/ChangeLog:
> 
>         * ada-lang.c (catch_ada_exception_command_split)
>         (create_ada_exception_catchpoint) <cond_string>: Change parameter
>         type.  Update code accordingly.
>         (catch_ada_exception_command, catch_ada_handlers_command): Use
>         C++ string instead of char* for conditional var.
>         (catch_ada_assert_command_split) <cond_string>: Change parameter
>         type.  Update code accordingly.
>         (catch_assert_command): Use C++ string instead of char* for
>         conditional var.
>         * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
>         Update declaration.
>         * mi/mi-cmd-catch.c (mi_cmd_catch_assert, mi_cmd_catch_exception:

Missing closing ')'.

>         Use std::string instead of char* for condition string.

Looks good to me. Well done!

-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-29 12:47   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
  2018-01-29 15:57     ` Eli Zaretskii
@ 2018-01-30  7:13     ` Joel Brobecker
  1 sibling, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-30  7:13 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

Hi Xavier,

On Mon, Jan 29, 2018 at 01:47:06PM +0100, Xavier Roirand wrote:
> Following my previous commit which add support for stopping at start of
> exception handler, this commit adds required gdb-mi support for this
> feature.
> 
> gdb/ChangeLog:
> 
>     * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
>     * mi/mi-cmds.c (struct mi_cmds): Add catch-handlers command.

"struct mi_cmds" -> "mi_cmds".

Rationale: You changed the variable called "mi_cmds", not "struct
mi_cmds". If you had changed the definition of the struct (ie,
the definition of the type), then you would have said "struct mi_cmd"
(note the lack of 's' as the variable and the type have a slightly
different name in this case).

>     * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
>     * NEWS: Document "-catch-handlers" command.
> 
> gdb/doc/ChangeLog:
> 
>     * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
>     documentation for new "-catch-handlers" command.
> 
> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/mi_catch_ex_hand.exp: New testcase.
>     * gdb.ada/mi_catch_ex_hand/foo.adb: New file.
> 
> Tested on x86_64-linux.

Only a few minor nits. See below.

> ---
>  gdb/NEWS                                       |   4 +
>  gdb/doc/gdb.texinfo                            |  44 ++++++++
>  gdb/mi/mi-cmd-catch.c                          |  73 ++++++++++++-
>  gdb/mi/mi-cmds.c                               |   2 +
>  gdb/mi/mi-cmds.h                               |   1 +
>  gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
>  gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
>  7 files changed, 292 insertions(+), 2 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
>  create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index f69173a..9cd38f3 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -377,6 +377,10 @@ show disassembler-options
>    List the shared libraries in the program.  This is
>    equivalent to the CLI command "info shared".
>  
> +-catch-handlers
> +  Catchpoints stopping the program when Ada exceptions are
> +  handled.  This is equivalent to the CLI command "catch handlers".
> +
>  *** Changes in GDB 7.12
>  
>  * GDB and GDBserver now build with a C++ compiler by default.
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 9ddfba5..4ed5f6b 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -28537,6 +28537,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
>  (gdb)
>  @end smallexample
>  
> +@subheading The @code{-catch-handlers} Command
> +@findex -catch-handlers
> +
> +@subsubheading Synopsis
> +
> +@smallexample
> + -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
> +    [ -t ]
> +@end smallexample
> +
> +Add a catchpoint stopping when Ada exceptions are handled.
> +By default, the command stops the program when any Ada exception
> +gets handled.  But it is also possible, by using some of the
> +optional parameters described below, to create more selective
> +catchpoints.
> +
> +The possible optional parameters for this command are:
> +
> +@table @samp
> +@item -c @var{condition}
> +Make the catchpoint conditional on @var{condition}.
> +@item -d
> +Create a disabled catchpoint.
> +@item -e @var{exception-name}
> +Only stop when @var{exception-name} is handled.
> +@item -t
> +Create a temporary catchpoint.
> +@end table
> +
> +@subsubheading @value{GDBN} Command
> +
> +The corresponding @value{GDBN} command is @samp{catch handlers}.
> +
> +@subsubheading Example
> +
> +@smallexample
> +-catch-handlers -e Constraint_Error
> +^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
> +enabled="y",addr="0x0000000000402f68",
> +what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
> +times="0",original-location="__gnat_begin_handler"@}
> +(gdb)
> +@end smallexample
> +
>  @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>  @node GDB/MI Program Context
>  @section @sc{gdb/mi}  Program Context
> diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
> index a0f311a..f124f56 100644
> --- a/gdb/mi/mi-cmd-catch.c
> +++ b/gdb/mi/mi-cmd-catch.c
> @@ -157,8 +157,77 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
>    if (exception_name != NULL)
>      exception_name = xstrdup (exception_name);
>    create_ada_exception_catchpoint (gdbarch, ex_kind,
> -				   exception_name, condition,
> -				   temp, enabled, 0);
> +				   exception_name,
> +				   condition, temp, enabled, 0);
> +}
> +
> +/* Handler for the -catch-handlers command.  */
> +
> +void
> +mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
> +{
> +  struct gdbarch *gdbarch = get_current_arch ();
> +  std::string condition;
> +  int enabled = 1;
> +  char *exception_name = NULL;
> +  int temp = 0;
> +  enum ada_exception_catchpoint_kind ex_kind = ada_catch_handlers;

This is not a variable, so why not use ada_catch_handlers
directly?

> +  int oind = 0;
> +  char *oarg;
> +
> +  enum opt
> +    {
> +      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
> +    };
> +  static const struct mi_opt opts[] =
> +    {
> +      { "c", OPT_CONDITION, 1},
> +      { "d", OPT_DISABLED, 0 },
> +      { "e", OPT_EXCEPTION_NAME, 1 },
> +      { "t", OPT_TEMP, 0 },
> +      { 0, 0, 0 }
> +    };
> +
> +  for (;;)
> +    {
> +      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
> +			   &oind, &oarg);
> +
> +      if (opt < 0)
> +        break;
> +
> +      switch ((enum opt) opt)
> +        {
> +	case OPT_CONDITION:
> +	  condition.assign (oarg);
> +	  break;
> +	case OPT_DISABLED:
> +	  enabled = 0;
> +	  break;
> +	case OPT_EXCEPTION_NAME:
> +	  exception_name = oarg;
> +	  break;
> +	case OPT_TEMP:
> +	  temp = 1;
> +	  break;
> +        }
> +    }
> +
> +  /* This command does not accept any argument.  Make sure the user
> +     did not provide any.  */
> +  if (oind != argc)
> +    error (_("Invalid argument: %s"), argv[oind]);
> +
> +  scoped_restore restore_breakpoint_reporting
> +    = setup_breakpoint_reporting ();
> +  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
> +     xstrdup'ed, and will assume control of its lifetime.  */
> +  if (exception_name != NULL)
> +    exception_name = xstrdup (exception_name);
> +  create_ada_exception_catchpoint (gdbarch, ex_kind,
> +				   exception_name,
> +				   condition, temp, enabled, 0);
>  }
>  
>  /* Common path for the -catch-load and -catch-unload.  */
> diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
> index c9ffda1..51014ed 100644
> --- a/gdb/mi/mi-cmds.c
> +++ b/gdb/mi/mi-cmds.c
> @@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
>                     &mi_suppress_notification.breakpoint),
>    DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
>                     &mi_suppress_notification.breakpoint),
> +  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
> +                   &mi_suppress_notification.breakpoint),
>    DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
>                     &mi_suppress_notification.breakpoint),
>    DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
> diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
> index c27f3ba..af96585 100644
> --- a/gdb/mi/mi-cmds.h
> +++ b/gdb/mi/mi-cmds.h
> @@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
>  extern mi_cmd_argv_ftype mi_cmd_break_watch;
>  extern mi_cmd_argv_ftype mi_cmd_catch_assert;
>  extern mi_cmd_argv_ftype mi_cmd_catch_exception;
> +extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
>  extern mi_cmd_argv_ftype mi_cmd_catch_load;
>  extern mi_cmd_argv_ftype mi_cmd_catch_unload;
>  extern mi_cmd_argv_ftype mi_cmd_disassemble;
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
> new file mode 100644
> index 0000000..0137add
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
> @@ -0,0 +1,137 @@
> +# Copyright 2011-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 "ada.exp"
> +
> +standard_ada_testfile foo
> +
> +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
> +  return -1
> +}
> +
> +# A global variable used to simplify the maintenance of some of
> +# the regular expressions below.
> +set eol "\[\r\n\]+"
> +
> +# Before going any further, verify that we can insert exception
> +# handlers catchpoints...  That way, we won't have to do this while
> +# doing the actual GDB/MI testing.
> +
> +clean_restart ${testfile}
> +
> +if ![runto_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +set msg "insert catchpoint on all Ada exceptions handlers"
> +gdb_test_multiple "catch handlers" $msg {
> +    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
> +	pass $msg
> +    }
> +    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
> +	# If the runtime was not built with enough debug information,
> +	# or if it was stripped, we can not test exception
> +	# catchpoints.
> +	unsupported $msg
> +	return -1
> +    }
> +}
> +
> +# Now, we can start the GDB/MI testing itself...
> +
> +load_lib mi-support.exp
> +set MIFLAGS "-i=mi"
> +
> +gdb_exit
> +if [mi_gdb_start] {
> +    continue
> +}
> +
> +#############################################
> +# 1. Try catching all exceptions handlers.  #
> +#############################################
> +
> +if ![mi_run_to_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +mi_gdb_test "-catch-handlers" \
> +            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
> +            "catch all exceptions handlers"
> +
> +# Continue to exception handler.
> +
> +proc continue_to_exception_handler { test line } {
> +
> +    global decimal
> +
> +    mi_send_resuming_command "exec-continue" "$test"
> +
> +    # Now MI stream output.
> +    mi_expect_stop \
> +	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
> +	"foo" "" ".*" "$line" \
> +	".*" \
> +        $test
> +}
> +
> +# We don't have the exception name info when stopping at the exception handlers
> +# breakpoint so we use source line to check if the inferior stops at the

breakpoint -> catchpoint.

No other comments past this point.

> +# right location.
> +
> +set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
> +continue_to_exception_handler \
> +    "continue until CE handling caught by all-exceptions handlers catchpoint" \
> +    "$bp_ce_location"
> +
> +set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
> +continue_to_exception_handler \
> +    "continue until PE handling caught by all-exceptions handlers catchpoint" \
> +    "$bp_pe_location"
> +
> +##########################################################
> +# 2. Try catching only some of the exceptions handlers.  #
> +##########################################################
> +
> +# Here is the scenario:
> +#  - Restart the debugger from scratch, runto_main
> +#  - We'll catch only "Constraint_Error handlers"
> +#  - continue, we should stop at the Constraint_Error exception handler
> +#  - continue, we should not stop at the Program_Error exception handler
> +#    but exit instead.
> +
> +if ![mi_run_to_main] then {
> +   fail "cannot run to main, testcase aborted"
> +   return 0
> +}
> +
> +mi_gdb_test "-catch-handlers -e Constraint_Error" \
> +            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
> +            "catch Constraint_Error"
> +
> +mi_execute_to "exec-continue" \
> +              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
> +              "foo" "" ".*" "$bp_ce_location" \
> +              ".*" \
> +              "continue to exception catchpoint hit"
> +
> +# Exit the inferior.
> +mi_send_resuming_command "exec-continue" "continuing to inferior exit"
> +mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
> +
> +mi_gdb_exit
> +return 0
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
> new file mode 100644
> index 0000000..da701a3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
> @@ -0,0 +1,33 @@
> +--  Copyright 2007-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/>.
> +
> +procedure Foo is
> +begin
> +
> +   begin
> +      raise Constraint_Error;
> +   exception
> +      when Constraint_Error => -- BREAK1
> +         null;
> +   end;
> +
> +   begin
> +      raise Program_Error;
> +   exception
> +      when Program_Error => -- BREAK2
> +         null;
> +   end;
> +
> +end Foo;
> -- 
> 2.7.4

-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition
  2018-01-23 11:43 ` Joel Brobecker
                     ` (4 preceding siblings ...)
  2018-01-30  9:23   ` [PATCHv2 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
@ 2018-01-30  9:23   ` Xavier Roirand
  2018-01-31  4:39     ` Joel Brobecker
  2018-01-30  9:24   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
  2018-01-30  9:24   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-30  9:23 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_assert.exp: New testcase.
    * gdb.ada/mi_catch_assert/bla.adb: New file.
    * gdb.ada/mi_catch_assert/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/mi_catch_assert.exp     | 96 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb | 46 +++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads | 19 ++++++
 3 files changed, 161 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads

diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert.exp b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
new file mode 100644
index 0000000..a168251
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
@@ -0,0 +1,96 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# Some global variables used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+# Before going any further, verify that we can insert exception
+# catchpoints...  That way, we won't have to do this while doing
+# the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+###################################################
+# 2. Try catching conditionnal failed assertion.  #
+###################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-assert -c \"Global_Var = 2\"" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"failed Ada assertions\",.*,cond=\"Global_Var = 2\",.*}" \
+            "catch assert failures with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal" \
+              "bla" "" ".*" "$bp_location" \
+              ".*" \
+              "continue to assert failure catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCHv2 1/4] (Ada) Add testcase for catch assert with condition
  2018-01-23 11:43 ` Joel Brobecker
                     ` (3 preceding siblings ...)
  2018-01-29 12:47   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
@ 2018-01-30  9:23   ` Xavier Roirand
  2018-01-31  4:37     ` Joel Brobecker
  2018-01-30  9:23   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-30  9:23 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

gdb/testsuite/ChangeLog:

    * gdb.ada/catch_assert_if.exp: New testcase.
    * gdb.ada/catch_assert_if/bla.adb: New file.
    * gdb.ada/catch_assert_if/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/catch_assert_if.exp     | 86 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb | 46 ++++++++++++++
 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads | 19 ++++++
 3 files changed, 151 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if.exp
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads

diff --git a/gdb/testsuite/gdb.ada/catch_assert_if.exp b/gdb/testsuite/gdb.ada/catch_assert_if.exp
new file mode 100644
index 0000000..a6d5dc3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if.exp
@@ -0,0 +1,86 @@
+# 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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+   return -1
+}
+
+clean_restart ${testfile}
+
+######################################################################
+# 1. Try catching all exceptions to check that runtime supports it.  #
+######################################################################
+
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*$eol$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+##################################################
+# 2. Try catching conditional failed assertion.  #
+##################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+gdb_test "catch assert if Global_Var = 2" \
+         "Catchpoint $decimal: failed Ada assertions" \
+         "insert catchpoint on failed assertions with condition"
+
+# Check that condition is stored and properly displayed.
+
+set exp_bp ".*$decimal${sp}breakpoint${sp}keep${sp}y${sp}$hex failed Ada assertions$eol${sp}stop only if Global_Var = 2.*"
+gdb_test "info breakpoint" $exp_bp "Check catch assertions with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+
+set catchpoint_msg \
+  "Catchpoint $decimal, failed assertion at $hex in bla \\\(\\\).*at .*bla.adb:$bp_location"
+gdb_test "continue" \
+         "Continuing\.$eol$catchpoint_msg$eol.*STOP" \
+         "continuing to expected failed assertion"
+
+gdb_test "continue" \
+         "Continuing\..*$inferior_exited_re.*" \
+         "continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-23 11:43 ` Joel Brobecker
                     ` (5 preceding siblings ...)
  2018-01-30  9:23   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
@ 2018-01-30  9:24   ` Xavier Roirand
  2018-01-31  4:45     ` Joel Brobecker
  2018-01-30  9:24   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-30  9:24 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

Following my previous commit which add support for stopping at start of
exception handler, this commit adds required gdb-mi support for this
feature.

gdb/ChangeLog:

    * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
    * mi/mi-cmds.c (mi_cmds): Add catch-handlers command.
    * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
    * NEWS: Document "-catch-handlers" command.

gdb/doc/ChangeLog:

    * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
    documentation for new "-catch-handlers" command.

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_ex_hand.exp: New testcase.
    * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

Tested on x86_64-linux.
---
 gdb/NEWS                                       |   4 +
 gdb/doc/gdb.texinfo                            |  44 ++++++++
 gdb/mi/mi-cmd-catch.c                          |  72 ++++++++++++-
 gdb/mi/mi-cmds.c                               |   2 +
 gdb/mi/mi-cmds.h                               |   1 +
 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
 7 files changed, 291 insertions(+), 2 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb

diff --git a/gdb/NEWS b/gdb/NEWS
index f69173a..9cd38f3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -377,6 +377,10 @@ show disassembler-options
   List the shared libraries in the program.  This is
   equivalent to the CLI command "info shared".
 
+-catch-handlers
+  Catchpoints stopping the program when Ada exceptions are
+  handled.  This is equivalent to the CLI command "catch handlers".
+
 *** Changes in GDB 7.12
 
 * GDB and GDBserver now build with a C++ compiler by default.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9ddfba5..4ed5f6b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28537,6 +28537,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
 (gdb)
 @end smallexample
 
+@subheading The @code{-catch-handlers} Command
+@findex -catch-handlers
+
+@subsubheading Synopsis
+
+@smallexample
+ -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
+    [ -t ]
+@end smallexample
+
+Add a catchpoint stopping when Ada exceptions are handled.
+By default, the command stops the program when any Ada exception
+gets handled.  But it is also possible, by using some of the
+optional parameters described below, to create more selective
+catchpoints.
+
+The possible optional parameters for this command are:
+
+@table @samp
+@item -c @var{condition}
+Make the catchpoint conditional on @var{condition}.
+@item -d
+Create a disabled catchpoint.
+@item -e @var{exception-name}
+Only stop when @var{exception-name} is handled.
+@item -t
+Create a temporary catchpoint.
+@end table
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{catch handlers}.
+
+@subsubheading Example
+
+@smallexample
+-catch-handlers -e Constraint_Error
+^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
+enabled="y",addr="0x0000000000402f68",
+what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
+times="0",original-location="__gnat_begin_handler"@}
+(gdb)
+@end smallexample
+
 @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 @node GDB/MI Program Context
 @section @sc{gdb/mi}  Program Context
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index a0f311a..078e73a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -157,8 +157,76 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
-				   exception_name, condition,
-				   temp, enabled, 0);
+				   exception_name,
+				   condition, temp, enabled, 0);
+}
+
+/* Handler for the -catch-handlers command.  */
+
+void
+mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
+{
+  struct gdbarch *gdbarch = get_current_arch ();
+  std::string condition;
+  int enabled = 1;
+  char *exception_name = NULL;
+  int temp = 0;
+
+  int oind = 0;
+  char *oarg;
+
+  enum opt
+    {
+      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
+    };
+  static const struct mi_opt opts[] =
+    {
+      { "c", OPT_CONDITION, 1},
+      { "d", OPT_DISABLED, 0 },
+      { "e", OPT_EXCEPTION_NAME, 1 },
+      { "t", OPT_TEMP, 0 },
+      { 0, 0, 0 }
+    };
+
+  for (;;)
+    {
+      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
+			   &oind, &oarg);
+
+      if (opt < 0)
+        break;
+
+      switch ((enum opt) opt)
+        {
+	case OPT_CONDITION:
+	  condition.assign (oarg);
+	  break;
+	case OPT_DISABLED:
+	  enabled = 0;
+	  break;
+	case OPT_EXCEPTION_NAME:
+	  exception_name = oarg;
+	  break;
+	case OPT_TEMP:
+	  temp = 1;
+	  break;
+        }
+    }
+
+  /* This command does not accept any argument.  Make sure the user
+     did not provide any.  */
+  if (oind != argc)
+    error (_("Invalid argument: %s"), argv[oind]);
+
+  scoped_restore restore_breakpoint_reporting
+    = setup_breakpoint_reporting ();
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
+  if (exception_name != NULL)
+    exception_name = xstrdup (exception_name);
+  create_ada_exception_catchpoint (gdbarch, ada_catch_handlers,
+				   exception_name,
+				   condition, temp, enabled, 0);
 }
 
 /* Common path for the -catch-load and -catch-unload.  */
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index c9ffda1..51014ed 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
                    &mi_suppress_notification.breakpoint),
+  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
+                   &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index c27f3ba..af96585 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
 extern mi_cmd_argv_ftype mi_cmd_break_watch;
 extern mi_cmd_argv_ftype mi_cmd_catch_assert;
 extern mi_cmd_argv_ftype mi_cmd_catch_exception;
+extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
 extern mi_cmd_argv_ftype mi_cmd_catch_load;
 extern mi_cmd_argv_ftype mi_cmd_catch_unload;
 extern mi_cmd_argv_ftype mi_cmd_disassemble;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
new file mode 100644
index 0000000..2745a44
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
@@ -0,0 +1,137 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# A global variable used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+
+# Before going any further, verify that we can insert exception
+# handlers catchpoints...  That way, we won't have to do this while
+# doing the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions handlers"
+gdb_test_multiple "catch handlers" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+#############################################
+# 1. Try catching all exceptions handlers.  #
+#############################################
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
+            "catch all exceptions handlers"
+
+# Continue to exception handler.
+
+proc continue_to_exception_handler { test line } {
+
+    global decimal
+
+    mi_send_resuming_command "exec-continue" "$test"
+
+    # Now MI stream output.
+    mi_expect_stop \
+	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+	"foo" "" ".*" "$line" \
+	".*" \
+        $test
+}
+
+# We don't have the exception name info when stopping at the exception handlers
+# breakpoints so we use source line to check if the inferior stops at the
+# right location.
+
+set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until CE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_ce_location"
+
+set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until PE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_pe_location"
+
+##########################################################
+# 2. Try catching only some of the exceptions handlers.  #
+##########################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#  - We'll catch only "Constraint_Error handlers"
+#  - continue, we should stop at the Constraint_Error exception handler
+#  - continue, we should not stop at the Program_Error exception handler
+#    but exit instead.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers -e Constraint_Error" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
+            "catch Constraint_Error"
+
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+              "foo" "" ".*" "$bp_ce_location" \
+              ".*" \
+              "continue to exception catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
new file mode 100644
index 0000000..da701a3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
@@ -0,0 +1,33 @@
+--  Copyright 2007-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/>.
+
+procedure Foo is
+begin
+
+   begin
+      raise Constraint_Error;
+   exception
+      when Constraint_Error => -- BREAK1
+         null;
+   end;
+
+   begin
+      raise Program_Error;
+   exception
+      when Program_Error => -- BREAK2
+         null;
+   end;
+
+end Foo;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] (Ada) C++fy conditional string when catching exception.
  2018-01-23 11:43 ` Joel Brobecker
                     ` (6 preceding siblings ...)
  2018-01-30  9:24   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
@ 2018-01-30  9:24   ` Xavier Roirand
  2018-01-31  4:41     ` Joel Brobecker
  7 siblings, 1 reply; 27+ messages in thread
From: Xavier Roirand @ 2018-01-30  9:24 UTC (permalink / raw)
  To: gdb-patches; +Cc: Xavier Roirand, brobecker

This commit C++fy the conditional string used when catching Ada exception.

gdb/ChangeLog:

        * ada-lang.c (catch_ada_exception_command_split)
        (create_ada_exception_catchpoint) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_ada_exception_command, catch_ada_handlers_command): Use
        C++ string instead of char* for conditional var.
        (catch_ada_assert_command_split) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_assert_command): Use C++ string instead of char* for
        conditional var.
        * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
        Update declaration.
        * mi/mi-cmd-catch.c (mi_cmd_catch_assert, mi_cmd_catch_exception):
        Use std::string instead of char* for condition string.

Tested on x86_64-linux.
---
 gdb/ada-lang.c        | 27 ++++++++++++++-------------
 gdb/ada-lang.h        |  4 ++--
 gdb/mi/mi-cmd-catch.c | 18 ++++++------------
 3 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3ff7169..0da58d9 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13142,7 +13142,7 @@ catch_ada_exception_command_split (const char *args,
 				   bool is_catch_handlers_cmd,
                                    enum ada_exception_catchpoint_kind *ex,
 				   char **excep_string,
-				   char **cond_string)
+				   std::string &cond_string)
 {
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   char *exception_name;
@@ -13209,7 +13209,8 @@ catch_ada_exception_command_split (const char *args,
       *ex = ada_catch_exception;
       *excep_string = exception_name;
     }
-  *cond_string = cond;
+  if (cond != NULL)
+    cond_string.assign (cond);
 }
 
 /* Return the name of the symbol on which we should break in order to
@@ -13400,7 +13401,7 @@ void
 create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 enum ada_exception_catchpoint_kind ex_kind,
 				 char *excep_string,
-				 char *cond_string,
+				 const std::string &cond_string,
 				 int tempflag,
 				 int disabled,
 				 int from_tty)
@@ -13415,8 +13416,8 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 ops, tempflag, disabled, from_tty);
   c->excep_string = excep_string;
   create_excep_cond_exprs (c.get (), ex_kind);
-  if (cond_string != NULL)
-    set_breakpoint_condition (c.get (), cond_string, from_tty);
+  if (!cond_string.empty ())
+    set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
   install_breakpoint (0, std::move (c), 1);
 }
 
@@ -13431,14 +13432,14 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13456,14 +13457,14 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13479,7 +13480,7 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
    (the memory needs to be deallocated after use).  */
 
 static void
-catch_ada_assert_command_split (const char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string &cond_string)
 {
   args = skip_spaces (args);
 
@@ -13491,7 +13492,7 @@ catch_ada_assert_command_split (const char *args, char **cond_string)
       args = skip_spaces (args);
       if (args[0] == '\0')
         error (_("condition missing after `if' keyword"));
-      *cond_string = xstrdup (args);
+      cond_string.assign (args);
     }
 
   /* Otherwise, there should be no other argument at the end of
@@ -13509,13 +13510,13 @@ catch_assert_command (const char *arg_entry, int from_tty,
   const char *arg = arg_entry;
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
-  catch_ada_assert_command_split (arg, &cond_string);
+  catch_ada_assert_command_split (arg, cond_string);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, cond_string,
 				   tempflag, 1 /* enabled */,
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index bac6c06..1f6ea77 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -379,8 +379,8 @@ extern std::string ada_name_for_lookup (const char *name);
 
 extern void create_ada_exception_catchpoint
   (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
-   char *excep_string, char *cond_string, int tempflag, int disabled,
-   int from_tty);
+   char *excep_string, const std::string &cond_string, int tempflag,
+   int disabled, int from_tty);
 
 /* Some information about a given Ada exception.  */
 
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index 38b96cc..a0f311a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -32,7 +32,7 @@ void
 mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   int temp = 0;
 
@@ -62,7 +62,7 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -79,10 +79,6 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
     error (_("Invalid argument: %s"), argv[oind]);
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs CONDITION to be xstrdup'ed,
-     and will assume control of its lifetime.  */
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, condition, temp, enabled, 0);
 }
@@ -93,7 +89,7 @@ void
 mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   char *exception_name = NULL;
   int temp = 0;
@@ -128,7 +124,7 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -156,12 +152,10 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
     error (_("\"-e\" and \"-u\" are mutually exclusive"));
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs EXCEPTION_NAME and CONDITION
-     to be xstrdup'ed, and will assume control of their lifetime.  */
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   exception_name, condition,
 				   temp, enabled, 0);
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCHv2 1/4] (Ada) Add testcase for catch assert with condition
  2018-01-30  9:23   ` [PATCHv2 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
@ 2018-01-31  4:37     ` Joel Brobecker
  2018-01-31 12:52       ` pushed: [PATCH " Xavier Roirand
                         ` (6 more replies)
  0 siblings, 7 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-31  4:37 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/catch_assert_if.exp: New testcase.
>     * gdb.ada/catch_assert_if/bla.adb: New file.
>     * gdb.ada/catch_assert_if/pck.ads: New file.

This patch is approved.

-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition
  2018-01-30  9:23   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
@ 2018-01-31  4:39     ` Joel Brobecker
  0 siblings, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-31  4:39 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/mi_catch_assert.exp: New testcase.
>     * gdb.ada/mi_catch_assert/bla.adb: New file.
>     * gdb.ada/mi_catch_assert/pck.ads: New file.

OK as well.

Thank you,
-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/4] (Ada) C++fy conditional string when catching exception.
  2018-01-30  9:24   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
@ 2018-01-31  4:41     ` Joel Brobecker
  0 siblings, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-31  4:41 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

> This commit C++fy the conditional string used when catching Ada exception.
> 
> gdb/ChangeLog:
> 
>         * ada-lang.c (catch_ada_exception_command_split)
>         (create_ada_exception_catchpoint) <cond_string>: Change parameter
>         type.  Update code accordingly.
>         (catch_ada_exception_command, catch_ada_handlers_command): Use
>         C++ string instead of char* for conditional var.
>         (catch_ada_assert_command_split) <cond_string>: Change parameter
>         type.  Update code accordingly.
>         (catch_assert_command): Use C++ string instead of char* for
>         conditional var.
>         * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
>         Update declaration.
>         * mi/mi-cmd-catch.c (mi_cmd_catch_assert, mi_cmd_catch_exception):
>         Use std::string instead of char* for condition string.

Approved.

Thank you,
-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-30  9:24   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
@ 2018-01-31  4:45     ` Joel Brobecker
  0 siblings, 0 replies; 27+ messages in thread
From: Joel Brobecker @ 2018-01-31  4:45 UTC (permalink / raw)
  To: Xavier Roirand; +Cc: gdb-patches

On Tue, Jan 30, 2018 at 10:24:12AM +0100, Xavier Roirand wrote:
> Following my previous commit which add support for stopping at start of
> exception handler, this commit adds required gdb-mi support for this
> feature.
> 
> gdb/ChangeLog:
> 
>     * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
>     * mi/mi-cmds.c (mi_cmds): Add catch-handlers command.
>     * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
>     * NEWS: Document "-catch-handlers" command.
> 
> gdb/doc/ChangeLog:
> 
>     * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
>     documentation for new "-catch-handlers" command.
> 
> gdb/testsuite/ChangeLog:
> 
>     * gdb.ada/mi_catch_ex_hand.exp: New testcase.
>     * gdb.ada/mi_catch_ex_hand/foo.adb: New file.
> 
> Tested on x86_64-linux.

One minor issue where you misunderstood what I was suggesting:

> +# We don't have the exception name info when stopping at the exception handlers
> +# breakpoints so we use source line to check if the inferior stops at the

I wasn't suggesting you pluralize "breakpoints" (although, not a bad
idea), but rather use "catchpoint" rather than "breakpoint". From
the user's perspective, we are stopping at a catchpoint, not a
breakpoint.

Pre-approved with that change made.
-- 
Joel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* pushed: [PATCH 1/4] (Ada) Add testcase for catch assert with condition
  2018-01-31  4:37     ` Joel Brobecker
@ 2018-01-31 12:52       ` Xavier Roirand
  2018-01-31 12:53       ` [PATCH 2/4] (Ada/MI) Add testcase for mi " Xavier Roirand
                         ` (5 subsequent siblings)
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 12:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

gdb/testsuite/ChangeLog:

    * gdb.ada/catch_assert_if.exp: New testcase.
    * gdb.ada/catch_assert_if/bla.adb: New file.
    * gdb.ada/catch_assert_if/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/catch_assert_if.exp     | 86 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb | 46 ++++++++++++++
 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads | 19 ++++++
 3 files changed, 151 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if.exp
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/catch_assert_if/pck.ads

diff --git a/gdb/testsuite/gdb.ada/catch_assert_if.exp b/gdb/testsuite/gdb.ada/catch_assert_if.exp
new file mode 100644
index 0000000..9d00f1c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if.exp
@@ -0,0 +1,86 @@
+# 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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+   return -1
+}
+
+clean_restart ${testfile}
+
+######################################################################
+# 1. Try catching all exceptions to check that runtime supports it.  #
+######################################################################
+
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*$eol$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+###################################################
+# 2. Try catching conditionnal failed assertion.  #
+###################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+gdb_test "catch assert if Global_Var = 2" \
+         "Catchpoint $decimal: failed Ada assertions" \
+         "insert catchpoint on failed assertions with condition"
+
+# Check that condition is stored and properly displayed.
+
+set exp_bp ".*$decimal${sp}breakpoint${sp}keep${sp}y${sp}$hex failed Ada assertions$eol${sp}stop only if Global_Var = 2.*"
+gdb_test "info breakpoint" $exp_bp "Check catch handlers with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+
+set catchpoint_msg \
+  "Catchpoint $decimal, failed assertion at $hex in bla \\\(\\\).*at .*bla.adb:$decimal"
+gdb_test "continue" \
+         "Continuing\.$eol$catchpoint_msg$eol.*STOP" \
+         "continuing to expected failed assertion"
+
+gdb_test "continue" \
+         "Continuing\..*$inferior_exited_re.*" \
+         "continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/catch_assert_if/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] (Ada) C++fy conditional string when catching exception.
  2018-01-31  4:37     ` Joel Brobecker
  2018-01-31 12:52       ` pushed: [PATCH " Xavier Roirand
  2018-01-31 12:53       ` [PATCH 2/4] (Ada/MI) Add testcase for mi " Xavier Roirand
@ 2018-01-31 12:53       ` Xavier Roirand
  2018-01-31 12:54       ` pushed: " Xavier Roirand
                         ` (3 subsequent siblings)
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 12:53 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

This commit C++fy the conditional string used when catching Ada exception.

gdb/ChangeLog:

        * ada-lang.c (catch_ada_exception_command_split)
        (create_ada_exception_catchpoint) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_ada_exception_command, catch_ada_handlers_command): Use
        C++ string instead of char* for conditional var.
        (catch_ada_assert_command_split) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_assert_command): Use C++ string instead of char* for
        conditional var.
        * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
        Update declaration.
        * mi/mi-cmd-catch.c (mi_cmd_catch_assert, mi_cmd_catch_exception:
        Use std::string instead of char* for condition string.

Tested on x86_64-linux.
---
 gdb/ada-lang.c        | 27 ++++++++++++++-------------
 gdb/ada-lang.h        |  4 ++--
 gdb/mi/mi-cmd-catch.c | 18 ++++++------------
 3 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3ff7169..0da58d9 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13142,7 +13142,7 @@ catch_ada_exception_command_split (const char *args,
 				   bool is_catch_handlers_cmd,
                                    enum ada_exception_catchpoint_kind *ex,
 				   char **excep_string,
-				   char **cond_string)
+				   std::string &cond_string)
 {
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   char *exception_name;
@@ -13209,7 +13209,8 @@ catch_ada_exception_command_split (const char *args,
       *ex = ada_catch_exception;
       *excep_string = exception_name;
     }
-  *cond_string = cond;
+  if (cond != NULL)
+    cond_string.assign (cond);
 }
 
 /* Return the name of the symbol on which we should break in order to
@@ -13400,7 +13401,7 @@ void
 create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 enum ada_exception_catchpoint_kind ex_kind,
 				 char *excep_string,
-				 char *cond_string,
+				 const std::string &cond_string,
 				 int tempflag,
 				 int disabled,
 				 int from_tty)
@@ -13415,8 +13416,8 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 ops, tempflag, disabled, from_tty);
   c->excep_string = excep_string;
   create_excep_cond_exprs (c.get (), ex_kind);
-  if (cond_string != NULL)
-    set_breakpoint_condition (c.get (), cond_string, from_tty);
+  if (!cond_string.empty ())
+    set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
   install_breakpoint (0, std::move (c), 1);
 }
 
@@ -13431,14 +13432,14 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13456,14 +13457,14 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13479,7 +13480,7 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
    (the memory needs to be deallocated after use).  */
 
 static void
-catch_ada_assert_command_split (const char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string &cond_string)
 {
   args = skip_spaces (args);
 
@@ -13491,7 +13492,7 @@ catch_ada_assert_command_split (const char *args, char **cond_string)
       args = skip_spaces (args);
       if (args[0] == '\0')
         error (_("condition missing after `if' keyword"));
-      *cond_string = xstrdup (args);
+      cond_string.assign (args);
     }
 
   /* Otherwise, there should be no other argument at the end of
@@ -13509,13 +13510,13 @@ catch_assert_command (const char *arg_entry, int from_tty,
   const char *arg = arg_entry;
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
-  catch_ada_assert_command_split (arg, &cond_string);
+  catch_ada_assert_command_split (arg, cond_string);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, cond_string,
 				   tempflag, 1 /* enabled */,
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index bac6c06..1f6ea77 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -379,8 +379,8 @@ extern std::string ada_name_for_lookup (const char *name);
 
 extern void create_ada_exception_catchpoint
   (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
-   char *excep_string, char *cond_string, int tempflag, int disabled,
-   int from_tty);
+   char *excep_string, const std::string &cond_string, int tempflag,
+   int disabled, int from_tty);
 
 /* Some information about a given Ada exception.  */
 
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index 38b96cc..a0f311a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -32,7 +32,7 @@ void
 mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   int temp = 0;
 
@@ -62,7 +62,7 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -79,10 +79,6 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
     error (_("Invalid argument: %s"), argv[oind]);
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs CONDITION to be xstrdup'ed,
-     and will assume control of its lifetime.  */
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, condition, temp, enabled, 0);
 }
@@ -93,7 +89,7 @@ void
 mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   char *exception_name = NULL;
   int temp = 0;
@@ -128,7 +124,7 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -156,12 +152,10 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
     error (_("\"-e\" and \"-u\" are mutually exclusive"));
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs EXCEPTION_NAME and CONDITION
-     to be xstrdup'ed, and will assume control of their lifetime.  */
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   exception_name, condition,
 				   temp, enabled, 0);
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition
  2018-01-31  4:37     ` Joel Brobecker
  2018-01-31 12:52       ` pushed: [PATCH " Xavier Roirand
@ 2018-01-31 12:53       ` Xavier Roirand
  2018-01-31 12:53       ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
                         ` (4 subsequent siblings)
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 12:53 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_assert.exp: New testcase.
    * gdb.ada/mi_catch_assert/bla.adb: New file.
    * gdb.ada/mi_catch_assert/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/mi_catch_assert.exp     | 99 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb | 46 +++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads | 19 +++++
 3 files changed, 164 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads

diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert.exp b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
new file mode 100644
index 0000000..ff8943c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
@@ -0,0 +1,99 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# Some global variables used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+# Before going any further, verify that we can insert exception
+# catchpoints...  That way, we won't have to do this while doing
+# the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+###################################################
+# 2. Try catching conditionnal failed assertion.  #
+###################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-assert -c \"Global_Var = 2\"" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"failed Ada assertions\",.*}" \
+            "catch assert failures with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal" \
+              "bla" "" ".*" "$bp_location" \
+              ".*" \
+              "continue to assert failure catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* pushed: [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition
  2018-01-31  4:37     ` Joel Brobecker
                         ` (3 preceding siblings ...)
  2018-01-31 12:54       ` pushed: " Xavier Roirand
@ 2018-01-31 12:54       ` Xavier Roirand
  2018-01-31 12:54       ` pushed: [PATCH] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
  2018-01-31 13:03       ` pushed: [PATCH 4/4] " Xavier Roirand
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 12:54 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_assert.exp: New testcase.
    * gdb.ada/mi_catch_assert/bla.adb: New file.
    * gdb.ada/mi_catch_assert/pck.ads: New file.

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.ada/mi_catch_assert.exp     | 99 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb | 46 +++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads | 19 +++++
 3 files changed, 164 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads

diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert.exp b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
new file mode 100644
index 0000000..ff8943c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert.exp
@@ -0,0 +1,99 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile bla
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# Some global variables used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+# Before going any further, verify that we can insert exception
+# catchpoints...  That way, we won't have to do this while doing
+# the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions"
+gdb_test_multiple "catch exception" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+###################################################
+# 2. Try catching conditionnal failed assertion.  #
+###################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#    We'll catch assertions if Global_Var = 2
+#  - continue, we should see the second failed assertion
+#  - continue, the program exits.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-assert -c \"Global_Var = 2\"" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"failed Ada assertions\",.*}" \
+            "catch assert failures with condition"
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/bla.adb]
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal" \
+              "bla" "" ".*" "$bp_location" \
+              ".*" \
+              "continue to assert failure catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
new file mode 100644
index 0000000..6b3b2e7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/bla.adb
@@ -0,0 +1,46 @@
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Bla is
+begin
+   Global_Var := 1;
+   declare
+   begin
+      pragma Assert (Global_Var /= 1, "Error #1");
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 2;
+   declare
+   begin
+      pragma Assert (Global_Var = 1, "Error #2"); -- STOP
+   exception
+      when others =>
+         null;
+   end;
+
+   Global_Var := 3;
+   declare
+   begin
+      pragma Assert (Global_Var = 2, "Error #3");
+   exception
+      when others =>
+         null;
+   end;
+end Bla;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
new file mode 100644
index 0000000..f00f5b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_assert/pck.ads
@@ -0,0 +1,19 @@
+--  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/>.
+
+package Pck is
+   Global_Var : Integer := 0;
+end Pck;
+
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* pushed: [PATCH] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-31  4:37     ` Joel Brobecker
                         ` (4 preceding siblings ...)
  2018-01-31 12:54       ` pushed: [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
@ 2018-01-31 12:54       ` Xavier Roirand
  2018-01-31 13:03       ` pushed: [PATCH 4/4] " Xavier Roirand
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 12:54 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

Following my previous commit which add support for stopping at start of
exception handler, this commit adds required gdb-mi support for this
feature.

gdb/ChangeLog:

    * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
    * mi/mi-cmds.c (mi_cmds): Add catch-handlers command.
    * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
    * NEWS: Document "-catch-handlers" command.

gdb/doc/ChangeLog:

    * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
    documentation for new "-catch-handlers" command.

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_ex_hand.exp: New testcase.
    * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

Tested on x86_64-linux.
---
 gdb/NEWS                                       |   4 +
 gdb/doc/gdb.texinfo                            |  44 ++++++++
 gdb/mi/mi-cmd-catch.c                          |  72 ++++++++++++-
 gdb/mi/mi-cmds.c                               |   2 +
 gdb/mi/mi-cmds.h                               |   1 +
 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
 7 files changed, 291 insertions(+), 2 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb

diff --git a/gdb/NEWS b/gdb/NEWS
index f69173a..9cd38f3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -377,6 +377,10 @@ show disassembler-options
   List the shared libraries in the program.  This is
   equivalent to the CLI command "info shared".
 
+-catch-handlers
+  Catchpoints stopping the program when Ada exceptions are
+  handled.  This is equivalent to the CLI command "catch handlers".
+
 *** Changes in GDB 7.12
 
 * GDB and GDBserver now build with a C++ compiler by default.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9ddfba5..4ed5f6b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28537,6 +28537,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
 (gdb)
 @end smallexample
 
+@subheading The @code{-catch-handlers} Command
+@findex -catch-handlers
+
+@subsubheading Synopsis
+
+@smallexample
+ -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
+    [ -t ]
+@end smallexample
+
+Add a catchpoint stopping when Ada exceptions are handled.
+By default, the command stops the program when any Ada exception
+gets handled.  But it is also possible, by using some of the
+optional parameters described below, to create more selective
+catchpoints.
+
+The possible optional parameters for this command are:
+
+@table @samp
+@item -c @var{condition}
+Make the catchpoint conditional on @var{condition}.
+@item -d
+Create a disabled catchpoint.
+@item -e @var{exception-name}
+Only stop when @var{exception-name} is handled.
+@item -t
+Create a temporary catchpoint.
+@end table
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{catch handlers}.
+
+@subsubheading Example
+
+@smallexample
+-catch-handlers -e Constraint_Error
+^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
+enabled="y",addr="0x0000000000402f68",
+what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
+times="0",original-location="__gnat_begin_handler"@}
+(gdb)
+@end smallexample
+
 @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 @node GDB/MI Program Context
 @section @sc{gdb/mi}  Program Context
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index a0f311a..078e73a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -157,8 +157,76 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
-				   exception_name, condition,
-				   temp, enabled, 0);
+				   exception_name,
+				   condition, temp, enabled, 0);
+}
+
+/* Handler for the -catch-handlers command.  */
+
+void
+mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
+{
+  struct gdbarch *gdbarch = get_current_arch ();
+  std::string condition;
+  int enabled = 1;
+  char *exception_name = NULL;
+  int temp = 0;
+
+  int oind = 0;
+  char *oarg;
+
+  enum opt
+    {
+      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
+    };
+  static const struct mi_opt opts[] =
+    {
+      { "c", OPT_CONDITION, 1},
+      { "d", OPT_DISABLED, 0 },
+      { "e", OPT_EXCEPTION_NAME, 1 },
+      { "t", OPT_TEMP, 0 },
+      { 0, 0, 0 }
+    };
+
+  for (;;)
+    {
+      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
+			   &oind, &oarg);
+
+      if (opt < 0)
+        break;
+
+      switch ((enum opt) opt)
+        {
+	case OPT_CONDITION:
+	  condition.assign (oarg);
+	  break;
+	case OPT_DISABLED:
+	  enabled = 0;
+	  break;
+	case OPT_EXCEPTION_NAME:
+	  exception_name = oarg;
+	  break;
+	case OPT_TEMP:
+	  temp = 1;
+	  break;
+        }
+    }
+
+  /* This command does not accept any argument.  Make sure the user
+     did not provide any.  */
+  if (oind != argc)
+    error (_("Invalid argument: %s"), argv[oind]);
+
+  scoped_restore restore_breakpoint_reporting
+    = setup_breakpoint_reporting ();
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
+  if (exception_name != NULL)
+    exception_name = xstrdup (exception_name);
+  create_ada_exception_catchpoint (gdbarch, ada_catch_handlers,
+				   exception_name,
+				   condition, temp, enabled, 0);
 }
 
 /* Common path for the -catch-load and -catch-unload.  */
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index c9ffda1..51014ed 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
                    &mi_suppress_notification.breakpoint),
+  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
+                   &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index c27f3ba..af96585 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
 extern mi_cmd_argv_ftype mi_cmd_break_watch;
 extern mi_cmd_argv_ftype mi_cmd_catch_assert;
 extern mi_cmd_argv_ftype mi_cmd_catch_exception;
+extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
 extern mi_cmd_argv_ftype mi_cmd_catch_load;
 extern mi_cmd_argv_ftype mi_cmd_catch_unload;
 extern mi_cmd_argv_ftype mi_cmd_disassemble;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
new file mode 100644
index 0000000..5ea4fa8
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
@@ -0,0 +1,137 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# A global variable used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+
+# Before going any further, verify that we can insert exception
+# handlers catchpoints...  That way, we won't have to do this while
+# doing the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions handlers"
+gdb_test_multiple "catch handlers" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+#############################################
+# 1. Try catching all exceptions handlers.  #
+#############################################
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
+            "catch all exceptions handlers"
+
+# Continue to exception handler.
+
+proc continue_to_exception_handler { test line } {
+
+    global decimal
+
+    mi_send_resuming_command "exec-continue" "$test"
+
+    # Now MI stream output.
+    mi_expect_stop \
+	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+	"foo" "" ".*" "$line" \
+	".*" \
+        $test
+}
+
+# We don't have the exception name info when stopping at the exception handlers
+# catchpoints so we use source line to check if the inferior stops at the
+# right location.
+
+set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until CE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_ce_location"
+
+set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until PE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_pe_location"
+
+##########################################################
+# 2. Try catching only some of the exceptions handlers.  #
+##########################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#  - We'll catch only "Constraint_Error handlers"
+#  - continue, we should stop at the Constraint_Error exception handler
+#  - continue, we should not stop at the Program_Error exception handler
+#    but exit instead.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers -e Constraint_Error" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
+            "catch Constraint_Error"
+
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+              "foo" "" ".*" "$bp_ce_location" \
+              ".*" \
+              "continue to exception catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
new file mode 100644
index 0000000..da701a3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
@@ -0,0 +1,33 @@
+--  Copyright 2007-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/>.
+
+procedure Foo is
+begin
+
+   begin
+      raise Constraint_Error;
+   exception
+      when Constraint_Error => -- BREAK1
+         null;
+   end;
+
+   begin
+      raise Program_Error;
+   exception
+      when Program_Error => -- BREAK2
+         null;
+   end;
+
+end Foo;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* pushed: [PATCH 3/4] (Ada) C++fy conditional string when catching exception.
  2018-01-31  4:37     ` Joel Brobecker
                         ` (2 preceding siblings ...)
  2018-01-31 12:53       ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
@ 2018-01-31 12:54       ` Xavier Roirand
  2018-01-31 12:54       ` pushed: [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
                         ` (2 subsequent siblings)
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 12:54 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

This commit C++fy the conditional string used when catching Ada exception.

gdb/ChangeLog:

        * ada-lang.c (catch_ada_exception_command_split)
        (create_ada_exception_catchpoint) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_ada_exception_command, catch_ada_handlers_command): Use
        C++ string instead of char* for conditional var.
        (catch_ada_assert_command_split) <cond_string>: Change parameter
        type.  Update code accordingly.
        (catch_assert_command): Use C++ string instead of char* for
        conditional var.
        * ada-lang.h (create_ada_exception_catchpoint) <cond_string>:
        Update declaration.
        * mi/mi-cmd-catch.c (mi_cmd_catch_assert, mi_cmd_catch_exception:
        Use std::string instead of char* for condition string.

Tested on x86_64-linux.
---
 gdb/ada-lang.c        | 27 ++++++++++++++-------------
 gdb/ada-lang.h        |  4 ++--
 gdb/mi/mi-cmd-catch.c | 18 ++++++------------
 3 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3ff7169..0da58d9 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13142,7 +13142,7 @@ catch_ada_exception_command_split (const char *args,
 				   bool is_catch_handlers_cmd,
                                    enum ada_exception_catchpoint_kind *ex,
 				   char **excep_string,
-				   char **cond_string)
+				   std::string &cond_string)
 {
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   char *exception_name;
@@ -13209,7 +13209,8 @@ catch_ada_exception_command_split (const char *args,
       *ex = ada_catch_exception;
       *excep_string = exception_name;
     }
-  *cond_string = cond;
+  if (cond != NULL)
+    cond_string.assign (cond);
 }
 
 /* Return the name of the symbol on which we should break in order to
@@ -13400,7 +13401,7 @@ void
 create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 enum ada_exception_catchpoint_kind ex_kind,
 				 char *excep_string,
-				 char *cond_string,
+				 const std::string &cond_string,
 				 int tempflag,
 				 int disabled,
 				 int from_tty)
@@ -13415,8 +13416,8 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
 				 ops, tempflag, disabled, from_tty);
   c->excep_string = excep_string;
   create_excep_cond_exprs (c.get (), ex_kind);
-  if (cond_string != NULL)
-    set_breakpoint_condition (c.get (), cond_string, from_tty);
+  if (!cond_string.empty ())
+    set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
   install_breakpoint (0, std::move (c), 1);
 }
 
@@ -13431,14 +13432,14 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13456,14 +13457,14 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
   int tempflag;
   enum ada_exception_catchpoint_kind ex_kind;
   char *excep_string = NULL;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
   catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
-				     &cond_string);
+				     cond_string);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   excep_string, cond_string,
 				   tempflag, 1 /* enabled */,
@@ -13479,7 +13480,7 @@ catch_ada_handlers_command (const char *arg_entry, int from_tty,
    (the memory needs to be deallocated after use).  */
 
 static void
-catch_ada_assert_command_split (const char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string &cond_string)
 {
   args = skip_spaces (args);
 
@@ -13491,7 +13492,7 @@ catch_ada_assert_command_split (const char *args, char **cond_string)
       args = skip_spaces (args);
       if (args[0] == '\0')
         error (_("condition missing after `if' keyword"));
-      *cond_string = xstrdup (args);
+      cond_string.assign (args);
     }
 
   /* Otherwise, there should be no other argument at the end of
@@ -13509,13 +13510,13 @@ catch_assert_command (const char *arg_entry, int from_tty,
   const char *arg = arg_entry;
   struct gdbarch *gdbarch = get_current_arch ();
   int tempflag;
-  char *cond_string = NULL;
+  std::string cond_string;
 
   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
 
   if (!arg)
     arg = "";
-  catch_ada_assert_command_split (arg, &cond_string);
+  catch_ada_assert_command_split (arg, cond_string);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, cond_string,
 				   tempflag, 1 /* enabled */,
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index bac6c06..1f6ea77 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -379,8 +379,8 @@ extern std::string ada_name_for_lookup (const char *name);
 
 extern void create_ada_exception_catchpoint
   (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
-   char *excep_string, char *cond_string, int tempflag, int disabled,
-   int from_tty);
+   char *excep_string, const std::string &cond_string, int tempflag,
+   int disabled, int from_tty);
 
 /* Some information about a given Ada exception.  */
 
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index 38b96cc..a0f311a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -32,7 +32,7 @@ void
 mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   int temp = 0;
 
@@ -62,7 +62,7 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -79,10 +79,6 @@ mi_cmd_catch_assert (const char *cmd, char *argv[], int argc)
     error (_("Invalid argument: %s"), argv[oind]);
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs CONDITION to be xstrdup'ed,
-     and will assume control of its lifetime.  */
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
 				   NULL, condition, temp, enabled, 0);
 }
@@ -93,7 +89,7 @@ void
 mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
 {
   struct gdbarch *gdbarch = get_current_arch();
-  char *condition = NULL;
+  std::string condition;
   int enabled = 1;
   char *exception_name = NULL;
   int temp = 0;
@@ -128,7 +124,7 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
       switch ((enum opt) opt)
         {
 	case OPT_CONDITION:
-	  condition = oarg;
+	  condition.assign (oarg);
 	  break;
 	case OPT_DISABLED:
 	  enabled = 0;
@@ -156,12 +152,10 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
     error (_("\"-e\" and \"-u\" are mutually exclusive"));
 
   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
-  /* create_ada_exception_catchpoint needs EXCEPTION_NAME and CONDITION
-     to be xstrdup'ed, and will assume control of their lifetime.  */
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
-  if (condition != NULL)
-    condition = xstrdup (condition);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
 				   exception_name, condition,
 				   temp, enabled, 0);
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

* pushed: [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler.
  2018-01-31  4:37     ` Joel Brobecker
                         ` (5 preceding siblings ...)
  2018-01-31 12:54       ` pushed: [PATCH] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
@ 2018-01-31 13:03       ` Xavier Roirand
  6 siblings, 0 replies; 27+ messages in thread
From: Xavier Roirand @ 2018-01-31 13:03 UTC (permalink / raw)
  To: gdb-patches; +Cc: brobecker, Xavier Roirand

Following my previous commit which add support for stopping at start of
exception handler, this commit adds required gdb-mi support for this
feature.

gdb/ChangeLog:

    * mi/mi-cmd-catch.c (mi_cmd_catch_handlers): New function.
    * mi/mi-cmds.c (mi_cmds): Add catch-handlers command.
    * mi/mi-cmds.h (mi_cmd_catch_handlers): Add external declaration.
    * NEWS: Document "-catch-handlers" command.

gdb/doc/ChangeLog:

    * gdb.texinfo (Ada Exception gdb/mi Catchpoints): Add
    documentation for new "-catch-handlers" command.

gdb/testsuite/ChangeLog:

    * gdb.ada/mi_catch_ex_hand.exp: New testcase.
    * gdb.ada/mi_catch_ex_hand/foo.adb: New file.

Tested on x86_64-linux.
---
 gdb/NEWS                                       |   4 +
 gdb/doc/gdb.texinfo                            |  44 ++++++++
 gdb/mi/mi-cmd-catch.c                          |  72 ++++++++++++-
 gdb/mi/mi-cmds.c                               |   2 +
 gdb/mi/mi-cmds.h                               |   1 +
 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp     | 137 +++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb |  33 ++++++
 7 files changed, 291 insertions(+), 2 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
 create mode 100644 gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb

diff --git a/gdb/NEWS b/gdb/NEWS
index f69173a..9cd38f3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -377,6 +377,10 @@ show disassembler-options
   List the shared libraries in the program.  This is
   equivalent to the CLI command "info shared".
 
+-catch-handlers
+  Catchpoints stopping the program when Ada exceptions are
+  handled.  This is equivalent to the CLI command "catch handlers".
+
 *** Changes in GDB 7.12
 
 * GDB and GDBserver now build with a C++ compiler by default.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9ddfba5..4ed5f6b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28537,6 +28537,50 @@ times="0",original-location="__gnat_debug_raise_exception"@}
 (gdb)
 @end smallexample
 
+@subheading The @code{-catch-handlers} Command
+@findex -catch-handlers
+
+@subsubheading Synopsis
+
+@smallexample
+ -catch-handlers [ -c @var{condition}] [ -d ] [ -e @var{exception-name} ]
+    [ -t ]
+@end smallexample
+
+Add a catchpoint stopping when Ada exceptions are handled.
+By default, the command stops the program when any Ada exception
+gets handled.  But it is also possible, by using some of the
+optional parameters described below, to create more selective
+catchpoints.
+
+The possible optional parameters for this command are:
+
+@table @samp
+@item -c @var{condition}
+Make the catchpoint conditional on @var{condition}.
+@item -d
+Create a disabled catchpoint.
+@item -e @var{exception-name}
+Only stop when @var{exception-name} is handled.
+@item -t
+Create a temporary catchpoint.
+@end table
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{catch handlers}.
+
+@subsubheading Example
+
+@smallexample
+-catch-handlers -e Constraint_Error
+^done,bkptno="4",bkpt=@{number="4",type="breakpoint",disp="keep",
+enabled="y",addr="0x0000000000402f68",
+what="`Constraint_Error' Ada exception handlers",thread-groups=["i1"],
+times="0",original-location="__gnat_begin_handler"@}
+(gdb)
+@end smallexample
+
 @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 @node GDB/MI Program Context
 @section @sc{gdb/mi}  Program Context
diff --git a/gdb/mi/mi-cmd-catch.c b/gdb/mi/mi-cmd-catch.c
index a0f311a..078e73a 100644
--- a/gdb/mi/mi-cmd-catch.c
+++ b/gdb/mi/mi-cmd-catch.c
@@ -157,8 +157,76 @@ mi_cmd_catch_exception (const char *cmd, char *argv[], int argc)
   if (exception_name != NULL)
     exception_name = xstrdup (exception_name);
   create_ada_exception_catchpoint (gdbarch, ex_kind,
-				   exception_name, condition,
-				   temp, enabled, 0);
+				   exception_name,
+				   condition, temp, enabled, 0);
+}
+
+/* Handler for the -catch-handlers command.  */
+
+void
+mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc)
+{
+  struct gdbarch *gdbarch = get_current_arch ();
+  std::string condition;
+  int enabled = 1;
+  char *exception_name = NULL;
+  int temp = 0;
+
+  int oind = 0;
+  char *oarg;
+
+  enum opt
+    {
+      OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
+    };
+  static const struct mi_opt opts[] =
+    {
+      { "c", OPT_CONDITION, 1},
+      { "d", OPT_DISABLED, 0 },
+      { "e", OPT_EXCEPTION_NAME, 1 },
+      { "t", OPT_TEMP, 0 },
+      { 0, 0, 0 }
+    };
+
+  for (;;)
+    {
+      int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
+			   &oind, &oarg);
+
+      if (opt < 0)
+        break;
+
+      switch ((enum opt) opt)
+        {
+	case OPT_CONDITION:
+	  condition.assign (oarg);
+	  break;
+	case OPT_DISABLED:
+	  enabled = 0;
+	  break;
+	case OPT_EXCEPTION_NAME:
+	  exception_name = oarg;
+	  break;
+	case OPT_TEMP:
+	  temp = 1;
+	  break;
+        }
+    }
+
+  /* This command does not accept any argument.  Make sure the user
+     did not provide any.  */
+  if (oind != argc)
+    error (_("Invalid argument: %s"), argv[oind]);
+
+  scoped_restore restore_breakpoint_reporting
+    = setup_breakpoint_reporting ();
+  /* create_ada_exception_catchpoint needs EXCEPTION_NAME to be
+     xstrdup'ed, and will assume control of its lifetime.  */
+  if (exception_name != NULL)
+    exception_name = xstrdup (exception_name);
+  create_ada_exception_catchpoint (gdbarch, ada_catch_handlers,
+				   exception_name,
+				   condition, temp, enabled, 0);
 }
 
 /* Common path for the -catch-load and -catch-unload.  */
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index c9ffda1..51014ed 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -69,6 +69,8 @@ static struct mi_cmd mi_cmds[] =
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
                    &mi_suppress_notification.breakpoint),
+  DEF_MI_CMD_MI_1 ("catch-handlers", mi_cmd_catch_handlers,
+                   &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
                    &mi_suppress_notification.breakpoint),
   DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index c27f3ba..af96585 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -41,6 +41,7 @@ extern mi_cmd_argv_ftype mi_cmd_break_passcount;
 extern mi_cmd_argv_ftype mi_cmd_break_watch;
 extern mi_cmd_argv_ftype mi_cmd_catch_assert;
 extern mi_cmd_argv_ftype mi_cmd_catch_exception;
+extern mi_cmd_argv_ftype mi_cmd_catch_handlers;
 extern mi_cmd_argv_ftype mi_cmd_catch_load;
 extern mi_cmd_argv_ftype mi_cmd_catch_unload;
 extern mi_cmd_argv_ftype mi_cmd_disassemble;
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
new file mode 100644
index 0000000..5ea4fa8
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand.exp
@@ -0,0 +1,137 @@
+# Copyright 2011-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 "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+  return -1
+}
+
+# A global variable used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+
+# Before going any further, verify that we can insert exception
+# handlers catchpoints...  That way, we won't have to do this while
+# doing the actual GDB/MI testing.
+
+clean_restart ${testfile}
+
+if ![runto_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+set msg "insert catchpoint on all Ada exceptions handlers"
+gdb_test_multiple "catch handlers" $msg {
+    -re "Catchpoint $decimal: all Ada exceptions handlers$eol$gdb_prompt $" {
+	pass $msg
+    }
+    -re "Your Ada runtime appears to be missing some debugging information.*\[\r\n\]+$gdb_prompt $" {
+	# If the runtime was not built with enough debug information,
+	# or if it was stripped, we can not test exception
+	# catchpoints.
+	unsupported $msg
+	return -1
+    }
+}
+
+# Now, we can start the GDB/MI testing itself...
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+#############################################
+# 1. Try catching all exceptions handlers.  #
+#############################################
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"all Ada exceptions handlers\",.*}" \
+            "catch all exceptions handlers"
+
+# Continue to exception handler.
+
+proc continue_to_exception_handler { test line } {
+
+    global decimal
+
+    mi_send_resuming_command "exec-continue" "$test"
+
+    # Now MI stream output.
+    mi_expect_stop \
+	"breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+	"foo" "" ".*" "$line" \
+	".*" \
+        $test
+}
+
+# We don't have the exception name info when stopping at the exception handlers
+# catchpoints so we use source line to check if the inferior stops at the
+# right location.
+
+set bp_ce_location [gdb_get_line_number "BREAK1" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until CE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_ce_location"
+
+set bp_pe_location [gdb_get_line_number "BREAK2" ${testdir}/foo.adb]
+continue_to_exception_handler \
+    "continue until PE handling caught by all-exceptions handlers catchpoint" \
+    "$bp_pe_location"
+
+##########################################################
+# 2. Try catching only some of the exceptions handlers.  #
+##########################################################
+
+# Here is the scenario:
+#  - Restart the debugger from scratch, runto_main
+#  - We'll catch only "Constraint_Error handlers"
+#  - continue, we should stop at the Constraint_Error exception handler
+#  - continue, we should not stop at the Program_Error exception handler
+#    but exit instead.
+
+if ![mi_run_to_main] then {
+   fail "cannot run to main, testcase aborted"
+   return 0
+}
+
+mi_gdb_test "-catch-handlers -e Constraint_Error" \
+            "\\^done,bkptno=\"$decimal\",bkpt={.*disp=\"keep\",enabled=\"y\",addr=\"$hex\",what=\"`Constraint_Error' Ada exception handlers\",.*}" \
+            "catch Constraint_Error"
+
+mi_execute_to "exec-continue" \
+              "breakpoint-hit\",disp=\"keep\",bkptno=\"$decimal\",exception-name=\"exception\"?" \
+              "foo" "" ".*" "$bp_ce_location" \
+              ".*" \
+              "continue to exception catchpoint hit"
+
+# Exit the inferior.
+mi_send_resuming_command "exec-continue" "continuing to inferior exit"
+mi_expect_stop "exited-normally" "" "" "" "" "" "exit normally"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
new file mode 100644
index 0000000..da701a3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/mi_catch_ex_hand/foo.adb
@@ -0,0 +1,33 @@
+--  Copyright 2007-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/>.
+
+procedure Foo is
+begin
+
+   begin
+      raise Constraint_Error;
+   exception
+      when Constraint_Error => -- BREAK1
+         null;
+   end;
+
+   begin
+      raise Program_Error;
+   exception
+      when Program_Error => -- BREAK2
+         null;
+   end;
+
+end Foo;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2018-01-31 13:03 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-08  9:15 [RFAv2] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
2018-01-08 18:38 ` Eli Zaretskii
2018-01-23 11:43 ` Joel Brobecker
2018-01-29 12:46   ` [PATCH 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
2018-01-30  4:41     ` Joel Brobecker
2018-01-29 12:47   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
2018-01-30  4:57     ` Joel Brobecker
2018-01-29 12:47   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
2018-01-30  4:49     ` Joel Brobecker
2018-01-29 12:47   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
2018-01-29 15:57     ` Eli Zaretskii
2018-01-30  7:13     ` Joel Brobecker
2018-01-30  9:23   ` [PATCHv2 1/4] (Ada) Add testcase for catch assert with condition Xavier Roirand
2018-01-31  4:37     ` Joel Brobecker
2018-01-31 12:52       ` pushed: [PATCH " Xavier Roirand
2018-01-31 12:53       ` [PATCH 2/4] (Ada/MI) Add testcase for mi " Xavier Roirand
2018-01-31 12:53       ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
2018-01-31 12:54       ` pushed: " Xavier Roirand
2018-01-31 12:54       ` pushed: [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
2018-01-31 12:54       ` pushed: [PATCH] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
2018-01-31 13:03       ` pushed: [PATCH 4/4] " Xavier Roirand
2018-01-30  9:23   ` [PATCH 2/4] (Ada/MI) Add testcase for mi catch assert with condition Xavier Roirand
2018-01-31  4:39     ` Joel Brobecker
2018-01-30  9:24   ` [PATCH 4/4] (Ada) Add gdb-mi support for stopping at start of exception handler Xavier Roirand
2018-01-31  4:45     ` Joel Brobecker
2018-01-30  9:24   ` [PATCH 3/4] (Ada) C++fy conditional string when catching exception Xavier Roirand
2018-01-31  4:41     ` Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).