This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [RFA/doco] (Ada) provide the exception message when hitting an exception catchpoint
- From: Joel Brobecker <brobecker at adacore dot com>
- To: Eli Zaretskii <eliz at gnu dot org>
- Cc: Xavier Roirand <roirand at adacore dot com>, gdb-patches at sourceware dot org
- Date: Fri, 24 Nov 2017 13:32:21 -0800
- Subject: Re: [RFA/doco] (Ada) provide the exception message when hitting an exception catchpoint
- Authentication-results: sourceware.org; auth=none
- References: <1510953646-116765-1-git-send-email-brobecker@adacore.com>
Hi Eli,
Would you have some time to review the doc changes in the patches
below?
Thanks!
On Fri, Nov 17, 2017 at 04:20:46PM -0500, Joel Brobecker wrote:
> Hello,
>
> This patch enhances the debugger to print the exception message, when
> available, as part of an exception catchpoint hit notification (both
> GDB/CLI and GDB/MI). For instance, with the following code...
>
> procedure A is
> begin
> raise Constraint_Error with "hello world";
> end A;
>
> ... instead of printing...
>
> Catchpoint 1, CONSTRAINT_ERROR at 0x000000000040245c in a () at a.adb:3
>
> ... it now prints:
>
> Catchpoint 1, CONSTRAINT_ERROR (hello world) at 0x000000000040245c in a ()
> ^^^^^^^^^^^^^
>
> This enhancement requires runtime support. If not present, the debugger
> just behaves as before.
>
> In GDB/MI mode, if the exception message is available, it is provided
> as an extra field named "exception-message" in the catchpoint notification:
>
> *stopped,bkptno="1",[...],exception-name="CONSTRAINT_ERROR",
> exception-message="hello world",[...]
>
> gdb/ChangeLog:
>
> * ada-lang.c (ada_exception_message_1, ada_exception_message):
> New functions.
> (print_it_exception): If available, display the exception
> message as well.
> NEWS: Document new feature.
>
> gdb/doc/ChangeLog:
>
> * gdb.texinfo (GDB/MI Ada Exception Information): Document
> new "exception-message" field.
>
> gdb/testsuite/ChangeLog:
>
> * gdb.ada/catch_ex.exp, gdb.ada/mi_catch_ex.exp,
> gdb.ada/mi_ex_cond.exp: Accept optional exception message in
> when hitting an exception catchpoint.
>
> Tested on x86_64-linux, no regression.
>
> Are the NEWS and doc/gdb.texinfo changes OK to commit?
>
> Thank you,
> --
> Joel
>
> ---
> gdb/NEWS | 5 +++
> gdb/ada-lang.c | 81 +++++++++++++++++++++++++++++++++++
> gdb/doc/gdb.texinfo | 4 +-
> gdb/testsuite/gdb.ada/catch_ex.exp | 8 ++--
> gdb/testsuite/gdb.ada/mi_catch_ex.exp | 10 ++---
> gdb/testsuite/gdb.ada/mi_ex_cond.exp | 2 +-
> 6 files changed, 99 insertions(+), 11 deletions(-)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index dc070fa..5928bd6 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -52,6 +52,11 @@
> variables that are to be set or unset from GDB. These variables
> will affect the environment to be passed to the inferior.
>
> +* When catching an Ada exception raised with a message, GDB now prints
> + the message in the catchpoint hit notification. In GDB/MI mode, that
> + information is provided as an extra field named "exception-message"
> + in the *stopped notification.
> +
> * New remote packets
>
> QEnvironmentHexEncoded
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 33c4e8e..3265c21 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -12105,6 +12105,73 @@ ada_exception_name_addr_1 (enum ada_exception_catchpoint_kind ex,
> return 0; /* Should never be reached. */
> }
>
> +/* Assuming the inferior is stopped at an exception catchpoint,
> + return the message which was associated to the exception, if
> + available. Return NULL if the message could not be retrieved.
> +
> + The caller must xfree the string after use.
> +
> + Note: The exception message can be associated to an exception
> + either through the use of the Raise_Exception function, or
> + more simply (Ada 2005 and later), via:
> +
> + raise Exception_Name with "exception message";
> +
> + */
> +
> +static char *
> +ada_exception_message_1 (void)
> +{
> + struct value *e_msg_val;
> + char *e_msg = NULL;
> + int e_msg_len;
> + struct cleanup *cleanups;
> +
> + /* For runtimes that support this feature, the exception message
> + is passed as an unbounded string argument called "message". */
> + e_msg_val = parse_and_eval ("message");
> + if (e_msg_val == NULL)
> + return NULL; /* Exception message not supported. */
> +
> + e_msg_val = ada_coerce_to_simple_array (e_msg_val);
> + gdb_assert (e_msg_val != NULL);
> + e_msg_len = TYPE_LENGTH (value_type (e_msg_val));
> +
> + /* If the message string is empty, then treat it as if there was
> + no exception message. */
> + if (e_msg_len <= 0)
> + return NULL;
> +
> + e_msg = (char *) xmalloc (e_msg_len + 1);
> + cleanups = make_cleanup (xfree, e_msg);
> + read_memory_string (value_address (e_msg_val), e_msg, e_msg_len + 1);
> + e_msg[e_msg_len] = '\0';
> +
> + discard_cleanups (cleanups);
> + return e_msg;
> +}
> +
> +/* Same as ada_exception_message_1, except that all exceptions are
> + contained here (returning NULL instead). */
> +
> +static char *
> +ada_exception_message (void)
> +{
> + char *e_msg = NULL; /* Avoid a spurious uninitialized warning. */
> +
> + TRY
> + {
> + e_msg = ada_exception_message_1 ();
> + }
> + CATCH (e, RETURN_MASK_ERROR)
> + {
> + e_msg = NULL;
> + }
> + END_CATCH
> +
> + return e_msg;
> +}
> +
> /* Same as ada_exception_name_addr_1, except that it intercepts and contains
> any error that ada_exception_name_addr_1 might cause to be thrown.
> When an error is intercepted, a warning with the error message is printed,
> @@ -12340,6 +12407,7 @@ print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
> {
> struct ui_out *uiout = current_uiout;
> struct breakpoint *b = bs->breakpoint_at;
> + char *exception_message;
>
> annotate_catchpoint (b->number);
>
> @@ -12405,6 +12473,19 @@ print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
> uiout->text ("failed assertion");
> break;
> }
> +
> + exception_message = ada_exception_message ();
> + if (exception_message != NULL)
> + {
> + struct cleanup *cleanups = make_cleanup (xfree, exception_message);
> +
> + uiout->text (" (");
> + uiout->field_string ("exception-message", exception_message);
> + uiout->text (")");
> +
> + do_cleanups (cleanups);
> + }
> +
> uiout->text (" at ");
> ada_find_printable_frame (get_current_frame ());
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 29d4789..430db0f 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -27183,7 +27183,9 @@ thread was last seen on. This field is optional.
> 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.
> +the @code{exception-name} field. Also, for exceptions that were raised
> +with an exception message, @value{GDBN} provides that message via
> +the @code{exception-message} field.
>
> @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> @node GDB/MI Simple Examples
> diff --git a/gdb/testsuite/gdb.ada/catch_ex.exp b/gdb/testsuite/gdb.ada/catch_ex.exp
> index 5313e77..3797601 100644
> --- a/gdb/testsuite/gdb.ada/catch_ex.exp
> +++ b/gdb/testsuite/gdb.ada/catch_ex.exp
> @@ -62,13 +62,13 @@ gdb_test "info break" \
> "info break, catch all Ada exceptions"
>
> set catchpoint_msg \
> - "Catchpoint $any_nb, CONSTRAINT_ERROR at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> + "Catchpoint $any_nb, CONSTRAINT_ERROR (\\\(foo\\.adb:$decimal explicit raise\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> gdb_test "continue" \
> "Continuing\.$eol$catchpoint_msg$eol.*SPOT1" \
> "continuing to first exception"
>
> set catchpoint_msg \
> - "Catchpoint $any_nb, PROGRAM_ERROR at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> + "Catchpoint $any_nb, PROGRAM_ERROR (\\\(foo\\.adb:$decimal explicit raise\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> gdb_test "continue" \
> "Continuing\.$eol$catchpoint_msg$eol.*SPOT2" \
> "continuing to second exception"
> @@ -116,7 +116,7 @@ gdb_test "info break" \
> "info break, second run"
>
> set catchpoint_msg \
> - "Catchpoint $any_nb, PROGRAM_ERROR at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> + "Catchpoint $any_nb, PROGRAM_ERROR (\\\(foo.adb:$decimal explicit raise\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> gdb_test "continue" \
> "Continuing\.$eol$catchpoint_msg$eol.*SPOT2" \
> "continuing to Program_Error exception"
> @@ -157,7 +157,7 @@ gdb_test "tcatch exception" \
> "Temporary catchpoint $any_nb: all Ada exceptions"
>
> set temp_catchpoint_msg \
> - "Temporary catchpoint $any_nb, CONSTRAINT_ERROR at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> + "Temporary catchpoint $any_nb, CONSTRAINT_ERROR (\\\(.*\\\) )?at $any_addr in foo \\\(\\\).*at .*foo.adb:$any_nb"
> gdb_test "continue" \
> "Continuing\.$eol$temp_catchpoint_msg$eol.*SPOT1" \
> "continuing to temporary catchpoint"
> diff --git a/gdb/testsuite/gdb.ada/mi_catch_ex.exp b/gdb/testsuite/gdb.ada/mi_catch_ex.exp
> index c9dd616..2ca3b6c 100644
> --- a/gdb/testsuite/gdb.ada/mi_catch_ex.exp
> +++ b/gdb/testsuite/gdb.ada/mi_catch_ex.exp
> @@ -80,7 +80,7 @@ mi_gdb_test "-catch-exception" \
>
> # Continue to caught exception.
>
> -proc continue_to_exception { exception_name test } {
> +proc continue_to_exception { exception_name exception_message test } {
> global hex any_nb
>
> mi_send_resuming_command "exec-continue" "$test"
> @@ -97,18 +97,18 @@ proc continue_to_exception { exception_name test } {
>
> # Now MI stream output.
> mi_expect_stop \
> - "breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"$exception_name" \
> + "breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"$exception_name(\",exception-message=\"$exception_message)?" \
> "foo" "" ".*" ".*" \
> ".*" \
> $test
> }
>
> continue_to_exception \
> - "CONSTRAINT_ERROR" \
> + "CONSTRAINT_ERROR" "foo\\.adb:$decimal explicit raise" \
> "continue until CE caught by all-exceptions catchpoint"
>
> continue_to_exception \
> - "PROGRAM_ERROR" \
> + "PROGRAM_ERROR" "foo\\.adb:$decimal explicit raise" \
> "continue until PE caught by all-exceptions catchpoint"
>
> ################################################
> @@ -143,7 +143,7 @@ mi_gdb_test "-catch-exception -u" \
> "catch unhandled exceptions"
>
> mi_execute_to "exec-continue" \
> - "breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"PROGRAM_ERROR" \
> + "breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"PROGRAM_ERROR(\",exception-message=\"foo\\.adb:$decimal explicit raise)?" \
> "foo" "" ".*" ".*" \
> ".*" \
> "continue to exception catchpoint hit"
> diff --git a/gdb/testsuite/gdb.ada/mi_ex_cond.exp b/gdb/testsuite/gdb.ada/mi_ex_cond.exp
> index 78765be..369f155 100644
> --- a/gdb/testsuite/gdb.ada/mi_ex_cond.exp
> +++ b/gdb/testsuite/gdb.ada/mi_ex_cond.exp
> @@ -81,7 +81,7 @@ mi_gdb_test "-catch-exception -c \"i = 2\" -e constraint_error" \
> mi_run_cmd
>
> mi_expect_stop \
> - "breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"CONSTRAINT_ERROR" \
> + "breakpoint-hit\",disp=\"keep\",bkptno=\"$any_nb\",exception-name=\"CONSTRAINT_ERROR(\",exception-message=\"foo\\.adb:$decimal explicit raise)?" \
> "foo" "" ".*" ".*" \
> ".*" \
> "run to exception catchpoint hit"
> --
> 2.1.4
--
Joel