+2011-06-22 Pedro Alves <pedro@codesourcery.com>
+
+ * 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.
+
2011-06-22 Pedro Alves <pedro@codesourcery.com>
* ada-lang.c: Include arch-utils.h.
#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).
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. */
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. */
+ 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;
+
+ /* 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);
+}
+
+/* Returns true if we should stop for this breakpoint hit. If the
+ user specified a specific exception, we only want to cause a stop
+ if the program thrown that exception. */
+
+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. */
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);
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);
}
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);
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:
/* 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)
{
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,
/* 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)
{
}
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,
/* 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)
{
}
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,
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.
/* 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;
{
/* 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;
}
}
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
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;
*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);
/* 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.
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. */
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
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. */
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
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
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 ");
}
}
-/* 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:
}
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);
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;
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;
{
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;
}
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)
{
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;
}
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,
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,
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,
{
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);
c->forked_inferior_pid = null_ptid;
- install_catchpoint (&c->base);
+ install_breakpoint (&c->base);
}
/* Exec catchpoints. */
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,
init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops);
c->syscalls_to_be_caught = filter;
- install_catchpoint (&c->base);
+ install_breakpoint (&c->base);
}
static int
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,
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 */
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,
&catch_exec_breakpoint_ops);
c->exec_pathname = NULL;
- install_catchpoint (&c->base);
+ install_breakpoint (&c->base);
}
static enum print_stop_action
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,
}
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);
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. */
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)
}
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.
/* 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:
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:
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
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;
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. */
-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. */
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);
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);
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,