diff options
author | Vladimir Prus <vladimir@codesourcery.com> | 2008-04-24 12:56:45 +0000 |
---|---|---|
committer | Vladimir Prus <vladimir@codesourcery.com> | 2008-04-24 12:56:45 +0000 |
commit | 18a1839349df0a60254542ab16bc5e299d9bfaeb (patch) | |
tree | 7d68644b1ba3642161d5d24f0198621fc519a88e /gdb | |
parent | 721c02def4f29758e8e63baf1276719e1b56d988 (diff) | |
download | gdb-18a1839349df0a60254542ab16bc5e299d9bfaeb.zip gdb-18a1839349df0a60254542ab16bc5e299d9bfaeb.tar.gz gdb-18a1839349df0a60254542ab16bc5e299d9bfaeb.tar.bz2 |
* breakpoint.c (bpstat_check_location)
(bpstat_check_watchpoint, bpstat_check_breakpoint_conditions):
New, extracted from bpstat_stop_status.
(bpstat_stop_status): Use the above.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/breakpoint.c | 513 |
2 files changed, 283 insertions, 239 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cb717d6..69f0d23 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,12 @@ 2008-04-24 Vladimir Prus <vladimir@codesourcery.com> - + + * breakpoint.c (bpstat_check_location) + (bpstat_check_watchpoint, bpstat_check_breakpoint_conditions): + New, extracted from bpstat_stop_status. + (bpstat_stop_status): Use the above. + +2008-04-24 Vladimir Prus <vladimir@codesourcery.com> + * mi/mi-main.c (last_async_command): Rename to current_token. (previous_async_command): Remove. (mi_cmd_gdb_exit): Adjust. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 2b6e16f..e3fa8f1 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2750,6 +2750,252 @@ 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. */ +static int +bpstat_check_location (const struct bp_location *bl, CORE_ADDR bp_addr) +{ + struct breakpoint *b = bl->owner; + + if (b->type != bp_watchpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint + && b->type != bp_hardware_breakpoint + && b->type != bp_catch_fork + && b->type != bp_catch_vfork + && b->type != bp_catch_exec) /* a non-watchpoint bp */ + { + if (bl->address != bp_addr) /* address doesn't match */ + 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 ((b->type == bp_hardware_watchpoint + || b->type == bp_read_watchpoint + || b->type == bp_access_watchpoint) + && 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; + } + + /* Is this a catchpoint of a load or unload? If so, did we + get a load or unload of the specified library? If not, + ignore it. */ + if ((b->type == bp_catch_load) +#if defined(SOLIB_HAVE_LOAD_EVENT) + && (!SOLIB_HAVE_LOAD_EVENT (PIDGET (inferior_ptid)) + || ((b->dll_pathname != NULL) + && (strcmp (b->dll_pathname, + SOLIB_LOADED_LIBRARY_PATHNAME ( + PIDGET (inferior_ptid))) + != 0))) +#endif + ) + return 0; + + if ((b->type == bp_catch_unload) +#if defined(SOLIB_HAVE_UNLOAD_EVENT) + && (!SOLIB_HAVE_UNLOAD_EVENT (PIDGET (inferior_ptid)) + || ((b->dll_pathname != NULL) + && (strcmp (b->dll_pathname, + SOLIB_UNLOADED_LIBRARY_PATHNAME ( + PIDGET (inferior_ptid))) + != 0))) +#endif + ) + return 0; + + if ((b->type == bp_catch_fork) + && !inferior_has_forked (PIDGET (inferior_ptid), + &b->forked_inferior_pid)) + return 0; + + if ((b->type == bp_catch_vfork) + && !inferior_has_vforked (PIDGET (inferior_ptid), + &b->forked_inferior_pid)) + return 0; + + if ((b->type == bp_catch_exec) + && !inferior_has_execd (PIDGET (inferior_ptid), &b->exec_pathname)) + return 0; + + return 1; +} + +/* If BS refers to a watchpoint, determine if the watched values + has actually changed, and we should stop. If not, set BS->stop + to 0. */ +static void +bpstat_check_watchpoint (bpstat bs) +{ + const struct bp_location *bl = bs->breakpoint_at; + struct breakpoint *b = bl->owner; + + if (b->type == bp_watchpoint + || b->type == bp_read_watchpoint + || b->type == bp_access_watchpoint + || b->type == bp_hardware_watchpoint) + { + CORE_ADDR addr; + struct value *v; + int must_check_value = 0; + + if (b->type == bp_watchpoint) + /* For a software watchpoint, we must always check the + watched value. */ + must_check_value = 1; + else if (b->watchpoint_triggered == watch_triggered_yes) + /* We have a hardware watchpoint (read, write, or access) + and the target earlier reported an address watched by + this watchpoint. */ + must_check_value = 1; + else if (b->watchpoint_triggered == watch_triggered_unknown + && b->type == bp_hardware_watchpoint) + /* We were stopped by a hardware watchpoint, but the target could + not report the data address. We must check the watchpoint's + value. Access and read watchpoints are out of luck; without + a data address, we can't figure it out. */ + must_check_value = 1; + + if (must_check_value) + { + char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", + b->number); + struct cleanup *cleanups = make_cleanup (xfree, message); + int e = catch_errors (watchpoint_check, bs, message, + RETURN_MASK_ALL); + do_cleanups (cleanups); + switch (e) + { + case WP_DELETED: + /* We've already printed what needs to be printed. */ + bs->print_it = print_it_done; + /* Stop. */ + break; + case WP_VALUE_CHANGED: + if (b->type == bp_read_watchpoint) + { + /* Don't stop: read watchpoints shouldn't fire if + the value has changed. This is for targets + which cannot set read-only watchpoints. */ + bs->print_it = print_it_noop; + bs->stop = 0; + } + break; + case WP_VALUE_NOT_CHANGED: + if (b->type == bp_hardware_watchpoint + || b->type == bp_watchpoint) + { + /* Don't stop: write watchpoints shouldn't fire if + the value hasn't changed. */ + bs->print_it = print_it_noop; + bs->stop = 0; + } + /* Stop. */ + break; + default: + /* Can't happen. */ + case 0: + /* Error from catch_errors. */ + printf_filtered (_("Watchpoint %d deleted.\n"), b->number); + if (b->related_breakpoint) + b->related_breakpoint->disposition = disp_del_at_next_stop; + b->disposition = disp_del_at_next_stop; + /* We've already printed what needs to be printed. */ + bs->print_it = print_it_done; + break; + } + } + else /* must_check_value == 0 */ + { + /* This is a case where some watchpoint(s) triggered, but + not at the address of this watchpoint, or else no + watchpoint triggered after all. So don't print + anything for this watchpoint. */ + bs->print_it = print_it_noop; + bs->stop = 0; + } + } +} + + +/* Check conditions (condition proper, frame, thread and ignore count) + of breakpoint referred to by BS. If we should not stop for this + breakpoint, set BS->stop to 0. */ +static void +bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) +{ + int thread_id = pid_to_thread_id (ptid); + const struct bp_location *bl = bs->breakpoint_at; + struct breakpoint *b = bl->owner; + + if (frame_id_p (b->frame_id) + && !frame_id_eq (b->frame_id, get_frame_id (get_current_frame ()))) + bs->stop = 0; + else if (bs->stop) + { + int value_is_zero = 0; + + /* If this is a scope breakpoint, mark the associated + watchpoint as triggered so that we will handle the + out-of-scope event. We'll get to the watchpoint next + iteration. */ + if (b->type == bp_watchpoint_scope) + b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; + + if (bl->cond && bl->owner->disposition != disp_del_at_next_stop) + { + /* Need to select the frame, with all that implies + so that the conditions will have the right context. */ + select_frame (get_current_frame ()); + value_is_zero + = catch_errors (breakpoint_cond_eval, (bl->cond), + "Error in testing breakpoint condition:\n", + RETURN_MASK_ALL); + /* FIXME-someday, should give breakpoint # */ + free_all_values (); + } + if (bl->cond && value_is_zero) + { + bs->stop = 0; + } + else if (b->thread != -1 && b->thread != thread_id) + { + bs->stop = 0; + } + else if (b->ignore_count > 0) + { + b->ignore_count--; + annotate_ignore_count_change (); + bs->stop = 0; + /* Increase the hit count even though we don't + stop. */ + ++(b->hit_count); + } + } +} + + /* Get a bpstat associated with having just stopped at address BP_ADDR in thread PTID. @@ -2776,7 +3022,6 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid) struct bpstats root_bs[1]; /* Pointer to the last thing in the chain currently. */ bpstat bs = root_bs; - int thread_id = pid_to_thread_id (ptid); ALL_BP_LOCATIONS (bl) { @@ -2785,87 +3030,6 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid) if (!breakpoint_enabled (b) && b->enable_state != bp_permanent) continue; - if (b->type != bp_watchpoint - && b->type != bp_hardware_watchpoint - && b->type != bp_read_watchpoint - && b->type != bp_access_watchpoint - && b->type != bp_hardware_breakpoint - && b->type != bp_catch_fork - && b->type != bp_catch_vfork - && b->type != bp_catch_exec) /* a non-watchpoint bp */ - { - if (bl->address != bp_addr) /* address doesn't match */ - continue; - if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - continue; - } - - /* 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 ((b->type == bp_hardware_watchpoint - || b->type == bp_read_watchpoint - || b->type == bp_access_watchpoint) - && b->watchpoint_triggered == watch_triggered_no) - continue; - - if (b->type == bp_hardware_breakpoint) - { - if (bl->address != bp_addr) - continue; - if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - continue; - } - - /* Is this a catchpoint of a load or unload? If so, did we - get a load or unload of the specified library? If not, - ignore it. */ - if ((b->type == bp_catch_load) -#if defined(SOLIB_HAVE_LOAD_EVENT) - && (!SOLIB_HAVE_LOAD_EVENT (PIDGET (inferior_ptid)) - || ((b->dll_pathname != NULL) - && (strcmp (b->dll_pathname, - SOLIB_LOADED_LIBRARY_PATHNAME ( - PIDGET (inferior_ptid))) - != 0))) -#endif - ) - continue; - - if ((b->type == bp_catch_unload) -#if defined(SOLIB_HAVE_UNLOAD_EVENT) - && (!SOLIB_HAVE_UNLOAD_EVENT (PIDGET (inferior_ptid)) - || ((b->dll_pathname != NULL) - && (strcmp (b->dll_pathname, - SOLIB_UNLOADED_LIBRARY_PATHNAME ( - PIDGET (inferior_ptid))) - != 0))) -#endif - ) - continue; - - if ((b->type == bp_catch_fork) - && !inferior_has_forked (PIDGET (inferior_ptid), - &b->forked_inferior_pid)) - continue; - - if ((b->type == bp_catch_vfork) - && !inferior_has_vforked (PIDGET (inferior_ptid), - &b->forked_inferior_pid)) - continue; - - if ((b->type == bp_catch_exec) - && !inferior_has_execd (PIDGET (inferior_ptid), &b->exec_pathname)) - continue; - /* For hardware watchpoints, we look only at the first location. The watchpoint_check function will work on entire expression, not the individual locations. For read watchopints, the @@ -2875,179 +3039,52 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid) if (b->type == bp_hardware_watchpoint && bl != b->loc) continue; + if (!bpstat_check_location (bl, bp_addr)) + continue; + /* Come here if it's a watchpoint, or if the break address matches */ bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */ - /* Watchpoints may change this, if not found to have triggered. */ + /* Assume we stop. Should we find watchpoint that is not actually + triggered, or if condition of breakpoint is false, we'll reset + 'stop' to 0. */ bs->stop = 1; bs->print = 1; - if (b->type == bp_watchpoint - || b->type == bp_read_watchpoint - || b->type == bp_access_watchpoint - || b->type == bp_hardware_watchpoint) - { - CORE_ADDR addr; - struct value *v; - int must_check_value = 0; - - if (b->type == bp_watchpoint) - /* For a software watchpoint, we must always check the - watched value. */ - must_check_value = 1; - else if (b->watchpoint_triggered == watch_triggered_yes) - /* We have a hardware watchpoint (read, write, or access) - and the target earlier reported an address watched by - this watchpoint. */ - must_check_value = 1; - else if (b->watchpoint_triggered == watch_triggered_unknown - && b->type == bp_hardware_watchpoint) - /* We were stopped by a hardware watchpoint, but the target could - not report the data address. We must check the watchpoint's - value. Access and read watchpoints are out of luck; without - a data address, we can't figure it out. */ - must_check_value = 1; - - if (must_check_value) - { - char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", - b->number); - struct cleanup *cleanups = make_cleanup (xfree, message); - int e = catch_errors (watchpoint_check, bs, message, - RETURN_MASK_ALL); - do_cleanups (cleanups); - switch (e) - { - case WP_DELETED: - /* We've already printed what needs to be printed. */ - bs->print_it = print_it_done; - /* Stop. */ - break; - case WP_VALUE_CHANGED: - if (b->type == bp_read_watchpoint) - { - /* Don't stop: read watchpoints shouldn't fire if - the value has changed. This is for targets - which cannot set read-only watchpoints. */ - bs->print_it = print_it_noop; - bs->stop = 0; - continue; - } - ++(b->hit_count); - break; - case WP_VALUE_NOT_CHANGED: - if (b->type == bp_hardware_watchpoint - || b->type == bp_watchpoint) - { - /* Don't stop: write watchpoints shouldn't fire if - the value hasn't changed. */ - bs->print_it = print_it_noop; - bs->stop = 0; - continue; - } - /* Stop. */ - ++(b->hit_count); - break; - default: - /* Can't happen. */ - case 0: - /* Error from catch_errors. */ - printf_filtered (_("Watchpoint %d deleted.\n"), b->number); - if (b->related_breakpoint) - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->disposition = disp_del_at_next_stop; - /* We've already printed what needs to be printed. */ - bs->print_it = print_it_done; - break; - } - } - else /* must_check_value == 0 */ - { - /* This is a case where some watchpoint(s) triggered, but - not at the address of this watchpoint, or else no - watchpoint triggered after all. So don't print - anything for this watchpoint. */ - bs->print_it = print_it_noop; - bs->stop = 0; - continue; - } - } - else - { - /* By definition, an encountered breakpoint is a triggered - breakpoint. */ - ++(b->hit_count); - } + bpstat_check_watchpoint (bs); + if (!bs->stop) + continue; - if (frame_id_p (b->frame_id) - && !frame_id_eq (b->frame_id, get_frame_id (get_current_frame ()))) + if (b->type == bp_thread_event || b->type == bp_overlay_event) + /* We do not stop for these. */ bs->stop = 0; else + bpstat_check_breakpoint_conditions (bs, ptid); + + if (bs->stop) { - int value_is_zero = 0; - - /* If this is a scope breakpoint, mark the associated - watchpoint as triggered so that we will handle the - out-of-scope event. We'll get to the watchpoint next - iteration. */ - if (b->type == bp_watchpoint_scope) - b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; + ++(b->hit_count); - if (bl->cond && bl->owner->disposition != disp_del_at_next_stop) - { - /* Need to select the frame, with all that implies - so that the conditions will have the right context. */ - select_frame (get_current_frame ()); - value_is_zero - = catch_errors (breakpoint_cond_eval, (bl->cond), - "Error in testing breakpoint condition:\n", - RETURN_MASK_ALL); - /* FIXME-someday, should give breakpoint # */ - free_all_values (); - } - if (bl->cond && value_is_zero) - { - bs->stop = 0; - /* Don't consider this a hit. */ - --(b->hit_count); - } - else if (b->thread != -1 && b->thread != thread_id) + /* We will stop here */ + if (b->disposition == disp_disable) { - bs->stop = 0; - /* Don't consider this a hit. */ - --(b->hit_count); + b->enable_state = bp_disabled; + update_global_location_list (); } - else if (b->ignore_count > 0) + if (b->silent) + bs->print = 0; + bs->commands = b->commands; + if (bs->commands && + (strcmp ("silent", bs->commands->line) == 0 + || (xdb_commands && strcmp ("Q", bs->commands->line) == 0))) { - b->ignore_count--; - annotate_ignore_count_change (); - bs->stop = 0; - } - else if (b->type == bp_thread_event || b->type == bp_overlay_event) - /* We do not stop for these. */ - bs->stop = 0; - else - { - /* We will stop here */ - if (b->disposition == disp_disable) - { - b->enable_state = bp_disabled; - update_global_location_list (); - } - if (b->silent) - bs->print = 0; - bs->commands = b->commands; - if (bs->commands && - (strcmp ("silent", bs->commands->line) == 0 - || (xdb_commands && strcmp ("Q", bs->commands->line) == 0))) - { - bs->commands = bs->commands->next; - bs->print = 0; - } - bs->commands = copy_command_lines (bs->commands); + bs->commands = bs->commands->next; + bs->print = 0; } + bs->commands = copy_command_lines (bs->commands); } + /* Print nothing for this entry if we dont stop or if we dont print. */ if (bs->stop == 0 || bs->print == 0) bs->print_it = print_it_noop; |