[2/2] more OO, Ada exception catchpoints: user specified conditions
Pedro Alves
pedro@codesourcery.com
Wed Jun 22 13:24:00 GMT 2011
Started out as wanting to eliminate ada_exception_catchpoint_p...
This switches Ada catchpoints to the OO scheme similar to how other
catchpoints have been converted in my previous series. This removes
most of the knowledge about Ada catchpoints out of breakpoint.c.
Only one function (init_ada_exception_breakpoint) is left, and,
I think it could be eliminated by factoring out create_breakpoint_sal
into a init_breakpoint_sal, and using that instead. I've left that
for some other day.
This stops the abuse of the regular breakpoint's condition to filter
out unwanted caught exceptions, removing the limitation that Ada
catchpoints can't have user specified conditions. To do that,
I've added a mechanism to be able to instantiate locations of
a breakpoint_ops specific "subclass" of bp_location
(the new breakpoint_ops->allocate_location method).
I've called the Ada catchpoints specific location type
struct ada_catchpoint_location. allocate_bp_location already
took the owner breakpoint as argument, but since bp_location
allocation now goes through breakpoint_ops, init_raw_breakpoint
and friends were changed to pass down the breakpoint_ops pointer,
in order to make sure that when allocate_bp_location is called, the
owner breakpoint's ->ops field already points where it should.
It's in this ada_catchpoint_location (an extended bp_location)
objects that the special internal specific-exception
condition expression are now stored. Since we need to release the
expressions when the location is itself released, I've added
a "vtable" mechanism to bp_location (bp_location_ops),
that currently only has a "dtor" (destructor) function pointer.
All this conversion required a yet couple more few more
breakpoint_ops methods `re_set' and `check_status', designed
while keeping in mind how would other breakpoint types not
currently using breakpoint_ops today use them.
Pedro Alves
2011-06-22 Pedro Alves <pedro@codesourcery.com>
gdb/
* breakpoint.c (bpstat_stop_status): Call the check_status
breakpoint_ops method.
(print_one_breakpoint_location): Also print the condition for Ada
exception catchpoints.
(allocate_bp_location): New, factored out from
allocate_bp_location.
(allocate_bp_location): Adjust. Call the owner breakpoint's
allocate_location method, if there is one.
(free_bp_location): Call the locations's dtor method, if there is
one.
(init_raw_breakpoint_without_location): New breakpoint_ops
parameter. Use it.
(set_raw_breakpoint_without_location): Adjust.
(init_raw_breakpoint): New breakpoint_ops parameter. Pass it down.
(set_raw_breakpoint): Adjust.
(catch_fork_breakpoint_ops, catch_vfork_breakpoint_ops)
(catch_syscall_breakpoint_ops): Install NULL allocate_location,
re_set and check_status methods.
(init_catchpoint): Don't memset, initialize thread, addr_string
and enable_state. Pass the ops down to init_raw_breakpoint.
(install_catchpoint): Rename to ...
(install_breakpoint): ... this, and make extern.
(create_fork_vfork_event_catchpoint): Adjust.
(catch_exec_breakpoint_ops): Install NULL allocate_location,
re_set and check_status methods.
(create_syscall_event_catchpoint): Adjust.
(ranged_breakpoint_ops, watchpoint_breakpoint_ops)
(masked_watchpoint_breakpoint_ops): Install NULL
allocate_location, re_set and check_status methods.
(catch_exec_command_1): Adjust.
(gnu_v3_exception_catchpoint_ops): Install NULL allocate_location,
re_set and check_status methods.
(create_ada_exception_breakpoint): Rename to ...
(init_ada_exception_breakpoint): ... this. Add a struct
breakpoint parameter, and delete the exp_string, cond_string and
cond parameters. Use init_raw_breakpoint, and don't install or
mention the breakpoint yet. Don't clear breakpoint fields that
init_raw_breakpoint already clears.
(re_set_breakpoint): Delete, split into ...
(breakpoint_re_set_default, prepare_re_set_context): ... these new
functions.
(breakpoint_re_set_one): Call the breakpoint's
breakpoint_ops->re_set implementation, if there's one. Adjust.
* breakpoint.h: Forward declare struct bpstats and struct bp_location.
(struct bp_location_ops): New type.
(struct bp_location): New field `ops'.
(struct breakpoint_ops): New `allocate_location', `re_set' and
`check_status' fields. Make `breakpoint_hit''s description match
reality.
(init_bp_location): Declare.
(breakpoint_re_set_default): Declare.
(create_ada_exception_breakpoint): Rename to ...
(init_ada_exception_breakpoint): ... this. Add a struct
breakpoint parameter, and delete the exp_string, cond_string and
cond parameters.
(install_breakpoint): Declare.
* ada-lang.c: Include exceptions.h.
<Ada exceptions description>: Update.
(struct ada_catchpoint_location): New type.
(ada_catchpoint_location_dtor): New function.
(ada_catchpoint_location_ops): New global.
(ada_catchpoint): New type.
(create_excep_cond_exprs): New function.
(dtor_exception, allocate_location_exception, re_set_exception)
(should_stop_exception, check_status_exception): New functions.
(print_one_exception, print_mention_exception)
(print_recreate_exception): Adjust.
(dtor_catch_exception, allocate_location_catch_exception)
(re_set_catch_exception, check_status_catch_exception): New
functions.
(catch_exception_breakpoint_ops): Install them.
(dtor_catch_exception_unhandled)
(allocate_location_catch_exception_unhandled)
(re_set_catch_exception_unhandled)
(check_status_catch_exception_unhandled): New functions.
(catch_exception_unhandled_breakpoint_ops): Install them.
(dtor_catch_assert, allocate_location_catch_assert)
(re_set_catch_assert, check_status_catch_assert): New functions.
(catch_assert_breakpoint_ops): Install them.
(ada_exception_catchpoint_p): Delete.
(catch_ada_exception_command_split)
(ada_exception_catchpoint_cond_string): Rename exp_string
parameter to excep_string. Adjust.
(ada_parse_catchpoint_condition): Delete.
(ada_exception_sal): Rename the exp_string parameter to
excep_string. Delete the cond_string and cond parameters.
Adjust.
(ada_decode_exception_location): Rename the exp_string parameter
to excep_string. Delete the cond_string and cond parameters.
Adjust.
(create_ada_exception_catchpoint): New function.
(catch_ada_exception_command, ada_decode_assert_location)
(catch_assert_command): Adjust.
* ada-lang.h (ada_exception_catchpoint_p): Delete declaration.
---
gdb/ada-lang.c | 461 ++++++++++++++++++++++++++++++++++++++++++-------------
gdb/ada-lang.h | 2
gdb/breakpoint.c | 184 +++++++++++++--------
gdb/breakpoint.h | 70 ++++++--
4 files changed, 525 insertions(+), 192 deletions(-)
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c 2011-06-22 11:07:06.000000000 +0100
+++ src/gdb/breakpoint.c 2011-06-22 13:08:16.485117028 +0100
@@ -4313,6 +4313,13 @@ bpstat_stop_status (struct address_space
b = bs->breakpoint_at;
+ if (b->ops != NULL && b->ops->check_status != NULL)
+ {
+ b->ops->check_status (bs);
+ if (!bs->stop)
+ continue;
+ }
+
if (b->type == bp_thread_event || b->type == bp_overlay_event
|| b->type == bp_longjmp_master
|| b->type == bp_std_terminate_master
@@ -5009,11 +5016,8 @@ print_one_breakpoint_location (struct br
ui_out_text (uiout, "\n");
}
- if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b))
+ if (!part_of_multiple && b->cond_string)
{
- /* We do not print the condition for Ada exception catchpoints
- because the condition is an internal implementation detail
- that we do not want to expose to the user. */
annotate_field (7);
if (is_tracepoint (b))
ui_out_text (uiout, "\ttrace only if ");
@@ -5685,22 +5689,19 @@ adjust_breakpoint_address (struct gdbarc
}
}
-/* Allocate a struct bp_location. */
-
-static struct bp_location *
-allocate_bp_location (struct breakpoint *bpt)
+void
+init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops,
+ struct breakpoint *owner)
{
- struct bp_location *loc;
-
- loc = xmalloc (sizeof (struct bp_location));
memset (loc, 0, sizeof (*loc));
- loc->owner = bpt;
+ loc->ops = ops;
+ loc->owner = owner;
loc->cond = NULL;
loc->shlib_disabled = 0;
loc->enabled = 1;
- switch (bpt->type)
+ switch (owner->type)
{
case bp_breakpoint:
case bp_until:
@@ -5745,12 +5746,29 @@ allocate_bp_location (struct breakpoint
}
loc->refc = 1;
+}
+
+/* Allocate a struct bp_location. */
+
+static struct bp_location *
+allocate_bp_location (struct breakpoint *bpt)
+{
+ struct bp_location *loc;
+
+ if (bpt->ops && bpt->ops->allocate_location)
+ return bpt->ops->allocate_location (bpt);
+
+ loc = xmalloc (sizeof (struct bp_location));
+ init_bp_location (loc, NULL, bpt);
return loc;
}
static void
free_bp_location (struct bp_location *loc)
{
+ if (loc->ops && loc->ops->dtor)
+ loc->ops->dtor (loc);
+
if (loc->cond)
xfree (loc->cond);
@@ -5807,10 +5825,12 @@ add_to_breakpoint_chain (struct breakpoi
static void
init_raw_breakpoint_without_location (struct breakpoint *b,
struct gdbarch *gdbarch,
- enum bptype bptype)
+ enum bptype bptype,
+ struct breakpoint_ops *ops)
{
memset (b, 0, sizeof (*b));
+ b->ops = ops;
b->type = bptype;
b->gdbarch = gdbarch;
b->language = current_language->la_language;
@@ -5822,7 +5842,6 @@ init_raw_breakpoint_without_location (st
b->ignore_count = 0;
b->commands = NULL;
b->frame_id = null_frame_id;
- b->ops = NULL;
b->condition_not_parsed = 0;
b->py_bp_object = NULL;
b->related_breakpoint = b;
@@ -5839,7 +5858,7 @@ set_raw_breakpoint_without_location (str
{
struct breakpoint *b = XNEW (struct breakpoint);
- init_raw_breakpoint_without_location (b, gdbarch, bptype);
+ init_raw_breakpoint_without_location (b, gdbarch, bptype, NULL);
add_to_breakpoint_chain (b);
return b;
}
@@ -5911,12 +5930,13 @@ get_sal_arch (struct symtab_and_line sal
static void
init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch,
- struct symtab_and_line sal, enum bptype bptype)
+ struct symtab_and_line sal, enum bptype bptype,
+ struct breakpoint_ops *ops)
{
CORE_ADDR adjusted_address;
struct gdbarch *loc_gdbarch;
- init_raw_breakpoint_without_location (b, gdbarch, bptype);
+ init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
loc_gdbarch = get_sal_arch (sal);
if (!loc_gdbarch)
@@ -5978,7 +5998,7 @@ set_raw_breakpoint (struct gdbarch *gdba
{
struct breakpoint *b = XNEW (struct breakpoint);
- init_raw_breakpoint (b, gdbarch, sal, bptype);
+ init_raw_breakpoint (b, gdbarch, sal, bptype, NULL);
add_to_breakpoint_chain (b);
return b;
}
@@ -6381,9 +6401,12 @@ print_recreate_catch_fork (struct breakp
static struct breakpoint_ops catch_fork_breakpoint_ops =
{
NULL, /* dtor */
+ NULL, /* allocate_location */
+ NULL, /* re_set */
insert_catch_fork,
remove_catch_fork,
breakpoint_hit_catch_fork,
+ NULL, /* check_status */
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_fork,
@@ -6486,9 +6509,12 @@ print_recreate_catch_vfork (struct break
static struct breakpoint_ops catch_vfork_breakpoint_ops =
{
NULL, /* dtor */
+ NULL, /* allocate_location */
+ NULL, /* re_set */
insert_catch_vfork,
remove_catch_vfork,
breakpoint_hit_catch_vfork,
+ NULL, /* check_status */
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_vfork,
@@ -6812,9 +6838,12 @@ print_recreate_catch_syscall (struct bre
static struct breakpoint_ops catch_syscall_breakpoint_ops =
{
dtor_catch_syscall,
+ NULL, /* allocate_location */
+ NULL, /* re_set */
insert_catch_syscall,
remove_catch_syscall,
breakpoint_hit_catch_syscall,
+ NULL, /* check_status */
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_syscall,
@@ -6845,26 +6874,17 @@ init_catchpoint (struct breakpoint *b,
{
struct symtab_and_line sal;
- memset (b, 0, sizeof (*b));
-
init_sal (&sal);
sal.pspace = current_program_space;
- init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint);
+ init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
b->cond_string = (cond_string == NULL) ? NULL : xstrdup (cond_string);
- b->thread = -1;
- b->addr_string = NULL;
- b->enable_state = bp_enabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
- b->ops = ops;
}
-/* Add breakpoint B on the breakpoint list, and notify the user, the
- target and breakpoint_created observers of its existence. */
-
-static void
-install_catchpoint (struct breakpoint *b)
+void
+install_breakpoint (struct breakpoint *b)
{
add_to_breakpoint_chain (b);
set_breakpoint_count (breakpoint_count + 1);
@@ -6885,7 +6905,7 @@ create_fork_vfork_event_catchpoint (stru
c->forked_inferior_pid = null_ptid;
- install_catchpoint (&c->base);
+ install_breakpoint (&c->base);
}
/* Exec catchpoints. */
@@ -6996,9 +7016,12 @@ print_recreate_catch_exec (struct breakp
static struct breakpoint_ops catch_exec_breakpoint_ops =
{
dtor_catch_exec,
+ NULL, /* allocate_location */
+ NULL, /* re_set */
insert_catch_exec,
remove_catch_exec,
breakpoint_hit_catch_exec,
+ NULL, /* check_status */
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_exec,
@@ -7019,7 +7042,7 @@ create_syscall_event_catchpoint (int tem
init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops);
c->syscalls_to_be_caught = filter;
- install_catchpoint (&c->base);
+ install_breakpoint (&c->base);
}
static int
@@ -8621,9 +8644,12 @@ print_recreate_ranged_breakpoint (struct
static struct breakpoint_ops ranged_breakpoint_ops =
{
NULL, /* dtor */
+ NULL, /* allocate_location */
+ NULL, /* re_set */
NULL, /* insert */
NULL, /* remove */
breakpoint_hit_ranged_breakpoint,
+ NULL, /* check_status */
resources_needed_ranged_breakpoint,
NULL, /* works_in_software_mode */
print_it_ranged_breakpoint,
@@ -8947,9 +8973,12 @@ works_in_software_mode_watchpoint (const
static struct breakpoint_ops watchpoint_breakpoint_ops =
{
NULL, /* dtor */
+ NULL, /* allocate_location */
+ NULL, /* re_set */
insert_watchpoint,
remove_watchpoint,
NULL, /* breakpoint_hit */
+ NULL, /* check_status */
resources_needed_watchpoint,
works_in_software_mode_watchpoint,
NULL, /* print_it */
@@ -9126,9 +9155,12 @@ print_recreate_masked_watchpoint (struct
static struct breakpoint_ops masked_watchpoint_breakpoint_ops =
{
NULL, /* dtor */
+ NULL, /* allocate_location */
+ NULL, /* re_set */
insert_masked_watchpoint,
remove_masked_watchpoint,
NULL, /* breakpoint_hit */
+ NULL, /* check_status */
resources_needed_masked_watchpoint,
works_in_software_mode_masked_watchpoint,
print_it_masked_watchpoint,
@@ -9850,7 +9882,7 @@ catch_exec_command_1 (char *arg, int fro
&catch_exec_breakpoint_ops);
c->exec_pathname = NULL;
- install_catchpoint (&c->base);
+ install_breakpoint (&c->base);
}
static enum print_stop_action
@@ -9942,9 +9974,12 @@ print_recreate_exception_catchpoint (str
static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
NULL, /* dtor */
+ NULL, /* allocate_location */
+ NULL, /* re_set */
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
+ NULL, /* check_status */
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_exception_catchpoint,
@@ -10026,18 +10061,14 @@ catch_throw_command (char *arg, int from
}
void
-create_ada_exception_breakpoint (struct gdbarch *gdbarch,
- struct symtab_and_line sal,
- char *addr_string,
- char *exp_string,
- char *cond_string,
- struct expression *cond,
- struct breakpoint_ops *ops,
- int tempflag,
- int from_tty)
+init_ada_exception_breakpoint (struct breakpoint *b,
+ struct gdbarch *gdbarch,
+ struct symtab_and_line sal,
+ char *addr_string,
+ struct breakpoint_ops *ops,
+ int tempflag,
+ int from_tty)
{
- struct breakpoint *b;
-
if (from_tty)
{
struct gdbarch *loc_gdbarch = get_sal_arch (sal);
@@ -10056,24 +10087,12 @@ create_ada_exception_breakpoint (struct
enough for now, though. */
}
- b = set_raw_breakpoint (gdbarch, sal, bp_breakpoint);
- set_breakpoint_count (breakpoint_count + 1);
+ init_raw_breakpoint (b, gdbarch, sal, bp_breakpoint, ops);
b->enable_state = bp_enabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
- b->number = breakpoint_count;
- b->ignore_count = 0;
- b->loc->cond = cond;
b->addr_string = addr_string;
b->language = language_ada;
- b->cond_string = cond_string;
- b->exp_string = exp_string;
- b->thread = -1;
- b->ops = ops;
-
- mention (b);
- observer_notify_breakpoint_created (b);
- update_global_location_list (1);
}
/* Cleanup function for a syscall filter list. */
@@ -11407,23 +11426,13 @@ addr_string_to_sals (struct breakpoint *
return sals;
}
-/* Reevaluate a hardware or software breakpoint and recreate its locations.
- This is necessary after symbols are read (e.g., an executable or DSO
- was loaded, or the inferior just started). */
-
-static void
-re_set_breakpoint (struct breakpoint *b)
+void
+breakpoint_re_set_default (struct breakpoint *b)
{
int found;
struct symtabs_and_lines sals, sals_end;
struct symtabs_and_lines expanded = {0};
struct symtabs_and_lines expanded_end = {0};
- struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
-
- input_radix = b->input_radix;
- save_current_space_and_thread ();
- switch_to_program_space_and_thread (b->pspace);
- set_language (b->language);
sals = addr_string_to_sals (b, b->addr_string, &found);
if (found)
@@ -11443,7 +11452,21 @@ re_set_breakpoint (struct breakpoint *b)
}
update_breakpoint_locations (b, expanded, expanded_end);
- do_cleanups (cleanups);
+}
+
+/* Prepare the global context for a re-set of breakpoint B. */
+
+static struct cleanup *
+prepare_re_set_context (struct breakpoint *b)
+{
+ struct cleanup *cleanups;
+
+ input_radix = b->input_radix;
+ cleanups = save_current_space_and_thread ();
+ switch_to_program_space_and_thread (b->pspace);
+ set_language (b->language);
+
+ return cleanups;
}
/* Reset a breakpoint given it's struct breakpoint * BINT.
@@ -11456,6 +11479,17 @@ breakpoint_re_set_one (void *bint)
/* Get past catch_errs. */
struct breakpoint *b = (struct breakpoint *) bint;
+ if (b->ops != NULL && b->ops->re_set != NULL)
+ {
+ struct cleanup *cleanups;
+
+ cleanups = prepare_re_set_context (b);
+ b->ops->re_set (b);
+ do_cleanups (cleanups);
+
+ return 0;
+ }
+
switch (b->type)
{
case bp_none:
@@ -11479,7 +11513,13 @@ breakpoint_re_set_one (void *bint)
return 0;
}
- re_set_breakpoint (b);
+ {
+ struct cleanup *cleanups;
+
+ cleanups = prepare_re_set_context (b);
+ breakpoint_re_set_default (b);
+ do_cleanups (cleanups);
+ }
break;
case bp_watchpoint:
Index: src/gdb/breakpoint.h
===================================================================
--- src.orig/gdb/breakpoint.h 2011-06-22 11:07:06.000000000 +0100
+++ src/gdb/breakpoint.h 2011-06-22 13:08:18.265117028 +0100
@@ -30,6 +30,8 @@ struct block;
struct breakpoint_object;
struct get_number_or_range_state;
struct thread_info;
+struct bpstats;
+struct bp_location;
/* This is the maximum number of bytes a breakpoint instruction can
take. Feel free to increase it. It's just used in a few places to
@@ -278,12 +280,26 @@ enum bp_loc_type
bp_loc_other /* Miscellaneous... */
};
+/* This structure is a collection of function pointers that, if
+ available, will be called instead of performing the default action
+ for this bp_loc_type. */
+
+struct bp_location_ops
+{
+ /* Destructor. Releases everything from SELF (but not SELF
+ itself). */
+ void (*dtor) (struct bp_location *self);
+};
+
struct bp_location
{
/* Chain pointer to the next breakpoint location for
the same parent breakpoint. */
struct bp_location *next;
+ /* Methods associated with this location. */
+ const struct bp_location_ops *ops;
+
/* The reference count. */
int refc;
@@ -397,6 +413,14 @@ struct breakpoint_ops
itself). */
void (*dtor) (struct breakpoint *self);
+ /* Allocate a location for this breakpoint. */
+ struct bp_location * (*allocate_location) (struct breakpoint *);
+
+ /* Reevaluate a breakpoint. This is necessary after symbols change
+ (e.g., an executable or DSO was loaded, or the inferior just
+ started). */
+ void (*re_set) (struct breakpoint *self);
+
/* Insert the breakpoint or watchpoint or activate the catchpoint.
Return 0 for success, 1 if the breakpoint, watchpoint or catchpoint
type is not supported, -1 for failure. */
@@ -408,11 +432,16 @@ struct breakpoint_ops
-1 for failure. */
int (*remove_location) (struct bp_location *);
- /* Return non-zero if the debugger should tell the user that this
- breakpoint was hit. */
- int (*breakpoint_hit) (const struct bp_location *, struct address_space *,
+ /* Return true if it the target has stopped due to hitting
+ breakpoint location BL. This function does not check if we
+ should stop, only if BL explains the stop. */
+ int (*breakpoint_hit) (const struct bp_location *bl, struct address_space *,
CORE_ADDR);
+ /* Check internal conditions of the breakpoint referred to by BS.
+ If we should not stop for this breakpoint, set BS->stop to 0. */
+ void (*check_status) (struct bpstats *bs);
+
/* Tell how many hardware resources (debug registers) are needed
for this breakpoint. If this function is not provided, then
the breakpoint or watchpoint needs one debug register. */
@@ -937,6 +966,12 @@ extern int breakpoint_thread_match (stru
extern void until_break_command (char *, int, int);
+/* Initialize a struct bp_location. */
+
+extern void init_bp_location (struct bp_location *loc,
+ const struct bp_location_ops *ops,
+ struct breakpoint *owner);
+
extern void update_breakpoint_locations (struct breakpoint *b,
struct symtabs_and_lines sals,
struct symtabs_and_lines sals_end);
@@ -945,6 +980,12 @@ extern void breakpoint_re_set (void);
extern void breakpoint_re_set_thread (struct breakpoint *);
+/* The default re_set method, for typical hardware or software
+ breakpoints. Reevaluate the breakpoint and recreate its
+ locations. */
+
+extern void breakpoint_re_set_default (struct breakpoint *);
+
extern struct breakpoint *set_momentary_breakpoint
(struct gdbarch *, struct symtab_and_line, struct frame_id, enum bptype);
@@ -1001,18 +1042,21 @@ extern void
void *user_data_catch,
void *user_data_tcatch);
-/* Create a breakpoint struct for Ada exception catchpoints. */
+/* Initialize a breakpoint struct for Ada exception catchpoints. */
extern void
- create_ada_exception_breakpoint (struct gdbarch *gdbarch,
- struct symtab_and_line sal,
- char *addr_string,
- char *exp_string,
- char *cond_string,
- struct expression *cond,
- struct breakpoint_ops *ops,
- int tempflag,
- int from_tty);
+ init_ada_exception_breakpoint (struct breakpoint *b,
+ struct gdbarch *gdbarch,
+ struct symtab_and_line sal,
+ char *addr_string,
+ struct breakpoint_ops *ops,
+ int tempflag,
+ int from_tty);
+
+/* Add breakpoint B on the breakpoint list, and notify the user, the
+ target and breakpoint_created observers of its existence. */
+
+extern void install_breakpoint (struct breakpoint *b);
extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
char *cond_string, int thread,
Index: src/gdb/ada-lang.c
===================================================================
--- src.orig/gdb/ada-lang.c 2011-06-22 11:07:06.000000000 +0100
+++ src/gdb/ada-lang.c 2011-06-22 11:13:33.595119404 +0100
@@ -62,6 +62,7 @@
#include "value.h"
#include "mi/mi-common.h"
#include "arch-utils.h"
+#include "exceptions.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
@@ -10395,19 +10396,7 @@ ada_modulus (struct type *type)
a few times already, and these changes affect the implementation
of these catchpoints. In order to be able to support several
variants of the runtime, we use a sniffer that will determine
- the runtime variant used by the program being debugged.
-
- At this time, we do not support the use of conditions on Ada exception
- catchpoints. The COND and COND_STRING fields are therefore set
- to NULL (most of the time, see below).
-
- Conditions where EXP_STRING, COND, and COND_STRING are used:
-
- When a user specifies the name of a specific exception in the case
- of catchpoints on Ada exceptions, we store the name of that exception
- in the EXP_STRING. We then translate this request into an actual
- condition stored in COND_STRING, and then parse it into an expression
- stored in COND. */
+ the runtime variant used by the program being debugged. */
/* The different types of catchpoints that we introduced for catching
Ada exceptions. */
@@ -10744,6 +10733,216 @@ ada_exception_name_addr (enum exception_
return result;
}
+static struct symtab_and_line ada_exception_sal (enum exception_catchpoint_kind,
+ char *, char **,
+ struct breakpoint_ops **);
+static char *ada_exception_catchpoint_cond_string (const char *excep_string);
+
+/* Ada catchpoints.
+
+ In the case of catchpoints on Ada exceptions, the catchpoint will
+ stop the target on every exception the program throws. When a user
+ specifies the name of a specific exception, we translate this
+ request into a condition expression (in text form), and then parse
+ it into an expression stored in each of the catchpoint's locations.
+ We then use this condition to check whether the exception that was
+ raised is the one the user is interested in. If not, then the
+ target is resumed again. We store the name of the requested
+ exception, in order to be able to re-set the condition expression
+ when symbols change. */
+
+/* An instance of this type is used to represent an Ada catchpoint
+ breakpoint location. It includes a "struct bp_location" as a kind
+ of base class; users downcast to "struct bp_location *" when
+ needed. */
+
+struct ada_catchpoint_location
+{
+ /* The base class. */
+ struct bp_location base;
+
+ /* The condition that checks whether the exception that was raised
+ is the specific exception the user specified on catchpoint
+ creation. */
+ struct expression *excep_cond_expr;
+};
+
+/* Implement the DTOR method in the bp_location_ops structure for all
+ Ada exception catchpoint kinds. */
+
+static void
+ada_catchpoint_location_dtor (struct bp_location *bl)
+{
+ struct ada_catchpoint_location *al = (struct ada_catchpoint_location *) bl;
+
+ xfree (al->excep_cond_expr);
+}
+
+/* The vtable to be used in Ada catchpoint locations. */
+
+static const struct bp_location_ops ada_catchpoint_location_ops =
+{
+ ada_catchpoint_location_dtor
+};
+
+/* An instance of this type is used to represent an Ada catchpoint.
+ It includes a "struct breakpoint" as a kind of base class; users
+ downcast to "struct breakpoint *" when needed. */
+
+struct ada_catchpoint
+{
+ /* The base class. */
+ struct breakpoint base;
+
+ /* The name of the specific exception the user specified. */
+ char *excep_string;
+};
+
+/* Parse the exception condition string in the context of each of the
+ catchpoint's locations, and store them for later evaluation. */
+
+static void
+create_excep_cond_exprs (struct ada_catchpoint *c)
+{
+ struct cleanup *old_chain;
+ struct bp_location *bl;
+ char *cond_string;
+
+ /* Nothing to do if there's no specific exception to catch. */
+ if (c->excep_string == NULL)
+ return;
+
+ /* Same if there are no locations... */
+ if (c->base.loc == NULL)
+ return;
+
+ /* Compute the condition expression in text form, from the specific
+ expection we want to catch. */
+ cond_string = ada_exception_catchpoint_cond_string (c->excep_string);
+ old_chain = make_cleanup (xfree, cond_string);
+
+ /* Iterate over all the catchpoint's locations, and parse an
+ expression for each. The position of the each expression in the
+ VEC corresponds to the same position of the corresponding
+ location in the location list. That is, e.g., the first entry in
+ the VEC corresponds to the first location; the second entry in
+ the VEC corresponds to the second location, and so on. */
+ for (bl = c->base.loc; bl != NULL; bl = bl->next)
+ {
+ struct ada_catchpoint_location *ada_loc
+ = (struct ada_catchpoint_location *) bl;
+ struct expression *exp = NULL;
+
+ if (!bl->shlib_disabled)
+ {
+ volatile struct gdb_exception e;
+ char *s;
+
+ s = cond_string;
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ exp = parse_exp_1 (&s, block_for_pc (bl->address), 0);
+ }
+ if (e.reason < 0)
+ warning (_("failed to reevaluate internal exception condition "
+ "for catchpoint %d: %s"),
+ c->base.number, e.message);
+ }
+
+ ada_loc->excep_cond_expr = exp;
+ }
+
+ do_cleanups (old_chain);
+}
+
+/* Implement the DTOR method in the breakpoint_ops structure for all
+ exception catchpoint kinds. */
+
+static void
+dtor_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+{
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
+
+ xfree (c->excep_string);
+}
+
+/* Implement the ALLOCATE_LOCATION method in the breakpoint_ops
+ structure for all exception catchpoint kinds. */
+
+static struct bp_location *
+allocate_location_exception (enum exception_catchpoint_kind ex,
+ struct breakpoint *self)
+{
+ struct ada_catchpoint_location *loc;
+
+ loc = XNEW (struct ada_catchpoint_location);
+ init_bp_location (&loc->base, &ada_catchpoint_location_ops, self);
+ loc->excep_cond_expr = NULL;
+ return &loc->base;
+}
+
+/* Implement the RE_SET method in the breakpoint_ops structure for all
+ exception catchpoint kinds. */
+
+static void
+re_set_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+{
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
+ struct bp_location *bl;
+
+ /* Call the base class's method. This updates the catchpoint's
+ locations. */
+ breakpoint_re_set_default (b);
+
+ /* Reparse the exception conditional expressions. One for each
+ location. */
+ create_excep_cond_exprs (c);
+}
+
+static int
+should_stop_exception (const struct bp_location *bl)
+{
+ struct ada_catchpoint *c = (struct ada_catchpoint *) bl->owner;
+ const struct ada_catchpoint_location *ada_loc
+ = (const struct ada_catchpoint_location *) bl;
+ volatile struct gdb_exception ex;
+ int stop;
+
+ /* With no specific exception, should always stop. */
+ if (c->excep_string == NULL)
+ return 1;
+
+ if (ada_loc->excep_cond_expr == NULL)
+ {
+ /* We will have a NULL expression if back when we were creating
+ the expressions, this location's had failed to parse. */
+ return 1;
+ }
+
+ stop = 1;
+ TRY_CATCH (ex, RETURN_MASK_ALL)
+ {
+ struct value *mark;
+
+ mark = value_mark ();
+ stop = value_true (evaluate_expression (ada_loc->excep_cond_expr));
+ value_free_to_mark (mark);
+ }
+ if (ex.reason < 0)
+ exception_fprintf (gdb_stderr, ex,
+ _("Error in testing exception condition:\n"));
+ return stop;
+}
+
+/* Implement the CHECK_STATUS method in the breakpoint_ops structure
+ for all exception catchpoint kinds. */
+
+static void
+check_status_exception (enum exception_catchpoint_kind ex, bpstat bs)
+{
+ bs->stop = should_stop_exception (bs->bp_location_at);
+}
+
/* Implement the PRINT_IT method in the breakpoint_ops structure
for all exception catchpoint kinds. */
@@ -10818,6 +11017,7 @@ static void
print_one_exception (enum exception_catchpoint_kind ex,
struct breakpoint *b, struct bp_location **last_loc)
{
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
struct value_print_options opts;
get_user_print_options (&opts);
@@ -10832,10 +11032,10 @@ print_one_exception (enum exception_catc
switch (ex)
{
case ex_catch_exception:
- if (b->exp_string != NULL)
+ if (c->excep_string != NULL)
{
- char *msg = xstrprintf (_("`%s' Ada exception"), b->exp_string);
-
+ char *msg = xstrprintf (_("`%s' Ada exception"), c->excep_string);
+
ui_out_field_string (uiout, "what", msg);
xfree (msg);
}
@@ -10865,12 +11065,14 @@ static void
print_mention_exception (enum exception_catchpoint_kind ex,
struct breakpoint *b)
{
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
+
switch (ex)
{
case ex_catch_exception:
- if (b->exp_string != NULL)
+ if (c->excep_string != NULL)
printf_filtered (_("Catchpoint %d: `%s' Ada exception"),
- b->number, b->exp_string);
+ b->number, c->excep_string);
else
printf_filtered (_("Catchpoint %d: all Ada exceptions"), b->number);
@@ -10898,12 +11100,14 @@ static void
print_recreate_exception (enum exception_catchpoint_kind ex,
struct breakpoint *b, struct ui_file *fp)
{
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
+
switch (ex)
{
case ex_catch_exception:
fprintf_filtered (fp, "catch exception");
- if (b->exp_string != NULL)
- fprintf_filtered (fp, " %s", b->exp_string);
+ if (c->excep_string != NULL)
+ fprintf_filtered (fp, " %s", c->excep_string);
break;
case ex_catch_exception_unhandled:
@@ -10921,6 +11125,30 @@ print_recreate_exception (enum exception
/* Virtual table for "catch exception" breakpoints. */
+static void
+dtor_catch_exception (struct breakpoint *b)
+{
+ dtor_exception (ex_catch_exception, b);
+}
+
+static struct bp_location *
+allocate_location_catch_exception (struct breakpoint *self)
+{
+ return allocate_location_exception (ex_catch_exception, self);
+}
+
+static void
+re_set_catch_exception (struct breakpoint *b)
+{
+ re_set_exception (ex_catch_exception, b);
+}
+
+static void
+check_status_catch_exception (bpstat bs)
+{
+ check_status_exception (ex_catch_exception, bs);
+}
+
static enum print_stop_action
print_it_catch_exception (struct breakpoint *b)
{
@@ -10947,10 +11175,13 @@ print_recreate_catch_exception (struct b
static struct breakpoint_ops catch_exception_breakpoint_ops =
{
- NULL, /* dtor */
+ dtor_catch_exception,
+ allocate_location_catch_exception,
+ re_set_catch_exception,
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
+ check_status_catch_exception,
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_exception,
@@ -10962,6 +11193,30 @@ static struct breakpoint_ops catch_excep
/* Virtual table for "catch exception unhandled" breakpoints. */
+static void
+dtor_catch_exception_unhandled (struct breakpoint *b)
+{
+ dtor_exception (ex_catch_exception_unhandled, b);
+}
+
+static struct bp_location *
+allocate_location_catch_exception_unhandled (struct breakpoint *self)
+{
+ return allocate_location_exception (ex_catch_exception_unhandled, self);
+}
+
+static void
+re_set_catch_exception_unhandled (struct breakpoint *b)
+{
+ re_set_exception (ex_catch_exception_unhandled, b);
+}
+
+static void
+check_status_catch_exception_unhandled (bpstat bs)
+{
+ check_status_exception (ex_catch_exception_unhandled, bs);
+}
+
static enum print_stop_action
print_it_catch_exception_unhandled (struct breakpoint *b)
{
@@ -10989,10 +11244,13 @@ print_recreate_catch_exception_unhandled
}
static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = {
- NULL, /* dtor */
+ dtor_catch_exception_unhandled,
+ allocate_location_catch_exception_unhandled,
+ re_set_catch_exception_unhandled,
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
+ check_status_catch_exception_unhandled,
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_exception_unhandled,
@@ -11004,6 +11262,30 @@ static struct breakpoint_ops catch_excep
/* Virtual table for "catch assert" breakpoints. */
+static void
+dtor_catch_assert (struct breakpoint *b)
+{
+ dtor_exception (ex_catch_assert, b);
+}
+
+static struct bp_location *
+allocate_location_catch_assert (struct breakpoint *self)
+{
+ return allocate_location_exception (ex_catch_assert, self);
+}
+
+static void
+re_set_catch_assert (struct breakpoint *b)
+{
+ return re_set_exception (ex_catch_assert, b);
+}
+
+static void
+check_status_catch_assert (bpstat bs)
+{
+ check_status_exception (ex_catch_assert, bs);
+}
+
static enum print_stop_action
print_it_catch_assert (struct breakpoint *b)
{
@@ -11029,10 +11311,13 @@ print_recreate_catch_assert (struct brea
}
static struct breakpoint_ops catch_assert_breakpoint_ops = {
- NULL, /* dtor */
+ dtor_catch_assert,
+ allocate_location_catch_assert,
+ re_set_catch_assert,
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
+ check_status_catch_assert,
NULL, /* resources_needed */
NULL, /* works_in_software_mode */
print_it_catch_assert,
@@ -11042,16 +11327,6 @@ static struct breakpoint_ops catch_asser
print_recreate_catch_assert
};
-/* Return non-zero if B is an Ada exception catchpoint. */
-
-int
-ada_exception_catchpoint_p (struct breakpoint *b)
-{
- return (b->ops == &catch_exception_breakpoint_ops
- || b->ops == &catch_exception_unhandled_breakpoint_ops
- || b->ops == &catch_assert_breakpoint_ops);
-}
-
/* Return a newly allocated copy of the first space-separated token
in ARGSP, and then adjust ARGSP to point immediately after that
token.
@@ -11094,13 +11369,13 @@ ada_get_next_arg (char **argsp)
/* Split the arguments specified in a "catch exception" command.
Set EX to the appropriate catchpoint type.
- Set EXP_STRING to the name of the specific exception if
+ Set EXCEP_STRING to the name of the specific exception if
specified by the user. */
static void
catch_ada_exception_command_split (char *args,
enum exception_catchpoint_kind *ex,
- char **exp_string)
+ char **excep_string)
{
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
char *exception_name;
@@ -11123,19 +11398,19 @@ catch_ada_exception_command_split (char
{
/* Catch all exceptions. */
*ex = ex_catch_exception;
- *exp_string = NULL;
+ *excep_string = NULL;
}
else if (strcmp (exception_name, "unhandled") == 0)
{
/* Catch unhandled exceptions. */
*ex = ex_catch_exception_unhandled;
- *exp_string = NULL;
+ *excep_string = NULL;
}
else
{
/* Catch a specific exception. */
*ex = ex_catch_exception;
- *exp_string = exception_name;
+ *excep_string = exception_name;
}
}
@@ -11196,13 +11471,13 @@ ada_exception_breakpoint_ops (enum excep
deallocated later. */
static char *
-ada_exception_catchpoint_cond_string (const char *exp_string)
+ada_exception_catchpoint_cond_string (const char *excep_string)
{
int i;
/* The standard exceptions are a special case. They are defined in
runtime units that have been compiled without debugging info; if
- EXP_STRING is the not-fully-qualified name of a standard
+ EXCEP_STRING is the not-fully-qualified name of a standard
exception (e.g. "constraint_error") then, during the evaluation
of the condition expression, the symbol lookup on this name would
*not* return this standard exception. The catchpoint condition
@@ -11221,44 +11496,28 @@ ada_exception_catchpoint_cond_string (co
for (i = 0; i < sizeof (standard_exc) / sizeof (char *); i++)
{
- if (strcmp (standard_exc [i], exp_string) == 0)
+ if (strcmp (standard_exc [i], excep_string) == 0)
{
return xstrprintf ("long_integer (e) = long_integer (&standard.%s)",
- exp_string);
+ excep_string);
}
}
- return xstrprintf ("long_integer (e) = long_integer (&%s)", exp_string);
-}
-
-/* Return the expression corresponding to COND_STRING evaluated at SAL. */
-
-static struct expression *
-ada_parse_catchpoint_condition (char *cond_string,
- struct symtab_and_line sal)
-{
- return (parse_exp_1 (&cond_string, block_for_pc (sal.pc), 0));
+ return xstrprintf ("long_integer (e) = long_integer (&%s)", excep_string);
}
/* Return the symtab_and_line that should be used to insert an exception
catchpoint of the TYPE kind.
- EX_STRING should contain the name of a specific exception
- that the catchpoint should catch, or NULL otherwise.
+ EXCEP_STRING should contain the name of a specific exception that
+ the catchpoint should catch, or NULL otherwise.
- The idea behind all the remaining parameters is that their names match
- the name of certain fields in the breakpoint structure that are used to
- handle exception catchpoints. This function returns the value to which
- these fields should be set, depending on the type of catchpoint we need
- to create.
-
- If COND and COND_STRING are both non-NULL, any value they might
- hold will be free'ed, and then replaced by newly allocated ones.
- These parameters are left untouched otherwise. */
+ ADDR_STRING returns the name of the function where the real
+ breakpoint that implements the catchpoints is set, depending on the
+ type of catchpoint we need to create. */
static struct symtab_and_line
-ada_exception_sal (enum exception_catchpoint_kind ex, char *exp_string,
- char **addr_string, char **cond_string,
- struct expression **cond, struct breakpoint_ops **ops)
+ada_exception_sal (enum exception_catchpoint_kind ex, char *excep_string,
+ char **addr_string, struct breakpoint_ops **ops)
{
const char *sym_name;
struct symbol *sym;
@@ -11304,27 +11563,6 @@ ada_exception_sal (enum exception_catchp
*addr_string = xstrdup (sym_name);
- /* Set the COND and COND_STRING (if not NULL). */
-
- if (cond_string != NULL && cond != NULL)
- {
- if (*cond_string != NULL)
- {
- xfree (*cond_string);
- *cond_string = NULL;
- }
- if (*cond != NULL)
- {
- xfree (*cond);
- *cond = NULL;
- }
- if (exp_string != NULL)
- {
- *cond_string = ada_exception_catchpoint_cond_string (exp_string);
- *cond = ada_parse_catchpoint_condition (*cond_string, sal);
- }
- }
-
/* Set OPS. */
*ops = ada_exception_breakpoint_ops (ex);
@@ -11333,7 +11571,6 @@ ada_exception_sal (enum exception_catchp
/* Parse the arguments (ARGS) of the "catch exception" command.
- Set TYPE to the appropriate exception catchpoint type.
If the user asked the catchpoint to catch only a specific
exception, then save the exception name in ADDR_STRING.
@@ -11342,15 +11579,34 @@ ada_exception_sal (enum exception_catchp
static struct symtab_and_line
ada_decode_exception_location (char *args, char **addr_string,
- char **exp_string, char **cond_string,
- struct expression **cond,
+ char **excep_string,
struct breakpoint_ops **ops)
{
enum exception_catchpoint_kind ex;
- catch_ada_exception_command_split (args, &ex, exp_string);
- return ada_exception_sal (ex, *exp_string, addr_string, cond_string,
- cond, ops);
+ catch_ada_exception_command_split (args, &ex, excep_string);
+ return ada_exception_sal (ex, *excep_string, addr_string, ops);
+}
+
+/* Create an Ada exception catchpoint. */
+
+static void
+create_ada_exception_catchpoint (struct gdbarch *gdbarch,
+ struct symtab_and_line sal,
+ char *addr_string,
+ char *excep_string,
+ struct breakpoint_ops *ops,
+ int tempflag,
+ int from_tty)
+{
+ struct ada_catchpoint *c;
+
+ c = XNEW (struct ada_catchpoint);
+ init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string,
+ ops, tempflag, from_tty);
+ c->excep_string = excep_string;
+ create_excep_cond_exprs (c);
+ install_breakpoint (&c->base);
}
/* Implement the "catch exception" command. */
@@ -11363,20 +11619,16 @@ catch_ada_exception_command (char *arg,
int tempflag;
struct symtab_and_line sal;
char *addr_string = NULL;
- char *exp_string = NULL;
- char *cond_string = NULL;
- struct expression *cond = NULL;
+ char *excep_string = NULL;
struct breakpoint_ops *ops = NULL;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
- &cond_string, &cond, &ops);
- create_ada_exception_breakpoint (gdbarch, sal, addr_string, exp_string,
- cond_string, cond, ops, tempflag,
- from_tty);
+ sal = ada_decode_exception_location (arg, &addr_string, &excep_string, &ops);
+ create_ada_exception_catchpoint (gdbarch, sal, addr_string,
+ excep_string, ops, tempflag, from_tty);
}
static struct symtab_and_line
@@ -11393,8 +11645,7 @@ ada_decode_assert_location (char *args,
error (_("Junk at end of arguments."));
}
- return ada_exception_sal (ex_catch_assert, NULL, addr_string, NULL, NULL,
- ops);
+ return ada_exception_sal (ex_catch_assert, NULL, addr_string, ops);
}
/* Implement the "catch assert" command. */
@@ -11414,8 +11665,8 @@ catch_assert_command (char *arg, int fro
if (!arg)
arg = "";
sal = ada_decode_assert_location (arg, &addr_string, &ops);
- create_ada_exception_breakpoint (gdbarch, sal, addr_string, NULL, NULL, NULL,
- ops, tempflag, from_tty);
+ create_ada_exception_catchpoint (gdbarch, sal, addr_string,
+ NULL, ops, tempflag, from_tty);
}
/* Operators */
/* Information about operators given special treatment in functions
Index: src/gdb/ada-lang.h
===================================================================
--- src.orig/gdb/ada-lang.h 2011-06-22 11:07:06.000000000 +0100
+++ src/gdb/ada-lang.h 2011-06-22 11:07:07.295119536 +0100
@@ -385,6 +385,4 @@ extern void iterate_over_live_ada_tasks
extern int ada_build_task_list (int warn_if_null);
-extern int ada_exception_catchpoint_p (struct breakpoint *b);
-
#endif
More information about the Gdb-patches
mailing list