mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-09 04:21:49 +08:00
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:
parent
02ae6bada6
commit
591f19e89b
@ -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
|
||||
|
3
gdb/NEWS
3
gdb/NEWS
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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}.
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user