static int tracepoint_count;
+static struct cmd_list_element *breakpoint_set_cmdlist;
+static struct cmd_list_element *breakpoint_show_cmdlist;
+static struct cmd_list_element *save_cmdlist;
+
/* Return whether a breakpoint is an active enabled breakpoint. */
static int
breakpoint_enabled (struct breakpoint *b)
}
\f
+
+void
+set_breakpoint_condition (struct breakpoint *b, char *exp,
+ int from_tty)
+{
+ struct bp_location *loc = b->loc;
+
+ for (; loc; loc = loc->next)
+ {
+ xfree (loc->cond);
+ loc->cond = NULL;
+ }
+ xfree (b->cond_string);
+ b->cond_string = NULL;
+ xfree (b->cond_exp);
+ b->cond_exp = NULL;
+
+ if (*exp == 0)
+ {
+ if (from_tty)
+ printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number);
+ }
+ else
+ {
+ char *arg = exp;
+ /* I don't know if it matters whether this is the string the user
+ typed in or the decompiled expression. */
+ b->cond_string = xstrdup (arg);
+ b->condition_not_parsed = 0;
+
+ if (is_watchpoint (b))
+ {
+ innermost_block = NULL;
+ arg = exp;
+ b->cond_exp = parse_exp_1 (&arg, 0, 0);
+ if (*arg)
+ error (_("Junk at end of expression"));
+ b->cond_exp_valid_block = innermost_block;
+ }
+ else
+ {
+ for (loc = b->loc; loc; loc = loc->next)
+ {
+ arg = exp;
+ loc->cond =
+ parse_exp_1 (&arg, block_for_pc (loc->address), 0);
+ if (*arg)
+ error (_("Junk at end of expression"));
+ }
+ }
+ }
+ breakpoints_changed ();
+ observer_notify_breakpoint_modified (b->number);
+}
+
/* condition N EXP -- set break condition of breakpoint N to EXP. */
static void
ALL_BREAKPOINTS (b)
if (b->number == bnum)
{
- struct bp_location *loc = b->loc;
- for (; loc; loc = loc->next)
- {
- xfree (loc->cond);
- loc->cond = NULL;
- }
- xfree (b->cond_string);
- b->cond_string = NULL;
- xfree (b->cond_exp);
- b->cond_exp = NULL;
-
- if (*p == 0)
- {
- if (from_tty)
- printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
- }
- else
- {
- arg = p;
- /* I don't know if it matters whether this is the string the user
- typed in or the decompiled expression. */
- b->cond_string = xstrdup (arg);
- b->condition_not_parsed = 0;
-
- if (is_watchpoint (b))
- {
- innermost_block = NULL;
- arg = p;
- b->cond_exp = parse_exp_1 (&arg, 0, 0);
- if (*arg)
- error (_("Junk at end of expression"));
- b->cond_exp_valid_block = innermost_block;
- }
- else
- {
- for (loc = b->loc; loc; loc = loc->next)
- {
- arg = p;
- loc->cond =
- parse_exp_1 (&arg, block_for_pc (loc->address), 0);
- if (*arg)
- error (_("Junk at end of expression"));
- }
- }
- }
- breakpoints_changed ();
- observer_notify_breakpoint_modified (b->number);
+ set_breakpoint_condition (b, p, from_tty);
return;
}
/* We were not stopped by a watchpoint. Mark all watchpoints
as not triggered. */
ALL_BREAKPOINTS (b)
- if (b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint)
+ if (is_hardware_watchpoint (b))
b->watchpoint_triggered = watch_triggered_no;
return 0;
/* We were stopped by a watchpoint, but we don't know where.
Mark all watchpoints as unknown. */
ALL_BREAKPOINTS (b)
- if (b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint)
+ if (is_hardware_watchpoint (b))
b->watchpoint_triggered = watch_triggered_unknown;
return stopped_by_watchpoint;
triggered. */
ALL_BREAKPOINTS (b)
- if (b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint)
+ if (is_hardware_watchpoint (b))
{
struct bp_location *loc;
struct value *v;
if (is_tracepoint (b))
return 0;
- if (b->type != bp_watchpoint
- && b->type != bp_hardware_watchpoint
- && b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
+ if (!is_watchpoint (b)
&& b->type != bp_hardware_breakpoint
&& b->type != bp_catchpoint) /* a non-watchpoint bp */
{
&& !section_is_mapped (bl->section))
return 0;
}
-
+
/* Continuable hardware watchpoints are treated as non-existent if the
reason we stopped wasn't a hardware watchpoint (we didn't stop on
some data address). Otherwise gdb won't stop on a break instruction
in the code (not from a breakpoint) when a hardware watchpoint has
been defined. Also skip watchpoints which we know did not trigger
(did not match the data address). */
-
- if ((b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint)
+
+ if (is_hardware_watchpoint (b)
&& b->watchpoint_triggered == watch_triggered_no)
return 0;
const struct bp_location *bl = bs->breakpoint_at;
struct breakpoint *b = bl->owner;
- if (b->type == bp_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint
- || b->type == bp_hardware_watchpoint)
+ if (is_watchpoint (b))
{
CORE_ADDR addr;
struct value *v;
for (bl = b->loc; bl != NULL; bl = bl->next)
{
/* For hardware watchpoints, we look only at the first location.
- The watchpoint_check function will work on entire expression,
- not the individual locations. For read watchopints, the
- watchpoints_triggered function have checked all locations
+ The watchpoint_check function will work on the entire expression,
+ not the individual locations. For read watchpoints, the
+ watchpoints_triggered function has checked all locations
already. */
if (b->type == bp_hardware_watchpoint && bl != b->loc)
break;
not have changed, but the intermediate memory locations we are
watching may have. Don't bother if we're stopping; this will get
done later. */
- for (bs = root_bs->next; bs != NULL; bs = bs->next)
- if (bs->stop)
- break;
-
need_remove_insert = 0;
- if (bs == NULL)
+ if (! bpstat_causes_stop (root_bs->next))
for (bs = root_bs->next; bs != NULL; bs = bs->next)
if (!bs->stop
&& bs->breakpoint_at->owner
|| b->type == bp_catchpoint
|| b->type == bp_hardware_breakpoint
|| is_tracepoint (b)
- || b->type == bp_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint
- || b->type == bp_hardware_watchpoint);
+ || is_watchpoint (b));
}
/* Print information on user settable breakpoint (watchpoint, etc)
return nr_printable_breakpoints;
}
+/* Display the value of default-collect in a way that is generally
+ compatible with the breakpoint list. */
+
+static void
+default_collect_info (void)
+{
+ /* If it has no value (which is frequently the case), say nothing; a
+ message like "No default-collect." gets in user's face when it's
+ not wanted. */
+ if (!*default_collect)
+ return;
+
+ /* The following phrase lines up nicely with per-tracepoint collect
+ actions. */
+ ui_out_text (uiout, "default collect ");
+ ui_out_field_string (uiout, "default-collect", default_collect);
+ ui_out_text (uiout, " \n");
+}
+
static void
breakpoints_info (char *bnum_exp, int from_tty)
{
bnum = parse_and_eval_long (bnum_exp);
breakpoint_1 (bnum, 0, NULL);
+
+ default_collect_info ();
}
static void
bnum = parse_and_eval_long (bnum_exp);
breakpoint_1 (bnum, 1, NULL);
+
+ default_collect_info ();
}
static int
printf_filtered (_("Catchpoint %d (fork)"), b->number);
}
+/* Implement the "print_recreate" breakpoint_ops method for fork
+ catchpoints. */
+
+static void
+print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp)
+{
+ fprintf_unfiltered (fp, "catch fork");
+}
+
/* The breakpoint_ops structure to be used in fork catchpoints. */
static struct breakpoint_ops catch_fork_breakpoint_ops =
breakpoint_hit_catch_fork,
print_it_catch_fork,
print_one_catch_fork,
- print_mention_catch_fork
+ print_mention_catch_fork,
+ print_recreate_catch_fork
};
/* Implement the "insert" breakpoint_ops method for vfork catchpoints. */
printf_filtered (_("Catchpoint %d (vfork)"), b->number);
}
+/* Implement the "print_recreate" breakpoint_ops method for vfork
+ catchpoints. */
+
+static void
+print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp)
+{
+ fprintf_unfiltered (fp, "catch vfork");
+}
+
/* The breakpoint_ops structure to be used in vfork catchpoints. */
static struct breakpoint_ops catch_vfork_breakpoint_ops =
breakpoint_hit_catch_vfork,
print_it_catch_vfork,
print_one_catch_vfork,
- print_mention_catch_vfork
+ print_mention_catch_vfork,
+ print_recreate_catch_vfork
};
/* Implement the "insert" breakpoint_ops method for syscall
b->number);
}
+/* Implement the "print_recreate" breakpoint_ops method for syscall
+ catchpoints. */
+
+static void
+print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
+{
+ fprintf_unfiltered (fp, "catch syscall");
+
+ if (b->syscalls_to_be_caught)
+ {
+ int i, iter;
+
+ for (i = 0;
+ VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
+ i++)
+ {
+ struct syscall s;
+
+ get_syscall_by_number (iter, &s);
+ if (s.name)
+ fprintf_unfiltered (fp, " %s", s.name);
+ else
+ fprintf_unfiltered (fp, " %d", s.number);
+ }
+ }
+}
+
/* The breakpoint_ops structure to be used in syscall catchpoints. */
static struct breakpoint_ops catch_syscall_breakpoint_ops =
breakpoint_hit_catch_syscall,
print_it_catch_syscall,
print_one_catch_syscall,
- print_mention_catch_syscall
+ print_mention_catch_syscall,
+ print_recreate_catch_syscall
};
/* Returns non-zero if 'b' is a syscall catchpoint. */
printf_filtered (_("Catchpoint %d (exec)"), b->number);
}
+/* Implement the "print_recreate" breakpoint_ops method for exec
+ catchpoints. */
+
+static void
+print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp)
+{
+ fprintf_unfiltered (fp, "catch exec");
+}
+
static struct breakpoint_ops catch_exec_breakpoint_ops =
{
insert_catch_exec,
breakpoint_hit_catch_exec,
print_it_catch_exec,
print_one_catch_exec,
- print_mention_catch_exec
+ print_mention_catch_exec,
+ print_recreate_catch_exec
};
static void
{
if (b->type == type)
i++;
- else if ((b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint))
+ else if (is_hardware_watchpoint (b))
*other_type_used = 1;
}
}
ALL_BREAKPOINTS (b)
{
- if (((b->type == bp_watchpoint)
- || (b->type == bp_hardware_watchpoint)
- || (b->type == bp_read_watchpoint)
- || (b->type == bp_access_watchpoint))
- && breakpoint_enabled (b))
+ if (is_watchpoint (b) && breakpoint_enabled (b))
{
b->enable_state = bp_call_disabled;
update_global_location_list (0);
ALL_BREAKPOINTS (b)
{
- if (((b->type == bp_watchpoint)
- || (b->type == bp_hardware_watchpoint)
- || (b->type == bp_read_watchpoint)
- || (b->type == bp_access_watchpoint))
- && (b->enable_state == bp_call_disabled))
+ if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
{
b->enable_state = bp_enabled;
update_global_location_list (1);
: _(" (catch)"));
}
+/* Implement the "print_recreate" breakpoint_ops method for throw and
+ catch catchpoints. */
+
+static void
+print_recreate_exception_catchpoint (struct breakpoint *b, struct ui_file *fp)
+{
+ int bp_temp;
+ int bp_throw;
+
+ bp_temp = b->disposition == disp_del;
+ bp_throw = strstr (b->addr_string, "throw") != NULL;
+ fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
+ fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
+}
+
static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
print_exception_catchpoint,
print_one_exception_catchpoint,
- print_mention_exception_catchpoint
+ print_mention_exception_catchpoint,
+ print_recreate_exception_catchpoint
};
static int
{
int match = 0;
/* Are we going to delete b? */
- if (b->type != bp_none
- && b->type != bp_watchpoint
- && b->type != bp_hardware_watchpoint
- && b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint)
+ if (b->type != bp_none && !is_watchpoint (b))
{
struct bp_location *loc = b->loc;
for (; loc; loc = loc->next)
error (_("Hardware breakpoints used exceeds limit."));
}
- if (bpt->type == bp_watchpoint
- || bpt->type == bp_hardware_watchpoint
- || bpt->type == bp_read_watchpoint
- || bpt->type == bp_access_watchpoint)
+ if (is_watchpoint (bpt))
{
struct gdb_exception e;
list that was acquired during tracepoint uploading. */
static struct uploaded_tp *this_utp;
-static struct uploaded_string *next_cmd;
+static int next_cmd;
static char *
read_uploaded_action (void)
{
char *rslt;
- if (!next_cmd)
- return NULL;
+ VEC_iterate (char_ptr, this_utp->cmd_strings, next_cmd, rslt);
- rslt = next_cmd->str;
- next_cmd = next_cmd->next;
+ next_cmd++;
return rslt;
}
special-purpose "reader" function and call the usual command line
reader, then pass the result to the breakpoint command-setting
function. */
- if (utp->cmd_strings)
+ if (!VEC_empty (char_ptr, utp->cmd_strings))
{
struct command_line *cmd_list;
this_utp = utp;
- next_cmd = utp->cmd_strings;
+ next_cmd = 0;
cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
breakpoint_set_commands (tp, cmd_list);
}
- else if (utp->numactions > 0 || utp->num_step_actions > 0)
+ else if (!VEC_empty (char_ptr, utp->actions)
+ || !VEC_empty (char_ptr, utp->step_actions))
warning (_("Uploaded tracepoint %d actions have no source form, ignoring them"),
utp->number);
else
ui_out_message (uiout, 0, "No tracepoint number %d.\n", tpnum);
}
+
+ default_collect_info ();
}
/* The 'enable trace' command enables tracepoints.
return NULL;
}
-/* save-tracepoints command */
+/* Save information on user settable breakpoints (watchpoints, etc) to
+ a new script file named FILENAME. If FILTER is non-NULL, call it
+ on each breakpoint and only include the ones for which it returns
+ non-zero. */
+
static void
-tracepoint_save_command (char *args, int from_tty)
+save_breakpoints (char *filename, int from_tty,
+ int (*filter) (const struct breakpoint *))
{
struct breakpoint *tp;
- int any_tp = 0;
- struct command_line *line;
+ int any = 0;
char *pathname;
- char tmp[40];
struct cleanup *cleanup;
struct ui_file *fp;
+ int extra_trace_bits = 0;
- if (args == 0 || *args == 0)
- error (_("Argument required (file name in which to save tracepoints)"));
+ if (filename == 0 || *filename == 0)
+ error (_("Argument required (file name in which to save)"));
/* See if we have anything to save. */
- ALL_TRACEPOINTS (tp)
+ ALL_BREAKPOINTS (tp)
{
- any_tp = 1;
- break;
+ /* Skip internal and momentary breakpoints. */
+ if (!user_settable_breakpoint (tp))
+ continue;
+
+ /* If we have a filter, only save the breakpoints it accepts. */
+ if (filter && !filter (tp))
+ continue;
+
+ any = 1;
+
+ if (is_tracepoint (tp))
+ {
+ extra_trace_bits = 1;
+
+ /* We can stop searching. */
+ break;
+ }
}
- if (!any_tp)
+
+ if (!any)
{
- warning (_("save-tracepoints: no tracepoints to save."));
+ warning (_("Nothing to save."));
return;
}
- pathname = tilde_expand (args);
+ pathname = tilde_expand (filename);
cleanup = make_cleanup (xfree, pathname);
fp = gdb_fopen (pathname, "w");
if (!fp)
- error (_("Unable to open file '%s' for saving tracepoints (%s)"),
- args, safe_strerror (errno));
+ error (_("Unable to open file '%s' for saving (%s)"),
+ filename, safe_strerror (errno));
make_cleanup_ui_file_delete (fp);
- save_trace_state_variables (fp);
+ if (extra_trace_bits)
+ save_trace_state_variables (fp);
- ALL_TRACEPOINTS (tp)
+ ALL_BREAKPOINTS (tp)
{
- if (tp->type == bp_fast_tracepoint)
- fprintf_unfiltered (fp, "ftrace");
- else
- fprintf_unfiltered (fp, "trace");
+ /* Skip internal and momentary breakpoints. */
+ if (!user_settable_breakpoint (tp))
+ continue;
+
+ /* If we have a filter, only save the breakpoints it accepts. */
+ if (filter && !filter (tp))
+ continue;
- if (tp->addr_string)
- fprintf_unfiltered (fp, " %s", tp->addr_string);
+ if (tp->ops != NULL)
+ (tp->ops->print_recreate) (tp, fp);
else
{
- sprintf_vma (tmp, tp->loc->address);
- fprintf_unfiltered (fp, " *0x%s", tmp);
+ if (tp->type == bp_fast_tracepoint)
+ fprintf_unfiltered (fp, "ftrace");
+ else if (tp->type == bp_tracepoint)
+ fprintf_unfiltered (fp, "trace");
+ else if (tp->type == bp_breakpoint && tp->disposition == disp_del)
+ fprintf_unfiltered (fp, "tbreak");
+ else if (tp->type == bp_breakpoint)
+ fprintf_unfiltered (fp, "break");
+ else if (tp->type == bp_hardware_breakpoint
+ && tp->disposition == disp_del)
+ fprintf_unfiltered (fp, "thbreak");
+ else if (tp->type == bp_hardware_breakpoint)
+ fprintf_unfiltered (fp, "hbreak");
+ else if (tp->type == bp_watchpoint)
+ fprintf_unfiltered (fp, "watch");
+ else if (tp->type == bp_hardware_watchpoint)
+ fprintf_unfiltered (fp, "watch");
+ else if (tp->type == bp_read_watchpoint)
+ fprintf_unfiltered (fp, "rwatch");
+ else if (tp->type == bp_access_watchpoint)
+ fprintf_unfiltered (fp, "awatch");
+ else
+ internal_error (__FILE__, __LINE__,
+ _("unhandled breakpoint type %d"), (int) tp->type);
+
+ if (tp->exp_string)
+ fprintf_unfiltered (fp, " %s", tp->exp_string);
+ else if (tp->addr_string)
+ fprintf_unfiltered (fp, " %s", tp->addr_string);
+ else
+ {
+ char tmp[40];
+
+ sprintf_vma (tmp, tp->loc->address);
+ fprintf_unfiltered (fp, " *0x%s", tmp);
+ }
}
- if (tp->cond_string)
- fprintf_unfiltered (fp, " if %s", tp->cond_string);
+ if (tp->thread != -1)
+ fprintf_unfiltered (fp, " thread %d", tp->thread);
+
+ if (tp->task != 0)
+ fprintf_unfiltered (fp, " task %d", tp->task);
fprintf_unfiltered (fp, "\n");
+ /* Note, we can't rely on tp->number for anything, as we can't
+ assume the recreated breakpoint numbers will match. Use $bpnum
+ instead. */
+
+ if (tp->cond_string)
+ fprintf_unfiltered (fp, " condition $bpnum %s\n", tp->cond_string);
+
+ if (tp->ignore_count)
+ fprintf_unfiltered (fp, " ignore $bpnum %d\n", tp->ignore_count);
+
if (tp->pass_count)
fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count);
{
volatile struct gdb_exception ex;
- fprintf_unfiltered (fp, " actions\n");
+ fprintf_unfiltered (fp, " commands\n");
ui_out_redirect (uiout, fp);
TRY_CATCH (ex, RETURN_MASK_ERROR)
fprintf_unfiltered (fp, " end\n");
}
+
+ if (tp->enable_state == bp_disabled)
+ fprintf_unfiltered (fp, "disable\n");
+
+ /* If this is a multi-location breakpoint, check if the locations
+ should be individually disabled. Watchpoint locations are
+ special, and not user visible. */
+ if (!is_watchpoint (tp) && tp->loc && tp->loc->next)
+ {
+ struct bp_location *loc;
+ int n = 1;
+
+ for (loc = tp->loc; loc != NULL; loc = loc->next, n++)
+ if (!loc->enabled)
+ fprintf_unfiltered (fp, "disable $bpnum.%d\n", n);
+ }
}
- if (*default_collect)
+ if (extra_trace_bits && *default_collect)
fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
do_cleanups (cleanup);
if (from_tty)
- printf_filtered (_("Tracepoints saved to file '%s'.\n"), args);
- return;
+ printf_filtered (_("Saved to file '%s'.\n"), filename);
+}
+
+/* The `save breakpoints' command. */
+
+static void
+save_breakpoints_command (char *args, int from_tty)
+{
+ save_breakpoints (args, from_tty, NULL);
+}
+
+/* The `save tracepoints' command. */
+
+static void
+save_tracepoints_command (char *args, int from_tty)
+{
+ save_breakpoints (args, from_tty, is_tracepoint);
}
/* Create a vector of all tracepoints. */
VEC_free (int, inf->syscalls_counts);
}
+static void
+save_command (char *arg, int from_tty)
+{
+ printf_unfiltered (_("\
+\"save\" must be followed by the name of a save subcommand.\n"));
+ help_list (save_cmdlist, "save ", -1, gdb_stdout);
+}
+
void
_initialize_breakpoint (void)
{
- static struct cmd_list_element *breakpoint_set_cmdlist;
- static struct cmd_list_element *breakpoint_show_cmdlist;
struct cmd_list_element *c;
observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
if TPNUM is omitted, passcount refers to the last tracepoint defined."));
- c = add_com ("save-tracepoints", class_trace, tracepoint_save_command, _("\
+ add_prefix_cmd ("save", class_breakpoint, save_command,
+ _("Save breakpoint definitions as a script."),
+ &save_cmdlist, "save ",
+ 0/*allow-unknown*/, &cmdlist);
+
+ c = add_cmd ("breakpoints", class_breakpoint, save_breakpoints_command, _("\
+Save current breakpoint definitions as a script.\n\
+This includes all types of breakpoints (breakpoints, watchpoints, \n\
+catchpoints, tracepoints). Use the 'source' command in another debug\n\
+session to restore them."),
+ &save_cmdlist);
+ set_cmd_completer (c, filename_completer);
+
+ c = add_cmd ("tracepoints", class_trace, save_tracepoints_command, _("\
Save current tracepoint definitions as a script.\n\
-Use the 'source' command in another debug session to restore them."));
+Use the 'source' command in another debug session to restore them."),
+ &save_cmdlist);
set_cmd_completer (c, filename_completer);
+ c = add_com_alias ("save-tracepoints", "save tracepoints", class_trace, 0);
+ deprecate_cmd (c, "save tracepoints");
+
add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
Breakpoint specific settings\n\
Configure various breakpoint-specific variables such as\n\