From patchwork Fri Sep 20 19:20:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 34621 Received: (qmail 118293 invoked by alias); 20 Sep 2019 19:20:29 -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 118188 invoked by uid 89); 20 Sep 2019 19:20:29 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=Points 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, 20 Sep 2019 19:20:25 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id A0E5E56080; Fri, 20 Sep 2019 15:20:22 -0400 (EDT) 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 WrttHwSvL2SW; Fri, 20 Sep 2019 15:20:22 -0400 (EDT) Received: from murgatroyd.Home (71-218-73-27.hlrn.qwest.net [71.218.73.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPSA id 46E6056079; Fri, 20 Sep 2019 15:20:22 -0400 (EDT) From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH v2 8/8] Add $_ada_exception convenience variable Date: Fri, 20 Sep 2019 13:20:17 -0600 Message-Id: <20190920192017.15293-9-tromey@adacore.com> In-Reply-To: <20190920192017.15293-1-tromey@adacore.com> References: <20190920192017.15293-1-tromey@adacore.com> MIME-Version: 1.0 This adds the $_ada_exception convenience variable. It is set by the Ada exception catchpoints, and holds the address of the exception currently being thrown. This is useful because it allows more fine-grained filtering of exceptions than is possible using the existing "catch" syntax. This also simplifies Ada catchpoints somewhat; because the catchpoint must now carry the "kind", it's possible to remove many helper functions. gdb/ChangeLog 2019-08-21 Tom Tromey * NEWS: Add $_ada_exception entry. * ada-lang.c (struct ada_catchpoint): Add constructor. : New member. (allocate_location_exception, re_set_exception): Remove "ex" parameter. (should_stop_exception): Compute $_ada_exception. (check_status_exception, print_it_exception) (print_one_exception, print_mention_exception): Remove "ex" parameter. (allocate_location_catch_exception, re_set_catch_exception) (check_status_exception, print_it_catch_exception) (print_one_catch_exception, print_mention_catch_exception) (print_recreate_catch_exception) (allocate_location_catch_exception_unhandled) (re_set_catch_exception_unhandled) (check_status_exception, print_it_catch_exception_unhandled) (print_one_catch_exception_unhandled) (print_mention_catch_exception_unhandled) (print_recreate_catch_exception_unhandled) (allocate_location_catch_assert, re_set_catch_assert) (check_status_assert, print_it_catch_assert) (print_one_catch_assert, print_mention_catch_assert) (print_recreate_catch_assert) (allocate_location_catch_handlers, re_set_catch_handlers) (check_status_handlers, print_it_catch_handlers) (print_one_catch_handlers, print_mention_catch_handlers) (print_recreate_catch_handlers): Remove. (create_ada_exception_catchpoint): Update. (initialize_ada_catchpoint_ops): Update. gdb/doc/ChangeLog 2019-08-21 Tom Tromey * gdb.texinfo (Set Catchpoints, Convenience Vars): Document $_ada_exception. gdb/testsuite/ChangeLog 2019-08-21 Tom Tromey * gdb.ada/catch_ex_std.exp: Add $_ada_exception test. --- gdb/ChangeLog | 32 +++ gdb/NEWS | 3 + gdb/ada-lang.c | 307 +++++++------------------ gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 20 +- gdb/testsuite/ChangeLog | 4 + gdb/testsuite/gdb.ada/catch_ex_std.exp | 3 + 7 files changed, 142 insertions(+), 232 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 1fefd814095..959ea27e749 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -34,6 +34,9 @@ * GDB can now be compiled with Python 3 on Windows. +* New convenience variable $_ada_exception holds the address of the + Ada exception being thrown. This is set by Ada-related catchpoints. + * Python API ** The gdb.Value type has a new method 'format_string' which returns a diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index e4702b96876..1f388eb4dba 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -12326,8 +12326,16 @@ public: struct ada_catchpoint : public breakpoint { + explicit ada_catchpoint (enum ada_exception_catchpoint_kind kind) + : m_kind (kind) + { + } + /* The name of the specific exception the user specified. */ std::string excep_string; + + /* What kind of catchpoint this is. */ + enum ada_exception_catchpoint_kind m_kind; }; /* Parse the exception condition string in the context of each of the @@ -12387,8 +12395,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c, structure for all exception catchpoint kinds. */ static struct bp_location * -allocate_location_exception (enum ada_exception_catchpoint_kind ex, - struct breakpoint *self) +allocate_location_exception (struct breakpoint *self) { return new ada_catchpoint_location (self); } @@ -12397,7 +12404,7 @@ allocate_location_exception (enum ada_exception_catchpoint_kind ex, exception catchpoint kinds. */ static void -re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b) +re_set_exception (struct breakpoint *b) { struct ada_catchpoint *c = (struct ada_catchpoint *) b; @@ -12407,7 +12414,7 @@ re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b) /* Reparse the exception conditional expressions. One for each location. */ - create_excep_cond_exprs (c, ex); + create_excep_cond_exprs (c, c->m_kind); } /* Returns true if we should stop for this breakpoint hit. If the @@ -12422,6 +12429,30 @@ should_stop_exception (const struct bp_location *bl) = (const struct ada_catchpoint_location *) bl; int stop; + struct internalvar *var = lookup_internalvar ("_ada_exception"); + if (c->m_kind == ada_catch_assert) + clear_internalvar (var); + else + { + try + { + const char *expr; + + if (c->m_kind == ada_catch_handlers) + expr = ("GNAT_GCC_exception_Access(gcc_exception)" + ".all.occurrence.id"); + else + expr = "e"; + + struct value *exc = parse_and_eval (expr); + set_internalvar (var, exc); + } + catch (const gdb_exception_error &ex) + { + clear_internalvar (var); + } + } + /* With no specific exception, should always stop. */ if (c->excep_string.empty ()) return 1; @@ -12455,7 +12486,7 @@ should_stop_exception (const struct bp_location *bl) for all exception catchpoint kinds. */ static void -check_status_exception (enum ada_exception_catchpoint_kind ex, bpstat bs) +check_status_exception (bpstat bs) { bs->stop = should_stop_exception (bs->bp_location_at); } @@ -12464,7 +12495,7 @@ check_status_exception (enum ada_exception_catchpoint_kind ex, bpstat bs) for all exception catchpoint kinds. */ static enum print_stop_action -print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs) +print_it_exception (bpstat bs) { struct ui_out *uiout = current_uiout; struct breakpoint *b = bs->breakpoint_at; @@ -12490,13 +12521,14 @@ print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs) ada_find_printable_frame). */ select_frame (get_current_frame ()); - switch (ex) + struct ada_catchpoint *c = (struct ada_catchpoint *) b; + switch (c->m_kind) { case ada_catch_exception: case ada_catch_exception_unhandled: case ada_catch_handlers: { - const CORE_ADDR addr = ada_exception_name_addr (ex, b); + const CORE_ADDR addr = ada_exception_name_addr (c->m_kind, b); char exception_name[256]; if (addr != 0) @@ -12520,7 +12552,7 @@ print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs) it clearer to the user which kind of catchpoint just got hit. We used ui_out_text to make sure that this extra info does not pollute the exception name in the MI case. */ - if (ex == ada_catch_exception_unhandled) + if (c->m_kind == ada_catch_exception_unhandled) uiout->text ("unhandled "); uiout->field_string ("exception-name", exception_name); } @@ -12553,8 +12585,7 @@ print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs) for all exception catchpoint kinds. */ static void -print_one_exception (enum ada_exception_catchpoint_kind ex, - struct breakpoint *b, struct bp_location **last_loc) +print_one_exception (struct breakpoint *b, struct bp_location **last_loc) { struct ui_out *uiout = current_uiout; struct ada_catchpoint *c = (struct ada_catchpoint *) b; @@ -12566,7 +12597,7 @@ print_one_exception (enum ada_exception_catchpoint_kind ex, uiout->field_skip ("addr"); annotate_field (5); - switch (ex) + switch (c->m_kind) { case ada_catch_exception: if (!c->excep_string.empty ()) @@ -12610,8 +12641,7 @@ print_one_exception (enum ada_exception_catchpoint_kind ex, for all exception catchpoint kinds. */ static void -print_mention_exception (enum ada_exception_catchpoint_kind ex, - struct breakpoint *b) +print_mention_exception (struct breakpoint *b) { struct ada_catchpoint *c = (struct ada_catchpoint *) b; struct ui_out *uiout = current_uiout; @@ -12621,7 +12651,7 @@ print_mention_exception (enum ada_exception_catchpoint_kind ex, uiout->field_signed ("bkptno", b->number); uiout->text (": "); - switch (ex) + switch (c->m_kind) { case ada_catch_exception: if (!c->excep_string.empty ()) @@ -12664,12 +12694,11 @@ print_mention_exception (enum ada_exception_catchpoint_kind ex, for all exception catchpoint kinds. */ static void -print_recreate_exception (enum ada_exception_catchpoint_kind ex, - struct breakpoint *b, struct ui_file *fp) +print_recreate_exception (struct breakpoint *b, struct ui_file *fp) { struct ada_catchpoint *c = (struct ada_catchpoint *) b; - switch (ex) + switch (c->m_kind) { case ada_catch_exception: fprintf_filtered (fp, "catch exception"); @@ -12695,192 +12724,10 @@ print_recreate_exception (enum ada_exception_catchpoint_kind ex, print_recreate_thread (b, fp); } -/* Virtual table for "catch exception" breakpoints. */ - -static struct bp_location * -allocate_location_catch_exception (struct breakpoint *self) -{ - return allocate_location_exception (ada_catch_exception, self); -} - -static void -re_set_catch_exception (struct breakpoint *b) -{ - re_set_exception (ada_catch_exception, b); -} - -static void -check_status_catch_exception (bpstat bs) -{ - check_status_exception (ada_catch_exception, bs); -} - -static enum print_stop_action -print_it_catch_exception (bpstat bs) -{ - return print_it_exception (ada_catch_exception, bs); -} - -static void -print_one_catch_exception (struct breakpoint *b, struct bp_location **last_loc) -{ - print_one_exception (ada_catch_exception, b, last_loc); -} - -static void -print_mention_catch_exception (struct breakpoint *b) -{ - print_mention_exception (ada_catch_exception, b); -} - -static void -print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp) -{ - print_recreate_exception (ada_catch_exception, b, fp); -} - +/* Virtual tables for various breakpoint types. */ static struct breakpoint_ops catch_exception_breakpoint_ops; - -/* Virtual table for "catch exception unhandled" breakpoints. */ - -static struct bp_location * -allocate_location_catch_exception_unhandled (struct breakpoint *self) -{ - return allocate_location_exception (ada_catch_exception_unhandled, self); -} - -static void -re_set_catch_exception_unhandled (struct breakpoint *b) -{ - re_set_exception (ada_catch_exception_unhandled, b); -} - -static void -check_status_catch_exception_unhandled (bpstat bs) -{ - check_status_exception (ada_catch_exception_unhandled, bs); -} - -static enum print_stop_action -print_it_catch_exception_unhandled (bpstat bs) -{ - return print_it_exception (ada_catch_exception_unhandled, bs); -} - -static void -print_one_catch_exception_unhandled (struct breakpoint *b, - struct bp_location **last_loc) -{ - print_one_exception (ada_catch_exception_unhandled, b, last_loc); -} - -static void -print_mention_catch_exception_unhandled (struct breakpoint *b) -{ - print_mention_exception (ada_catch_exception_unhandled, b); -} - -static void -print_recreate_catch_exception_unhandled (struct breakpoint *b, - struct ui_file *fp) -{ - print_recreate_exception (ada_catch_exception_unhandled, b, fp); -} - static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops; - -/* Virtual table for "catch assert" breakpoints. */ - -static struct bp_location * -allocate_location_catch_assert (struct breakpoint *self) -{ - return allocate_location_exception (ada_catch_assert, self); -} - -static void -re_set_catch_assert (struct breakpoint *b) -{ - re_set_exception (ada_catch_assert, b); -} - -static void -check_status_catch_assert (bpstat bs) -{ - check_status_exception (ada_catch_assert, bs); -} - -static enum print_stop_action -print_it_catch_assert (bpstat bs) -{ - return print_it_exception (ada_catch_assert, bs); -} - -static void -print_one_catch_assert (struct breakpoint *b, struct bp_location **last_loc) -{ - print_one_exception (ada_catch_assert, b, last_loc); -} - -static void -print_mention_catch_assert (struct breakpoint *b) -{ - print_mention_exception (ada_catch_assert, b); -} - -static void -print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp) -{ - print_recreate_exception (ada_catch_assert, b, fp); -} - static struct breakpoint_ops catch_assert_breakpoint_ops; - -/* Virtual table for "catch handlers" breakpoints. */ - -static struct bp_location * -allocate_location_catch_handlers (struct breakpoint *self) -{ - return allocate_location_exception (ada_catch_handlers, self); -} - -static void -re_set_catch_handlers (struct breakpoint *b) -{ - re_set_exception (ada_catch_handlers, b); -} - -static void -check_status_catch_handlers (bpstat bs) -{ - check_status_exception (ada_catch_handlers, bs); -} - -static enum print_stop_action -print_it_catch_handlers (bpstat bs) -{ - return print_it_exception (ada_catch_handlers, bs); -} - -static void -print_one_catch_handlers (struct breakpoint *b, - struct bp_location **last_loc) -{ - print_one_exception (ada_catch_handlers, b, last_loc); -} - -static void -print_mention_catch_handlers (struct breakpoint *b) -{ - print_mention_exception (ada_catch_handlers, b); -} - -static void -print_recreate_catch_handlers (struct breakpoint *b, - struct ui_file *fp) -{ - print_recreate_exception (ada_catch_handlers, b, fp); -} - static struct breakpoint_ops catch_handlers_breakpoint_ops; /* See ada-lang.h. */ @@ -13154,7 +13001,7 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch, const struct breakpoint_ops *ops = NULL; struct symtab_and_line sal = ada_exception_sal (ex_kind, &addr_string, &ops); - std::unique_ptr c (new ada_catchpoint ()); + std::unique_ptr c (new ada_catchpoint (ex_kind)); init_ada_exception_breakpoint (c.get (), gdbarch, sal, addr_string.c_str (), ops, tempflag, disabled, from_tty); c->excep_string = excep_string; @@ -14345,43 +14192,43 @@ initialize_ada_catchpoint_ops (void) ops = &catch_exception_breakpoint_ops; *ops = bkpt_breakpoint_ops; - ops->allocate_location = allocate_location_catch_exception; - ops->re_set = re_set_catch_exception; - ops->check_status = check_status_catch_exception; - ops->print_it = print_it_catch_exception; - ops->print_one = print_one_catch_exception; - ops->print_mention = print_mention_catch_exception; - ops->print_recreate = print_recreate_catch_exception; + ops->allocate_location = allocate_location_exception; + ops->re_set = re_set_exception; + ops->check_status = check_status_exception; + ops->print_it = print_it_exception; + ops->print_one = print_one_exception; + ops->print_mention = print_mention_exception; + ops->print_recreate = print_recreate_exception; ops = &catch_exception_unhandled_breakpoint_ops; *ops = bkpt_breakpoint_ops; - ops->allocate_location = allocate_location_catch_exception_unhandled; - ops->re_set = re_set_catch_exception_unhandled; - ops->check_status = check_status_catch_exception_unhandled; - ops->print_it = print_it_catch_exception_unhandled; - ops->print_one = print_one_catch_exception_unhandled; - ops->print_mention = print_mention_catch_exception_unhandled; - ops->print_recreate = print_recreate_catch_exception_unhandled; + ops->allocate_location = allocate_location_exception; + ops->re_set = re_set_exception; + ops->check_status = check_status_exception; + ops->print_it = print_it_exception; + ops->print_one = print_one_exception; + ops->print_mention = print_mention_exception; + ops->print_recreate = print_recreate_exception; ops = &catch_assert_breakpoint_ops; *ops = bkpt_breakpoint_ops; - ops->allocate_location = allocate_location_catch_assert; - ops->re_set = re_set_catch_assert; - ops->check_status = check_status_catch_assert; - ops->print_it = print_it_catch_assert; - ops->print_one = print_one_catch_assert; - ops->print_mention = print_mention_catch_assert; - ops->print_recreate = print_recreate_catch_assert; + ops->allocate_location = allocate_location_exception; + ops->re_set = re_set_exception; + ops->check_status = check_status_exception; + ops->print_it = print_it_exception; + ops->print_one = print_one_exception; + ops->print_mention = print_mention_exception; + ops->print_recreate = print_recreate_exception; ops = &catch_handlers_breakpoint_ops; *ops = bkpt_breakpoint_ops; - ops->allocate_location = allocate_location_catch_handlers; - ops->re_set = re_set_catch_handlers; - ops->check_status = check_status_catch_handlers; - ops->print_it = print_it_catch_handlers; - ops->print_one = print_one_catch_handlers; - ops->print_mention = print_mention_catch_handlers; - ops->print_recreate = print_recreate_catch_handlers; + ops->allocate_location = allocate_location_exception; + ops->re_set = re_set_exception; + ops->check_status = check_status_exception; + ops->print_it = print_it_exception; + ops->print_one = print_one_exception; + ops->print_mention = print_mention_exception; + ops->print_recreate = print_recreate_exception; } /* This module's 'new_objfile' observer. */ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a129ea0aa1b..c3ed62002f8 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4788,9 +4788,16 @@ called @code{Constraint_Error} is defined in package @code{Pck}, then the command to use to catch such exceptions is @kbd{catch exception Pck.Constraint_Error}. +@vindex $_ada_exception@r{, convenience variable} +The convenience variable @code{$_ada_exception} holds the address of +the exception being thrown. This can be useful when setting a +condition for such a catchpoint. + @item exception unhandled @kindex catch exception unhandled -An exception that was raised but is not handled by the program. +An exception that was raised but is not handled by the program. The +convenience variable @code{$_ada_exception} is set as for @code{catch +exception}. @item handlers @r{[}@var{name}@r{]} @kindex catch handlers @@ -4812,9 +4819,13 @@ user-defined one. For instance, assuming an exception called command to use to catch such exceptions handling is @kbd{catch handlers Pck.Constraint_Error}. +The convenience variable @code{$_ada_exception} is set as for +@code{catch exception}. + @item assert @kindex catch assert -A failed Ada assertion. +A failed Ada assertion. Note that the convenience variable +@code{$_ada_exception} is @emph{not} set by this catchpoint. @item exec @kindex catch exec @@ -11823,6 +11834,11 @@ The program has exited The variable @code{$_exception} is set to the exception object being thrown at an exception-related catchpoint. @xref{Set Catchpoints}. +@item $_ada_exception +The variable @code{$_ada_exception} is set to the address of the +exception being caught or thrown at an Ada exception-related +catchpoint. @xref{Set Catchpoints}. + @item $_probe_argc @itemx $_probe_arg0@dots{}$_probe_arg11 Arguments to a static probe. @xref{Static Probe Points}. diff --git a/gdb/testsuite/gdb.ada/catch_ex_std.exp b/gdb/testsuite/gdb.ada/catch_ex_std.exp index 63714a8aa81..839d0bb092f 100644 --- a/gdb/testsuite/gdb.ada/catch_ex_std.exp +++ b/gdb/testsuite/gdb.ada/catch_ex_std.exp @@ -101,3 +101,6 @@ gdb_test "catch exception some_kind_of_error" \ gdb_test "cont" \ "Catchpoint \[0-9\]+, .* at .*foo\.adb:\[0-9\]+.*" \ "caught the exception" + +gdb_test "print \$_ada_exception = some_package.some_kind_of_error'Address" \ + " = true"