* 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>
* 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\
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. */

View File

@ -1,5 +1,5 @@
/* 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.
@ -15,7 +15,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
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)
#define BREAKPOINT_H 1
@ -39,9 +39,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
enum bptype {
bp_breakpoint, /* Normal breakpoint */
bp_hardware_breakpoint, /* Hardware assisted breakpoint */
bp_until, /* used by until command */
bp_finish, /* used by finish command */
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_resume, /* secret breakpoint to escape longjmp() */
@ -52,6 +56,20 @@ enum bptype {
/* Used by wait_for_inferior for stepping over signal handlers. */
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. */
/* 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
@ -59,17 +77,28 @@ enum bptype {
(Probably can solve this by noticing longjmp, "return", etc., it's
similar to noticing when a watchpoint on a local variable goes out
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. */
enum enable { disabled, enabled};
enum enable { disabled, enabled, shlib_disabled};
/* Disposition of breakpoint. Ie: what to do after hitting it. */
enum bpdisp {
delete, /* Delete it */
del, /* Delete it */
del_at_next_stop, /* Delete at next stop, whether hit or not */
disable, /* Disable it */
donttouch /* Leave it alone */
};
@ -128,13 +157,17 @@ struct breakpoint
struct command_line *commands;
/* Stack depth (address of frame). If nonzero, break only if fp
equals this. */
FRAME_ADDR frame;
CORE_ADDR frame;
/* Conditional. Break only if this expression's value is nonzero. */
struct expression *cond;
/* String we used to set the breakpoint (malloc'd). Only matters if
address is non-NULL. */
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
is no condition. */
char *cond_string;
@ -147,16 +180,38 @@ struct breakpoint
valid anywhere (e.g. consists just of global symbols). */
struct block *exp_valid_block;
/* 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 */
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").
This provides the ability to determine whether we have stopped at a
breakpoint, and what we should do about it. */
typedef struct bpstat *bpstat;
typedef struct bpstats *bpstat;
/* Interface: */
/* 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. */
extern bpstat bpstat_copy PARAMS ((bpstat));
/* FIXME: prototypes uses equivalence between FRAME_ADDR and CORE_ADDR */
extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, CORE_ADDR, int));
extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, int));
/* This bpstat_what stuff tells wait_for_inferior what to do with a
breakpoint (a challenging task). */
@ -217,6 +271,10 @@ enum bpstat_what_main_action {
checking. */
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. */
BPSTAT_WHAT_LAST
};
@ -269,7 +327,7 @@ extern void bpstat_do_actions PARAMS ((bpstat *));
extern void bpstat_clear_actions PARAMS ((bpstat));
/* Implementation: */
struct bpstat
struct bpstats
{
/* Linked list because there can be two breakpoints at the
same place, and a bpstat reflects the fact that both have been hit. */
@ -279,7 +337,7 @@ struct bpstat
/* Commands left to be done. */
struct command_line *commands;
/* Old value associated with a watchpoint. */
value old_val;
value_ptr old_val;
/* Nonzero if this breakpoint tells us to print the frame. */
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 void
until_break_command PARAMS ((char *, int));
extern void until_break_command PARAMS ((char *, int));
extern void
breakpoint_re_set PARAMS ((void));
extern void breakpoint_re_set PARAMS ((void));
extern void
clear_momentary_breakpoints PARAMS ((void));
extern void clear_momentary_breakpoints PARAMS ((void));
/* FIXME: Prototype uses equivalence of "struct frame_info *" and FRAME */
extern struct breakpoint *
set_momentary_breakpoint PARAMS ((struct symtab_and_line,
struct frame_info *,
enum bptype));
extern struct breakpoint *set_momentary_breakpoint
PARAMS ((struct symtab_and_line, struct frame_info *, enum bptype));
extern void
set_ignore_count PARAMS ((int, int, int));
extern void set_ignore_count PARAMS ((int, int, int));
extern void
set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
extern void set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
extern void
mark_breakpoints_out PARAMS ((void));
extern void mark_breakpoints_out PARAMS ((void));
extern void
breakpoint_init_inferior PARAMS ((void));
extern void breakpoint_init_inferior PARAMS ((void));
extern void
delete_breakpoint PARAMS ((struct breakpoint *));
extern void delete_breakpoint PARAMS ((struct breakpoint *));
extern void
breakpoint_auto_delete PARAMS ((bpstat));
extern void breakpoint_auto_delete PARAMS ((bpstat));
extern void
breakpoint_clear_ignore_counts PARAMS ((void));
extern void breakpoint_clear_ignore_counts PARAMS ((void));
extern void
break_command PARAMS ((char *, int));
extern void break_command PARAMS ((char *, int));
extern int
insert_breakpoints PARAMS ((void));
extern int insert_breakpoints PARAMS ((void));
extern int
remove_breakpoints PARAMS ((void));
extern int remove_breakpoints PARAMS ((void));
extern void
enable_longjmp_breakpoint PARAMS ((void));
extern void enable_longjmp_breakpoint PARAMS ((void));
extern void
disable_longjmp_breakpoint PARAMS ((void));
extern void disable_longjmp_breakpoint PARAMS ((void));
extern void
set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR, FRAME));
extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR,
struct frame_info *));
extern void clear_breakpoint_hit_counts PARAMS ((void));
/* The following are for displays, which aren't really breakpoints, but
here is as good a place as any for them. */
extern void
disable_current_display PARAMS ((void));
extern void disable_current_display PARAMS ((void));
extern void
do_displays PARAMS ((void));
extern void do_displays PARAMS ((void));
extern void
disable_display PARAMS ((int));
extern void disable_display PARAMS ((int));
extern void
clear_displays PARAMS ((void));
extern 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) */