From: Pedro Alves Date: Wed, 22 Jun 2011 17:53:44 +0000 (+0000) Subject: 2011-06-22 Pedro Alves X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=28010a5d424317a8334ea1851206d8fa8153e112;p=binutils-gdb.git 2011-06-22 Pedro Alves * 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. : 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c5224225de8..fb4c664797f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,100 @@ +2011-06-22 Pedro Alves + + * 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. + : 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 * ada-lang.c: Include arch-utils.h. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 05fd75d3859..a3234fba0f7 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -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,215 @@ ada_exception_name_addr (enum exception_catchpoint_kind ex, 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. */ @@ -10818,6 +11016,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 +11031,10 @@ print_one_exception (enum exception_catchpoint_kind ex, 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 +11064,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 +11099,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 +11124,30 @@ print_recreate_exception (enum exception_catchpoint_kind ex, /* 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 +11174,13 @@ print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp) 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 +11192,30 @@ static struct breakpoint_ops catch_exception_breakpoint_ops = /* 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 +11243,13 @@ print_recreate_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, @@ -11004,6 +11261,30 @@ static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = { /* 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 +11310,13 @@ print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp) } 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 +11326,6 @@ static struct breakpoint_ops catch_assert_breakpoint_ops = { 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 +11368,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 +11397,19 @@ catch_ada_exception_command_split (char *args, { /* 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 +11470,13 @@ ada_exception_breakpoint_ops (enum exception_catchpoint_kind ex) 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 +11495,28 @@ ada_exception_catchpoint_cond_string (const char *exp_string) 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 +11562,6 @@ ada_exception_sal (enum exception_catchpoint_kind ex, char *exp_string, *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 +11570,6 @@ ada_exception_sal (enum exception_catchpoint_kind ex, char *exp_string, /* 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 +11578,34 @@ ada_exception_sal (enum exception_catchpoint_kind ex, char *exp_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. */ @@ -11363,20 +11618,16 @@ catch_ada_exception_command (char *arg, int from_tty, 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 +11644,7 @@ ada_decode_assert_location (char *args, char **addr_string, 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 +11664,8 @@ catch_assert_command (char *arg, int from_tty, 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 diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h index e0366fcbcc2..c36305977d0 100644 --- a/gdb/ada-lang.h +++ b/gdb/ada-lang.h @@ -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 diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 714437e8c4b..935cd0338bb 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -4313,6 +4313,13 @@ bpstat_stop_status (struct address_space *aspace, 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 breakpoint *b, 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 gdbarch *gdbarch, } } -/* 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 *bpt) } 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 breakpoint *b) 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 (struct breakpoint *b, 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 (struct gdbarch *gdbarch, { 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 *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; } @@ -6381,9 +6401,12 @@ print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp) 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 breakpoint *b, struct ui_file *fp) 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 breakpoint *b, struct ui_file *fp) 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 (struct gdbarch *gdbarch, c->forked_inferior_pid = null_ptid; - install_catchpoint (&c->base); + install_breakpoint (&c->base); } /* Exec catchpoints. */ @@ -6991,9 +7011,12 @@ print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp) 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, @@ -7014,7 +7037,7 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter, init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops); c->syscalls_to_be_caught = filter; - install_catchpoint (&c->base); + install_breakpoint (&c->base); } static int @@ -8616,9 +8639,12 @@ print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp) 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, @@ -8942,9 +8968,12 @@ works_in_software_mode_watchpoint (const struct breakpoint *b) 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 */ @@ -9121,9 +9150,12 @@ print_recreate_masked_watchpoint (struct breakpoint *b, struct ui_file *fp) 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, @@ -9845,7 +9877,7 @@ catch_exec_command_1 (char *arg, int from_tty, &catch_exec_breakpoint_ops); c->exec_pathname = NULL; - install_catchpoint (&c->base); + install_breakpoint (&c->base); } static enum print_stop_action @@ -9937,9 +9969,12 @@ print_recreate_exception_catchpoint (struct breakpoint *b, 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, @@ -10021,18 +10056,14 @@ catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command) } 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); @@ -10051,24 +10082,12 @@ create_ada_exception_breakpoint (struct gdbarch *gdbarch, 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. */ @@ -11402,23 +11421,13 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) 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) @@ -11438,7 +11447,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. @@ -11451,6 +11474,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: @@ -11474,7 +11508,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: diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 9dbf23b6ad8..6fca4791c6e 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -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 (struct address_space *, 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,