[v2,7/8] Add $_ada_exception convenience variable

Message ID 20190801170412.5553-8-tromey@adacore.com
State New
Headers show
Series
  • Handle copy relocations and add $_ada_exception
Related show

Commit Message

Tom Tromey Aug. 1, 2019, 5:04 p.m.
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.

2019-08-01  Tom Tromey  <tromey@adacore.com>

	* NEWS: Add $_ada_exception entry.
	* ada-lang.c (struct ada_catchpoint): Add constructor.
	<m_kind>: 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-01  Tom Tromey  <tromey@adacore.com>

	* gdb.texinfo (Set Catchpoints, Convenience Vars): Document
	$_ada_exception.

gdb/testsuite/ChangeLog
2019-08-01  Tom Tromey  <tromey@adacore.com>

	* 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                    |  19 +-
 gdb/testsuite/ChangeLog                |   4 +
 gdb/testsuite/gdb.ada/catch_ex_std.exp |   3 +
 7 files changed, 141 insertions(+), 232 deletions(-)

-- 
2.20.1

Comments

Eli Zaretskii Aug. 1, 2019, 5:55 p.m. | #1
> From: Tom Tromey <tromey@adacore.com>

> Cc: Tom Tromey <tromey@adacore.com>

> Date: Thu,  1 Aug 2019 11:04:11 -0600

> 

> 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.

> 

> 2019-08-01  Tom Tromey  <tromey@adacore.com>

> 

> 	* NEWS: Add $_ada_exception entry.

> 	* ada-lang.c (struct ada_catchpoint): Add constructor.

> 	<m_kind>: 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-01  Tom Tromey  <tromey@adacore.com>

> 

> 	* gdb.texinfo (Set Catchpoints, Convenience Vars): Document

> 	$_ada_exception.

> 

> gdb/testsuite/ChangeLog

> 2019-08-01  Tom Tromey  <tromey@adacore.com>

> 

> 	* gdb.ada/catch_ex_std.exp: Add $_ada_exception test.


Thanks.  The documentation parts are approved, but I wonder whether we
should index this new variable, as others are indexed.
Andrew Burgess Aug. 27, 2019, 9:47 a.m. | #2
* Tom Tromey <tromey@adacore.com> [2019-08-01 11:04:11 -0600]:

> 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.

> 

> 2019-08-01  Tom Tromey  <tromey@adacore.com>

> 

> 	* NEWS: Add $_ada_exception entry.

> 	* ada-lang.c (struct ada_catchpoint): Add constructor.

> 	<m_kind>: 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-01  Tom Tromey  <tromey@adacore.com>

> 

> 	* gdb.texinfo (Set Catchpoints, Convenience Vars): Document

> 	$_ada_exception.

> 

> gdb/testsuite/ChangeLog

> 2019-08-01  Tom Tromey  <tromey@adacore.com>

> 

> 	* 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                    |  19 +-

>  gdb/testsuite/ChangeLog                |   4 +

>  gdb/testsuite/gdb.ada/catch_ex_std.exp |   3 +

>  7 files changed, 141 insertions(+), 232 deletions(-)

> 

> diff --git a/gdb/NEWS b/gdb/NEWS

> index ac44399304c..6bee9b13a38 100644

> --- a/gdb/NEWS

> +++ b/gdb/NEWS

> @@ -25,6 +25,9 @@

>    provide the exitcode or exit status of the shell commands launched by

>    GDB commands such as "shell", "pipe" and "make".

>  

> +* 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 6851386b48b..286eca3bfa1 100644

> --- a/gdb/ada-lang.c

> +++ b/gdb/ada-lang.c

> @@ -12275,8 +12275,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

> @@ -12336,8 +12344,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);

>  }

> @@ -12346,7 +12353,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;

>  

> @@ -12356,7 +12363,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

> @@ -12371,6 +12378,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;

> @@ -12404,7 +12435,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);

>  }

> @@ -12413,7 +12444,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;

> @@ -12439,13 +12470,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)

> @@ -12469,7 +12501,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);

>  	}

> @@ -12502,8 +12534,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;

> @@ -12515,7 +12546,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 ())

> @@ -12559,8 +12590,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;

> @@ -12570,7 +12600,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 ())

> @@ -12613,12 +12643,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");

> @@ -12644,192 +12673,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.  */

> @@ -13103,7 +12950,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<ada_catchpoint> c (new ada_catchpoint ());

> +  std::unique_ptr<ada_catchpoint> 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;

> @@ -14294,43 +14141,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 0fcd131f71e..ae266d4bfac 100644

> --- a/gdb/doc/gdb.texinfo

> +++ b/gdb/doc/gdb.texinfo

> @@ -4788,9 +4788,15 @@ 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}.

>  

> +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 +4818,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

> @@ -11742,6 +11752,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"


When I ran these tests I noticed that this new test was failing for
me.  It turns out that a previous test in this file already fails for
me, like this:

    (gdb) catch exception some_kind_of_error
    Your Ada runtime appears to be missing some debugging information.
    Cannot insert Ada exception catchpoint in this configuration.
    (gdb) FAIL: gdb.ada/catch_ex_std.exp: catch exception some_kind_of_error

And as a result, the new test will also fail.

I suspect there's probably a package I should be installing to resolve
this issue, but I put together the patch below that spots the above
warning and reports UNSUPPORTED rather than FAIL.  I don't know if
this is something you feel is worth including or not?

Obviously I've only confirmed that the UNSUPPORTED path through the
code works, so you'd need to test the PASS path for me.

Thanks,
Andrew

---

diff --git a/gdb/testsuite/gdb.ada/catch_ex_std.exp b/gdb/testsuite/gdb.ada/catch_ex_std.exp
index 839d0bb092f..97ea307c08f 100644
--- a/gdb/testsuite/gdb.ada/catch_ex_std.exp
+++ b/gdb/testsuite/gdb.ada/catch_ex_std.exp
@@ -95,12 +95,24 @@ if {![runto_main]} then {
    return 0
 }
 
-gdb_test "catch exception some_kind_of_error" \
-    "Catchpoint \[0-9\]+: `some_kind_of_error' Ada exception"
+set can_catch_exceptions 0
+set test "catch exception some_kind_of_error"
+gdb_test_multiple "$test" "$test" {
+    -re "Catchpoint \[0-9\]+: `some_kind_of_error' Ada exception\r\n$gdb_prompt $" {
+	pass $test
+	set can_catch_exceptions 1
+    }
 
-gdb_test "cont" \
-    "Catchpoint \[0-9\]+, .* at .*foo\.adb:\[0-9\]+.*" \
-    "caught the exception"
+    -re "Your Ada runtime appears to be missing some debugging information.\r\nCannot insert Ada exception catchpoint in this configuration.\r\n$gdb_prompt $" {
+	    unsupported $test
+    }
+}
 
-gdb_test "print \$_ada_exception = some_package.some_kind_of_error'Address" \
-    " = true"
+if { $can_catch_exceptions } {
+    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"
+}
Tom Tromey Sept. 20, 2019, 7:15 p.m. | #3
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:


>> +gdb_test "print \$_ada_exception = some_package.some_kind_of_error'Address" \

>> +    " = true"


Andrew> When I ran these tests I noticed that this new test was failing for
Andrew> me.  It turns out that a previous test in this file already fails for
Andrew> me, like this:

Andrew>     (gdb) catch exception some_kind_of_error
Andrew>     Your Ada runtime appears to be missing some debugging information.
Andrew>     Cannot insert Ada exception catchpoint in this configuration.
Andrew>     (gdb) FAIL: gdb.ada/catch_ex_std.exp: catch exception some_kind_of_error

Andrew> And as a result, the new test will also fail.

Andrew> I suspect there's probably a package I should be installing to resolve
Andrew> this issue, but I put together the patch below that spots the above
Andrew> warning and reports UNSUPPORTED rather than FAIL.  I don't know if
Andrew> this is something you feel is worth including or not?

Andrew> Obviously I've only confirmed that the UNSUPPORTED path through the
Andrew> code works, so you'd need to test the PASS path for me.

Thanks.  This does still work for me.  I think you should check it in.
Maybe it's also needed by catch_ex.exp?

Tom
Tom Tromey Sept. 20, 2019, 7:16 p.m. | #4
>> gdb/doc/ChangeLog

>> 2019-08-01  Tom Tromey  <tromey@adacore.com>

>> 

>> * gdb.texinfo (Set Catchpoints, Convenience Vars): Document

>> $_ada_exception.


Eli> Thanks.  The documentation parts are approved, but I wonder whether we
Eli> should index this new variable, as others are indexed.

I've done this in the next version of the patch.

Tom

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index ac44399304c..6bee9b13a38 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -25,6 +25,9 @@ 
   provide the exitcode or exit status of the shell commands launched by
   GDB commands such as "shell", "pipe" and "make".
 
+* 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 6851386b48b..286eca3bfa1 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12275,8 +12275,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
@@ -12336,8 +12344,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);
 }
@@ -12346,7 +12353,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;
 
@@ -12356,7 +12363,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
@@ -12371,6 +12378,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;
@@ -12404,7 +12435,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);
 }
@@ -12413,7 +12444,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;
@@ -12439,13 +12470,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)
@@ -12469,7 +12501,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);
 	}
@@ -12502,8 +12534,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;
@@ -12515,7 +12546,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 ())
@@ -12559,8 +12590,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;
@@ -12570,7 +12600,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 ())
@@ -12613,12 +12643,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");
@@ -12644,192 +12673,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.  */
@@ -13103,7 +12950,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<ada_catchpoint> c (new ada_catchpoint ());
+  std::unique_ptr<ada_catchpoint> 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;
@@ -14294,43 +14141,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 0fcd131f71e..ae266d4bfac 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4788,9 +4788,15 @@  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}.
 
+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 +4818,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
@@ -11742,6 +11752,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"