(Ada) Add gdb-mi support for stopping at start of exception handler.

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.
This commit is contained in:
Xavier Roirand 2018-01-26 11:13:11 +01:00
parent 56ecd069f0
commit bea298f954
7 changed files with 291 additions and 2 deletions

View File

@ -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.

View File

@ -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

View File

@ -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. */

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;