Add $_ada_exception convenience variable

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-10-02  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-10-02  Tom Tromey  <tromey@adacore.com>

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

gdb/testsuite/ChangeLog
2019-10-02  Tom Tromey  <tromey@adacore.com>

	* gdb.ada/catch_ex_std.exp: Add $_ada_exception test.
This commit is contained in:
Tom Tromey 2019-05-31 14:50:23 -06:00
parent fccf9de11f
commit 37f6a7f456
7 changed files with 142 additions and 232 deletions

View File

@ -1,3 +1,35 @@
2019-10-02 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.
2019-10-02 Tom Tromey <tromey@adacore.com>
* ada-lang.c (ada_lookup_simple_minsyms): Remove.

View File

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

View File

@ -12314,8 +12314,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
@ -12375,8 +12383,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);
}
@ -12385,7 +12392,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;
@ -12395,7 +12402,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
@ -12410,6 +12417,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;
@ -12443,7 +12474,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);
}
@ -12452,7 +12483,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;
@ -12478,13 +12509,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)
@ -12508,7 +12540,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);
}
@ -12541,8 +12573,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;
@ -12554,7 +12585,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 ())
@ -12598,8 +12629,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;
@ -12609,7 +12639,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 ())
@ -12652,12 +12682,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");
@ -12683,192 +12712,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. */
@ -13142,7 +12989,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;
@ -14333,43 +14180,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. */

View File

@ -1,3 +1,8 @@
2019-10-02 Tom Tromey <tromey@adacore.com>
* gdb.texinfo (Set Catchpoints, Convenience Vars): Document
$_ada_exception.
2019-09-20 Ulrich Weigand <uweigand@de.ibm.com>
* doc/gdb.texinfo (Remote Configuration): Remove documentation for

View File

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

View File

@ -1,3 +1,7 @@
2019-10-02 Tom Tromey <tromey@adacore.com>
* gdb.ada/catch_ex_std.exp: Add $_ada_exception test.
2019-10-02 Pedro Alves <palves@redhat.com>
Andrew Burgess <andrew.burgess@embecosm.com>

View File

@ -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"