PR c++/12824:

* NEWS: Update.
	* breakpoint.c (enum exception_event_kind) <EX_EVENT_RETHROW>:
	New constant.
	(classify_exception_breakpoint): New function.
	(print_it_exception_catchpoint, print_one_exception_catchpoint)
	(print_mention_exception_catchpoint)
	(print_recreate_exception_catchpoint, handle_gnu_v3_exceptions)
	(catch_exception_command_1): Handle "rethrow" catchpoint.
	(catch_rethrow_command): New function.
	(_initialize_breakpoint): Add "catch rethrow" command.
gdb/doc
	* gdb.texinfo (Set Catchpoints): Reorganize exception
	catchpoints.  Document "catch rethrow".
	(Debugging C Plus Plus): Mention "catch rethrow".
gdb/testsuite
	* gdb.cp/exception.exp: Add "catch rethrow" tests.
This commit is contained in:
Tom Tromey 2013-04-15 17:27:44 +00:00
parent 02ae6bada6
commit 591f19e89b
7 changed files with 156 additions and 58 deletions

View File

@ -1,3 +1,17 @@
2013-04-15 Tom Tromey <tromey@redhat.com>
PR c++/12824:
* NEWS: Update.
* breakpoint.c (enum exception_event_kind) <EX_EVENT_RETHROW>:
New constant.
(classify_exception_breakpoint): New function.
(print_it_exception_catchpoint, print_one_exception_catchpoint)
(print_mention_exception_catchpoint)
(print_recreate_exception_catchpoint, handle_gnu_v3_exceptions)
(catch_exception_command_1): Handle "rethrow" catchpoint.
(catch_rethrow_command): New function.
(_initialize_breakpoint): Add "catch rethrow" command.
2013-04-15 Pierre Muller <muller@sourceware.org>
* contrib/ari/gdb_ari.sh (write_pc rule): Do not consider

View File

@ -151,6 +151,9 @@ Tilera TILE-Gx GNU/Linux tilegx*-*-linux
* New commands (for set/show, see "New options" below)
catch rethrow
Like "catch throw", but catches a re-thrown exception.
catch signal
Catch signals. This is similar to "handle", but allows commands and
conditions to be attached.

View File

@ -86,6 +86,7 @@
enum exception_event_kind
{
EX_EVENT_THROW,
EX_EVENT_RETHROW,
EX_EVENT_CATCH
};
@ -11570,16 +11571,30 @@ catch_exec_command_1 (char *arg, int from_tty,
install_breakpoint (0, &c->base, 1);
}
/* A helper function that returns a value indicating the kind of the
exception catchpoint B. */
static enum exception_event_kind
classify_exception_breakpoint (struct breakpoint *b)
{
if (strstr (b->addr_string, "catch") != NULL)
return EX_EVENT_CATCH;
else if (strstr (b->addr_string, "rethrow") != NULL)
return EX_EVENT_RETHROW;
else
return EX_EVENT_THROW;
}
static enum print_stop_action
print_it_exception_catchpoint (bpstat bs)
{
struct ui_out *uiout = current_uiout;
struct breakpoint *b = bs->breakpoint_at;
int bp_temp, bp_throw;
int bp_temp;
enum exception_event_kind kind = classify_exception_breakpoint (b);
annotate_catchpoint (b->number);
bp_throw = strstr (b->addr_string, "throw") != NULL;
if (b->loc->address != b->loc->requested_address)
breakpoint_adjustment_warning (b->loc->requested_address,
b->loc->address,
@ -11591,8 +11606,9 @@ print_it_exception_catchpoint (bpstat bs)
if (!ui_out_is_mi_like_p (uiout))
ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout,
bp_throw ? " (exception thrown), "
: " (exception caught), ");
(kind == EX_EVENT_THROW ? " (exception thrown), "
: (kind == EX_EVENT_CATCH ? " (exception caught), "
: " (exception rethrown), ")));
if (ui_out_is_mi_like_p (uiout))
{
ui_out_field_string (uiout, "reason",
@ -11609,6 +11625,7 @@ print_one_exception_catchpoint (struct breakpoint *b,
{
struct value_print_options opts;
struct ui_out *uiout = current_uiout;
enum exception_event_kind kind = classify_exception_breakpoint (b);
get_user_print_options (&opts);
if (opts.addressprint)
@ -11623,17 +11640,26 @@ print_one_exception_catchpoint (struct breakpoint *b,
annotate_field (5);
if (b->loc)
*last_loc = b->loc;
if (strstr (b->addr_string, "throw") != NULL)
switch (kind)
{
case EX_EVENT_THROW:
ui_out_field_string (uiout, "what", "exception throw");
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string (uiout, "catch-type", "throw");
}
else
{
break;
case EX_EVENT_RETHROW:
ui_out_field_string (uiout, "what", "exception rethrow");
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string (uiout, "catch-type", "rethrow");
break;
case EX_EVENT_CATCH:
ui_out_field_string (uiout, "what", "exception catch");
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string (uiout, "catch-type", "catch");
break;
}
}
@ -11642,15 +11668,15 @@ print_mention_exception_catchpoint (struct breakpoint *b)
{
struct ui_out *uiout = current_uiout;
int bp_temp;
int bp_throw;
enum exception_event_kind kind = classify_exception_breakpoint (b);
bp_temp = b->disposition == disp_del;
bp_throw = strstr (b->addr_string, "throw") != NULL;
ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
: _("Catchpoint "));
ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout, bp_throw ? _(" (throw)")
: _(" (catch)"));
ui_out_text (uiout, (kind == EX_EVENT_THROW ? _(" (throw)")
: (kind == EX_EVENT_CATCH ? _(" (catch)")
: _(" (rethrow)"))));
}
/* Implement the "print_recreate" breakpoint_ops method for throw and
@ -11661,12 +11687,22 @@ print_recreate_exception_catchpoint (struct breakpoint *b,
struct ui_file *fp)
{
int bp_temp;
int bp_throw;
enum exception_event_kind kind = classify_exception_breakpoint (b);
bp_temp = b->disposition == disp_del;
bp_throw = strstr (b->addr_string, "throw") != NULL;
fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
switch (kind)
{
case EX_EVENT_THROW:
fprintf_unfiltered (fp, "throw");
break;
case EX_EVENT_CATCH:
fprintf_unfiltered (fp, "catch");
break;
case EX_EVENT_RETHROW:
fprintf_unfiltered (fp, "rethrow");
break;
}
print_recreate_thread (b, fp);
}
@ -11680,8 +11716,13 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
if (ex_event == EX_EVENT_CATCH)
trigger_func_name = "__cxa_begin_catch";
else if (ex_event == EX_EVENT_RETHROW)
trigger_func_name = "__cxa_rethrow";
else
trigger_func_name = "__cxa_throw";
{
gdb_assert (ex_event == EX_EVENT_THROW);
trigger_func_name = "__cxa_throw";
}
create_breakpoint (get_current_arch (),
trigger_func_name, cond_string, -1, NULL,
@ -11715,7 +11756,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
error (_("Junk at end of arguments."));
if (ex_event != EX_EVENT_THROW
&& ex_event != EX_EVENT_CATCH)
&& ex_event != EX_EVENT_CATCH
&& ex_event != EX_EVENT_RETHROW)
error (_("Unsupported or unknown exception event; cannot catch it"));
if (handle_gnu_v3_exceptions (tempflag, cond_string, ex_event, from_tty))
@ -11744,6 +11786,17 @@ catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
}
/* Implementation of "catch rethrow" command. */
static void
catch_rethrow_command (char *arg, int from_tty,
struct cmd_list_element *command)
{
int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
catch_exception_command_1 (EX_EVENT_RETHROW, arg, tempflag, from_tty);
}
void
init_ada_exception_breakpoint (struct breakpoint *b,
struct gdbarch *gdbarch,
@ -16355,6 +16408,12 @@ Catch an exception, when thrown."),
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
add_catch_command ("rethrow", _("\
Catch an exception, when rethrown."),
catch_rethrow_command,
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
add_catch_command ("fork", _("Catch calls to fork."),
catch_fork_command_1,
NULL,

View File

@ -1,3 +1,9 @@
2013-04-15 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Set Catchpoints): Reorganize exception
catchpoints. Document "catch rethrow".
(Debugging C Plus Plus): Mention "catch rethrow".
2013-04-15 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Set Catchpoints): Remove obsolete text.

View File

@ -4072,13 +4072,46 @@ shared library. Use the @code{catch} command to set a catchpoint.
@kindex catch
@item catch @var{event}
Stop when @var{event} occurs. @var{event} can be any of the following:
@table @code
@item throw
@itemx rethrow
@itemx catch
@cindex stop on C@t{++} exceptions
The throwing of a C@t{++} exception.
The throwing, re-throwing, or catching of a C@t{++} exception.
@item catch
The catching of a C@t{++} exception.
There are currently some limitations to C@t{++} exception handling in
@value{GDBN}:
@itemize @bullet
@item
The support for these commands is system-dependent. Currently, only
systems using the @samp{gnu-v3} C@t{++} ABI (@pxref{ABI}) are
supported.
@item
When an exception-related catchpoint is hit, @value{GDBN} stops at a
location in the system library which implements runtime exception
support for C@t{++}, usually @code{libstdc++}. You can use @code{up}
(@pxref{Selection}) to get to your code.
@item
If you call a function interactively, @value{GDBN} normally returns
control to you when the function has finished executing. If the call
raises an exception, however, the call may bypass the mechanism that
returns control to you and cause your program either to abort or to
simply continue running until it hits a breakpoint, catches a signal
that @value{GDBN} is listening for, or exits. This is the case even if
you set a catchpoint for the exception; catchpoints on exceptions are
disabled within interactive calls. @xref{Calling}, for information on
controlling this with @code{set unwind-on-terminating-exception}.
@item
You cannot raise an exception interactively.
@item
You cannot install an exception handler interactively.
@end itemize
@item exception
@cindex Ada exception catching
@ -4288,27 +4321,6 @@ automatically deleted after the first time the event is caught.
Use the @code{info break} command to list the current catchpoints.
There are currently some limitations to C@t{++} exception handling
(@code{catch throw} and @code{catch catch}) in @value{GDBN}:
@itemize @bullet
@item
If you call a function interactively, @value{GDBN} normally returns
control to you when the function has finished executing. If the call
raises an exception, however, the call may bypass the mechanism that
returns control to you and cause your program either to abort or to
simply continue running until it hits a breakpoint, catches a signal
that @value{GDBN} is listening for, or exits. This is the case even if
you set a catchpoint for the exception; catchpoints on exceptions are
disabled within interactive calls.
@item
You cannot raise an exception interactively.
@item
You cannot install an exception handler interactively.
@end itemize
@node Delete Breaks
@subsection Deleting Breakpoints
@ -13508,6 +13520,7 @@ classes.
@cindex C@t{++} exception handling
@item catch throw
@itemx catch rethrow
@itemx catch catch
Debug C@t{++} exception handling using these commands. @xref{Set
Catchpoints, , Setting Catchpoints}.

View File

@ -1,3 +1,7 @@
2013-04-15 Tom Tromey <tromey@redhat.com>
* gdb.cp/exception.exp: Add "catch rethrow" tests.
2013-04-13 Yao Qi <yao@codesourcery.com>
* gdb.base/completion.exp: Test completion of command

View File

@ -56,6 +56,11 @@ gdb_test "catch catch" "Catchpoint \[0-9\]+ \\(catch\\)" \
gdb_test "catch throw" "Catchpoint \[0-9\]+ \\(throw\\)" \
"catch throw (before inferior run)"
# Set a rethrow catchpoint
gdb_test "catch rethrow" "Catchpoint \[0-9\]+ \\(rethrow\\)" \
"catch rethrow (before inferior run)"
# The catchpoints should be listed in the list of breakpoints.
# In case of a statically linked test, we won't have a pending breakpoint.
@ -66,10 +71,11 @@ set addr "\(<PENDING>|$hex\)"
set re_head "Num${ws}Type${ws}Disp${ws}Enb${ws}Address${ws}What"
set re_2_bp "1${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception catch"
set re_3_bp "2${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception throw"
set re_4_bp "3${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception rethrow"
set name "info breakpoints (before inferior run)"
gdb_test_multiple "info breakpoints" $name {
-re "$re_head${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
-re "$re_head${ws}$re_2_bp${ws}$re_3_bp${ws}$re_4_bp\r\n$gdb_prompt $" {
pass $name
}
-re ".*$gdb_prompt $"
@ -78,13 +84,13 @@ gdb_test_multiple "info breakpoints" $name {
}
}
gdb_test "tbreak main" "Temporary breakpoint 3.*" \
gdb_test "tbreak main" "Temporary breakpoint 4.*" \
"Set temporary breakpoint at main"
set ok 0
gdb_run_cmd
gdb_test_multiple "" "Run to main" {
-re "Temporary breakpoint 3,.*$gdb_prompt $" {
-re "Temporary breakpoint 4,.*$gdb_prompt $" {
pass "Run to main"
set ok 1
}
@ -98,10 +104,11 @@ set addr "$hex"
set re_head "Num${ws}Type${ws}Disp${ws}Enb${ws}Address${ws}What"
set re_2_bp "1${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception catch"
set re_3_bp "2${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception throw"
set re_4_bp "3${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception rethrow"
set name "info breakpoints (after inferior run)"
gdb_test_multiple "info breakpoints" $name {
-re "$re_head${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
-re "$re_head${ws}$re_2_bp${ws}$re_3_bp${ws}$re_4_bp\r\n$gdb_prompt $" {
pass $name
}
-re ".*$gdb_prompt $"
@ -209,16 +216,8 @@ gdb_test_multiple "backtrace" $name {
# Continue to breakpoint on catcher.
gdb_test "continue" ".*catcher \\(x=13\\).*" "continue to catcher for the second time"
# That is all for now.
#
# The original code had:
#
# continue to re-throw ; backtrace
# continue to catch ; backtrace
# continue to throw out of main
#
# The problem is that "re-throw" does not show a throw; only a catch.
# I do not know if this is because of a bug, or because the generated
# code is optimized for a throw into the same function.
#
# -- chastain 2004-01-09
# Continue to the re-throw.
gdb_test "continue" "Catchpoint \[0-9\]+.*exception rethrown.*" \
"continue to rethrow"