diff options
-rw-r--r-- | gdb/ChangeLog | 135 | ||||
-rw-r--r-- | gdb/ada-lang.c | 56 | ||||
-rw-r--r-- | gdb/breakpoint.c | 1757 | ||||
-rw-r--r-- | gdb/breakpoint.h | 48 | ||||
-rw-r--r-- | gdb/mi/mi-cmd-break.c | 2 | ||||
-rw-r--r-- | gdb/python/py-breakpoint.c | 3 |
6 files changed, 1175 insertions, 826 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 32c9a4d..ec1d3b3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,138 @@ +2011-07-25 Pedro Alves <pedro@codesourcery.com> + + Implement most breakpoint_ops methods for all breakpoint types, + and move the default handlings to the proper callbacks. + + * breakpoint.c (update_watchpoint): Always call the breakpoint's + works_in_software_mode method. + (insert_bp_location): Go through breakpoint_ops->insert_location + for software and hardware watchpoints. + (create_internal_breakpoint): Pass bkpt_breakpoint_ops as + breakpoint_ops. + (remove_breakpoint_1): Go through breakpoint_ops->remove_location + for software and hardware watchpoints. + (print_it_typical): Delete. + (print_bp_stop_message): Always call the breakpoint_ops->print_it + method. + (watchpoint_check): Adjust comment. + (bpstat_check_location): Simply always call the breakpoint's + breakpoint_hit method. + (bpstat_stop_status): Always call the breakpoint's check_status + method. Remove special cases for watchpoints and internal event + breakpoints from here (moved to the check_status implementations). + (print_one_breakpoint_location): Assume b->ops is never NULL. + Remove static tracepoint marker id printing from here (moved to + the print_one_detail callback implementation of tracepoints). + (init_bp_location): Assert OPS is never NULL. + (allocate_bp_location): Always call the breakpoint's + allocate_location method, and remove the default code from here. + (free_bp_location): Always call the location's dtor method, and + remove the default code from here. + (init_raw_breakpoint_without_location): Assert OPS is never NULL. + (set_raw_breakpoint_without_location): Add new breakpoint_ops + parameter. Pass it down. + (set_raw_breakpoint): Ditto. + (print_it_catch_fork): Adjust to take a bpstat as argument. + (catch_fork_breakpoint_ops): Install methods. + (print_it_catch_vfork): Adjust to take a bpstat as argument. + (catch_vfork_breakpoint_ops): Install methods. + (dtor_catch_syscall): Call the base dtor. + (print_it_catch_syscall): Adjust to take a bpstat as argument. + (catch_syscall_breakpoint_ops): Install methods. + (dtor_catch_exec): Call the base dtor. + (print_it_catch_exec): Adjust to take a bpstat as argument. + (catch_exec_breakpoint_ops): Install methods. + (hw_breakpoint_used_count, hw_watchpoint_used_count): Always call + the breakpoint's resources_needed method, and remove the default + code from here. + (set_momentary_breakpoint): Pass bkpt_breakpoint_ops as + breakpoint_ops. + (clone_momentary_breakpoint): Clone the original's ops. + (mention): Always call the breakpoint's print_mention method, and + remove the default code from here. + (create_breakpoint_sal): Adjust to pass the ops to + set_raw_breakpoint rather than setting it manually. + (create_breakpoint): Assert ops is never NULL. Adjust to pass the + ops to set_raw_breakpoint_without_location rather than setting it + manually. + (break_command_1): Pass bkpt_breakpoint_ops as breakpoint_ops. + (print_it_ranged_breakpoint): Adjust to take a bpstat as argument. + (ranged_breakpoint_ops): Install methods. + (break_range_command): Adjust to pass the ops to + set_raw_breakpoint rather than setting it manually. + (re_set_watchpoint, breakpoint_hit_watchpoint) + (check_status_watchpoint, resources_needed_watchpoint) + (works_in_software_mode_watchpoint, print_it_watchpoint) + (print_mention_watchpoint, print_recreate_watchpoint): New + functions. + (watchpoint_breakpoint_ops): Install new methods. + (print_it_masked_watchpoint): New function. + (masked_watchpoint_breakpoint_ops): Install new methods. + (watch_command_1): Adjust to pass the right breakpoint_ops to + set_raw_breakpoint_without_location rather than setting it + manually later. Record the current pspace. + (print_it_exception_catchpoint): Adjust to take a bpstat as + argument. + (gnu_v3_exception_catchpoint_ops): Install new methods. + (say_where): New function. + (null_re_set, null_check_status, null_works_in_software_mode) + (null_resources_needed, null_print_one_detail, bp_location_dtor): + New functions. + (bp_location_ops): New global. + (bkpt_dtor, bkpt_allocate_location, bkpt_re_set) + (bkpt_insert_location, bkpt_remove_location, bkpt_breakpoint_hit) + (bkpt_check_status, bkpt_resources_needed) + (bkpt_works_in_software_mode, bkpt_print_it, bkpt_print_mention) + (bkpt_print_recreate): New functions. + (bkpt_breakpoint_ops): New global. + (tracepoint_re_set, tracepoint_insert_location) + (tracepoint_remove_location, tracepoint_breakpoint_hit) + (tracepoint_check_status, tracepoint_works_in_software_mode) + (tracepoint_print_it, tracepoint_print_one_detail) + (tracepoint_print_mention, tracepoint_print_recreate): New + functions. + (tracepoint_breakpoint_ops): New global. + (delete_breakpoint): Always call the breakpoint's dtor method, and + remove the default handling from here. + (breakpoint_re_set_default): Make static. + (breakpoint_re_set_one): Always call the breakpoints re_set + method, and remove the default handling from here. + (trace_command, ftrace_command, strace_command) + (create_tracepoint_from_upload): Pass appropriate breakpoints_ops + to create_breakpoint. + (save_breakpoints): Always call the breakpoint's print_recreate + method, and remove the default handling from here. + + * ada-lang.c (dtor_exception): Call the base dtor. + (re_set_exception): Call the base method. + (print_it_exception, print_it_catch_exception): Adjust to take a + bpstat as argument. + (catch_exception_breakpoint_ops): Install methods. + (print_it_catch_exception_unhandled): Adjust to take a bpstat as + argument. + (catch_exception_unhandled_breakpoint_ops): Install methods. + (print_it_catch_assert): Adjust to take a bpstat as argument. + (catch_assert_breakpoint_ops): Install methods. + + * breakpoint.h (struct breakpoint_ops): Adjust the print_it method + to take a bpstat as argument. + (enum print_stop_action): Add describing comments to each enum + value. + (breakpoint_re_set_default): Delete declaration. + (null_re_set, null_works_in_software_mode, null_resources_needed) + (null_check_status, null_print_one_detail): Declare. + (bkpt_breakpoint_ops): Declare. + (bkpt_dtor, bkpt_allocate_location, bkpt_re_set) + (bkpt_insert_location, bkpt_remove_location, bkpt_breakpoint_hit) + (bkpt_check_status, bkpt_resources_needed) + (bkpt_works_in_software_mode, bkpt_print_it) + (null_print_one_detail, bkpt_print_mention, bkpt_print_recreate): + Declare. + + * mi/mi-cmd-break.c (mi_cmd_break_insert): Adjust to pass + bkpt_breakpoint_ops. + * python/py-breakpoint.c (bppy_init): Ditto. + 2011-07-15 Philippe Waroquiers <philippe.waroquiers@skynet.be> * MAINTAINERS (Write After Approval): Add myself to the list. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 4499873..a052cb6 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -10988,6 +10988,8 @@ dtor_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) struct ada_catchpoint *c = (struct ada_catchpoint *) b; xfree (c->excep_string); + + bkpt_dtor (b); } /* Implement the ALLOCATE_LOCATION method in the breakpoint_ops @@ -11015,7 +11017,7 @@ re_set_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) /* Call the base class's method. This updates the catchpoint's locations. */ - breakpoint_re_set_default (b); + bkpt_re_set (b); /* Reparse the exception conditional expressions. One for each location. */ @@ -11074,8 +11076,10 @@ check_status_exception (enum exception_catchpoint_kind ex, bpstat bs) for all exception catchpoint kinds. */ static enum print_stop_action -print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) +print_it_exception (enum exception_catchpoint_kind ex, bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; + annotate_catchpoint (b->number); if (ui_out_is_mi_like_p (uiout)) @@ -11287,9 +11291,9 @@ check_status_catch_exception (bpstat bs) } static enum print_stop_action -print_it_catch_exception (struct breakpoint *b) +print_it_catch_exception (bpstat bs) { - return print_it_exception (ex_catch_exception, b); + return print_it_exception (ex_catch_exception, bs); } static void @@ -11315,15 +11319,15 @@ static struct breakpoint_ops catch_exception_breakpoint_ops = dtor_catch_exception, allocate_location_catch_exception, re_set_catch_exception, - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ + bkpt_insert_location, + bkpt_remove_location, + bkpt_breakpoint_hit, check_status_catch_exception, - NULL, /* resources_needed */ - NULL, /* works_in_software_mode */ + bkpt_resources_needed, + null_works_in_software_mode, print_it_catch_exception, print_one_catch_exception, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_exception, print_recreate_catch_exception }; @@ -11355,9 +11359,9 @@ check_status_catch_exception_unhandled (bpstat bs) } static enum print_stop_action -print_it_catch_exception_unhandled (struct breakpoint *b) +print_it_catch_exception_unhandled (bpstat bs) { - return print_it_exception (ex_catch_exception_unhandled, b); + return print_it_exception (ex_catch_exception_unhandled, bs); } static void @@ -11384,15 +11388,15 @@ static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = { dtor_catch_exception_unhandled, allocate_location_catch_exception_unhandled, re_set_catch_exception_unhandled, - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ + bkpt_insert_location, + bkpt_remove_location, + bkpt_breakpoint_hit, check_status_catch_exception_unhandled, - NULL, /* resources_needed */ - NULL, /* works_in_software_mode */ + bkpt_resources_needed, + null_works_in_software_mode, print_it_catch_exception_unhandled, print_one_catch_exception_unhandled, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_exception_unhandled, print_recreate_catch_exception_unhandled }; @@ -11424,9 +11428,9 @@ check_status_catch_assert (bpstat bs) } static enum print_stop_action -print_it_catch_assert (struct breakpoint *b) +print_it_catch_assert (bpstat bs) { - return print_it_exception (ex_catch_assert, b); + return print_it_exception (ex_catch_assert, bs); } static void @@ -11451,15 +11455,15 @@ static struct breakpoint_ops catch_assert_breakpoint_ops = { dtor_catch_assert, allocate_location_catch_assert, re_set_catch_assert, - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ + bkpt_insert_location, + bkpt_remove_location, + bkpt_breakpoint_hit, check_status_catch_assert, - NULL, /* resources_needed */ - NULL, /* works_in_software_mode */ + bkpt_resources_needed, + null_works_in_software_mode, print_it_catch_assert, print_one_catch_assert, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_assert, print_recreate_catch_assert }; diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 802c8a1..9626cdd 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -94,6 +94,8 @@ static void ignore_command (char *, int); static int breakpoint_re_set_one (void *); +static void breakpoint_re_set_default (struct breakpoint *); + static void clear_command (char *, int); static void catch_command (char *, int); @@ -104,11 +106,14 @@ static void break_command_1 (char *, int, int); static void mention (struct breakpoint *); +static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *, + enum bptype, + struct breakpoint_ops *); /* This function is used in gdbtk sources and thus can not be made static. */ struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch, - struct symtab_and_line, - enum bptype); + struct symtab_and_line, + enum bptype, struct breakpoint_ops *); static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int); @@ -157,8 +162,6 @@ insertion_state_t; static int remove_breakpoint (struct bp_location *, insertion_state_t); static int remove_breakpoint_1 (struct bp_location *, insertion_state_t); -static enum print_stop_action print_it_typical (bpstat); - static enum print_stop_action print_bp_stop_message (bpstat bs); static int watchpoint_check (void *); @@ -1436,10 +1439,7 @@ update_watchpoint (struct breakpoint *b, int reparse) (b->type, i, other_type_used); if (target_resources_ok <= 0) { - /* If there's no works_in_software_mode method, we - assume that the watchpoint works in software mode. */ - int sw_mode = (!b->ops || !b->ops->works_in_software_mode - || b->ops->works_in_software_mode (b)); + int sw_mode = b->ops->works_in_software_mode (b); if (target_resources_ok == 0 && !sw_mode) error (_("Target does not support this type of " @@ -1451,8 +1451,7 @@ update_watchpoint (struct breakpoint *b, int reparse) b->type = bp_watchpoint; } } - else if (b->ops && b->ops->works_in_software_mode - && !b->ops->works_in_software_mode (b)) + else if (!b->ops->works_in_software_mode (b)) error (_("Expression cannot be implemented with " "read/access watchpoint.")); else @@ -1622,12 +1621,7 @@ insert_bp_location (struct bp_location *bl, { /* No overlay handling: just set the breakpoint. */ - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (bl->gdbarch, - &bl->target_info); - else - val = target_insert_breakpoint (bl->gdbarch, - &bl->target_info); + val = bl->owner->ops->insert_location (bl); } else { @@ -1661,12 +1655,7 @@ insert_bp_location (struct bp_location *bl, if (section_is_mapped (bl->section)) { /* Yes. This overlay section is mapped into memory. */ - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (bl->gdbarch, - &bl->target_info); - else - val = target_insert_breakpoint (bl->gdbarch, - &bl->target_info); + val = bl->owner->ops->insert_location (bl); } else { @@ -2088,7 +2077,7 @@ create_internal_breakpoint (struct gdbarch *gdbarch, sal.section = find_pc_overlay (sal.pc); sal.pspace = current_program_space; - b = set_raw_breakpoint (gdbarch, sal, type); + b = set_raw_breakpoint (gdbarch, sal, type, &bkpt_breakpoint_ops); b->number = internal_breakpoint_number--; b->disposition = disp_donttouch; @@ -2547,11 +2536,7 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) || !(section_is_overlay (bl->section))) { /* No overlay handling: just remove the breakpoint. */ - - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); - else - val = target_remove_breakpoint (bl->gdbarch, &bl->target_info); + val = bl->owner->ops->remove_location (bl); } else { @@ -2579,16 +2564,13 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) remove the breakpoint if the section had been unmapped, but let's not rely on that being safe. We don't know what the overlay manager might do. */ - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_remove_hw_breakpoint (bl->gdbarch, - &bl->target_info); /* However, we should remove *software* breakpoints only if the section is still mapped, or else we overwrite wrong code with the saved shadow contents. */ - else if (section_is_mapped (bl->section)) - val = target_remove_breakpoint (bl->gdbarch, - &bl->target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint + || section_is_mapped (bl->section)) + val = bl->owner->ops->remove_location (bl); else val = 0; } @@ -3305,219 +3287,6 @@ watchpoint_value_print (struct value *val, struct ui_file *stream) } } -/* This is the normal print function for a bpstat. In the future, - much of this logic could (should?) be moved to bpstat_stop_status, - by having it set different print_it values. - - Current scheme: When we stop, bpstat_print() is called. It loops - through the bpstat list of things causing this stop, calling the - print_bp_stop_message function on each one. The behavior of the - print_bp_stop_message function depends on the print_it field of - bpstat. If such field so indicates, call this function here. - - Return values from this routine (ultimately used by bpstat_print() - and normal_stop() to decide what to do): - PRINT_NOTHING: Means we already printed all we needed to print, - don't print anything else. - PRINT_SRC_ONLY: Means we printed something, and we do *not* desire - that something to be followed by a location. - PRINT_SCR_AND_LOC: Means we printed something, and we *do* desire - that something to be followed by a location. - PRINT_UNKNOWN: Means we printed nothing or we need to do some more - analysis. */ - -static enum print_stop_action -print_it_typical (bpstat bs) -{ - struct cleanup *old_chain; - struct breakpoint *b; - const struct bp_location *bl; - struct ui_stream *stb; - int bp_temp = 0; - enum print_stop_action result; - - gdb_assert (bs->bp_location_at != NULL); - - bl = bs->bp_location_at; - b = bs->breakpoint_at; - - stb = ui_out_stream_new (uiout); - old_chain = make_cleanup_ui_out_stream_delete (stb); - - switch (b->type) - { - case bp_breakpoint: - case bp_hardware_breakpoint: - bp_temp = b->disposition == disp_del; - if (bl->address != bl->requested_address) - breakpoint_adjustment_warning (bl->requested_address, - bl->address, - b->number, 1); - annotate_breakpoint (b->number); - if (bp_temp) - ui_out_text (uiout, "\nTemporary breakpoint "); - else - ui_out_text (uiout, "\nBreakpoint "); - if (ui_out_is_mi_like_p (uiout)) - { - ui_out_field_string (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); - ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); - } - ui_out_field_int (uiout, "bkptno", b->number); - ui_out_text (uiout, ", "); - result = PRINT_SRC_AND_LOC; - break; - - case bp_shlib_event: - /* Did we stop because the user set the stop_on_solib_events - variable? (If so, we report this as a generic, "Stopped due - to shlib event" message.) */ - printf_filtered (_("Stopped due to shared library event\n")); - result = PRINT_NOTHING; - break; - - case bp_thread_event: - /* Not sure how we will get here. - GDB should not stop for these breakpoints. */ - printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n")); - result = PRINT_NOTHING; - break; - - case bp_overlay_event: - /* By analogy with the thread event, GDB should not stop for these. */ - printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n")); - result = PRINT_NOTHING; - break; - - case bp_longjmp_master: - /* These should never be enabled. */ - printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n")); - result = PRINT_NOTHING; - break; - - case bp_std_terminate_master: - /* These should never be enabled. */ - printf_filtered (_("std::terminate Master Breakpoint: " - "gdb should not stop!\n")); - result = PRINT_NOTHING; - break; - - case bp_exception_master: - /* These should never be enabled. */ - printf_filtered (_("Exception Master Breakpoint: " - "gdb should not stop!\n")); - result = PRINT_NOTHING; - break; - - case bp_watchpoint: - case bp_hardware_watchpoint: - annotate_watchpoint (b->number); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER)); - mention (b); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nOld value = "); - watchpoint_value_print (bs->old_val, stb->stream); - ui_out_field_stream (uiout, "old", stb); - ui_out_text (uiout, "\nNew value = "); - watchpoint_value_print (b->val, stb->stream); - ui_out_field_stream (uiout, "new", stb); - ui_out_text (uiout, "\n"); - /* More than one watchpoint may have been triggered. */ - result = PRINT_UNKNOWN; - break; - - case bp_read_watchpoint: - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER)); - mention (b); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nValue = "); - watchpoint_value_print (b->val, stb->stream); - ui_out_field_stream (uiout, "value", stb); - ui_out_text (uiout, "\n"); - result = PRINT_UNKNOWN; - break; - - case bp_access_watchpoint: - if (bs->old_val != NULL) - { - annotate_watchpoint (b->number); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); - mention (b); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nOld value = "); - watchpoint_value_print (bs->old_val, stb->stream); - ui_out_field_stream (uiout, "old", stb); - ui_out_text (uiout, "\nNew value = "); - } - else - { - mention (b); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nValue = "); - } - watchpoint_value_print (b->val, stb->stream); - ui_out_field_stream (uiout, "new", stb); - ui_out_text (uiout, "\n"); - result = PRINT_UNKNOWN; - break; - - /* Fall through, we don't deal with these types of breakpoints - here. */ - - case bp_finish: - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED)); - result = PRINT_UNKNOWN; - break; - - case bp_until: - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED)); - result = PRINT_UNKNOWN; - break; - - case bp_none: - case bp_longjmp: - case bp_longjmp_resume: - case bp_exception: - case bp_exception_resume: - case bp_step_resume: - case bp_hp_step_resume: - case bp_watchpoint_scope: - case bp_call_dummy: - case bp_std_terminate: - case bp_tracepoint: - case bp_fast_tracepoint: - case bp_jit_event: - case bp_gnu_ifunc_resolver: - case bp_gnu_ifunc_resolver_return: - default: - result = PRINT_UNKNOWN; - break; - } - - do_cleanups (old_chain); - return result; -} - /* Generic routine for printing messages indicating why we stopped. The behavior of this function depends on the value 'print_it' in the bpstat structure. Under some circumstances we @@ -3549,14 +3318,10 @@ print_bp_stop_message (bpstat bs) if (b == NULL) return PRINT_UNKNOWN; - /* Normal case. Call the breakpoint's print_it method, or - print_it_typical. */ - if (b->ops != NULL && b->ops->print_it != NULL) - return b->ops->print_it (b); - else - return print_it_typical (bs); + /* Normal case. Call the breakpoint's print_it method. */ + return b->ops->print_it (bs); } - break; + break; default: internal_error (__FILE__, __LINE__, @@ -3851,10 +3616,11 @@ watchpoint_check (void *p) So we can't even detect the first assignment to it and watch after that (since the garbage may or may not equal the first value assigned). */ - /* We print all the stop information in print_it_typical(), but - in this case, by the time we call print_it_typical() this bp - will be deleted already. So we have no choice but print the - information here. */ + /* We print all the stop information in + breakpoint_ops->print_it, but in this case, by the time we + call breakpoint_ops->print_it this bp will be deleted + already. So we have no choice but print the information + here. */ if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE)); @@ -3873,60 +3639,19 @@ which its expression is valid.\n"); } /* Return true if it looks like target has stopped due to hitting - breakpoint location BL. This function does not check if we - should stop, only if BL explains the stop. */ + breakpoint location BL. This function does not check if we should + stop, only if BL explains the stop. */ + static int bpstat_check_location (const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr) { struct breakpoint *b = bl->owner; - /* BL is from existing struct breakpoint. */ + /* BL is from an existing breakpoint. */ gdb_assert (b != NULL); - if (b->ops && b->ops->breakpoint_hit) - return b->ops->breakpoint_hit (bl, aspace, bp_addr); - - /* By definition, the inferior does not report stops at - tracepoints. */ - if (is_tracepoint (b)) - return 0; - - if (!is_watchpoint (b) - && b->type != bp_hardware_breakpoint - && b->type != bp_catchpoint) /* a non-watchpoint bp */ - { - if (!breakpoint_address_match (bl->pspace->aspace, bl->address, - aspace, bp_addr)) - return 0; - if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - return 0; - } - - /* Continuable hardware watchpoints are treated as non-existent if the - reason we stopped wasn't a hardware watchpoint (we didn't stop on - some data address). Otherwise gdb won't stop on a break instruction - in the code (not from a breakpoint) when a hardware watchpoint has - been defined. Also skip watchpoints which we know did not trigger - (did not match the data address). */ - - if (is_hardware_watchpoint (b) - && b->watchpoint_triggered == watch_triggered_no) - return 0; - - if (b->type == bp_hardware_breakpoint) - { - if (bl->address != bp_addr) - return 0; - if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - return 0; - } - - return 1; + return b->ops->breakpoint_hit (bl, aspace, bp_addr); } /* If BS refers to a watchpoint, determine if the watched values @@ -4307,27 +4032,11 @@ bpstat_stop_status (struct address_space *aspace, if (!bs->stop) continue; - bpstat_check_watchpoint (bs); - if (!bs->stop) - continue; - b = bs->breakpoint_at; - - if (b->ops != NULL && b->ops->check_status != NULL) + b->ops->check_status (bs); + if (bs->stop) { - 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 - || b->type == bp_exception_master) - /* We do not stop for these. */ - bs->stop = 0; - else - bpstat_check_breakpoint_conditions (bs, ptid); + bpstat_check_breakpoint_conditions (bs, ptid); if (bs->stop) { @@ -4360,6 +4069,7 @@ bpstat_stop_status (struct address_space *aspace, /* Print nothing for this entry if we don't stop or don't print. */ if (bs->stop == 0 || bs->print == 0) bs->print_it = print_it_noop; + } } /* If we aren't stopping, the value of some hardware watchpoint may @@ -4990,19 +4700,9 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_text (uiout, "\n"); - if (!part_of_multiple && b->ops && b->ops->print_one_detail) + if (!part_of_multiple) b->ops->print_one_detail (b, uiout); - if (!part_of_multiple && b->static_trace_marker_id) - { - gdb_assert (b->type == bp_static_tracepoint); - - ui_out_text (uiout, "\tmarker id is "); - ui_out_field_string (uiout, "static-tracepoint-marker-string-id", - b->static_trace_marker_id); - ui_out_text (uiout, "\n"); - } - if (part_of_multiple && frame_id_p (b->frame_id)) { annotate_field (6); @@ -5693,6 +5393,8 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops, { memset (loc, 0, sizeof (*loc)); + gdb_assert (ops != NULL); + loc->ops = ops; loc->owner = owner; loc->cond = NULL; @@ -5751,28 +5453,13 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops, 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; + return bpt->ops->allocate_location (bpt); } 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); - - if (loc->function_name) - xfree (loc->function_name); - + loc->ops->dtor (loc); xfree (loc); } @@ -5828,6 +5515,8 @@ init_raw_breakpoint_without_location (struct breakpoint *b, { memset (b, 0, sizeof (*b)); + gdb_assert (ops != NULL); + b->ops = ops; b->type = bptype; b->gdbarch = gdbarch; @@ -5847,16 +5536,15 @@ init_raw_breakpoint_without_location (struct breakpoint *b, /* Helper to set_raw_breakpoint below. Creates a breakpoint that has type BPTYPE and has no locations as yet. */ -/* This function is used in gdbtk sources and thus can not be made - static. */ static struct breakpoint * set_raw_breakpoint_without_location (struct gdbarch *gdbarch, - enum bptype bptype) + enum bptype bptype, + struct breakpoint_ops *ops) { struct breakpoint *b = XNEW (struct breakpoint); - init_raw_breakpoint_without_location (b, gdbarch, bptype, NULL); + init_raw_breakpoint_without_location (b, gdbarch, bptype, ops); add_to_breakpoint_chain (b); return b; } @@ -5992,11 +5680,12 @@ init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch, struct breakpoint * set_raw_breakpoint (struct gdbarch *gdbarch, - struct symtab_and_line sal, enum bptype bptype) + struct symtab_and_line sal, enum bptype bptype, + struct breakpoint_ops *ops) { struct breakpoint *b = XNEW (struct breakpoint); - init_raw_breakpoint (b, gdbarch, sal, bptype, NULL); + init_raw_breakpoint (b, gdbarch, sal, bptype, ops); add_to_breakpoint_chain (b); return b; } @@ -6339,9 +6028,10 @@ breakpoint_hit_catch_fork (const struct bp_location *bl, catchpoints. */ static enum print_stop_action -print_it_catch_fork (struct breakpoint *b) +print_it_catch_fork (bpstat bs) { - struct fork_catchpoint *c = (struct fork_catchpoint *) b; + struct breakpoint *b = bs->breakpoint_at; + struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at; annotate_catchpoint (b->number); printf_filtered (_("\nCatchpoint %d (forked process %d), "), @@ -6398,18 +6088,18 @@ 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 */ + bkpt_dtor, + bkpt_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 */ + null_check_status, + null_resources_needed, + null_works_in_software_mode, print_it_catch_fork, print_one_catch_fork, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_fork, print_recreate_catch_fork }; @@ -6448,8 +6138,9 @@ breakpoint_hit_catch_vfork (const struct bp_location *bl, catchpoints. */ static enum print_stop_action -print_it_catch_vfork (struct breakpoint *b) +print_it_catch_vfork (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; struct fork_catchpoint *c = (struct fork_catchpoint *) b; annotate_catchpoint (b->number); @@ -6506,18 +6197,18 @@ 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 */ + bkpt_dtor, + bkpt_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 */ + null_check_status, + null_resources_needed, + null_works_in_software_mode, print_it_catch_vfork, print_one_catch_vfork, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_vfork, print_recreate_catch_vfork }; @@ -6549,6 +6240,8 @@ dtor_catch_syscall (struct breakpoint *b) struct syscall_catchpoint *c = (struct syscall_catchpoint *) b; VEC_free (int, c->syscalls_to_be_caught); + + bkpt_dtor (b); } /* Implement the "insert" breakpoint_ops method for syscall @@ -6673,8 +6366,9 @@ breakpoint_hit_catch_syscall (const struct bp_location *bl, catchpoints. */ static enum print_stop_action -print_it_catch_syscall (struct breakpoint *b) +print_it_catch_syscall (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; /* These are needed because we want to know in which state a syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we @@ -6836,17 +6530,17 @@ 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 */ + bkpt_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 */ + null_check_status, + null_resources_needed, + null_works_in_software_mode, print_it_catch_syscall, print_one_catch_syscall, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_syscall, print_recreate_catch_syscall }; @@ -6934,6 +6628,8 @@ dtor_catch_exec (struct breakpoint *b) struct exec_catchpoint *c = (struct exec_catchpoint *) b; xfree (c->exec_pathname); + + bkpt_dtor (b); } static int @@ -6958,8 +6654,9 @@ breakpoint_hit_catch_exec (const struct bp_location *bl, } static enum print_stop_action -print_it_catch_exec (struct breakpoint *b) +print_it_catch_exec (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; struct exec_catchpoint *c = (struct exec_catchpoint *) b; annotate_catchpoint (b->number); @@ -7009,17 +6706,17 @@ 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 */ + bkpt_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 */ + null_check_status, + null_resources_needed, + null_works_in_software_mode, print_it_catch_exec, print_one_catch_exec, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_catch_exec, print_recreate_catch_exec }; @@ -7052,10 +6749,7 @@ hw_breakpoint_used_count (void) { /* Special types of hardware breakpoints may use more than one register. */ - if (b->ops && b->ops->resources_needed) - i += b->ops->resources_needed (bl); - else - i++; + i += b->ops->resources_needed (bl); } } @@ -7080,10 +6774,7 @@ hw_watchpoint_used_count (enum bptype type, int *other_type_used) { /* Special types of hardware watchpoints may use more than one register. */ - if (b->ops && b->ops->resources_needed) - i += b->ops->resources_needed (bl); - else - i++; + i += b->ops->resources_needed (bl); } else if (is_hardware_watchpoint (b)) *other_type_used = 1; @@ -7189,7 +6880,7 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, one. */ gdb_assert (!frame_id_inlined_p (frame_id)); - b = set_raw_breakpoint (gdbarch, sal, type); + b = set_raw_breakpoint (gdbarch, sal, type, &bkpt_breakpoint_ops); b->enable_state = bp_enabled; b->disposition = disp_donttouch; b->frame_id = frame_id; @@ -7217,7 +6908,8 @@ clone_momentary_breakpoint (struct breakpoint *orig) if (orig == NULL) return NULL; - copy = set_raw_breakpoint_without_location (orig->gdbarch, orig->type); + copy = set_raw_breakpoint_without_location (orig->gdbarch, + orig->type, orig->ops); copy->loc = allocate_bp_location (copy); set_breakpoint_location_function (copy->loc, 1); @@ -7265,162 +6957,7 @@ set_momentary_breakpoint_at_pc (struct gdbarch *gdbarch, CORE_ADDR pc, static void mention (struct breakpoint *b) { - int say_where = 0; - struct cleanup *ui_out_chain; - struct value_print_options opts; - - get_user_print_options (&opts); - - if (b->ops != NULL && b->ops->print_mention != NULL) - b->ops->print_mention (b); - else - switch (b->type) - { - case bp_none: - printf_filtered (_("(apparently deleted?) Eventpoint %d: "), - b->number); - break; - case bp_watchpoint: - ui_out_text (uiout, "Watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_hardware_watchpoint: - ui_out_text (uiout, "Hardware watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_read_watchpoint: - ui_out_text (uiout, "Hardware read watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_access_watchpoint: - ui_out_text (uiout, "Hardware access (read/write) watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_breakpoint: - case bp_gnu_ifunc_resolver: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - if (b->disposition == disp_del) - printf_filtered (_("Temporary breakpoint")); - else - printf_filtered (_("Breakpoint")); - printf_filtered (_(" %d"), b->number); - if (b->type == bp_gnu_ifunc_resolver) - printf_filtered (_(" at gnu-indirect-function resolver")); - say_where = 1; - break; - case bp_hardware_breakpoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Hardware assisted breakpoint %d"), b->number); - say_where = 1; - break; - case bp_tracepoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Tracepoint")); - printf_filtered (_(" %d"), b->number); - say_where = 1; - break; - case bp_fast_tracepoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Fast tracepoint")); - printf_filtered (_(" %d"), b->number); - say_where = 1; - break; - case bp_static_tracepoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Static tracepoint")); - printf_filtered (_(" %d"), b->number); - say_where = 1; - break; - - case bp_until: - case bp_finish: - case bp_longjmp: - case bp_longjmp_resume: - case bp_exception: - case bp_exception_resume: - case bp_step_resume: - case bp_hp_step_resume: - case bp_call_dummy: - case bp_std_terminate: - case bp_watchpoint_scope: - case bp_shlib_event: - case bp_thread_event: - case bp_overlay_event: - case bp_jit_event: - case bp_longjmp_master: - case bp_std_terminate_master: - case bp_exception_master: - case bp_gnu_ifunc_resolver_return: - break; - } - - if (say_where) - { - /* i18n: cagney/2005-02-11: Below needs to be merged into a - single string. */ - if (b->loc == NULL) - { - printf_filtered (_(" (%s) pending."), b->addr_string); - } - else - { - if (opts.addressprint || b->source_file == NULL) - { - printf_filtered (" at "); - fputs_filtered (paddress (b->loc->gdbarch, b->loc->address), - gdb_stdout); - } - if (b->source_file) - printf_filtered (": file %s, line %d.", - b->source_file, b->line_number); - - if (b->loc->next) - { - struct bp_location *loc = b->loc; - int n = 0; - for (; loc; loc = loc->next) - ++n; - printf_filtered (" (%d locations)", n); - } - - } - } + b->ops->print_mention (b); if (ui_out_is_mi_like_p (uiout)) return; printf_filtered ("\n"); @@ -7543,7 +7080,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch, if (i == 0) { - b = set_raw_breakpoint (gdbarch, sal, type); + b = set_raw_breakpoint (gdbarch, sal, type, ops); set_breakpoint_number (internal, b); b->thread = thread; b->task = task; @@ -7625,7 +7162,6 @@ create_breakpoint_sal (struct gdbarch *gdbarch, b->addr_string = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address)); - b->ops = ops; /* Do not mention breakpoints with a negative number, but do notify observers. */ if (!internal) @@ -8083,6 +7619,8 @@ create_breakpoint (struct gdbarch *gdbarch, int task = 0; int prev_bkpt_count = breakpoint_count; + gdb_assert (ops != NULL); + sals.sals = NULL; sals.nelts = 0; init_linespec_result (&canonical); @@ -8275,7 +7813,7 @@ create_breakpoint (struct gdbarch *gdbarch, make_cleanup (xfree, copy_arg); - b = set_raw_breakpoint_without_location (gdbarch, type_wanted); + b = set_raw_breakpoint_without_location (gdbarch, type_wanted, ops); set_breakpoint_number (internal, b); b->thread = -1; b->addr_string = canonical.canonical[0]; @@ -8283,7 +7821,6 @@ create_breakpoint (struct gdbarch *gdbarch, b->ignore_count = ignore_count; b->disposition = tempflag ? disp_del : disp_donttouch; b->condition_not_parsed = 1; - b->ops = ops; b->enable_state = enabled ? bp_enabled : bp_disabled; b->pspace = current_program_space; b->py_bp_object = NULL; @@ -8319,13 +7856,13 @@ create_breakpoint (struct gdbarch *gdbarch, return 1; } -/* Set a breakpoint. +/* Set a breakpoint. ARG is a string describing breakpoint address, condition, and thread. FLAG specifies if a breakpoint is hardware on, and if breakpoint is temporary, using BP_HARDWARE_FLAG and BP_TEMPFLAG. */ - + static void break_command_1 (char *arg, int flag, int from_tty) { @@ -8340,13 +7877,12 @@ break_command_1 (char *arg, int flag, int from_tty) tempflag, type_wanted, 0 /* Ignore count */, pending_break_support, - NULL /* breakpoint_ops */, + &bkpt_breakpoint_ops, from_tty, 1 /* enabled */, 0 /* internal */); } - /* Helper function for break_command_1 and disassemble_command. */ void @@ -8526,8 +8062,9 @@ resources_needed_ranged_breakpoint (const struct bp_location *bl) ranged breakpoints. */ static enum print_stop_action -print_it_ranged_breakpoint (struct breakpoint *b) +print_it_ranged_breakpoint (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; struct bp_location *bl = b->loc; gdb_assert (b->type == bp_hardware_breakpoint); @@ -8636,15 +8173,15 @@ 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 */ + bkpt_dtor, + bkpt_allocate_location, + bkpt_re_set, + bkpt_insert_location, + bkpt_remove_location, breakpoint_hit_ranged_breakpoint, - NULL, /* check_status */ + null_check_status, resources_needed_ranged_breakpoint, - NULL, /* works_in_software_mode */ + null_works_in_software_mode, print_it_ranged_breakpoint, print_one_ranged_breakpoint, print_one_detail_ranged_breakpoint, @@ -8794,13 +8331,12 @@ break_range_command (char *arg, int from_tty) /* Now set up the breakpoint. */ b = set_raw_breakpoint (get_current_arch (), sal_start, - bp_hardware_breakpoint); + bp_hardware_breakpoint, &ranged_breakpoint_ops); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; b->disposition = disp_donttouch; b->addr_string = addr_string_start; b->addr_string_range_end = addr_string_end; - b->ops = &ranged_breakpoint_ops; b->loc->length = length; discard_cleanups (cleanup_bkpt); @@ -8919,6 +8455,39 @@ watchpoint_exp_is_const (const struct expression *exp) return 1; } +/* Implement the "re_set" breakpoint_ops method for watchpoints. */ + +static void +re_set_watchpoint (struct breakpoint *b) +{ + /* Watchpoint can be either on expression using entirely global + variables, or it can be on local variables. + + Watchpoints of the first kind are never auto-deleted, and even + persist across program restarts. Since they can use variables + from shared libraries, we need to reparse expression as libraries + are loaded and unloaded. + + Watchpoints on local variables can also change meaning as result + of solib event. For example, if a watchpoint uses both a local + and a global variables in expression, it's a local watchpoint, + but unloading of a shared library will make the expression + invalid. This is not a very common use case, but we still + re-evaluate expression, to avoid surprises to the user. + + Note that for local watchpoints, we re-evaluate it only if + watchpoints frame id is still valid. If it's not, it means the + watchpoint is out of scope and will be deleted soon. In fact, + I'm not sure we'll ever be called in this case. + + If a local watchpoint's frame id is still valid, then + b->exp_valid_block is likewise valid, and we can safely use it. + + Don't do anything about disabled watchpoints, since they will + be reevaluated again when enabled. */ + update_watchpoint (b, 1 /* reparse */); +} + /* Implement the "insert" breakpoint_ops method for hardware watchpoints. */ static int @@ -8941,6 +8510,33 @@ remove_watchpoint (struct bp_location *bl) bl->owner->cond_exp); } +static int +breakpoint_hit_watchpoint (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) +{ + struct breakpoint *b = bl->owner; + + /* Continuable hardware watchpoints are treated as non-existent if the + reason we stopped wasn't a hardware watchpoint (we didn't stop on + some data address). Otherwise gdb won't stop on a break instruction + in the code (not from a breakpoint) when a hardware watchpoint has + been defined. Also skip watchpoints which we know did not trigger + (did not match the data address). */ + if (is_hardware_watchpoint (b) + && b->watchpoint_triggered == watch_triggered_no) + return 0; + + return 1; +} + +static void +check_status_watchpoint (bpstat bs) +{ + gdb_assert (is_watchpoint (bs->breakpoint_at)); + + bpstat_check_watchpoint (bs); +} + /* Implement the "resources_needed" breakpoint_ops method for hardware watchpoints. */ @@ -8955,30 +8551,184 @@ resources_needed_watchpoint (const struct bp_location *bl) /* Implement the "works_in_software_mode" breakpoint_ops method for hardware watchpoints. */ -int +static int works_in_software_mode_watchpoint (const struct breakpoint *b) { return b->type == bp_hardware_watchpoint; } +static enum print_stop_action +print_it_watchpoint (bpstat bs) +{ + struct cleanup *old_chain; + struct breakpoint *b; + const struct bp_location *bl; + struct ui_stream *stb; + enum print_stop_action result; + + gdb_assert (bs->bp_location_at != NULL); + + bl = bs->bp_location_at; + b = bs->breakpoint_at; + + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); + + switch (b->type) + { + case bp_watchpoint: + case bp_hardware_watchpoint: + annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER)); + mention (b); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nOld value = "); + watchpoint_value_print (bs->old_val, stb->stream); + ui_out_field_stream (uiout, "old", stb); + ui_out_text (uiout, "\nNew value = "); + watchpoint_value_print (b->val, stb->stream); + ui_out_field_stream (uiout, "new", stb); + ui_out_text (uiout, "\n"); + /* More than one watchpoint may have been triggered. */ + result = PRINT_UNKNOWN; + break; + + case bp_read_watchpoint: + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER)); + mention (b); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nValue = "); + watchpoint_value_print (b->val, stb->stream); + ui_out_field_stream (uiout, "value", stb); + ui_out_text (uiout, "\n"); + result = PRINT_UNKNOWN; + break; + + case bp_access_watchpoint: + if (bs->old_val != NULL) + { + annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); + mention (b); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nOld value = "); + watchpoint_value_print (bs->old_val, stb->stream); + ui_out_field_stream (uiout, "old", stb); + ui_out_text (uiout, "\nNew value = "); + } + else + { + mention (b); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nValue = "); + } + watchpoint_value_print (b->val, stb->stream); + ui_out_field_stream (uiout, "new", stb); + ui_out_text (uiout, "\n"); + result = PRINT_UNKNOWN; + break; + default: + result = PRINT_UNKNOWN; + } + + do_cleanups (old_chain); + return result; +} + +/* Implement the "print_mention" breakpoint_ops method for hardware + watchpoints. */ + +static void +print_mention_watchpoint (struct breakpoint *b) +{ + struct cleanup *ui_out_chain; + + switch (b->type) + { + case bp_watchpoint: + ui_out_text (uiout, "Watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); + break; + case bp_hardware_watchpoint: + ui_out_text (uiout, "Hardware watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); + break; + case bp_read_watchpoint: + ui_out_text (uiout, "Hardware read watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt"); + break; + case bp_access_watchpoint: + ui_out_text (uiout, "Hardware access (read/write) watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt"); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid hardware watchpoint type.")); + } + + ui_out_field_int (uiout, "number", b->number); + ui_out_text (uiout, ": "); + ui_out_field_string (uiout, "exp", b->exp_string); + do_cleanups (ui_out_chain); +} + +/* Implement the "print_recreate" breakpoint_ops method for + watchpoints. */ + +static void +print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp) +{ + switch (b->type) + { + case bp_watchpoint: + case bp_hardware_watchpoint: + fprintf_unfiltered (fp, "watch"); + break; + case bp_read_watchpoint: + fprintf_unfiltered (fp, "rwatch"); + break; + case bp_access_watchpoint: + fprintf_unfiltered (fp, "awatch"); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid watchpoint type.")); + } + + fprintf_unfiltered (fp, " %s", b->exp_string); +} + /* The breakpoint_ops structure to be used in hardware watchpoints. */ static struct breakpoint_ops watchpoint_breakpoint_ops = { - NULL, /* dtor */ - NULL, /* allocate_location */ - NULL, /* re_set */ + bkpt_dtor, + bkpt_allocate_location, + re_set_watchpoint, insert_watchpoint, remove_watchpoint, - NULL, /* breakpoint_hit */ - NULL, /* check_status */ + breakpoint_hit_watchpoint, + check_status_watchpoint, resources_needed_watchpoint, works_in_software_mode_watchpoint, - NULL, /* print_it */ + print_it_watchpoint, NULL, /* print_one */ - NULL, /* print_one_detail */ - NULL, /* print_mention */ - NULL /* print_recreate */ + null_print_one_detail, + print_mention_watchpoint, + print_recreate_watchpoint }; /* Implement the "insert" breakpoint_ops method for @@ -9024,8 +8774,10 @@ works_in_software_mode_masked_watchpoint (const struct breakpoint *b) masked hardware watchpoints. */ static enum print_stop_action -print_it_masked_watchpoint (struct breakpoint *b) +print_it_masked_watchpoint (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; + /* Masked watchpoints have only one location. */ gdb_assert (b->loc && b->loc->next == NULL); @@ -9147,13 +8899,13 @@ 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 */ + bkpt_dtor, + bkpt_allocate_location, + re_set_watchpoint, insert_masked_watchpoint, remove_masked_watchpoint, - NULL, /* breakpoint_hit */ - NULL, /* check_status */ + breakpoint_hit_watchpoint, + check_status_watchpoint, resources_needed_masked_watchpoint, works_in_software_mode_masked_watchpoint, print_it_masked_watchpoint, @@ -9392,12 +9144,18 @@ watch_command_1 (char *arg, int accessflag, int from_tty, } /* Now set up the breakpoint. */ - b = set_raw_breakpoint_without_location (NULL, bp_type); + if (use_mask) + b = set_raw_breakpoint_without_location (NULL, bp_type, + &masked_watchpoint_breakpoint_ops); + else + b = set_raw_breakpoint_without_location (NULL, bp_type, + &watchpoint_breakpoint_ops); b->thread = thread; b->disposition = disp_donttouch; b->exp = exp; b->exp_valid_block = exp_valid_block; b->cond_exp_valid_block = cond_exp_valid_block; + b->pspace = current_program_space; if (just_location) { struct type *t = value_type (val); @@ -9423,13 +9181,11 @@ watch_command_1 (char *arg, int accessflag, int from_tty, if (use_mask) { b->hw_wp_mask = mask; - b->ops = &masked_watchpoint_breakpoint_ops; } else { b->val = val; b->val_valid = 1; - b->ops = &watchpoint_breakpoint_ops; } if (cond_start) @@ -9879,8 +9635,9 @@ catch_exec_command_1 (char *arg, int from_tty, } static enum print_stop_action -print_it_exception_catchpoint (struct breakpoint *b) +print_it_exception_catchpoint (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; int bp_temp, bp_throw; annotate_catchpoint (b->number); @@ -9966,18 +9723,18 @@ 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 */ + bkpt_dtor, + bkpt_allocate_location, + bkpt_re_set, + bkpt_insert_location, + bkpt_remove_location, + bkpt_breakpoint_hit, + bkpt_check_status, + bkpt_resources_needed, + null_works_in_software_mode, print_it_exception_catchpoint, print_one_exception_catchpoint, - NULL, /* print_one_detail */ + null_print_one_detail, print_mention_exception_catchpoint, print_recreate_exception_catchpoint }; @@ -10797,6 +10554,600 @@ bpstat_remove_breakpoint_callback (struct thread_info *th, void *data) return 0; } +/* Helper for breakpoint and tracepoint breakpoint_ops->mention + callbacks. */ + +static void +say_where (struct breakpoint *b) +{ + struct value_print_options opts; + + get_user_print_options (&opts); + + /* i18n: cagney/2005-02-11: Below needs to be merged into a + single string. */ + if (b->loc == NULL) + { + printf_filtered (_(" (%s) pending."), b->addr_string); + } + else + { + if (opts.addressprint || b->source_file == NULL) + { + printf_filtered (" at "); + fputs_filtered (paddress (b->loc->gdbarch, b->loc->address), + gdb_stdout); + } + if (b->source_file) + printf_filtered (": file %s, line %d.", + b->source_file, b->line_number); + + if (b->loc->next) + { + struct bp_location *loc = b->loc; + int n = 0; + for (; loc; loc = loc->next) + ++n; + printf_filtered (" (%d locations)", n); + } + } +} + +/* Default breakpoint_ops methods that do nothing. */ + +void +null_re_set (struct breakpoint *b) +{ + /* Nothing to re-set. */ +} + +void +null_check_status (bpstat bs) +{ + /* nothing */ +} + +/* A "works_in_software_mode" breakpoint_ops method that just internal + errors. */ + +int +null_works_in_software_mode (const struct breakpoint *b) +{ + gdb_assert_not_reached ("null_works_in_software_mode called"); +} + +/* A "resources_needed" breakpoint_ops method that just internal + errors. */ + +int +null_resources_needed (const struct bp_location *bl) +{ + gdb_assert_not_reached ("null_resources_needed"); +} + +void +null_print_one_detail (const struct breakpoint *self, + struct ui_out *uiout) +{ + /* nothing */ +} + +/* Default bp_location_ops methods. */ + +static void +bp_location_dtor (struct bp_location *self) +{ + xfree (self->cond); + xfree (self->function_name); +} + +static const struct bp_location_ops bp_location_ops = +{ + bp_location_dtor +}; + +/* Default breakpoint_ops methods. */ + +void +bkpt_dtor (struct breakpoint *self) +{ + decref_counted_command_line (&self->commands); + xfree (self->cond_string); + xfree (self->cond_exp); + xfree (self->addr_string); + xfree (self->addr_string_range_end); + xfree (self->exp); + xfree (self->exp_string); + xfree (self->exp_string_reparse); + value_free (self->val); + xfree (self->source_file); +} + +struct bp_location * +bkpt_allocate_location (struct breakpoint *self) +{ + struct bp_location *loc; + + loc = XNEW (struct bp_location); + init_bp_location (loc, &bp_location_ops, self); + return loc; +} + +void +bkpt_re_set (struct breakpoint *b) +{ + switch (b->type) + { + case bp_breakpoint: + case bp_hardware_breakpoint: + case bp_gnu_ifunc_resolver: + /* Do not attempt to re-set breakpoints disabled during + startup. */ + if (b->enable_state == bp_startup_disabled) + return; + + if (b->addr_string == NULL) + { + /* Anything without a string can't be re-set. */ + delete_breakpoint (b); + return; + } + + breakpoint_re_set_default (b); + break; + + default: + printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type); + /* fall through */ + /* Delete overlay event and longjmp master breakpoints; they + will be reset later by breakpoint_re_set. */ + case bp_overlay_event: + case bp_longjmp_master: + case bp_std_terminate_master: + case bp_exception_master: + delete_breakpoint (b); + break; + + /* This breakpoint is special, it's set up when the inferior + starts and we really don't want to touch it. */ + case bp_shlib_event: + + /* Like bp_shlib_event, this breakpoint type is special. Once + it is set up, we do not want to touch it. */ + case bp_thread_event: + + /* Keep temporary breakpoints, which can be encountered when we + step over a dlopen call and SOLIB_ADD is resetting the + breakpoints. Otherwise these should have been blown away via + the cleanup chain or by breakpoint_init_inferior when we + rerun the executable. */ + case bp_until: + case bp_finish: + case bp_watchpoint_scope: + case bp_call_dummy: + case bp_std_terminate: + case bp_step_resume: + case bp_hp_step_resume: + case bp_longjmp: + case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: + case bp_jit_event: + case bp_gnu_ifunc_resolver_return: + break; + } +} + +int +bkpt_insert_location (struct bp_location *bl) +{ + if (bl->loc_type == bp_loc_hardware_breakpoint) + return target_insert_hw_breakpoint (bl->gdbarch, + &bl->target_info); + else + return target_insert_breakpoint (bl->gdbarch, + &bl->target_info); +} + +int +bkpt_remove_location (struct bp_location *bl) +{ + if (bl->loc_type == bp_loc_hardware_breakpoint) + return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); + else + return target_remove_breakpoint (bl->gdbarch, &bl->target_info); +} + +int +bkpt_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) +{ + struct breakpoint *b = bl->owner; + + if (!breakpoint_address_match (bl->pspace->aspace, bl->address, + aspace, bp_addr)) + return 0; + + if (overlay_debugging /* unmapped overlay section */ + && section_is_overlay (bl->section) + && !section_is_mapped (bl->section)) + return 0; + + return 1; +} + +void +bkpt_check_status (bpstat bs) +{ + struct breakpoint *b = bs->breakpoint_at; + + if (b->type == bp_thread_event + || b->type == bp_overlay_event + || b->type == bp_longjmp_master + || b->type == bp_std_terminate_master + || b->type == bp_exception_master) + /* We do not stop for these. */ + bs->stop = 0; +} + +int +bkpt_resources_needed (const struct bp_location *bl) +{ + gdb_assert (bl->owner->type == bp_hardware_breakpoint); + + return 1; +} + +int +bkpt_works_in_software_mode (const struct breakpoint *b) +{ + gdb_assert_not_reached ("bkpt_works_in_software_mode called"); +} + +enum print_stop_action +bkpt_print_it (bpstat bs) +{ + struct cleanup *old_chain; + struct breakpoint *b; + const struct bp_location *bl; + struct ui_stream *stb; + int bp_temp = 0; + enum print_stop_action result; + + gdb_assert (bs->bp_location_at != NULL); + + bl = bs->bp_location_at; + b = bs->breakpoint_at; + + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); + + switch (b->type) + { + case bp_breakpoint: + case bp_hardware_breakpoint: + bp_temp = b->disposition == disp_del; + if (bl->address != bl->requested_address) + breakpoint_adjustment_warning (bl->requested_address, + bl->address, + b->number, 1); + annotate_breakpoint (b->number); + if (bp_temp) + ui_out_text (uiout, "\nTemporary breakpoint "); + else + ui_out_text (uiout, "\nBreakpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ", "); + result = PRINT_SRC_AND_LOC; + break; + + case bp_shlib_event: + /* Did we stop because the user set the stop_on_solib_events + variable? (If so, we report this as a generic, "Stopped due + to shlib event" message.) */ + printf_filtered (_("Stopped due to shared library event\n")); + result = PRINT_NOTHING; + break; + + case bp_thread_event: + /* Not sure how we will get here. + GDB should not stop for these breakpoints. */ + printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n")); + result = PRINT_NOTHING; + break; + + case bp_overlay_event: + /* By analogy with the thread event, GDB should not stop for these. */ + printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n")); + result = PRINT_NOTHING; + break; + + case bp_longjmp_master: + /* These should never be enabled. */ + printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n")); + result = PRINT_NOTHING; + break; + + case bp_std_terminate_master: + /* These should never be enabled. */ + printf_filtered (_("std::terminate Master Breakpoint: " + "gdb should not stop!\n")); + result = PRINT_NOTHING; + break; + + case bp_exception_master: + /* These should never be enabled. */ + printf_filtered (_("Exception Master Breakpoint: " + "gdb should not stop!\n")); + result = PRINT_NOTHING; + break; + + /* Fall through, we don't deal with these types of breakpoints + here. */ + + case bp_finish: + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED)); + result = PRINT_UNKNOWN; + break; + + case bp_until: + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED)); + result = PRINT_UNKNOWN; + break; + + case bp_none: + case bp_longjmp: + case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: + case bp_step_resume: + case bp_hp_step_resume: + case bp_watchpoint_scope: + case bp_call_dummy: + case bp_std_terminate: + case bp_jit_event: + case bp_gnu_ifunc_resolver: + case bp_gnu_ifunc_resolver_return: + default: + result = PRINT_UNKNOWN; + break; + } + + do_cleanups (old_chain); + return result; +} + +void +bkpt_print_mention (struct breakpoint *b) +{ + if (ui_out_is_mi_like_p (uiout)) + return; + + switch (b->type) + { + case bp_breakpoint: + case bp_gnu_ifunc_resolver: + if (b->disposition == disp_del) + printf_filtered (_("Temporary breakpoint")); + else + printf_filtered (_("Breakpoint")); + printf_filtered (_(" %d"), b->number); + if (b->type == bp_gnu_ifunc_resolver) + printf_filtered (_(" at gnu-indirect-function resolver")); + say_where (b); + break; + case bp_hardware_breakpoint: + printf_filtered (_("Hardware assisted breakpoint %d"), b->number); + say_where (b); + break; + case bp_until: + case bp_finish: + case bp_longjmp: + case bp_longjmp_resume: + case bp_exception: + case bp_exception_resume: + case bp_step_resume: + case bp_hp_step_resume: + case bp_call_dummy: + case bp_std_terminate: + case bp_watchpoint_scope: + case bp_shlib_event: + case bp_thread_event: + case bp_overlay_event: + case bp_jit_event: + case bp_longjmp_master: + case bp_std_terminate_master: + case bp_exception_master: + case bp_gnu_ifunc_resolver_return: + break; + } +} + +void +bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp) +{ + if (tp->type == bp_breakpoint && tp->disposition == disp_del) + fprintf_unfiltered (fp, "tbreak"); + else if (tp->type == bp_breakpoint) + fprintf_unfiltered (fp, "break"); + else if (tp->type == bp_hardware_breakpoint + && tp->disposition == disp_del) + fprintf_unfiltered (fp, "thbreak"); + else if (tp->type == bp_hardware_breakpoint) + fprintf_unfiltered (fp, "hbreak"); + else + internal_error (__FILE__, __LINE__, + _("unhandled breakpoint type %d"), (int) tp->type); + + if (tp->exp_string) + fprintf_unfiltered (fp, " %s", tp->exp_string); + else if (tp->addr_string) + fprintf_unfiltered (fp, " %s", tp->addr_string); + else + { + char tmp[40]; + + sprintf_vma (tmp, tp->loc->address); + fprintf_unfiltered (fp, " *0x%s", tmp); + } +} + +/* The breakpoint_ops structure to be used in regular breakpoints. */ + +struct breakpoint_ops bkpt_breakpoint_ops = +{ + bkpt_dtor, + bkpt_allocate_location, + bkpt_re_set, + bkpt_insert_location, + bkpt_remove_location, + bkpt_breakpoint_hit, + bkpt_check_status, + bkpt_resources_needed, + null_works_in_software_mode, + bkpt_print_it, + NULL, /* print_one */ + null_print_one_detail, + bkpt_print_mention, + bkpt_print_recreate +}; + +/* The breakpoint_ops structure to be used in tracepoints. */ + +static void +tracepoint_re_set (struct breakpoint *b) +{ + breakpoint_re_set_default (b); +} + +static int +tracepoint_insert_location (struct bp_location *bl) +{ + gdb_assert_not_reached ("tracepoint_insert_location called"); +} + +static int +tracepoint_remove_location (struct bp_location *bl) +{ + gdb_assert_not_reached ("tracepoint_remove_location called"); +} + +static int +tracepoint_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) +{ + /* By definition, the inferior does not report stops at + tracepoints. */ + return 0; +} + +static void +tracepoint_check_status (bpstat bs) +{ + gdb_assert_not_reached ("tracepoint_check_status called"); +} + +static int +tracepoint_works_in_software_mode (const struct breakpoint *b) +{ + gdb_assert_not_reached ("tracepoint_works_in_software_mode called"); +} + +static enum print_stop_action +tracepoint_print_it (bpstat bs) +{ + gdb_assert_not_reached ("tracepoint_print_it called"); +} + +static void +tracepoint_print_one_detail (const struct breakpoint *self, + struct ui_out *uiout) +{ + if (self->static_trace_marker_id) + { + gdb_assert (self->type == bp_static_tracepoint); + + ui_out_text (uiout, "\tmarker id is "); + ui_out_field_string (uiout, "static-tracepoint-marker-string-id", + self->static_trace_marker_id); + ui_out_text (uiout, "\n"); + } +} + +static void +tracepoint_print_mention (struct breakpoint *b) +{ + if (ui_out_is_mi_like_p (uiout)) + return; + + switch (b->type) + { + case bp_tracepoint: + printf_filtered (_("Tracepoint")); + printf_filtered (_(" %d"), b->number); + break; + case bp_fast_tracepoint: + printf_filtered (_("Fast tracepoint")); + printf_filtered (_(" %d"), b->number); + break; + case bp_static_tracepoint: + printf_filtered (_("Static tracepoint")); + printf_filtered (_(" %d"), b->number); + break; + default: + internal_error (__FILE__, __LINE__, + _("unhandled tracepoint type %d"), (int) b->type); + } + + say_where (b); +} + +static void +tracepoint_print_recreate (struct breakpoint *tp, struct ui_file *fp) +{ + if (tp->type == bp_fast_tracepoint) + fprintf_unfiltered (fp, "ftrace"); + if (tp->type == bp_static_tracepoint) + fprintf_unfiltered (fp, "strace"); + else if (tp->type == bp_tracepoint) + fprintf_unfiltered (fp, "trace"); + else + internal_error (__FILE__, __LINE__, + _("unhandled tracepoint type %d"), (int) tp->type); + + fprintf_unfiltered (fp, " %s", tp->addr_string); +} + +struct breakpoint_ops tracepoint_breakpoint_ops = +{ + bkpt_dtor, + bkpt_allocate_location, + tracepoint_re_set, + tracepoint_insert_location, + tracepoint_remove_location, + tracepoint_breakpoint_hit, + tracepoint_check_status, + null_resources_needed, + tracepoint_works_in_software_mode, + tracepoint_print_it, + NULL, /* print_one */ + tracepoint_print_one_detail, + tracepoint_print_mention, + tracepoint_print_recreate +}; + /* Delete a breakpoint and clean up all traces of it in the data structures. */ @@ -10861,21 +11212,6 @@ delete_breakpoint (struct breakpoint *bpt) break; } - if (bpt->ops != NULL && bpt->ops->dtor != NULL) - bpt->ops->dtor (bpt); - - decref_counted_command_line (&bpt->commands); - xfree (bpt->cond_string); - xfree (bpt->cond_exp); - xfree (bpt->addr_string); - xfree (bpt->addr_string_range_end); - xfree (bpt->exp); - xfree (bpt->exp_string); - xfree (bpt->exp_string_reparse); - value_free (bpt->val); - xfree (bpt->source_file); - - /* Be sure no bpstat's are pointing at the breakpoint after it's been freed. */ /* FIXME, how can we find all bpstat's? We just check stop_bpstat @@ -10896,11 +11232,10 @@ delete_breakpoint (struct breakpoint *bpt) self-contained, but it's not the case now. */ update_global_location_list (0); - + bpt->ops->dtor (bpt); /* On the chance that someone will soon try again to delete this same bp, we mark it as deleted before freeing its storage. */ bpt->type = bp_none; - xfree (bpt); } @@ -11419,7 +11754,11 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) return sals; } -void +/* The default re_set method, for typical hardware or software + breakpoints. Reevaluate the breakpoint and recreate its + locations. */ + +static void breakpoint_re_set_default (struct breakpoint *b) { int found; @@ -11471,129 +11810,11 @@ breakpoint_re_set_one (void *bint) { /* Get past catch_errs. */ struct breakpoint *b = (struct breakpoint *) bint; + struct cleanup *cleanups; - 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: - warning (_("attempted to reset apparently deleted breakpoint #%d?"), - b->number); - return 0; - case bp_breakpoint: - case bp_hardware_breakpoint: - case bp_tracepoint: - case bp_fast_tracepoint: - case bp_static_tracepoint: - case bp_gnu_ifunc_resolver: - /* Do not attempt to re-set breakpoints disabled during startup. */ - if (b->enable_state == bp_startup_disabled) - return 0; - - if (b->addr_string == NULL) - { - /* Anything without a string can't be re-set. */ - delete_breakpoint (b); - return 0; - } - - { - struct cleanup *cleanups; - - cleanups = prepare_re_set_context (b); - breakpoint_re_set_default (b); - do_cleanups (cleanups); - } - break; - - case bp_watchpoint: - case bp_hardware_watchpoint: - case bp_read_watchpoint: - case bp_access_watchpoint: - /* Watchpoint can be either on expression using entirely global - variables, or it can be on local variables. - - Watchpoints of the first kind are never auto-deleted, and - even persist across program restarts. Since they can use - variables from shared libraries, we need to reparse - expression as libraries are loaded and unloaded. - - Watchpoints on local variables can also change meaning as - result of solib event. For example, if a watchpoint uses - both a local and a global variables in expression, it's a - local watchpoint, but unloading of a shared library will make - the expression invalid. This is not a very common use case, - but we still re-evaluate expression, to avoid surprises to - the user. - - Note that for local watchpoints, we re-evaluate it only if - watchpoints frame id is still valid. If it's not, it means - the watchpoint is out of scope and will be deleted soon. In - fact, I'm not sure we'll ever be called in this case. - - If a local watchpoint's frame id is still valid, then - b->exp_valid_block is likewise valid, and we can safely use it. - - Don't do anything about disabled watchpoints, since they will - be reevaluated again when enabled. */ - update_watchpoint (b, 1 /* reparse */); - break; - /* We needn't really do anything to reset these, since the mask - that requests them is unaffected by e.g., new libraries being - loaded. */ - case bp_catchpoint: - break; - - default: - printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type); - /* fall through */ - /* Delete overlay event and longjmp master breakpoints; they will be - reset later by breakpoint_re_set. */ - case bp_overlay_event: - case bp_longjmp_master: - case bp_std_terminate_master: - case bp_exception_master: - delete_breakpoint (b); - break; - - /* This breakpoint is special, it's set up when the inferior - starts and we really don't want to touch it. */ - case bp_shlib_event: - - /* Like bp_shlib_event, this breakpoint type is special. - Once it is set up, we do not want to touch it. */ - case bp_thread_event: - - /* Keep temporary breakpoints, which can be encountered when we - step over a dlopen call and SOLIB_ADD is resetting the - breakpoints. Otherwise these should have been blown away via - the cleanup chain or by breakpoint_init_inferior when we - rerun the executable. */ - case bp_until: - case bp_finish: - case bp_watchpoint_scope: - case bp_call_dummy: - case bp_std_terminate: - case bp_step_resume: - case bp_hp_step_resume: - case bp_longjmp: - case bp_longjmp_resume: - case bp_exception: - case bp_exception_resume: - case bp_jit_event: - case bp_gnu_ifunc_resolver_return: - break; - } - + cleanups = prepare_re_set_context (b); + b->ops->re_set (b); + do_cleanups (cleanups); return 0; } @@ -12345,7 +12566,7 @@ trace_command (char *arg, int from_tty) bp_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, 0 /* internal */)) @@ -12362,7 +12583,7 @@ ftrace_command (char *arg, int from_tty) bp_fast_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, 0 /* internal */)) @@ -12381,7 +12602,7 @@ strace_command (char *arg, int from_tty) bp_static_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, 0 /* internal */)) @@ -12446,7 +12667,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) utp->type /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, 0 /* from_tty */, utp->enabled /* enabled */, 0 /* internal */)) @@ -12772,49 +12993,7 @@ save_breakpoints (char *filename, int from_tty, if (filter && !filter (tp)) continue; - if (tp->ops != NULL && tp->ops->print_recreate != NULL) - (tp->ops->print_recreate) (tp, fp); - else - { - if (tp->type == bp_fast_tracepoint) - fprintf_unfiltered (fp, "ftrace"); - if (tp->type == bp_static_tracepoint) - fprintf_unfiltered (fp, "strace"); - else if (tp->type == bp_tracepoint) - fprintf_unfiltered (fp, "trace"); - else if (tp->type == bp_breakpoint && tp->disposition == disp_del) - fprintf_unfiltered (fp, "tbreak"); - else if (tp->type == bp_breakpoint) - fprintf_unfiltered (fp, "break"); - else if (tp->type == bp_hardware_breakpoint - && tp->disposition == disp_del) - fprintf_unfiltered (fp, "thbreak"); - else if (tp->type == bp_hardware_breakpoint) - fprintf_unfiltered (fp, "hbreak"); - else if (tp->type == bp_watchpoint) - fprintf_unfiltered (fp, "watch"); - else if (tp->type == bp_hardware_watchpoint) - fprintf_unfiltered (fp, "watch"); - else if (tp->type == bp_read_watchpoint) - fprintf_unfiltered (fp, "rwatch"); - else if (tp->type == bp_access_watchpoint) - fprintf_unfiltered (fp, "awatch"); - else - internal_error (__FILE__, __LINE__, - _("unhandled breakpoint type %d"), (int) tp->type); - - if (tp->exp_string) - fprintf_unfiltered (fp, " %s", tp->exp_string); - else if (tp->addr_string) - fprintf_unfiltered (fp, " %s", tp->addr_string); - else - { - char tmp[40]; - - sprintf_vma (tmp, tp->loc->address); - fprintf_unfiltered (fp, " *0x%s", tmp); - } - } + tp->ops->print_recreate (tp, fp); if (tp->thread != -1) fprintf_unfiltered (fp, " thread %d", tp->thread); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 6fca479..28fdd4e 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -422,8 +422,8 @@ struct breakpoint_ops 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. */ + Return 0 for success, 1 if the breakpoint, watchpoint or + catchpoint type is not supported, -1 for failure. */ int (*insert_location) (struct bp_location *); /* Remove the breakpoint/catchpoint that was previously inserted @@ -454,7 +454,7 @@ struct breakpoint_ops /* The normal print routine for this breakpoint, called when we hit it. */ - enum print_stop_action (*print_it) (struct breakpoint *); + enum print_stop_action (*print_it) (struct bpstats *bs); /* Display information about this breakpoint, for "info breakpoints". */ @@ -801,9 +801,19 @@ struct bpstat_what print_it_done, print_it_noop. */ enum print_stop_action { + /* We printed nothing or we need to do some more analysis. */ PRINT_UNKNOWN = -1, + + /* We printed something, and we *do* desire that something to be + followed by a location. */ PRINT_SRC_AND_LOC, + + /* We printed something, and we do *not* desire that something to + be followed by a location. */ PRINT_SRC_ONLY, + + /* We already printed all we needed to print, don't print anything + else. */ PRINT_NOTHING }; @@ -980,12 +990,6 @@ 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); @@ -1025,6 +1029,32 @@ extern void awatch_command_wrapper (char *, int, int); extern void rwatch_command_wrapper (char *, int, int); extern void tbreak_command (char *, int); +extern void null_re_set (struct breakpoint *b); +extern int null_works_in_software_mode (const struct breakpoint *b); +extern int null_resources_needed (const struct bp_location *bl); +extern void null_check_status (bpstat bs); +extern void null_print_one_detail (const struct breakpoint *self, + struct ui_out *uiout); + +extern struct breakpoint_ops bkpt_breakpoint_ops; + +extern void bkpt_dtor (struct breakpoint *self); +extern struct bp_location *bkpt_allocate_location (struct breakpoint *self); +extern void bkpt_re_set (struct breakpoint *b); +extern int bkpt_insert_location (struct bp_location *bl); +extern int bkpt_remove_location (struct bp_location *bl); +extern int bkpt_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR bp_addr); +extern void bkpt_check_status (bpstat bs); +extern int bkpt_resources_needed (const struct bp_location *bl); +extern int bkpt_works_in_software_mode (const struct breakpoint *b); +extern enum print_stop_action bkpt_print_it (bpstat bs); +extern void null_print_one_detail (const struct breakpoint *self, + struct ui_out *uiout); +extern void bkpt_print_mention (struct breakpoint *b); +extern void bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp); + /* Arguments to pass as context to some catch command handlers. */ #define CATCH_PERMANENT ((void *) (uintptr_t) 0) #define CATCH_TEMPORARY ((void *) (uintptr_t) 1) diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index d68a033..b012159 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -169,7 +169,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc) temp_p, type_wanted, ignore_count, pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, - NULL, 0, enabled, 0); + &bkpt_breakpoint_ops, 0, enabled, 0); do_cleanups (back_to); } diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 294e648..c278cac 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -636,7 +636,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) 0, bp_breakpoint, 0, AUTO_BOOLEAN_TRUE, - NULL, 0, 1, internal_bp); + &bkpt_breakpoint_ops, + 0, 1, internal_bp); break; } case bp_watchpoint: |