diff options
author | Jeff Law <law@redhat.com> | 1996-05-02 18:43:28 +0000 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 1996-05-02 18:43:28 +0000 |
commit | e51481f96757303b0f4e7034de800b1fb5c87aa7 (patch) | |
tree | fb0d6dddf9d93cfa78d5dc241ee6293cc3a08081 /gdb/breakpoint.c | |
parent | d124785e82f44000d0dcfad95388c767a54b46d6 (diff) | |
download | gdb-e51481f96757303b0f4e7034de800b1fb5c87aa7.zip gdb-e51481f96757303b0f4e7034de800b1fb5c87aa7.tar.gz gdb-e51481f96757303b0f4e7034de800b1fb5c87aa7.tar.bz2 |
* From Peter Schauer:
* breakpoint.h (enum bpdisp): Add del_at_next_stop.
* breakpoint.c (insert_breakpoints, watchpoint_check,
bpstat_stop_status): Avoid bad references to memory freed via
delete_breakpoint on watchpoints going out of scope.
Do not delete these watchpoints, disable them and change their
disposition to del_at_next_stop instead.
(breakpoint_auto_delete): Delete all breakpoints whose disposition
is del_at_next_stop.
(breakpoint_init_inferior): Use switch to avoid reference to
already deleted breakpoint.
Fixes dangling pointer problems with watchpoints.
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index a921646..f01e685 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -574,8 +574,12 @@ insert_breakpoints () Hardware watchpoint %d deleted because the program has left the block in\n\ which its expression is valid.\n", b->number); if (b->related_breakpoint) - delete_breakpoint (b->related_breakpoint); - delete_breakpoint (b); + { + b->related_breakpoint->enable = disable; + b->related_breakpoint->disposition = del_at_next_stop; + } + b->enable = disable; + b->disposition = del_at_next_stop; } /* Restore the frame and level. */ @@ -691,21 +695,32 @@ breakpoint_init_inferior () { b->inserted = 0; - /* If the call dummy breakpoint is at the entry point it will - cause problems when the inferior is rerun, so we better - get rid of it. */ - if (b->type == bp_call_dummy) - delete_breakpoint (b); + switch (b->type) + { + case bp_call_dummy: + case bp_watchpoint_scope: - /* Likewise for scope breakpoints. */ - if (b->type == bp_watchpoint_scope) - delete_breakpoint (b); + /* If the call dummy breakpoint is at the entry point it will + cause problems when the inferior is rerun, so we better + get rid of it. - /* Likewise for watchpoints on local expressions. */ - if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint || - b->type == bp_read_watchpoint || b->type == bp_access_watchpoint) - && b->exp_valid_block != NULL) - delete_breakpoint (b); + Also get rid of scope breakpoints. */ + delete_breakpoint (b); + break; + + case bp_watchpoint: + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: + + /* Likewise for watchpoints on local expressions. */ + if (b->exp_valid_block != NULL) + delete_breakpoint (b); + break; + + default: + break; + } } } @@ -1151,8 +1166,12 @@ watchpoint_check (p) Watchpoint %d deleted because the program has left the block in\n\ which its expression is valid.\n", bs->breakpoint_at->number); if (b->related_breakpoint) - delete_breakpoint (b->related_breakpoint); - delete_breakpoint (b); + { + b->related_breakpoint->enable = disable; + b->related_breakpoint->disposition = del_at_next_stop; + } + b->enable = disable; + b->disposition = del_at_next_stop; return WP_DELETED; } @@ -1280,8 +1299,12 @@ bpstat_stop_status (pc, not_a_breakpoint) /* Error from catch_errors. */ printf_filtered ("Watchpoint %d deleted.\n", b->number); if (b->related_breakpoint) - delete_breakpoint (b->related_breakpoint); - delete_breakpoint (b); + { + b->related_breakpoint->enable = disable; + b->related_breakpoint->disposition = del_at_next_stop; + } + b->enable = disable; + b->disposition = del_at_next_stop; /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; @@ -1326,9 +1349,13 @@ bpstat_stop_status (pc, not_a_breakpoint) case 0: /* Error from catch_errors. */ printf_filtered ("Watchpoint %d deleted.\n", b->number); - if (b->related_breakpoint) - delete_breakpoint (b->related_breakpoint); - delete_breakpoint (b); + if (b->related_breakpoint) + { + b->related_breakpoint->enable = disable; + b->related_breakpoint->disposition = del_at_next_stop; + } + b->enable = disable; + b->disposition = del_at_next_stop; /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; break; @@ -1638,7 +1665,7 @@ breakpoint_1 (bnum, allflag) "sigtramp", "watchpoint scope", "call dummy", "shlib events" }; - static char *bpdisps[] = {"del", "dis", "keep"}; + static char *bpdisps[] = {"del", "dstp", "dis", "keep"}; static char bpenables[] = "ny"; char wrap_indent[80]; @@ -3231,17 +3258,26 @@ clear_command (arg, from_tty) free ((PTR)sals.sals); } -/* Delete breakpoint in BS if they are `delete' breakpoints. +/* Delete breakpoint in BS if they are `delete' breakpoints and + all breakpoints that are marked for deletion, whether hit or not. This is called after any breakpoint is hit, or after errors. */ void breakpoint_auto_delete (bs) bpstat bs; { + struct breakpoint *b, *temp; + for (; bs; bs = bs->next) if (bs->breakpoint_at && bs->breakpoint_at->disposition == del && bs->stop) delete_breakpoint (bs->breakpoint_at); + + ALL_BREAKPOINTS_SAFE (b, temp) + { + if (b->disposition == del_at_next_stop) + delete_breakpoint (b); + } } /* Delete a breakpoint and clean up all traces of it in the data structures. */ |