From patchwork Fri Nov 17 21:20:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Brobecker X-Patchwork-Id: 24336 Received: (qmail 41413 invoked by alias); 17 Nov 2017 21:20:54 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 41184 invoked by uid 89); 17 Nov 2017 21:20:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KB_WAM_FROM_NAME_SINGLEWORD, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Whenever X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 17 Nov 2017 21:20:50 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 5B4F91163DB; Fri, 17 Nov 2017 16:20:49 -0500 (EST) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id NVs5JYqWC5Yn; Fri, 17 Nov 2017 16:20:49 -0500 (EST) Received: from tron.gnat.com (tron.gnat.com [205.232.38.10]) by rock.gnat.com (Postfix) with ESMTP id 49FF01163A9; Fri, 17 Nov 2017 16:20:49 -0500 (EST) Received: by tron.gnat.com (Postfix, from userid 4233) id 44D9010C; Fri, 17 Nov 2017 16:20:49 -0500 (EST) From: Joel Brobecker To: gdb-patches@sourceware.org Cc: Xavier Roirand Subject: [RFA/doco] (Ada) provide the exception message when hitting an exception catchpoint Date: Fri, 17 Nov 2017 16:20:46 -0500 Message-Id: <1510953646-116765-1-git-send-email-brobecker@adacore.com> 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, 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"