improve Ada exception catchpoint MI notification

This rewrites the code generating the Ada exception catchpoint hit
notification for both the GDB/MI case as well as the non-MI case,
by using the relevant ui_out_* functions to generate the output.
the MI notifications for Ada exception catchpoints now include
the stop reason, and the breakpoint "disp", much like other breakpoint
events do.  It also introduces a new field "exception-name" for
exception catchpoints (excluding "failed assertion catchpoints,
where we just want to know that it was a failed assertion).

gdb/ChangeLog:

        * breakpoint.h (bpdisp_text): Add declaration.
        * breakpoint.c (bpdisp_text): Make non-static.
        * ada-lang.c: #include "mi/mi-common.h".
        (print_it_exception): Rewrite to improve GDB/MI output.

gdb/doc/ChangeLog:

        * gdb.texinfo (GDB/MI Ada Exception Information): Document
        the "exception-name" field in the *stopped async record.

gdb/testsuite/ChangeLog:

        * gdb.ada/mi_catch_ex: New testcase.
This commit is contained in:
Joel Brobecker 2011-04-01 16:59:58 +00:00
parent d0c4d64237
commit 956a9fb9fb
9 changed files with 256 additions and 24 deletions

View File

@ -1,3 +1,10 @@
2011-04-01 Joel Brobecker <brobecker@adacore.com>
* breakpoint.h (bpdisp_text): Add declaration.
* breakpoint.c (bpdisp_text): Make non-static.
* ada-lang.c: #include "mi/mi-common.h".
(print_it_exception): Rewrite to improve GDB/MI output.
2011-04-01 Pedro Alves <pedro@codesourcery.com>
* arm-tdep.h (struct address_space): Add forward declaration.

View File

@ -60,6 +60,7 @@
#include "psymtab.h"
#include "value.h"
#include "mi/mi-common.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
@ -10745,40 +10746,63 @@ ada_exception_name_addr (enum exception_catchpoint_kind ex,
static enum print_stop_action
print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
{
const CORE_ADDR addr = ada_exception_name_addr (ex, b);
char exception_name[256];
annotate_catchpoint (b->number);
if (addr != 0)
if (ui_out_is_mi_like_p (uiout))
{
read_memory (addr, exception_name, sizeof (exception_name) - 1);
exception_name [sizeof (exception_name) - 1] = '\0';
ui_out_field_string (uiout, "reason",
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
}
ada_find_printable_frame (get_current_frame ());
ui_out_text (uiout, "\nCatchpoint ");
ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout, ", ");
annotate_catchpoint (b->number);
switch (ex)
{
case ex_catch_exception:
if (addr != 0)
printf_filtered (_("\nCatchpoint %d, %s at "),
b->number, exception_name);
else
printf_filtered (_("\nCatchpoint %d, exception at "), b->number);
break;
case ex_catch_exception_unhandled:
if (addr != 0)
printf_filtered (_("\nCatchpoint %d, unhandled %s at "),
b->number, exception_name);
else
printf_filtered (_("\nCatchpoint %d, unhandled exception at "),
b->number);
break;
{
const CORE_ADDR addr = ada_exception_name_addr (ex, b);
char exception_name[256];
if (addr != 0)
{
read_memory (addr, exception_name, sizeof (exception_name) - 1);
exception_name [sizeof (exception_name) - 1] = '\0';
}
else
{
/* For some reason, we were unable to read the exception
name. This could happen if the Runtime was compiled
without debugging info, for instance. In that case,
just replace the exception name by the generic string
"exception" - it will read as "an exception" in the
notification we are about to print. */
sprintf (exception_name, "exception");
}
/* In the case of unhandled exception breakpoints, we print
the exception name as "unhandled EXCEPTION_NAME", to make
it clearer to the user which kind of catchpoint just got
hit. We used ui_out_text to make sure that this extra
info does not pollute the exception name in the MI case. */
if (ex == ex_catch_exception_unhandled)
ui_out_text (uiout, "unhandled ");
ui_out_field_string (uiout, "exception-name", exception_name);
}
break;
case ex_catch_assert:
printf_filtered (_("\nCatchpoint %d, failed assertion at "),
b->number);
break;
/* In this case, the name of the exception is not really
important. Just print "failed assertion" to make it clearer
that his program just hit an assertion-failure catchpoint.
We used ui_out_text because this info does not belong in
the MI output. */
ui_out_text (uiout, "failed assertion");
break;
}
ui_out_text (uiout, " at ");
ada_find_printable_frame (get_current_frame ());
return PRINT_SRC_AND_LOC;
}

View File

@ -251,7 +251,7 @@ breakpoint_commands (struct breakpoint *b)
static int breakpoint_proceeded;
static const char *
const char *
bpdisp_text (enum bpdisp disp)
{
/* NOTE: the following values are a part of MI protocol and

View File

@ -961,6 +961,10 @@ extern void breakpoint_auto_delete (bpstat);
is hit. */
extern struct command_line *breakpoint_commands (struct breakpoint *b);
/* Return a string image of DISP. The string is static, and thus should
NOT be deallocated after use. */
const char *bpdisp_text (enum bpdisp disp);
extern void break_command (char *, int);
extern void hbreak_command_wrapper (char *, int);

View File

@ -1,3 +1,8 @@
2011-04-01 Joel Brobecker <brobecker@adacore.com>
* gdb.texinfo (GDB/MI Ada Exception Information): Document
the "exception-name" field in the *stopped async record.
2011-03-31 Thiago Jung Bauermann <bauerman@br.ibm.com>
Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>

View File

@ -24947,6 +24947,7 @@ follow development on @email{gdb@@sourceware.org} and
* GDB/MI Async Records::
* GDB/MI Frame Information::
* GDB/MI Thread Information::
* GDB/MI Ada Exception Information
@end menu
@node GDB/MI Result Records
@ -25212,6 +25213,13 @@ The value of this field is an integer number of the processor core the
thread was last seen on. This field is optional.
@end table
@node GDB/MI Ada Exception Information
@subsection @sc{gdb/mi} Ada Exception Information
Whenever a @code{*stopped} record is emitted because the program
stopped after hitting an exception catchpoint (@pxref{Set Catchpoints}),
@value{GDBN} provides the name of the exception that was raised via
the @code{exception-name} field.
@c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node GDB/MI Simple Examples

View File

@ -1,3 +1,7 @@
2011-04-01 Joel Brobecker <brobecker@adacore.com>
* gdb.ada/mi_catch_ex: New testcase.
2011-04-01 Pedro Alves <pedro@codesourcery.com>
* gdb.cp/cpexprs.exp (Overloaded methods): No longer try the

View File

@ -0,0 +1,137 @@
# Copyright 2011 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"
set testdir "mi_catch_ex"
set testfile "${testdir}/foo"
set srcfile ${srcdir}/${subdir}/${testfile}.adb
set binfile ${objdir}/${subdir}/${testfile}
file mkdir ${objdir}/${subdir}/${testdir}
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 any_nb "\[0-9\]+"
set eol "\[\r\n\]+"
# 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 $any_nb: all Ada exceptions$eol$gdb_prompt $" {
pass $msg
}
-re "Cannot break on __gnat_raise_nodefer_with_msg in this configuration\.\[\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}
####################################
# 1. Try catching all exceptions. #
####################################
if ![mi_run_to_main] then {
fail "Cannot run to main, testcase aborted"
return 0
}
mi_gdb_test "catch exception"
mi_execute_to "exec-continue" \
"breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"CONSTRAINT_ERROR" \
"foo" "" ".*" ".*" \
".*" \
"continue to exception catchpoint hit"
mi_execute_to "exec-continue" \
"breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"PROGRAM_ERROR" \
"foo" "" ".*" ".*" \
".*" \
"continue to exception catchpoint hit"
################################################
# 2. Try catching only some of the exceptions. #
################################################
# Here is the scenario:
# - Restart the debugger from scratch, runto_main
# - We'll catch only "Program_Error"
# We'll catch assertions
# We'll catch unhandled exceptions
# - continue, we should see the first Program_Error exception
# - continue, we should see the failed assertion
# - continue, we should see the unhandled Constrait_Error exception
# - continue, the program exits.
if ![mi_run_to_main] then {
fail "Cannot run to main, testcase aborted"
return 0
}
mi_gdb_test "catch exception Program_Error"
mi_gdb_test "catch assert"
mi_gdb_test "catch exception unhandled"
mi_execute_to "exec-continue" \
"breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"PROGRAM_ERROR" \
"foo" "" ".*" ".*" \
".*" \
"continue to exception catchpoint hit"
mi_execute_to "exec-continue" \
"breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb" \
"foo" "" ".*" ".*" \
".*" \
"continue to exception catchpoint hit"
mi_execute_to "exec-continue" \
"breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"CONSTRAINT_ERROR" \
"foo" "" ".*" ".*" \
".*" \
"continue to exception catchpoint hit"

View File

@ -0,0 +1,43 @@
-- Copyright 2007, 2008, 2009, 2010, 2011 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; -- SPOT1
exception
when others =>
null;
end;
begin
raise Program_Error; -- SPOT2
exception
when others =>
null;
end;
begin
pragma Assert (False); -- SPOT3
null;
exception
when others =>
null;
end;
raise Constraint_Error; -- SPOT4
end Foo;