/* Everything about breakpoints, for GDB.
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
Free Software Foundation, Inc.
This file is part of GDB.
#include "value.h"
#include "command.h"
#include "inferior.h"
-#include "thread.h"
+#include "gdbthread.h"
#include "target.h"
#include "language.h"
#include "gdb_string.h"
#include "demangle.h"
#include "annotate.h"
+#include "symfile.h"
+#include "objfiles.h"
/* local function prototypes */
set_raw_breakpoint PARAMS ((struct symtab_and_line));
static void
-check_duplicates PARAMS ((CORE_ADDR));
+check_duplicates PARAMS ((CORE_ADDR, asection *));
static void
-describe_other_breakpoints PARAMS ((CORE_ADDR));
+describe_other_breakpoints PARAMS ((CORE_ADDR, asection *));
static void
breakpoints_info PARAMS ((char *, int));
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? */
+#if defined (GET_LONGJMP_TARGET) || defined (SOLIB_ADD)
+static int internal_breakpoint_number = -1;
+#endif
+
/* Are we executing breakpoint commands? */
static int executing_breakpoint_commands;
b? (tmp=b->next, 1): 0; \
b = tmp)
+/* True if SHIFT_INST_REGS defined, false otherwise. */
+
+int must_shift_inst_regs =
+#if defined(SHIFT_INST_REGS)
+1
+#else
+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 (b->type == bp_hardware_breakpoint)
val = target_insert_hw_breakpoint(b->address, b->shadow_contents);
else
- val = target_insert_breakpoint(b->address, b->shadow_contents);
+ {
+ /* Check to see if breakpoint is in an overlay section;
+ if so, we should set the breakpoint at the LMA address.
+ Only if the section is currently mapped should we ALSO
+ set a break at the VMA address. */
+ if (overlay_debugging && b->section &&
+ section_is_overlay (b->section))
+ {
+ CORE_ADDR addr;
+
+ addr = overlay_unmapped_address (b->address, b->section);
+ val = target_insert_breakpoint (addr, b->shadow_contents);
+ /* This would be the time to check val, to see if the
+ breakpoint write to the load address succeeded.
+ However, this might be an ordinary occurrance, eg. if
+ the unmapped overlay is in ROM. */
+ val = 0; /* in case unmapped address failed */
+ if (section_is_mapped (b->section))
+ val = target_insert_breakpoint (b->address,
+ b->shadow_contents);
+ }
+ else /* ordinary (non-overlay) address */
+ val = target_insert_breakpoint(b->address, b->shadow_contents);
+ }
if (val)
{
/* Can't set the breakpoint. */
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);
within_current_scope = 1;
else
{
- struct frame_info *fi =
- find_frame_addr_in_frame_chain (b->watchpoint_frame);
+ struct frame_info *fi;
+
+ /* There might be no current frame at this moment if we are
+ resuming from a step over a breakpoint.
+ Set up current frame before trying to find the watchpoint
+ frame. */
+ get_current_frame ();
+ fi = find_frame_addr_in_frame_chain (b->watchpoint_frame);
within_current_scope = (fi != NULL);
if (within_current_scope)
select_frame (fi, -1);
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->disposition = del_at_next_stop;
+ b->disposition = del_at_next_stop;
}
/* Restore the frame and level. */
if (b->type == bp_hardware_breakpoint)
val = target_remove_hw_breakpoint(b->address, b->shadow_contents);
else
- val = target_remove_breakpoint(b->address, b->shadow_contents);
+ {
+ /* Check to see if breakpoint is in an overlay section;
+ if so, we should remove the breakpoint at the LMA address.
+ If that is not equal to the raw address, then we should
+ presumable remove the breakpoint there as well. */
+ if (overlay_debugging && b->section &&
+ section_is_overlay (b->section))
+ {
+ CORE_ADDR addr;
+
+ addr = overlay_unmapped_address (b->address, b->section);
+ val = target_remove_breakpoint (addr, b->shadow_contents);
+ /* This would be the time to check val, to see if the
+ shadow breakpoint write to the load address succeeded.
+ However, this might be an ordinary occurrance, eg. if
+ the unmapped overlay is in ROM. */
+ val = 0; /* in case unmapped address failed */
+ if (section_is_mapped (b->section))
+ val = target_remove_breakpoint (b->address,
+ b->shadow_contents);
+ }
+ else /* ordinary (non-overlay) address */
+ val = target_remove_breakpoint(b->address, b->shadow_contents);
+ }
if (val)
return val;
b->inserted = 0;
at that address. */
if (v->lval == lval_memory)
{
- int addr, len;
+ int addr, len, type;
addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
len = TYPE_LENGTH (VALUE_TYPE (v));
- val = target_remove_watchpoint (addr, len, b->type);
+ type = 0;
+ if (b->type == bp_read_watchpoint)
+ type = 1;
+ else if (b->type == bp_access_watchpoint)
+ type = 2;
+
+ val = target_remove_watchpoint (addr, len, type);
if (val == -1)
b->inserted = 1;
val = 0;
{
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)
- return 1;
+ if (b->enable == enabled
+ && b->address == pc) /* bp is enabled and matches pc */
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+
+ return 0;
+}
+
+/* breakpoint_inserted_here_p (PC) is just like breakpoint_here_p(), but it
+ only returns true if there is actually a breakpoint inserted at PC. */
+
+int
+breakpoint_inserted_here_p (pc)
+ CORE_ADDR pc;
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->inserted
+ && b->address == pc) /* bp is inserted and matches pc */
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
return 0;
}
frame_in_dummy (frame)
struct frame_info *frame;
{
+#ifdef CALL_DUMMY
+#ifdef USE_GENERIC_DUMMY_FRAMES
+ return generic_pc_in_call_dummy (frame->pc, frame->frame);
+#else
struct breakpoint *b;
-#ifdef CALL_DUMMY
ALL_BREAKPOINTS (b)
{
- static unsigned LONGEST dummy[] = CALL_DUMMY;
+ static ULONGEST dummy[] = CALL_DUMMY;
if (b->type == bp_call_dummy
&& b->frame == frame->frame
&& frame->pc <= b->address)
return 1;
}
+#endif /* GENERIC_DUMMY_FRAMES */
#endif /* CALL_DUMMY */
return 0;
}
ALL_BREAKPOINTS (b)
if (b->enable != disabled
+ && b->enable != shlib_disabled
&& b->address == pc
&& (b->thread == -1 || b->thread == thread))
- return 1;
+ if (overlay_debugging &&
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
return 0;
}
/* 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);
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->disposition = del_at_next_stop;
+ 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). */
int real_breakpoint = 0;
-#endif
/* Root of the chain of bpstat's */
struct bpstats root_bs[1];
/* Pointer to the last thing in the chain currently. */
/* 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->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
&& b->type != bp_access_watchpoint
- && b->type != bp_hardware_breakpoint
- && b->address != bp_addr)
- continue;
+ && b->type != bp_hardware_breakpoint) /* a non-watchpoint bp */
+ if (b->address != bp_addr || /* address doesn't match or */
+ (overlay_debugging && /* overlay doesn't match */
+ section_is_overlay (b->section) &&
+ !section_is_mapped (b->section)))
+ continue;
if (b->type == bp_hardware_breakpoint
&& b->address != (bp_addr - DECR_PC_AFTER_HW_BREAK))
/* 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->disposition = del_at_next_stop;
+ 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->disposition = del_at_next_stop;
+ b->disposition = del_at_next_stop;
/* We've already printed what needs to be printed. */
bs->print_it = print_it_done;
break;
}
}
-#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
- else
+ else if (DECR_PC_AFTER_BREAK != 0 || must_shift_inst_regs)
real_breakpoint = 1;
-#endif
if (b->frame && b->frame != (get_current_frame ())->frame)
bs->stop = 0;
bs->next = NULL; /* Terminate the chain */
bs = root_bs->next; /* Re-grab the head of the chain */
-#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
- if (bs)
+
+ if ((DECR_PC_AFTER_BREAK != 0 || must_shift_inst_regs) && bs)
{
if (real_breakpoint)
{
#endif /* No SHIFT_INST_REGS. */
}
}
-#endif /* DECR_PC_AFTER_BREAK != 0. */
/* The value of a hardware watchpoint hasn't changed, but the
intermediate memory locations we are watching may have. */
/* 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);
last_addr = b->address;
if (b->source_file)
{
- sym = find_pc_function (b->address);
+ sym = find_pc_sect_function (b->address, b->section);
if (sym)
{
fputs_filtered ("in ", gdb_stdout);
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 */
/* Print a message describing any breakpoints set at PC. */
static void
-describe_other_breakpoints (pc)
- register CORE_ADDR pc;
+describe_other_breakpoints (pc, section)
+ CORE_ADDR pc;
+ asection *section;
{
register int others = 0;
register struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->address == pc)
- others++;
+ if (overlay_debugging == 0 ||
+ b->section == section)
+ others++;
if (others > 0)
{
printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : "");
ALL_BREAKPOINTS (b)
if (b->address == pc)
- {
- others--;
- printf_filtered
- ("%d%s%s ",
- b->number,
- (b->enable == disabled) ? " (disabled)" : "",
- (others > 1) ? "," : ((others == 1) ? " and" : ""));
- }
+ if (overlay_debugging == 0 ||
+ b->section == section)
+ {
+ others--;
+ printf_filtered
+ ("%d%s%s ",
+ b->number,
+ ((b->enable == disabled || b->enable == shlib_disabled)
+ ? " (disabled)" : ""),
+ (others > 1) ? "," : ((others == 1) ? " and" : ""));
+ }
printf_filtered ("also set at pc ");
print_address_numeric (pc, 1, gdb_stdout);
printf_filtered (".\n");
This is so that the bpt instruction is only inserted once. */
static void
-check_duplicates (address)
+check_duplicates (address, section)
CORE_ADDR address;
+ asection *section;
{
register struct breakpoint *b;
register int count = 0;
return;
ALL_BREAKPOINTS (b)
- if (b->enable != disabled && b->address == address)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->address == address
+ && (overlay_debugging == 0 || b->section == section))
{
count++;
b->duplicate = count > 1;
else
b->source_file = savestring (sal.symtab->filename,
strlen (sal.symtab->filename));
+ b->section = sal.section;
b->language = current_language->la_language;
b->input_radix = input_radix;
b->thread = -1;
b1->next = b;
}
- check_duplicates (sal.pc);
+ check_duplicates (sal.pc, sal.section);
breakpoints_changed ();
return b;
}
+#ifdef GET_LONGJMP_TARGET
+
static void
create_longjmp_breakpoint (func_name)
char *func_name;
{
struct symtab_and_line sal;
struct breakpoint *b;
- static int internal_breakpoint_number = -1;
+ INIT_SAL (&sal); /* initialize to zeroes */
if (func_name != NULL)
{
struct minimal_symbol *m;
else
return;
}
- else
- sal.pc = 0;
-
- sal.symtab = NULL;
- sal.line = 0;
-
+ sal.section = find_pc_overlay (sal.pc);
b = set_raw_breakpoint (sal);
if (!b) return;
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. */
if (b->type == bp_longjmp)
{
b->enable = enabled;
- check_duplicates (b->address);
+ check_duplicates (b->address, b->section);
}
}
|| b->type == bp_longjmp_resume)
{
b->enable = disabled;
- check_duplicates (b->address);
+ check_duplicates (b->address, b->section);
}
}
-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;
+
+ INIT_SAL (&sal); /* initialize to zeroes */
+ sal.pc = address;
+ sal.section = find_pc_overlay (sal.pc);
+ 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->frame = frame->frame;
else
b->frame = 0;
- check_duplicates (b->address);
+ check_duplicates (b->address, b->section);
return;
}
}
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.
sals.sals = NULL;
sals.nelts = 0;
- sal.line = sal.pc = sal.end = 0;
- sal.symtab = 0;
+ INIT_SAL (&sal); /* initialize to zeroes */
/* If no arg given, or if first arg is 'if ', use the default breakpoint. */
sal.pc = default_breakpoint_address;
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
+ sal.section = find_pc_overlay (sal.pc);
sals.sals[0] = sal;
sals.nelts = 1;
}
sal = sals.sals[i];
if (from_tty)
- describe_other_breakpoints (sal.pc);
+ describe_other_breakpoints (sal.pc, sal.section);
b = set_raw_breakpoint (sal);
set_breakpoint_count (breakpoint_count + 1);
b->enable = enabled;
b->disposition = tempflag ? del : donttouch;
-
mention (b);
}
{
CORE_ADDR pc;
- if (sal->pc == 0 && sal->symtab != 0)
+ if (sal->pc == 0 && sal->symtab != NULL)
{
pc = find_line_pc (sal->symtab, sal->line);
if (pc == 0)
sal->line, sal->symtab->filename);
sal->pc = pc;
}
+
+ if (sal->section == 0 && sal->symtab != NULL)
+ {
+ struct blockvector *bv;
+ struct block *b;
+ struct symbol *sym;
+ int index;
+
+ bv = blockvector_for_pc_sect (sal->pc, 0, &index, sal->symtab);
+ b = BLOCKVECTOR_BLOCK (bv, index);
+ sym = block_function (b);
+ if (sym != NULL)
+ {
+ fixup_symbol_section (sym, sal->symtab->objfile);
+ sal->section = SYMBOL_BFD_SECTION (block_function (b));
+ }
+ }
}
void
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;
char *cond_start = NULL;
char *cond_end = NULL;
struct expression *cond = NULL;
- int i, other_type_used, target_resources_ok;
+ int i, other_type_used, target_resources_ok = 0;
enum bptype bp_type;
int mem_cnt = 0;
- sal.pc = 0;
- sal.symtab = NULL;
- sal.line = 0;
+ INIT_SAL (&sal); /* initialize to zeroes */
/* Parse arguments. */
innermost_block = NULL;
expression. */
if (innermost_block)
{
- struct breakpoint *scope_breakpoint;
- struct symtab_and_line scope_sal;
-
if (prev_frame)
{
- scope_sal.pc = get_frame_pc (prev_frame);
- scope_sal.symtab = NULL;
- scope_sal.line = 0;
-
+ struct breakpoint *scope_breakpoint;
+ struct symtab_and_line scope_sal;
+
+ INIT_SAL (&scope_sal); /* initialize to zeroes */
+ scope_sal.pc = get_frame_pc (prev_frame);
+ scope_sal.section = find_pc_overlay (scope_sal.pc);
+
scope_breakpoint = set_raw_breakpoint (scope_sal);
set_breakpoint_count (breakpoint_count + 1);
scope_breakpoint->number = breakpoint_count;
#if 0
if (function (p))
{
- struct sal_chain *next
- = (struct sal_chain *)alloca (sizeof (struct sal_chain));
+ struct sal_chain *next = (struct sal_chain *)
+ alloca (sizeof (struct sal_chain));
next->next = sal_chain;
next->sal = get_catch_sal (p);
sal_chain = next;
char *save_arg;
int i;
- sal.line = sal.pc = sal.end = 0;
- sal.symtab = 0;
+ INIT_SAL (&sal); /* initialize to zeroes */
/* If no arg given, or if first arg is 'if ', all active catch clauses
are breakpointed. */
sal = sals.sals[i];
if (from_tty)
- describe_other_breakpoints (sal.pc);
+ describe_other_breakpoints (sal.pc, sal.section);
b = set_raw_breakpoint (sal);
set_breakpoint_count (breakpoint_count + 1);
struct breakpoint *
set_breakpoint_sal (sal)
-struct symtab_and_line sal;
+ struct symtab_and_line sal;
{
struct breakpoint *b;
b = set_raw_breakpoint (sal);
}
else
{
- sals.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ INIT_SAL (&sal); /* initialize to zeroes */
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
- sal.pc = 0;
if (sal.symtab == 0)
error ("No source file specified.");
But if sal.pc is zero, clear all bpts on specified line. */
sal = sals.sals[i];
found = (struct breakpoint *) 0;
+
while (breakpoint_chain
&& (sal.pc
- ? breakpoint_chain->address == sal.pc
+ ? (breakpoint_chain->address == sal.pc &&
+ (overlay_debugging == 0 ||
+ breakpoint_chain->section == sal.section))
: (breakpoint_chain->source_file != NULL
&& sal.symtab != NULL
&& STREQ (breakpoint_chain->source_file,
&& b->next->type != bp_read_watchpoint
&& b->next->type != bp_access_watchpoint
&& (sal.pc
- ? b->next->address == sal.pc
+ ? (b->next->address == sal.pc &&
+ (overlay_debugging == 0 ||
+ b->next->section == sal.section))
: (b->next->source_file != NULL
&& sal.symtab != NULL
&& STREQ (b->next->source_file, sal.symtab->filename)
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. */
break;
}
- check_duplicates (bpt->address);
+ check_duplicates (bpt->address, bpt->section);
/* If this breakpoint was inserted, and there is another breakpoint
at the same address, we need to insert the other breakpoint. */
if (bpt->inserted
{
ALL_BREAKPOINTS (b)
if (b->address == bpt->address
+ && b->section == bpt->section
&& !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);
char *arg;
int from_tty;
{
+ struct breakpoint *b, *temp;
if (arg == 0)
{
|| (breakpoint_chain && query ("Delete all breakpoints? ")))
{
/* No arg; clear all breakpoints. */
- while (breakpoint_chain)
- delete_breakpoint (breakpoint_chain);
+ ALL_BREAKPOINTS_SAFE(b, temp)
+ /* do not delete call-dummy breakpoint unles explicitly named! */
+ if (b->type != bp_call_dummy)
+ delete_breakpoint (b);
}
}
else
strlen (sals.sals[i].symtab->filename));
b->line_number = sals.sals[i].line;
b->address = sals.sals[i].pc;
-
- check_duplicates (b->address);
+ check_duplicates (b->address, b->section);
mention (b);
rather than once for every breakpoint. */
breakpoints_changed ();
}
+ b->section = sals.sals[i].section;
b->enable = save_enable; /* Restore it, this worked. */
}
free ((PTR)sals.sals);
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;
}
create_longjmp_breakpoint ("longjmp");
create_longjmp_breakpoint ("_longjmp");
create_longjmp_breakpoint ("siglongjmp");
+ create_longjmp_breakpoint ("_siglongjmp");
create_longjmp_breakpoint (NULL);
#endif
}
}
-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;
bpt->enable = disabled;
- check_duplicates (bpt->address);
+ check_duplicates (bpt->address, bpt->section);
if (modify_breakpoint_hook)
modify_breakpoint_hook (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;
- check_duplicates (bpt->address);
+ bpt->disposition = disposition;
+ check_duplicates (bpt->address, bpt->section);
breakpoints_changed ();
if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_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);
+ 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 */