/* Everything about breakpoints, for GDB.
- Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Copyright 1986, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
Free Software Foundation, Inc.
This file is part of GDB.
static void
ignore_command PARAMS ((char *, int));
-static int
-breakpoint_re_set_one PARAMS ((char *));
+static int breakpoint_re_set_one PARAMS ((PTR));
static void
clear_command PARAMS ((char *, int));
static int
can_use_hardware_watchpoint PARAMS ((struct value *));
+static void break_at_finish_command PARAMS ((char *, int));
+static void break_at_finish_at_depth_command PARAMS ((char *, int));
+
void
tbreak_command PARAMS ((char *, int));
+static void tbreak_at_finish_command PARAMS ((char *, int));
+
static void
break_command_1 PARAMS ((char *, int, int));
static bpstat
bpstat_alloc PARAMS ((struct breakpoint *, bpstat));
-static int
-breakpoint_cond_eval PARAMS ((char *));
+static int breakpoint_cond_eval PARAMS ((PTR));
static void
cleanup_executing_breakpoints PARAMS ((PTR));
typedef enum {
mark_inserted,
- mark_uninserted,
+ mark_uninserted
} insertion_state_t;
static int
int enable;
} args_for_catchpoint_enable;
-static int watchpoint_check PARAMS ((char *));
+static int watchpoint_check PARAMS ((PTR));
-static struct symtab_and_line *
-cover_target_enable_exception_callback PARAMS ((args_for_catchpoint_enable *));
+static int cover_target_enable_exception_callback PARAMS ((PTR));
static int print_it_done PARAMS ((bpstat));
static void do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+static void create_solib_load_unload_event_breakpoint PARAMS ((char *hookname, int tempflag, char *dll_pathname, char *cond_string, enum bptype bp_kind));
+
+static void create_fork_vfork_event_catchpoint PARAMS ((int tempflag, char * cond_string, enum bptype bp_kind));
+
+static void break_at_finish_at_depth_command_1 PARAMS ((char *arg, int flag, int from_tty));
+
+static void break_at_finish_command_1 PARAMS ((char *arg, int flag, int from_tty));
+
+static void stop_command PARAMS ((char *arg, int from_tty));
+
+static void stopin_command PARAMS ((char *arg, int from_tty));
+
+static void stopat_command PARAMS ((char *arg, int from_tty));
+
+static char *ep_find_event_name_end PARAMS ((char *arg));
+
+static char *ep_parse_optional_if_clause PARAMS ((char **arg));
+
+static char *ep_parse_optional_filename PARAMS ((char **arg));
+
+static void catch_exec_command_1 PARAMS ((char *arg, int tempflag, int from_tty));
+
+static void create_exception_catchpoint PARAMS ((int tempflag, char *cond_string, enum exception_event_kind ex_event, struct symtab_and_line *sal));
+
+static void catch_exception_command_1 PARAMS ((enum exception_event_kind ex_event, char *arg, int tempflag, int from_tty));
+
+static void tcatch_command PARAMS ((char *arg, int from_tty));
+
+static void ep_skip_leading_whitespace PARAMS ((char **s));
+
/* Prototypes for exported functions. */
static void
reinitialized -- e.g. when program is re-run */
int exception_support_initialized = 0;
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been
+ loaded.
+
+ This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
+ or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the
+ inferior has stopped in the dynamic linker hook, and becomes
+ invalid as soon as the inferior is continued. Clients should make
+ a copy of this string if they wish to continue the inferior and
+ then access the string. */
+
+#ifndef SOLIB_LOADED_LIBRARY_PATHNAME
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) ""
+#endif
+
+/* This function returns a pointer to the string representation of the
+ pathname of the dynamically-linked library that has just been
+ unloaded.
+
+ This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is
+ TRUE, or undefined results are guaranteed.
+
+ This string's contents are only valid immediately after the
+ inferior has stopped in the dynamic linker hook, and becomes
+ invalid as soon as the inferior is continued. Clients should make
+ a copy of this string if they wish to continue the inferior and
+ then access the string. */
+
+#ifndef SOLIB_UNLOADED_LIBRARY_PATHNAME
+#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) ""
+#endif
+
+/* This function is called by the "catch load" command. It allows the
+ debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is loaded. */
+
+#ifndef SOLIB_CREATE_CATCH_LOAD_HOOK
+#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error ("catch of library loads not yet implemented on this platform")
+#endif
+
+/* This function is called by the "catch unload" command. It allows
+ the debugger to be notified by the dynamic linker when a specified
+ library file (or any library file, if filename is NULL) is
+ unloaded. */
+
+#ifndef SOLIB_CREATE_CATCH_UNLOAD_HOOK
+#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
+ error ("catch of library unloads not yet implemented on this platform")
+#endif
/* Set breakpoint count to NUM. */
/* If we get here, we must have a callback mechanism for exception
events -- with g++ style embedded label support, we insert
ordinary breakpoints and not catchpoints. */
- struct symtab_and_line * sal;
- args_for_catchpoint_enable args;
sprintf (message, message1, b->number); /* Format possible error message */
val = target_insert_breakpoint(b->address, b->shadow_contents);
else
{
/* Bp set, now make sure callbacks are enabled */
- args.kind = b->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
- args.enable = 1;
- sal = catch_errors ((int (*) PARAMS ((char *)))
- cover_target_enable_exception_callback,
- (char *) &args,
- message, RETURN_MASK_ALL);
- if (sal && (sal != (struct symtab_and_line *) -1))
- {
- b->inserted = 1;
- }
- /* Check if something went wrong; sal == 0 can be ignored */
- if (sal == (struct symtab_and_line *) -1)
- {
- /* something went wrong */
- target_terminal_ours_for_output ();
- fprintf_unfiltered (gdb_stderr, "Cannot insert catchpoint %d; disabling it\n", b->number);
- b->enable = disabled;
- }
+ int val;
+ args_for_catchpoint_enable args;
+ args.kind = b->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
+ args.enable = 1;
+ val = catch_errors (cover_target_enable_exception_callback,
+ &args,
+ message, RETURN_MASK_ALL);
+ if (val != 0 && val != -1)
+ {
+ b->inserted = 1;
+ }
+ /* Check if something went wrong; val == 0 can be ignored */
+ if (val == -1)
+ {
+ /* something went wrong */
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr, "Cannot insert catchpoint %d; disabling it\n", b->number);
+ b->enable = disabled;
+ }
}
}
case bp_catch_exec :
val = target_insert_exec_catchpoint (inferior_pid);
break;
+ default:
+ warning ("GDB bug: breakpoint.c (insert_breakpoints): enclosing `if' does not protect `switch'");
+ break;
}
if (val < 0)
{
case bp_catch_exec :
val = target_remove_exec_catchpoint (inferior_pid);
break;
+ default:
+ warning ("GDB bug: breakpoint.c (remove_breakpoint): enclosing `if' does not protect `switch'");
+ break;
}
if (val)
return val;
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;
+ if (! CALL_DUMMY_P)
+ return 0;
+
+ if (USE_GENERIC_DUMMY_FRAMES)
+ return generic_pc_in_call_dummy (frame->pc, frame->frame, frame->frame);
+
ALL_BREAKPOINTS (b)
{
- static ULONGEST dummy[] = CALL_DUMMY;
-
if (b->type == bp_call_dummy
&& b->frame == frame->frame
-
/* We need to check the PC as well as the frame on the sparc,
for signals.exp in the testsuite. */
&& (frame->pc
>= (b->address
- - sizeof (dummy) / sizeof (LONGEST) * REGISTER_SIZE))
+ - SIZEOF_CALL_DUMMY_WORDS / sizeof (LONGEST) * REGISTER_SIZE))
&& frame->pc <= b->address)
return 1;
}
-#endif /* GENERIC_DUMMY_FRAMES */
-#endif /* CALL_DUMMY */
return 0;
}
static int
breakpoint_cond_eval (exp)
- char *exp;
+ PTR exp;
{
value_ptr mark = value_mark ();
int i = !value_true (evaluate_expression ((struct expression *)exp));
static int
watchpoint_check (p)
- char *p;
+ PTR p;
{
bpstat bs = (bpstat) p;
struct breakpoint *b;
continue;
if (b->type == bp_hardware_breakpoint
- && b->address != (bp_addr - DECR_PC_AFTER_HW_BREAK))
+ && b->address != (*pc - DECR_PC_AFTER_HW_BREAK))
continue;
if (b->type != bp_watchpoint
sprintf (message, message1, b->number);
if (b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
{
- switch (catch_errors ((int (*) PARAMS ((char *))) watchpoint_check, (char *) bs, message,
- RETURN_MASK_ALL))
+ switch (catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL))
{
case WP_DELETED:
/* We've already printed what needs to be printed. */
}
}
if (found)
- switch (catch_errors ((int (*) PARAMS ((char *))) watchpoint_check, (char *) bs, message,
- RETURN_MASK_ALL))
+ switch (catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL))
{
case WP_DELETED:
/* We've already printed what needs to be printed. */
breakpoint. */
++(b->hit_count);
- if (DECR_PC_AFTER_BREAK != 0 || must_shift_inst_regs)
- real_breakpoint = 1;
+ real_breakpoint = 1;
}
if (b->frame && b->frame != (get_current_frame ())->frame &&
so that the conditions will have the right context. */
select_frame (get_current_frame (), 0);
value_is_zero
- = catch_errors ((int (*) PARAMS ((char *))) breakpoint_cond_eval, (char *)(b->cond),
+ = catch_errors (breakpoint_cond_eval, (b->cond),
"Error in testing breakpoint condition:\n",
RETURN_MASK_ALL);
/* FIXME-someday, should give breakpoint # */
bs->next = NULL; /* Terminate the chain */
bs = root_bs->next; /* Re-grab the head of the chain */
- if ((DECR_PC_AFTER_BREAK != 0 || must_shift_inst_regs) && bs)
+ if (real_breakpoint && bs)
{
- if (real_breakpoint)
+ if (bs->breakpoint_at->type == bp_hardware_breakpoint)
{
- *pc = bp_addr;
+ if (DECR_PC_AFTER_HW_BREAK != 0)
+ {
+ *pc = *pc - DECR_PC_AFTER_HW_BREAK;
+ write_pc (*pc);
+ }
+ }
+ else
+ {
+ if (DECR_PC_AFTER_BREAK != 0 || must_shift_inst_regs)
+ {
+ *pc = bp_addr;
#if defined (SHIFT_INST_REGS)
- SHIFT_INST_REGS();
+ SHIFT_INST_REGS();
#else /* No SHIFT_INST_REGS. */
- write_pc (bp_addr);
+ write_pc (bp_addr);
#endif /* No SHIFT_INST_REGS. */
+ }
}
}
static char bpenables[] = "nyn";
char wrap_indent[80];
+
ALL_BREAKPOINTS (b)
if (bnum == -1
|| bnum == b->number)
while (l)
{
- print_command_line (l, 4);
+ print_command_line (l, 4, gdb_stdout);
l = l->next;
}
}
breakpoint_1 (bnum, 0);
}
-#if MAINTENANCE_CMDS
-
/* ARGSUSED */
-void
+static void
maintenance_info_breakpoints (bnum_exp, from_tty)
char *bnum_exp;
int from_tty;
breakpoint_1 (bnum, 1);
}
-#endif
-
/* Print a message describing any breakpoints set at PC. */
static void
}
void
-disable_breakpoints_in_shlibs ()
+disable_breakpoints_in_shlibs (silent)
+ int silent;
{
struct breakpoint * b;
int disabled_shlib_breaks = 0;
PC_SOLIB (b->address))
{
b->enable = shlib_disabled;
- if (!disabled_shlib_breaks)
- {
- target_terminal_ours_for_output ();
- printf_filtered ("Temporarily disabling shared library breakpoints:\n");
- }
- disabled_shlib_breaks = 1;
- printf_filtered ("%d ", b->number);
+ if (!silent)
+ {
+ if (!disabled_shlib_breaks)
+ {
+ target_terminal_ours_for_output ();
+ printf_filtered ("Temporarily disabling shared library breakpoints:\n");
+ }
+ disabled_shlib_breaks = 1;
+ printf_filtered ("%d ", b->number);
+ }
}
#endif
}
- if (disabled_shlib_breaks)
+ if (disabled_shlib_breaks && !silent)
printf_filtered ("\n");
}
static void
create_solib_load_unload_event_breakpoint (hookname, tempflag, dll_pathname, cond_string, bp_kind)
- char * hookname;
- int tempflag;
- char * dll_pathname;
- char * cond_string;
- enum bptype bp_kind;
+ char *hookname;
+ int tempflag;
+ char *dll_pathname;
+ char *cond_string;
+ enum bptype bp_kind;
{
struct breakpoint * b;
struct symtabs_and_lines sals;
static void
create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_kind)
- int tempflag;
- char * cond_string;
- enum bptype bp_kind;
+ int tempflag;
+ char *cond_string;
+ enum bptype bp_kind;
{
struct symtab_and_line sal;
struct breakpoint * b;
break_command_1 (arg, 0, from_tty);
}
-void
+static void
break_at_finish_command (arg, from_tty)
char *arg;
int from_tty;
break_at_finish_command_1 (arg, 0, from_tty);
}
-void
+static void
break_at_finish_at_depth_command (arg, from_tty)
char *arg;
int from_tty;
break_command_1 (arg, BP_TEMPFLAG, from_tty);
}
-void
+static void
tbreak_at_finish_command (arg, from_tty)
char *arg;
int from_tty;
}
#if defined(HPUXHPPA)
- /* ??rehrauer: DTS #CHFts23014 notes that on HP-UX if you set a h/w
+ /* On HP-UX if you set a h/w
watchpoint before the "run" command, the inferior dies with a e.g.,
SIGILL once you start it. I initially believed this was due to a
bad interaction between page protection traps and the initial
struct symtab_and_line sal;
};
+#if 0
/* Not really used -- invocation in handle_gnu_4_16_catch_command
had been commented out in the v.4.16 sources, and stays
disabled there now because "catch NAME" syntax isn't allowed.
while (*p == ' ' || *p == '\t') p++;
}
}
+#endif
/* This shares a lot of code with `print_frame_label_vars' from stack.c. */
static void
ep_skip_leading_whitespace (s)
- char ** s;
+ char **s;
{
if ((s == NULL) || (*s == NULL))
return;
the token is returned. Else, NULL is returned. */
static char *
ep_find_event_name_end (arg)
- char * arg;
+ char *arg;
{
char * s = arg;
char * event_name_end = NULL;
if clause in the arg string. */
static char *
ep_parse_optional_if_clause (arg)
- char ** arg;
+ char **arg;
{
char * cond_string;
future access should copy it to their own buffers. */
static char *
ep_parse_optional_filename (arg)
- char ** arg;
+ char **arg;
{
static char filename [1024];
char * arg_p = *arg;
typedef enum {catch_fork, catch_vfork} catch_fork_kind;
+static void catch_fork_command_1 PARAMS ((catch_fork_kind fork_kind, char *arg, int tempflag, int from_tty));
+
static void
catch_fork_command_1 (fork_kind, arg, tempflag, from_tty)
- catch_fork_kind fork_kind;
- char * arg;
- int tempflag;
- int from_tty;
+ catch_fork_kind fork_kind;
+ char *arg;
+ int tempflag;
+ int from_tty;
{
char * cond_string = NULL;
static void
catch_exec_command_1 (arg, tempflag, from_tty)
- char * arg;
- int tempflag;
- int from_tty;
+ char *arg;
+ int tempflag;
+ int from_tty;
{
char * cond_string = NULL;
static void
create_exception_catchpoint (tempflag, cond_string, ex_event, sal)
- int tempflag;
- char * cond_string;
- enum exception_event_kind ex_event;
- struct symtab_and_line * sal;
+ int tempflag;
+ char *cond_string;
+ enum exception_event_kind ex_event;
+ struct symtab_and_line *sal;
{
struct breakpoint * b;
int i;
static void
catch_exception_command_1 (ex_event, arg, tempflag, from_tty)
- enum exception_event_kind ex_event;
- char * arg;
- int tempflag;
- int from_tty;
+ enum exception_event_kind ex_event;
+ char *arg;
+ int tempflag;
+ int from_tty;
{
char * cond_string = NULL;
struct symtab_and_line * sal = NULL;
/* Cover routine to allow wrapping target_enable_exception_catchpoints
inside a catch_errors */
-static struct symtab_and_line *
-cover_target_enable_exception_callback (args)
- args_for_catchpoint_enable * args;
+static int
+cover_target_enable_exception_callback (arg)
+ PTR arg;
{
- target_enable_exception_callback (args->kind, args->enable);
+ args_for_catchpoint_enable *args = arg;
+ struct symtab_and_line *sal;
+ sal = target_enable_exception_callback (args->kind, args->enable);
+ if (sal == NULL)
+ return 0;
+ else if (sal == (struct symtab_and_line *) -1)
+ return -1;
+ else
+ return 1; /*is valid*/
}
sprintf (message, message1, bpt->number); /* Format possible error msg */
args.kind = bpt->type == bp_catch_catch ? EX_EVENT_CATCH : EX_EVENT_THROW;
args.enable = 0;
- (void) catch_errors ((int (*) PARAMS ((char *))) cover_target_enable_exception_callback,
- (char *) &args,
- message, RETURN_MASK_ALL);
+ catch_errors (cover_target_enable_exception_callback, &args,
+ message, RETURN_MASK_ALL);
}
static int
breakpoint_re_set_one (bint)
- char *bint;
+ PTR bint;
{
struct breakpoint *b = (struct breakpoint *)bint; /* get past catch_errs */
struct value *mark;
ALL_BREAKPOINTS_SAFE (b, temp)
{
sprintf (message, message1, b->number); /* Format possible error msg */
- catch_errors ((int (*) PARAMS ((char *))) breakpoint_re_set_one, (char *) b, message,
- RETURN_MASK_ALL);
+ catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
}
set_language (save_language);
input_radix = save_input_radix;
Convenience variable \"$bpnum\" contains the number of the last\n\
breakpoint set.", NULL));
-#if MAINTENANCE_CMDS
-
add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints,
concat ("Status of all breakpoints, or breakpoint number NUMBER.\n\
The \"Type\" column indicates one of:\n\
breakpoint set.", NULL),
&maintenanceinfolist);
-#endif /* MAINTENANCE_CMDS */
-
add_com ("catch", class_breakpoint, catch_command,
"Set catchpoints to catch events.\n\
Raised signals may be caught:\n\