summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog34
-rw-r--r--gdb/NEWS3
-rw-r--r--gdb/ada-lang.c197
-rw-r--r--gdb/ada-lang.h3
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/gdb.texinfo20
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.ada/excep_handle.exp171
-rw-r--r--gdb/testsuite/gdb.ada/excep_handle/foo.adb103
-rw-r--r--gdb/testsuite/gdb.ada/excep_handle/pck.ads19
10 files changed, 547 insertions, 14 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1ab2a892352..ed9d2b0ce53 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,37 @@
+2018-01-03 Xavier Roirand <roirand@adacore.com>
+
+ * ada-lang.h (ada_exception_catchpoint_kind) <ada_catch_handlers>:
+ Add field.
+ * ada-lang.c (struct exception_support_info) <catch_handlers_sym>:
+ Add field.
+ (default_exception_support_info) <catch_handlers_sym>: Add field.
+ (exception_support_info_fallback) <catch_handlers_sym>: Add field.
+ (ada_exception_name_addr_1): Add "catch handlers" handling.
+ (ada_exception_catchpoint_cond_string) <ex>: New parameter.
+ Update all callers.
+ (create_excep_cond_exprs) <ex>: Add parameter.
+ (re_set_exception): Update create_excep_cond_exprs call.
+ (print_it_exception, print_one_exception, print_mention_exception)
+ (print_recreate_exception): Add "catch handler" handling.
+ (allocate_location_catch_handlers, re_set_catch_handlers)
+ (check_status_catch_handlers, print_it_catch_handlers)
+ (print_one_catch_handlers, print_mention_catch_handlers)
+ (print_recreate_catch_handlers): New function.
+ (catch_handlers_breakpoint_ops): New variable.
+ (catch_ada_exception_command_split) <is_catch_handlers_cmd>:
+ Add parameter. Add "catch handler" handling.
+ (ada_exception_sym_name, ada_exception_breakpoint_ops):
+ Add "catch handler" handling.
+ (ada_exception_catchpoint_cond_string): Add "catch handler"
+ handling.
+ (create_ada_exception_catchpoint): Update create_excep_cond_exprs
+ call.
+ (catch_ada_handlers_command): New function.
+ (initialize_ada_catchpoint_ops): Initialize "catch handlers"
+ operations structure.
+ (_initialize_ada_language): Add "catch handlers" command entry.
+ * NEWS: Document "catch handlers" feature.
+
2018-01-02 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (ada_value_slice_from_ptr): Take array stride into
diff --git a/gdb/NEWS b/gdb/NEWS
index c8618537983..14fcdf86746 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -669,6 +669,9 @@ show max-value-size
* Support for reading/writing memory and extracting values on architectures
whose memory is addressable in units of any integral multiple of 8 bits.
+catch handlers
+ Allows to break when an Ada exception is handled.
+
* New remote packets
exec stop reason
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 851e69ac4ba..4ecf7b0051c 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12024,6 +12024,10 @@ struct exception_support_info
a catchpoint on failed assertions. */
const char *catch_assert_sym;
+ /* The name of the symbol to break on in order to insert
+ a catchpoint on exception handling. */
+ const char *catch_handlers_sym;
+
/* Assuming that the inferior just triggered an unhandled exception
catchpoint, this function is responsible for returning the address
in inferior memory where the name of that exception is stored.
@@ -12043,6 +12047,7 @@ static const struct exception_support_info default_exception_support_info =
"__gnat_debug_raise_exception", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
"__gnat_debug_raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler", /* catch_handlers_sym */
ada_unhandled_exception_name_addr
};
@@ -12055,6 +12060,7 @@ static const struct exception_support_info exception_support_info_fallback =
"__gnat_raise_nodefer_with_msg", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
"system__assertions__raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler", /* catch_handlers_sym */
ada_unhandled_exception_name_addr_from_raise
};
@@ -12323,7 +12329,12 @@ ada_exception_name_addr_1 (enum ada_exception_catchpoint_kind ex,
case ada_catch_exception_unhandled:
return data->exception_info->unhandled_exception_name_addr ();
break;
-
+
+ case ada_catch_handlers:
+ return 0; /* The runtimes does not provide access to the exception
+ name. */
+ break;
+
case ada_catch_assert:
return 0; /* Exception name is not relevant in this case. */
break;
@@ -12429,7 +12440,9 @@ ada_exception_name_addr (enum ada_exception_catchpoint_kind ex,
return result;
}
-static char *ada_exception_catchpoint_cond_string (const char *excep_string);
+static char *ada_exception_catchpoint_cond_string
+ (const char *excep_string,
+ enum ada_exception_catchpoint_kind ex);
/* Ada catchpoints.
@@ -12492,7 +12505,8 @@ struct ada_catchpoint : public breakpoint
catchpoint's locations, and store them for later evaluation. */
static void
-create_excep_cond_exprs (struct ada_catchpoint *c)
+create_excep_cond_exprs (struct ada_catchpoint *c,
+ enum ada_exception_catchpoint_kind ex)
{
struct cleanup *old_chain;
struct bp_location *bl;
@@ -12508,7 +12522,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c)
/* Compute the condition expression in text form, from the specific
expection we want to catch. */
- cond_string = ada_exception_catchpoint_cond_string (c->excep_string);
+ cond_string = ada_exception_catchpoint_cond_string (c->excep_string, ex);
old_chain = make_cleanup (xfree, cond_string);
/* Iterate over all the catchpoint's locations, and parse an
@@ -12576,7 +12590,7 @@ re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
/* Reparse the exception conditional expressions. One for each
location. */
- create_excep_cond_exprs (c);
+ create_excep_cond_exprs (c, ex);
}
/* Returns true if we should stop for this breakpoint hit. If the
@@ -12665,6 +12679,7 @@ print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
{
case ada_catch_exception:
case ada_catch_exception_unhandled:
+ case ada_catch_handlers:
{
const CORE_ADDR addr = ada_exception_name_addr (ex, b);
char exception_name[256];
@@ -12762,6 +12777,17 @@ print_one_exception (enum ada_exception_catchpoint_kind ex,
uiout->field_string ("what", "unhandled Ada exceptions");
break;
+ case ada_catch_handlers:
+ if (c->excep_string != NULL)
+ {
+ uiout->field_fmt ("what",
+ _("`%s' Ada exception handlers"),
+ c->excep_string);
+ }
+ else
+ uiout->field_string ("what", "all Ada exceptions handlers");
+ break;
+
case ada_catch_assert:
uiout->field_string ("what", "failed Ada assertions");
break;
@@ -12805,7 +12831,19 @@ print_mention_exception (enum ada_exception_catchpoint_kind ex,
case ada_catch_exception_unhandled:
uiout->text (_("unhandled Ada exceptions"));
break;
-
+
+ case ada_catch_handlers:
+ if (c->excep_string != NULL)
+ {
+ std::string info
+ = string_printf (_("`%s' Ada exception handlers"),
+ c->excep_string);
+ uiout->text (info.c_str ());
+ }
+ else
+ uiout->text (_("all Ada exceptions handlers"));
+ break;
+
case ada_catch_assert:
uiout->text (_("failed Ada assertions"));
break;
@@ -12837,6 +12875,10 @@ print_recreate_exception (enum ada_exception_catchpoint_kind ex,
fprintf_filtered (fp, "catch exception unhandled");
break;
+ case ada_catch_handlers:
+ fprintf_filtered (fp, "catch handlers");
+ break;
+
case ada_catch_assert:
fprintf_filtered (fp, "catch assert");
break;
@@ -12987,6 +13029,54 @@ print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp)
static struct breakpoint_ops catch_assert_breakpoint_ops;
+/* Virtual table for "catch handlers" breakpoints. */
+
+static struct bp_location *
+allocate_location_catch_handlers (struct breakpoint *self)
+{
+ return allocate_location_exception (ada_catch_handlers, self);
+}
+
+static void
+re_set_catch_handlers (struct breakpoint *b)
+{
+ re_set_exception (ada_catch_handlers, b);
+}
+
+static void
+check_status_catch_handlers (bpstat bs)
+{
+ check_status_exception (ada_catch_handlers, bs);
+}
+
+static enum print_stop_action
+print_it_catch_handlers (bpstat bs)
+{
+ return print_it_exception (ada_catch_handlers, bs);
+}
+
+static void
+print_one_catch_handlers (struct breakpoint *b,
+ struct bp_location **last_loc)
+{
+ print_one_exception (ada_catch_handlers, b, last_loc);
+}
+
+static void
+print_mention_catch_handlers (struct breakpoint *b)
+{
+ print_mention_exception (ada_catch_handlers, b);
+}
+
+static void
+print_recreate_catch_handlers (struct breakpoint *b,
+ struct ui_file *fp)
+{
+ print_recreate_exception (ada_catch_handlers, b, fp);
+}
+
+static struct breakpoint_ops catch_handlers_breakpoint_ops;
+
/* Return a newly allocated copy of the first space-separated token
in ARGSP, and then adjust ARGSP to point immediately after that
token.
@@ -13025,12 +13115,15 @@ ada_get_next_arg (const char **argsp)
Set EX to the appropriate catchpoint type.
Set EXCEP_STRING to the name of the specific exception if
specified by the user.
+ IS_CATCH_HANDLERS_CMD: True if the arguments are for a
+ "catch handlers" command. False otherwise.
If a condition is found at the end of the arguments, the condition
expression is stored in COND_STRING (memory must be deallocated
after use). Otherwise COND_STRING is set to NULL. */
static void
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)
@@ -13076,7 +13169,13 @@ catch_ada_exception_command_split (const char *args,
discard_cleanups (old_chain);
- if (exception_name == NULL)
+ if (is_catch_handlers_cmd)
+ {
+ /* Catch handling of exceptions. */
+ *ex = ada_catch_handlers;
+ *excep_string = exception_name;
+ }
+ else if (exception_name == NULL)
{
/* Catch all exceptions. */
*ex = ada_catch_exception;
@@ -13118,6 +13217,9 @@ ada_exception_sym_name (enum ada_exception_catchpoint_kind ex)
case ada_catch_assert:
return (data->exception_info->catch_assert_sym);
break;
+ case ada_catch_handlers:
+ return (data->exception_info->catch_handlers_sym);
+ break;
default:
internal_error (__FILE__, __LINE__,
_("unexpected catchpoint kind (%d)"), ex);
@@ -13141,6 +13243,9 @@ ada_exception_breakpoint_ops (enum ada_exception_catchpoint_kind ex)
case ada_catch_assert:
return (&catch_assert_breakpoint_ops);
break;
+ case ada_catch_handlers:
+ return (&catch_handlers_breakpoint_ops);
+ break;
default:
internal_error (__FILE__, __LINE__,
_("unexpected catchpoint kind (%d)"), ex);
@@ -13151,14 +13256,29 @@ ada_exception_breakpoint_ops (enum ada_exception_catchpoint_kind ex)
being raised with the exception that the user wants to catch. This
assumes that this condition is used when the inferior just triggered
an exception catchpoint.
+ EX: the type of catchpoints used for catching Ada exceptions.
The string returned is a newly allocated string that needs to be
deallocated later. */
static char *
-ada_exception_catchpoint_cond_string (const char *excep_string)
+ada_exception_catchpoint_cond_string (const char *excep_string,
+ enum ada_exception_catchpoint_kind ex)
{
int i;
+ bool is_standard_exc = false;
+ const char *actual_exc_expr;
+ char *ref_exc_expr;
+
+ if (ex == ada_catch_handlers)
+ {
+ /* For exception handlers catchpoints, the condition string does
+ not use the same parameter as for the other exceptions. */
+ actual_exc_expr = ("long_integer (GNAT_GCC_exception_Access"
+ "(gcc_exception).all.occurrence.id)");
+ }
+ else
+ actual_exc_expr = "long_integer (e)";
/* The standard exceptions are a special case. They are defined in
runtime units that have been compiled without debugging info; if
@@ -13183,11 +13303,19 @@ ada_exception_catchpoint_cond_string (const char *excep_string)
{
if (strcmp (standard_exc [i], excep_string) == 0)
{
- return xstrprintf ("long_integer (e) = long_integer (&standard.%s)",
- excep_string);
+ is_standard_exc = true;
+ break;
}
}
- return xstrprintf ("long_integer (e) = long_integer (&%s)", excep_string);
+
+ if (is_standard_exc)
+ ref_exc_expr = xstrprintf ("long_integer (&standard.%s)", excep_string);
+ else
+ ref_exc_expr = xstrprintf ("long_integer (&%s)", excep_string);
+
+ char *result = xstrprintf ("%s = %s", actual_exc_expr, ref_exc_expr);
+ xfree (ref_exc_expr);
+ return result;
}
/* Return the symtab_and_line that should be used to insert an exception
@@ -13270,7 +13398,7 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
init_ada_exception_breakpoint (c.get (), gdbarch, sal, addr_string,
ops, tempflag, disabled, from_tty);
c->excep_string = excep_string;
- create_excep_cond_exprs (c.get ());
+ create_excep_cond_exprs (c.get (), ex_kind);
if (cond_string != NULL)
set_breakpoint_condition (c.get (), cond_string, from_tty);
install_breakpoint (0, std::move (c), 1);
@@ -13293,7 +13421,32 @@ catch_ada_exception_command (const char *arg_entry, int from_tty,
if (!arg)
arg = "";
- catch_ada_exception_command_split (arg, &ex_kind, &excep_string,
+ catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
+ &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ex_kind,
+ excep_string, cond_string,
+ tempflag, 1 /* enabled */,
+ from_tty);
+}
+
+/* Implement the "catch handlers" command. */
+
+static void
+catch_ada_handlers_command (const char *arg_entry, int from_tty,
+ struct cmd_list_element *command)
+{
+ const char *arg = arg_entry;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int tempflag;
+ enum ada_exception_catchpoint_kind ex_kind;
+ char *excep_string = NULL;
+ char *cond_string = NULL;
+
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
+ catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
&cond_string);
create_ada_exception_catchpoint (gdbarch, ex_kind,
excep_string, cond_string,
@@ -14408,6 +14561,16 @@ initialize_ada_catchpoint_ops (void)
ops->print_one = print_one_catch_assert;
ops->print_mention = print_mention_catch_assert;
ops->print_recreate = print_recreate_catch_assert;
+
+ ops = &catch_handlers_breakpoint_ops;
+ *ops = bkpt_breakpoint_ops;
+ ops->allocate_location = allocate_location_catch_handlers;
+ ops->re_set = re_set_catch_handlers;
+ ops->check_status = check_status_catch_handlers;
+ ops->print_it = print_it_catch_handlers;
+ ops->print_one = print_one_catch_handlers;
+ ops->print_mention = print_mention_catch_handlers;
+ ops->print_recreate = print_recreate_catch_handlers;
}
/* This module's 'new_objfile' observer. */
@@ -14468,6 +14631,14 @@ With an argument, catch only exceptions with the given name."),
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
+
+ add_catch_command ("handlers", _("\
+Catch Ada exceptions, when handled.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_ada_handlers_command,
+ NULL,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
add_catch_command ("assert", _("\
Catch failed Ada assertions, when raised.\n\
With an argument, catch only exceptions with the given name."),
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index da7edca78c3..bac6c06e40b 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -108,7 +108,8 @@ enum ada_exception_catchpoint_kind
{
ada_catch_exception,
ada_catch_exception_unhandled,
- ada_catch_assert
+ ada_catch_assert,
+ ada_catch_handlers
};
/* Ada task structures. */
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 6a0dbda51ef..5a3437cd32e 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2018-01-03 Xavier Roirand <roirand@adacore.com>
+
+ * gdb.texinfo (Set Catchpoints): Add documentation for new
+ "catch handlers" action.
+
2017-12-27 Stafford Horne <shorne@gmail.com>
* gdb.texinfo (Target Description Format): Explain that arbitrary
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6ffba3d8648..8bdafb0ba44 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4458,6 +4458,26 @@ called @code{Constraint_Error} is defined in package @code{Pck}, then
the command to use to catch such exceptions is @kbd{catch exception
Pck.Constraint_Error}.
+@item handlers
+@kindex catch handlers
+@cindex Ada exception handlers catching
+@cindex catch Ada exceptions when handled
+An Ada exception being handled. If an exception name is
+specified at the end of the command
+ (eg @kbd{catch handlers Program_Error}), the debugger will stop
+only when this specific exception is handled.
+Otherwise, the debugger stops execution when any Ada exception is handled.
+
+When inserting a handlers catchpoint on a user-defined
+exception whose name is identical to one of the exceptions
+defined by the language, the fully qualified name must be used
+as the exception name. Otherwise, @value{GDBN} will assume that it
+should stop on the pre-defined exception rather than the
+user-defined one. For instance, assuming an exception called
+ @code{Constraint_Error} is defined in package @code{Pck}, then the
+command to use to catch such exceptions handling is
+@kbd{catch handlers Pck.Constraint_Error}.
+
@item exception unhandled
@kindex catch exception unhandled
An exception that was raised but is not handled by the program.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 5f32d89c29b..500dbddf1c6 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-03 Xavier Roirand <roirand@adacore.com>
+
+ * gdb.ada/excep_handle.exp: New testcase.
+ * gdb.ada/excep_handle/foo.adb: New file.
+ * gdb.ada/excep_handle/pck.ads: New file.
+
2018-01-03 Joel Brobecker <brobecker@adacore.com>
* gdb.base/step-line.c: Add extra empty line in copyright header.
diff --git a/gdb/testsuite/gdb.ada/excep_handle.exp b/gdb/testsuite/gdb.ada/excep_handle.exp
new file mode 100644
index 00000000000..c693fd30ea2
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/excep_handle.exp
@@ -0,0 +1,171 @@
+# 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 foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug additional_flags=-gnata ]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+# Some global variables used to simplify the maintenance of some of
+# the regular expressions below.
+set eol "\[\r\n\]+"
+set sp "\[ \t\]*"
+
+set when "when"
+set catchpoint_constraint_error_msg \
+ "Catchpoint $decimal, exception at $hex in foo \\\(\\\).*at .*foo.adb:$decimal$eol$decimal$sp$when Constraint_Error =>"
+
+set catchpoint_program_error_msg \
+ "Catchpoint $decimal, exception at $hex in foo \\\(\\\).*at .*foo.adb:$decimal$eol$decimal$sp$when Program_Error =>"
+
+set catchpoint_storage_error_msg \
+ "Catchpoint $decimal, exception at $hex in foo \\\(\\\).*at .*foo.adb:$decimal$eol$decimal$sp$when Storage_Error =>"
+
+############################################
+# Check that runtime supports catchpoint. #
+############################################
+
+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.*$eol$gdb_prompt $" {
+ # If the runtime was not built with enough debug information,
+ # or if it was stripped, we can not test exception handlers
+ # catchpoints.
+ unsupported $msg
+ return -1
+ }
+}
+
+############################################
+# 1. Try catching all exceptions handlers. #
+############################################
+
+# Continue. The program should stop at first exception handling.
+
+gdb_test "continue" \
+ "Continuing\.$eol$catchpoint_constraint_error_msg$eol.*" \
+ "continuing to first Constraint_Error exception handlers"
+
+# Resume the program's exception.
+#
+# The program will first go through a block of code which has an
+# exception handler, but since no exception is raised, we should
+# not stop there. Instead, we expect to stop in the handler of
+# the next exception being raised.
+
+gdb_test "continue" \
+ "Continuing\.$eol$catchpoint_storage_error_msg$eol.*" \
+ "continuing and stopping in Storage_Error exception handlers"
+
+gdb_test_no_output "delete 2" \
+ "delete catchpoint on all Ada exceptions handlers"
+
+##################################################
+# 2. Try catching some named exception handlers. #
+##################################################
+
+# Insert a catchpoint on Program_Error Ada exception handlers.
+
+gdb_test "catch handlers Program_Error" \
+ "Catchpoint $decimal: `Program_Error' Ada exception handlers" \
+ "insert catchpoint on Program_Error Ada exception handlers"
+
+# Continue, we should not stop at ABORT_SIGNAL but at Program_Error one.
+
+gdb_test "continue" \
+ "Continuing\.$eol$catchpoint_program_error_msg$eol.*" \
+ "continuing without stopping to Program_Error exception handlers"
+
+gdb_test_no_output \
+ "delete 3" \
+ "delete catchpoint on all Program_Error Ada exception handlers"
+
+# Insert a catchpoint on Storage_Error Ada exception handlers.
+
+gdb_test "catch handlers Storage_Error" \
+ "Catchpoint $decimal: `Storage_Error' Ada exception handlers" \
+ "insert catchpoint on Storage_Error Ada exception handlers"
+
+# Continue, we should stop at Storage_Error handlers.
+
+gdb_test "continue" \
+ "Continuing\.$eol$catchpoint_storage_error_msg$eol.*" \
+ "continuing without stopping to Storage_Error exception handlers"
+
+gdb_test_no_output \
+ "delete 4" \
+ "delete catchpoint on all Storage_Error Ada exception handlers"
+
+########################################################################
+# 3. Try catching with condition and without named exception handlers. #
+########################################################################
+
+# Insert a catchpoint on all Ada exceptions handlers with condition.
+
+gdb_test "catch handlers if Global_Var = 2" \
+ "Catchpoint $decimal: all Ada exceptions handlers" \
+ "insert catchpoint on all Ada exception handlers with condition"
+
+# Check that condition is stored and properly displayed.
+
+gdb_test "info breakpoint" "stop only if Global_Var = 2" \
+ "Check catch handlers with condition"
+
+# Continue, we should not stop at ABORT_SIGNAL but at Program_Error one.
+
+gdb_test "continue" \
+ "Continuing\.$eol$catchpoint_constraint_error_msg$eol.*" \
+ "continuing to second Constraint_Error exception handlers"
+
+gdb_test_no_output \
+ "delete 5" \
+ "delete catchpoint on all all Ada exceptions handlers with condition"
+
+################################################################
+# 4. Try catching with condition and named exception handlers. #
+################################################################
+
+# Insert a catchpoint on Program_Error Ada exception handlers with
+# condition.
+
+gdb_test "catch handlers Program_Error if Global_Var = 4" \
+ "Catchpoint $decimal: `Program_Error' Ada exception handlers" \
+ "insert catchpoint on Program_Error Ada exception handlers with condition"
+
+# Continue, we should not stop at first Program_Error handlers but at
+# the second one.
+
+gdb_test "continue" \
+ "Continuing\.$eol$catchpoint_program_error_msg$eol.*" \
+ "continuing to Program_Error exception handlers"
+
+# Continue, the program should exit properly.
+
+gdb_test "continue" \
+ "Continuing\..*$inferior_exited_re.*" \
+ "continuing to program completion"
diff --git a/gdb/testsuite/gdb.ada/excep_handle/foo.adb b/gdb/testsuite/gdb.ada/excep_handle/foo.adb
new file mode 100644
index 00000000000..93c684347ae
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/excep_handle/foo.adb
@@ -0,0 +1,103 @@
+-- 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 Foo is
+begin
+
+ -- Part 1 of the testcase
+
+ begin
+ raise Constraint_Error;
+ exception
+ when Constraint_Error =>
+ null;
+ end;
+
+ begin
+ null;
+ exception
+ when others =>
+ null;
+ end;
+
+ begin
+ raise Storage_Error;
+ exception
+ when Storage_Error =>
+ null;
+ end;
+
+ -- Part 2 of the testcase
+
+ begin
+ raise ABORT_SIGNAL;
+ exception
+ when others =>
+ null;
+ end;
+
+ begin
+ raise Program_Error;
+ exception
+ when Program_Error =>
+ null;
+ end;
+
+ begin
+ raise Storage_Error;
+ exception
+ when Storage_Error =>
+ null;
+ end;
+
+ -- Part 3 of the testcase
+
+ begin
+ Global_Var := Global_Var + 1;
+ raise ABORT_SIGNAL;
+ exception
+ when others =>
+ null;
+ end;
+
+ begin
+ Global_Var := Global_Var + 1;
+ raise Constraint_Error;
+ exception
+ when Constraint_Error =>
+ null;
+ end;
+
+ -- Part 4 of the testcase
+
+ begin
+ Global_Var := Global_Var + 1;
+ raise Program_Error;
+ exception
+ when others =>
+ null;
+ end;
+
+ begin
+ Global_Var := Global_Var + 1;
+ raise Program_Error;
+ exception
+ when Program_Error =>
+ null;
+ end;
+
+end Foo;
diff --git a/gdb/testsuite/gdb.ada/excep_handle/pck.ads b/gdb/testsuite/gdb.ada/excep_handle/pck.ads
new file mode 100644
index 00000000000..6a7cf084d8a
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/excep_handle/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;
+ ABORT_SIGNAL : exception;
+end Pck;