* 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.
This commit is contained in:
Jeff Law 1996-05-02 18:43:28 +00:00
parent d124785e82
commit e51481f967
3 changed files with 179 additions and 81 deletions

View file

@ -1,3 +1,17 @@
Thu May 2 12:46:14 1996 Jeffrey A Law (law@cygnus.com)
* 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.
Wed May 1 17:29:18 1996 Fred Fish <fnf@cygnus.com> Wed May 1 17:29:18 1996 Fred Fish <fnf@cygnus.com>
* Makefile.in (rs6000-nat.o): Dependant on xcoffsolib.h. * Makefile.in (rs6000-nat.o): Dependant on xcoffsolib.h.

View file

@ -574,8 +574,12 @@ insert_breakpoints ()
Hardware watchpoint %d deleted because the program has left the block in\n\ Hardware watchpoint %d deleted because the program has left the block in\n\
which its expression is valid.\n", b->number); which its expression is valid.\n", b->number);
if (b->related_breakpoint) 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. */ /* Restore the frame and level. */
@ -691,21 +695,32 @@ breakpoint_init_inferior ()
{ {
b->inserted = 0; b->inserted = 0;
switch (b->type)
{
case bp_call_dummy:
case bp_watchpoint_scope:
/* If the call dummy breakpoint is at the entry point it will /* If the call dummy breakpoint is at the entry point it will
cause problems when the inferior is rerun, so we better cause problems when the inferior is rerun, so we better
get rid of it. */ get rid of it.
if (b->type == bp_call_dummy)
delete_breakpoint (b);
/* Likewise for scope breakpoints. */ Also get rid of scope breakpoints. */
if (b->type == bp_watchpoint_scope)
delete_breakpoint (b); 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. */ /* Likewise for watchpoints on local expressions. */
if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint || if (b->exp_valid_block != NULL)
b->type == bp_read_watchpoint || b->type == bp_access_watchpoint)
&& b->exp_valid_block != NULL)
delete_breakpoint (b); 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\ Watchpoint %d deleted because the program has left the block in\n\
which its expression is valid.\n", bs->breakpoint_at->number); which its expression is valid.\n", bs->breakpoint_at->number);
if (b->related_breakpoint) 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; return WP_DELETED;
} }
@ -1280,8 +1299,12 @@ bpstat_stop_status (pc, not_a_breakpoint)
/* Error from catch_errors. */ /* Error from catch_errors. */
printf_filtered ("Watchpoint %d deleted.\n", b->number); printf_filtered ("Watchpoint %d deleted.\n", b->number);
if (b->related_breakpoint) 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. */ /* We've already printed what needs to be printed. */
bs->print_it = print_it_done; bs->print_it = print_it_done;
@ -1327,8 +1350,12 @@ bpstat_stop_status (pc, not_a_breakpoint)
/* Error from catch_errors. */ /* Error from catch_errors. */
printf_filtered ("Watchpoint %d deleted.\n", b->number); printf_filtered ("Watchpoint %d deleted.\n", b->number);
if (b->related_breakpoint) 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. */ /* We've already printed what needs to be printed. */
bs->print_it = print_it_done; bs->print_it = print_it_done;
break; break;
@ -1638,7 +1665,7 @@ breakpoint_1 (bnum, allflag)
"sigtramp", "sigtramp",
"watchpoint scope", "call dummy", "watchpoint scope", "call dummy",
"shlib events" }; "shlib events" };
static char *bpdisps[] = {"del", "dis", "keep"}; static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
static char bpenables[] = "ny"; static char bpenables[] = "ny";
char wrap_indent[80]; char wrap_indent[80];
@ -3231,17 +3258,26 @@ clear_command (arg, from_tty)
free ((PTR)sals.sals); 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. */ This is called after any breakpoint is hit, or after errors. */
void void
breakpoint_auto_delete (bs) breakpoint_auto_delete (bs)
bpstat bs; bpstat bs;
{ {
struct breakpoint *b, *temp;
for (; bs; bs = bs->next) for (; bs; bs = bs->next)
if (bs->breakpoint_at && bs->breakpoint_at->disposition == del if (bs->breakpoint_at && bs->breakpoint_at->disposition == del
&& bs->stop) && bs->stop)
delete_breakpoint (bs->breakpoint_at); 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. */ /* Delete a breakpoint and clean up all traces of it in the data structures. */

View file

@ -1,5 +1,5 @@
/* Data structures associated with breakpoints in GDB. /* Data structures associated with breakpoints in GDB.
Copyright (C) 1992 Free Software Foundation, Inc. Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GDB. This file is part of GDB.
@ -15,7 +15,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (BREAKPOINT_H) #if !defined (BREAKPOINT_H)
#define BREAKPOINT_H 1 #define BREAKPOINT_H 1
@ -39,9 +39,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
enum bptype { enum bptype {
bp_breakpoint, /* Normal breakpoint */ bp_breakpoint, /* Normal breakpoint */
bp_hardware_breakpoint, /* Hardware assisted breakpoint */
bp_until, /* used by until command */ bp_until, /* used by until command */
bp_finish, /* used by finish command */ bp_finish, /* used by finish command */
bp_watchpoint, /* Watchpoint */ bp_watchpoint, /* Watchpoint */
bp_hardware_watchpoint, /* Hardware assisted watchpoint */
bp_read_watchpoint, /* read watchpoint, (hardware assisted) */
bp_access_watchpoint, /* access watchpoint, (hardware assisted) */
bp_longjmp, /* secret breakpoint to find longjmp() */ bp_longjmp, /* secret breakpoint to find longjmp() */
bp_longjmp_resume, /* secret breakpoint to escape longjmp() */ bp_longjmp_resume, /* secret breakpoint to escape longjmp() */
@ -52,6 +56,20 @@ enum bptype {
/* Used by wait_for_inferior for stepping over signal handlers. */ /* Used by wait_for_inferior for stepping over signal handlers. */
bp_through_sigtramp, bp_through_sigtramp,
/* Used to detect when a watchpoint expression has gone out of
scope. These breakpoints are usually not visible to the user.
This breakpoint has some interesting properties:
1) There's always a 1:1 mapping between watchpoints
on local variables and watchpoint_scope breakpoints.
2) It automatically deletes itself and the watchpoint it's
associated with when hit.
3) It can never be disabled. */
bp_watchpoint_scope,
/* The breakpoint at the end of a call dummy. */ /* The breakpoint at the end of a call dummy. */
/* FIXME: What if the function we are calling longjmp()s out of the /* FIXME: What if the function we are calling longjmp()s out of the
call, or the user gets out with the "return" command? We currently call, or the user gets out with the "return" command? We currently
@ -59,17 +77,28 @@ enum bptype {
(Probably can solve this by noticing longjmp, "return", etc., it's (Probably can solve this by noticing longjmp, "return", etc., it's
similar to noticing when a watchpoint on a local variable goes out similar to noticing when a watchpoint on a local variable goes out
of scope (with hardware support for watchpoints)). */ of scope (with hardware support for watchpoints)). */
bp_call_dummy bp_call_dummy,
/* Some dynamic linkers (HP, maybe Solaris) can arrange for special
code in the inferior to run when significant events occur in the
dynamic linker (for example a library is loaded or unloaded).
By placing a breakpoint in this magic code GDB will get control
when these significant events occur. GDB can then re-examine
the dynamic linker's data structures to discover any newly loaded
dynamic libraries. */
bp_shlib_event
}; };
/* States of enablement of breakpoint. */ /* States of enablement of breakpoint. */
enum enable { disabled, enabled}; enum enable { disabled, enabled, shlib_disabled};
/* Disposition of breakpoint. Ie: what to do after hitting it. */ /* Disposition of breakpoint. Ie: what to do after hitting it. */
enum bpdisp { enum bpdisp {
delete, /* Delete it */ del, /* Delete it */
del_at_next_stop, /* Delete at next stop, whether hit or not */
disable, /* Disable it */ disable, /* Disable it */
donttouch /* Leave it alone */ donttouch /* Leave it alone */
}; };
@ -128,13 +157,17 @@ struct breakpoint
struct command_line *commands; struct command_line *commands;
/* Stack depth (address of frame). If nonzero, break only if fp /* Stack depth (address of frame). If nonzero, break only if fp
equals this. */ equals this. */
FRAME_ADDR frame; CORE_ADDR frame;
/* Conditional. Break only if this expression's value is nonzero. */ /* Conditional. Break only if this expression's value is nonzero. */
struct expression *cond; struct expression *cond;
/* String we used to set the breakpoint (malloc'd). Only matters if /* String we used to set the breakpoint (malloc'd). Only matters if
address is non-NULL. */ address is non-NULL. */
char *addr_string; char *addr_string;
/* Language we used to set the breakpoint. */
enum language language;
/* Input radix we used to set the breakpoint. */
int input_radix;
/* String form of the breakpoint condition (malloc'd), or NULL if there /* String form of the breakpoint condition (malloc'd), or NULL if there
is no condition. */ is no condition. */
char *cond_string; char *cond_string;
@ -147,16 +180,38 @@ struct breakpoint
valid anywhere (e.g. consists just of global symbols). */ valid anywhere (e.g. consists just of global symbols). */
struct block *exp_valid_block; struct block *exp_valid_block;
/* Value of the watchpoint the last time we checked it. */ /* Value of the watchpoint the last time we checked it. */
value val; value_ptr val;
/* Holds the value chain for a hardware watchpoint expression. */
value_ptr val_chain;
/* Holds the address of the related watchpoint_scope breakpoint
when using watchpoints on local variables (might the concept
of a related breakpoint be useful elsewhere, if not just call
it the watchpoint_scope breakpoint or something like that. FIXME). */
struct breakpoint *related_breakpoint;
/* Holds the frame address which identifies the frame this watchpoint
should be evaluated in, or NULL if the watchpoint should be evaluated
on the outermost frame. */
CORE_ADDR watchpoint_frame;
/* Thread number for thread-specific breakpoint, or -1 if don't care */ /* Thread number for thread-specific breakpoint, or -1 if don't care */
int thread; int thread;
/* Count of the number of times this breakpoint was taken, dumped
with the info, but not used for anything else. Useful for
seeing how many times you hit a break prior to the program
aborting, so you can back up to just before the abort. */
int hit_count;
}; };
/* The following stuff is an abstract data type "bpstat" ("breakpoint status"). /* The following stuff is an abstract data type "bpstat" ("breakpoint status").
This provides the ability to determine whether we have stopped at a This provides the ability to determine whether we have stopped at a
breakpoint, and what we should do about it. */ breakpoint, and what we should do about it. */
typedef struct bpstat *bpstat; typedef struct bpstats *bpstat;
/* Interface: */ /* Interface: */
/* Clear a bpstat so that it says we are not at any breakpoint. /* Clear a bpstat so that it says we are not at any breakpoint.
@ -167,8 +222,7 @@ extern void bpstat_clear PARAMS ((bpstat *));
is part of the bpstat is copied as well. */ is part of the bpstat is copied as well. */
extern bpstat bpstat_copy PARAMS ((bpstat)); extern bpstat bpstat_copy PARAMS ((bpstat));
/* FIXME: prototypes uses equivalence between FRAME_ADDR and CORE_ADDR */ extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, int));
extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, CORE_ADDR, int));
/* This bpstat_what stuff tells wait_for_inferior what to do with a /* This bpstat_what stuff tells wait_for_inferior what to do with a
breakpoint (a challenging task). */ breakpoint (a challenging task). */
@ -217,6 +271,10 @@ enum bpstat_what_main_action {
checking. */ checking. */
BPSTAT_WHAT_THROUGH_SIGTRAMP, BPSTAT_WHAT_THROUGH_SIGTRAMP,
/* Check the dynamic linker's data structures for new libraries, then
keep checking. */
BPSTAT_WHAT_CHECK_SHLIBS,
/* This is just used to keep track of how many enums there are. */ /* This is just used to keep track of how many enums there are. */
BPSTAT_WHAT_LAST BPSTAT_WHAT_LAST
}; };
@ -269,7 +327,7 @@ extern void bpstat_do_actions PARAMS ((bpstat *));
extern void bpstat_clear_actions PARAMS ((bpstat)); extern void bpstat_clear_actions PARAMS ((bpstat));
/* Implementation: */ /* Implementation: */
struct bpstat struct bpstats
{ {
/* Linked list because there can be two breakpoints at the /* Linked list because there can be two breakpoints at the
same place, and a bpstat reflects the fact that both have been hit. */ same place, and a bpstat reflects the fact that both have been hit. */
@ -279,7 +337,7 @@ struct bpstat
/* Commands left to be done. */ /* Commands left to be done. */
struct command_line *commands; struct command_line *commands;
/* Old value associated with a watchpoint. */ /* Old value associated with a watchpoint. */
value old_val; value_ptr old_val;
/* Nonzero if this breakpoint tells us to print the frame. */ /* Nonzero if this breakpoint tells us to print the frame. */
char print; char print;
@ -305,73 +363,63 @@ extern int frame_in_dummy PARAMS ((struct frame_info *));
extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int)); extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int));
extern void extern void until_break_command PARAMS ((char *, int));
until_break_command PARAMS ((char *, int));
extern void extern void breakpoint_re_set PARAMS ((void));
breakpoint_re_set PARAMS ((void));
extern void extern void clear_momentary_breakpoints PARAMS ((void));
clear_momentary_breakpoints PARAMS ((void));
/* FIXME: Prototype uses equivalence of "struct frame_info *" and FRAME */ extern struct breakpoint *set_momentary_breakpoint
extern struct breakpoint * PARAMS ((struct symtab_and_line, struct frame_info *, enum bptype));
set_momentary_breakpoint PARAMS ((struct symtab_and_line,
struct frame_info *,
enum bptype));
extern void extern void set_ignore_count PARAMS ((int, int, int));
set_ignore_count PARAMS ((int, int, int));
extern void extern void set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
extern void extern void mark_breakpoints_out PARAMS ((void));
mark_breakpoints_out PARAMS ((void));
extern void extern void breakpoint_init_inferior PARAMS ((void));
breakpoint_init_inferior PARAMS ((void));
extern void extern void delete_breakpoint PARAMS ((struct breakpoint *));
delete_breakpoint PARAMS ((struct breakpoint *));
extern void extern void breakpoint_auto_delete PARAMS ((bpstat));
breakpoint_auto_delete PARAMS ((bpstat));
extern void extern void breakpoint_clear_ignore_counts PARAMS ((void));
breakpoint_clear_ignore_counts PARAMS ((void));
extern void extern void break_command PARAMS ((char *, int));
break_command PARAMS ((char *, int));
extern int extern int insert_breakpoints PARAMS ((void));
insert_breakpoints PARAMS ((void));
extern int extern int remove_breakpoints PARAMS ((void));
remove_breakpoints PARAMS ((void));
extern void extern void enable_longjmp_breakpoint PARAMS ((void));
enable_longjmp_breakpoint PARAMS ((void));
extern void extern void disable_longjmp_breakpoint PARAMS ((void));
disable_longjmp_breakpoint PARAMS ((void));
extern void extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR,
set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR, FRAME)); struct frame_info *));
extern void clear_breakpoint_hit_counts PARAMS ((void));
/* The following are for displays, which aren't really breakpoints, but /* The following are for displays, which aren't really breakpoints, but
here is as good a place as any for them. */ here is as good a place as any for them. */
extern void extern void disable_current_display PARAMS ((void));
disable_current_display PARAMS ((void));
extern void extern void do_displays PARAMS ((void));
do_displays PARAMS ((void));
extern void extern void disable_display PARAMS ((int));
disable_display PARAMS ((int));
extern void extern void clear_displays PARAMS ((void));
clear_displays PARAMS ((void));
extern void disable_breakpoint PARAMS ((struct breakpoint *));
extern void enable_breakpoint PARAMS ((struct breakpoint *));
extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
extern void remove_solib_event_breakpoints PARAMS ((void));
extern void re_enable_breakpoints_in_shlibs PARAMS ((void));
#endif /* !defined (BREAKPOINT_H) */ #endif /* !defined (BREAKPOINT_H) */