aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1996-05-02 18:43:28 +0000
committerJeff Law <law@redhat.com>1996-05-02 18:43:28 +0000
commite51481f96757303b0f4e7034de800b1fb5c87aa7 (patch)
treefb0d6dddf9d93cfa78d5dc241ee6293cc3a08081
parentd124785e82f44000d0dcfad95388c767a54b46d6 (diff)
downloadgdb-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.
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/breakpoint.c84
-rw-r--r--gdb/breakpoint.h162
3 files changed, 179 insertions, 81 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6d143eb..c643aa1 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
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. */
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 5f45ccd..0aa42f5 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -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 disable_display PARAMS ((int));
+
+extern void clear_displays PARAMS ((void));
+
+extern void disable_breakpoint PARAMS ((struct breakpoint *));
+
+extern void enable_breakpoint PARAMS ((struct breakpoint *));
-extern void
-do_displays PARAMS ((void));
+extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
-extern void
-disable_display PARAMS ((int));
+extern void remove_solib_event_breakpoints PARAMS ((void));
-extern void
-clear_displays PARAMS ((void));
+extern void re_enable_breakpoints_in_shlibs PARAMS ((void));
#endif /* !defined (BREAKPOINT_H) */