/* Everything about breakpoints, for GDB.
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
Free Software Foundation, Inc.
This file is part of GDB.
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. */
#include "defs.h"
#include <ctype.h>
#include "gdbcore.h"
#include "gdbcmd.h"
#include "value.h"
-#include "ctype.h"
#include "command.h"
#include "inferior.h"
-#include "thread.h"
+#include "gdbthread.h"
#include "target.h"
#include "language.h"
-#include <string.h>
+#include "gdb_string.h"
#include "demangle.h"
#include "annotate.h"
breakpoint_cond_eval PARAMS ((char *));
static void
-cleanup_executing_breakpoints PARAMS ((int));
+cleanup_executing_breakpoints PARAMS ((PTR));
static void
commands_command PARAMS ((char *, int));
static int
remove_breakpoint PARAMS ((struct breakpoint *));
+static int
+print_it_normal PARAMS ((bpstat));
+
+static int
+watchpoint_check PARAMS ((char *));
+
+static int
+print_it_done PARAMS ((bpstat));
+
+static int
+print_it_noop PARAMS ((bpstat));
+
+static void
+maintenance_info_breakpoints PARAMS ((char *, int));
+
+#ifdef GET_LONGJMP_TARGET
+static void
+create_longjmp_breakpoint PARAMS ((char *));
+#endif
+
+static int
+hw_breakpoint_used_count PARAMS ((void));
+
+static int
+hw_watchpoint_used_count PARAMS ((enum bptype, int *));
+
+static void
+hbreak_command PARAMS ((char *, int));
+
+static void
+thbreak_command PARAMS ((char *, int));
+
+static void
+watch_command_1 PARAMS ((char *, int, int));
+
+static void
+rwatch_command PARAMS ((char *, int));
+
+static void
+awatch_command PARAMS ((char *, int));
+
+static void
+do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+
extern int addressprint; /* Print machine addresses? */
/* Are we executing breakpoint commands? */
b? (tmp=b->next, 1): 0; \
b = tmp)
-/* Provide defaults for systems that don't support hardware watchpoints. */
-
-#ifndef TARGET_CAN_USE_HARDWARE_WATCHPOINT
-
-/* Returns non-zero if we can set a hardware watchpoint of type TYPE. TYPE is
- one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint, or
- bp_hardware_breakpoint. CNT is the number of such watchpoints used so far
- (including this one?). OTHERTYPE is who knows what... */
-
-#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(TYPE,CNT,OTHERTYPE) 0
-
-/* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes. TYPE is 1
- for read and 2 for read/write accesses. Returns 0 for success, non-zero for
- failure. */
-
-#define target_remove_watchpoint(ADDR,LEN,TYPE) -1
-#define target_insert_watchpoint(ADDR,LEN,TYPE) -1
-#endif
-
-#ifndef target_insert_hw_breakpoint
-#define target_remove_hw_breakpoint(ADDR,SHADOW) -1
-#define target_insert_hw_breakpoint(ADDR,SHADOW) -1
-#endif
-
-#ifndef target_stopped_data_address
-#define target_stopped_data_address() 0
-#endif
-
/* True if breakpoint hit counts should be displayed in breakpoint info. */
int show_breakpoint_hit_counts = 1;
ALL_BREAKPOINTS (b)
if (b->number == bnum)
{
- if (from_tty && input_from_terminal_p ())
- printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\
-End with a line saying just \"end\".\n", bnum);
- l = read_command_lines ();
+ char tmpbuf[128];
+ sprintf (tmpbuf, "Type commands for when breakpoint %d is hit, one per line.", bnum);
+ l = read_command_lines (tmpbuf, from_tty);
free_command_lines (&b->commands);
b->commands = l;
breakpoints_changed ();
int
insert_breakpoints ()
{
- register struct breakpoint *b;
+ register struct breakpoint *b, *temp;
int val = 0;
int disabled_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BREAKPOINTS_SAFE (b, temp)
if (b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
&& b->type != bp_access_watchpoint
&& b->enable != disabled
+ && b->enable != shlib_disabled
&& ! b->inserted
&& ! b->duplicate)
{
if (DISABLE_UNSETTABLE_BREAK (b->address))
{
val = 0;
- b->enable = disabled;
+ b->enable = shlib_disabled;
if (!disabled_breaks)
{
target_terminal_ours_for_output ();
fprintf_unfiltered (gdb_stderr,
"Cannot insert breakpoint %d:\n", b->number);
- printf_filtered ("Disabling shared library breakpoints:\n");
+ printf_filtered ("Temporarily disabling shared library breakpoints:\n");
}
disabled_breaks = 1;
printf_filtered ("%d ", b->number);
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. */
}
/* Failure to remove any of the hardware watchpoints comes here. */
if (b->inserted)
- error ("Hardware watchpoint %d: Could not remove watchpoint\n",
- b->number);
+ warning ("Hardware watchpoint %d: Could not remove watchpoint\n",
+ b->number);
/* Free the saved value chain. We will construct a new one
the next time the watchpoint is inserted. */
{
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;
+ }
}
}
register struct breakpoint *b;
ALL_BREAKPOINTS (b)
- if (b->enable != disabled && b->address == pc)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->address == pc)
return 1;
return 0;
ALL_BREAKPOINTS (b)
if (b->enable != disabled
+ && b->enable != shlib_disabled
&& b->address == pc
&& (b->thread == -1 || b->thread == thread))
return 1;
/* ARGSUSED */
static void
cleanup_executing_breakpoints (ignore)
- int ignore;
+ PTR ignore;
{
executing_breakpoint_commands = 0;
}
struct cleanup *old_chain;
struct command_line *cmd;
+ /* Avoid endless recursion if a `source' command is contained
+ in bs->commands. */
+ if (executing_breakpoint_commands)
+ return;
+
executing_breakpoint_commands = 1;
old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
{
bpstat bs = (bpstat) p;
struct breakpoint *b;
- struct frame_info *saved_frame, *fr;
- int within_current_scope, saved_level;
+ struct frame_info *fr;
+ int within_current_scope;
b = bs->breakpoint_at;
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;
}
CORE_ADDR *pc;
int not_a_breakpoint;
{
- register struct breakpoint *b;
+ register struct breakpoint *b, *temp;
CORE_ADDR bp_addr;
#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
/* Get the address where the breakpoint would have been. */
bp_addr = *pc - DECR_PC_AFTER_BREAK;
- ALL_BREAKPOINTS (b)
+ ALL_BREAKPOINTS_SAFE (b, temp)
{
- if (b->enable == disabled)
+ if (b->enable == disabled
+ || b->enable == shlib_disabled)
continue;
if (b->type != bp_watchpoint
&& b->address != bp_addr)
continue;
-/* If defined, then we need to decr pc by this much after a hardware break-
- point. Presumably should override DECR_PC_AFTER_BREAK, though it doesn't
- now... */
-
-#ifndef DECR_PC_AFTER_HW_BREAK
-#define DECR_PC_AFTER_HW_BREAK 0
-#endif
-
if (b->type == bp_hardware_breakpoint
&& b->address != (bp_addr - DECR_PC_AFTER_HW_BREAK))
continue;
/* 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;
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;
/* We hit the through_sigtramp breakpoint. */
through_sig,
+ /* We hit the shared library event breakpoint. */
+ shlib_event,
+
/* This is just used to count how many enums there are. */
class_last
};
/* Here is the table which drives this routine. So that we can
format it pretty, we define some abbreviations for the
enum bpstat_what codes. */
-#define keep_c BPSTAT_WHAT_KEEP_CHECKING
-#define stop_s BPSTAT_WHAT_STOP_SILENT
-#define stop_n BPSTAT_WHAT_STOP_NOISY
-#define single BPSTAT_WHAT_SINGLE
-#define setlr BPSTAT_WHAT_SET_LONGJMP_RESUME
-#define clrlr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
-#define clrlrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
+#define kc BPSTAT_WHAT_KEEP_CHECKING
+#define ss BPSTAT_WHAT_STOP_SILENT
+#define sn BPSTAT_WHAT_STOP_NOISY
+#define sgl BPSTAT_WHAT_SINGLE
+#define slr BPSTAT_WHAT_SET_LONGJMP_RESUME
+#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
+#define clrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
#define sr BPSTAT_WHAT_STEP_RESUME
#define ts BPSTAT_WHAT_THROUGH_SIGTRAMP
+#define shl BPSTAT_WHAT_CHECK_SHLIBS
/* "Can't happen." Might want to print an error message.
abort() is not out of the question, but chances are GDB is just
table[(int)class_last][(int)BPSTAT_WHAT_LAST] =
{
/* old action */
- /* keep_c stop_s stop_n single setlr clrlr clrlrs sr ts
+ /* kc ss sn sgl slr clr clrs sr ts shl
*/
-/*no_effect*/ {keep_c,stop_s,stop_n,single, setlr , clrlr , clrlrs, sr, ts},
-/*wp_silent*/ {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts},
-/*wp_noisy*/ {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts},
-/*bp_nostop*/ {single,stop_s,stop_n,single, setlr , clrlrs, clrlrs, sr, ts},
-/*bp_silent*/ {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts},
-/*bp_noisy*/ {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts},
-/*long_jump*/ {setlr ,stop_s,stop_n,setlr , err , err , err , sr, ts},
-/*long_resume*/ {clrlr ,stop_s,stop_n,clrlrs, err , err , err , sr, ts},
-/*step_resume*/ {sr ,sr ,sr ,sr , sr , sr , sr , sr, ts},
-/*through_sig*/ {ts ,ts ,ts ,ts , ts , ts , ts , ts, ts}
+/*no_effect*/ {kc, ss, sn, sgl, slr, clr, clrs, sr, ts, shl},
+/*wp_silent*/ {ss, ss, sn, ss, ss, ss, ss, sr, ts, shl},
+/*wp_noisy*/ {sn, sn, sn, sn, sn, sn, sn, sr, ts, shl},
+/*bp_nostop*/ {sgl, ss, sn, sgl, slr, clrs, clrs, sr, ts, shl},
+/*bp_silent*/ {ss, ss, sn, ss, ss, ss, ss, sr, ts, shl},
+/*bp_noisy*/ {sn, sn, sn, sn, sn, sn, sn, sr, ts, shl},
+/*long_jump*/ {slr, ss, sn, slr, err, err, err, sr, ts, shl},
+/*long_resume*/ {clr, ss, sn, clrs, err, err, err, sr, ts, shl},
+/*step_resume*/ {sr, sr, sr, sr, sr, sr, sr, sr, ts, shl},
+/*through_sig*/ {ts, ts, ts, ts, ts, ts, ts, ts, ts, shl},
+/*shlib*/ {shl, shl, shl, shl, shl, shl, shl, shl, ts, shl}
};
-#undef keep_c
-#undef stop_s
-#undef stop_n
-#undef single
-#undef setlr
-#undef clrlr
-#undef clrlrs
+#undef kc
+#undef ss
+#undef sn
+#undef sgl
+#undef slr
+#undef clr
+#undef clrs
#undef err
#undef sr
#undef ts
+#undef shl
enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
struct bpstat_what retval;
case bp_watchpoint_scope:
bs_class = bp_nostop;
break;
-
+ case bp_shlib_event:
+ bs_class = shlib_event;
+ break;
case bp_call_dummy:
/* Make sure the action is stop (silent or noisy), so infrun.c
pops the dummy frame. */
"hw watchpoint", "read watchpoint",
"acc watchpoint", "longjmp",
"longjmp resume", "step resume",
- "watchpoint scope", "call dummy" };
- static char *bpdisps[] = {"del", "dis", "keep"};
- static char bpenables[] = "ny";
+ "sigtramp",
+ "watchpoint scope", "call dummy",
+ "shlib events" };
+ static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
+ static char bpenables[] = "nyn";
char wrap_indent[80];
ALL_BREAKPOINTS (b)
case bp_through_sigtramp:
case bp_watchpoint_scope:
case bp_call_dummy:
+ case bp_shlib_event:
if (addressprint)
{
annotate_field (4);
printf_filtered ("\n");
}
+ if (b->thread != -1)
+ {
+ /* FIXME should make an annotation for this */
+ printf_filtered ("\tstop only in thread %d\n", b->thread);
+ }
+
if (show_breakpoint_hit_counts && b->hit_count)
{
/* FIXME should make an annotation for this */
printf_filtered
("%d%s%s ",
b->number,
- (b->enable == disabled) ? " (disabled)" : "",
+ ((b->enable == disabled || b->enable == shlib_disabled)
+ ? " (disabled)" : ""),
(others > 1) ? "," : ((others == 1) ? " and" : ""));
}
printf_filtered ("also set at pc ");
return;
ALL_BREAKPOINTS (b)
- if (b->enable != disabled && b->address == address)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->address == address)
{
count++;
b->duplicate = count > 1;
return b;
}
+static int internal_breakpoint_number = -1;
+
+#ifdef GET_LONGJMP_TARGET
+
static void
-create_longjmp_breakpoint(func_name)
+create_longjmp_breakpoint (func_name)
char *func_name;
{
struct symtab_and_line sal;
struct breakpoint *b;
- static int internal_breakpoint_number = -1;
if (func_name != NULL)
{
sal.symtab = NULL;
sal.line = 0;
- b = set_raw_breakpoint(sal);
+ b = set_raw_breakpoint (sal);
if (!b) return;
b->type = func_name != NULL ? bp_longjmp : bp_longjmp_resume;
b->number = internal_breakpoint_number--;
}
+#endif /* #ifdef GET_LONGJMP_TARGET */
+
/* Call this routine when stepping and nexting to enable a breakpoint if we do
a longjmp(). When we hit that breakpoint, call
set_longjmp_resume_breakpoint() to figure out where we are going. */
}
}
-int
+#ifdef SOLIB_ADD
+void
+remove_solib_event_breakpoints ()
+{
+ register struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type == bp_shlib_event)
+ delete_breakpoint (b);
+}
+
+void
+create_solib_event_breakpoint (address)
+ CORE_ADDR address;
+{
+ struct breakpoint *b;
+ struct symtab_and_line sal;
+
+ sal.pc = address;
+ sal.symtab = NULL;
+ sal.line = 0;
+ b = set_raw_breakpoint (sal);
+ b->number = internal_breakpoint_number--;
+ b->disposition = donttouch;
+ b->type = bp_shlib_event;
+}
+
+/* Try to reenable any breakpoints in shared libraries. */
+void
+re_enable_breakpoints_in_shlibs ()
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable == shlib_disabled)
+ {
+ char buf[1];
+
+ /* Do not reenable the breakpoint if the shared library
+ is still not mapped in. */
+ if (target_read_memory (b->address, buf, 1) == 0)
+ b->enable = enabled;
+ }
+}
+
+#endif
+
+static int
hw_breakpoint_used_count()
{
register struct breakpoint *b;
return i;
}
-int
+static int
hw_watchpoint_used_count(type, other_type_used)
enum bptype type;
int *other_type_used;
b->enable = enabled;
b->disposition = donttouch;
b->frame = (frame ? frame->frame : 0);
+
+ /* If we're debugging a multi-threaded program, then we
+ want momentary breakpoints to be active in only a
+ single thread of control. */
+ if (in_thread_list (inferior_pid))
+ b->thread = pid_to_thread_id (inferior_pid);
+
return b;
}
-#if 0
-void
-clear_momentary_breakpoints ()
-{
- register struct breakpoint *b;
- ALL_BREAKPOINTS (b)
- if (b->disposition == delete)
- {
- delete_breakpoint (b);
- break;
- }
-}
-#endif
\f
/* Tell the user we have just set a breakpoint B. */
case bp_through_sigtramp:
case bp_call_dummy:
case bp_watchpoint_scope:
+ case bp_shlib_event:
break;
}
if (say_where)
printf_filtered ("\n");
}
-#if 0
-/* Nobody calls this currently. */
-/* Set a breakpoint from a symtab and line.
- If TEMPFLAG is nonzero, it is a temporary breakpoint.
- ADDR_STRING is a malloc'd string holding the name of where we are
- setting the breakpoint. This is used later to re-set it after the
- program is relinked and symbols are reloaded.
- Print the same confirmation messages that the breakpoint command prints. */
-
-void
-set_breakpoint (s, line, tempflag, addr_string)
- struct symtab *s;
- int line;
- int tempflag;
- char *addr_string;
-{
- register struct breakpoint *b;
- struct symtab_and_line sal;
-
- sal.symtab = s;
- sal.line = line;
- sal.pc = 0;
- resolve_sal_pc (&sal); /* Might error out */
- describe_other_breakpoints (sal.pc);
-
- b = set_raw_breakpoint (sal);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->type = bp_breakpoint;
- b->cond = 0;
- b->addr_string = addr_string;
- b->enable = enabled;
- b->disposition = tempflag ? delete : donttouch;
-
- mention (b);
-}
-#endif /* 0 */
\f
/* Set a breakpoint according to ARG (function, linenum or *address)
flag: first bit : 0 non-temporary, 1 temporary.
struct expression *exp;
struct block *exp_valid_block;
struct value *val, *mark;
- struct frame_info *frame, *prev_frame;
+ struct frame_info *frame;
+ struct frame_info *prev_frame = NULL;
char *exp_start = NULL;
char *exp_end = NULL;
char *tok, *end_tok;
free ((PTR)sals.sals);
}
\f
-/* 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. */
ALL_BREAKPOINTS (b)
if (b->address == bpt->address
&& !b->duplicate
- && b->enable != disabled)
+ && b->enable != disabled
+ && b->enable != shlib_disabled)
{
int val;
val = target_insert_breakpoint (b->address, b->shadow_contents);
free (bpt->cond_string);
if (bpt->addr_string != NULL)
free (bpt->addr_string);
+ if (bpt->exp != NULL)
+ free (bpt->exp);
if (bpt->exp_string != NULL)
free (bpt->exp_string);
+ if (bpt->val != NULL)
+ value_free (bpt->val);
if (bpt->source_file != NULL)
free (bpt->source_file);
particular level, but that's going to be less stable than filenames
or functionnames. */
/* So for now, just use a global context. */
+ if (b->exp)
+ free ((PTR)b->exp);
b->exp = parse_expression (b->exp_string);
b->exp_valid_block = innermost_block;
mark = value_mark ();
+ if (b->val)
+ value_free (b->val);
b->val = evaluate_expression (b->exp);
release_value (b->val);
if (VALUE_LAZY (b->val))
if (b->cond_string != NULL)
{
s = b->cond_string;
+ if (b->cond)
+ free ((PTR)b->cond);
b->cond = parse_exp_1 (&s, (struct block *)0, 0);
}
if (b->enable == enabled)
default:
printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
/* fall through */
- case bp_until:
- case bp_finish:
+ /* Delete longjmp breakpoints, they will be reset later by
+ breakpoint_re_set. */
case bp_longjmp:
case bp_longjmp_resume:
+ delete_breakpoint (b);
+ break;
+
+ /* This breakpoint is special, it's set up when the inferior
+ starts and we really don't want to touch it. */
+ case bp_shlib_event:
+
+ /* Keep temporary breakpoints, which can be encountered when we step
+ over a dlopen call and SOLIB_ADD is resetting the breakpoints.
+ Otherwise these should have been blown away via the cleanup chain
+ or by breakpoint_init_inferior when we rerun the executable. */
+ case bp_until:
+ case bp_finish:
case bp_watchpoint_scope:
case bp_call_dummy:
- delete_breakpoint (b);
+ case bp_step_resume:
break;
}
set_language (save_language);
input_radix = save_input_radix;
- create_longjmp_breakpoint("longjmp");
- create_longjmp_breakpoint("_longjmp");
- create_longjmp_breakpoint("siglongjmp");
- create_longjmp_breakpoint(NULL);
+#ifdef GET_LONGJMP_TARGET
+ create_longjmp_breakpoint ("longjmp");
+ create_longjmp_breakpoint ("_longjmp");
+ create_longjmp_breakpoint ("siglongjmp");
+ create_longjmp_breakpoint (NULL);
+#endif
#if 0
- /* Took this out (temporaliy at least), since it produces an extra
+ /* Took this out (temporarily at least), since it produces an extra
blank line at startup. This messes up the gdbtests. -PB */
/* Blank line to finish off all those mention() messages we just printed. */
printf_filtered ("\n");
}
}
-void
-enable_breakpoint (bpt)
- struct breakpoint *bpt;
-{
- struct frame_info *save_selected_frame = NULL;
- int save_selected_frame_level = -1;
- int target_resources_ok, other_type_used;
- struct value *mark;
-
- if (bpt->type == bp_hardware_breakpoint)
- {
- int i;
- i = hw_breakpoint_used_count();
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
- bp_hardware_breakpoint, i+1, 0);
- if (target_resources_ok == 0)
- error ("No hardware breakpoint support in the target.");
- else if (target_resources_ok < 0)
- error ("Hardware breakpoints used exceeds limit.");
- }
- bpt->enable = enabled;
- check_duplicates (bpt->address);
-
- if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint)
- {
- if (bpt->exp_valid_block != NULL)
- {
- struct frame_info *fr =
- find_frame_addr_in_frame_chain (bpt->watchpoint_frame);
- if (fr == NULL)
- {
- printf_filtered ("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n", bpt->number);
- bpt->enable = disabled;
- return;
- }
-
- save_selected_frame = selected_frame;
- save_selected_frame_level = selected_frame_level;
- select_frame (fr, -1);
- }
-
- value_free (bpt->val);
- mark = value_mark ();
- bpt->val = evaluate_expression (bpt->exp);
- release_value (bpt->val);
- if (VALUE_LAZY (bpt->val))
- value_fetch_lazy (bpt->val);
-
- if (bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint ||
- bpt->type == bp_access_watchpoint)
- {
- int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
- int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
- bpt->type, i + mem_cnt, other_type_used);
- /* we can consider of type is bp_hardware_watchpoint, convert to
- bp_watchpoint in the following condition */
- if (target_resources_ok < 0)
- {
- printf_filtered("\
-Cannot enable watchpoint %d because target watch resources\n\
-have been allocated for other watchpoints.\n", bpt->number);
- bpt->enable = disabled;
- value_free_to_mark (mark);
- return;
- }
- }
-
- if (save_selected_frame_level >= 0)
- select_frame (save_selected_frame, save_selected_frame_level);
- value_free_to_mark (mark);
- }
-
- if (modify_breakpoint_hook)
- modify_breakpoint_hook (bpt);
-}
-
-/* ARGSUSED */
-static void
-enable_command (args, from_tty)
- char *args;
- int from_tty;
-{
- struct breakpoint *bpt;
- if (args == 0)
- ALL_BREAKPOINTS (bpt)
- switch (bpt->type)
- {
- case bp_breakpoint:
- case bp_hardware_breakpoint:
- case bp_watchpoint:
- case bp_hardware_watchpoint:
- case bp_read_watchpoint:
- case bp_access_watchpoint:
- enable_breakpoint (bpt);
- default:
- continue;
- }
- else
- map_breakpoint_numbers (args, enable_breakpoint);
-}
-
void
disable_breakpoint (bpt)
struct breakpoint *bpt;
}
static void
-enable_once_breakpoint (bpt)
+do_enable_breakpoint (bpt, disposition)
struct breakpoint *bpt;
+ enum bpdisp disposition;
{
struct frame_info *save_selected_frame = NULL;
int save_selected_frame_level = -1;
int target_resources_ok, other_type_used;
struct value *mark;
- if (bpt->type == bp_hardware_breakpoint)
- {
+ if (bpt->type == bp_hardware_breakpoint)
+ {
int i;
i = hw_breakpoint_used_count();
target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
}
bpt->enable = enabled;
- bpt->disposition = disable;
+ bpt->disposition = disposition;
check_duplicates (bpt->address);
breakpoints_changed ();
bpt->type == bp_access_watchpoint)
{
int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
- int mem_cnt = can_use_hardware_watchpoint(bpt->val);
+ int mem_cnt = can_use_hardware_watchpoint (bpt->val);
+
target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
- bpt->type, i+mem_cnt, other_type_used);
+ bpt->type, i + mem_cnt, other_type_used);
/* we can consider of type is bp_hardware_watchpoint, convert to
bp_watchpoint in the following condition */
if (target_resources_ok < 0)
printf_filtered("\
Cannot enable watchpoint %d because target watch resources\n\
have been allocated for other watchpoints.\n", bpt->number);
- bpt->enable = disabled;
- value_free_to_mark (mark);
+ bpt->enable = disabled;
+ value_free_to_mark (mark);
+ return;
}
}
select_frame (save_selected_frame, save_selected_frame_level);
value_free_to_mark (mark);
}
+ if (modify_breakpoint_hook)
+ modify_breakpoint_hook (bpt);
+}
+
+void
+enable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ do_enable_breakpoint (bpt, donttouch);
+}
+
+/* The enable command enables the specified breakpoints (or all defined
+ breakpoints) so they once again become (or continue to be) effective
+ in stopping the inferior. */
+
+/* ARGSUSED */
+static void
+enable_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ switch (bpt->type)
+ {
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+ enable_breakpoint (bpt);
+ default:
+ continue;
+ }
+ else
+ map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ do_enable_breakpoint (bpt, disable);
}
/* ARGSUSED */
enable_delete_breakpoint (bpt)
struct breakpoint *bpt;
{
- bpt->enable = enabled;
- bpt->disposition = del;
-
- check_duplicates (bpt->address);
- breakpoints_changed ();
+ do_enable_breakpoint (bpt, del);
}
/* ARGSUSED */