* 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.
+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
* 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.
enum exception_event_kind
{
EX_EVENT_THROW,
+ EX_EVENT_RETHROW,
EX_EVENT_CATCH
};
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,
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",
{
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)
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;
}
}
{
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
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);
}
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,
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))
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,
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,
+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.
@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.
+
+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 catch
-The catching of a C@t{++} exception.
+@item
+You cannot install an exception handler interactively.
+@end itemize
@item exception
@cindex Ada exception catching
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
@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}.
+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
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.
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 $"
}
}
-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
}
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 $"
# 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"