static void enable_delete_command (char *, int);
-static void enable_delete_breakpoint (struct breakpoint *);
-
static void enable_once_command (char *, int);
-static void enable_once_breakpoint (struct breakpoint *);
-
static void disable_command (char *, int);
static void enable_command (char *, int);
-static void map_breakpoint_numbers (char *, void (*)(struct breakpoint *));
+static void map_breakpoint_numbers (char *, void (*) (struct breakpoint *,
+ void *),
+ void *);
static void ignore_command (char *, int);
static void breakpoints_info (char *, int);
-static void breakpoint_1 (int, int);
+static void watchpoints_info (char *, int);
+
+static int breakpoint_1 (int, int, int (*) (const struct breakpoint *));
static bpstat bpstat_alloc (const struct bp_location *, bpstat);
static int get_number_trailer (char **, int);
-void set_breakpoint_count (int);
-
typedef enum
{
mark_inserted,
static void update_global_location_list_nothrow (int);
-static int is_hardware_watchpoint (struct breakpoint *bpt);
+static int is_hardware_watchpoint (const struct breakpoint *bpt);
-static int is_watchpoint (struct breakpoint *bpt);
+static int is_watchpoint (const struct breakpoint *bpt);
static void insert_breakpoint_locations (void);
static void trace_pass_command (char *, int);
-static void skip_prologue_sal (struct symtab_and_line *sal);
+/* A reference-counted struct command_line. This lets multiple
+ breakpoints share a single command list. */
+struct counted_command_line
+{
+ /* The reference count. */
+ int refc;
+ /* The command list. */
+ struct command_line *commands;
+};
+
+struct command_line *
+breakpoint_commands (struct breakpoint *b)
+{
+ return b->commands ? b->commands->commands : NULL;
+}
/* Flag indicating that a command has proceeded the inferior past the
current breakpoint. */
/* NOTE: the following values are a part of MI protocol and represent
values of 'disp' field returned when inferior stops at a breakpoint. */
static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
+
return bpdisps[(int) disp];
}
#define ALL_TRACEPOINTS(B) \
for (B = breakpoint_chain; B; B = B->next) \
- if (tracepoint_type (B))
+ if (is_tracepoint (B))
/* Chains of all breakpoints defined. */
/* Number of last breakpoint made. */
-int breakpoint_count;
+static int breakpoint_count;
+
+/* The value of `breakpoint_count' before the last command that
+ created breakpoints. If the last (break-like) command created more
+ than one breakpoint, then the difference between BREAKPOINT_COUNT
+ and PREV_BREAKPOINT_COUNT is more than one. */
+static int prev_breakpoint_count;
/* Number of last tracepoint made. */
-int tracepoint_count;
+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
/* Set breakpoint count to NUM. */
-void
+static void
set_breakpoint_count (int num)
{
+ prev_breakpoint_count = breakpoint_count;
breakpoint_count = num;
set_internalvar_integer (lookup_internalvar ("bpnum"), num);
}
+/* Used by `start_rbreak_breakpoints' below, to record the current
+ breakpoint count before "rbreak" creates any breakpoint. */
+static int rbreak_start_breakpoint_count;
+
+/* Called at the start an "rbreak" command to record the first
+ breakpoint made. */
+
+void
+start_rbreak_breakpoints (void)
+{
+ rbreak_start_breakpoint_count = breakpoint_count;
+}
+
+/* Called at the end of an "rbreak" command to record the last
+ breakpoint made. */
+
+void
+end_rbreak_breakpoints (void)
+{
+ prev_breakpoint_count = rbreak_start_breakpoint_count;
+}
+
/* Used in run_command to zero the hit count when a new run starts. */
void
b->hit_count = 0;
}
-/* Encapsulate tests for different types of tracepoints. */
+/* Allocate a new counted_command_line with reference count of 1.
+ The new structure owns COMMANDS. */
-static int
-tracepoint_type (const struct breakpoint *b)
+static struct counted_command_line *
+alloc_counted_command_line (struct command_line *commands)
{
- return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
+ struct counted_command_line *result
+ = xmalloc (sizeof (struct counted_command_line));
+
+ result->refc = 1;
+ result->commands = commands;
+ return result;
}
-
+
+/* Increment reference count. This does nothing if CMD is NULL. */
+
+static void
+incref_counted_command_line (struct counted_command_line *cmd)
+{
+ if (cmd)
+ ++cmd->refc;
+}
+
+/* Decrement reference count. If the reference count reaches 0,
+ destroy the counted_command_line. Sets *CMDP to NULL. This does
+ nothing if *CMDP is NULL. */
+
+static void
+decref_counted_command_line (struct counted_command_line **cmdp)
+{
+ if (*cmdp)
+ {
+ if (--(*cmdp)->refc == 0)
+ {
+ free_command_lines (&(*cmdp)->commands);
+ xfree (*cmdp);
+ }
+ *cmdp = NULL;
+ }
+}
+
+/* A cleanup function that calls decref_counted_command_line. */
+
+static void
+do_cleanup_counted_command_line (void *arg)
+{
+ decref_counted_command_line (arg);
+}
+
+/* Create a cleanup that calls decref_counted_command_line on the
+ argument. */
+
+static struct cleanup *
+make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp)
+{
+ return make_cleanup (do_cleanup_counted_command_line, cmdp);
+}
+
/* Default address, symtab and line to put a breakpoint at
for "break" command with no arg.
if default_breakpoint_valid is zero, the other three are
}
\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;
}
error (_("No breakpoint number %d."), bnum);
}
-/* Set the command list of B to COMMANDS. */
+/* Check that COMMAND do not contain commands that are suitable
+ only for tracepoints and not suitable for ordinary breakpoints.
+ Throw if any such commands is found.
+*/
+static void
+check_no_tracepoint_commands (struct command_line *commands)
+{
+ struct command_line *c;
+
+ for (c = commands; c; c = c->next)
+ {
+ int i;
+
+ if (c->control_type == while_stepping_control)
+ error (_("The 'while-stepping' command can only be used for tracepoints"));
+
+ for (i = 0; i < c->body_count; ++i)
+ check_no_tracepoint_commands ((c->body_list)[i]);
+
+ /* Not that command parsing removes leading whitespace and comment
+ lines and also empty lines. So, we only need to check for
+ command directly. */
+ if (strstr (c->line, "collect ") == c->line)
+ error (_("The 'collect' command can only be used for tracepoints"));
+
+ if (strstr (c->line, "teval ") == c->line)
+ error (_("The 'teval' command can only be used for tracepoints"));
+ }
+}
+
+/* Encapsulate tests for different types of tracepoints. */
+
+int
+is_tracepoint (const struct breakpoint *b)
+{
+ return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
+}
+
+/* A helper function that validsates that COMMANDS are valid for a
+ breakpoint. This function will throw an exception if a problem is
+ found. */
+
+static void
+validate_commands_for_breakpoint (struct breakpoint *b,
+ struct command_line *commands)
+{
+ if (is_tracepoint (b))
+ {
+ /* We need to verify that each top-level element of commands
+ is valid for tracepoints, that there's at most one while-stepping
+ element, and that while-stepping's body has valid tracing commands
+ excluding nested while-stepping. */
+ struct command_line *c;
+ struct command_line *while_stepping = 0;
+ for (c = commands; c; c = c->next)
+ {
+ if (c->control_type == while_stepping_control)
+ {
+ if (b->type == bp_fast_tracepoint)
+ error (_("The 'while-stepping' command cannot be used for fast tracepoint"));
+
+ if (while_stepping)
+ error (_("The 'while-stepping' command can be used only once"));
+ else
+ while_stepping = c;
+ }
+ }
+ if (while_stepping)
+ {
+ struct command_line *c2;
+
+ gdb_assert (while_stepping->body_count == 1);
+ c2 = while_stepping->body_list[0];
+ for (; c2; c2 = c2->next)
+ {
+ if (c2->control_type == while_stepping_control)
+ error (_("The 'while-stepping' command cannot be nested"));
+ }
+ }
+ }
+ else
+ {
+ check_no_tracepoint_commands (commands);
+ }
+}
+
+/* Set the command list of B to COMMANDS. If breakpoint is tracepoint,
+ validate that only allowed commands are included.
+*/
void
breakpoint_set_commands (struct breakpoint *b, struct command_line *commands)
{
- free_command_lines (&b->commands);
- b->commands = commands;
+ validate_commands_for_breakpoint (b, commands);
+
+ decref_counted_command_line (&b->commands);
+ b->commands = alloc_counted_command_line (commands);
breakpoints_changed ();
observer_notify_breakpoint_modified (b->number);
}
+void
+check_tracepoint_command (char *line, void *closure)
+{
+ struct breakpoint *b = closure;
+
+ validate_actionline (&line, b);
+}
+
+/* A structure used to pass information through
+ map_breakpoint_numbers. */
+
+struct commands_info
+{
+ /* True if the command was typed at a tty. */
+ int from_tty;
+
+ /* The breakpoint range spec. */
+ char *arg;
+
+ /* Non-NULL if the body of the commands are being read from this
+ already-parsed command. */
+ struct command_line *control;
+
+ /* The command lines read from the user, or NULL if they have not
+ yet been read. */
+ struct counted_command_line *cmd;
+};
+
+/* A callback for map_breakpoint_numbers that sets the commands for
+ commands_command. */
+
static void
-commands_command (char *arg, int from_tty)
+do_map_commands_command (struct breakpoint *b, void *data)
{
- struct breakpoint *b;
- char *p;
- int bnum;
- struct command_line *l;
+ struct commands_info *info = data;
- /* If we allowed this, we would have problems with when to
- free the storage, if we change the commands currently
- being read from. */
+ if (info->cmd == NULL)
+ {
+ struct command_line *l;
- if (executing_breakpoint_commands)
- error (_("Can't use the \"commands\" command among a breakpoint's commands."));
+ if (info->control != NULL)
+ l = copy_command_lines (info->control->body_list[0]);
+ else
+ {
+ struct cleanup *old_chain;
+ char *str;
- p = arg;
- bnum = get_number (&p);
+ str = xstrprintf (_("Type commands for breakpoint(s) %s, one per line."),
+ info->arg);
- if (p && *p)
- error (_("Unexpected extra arguments following breakpoint number."));
+ old_chain = make_cleanup (xfree, str);
- ALL_BREAKPOINTS (b)
- if (b->number == bnum)
- {
- char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.",
- bnum);
- struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
- l = read_command_lines (tmpbuf, from_tty, 1);
- do_cleanups (cleanups);
- breakpoint_set_commands (b, l);
- return;
+ l = read_command_lines (str,
+ info->from_tty, 1,
+ (is_tracepoint (b)
+ ? check_tracepoint_command : 0),
+ b);
+
+ do_cleanups (old_chain);
+ }
+
+ info->cmd = alloc_counted_command_line (l);
+ }
+
+ /* If a breakpoint was on the list more than once, we don't need to
+ do anything. */
+ if (b->commands != info->cmd)
+ {
+ validate_commands_for_breakpoint (b, info->cmd->commands);
+ incref_counted_command_line (info->cmd);
+ decref_counted_command_line (&b->commands);
+ b->commands = info->cmd;
+ breakpoints_changed ();
+ observer_notify_breakpoint_modified (b->number);
}
- error (_("No breakpoint number %d."), bnum);
+}
+
+static void
+commands_command_1 (char *arg, int from_tty, struct command_line *control)
+{
+ struct cleanup *cleanups;
+ struct commands_info info;
+
+ info.from_tty = from_tty;
+ info.control = control;
+ info.cmd = NULL;
+ /* If we read command lines from the user, then `info' will hold an
+ extra reference to the commands that we must clean up. */
+ cleanups = make_cleanup_decref_counted_command_line (&info.cmd);
+
+ if (arg == NULL || !*arg)
+ {
+ if (breakpoint_count - prev_breakpoint_count > 1)
+ arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, breakpoint_count);
+ else if (breakpoint_count > 0)
+ arg = xstrprintf ("%d", breakpoint_count);
+ else
+ {
+ /* So that we don't try to free the incoming non-NULL
+ argument in the cleanup below. Mapping breakpoint
+ numbers will fail in this case. */
+ arg = NULL;
+ }
+ }
+ else
+ /* The command loop has some static state, so we need to preserve
+ our argument. */
+ arg = xstrdup (arg);
+
+ if (arg != NULL)
+ make_cleanup (xfree, arg);
+
+ info.arg = arg;
+
+ map_breakpoint_numbers (arg, do_map_commands_command, &info);
+
+ if (info.cmd == NULL)
+ error (_("No breakpoints specified."));
+
+ do_cleanups (cleanups);
+}
+
+static void
+commands_command (char *arg, int from_tty)
+{
+ commands_command_1 (arg, from_tty, NULL);
}
/* Like commands_command, but instead of reading the commands from
enum command_control_type
commands_from_control_command (char *arg, struct command_line *cmd)
{
- struct breakpoint *b;
- char *p;
- int bnum;
-
- /* If we allowed this, we would have problems with when to
- free the storage, if we change the commands currently
- being read from. */
-
- if (executing_breakpoint_commands)
- error (_("Can't use the \"commands\" command among a breakpoint's commands."));
-
- /* An empty string for the breakpoint number means the last
- breakpoint, but get_number expects a NULL pointer. */
- if (arg && !*arg)
- p = NULL;
- else
- p = arg;
- bnum = get_number (&p);
-
- if (p && *p)
- error (_("Unexpected extra arguments following breakpoint number."));
-
- ALL_BREAKPOINTS (b)
- if (b->number == bnum)
- {
- free_command_lines (&b->commands);
- if (cmd->body_count != 1)
- error (_("Invalid \"commands\" block structure."));
- /* We need to copy the commands because if/while will free the
- list after it finishes execution. */
- b->commands = copy_command_lines (cmd->body_list[0]);
- breakpoints_changed ();
- observer_notify_breakpoint_modified (b->number);
- return simple_control;
- }
- error (_("No breakpoint number %d."), bnum);
+ commands_command_1 (arg, 0, cmd);
+ return simple_control;
}
/* Return non-zero if BL->TARGET_INFO contains valid information. */
insert_catchpoint (struct ui_out *uo, void *args)
{
struct breakpoint *b = (struct breakpoint *) args;
- int val = -1;
gdb_assert (b->type == bp_catchpoint);
gdb_assert (b->ops != NULL && b->ops->insert != NULL);
/* Return true if BPT is of any hardware watchpoint kind. */
static int
-is_hardware_watchpoint (struct breakpoint *bpt)
+is_hardware_watchpoint (const struct breakpoint *bpt)
{
return (bpt->type == bp_hardware_watchpoint
|| bpt->type == bp_read_watchpoint
software. */
static int
-is_watchpoint (struct breakpoint *bpt)
+is_watchpoint (const struct breakpoint *bpt)
{
return (is_hardware_watchpoint (bpt)
|| bpt->type == bp_watchpoint);
{
int within_current_scope;
struct frame_id saved_frame_id;
- struct bp_location *loc;
int frame_saved;
- bpstat bs;
/* If this is a local watchpoint, we only want to check if the
watchpoint frame is in scope if the current thread is the thread
/* Tracepoints are inserted by the target at a time of its choosing,
not by us. */
- if (tracepoint_type (bpt->owner))
+ if (is_tracepoint (bpt->owner))
return 0;
return 1;
{
if (automatic_hardware_breakpoints)
{
- int changed = 0;
enum bp_loc_type new_type;
if (mr->attrib.mode != MEM_RW)
if (new_type != bpt->loc_type)
{
static int said = 0;
+
bpt->loc_type = new_type;
if (!said)
{
ALL_BP_LOCATIONS (b, bp_tmp)
{
- struct thread_info *tp;
- CORE_ADDR last_addr;
-
if (!should_be_inserted (b) || b->inserted)
continue;
do_cleanups (old_chain);
}
+/* Create a master std::terminate breakpoint. The actual function
+ looked for is named FUNC_NAME. */
+static void
+create_std_terminate_master_breakpoint (const char *func_name)
+{
+ struct program_space *pspace;
+ struct objfile *objfile;
+ struct cleanup *old_chain;
+
+ old_chain = save_current_program_space ();
+
+ ALL_PSPACES (pspace)
+ ALL_OBJFILES (objfile)
+ {
+ struct breakpoint *b;
+ struct minimal_symbol *m;
+
+ set_current_program_space (pspace);
+
+ m = lookup_minimal_symbol (func_name, NULL, objfile);
+ if (m == NULL || (MSYMBOL_TYPE (m) != mst_text
+ && MSYMBOL_TYPE (m) != mst_file_text))
+ continue;
+
+ b = create_internal_breakpoint (get_objfile_arch (objfile),
+ SYMBOL_VALUE_ADDRESS (m),
+ bp_std_terminate_master);
+ b->addr_string = xstrdup (func_name);
+ b->enable_state = bp_disabled;
+ }
+ update_global_location_list (1);
+
+ do_cleanups (old_chain);
+}
+
void
update_breakpoints_after_exec (void)
{
/* Thread event breakpoints must be set anew after an exec(),
as must overlay event and longjmp master breakpoints. */
if (b->type == bp_thread_event || b->type == bp_overlay_event
- || b->type == bp_longjmp_master)
+ || b->type == bp_longjmp_master || b->type == bp_std_terminate_master)
{
delete_breakpoint (b);
continue;
create_longjmp_master_breakpoint ("_longjmp");
create_longjmp_master_breakpoint ("siglongjmp");
create_longjmp_master_breakpoint ("_siglongjmp");
+ create_std_terminate_master_breakpoint ("std::terminate()");
}
int
remove_breakpoint_1 (struct bp_location *b, insertion_state_t is)
{
int val;
- struct cleanup *old_chain;
if (b->owner->enable_state == bp_permanent)
/* Permanent breakpoints cannot be inserted or removed. */
}
else if (b->loc_type == bp_loc_hardware_watchpoint)
{
- struct value *v;
- struct value *n;
-
b->inserted = (is == mark_inserted);
val = target_remove_watchpoint (b->address, b->length,
b->watchpoint_type);
software_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
{
struct bp_location *bpt, **bptp_tmp;
- int any_breakpoint_here = 0;
ALL_BP_LOCATIONS (bpt, bptp_tmp)
{
{
if (bs->old_val != NULL)
value_free (bs->old_val);
- free_command_lines (&bs->commands);
+ decref_counted_command_line (&bs->commands);
xfree (bs);
}
{
tmp = (bpstat) xmalloc (sizeof (*tmp));
memcpy (tmp, bs, sizeof (*tmp));
- if (bs->commands != NULL)
- tmp->commands = copy_command_lines (bs->commands);
+ incref_counted_command_line (tmp->commands);
if (bs->old_val != NULL)
{
tmp->old_val = value_copy (bs->old_val);
return NULL;
}
-/* Find a step_resume breakpoint associated with this bpstat.
- (If there are multiple step_resume bp's on the list, this function
- will arbitrarily pick one.)
-
- It is an error to use this function if BPSTAT doesn't contain a
- step_resume breakpoint.
-
- See wait_for_inferior's use of this function. */
-struct breakpoint *
-bpstat_find_step_resume_breakpoint (bpstat bsp)
-{
- int current_thread;
-
- gdb_assert (bsp != NULL);
-
- current_thread = pid_to_thread_id (inferior_ptid);
-
- for (; bsp != NULL; bsp = bsp->next)
- {
- if ((bsp->breakpoint_at != NULL)
- && (bsp->breakpoint_at->owner->type == bp_step_resume)
- && (bsp->breakpoint_at->owner->thread == current_thread
- || bsp->breakpoint_at->owner->thread == -1))
- return bsp->breakpoint_at->owner;
- }
-
- internal_error (__FILE__, __LINE__, _("No step_resume breakpoint found."));
-}
-
-
/* Put in *NUM the breakpoint number of the first breakpoint we are stopped
at. *BSP upon return is a bpstat which points to the remaining
breakpoints stopped at (but which is not guaranteed to be good for
{
for (; bs != NULL; bs = bs->next)
{
- free_command_lines (&bs->commands);
+ decref_counted_command_line (&bs->commands);
+ bs->commands_left = NULL;
if (bs->old_val != NULL)
{
value_free (bs->old_val);
breakpoint_proceeded = 0;
for (; bs != NULL; bs = bs->next)
{
+ struct counted_command_line *ccmd;
struct command_line *cmd;
struct cleanup *this_cmd_tree_chain;
commands are only executed once, we don't need to copy it; we
can clear the pointer in the bpstat, and make sure we free
the tree when we're done. */
- cmd = bs->commands;
- bs->commands = 0;
- this_cmd_tree_chain = make_cleanup_free_command_lines (&cmd);
+ ccmd = bs->commands;
+ bs->commands = NULL;
+ this_cmd_tree_chain
+ = make_cleanup_decref_counted_command_line (&ccmd);
+ cmd = bs->commands_left;
+ bs->commands_left = NULL;
while (cmd != NULL)
{
result = PRINT_NOTHING;
break;
+ case bp_std_terminate_master:
+ /* These should never be enabled. */
+ printf_filtered (_("std::terminate Master Breakpoint: gdb should not stop!\n"));
+ result = PRINT_NOTHING;
+ break;
+
case bp_watchpoint:
case bp_hardware_watchpoint:
annotate_watchpoint (b->number);
case bp_step_resume:
case bp_watchpoint_scope:
case bp_call_dummy:
+ case bp_std_terminate:
case bp_tracepoint:
case bp_fast_tracepoint:
case bp_jit_event:
{
struct value *mark = value_mark ();
int i = !value_true (evaluate_expression ((struct expression *) exp));
+
value_free_to_mark (mark);
return i;
}
bs->breakpoint_at = bl;
/* If the condition is false, etc., don't do the commands. */
bs->commands = NULL;
+ bs->commands_left = NULL;
bs->old_val = NULL;
bs->print_it = print_it_normal;
return bs;
/* 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;
b->watchpoint_triggered = watch_triggered_no;
for (loc = b->loc; loc; loc = loc->next)
/* By definition, the inferior does not report stops at
tracepoints. */
- if (tracepoint_type (b))
+ 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;
int must_check_value = 0;
if (b->type == bp_watchpoint)
CORE_ADDR bp_addr, ptid_t ptid)
{
struct breakpoint *b = NULL;
- struct bp_location *bl, **blp_tmp;
+ struct bp_location *bl;
struct bp_location *loc;
/* Root of the chain of bpstat's */
struct bpstats root_bs[1];
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;
continue;
if (b->type == bp_thread_event || b->type == bp_overlay_event
- || b->type == bp_longjmp_master)
+ || b->type == bp_longjmp_master
+ || b->type == bp_std_terminate_master)
/* We do not stop for these. */
bs->stop = 0;
else
if (b->silent)
bs->print = 0;
bs->commands = b->commands;
- if (bs->commands
- && (strcmp ("silent", bs->commands->line) == 0
- || (xdb_commands && strcmp ("Q",
- bs->commands->line) == 0)))
+ incref_counted_command_line (bs->commands);
+ bs->commands_left = bs->commands ? bs->commands->commands : NULL;
+ if (bs->commands_left
+ && (strcmp ("silent", bs->commands_left->line) == 0
+ || (xdb_commands
+ && strcmp ("Q",
+ bs->commands_left->line) == 0)))
{
- bs->commands = bs->commands->next;
+ bs->commands_left = bs->commands_left->next;
bs->print = 0;
}
- bs->commands = copy_command_lines (bs->commands);
}
/* Print nothing for this entry if we dont stop or dont print. */
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
enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
struct bpstat_what retval;
- retval.call_dummy = 0;
+ retval.call_dummy = STOP_NONE;
for (; bs != NULL; bs = bs->next)
{
enum class bs_class = no_effect;
case bp_thread_event:
case bp_overlay_event:
case bp_longjmp_master:
+ case bp_std_terminate_master:
bs_class = bp_nostop;
break;
case bp_catchpoint:
/* Make sure the action is stop (silent or noisy),
so infrun.c pops the dummy frame. */
bs_class = bp_silent;
- retval.call_dummy = 1;
+ retval.call_dummy = STOP_STACK_DUMMY;
+ break;
+ case bp_std_terminate:
+ /* Make sure the action is stop (silent or noisy),
+ so infrun.c pops the dummy frame. */
+ bs_class = bp_silent;
+ retval.call_dummy = STOP_STD_TERMINATE;
break;
case bp_tracepoint:
case bp_fast_tracepoint:
bpstat_should_step (void)
{
struct breakpoint *b;
+
ALL_BREAKPOINTS (b)
if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
return 1;
int allflag)
{
struct command_line *l;
- struct symbol *sym;
struct ep_type_description
{
enum bptype type;
{bp_step_resume, "step resume"},
{bp_watchpoint_scope, "watchpoint scope"},
{bp_call_dummy, "call dummy"},
+ {bp_std_terminate, "std::terminate"},
{bp_shlib_event, "shlib events"},
{bp_thread_event, "thread events"},
{bp_overlay_event, "overlay events"},
{bp_longjmp_master, "longjmp master"},
+ {bp_std_terminate_master, "std::terminate master"},
{bp_catchpoint, "catchpoint"},
{bp_tracepoint, "tracepoint"},
{bp_fast_tracepoint, "fast tracepoint"},
case bp_step_resume:
case bp_watchpoint_scope:
case bp_call_dummy:
+ case bp_std_terminate:
case bp_shlib_event:
case bp_thread_event:
case bp_overlay_event:
case bp_longjmp_master:
+ case bp_std_terminate_master:
case bp_tracepoint:
case bp_fast_tracepoint:
case bp_jit_event:
because the condition is an internal implementation detail
that we do not want to expose to the user. */
annotate_field (7);
- if (tracepoint_type (b))
+ if (is_tracepoint (b))
ui_out_text (uiout, "\ttrace only if ");
else
ui_out_text (uiout, "\tstop only if ");
ui_out_text (uiout, " hits\n");
}
- l = b->commands;
+ l = b->commands ? b->commands->commands : NULL;
if (!part_of_multiple && l)
{
struct cleanup *script_chain;
ui_out_text (uiout, " \n");
}
- if (!part_of_multiple && b->step_count)
- {
- annotate_field (11);
- ui_out_text (uiout, "\tstep count ");
- ui_out_field_int (uiout, "step", b->step_count);
- ui_out_text (uiout, " \n");
- }
-
- if (!part_of_multiple && b->actions)
- {
- struct action_line *action;
- annotate_field (12);
- for (action = b->actions; action; action = action->next)
- {
- ui_out_text (uiout, " A\t");
- ui_out_text (uiout, action->action);
- ui_out_text (uiout, "\n");
- }
- }
-
if (ui_out_is_mi_like_p (uiout) && !part_of_multiple)
{
if (b->addr_string)
struct captured_breakpoint_query_args *args = data;
struct breakpoint *b;
struct bp_location *dummy_loc = NULL;
+
ALL_BREAKPOINTS (b)
{
if (args->bnum == b->number)
{
int print_address_bits = breakpoint_address_bits (b);
+
print_one_breakpoint (b, &dummy_loc, print_address_bits, 0);
return GDB_RC_OK;
}
gdb_breakpoint_query (struct ui_out *uiout, int bnum, char **error_message)
{
struct captured_breakpoint_query_args args;
+
args.bnum = bnum;
/* For the moment we don't trust print_one_breakpoint() to not throw
an error. */
return (b->type == bp_breakpoint
|| b->type == bp_catchpoint
|| b->type == bp_hardware_breakpoint
- || tracepoint_type (b)
- || b->type == bp_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint
- || b->type == bp_hardware_watchpoint);
+ || is_tracepoint (b)
+ || is_watchpoint (b));
}
/* Print information on user settable breakpoint (watchpoint, etc)
- number BNUM. If BNUM is -1 print all user settable breakpoints.
- If ALLFLAG is non-zero, include non- user settable breakpoints. */
+ number BNUM. If BNUM is -1 print all user-settable breakpoints.
+ If ALLFLAG is non-zero, include non-user-settable breakpoints. If
+ FILTER is non-NULL, call it on each breakpoint and only include the
+ ones for which it returns non-zero. Return the total number of
+ breakpoints listed. */
-static void
-breakpoint_1 (int bnum, int allflag)
+static int
+breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
{
struct breakpoint *b;
struct bp_location *last_loc = NULL;
if (bnum == -1
|| bnum == b->number)
{
+ /* If we have a filter, only list the breakpoints it accepts. */
+ if (filter && !filter (b))
+ continue;
+
if (allflag || user_settable_breakpoint (b))
{
int addr_bit = breakpoint_address_bits (b);
if (bnum == -1
|| bnum == b->number)
{
+ /* If we have a filter, only list the breakpoints it accepts. */
+ if (filter && !filter (b))
+ continue;
+
/* We only print out user settable breakpoints unless the
allflag is set. */
if (allflag || user_settable_breakpoint (b))
if (nr_printable_breakpoints == 0)
{
- if (bnum == -1)
- ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
- else
- ui_out_message (uiout, 0, "No breakpoint or watchpoint number %d.\n",
- bnum);
+ /* If there's a filter, let the caller decide how to report empty list. */
+ if (!filter)
+ {
+ if (bnum == -1)
+ ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
+ else
+ ui_out_message (uiout, 0, "No breakpoint or watchpoint number %d.\n",
+ bnum);
+ }
}
else
{
/* FIXME? Should this be moved up so that it is only called when
there have been breakpoints? */
annotate_breakpoints_table_end ();
+
+ 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)
{
if (bnum_exp)
bnum = parse_and_eval_long (bnum_exp);
- breakpoint_1 (bnum, 0);
+ breakpoint_1 (bnum, 0, NULL);
+
+ default_collect_info ();
+}
+
+static void
+watchpoints_info (char *wpnum_exp, int from_tty)
+{
+ int wpnum = -1, num_printed;
+
+ if (wpnum_exp)
+ wpnum = parse_and_eval_long (wpnum_exp);
+
+ num_printed = breakpoint_1 (wpnum, 0, is_watchpoint);
+
+ if (num_printed == 0)
+ {
+ if (wpnum == -1)
+ ui_out_message (uiout, 0, "No watchpoints.\n");
+ else
+ ui_out_message (uiout, 0, "No watchpoint number %d.\n", wpnum);
+ }
}
static void
if (bnum_exp)
bnum = parse_and_eval_long (bnum_exp);
- breakpoint_1 (bnum, 1);
+ breakpoint_1 (bnum, 1, NULL);
+
+ default_collect_info ();
}
static int
CORE_ADDR pc, struct obj_section *section)
{
struct bp_location *bl = b->loc;
+
for (; bl; bl = bl->next)
{
if (bl->pspace == pspace
static struct bp_location *
allocate_bp_location (struct breakpoint *bpt)
{
- struct bp_location *loc, *loc_p;
+ struct bp_location *loc;
loc = xmalloc (sizeof (struct bp_location));
memset (loc, 0, sizeof (*loc));
case bp_step_resume:
case bp_watchpoint_scope:
case bp_call_dummy:
+ case bp_std_terminate:
case bp_shlib_event:
case bp_thread_event:
case bp_overlay_event:
case bp_jit_event:
case bp_longjmp_master:
+ case bp_std_terminate_master:
loc->loc_type = bp_loc_software_breakpoint;
break;
case bp_hardware_breakpoint:
{
if (loc->owner->type == bp_breakpoint
|| loc->owner->type == bp_hardware_breakpoint
- || tracepoint_type (loc->owner))
+ || is_tracepoint (loc->owner))
{
find_pc_partial_function (loc->address, &(loc->function_name),
NULL, NULL);
make_breakpoint_permanent (struct breakpoint *b)
{
struct bp_location *bl;
+
b->enable_state = bp_permanent;
/* By definition, permanent breakpoints are already present in the code.
&& b->type == bp_longjmp_master)
{
struct breakpoint *clone = clone_momentary_breakpoint (b);
+
clone->type = bp_longjmp;
clone->thread = thread;
}
}
}
+/* Set an active std::terminate breakpoint for each std::terminate
+ master breakpoint. */
+void
+set_std_terminate_breakpoint (void)
+{
+ struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->pspace == current_program_space
+ && b->type == bp_std_terminate_master)
+ {
+ struct breakpoint *clone = clone_momentary_breakpoint (b);
+ clone->type = bp_std_terminate;
+ }
+}
+
+/* Delete all the std::terminate breakpoints. */
+void
+delete_std_terminate_breakpoint (void)
+{
+ struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type == bp_std_terminate)
+ delete_breakpoint (b);
+}
+
struct breakpoint *
create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
all breakpoints. If we don't set shlib_disabled here, we'll try
to insert those breakpoints and fail. */
if (((b->type == bp_breakpoint)
+ || (b->type == bp_jit_event)
|| (b->type == bp_hardware_breakpoint)
- || (tracepoint_type (b)))
+ || (is_tracepoint (b)))
&& loc->pspace == current_program_space
&& !loc->shlib_disabled
#ifdef PC_SOLIB
ALL_BP_LOCATIONS (loc, locp_tmp)
{
struct breakpoint *b = loc->owner;
+
if ((loc->loc_type == bp_loc_hardware_breakpoint
|| loc->loc_type == bp_loc_software_breakpoint)
&& solib->pspace == loc->pspace
&& !loc->shlib_disabled
- && (b->type == bp_breakpoint || b->type == bp_hardware_breakpoint)
+ && (b->type == bp_breakpoint
+ || b->type == bp_jit_event
+ || b->type == bp_hardware_breakpoint)
&& solib_contains_address_p (solib, loc->address))
{
loc->shlib_disabled = 1;
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
else
{
int i, iter;
+
for (i = 0;
VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
i++)
{
int elem;
+
if (iter >= VEC_length (int, inf->syscalls_counts))
{
int old_size = VEC_length (int, inf->syscalls_counts);
else
{
int i, iter;
+
for (i = 0;
VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
i++)
if (b->syscalls_to_be_caught)
{
int i, iter;
+
for (i = 0;
VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
i++)
{
int i, iter;
char *text = xstrprintf ("%s", "");
+
for (i = 0;
VEC_iterate (int, b->syscalls_to_be_caught, i, iter);
i++)
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);
case bp_longjmp_resume:
case bp_step_resume:
case bp_call_dummy:
+ case bp_std_terminate:
case bp_watchpoint_scope:
case bp_shlib_event:
case bp_thread_event:
case bp_overlay_event:
case bp_jit_event:
case bp_longjmp_master:
+ case bp_std_terminate_master:
break;
}
remove_sal (&expanded, i);
--i;
}
- else if (func_addr == pc)
- {
- /* We're at beginning of a function, and should
- skip prologue. */
- struct symbol *sym = find_pc_function (pc);
- if (sym)
- expanded.sals[i] = find_function_start_sal (sym, 1);
- else
- {
- /* Since find_pc_partial_function returned true,
- we should really always find the section here. */
- struct obj_section *section = find_pc_section (pc);
- if (section)
- {
- struct gdbarch *gdbarch
- = get_objfile_arch (section->objfile);
- expanded.sals[i].pc
- = gdbarch_skip_prologue (gdbarch, pc);
- }
- }
- }
}
}
}
- else
- {
- for (i = 0; i < expanded.nelts; ++i)
- {
- /* If this SAL corresponds to a breakpoint inserted using a
- line number, then skip the function prologue if necessary. */
- skip_prologue_sal (&expanded.sals[i]);
- }
- }
+
+ /* Skip the function prologue if necessary. */
+ for (i = 0; i < expanded.nelts; ++i)
+ skip_prologue_sal (&expanded.sals[i]);
do_cleanups (old_chain);
int enabled)
{
int i;
+
for (i = 0; i < sals.nelts; ++i)
{
struct symtabs_and_lines expanded =
int *not_found_ptr)
{
char *addr_start = *address;
+
*addr_string = NULL;
/* If no arg given, or if first arg is 'if ', use the default
breakpoint. */
if (default_breakpoint_valid)
{
struct symtab_and_line sal;
+
init_sal (&sal); /* initialize to zeroes */
sals->sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
if (addr_start != (*address))
{
int i;
+
for (i = 0; i < sals->nelts; i++)
{
/* Add the string if not present. */
if ((*addr_string)[i] == NULL)
- (*addr_string)[i] = savestring (addr_start, (*address) - addr_start);
+ (*addr_string)[i] = savestring (addr_start,
+ (*address) - addr_start);
}
}
}
char *address)
{
int i;
+
for (i = 0; i < sals->nelts; i++)
resolve_sal_pc (&sals->sals[i]);
}
int toklen;
char *cond_start = NULL;
char *cond_end = NULL;
+
while (*tok == ' ' || *tok == '\t')
tok++;
struct symtabs_and_lines sals;
struct symtab_and_line pending_sal;
char *copy_arg;
- char *err_msg;
char *addr_start = arg;
char **addr_string;
struct cleanup *old_chain;
int not_found = 0;
enum bptype type_wanted;
int task = 0;
+ int prev_bkpt_count = breakpoint_count;
sals.sals = NULL;
sals.nelts = 0;
}
else
{
- struct symtab_and_line sal = {0};
struct breakpoint *b;
make_cleanup (xfree, copy_arg);
}
if (sals.nelts > 1)
- warning (_("Multiple breakpoints were set.\n"
- "Use the \"delete\" command to delete unwanted breakpoints."));
+ {
+ warning (_("Multiple breakpoints were set.\n"
+ "Use the \"delete\" command to delete unwanted breakpoints."));
+ prev_breakpoint_count = prev_bkpt_count;
+ }
+
/* That's it. Discard the cleanups for data inserted into the
breakpoint. */
discard_cleanups (bkpt_chain);
}
-
-/* Adjust SAL to the first instruction past the function prologue.
- The end of the prologue is determined using the line table from
- the debugging information. explicit_pc and explicit_line are
- not modified.
-
- If SAL is already past the prologue, then do nothing. */
-
-static void
-skip_prologue_sal (struct symtab_and_line *sal)
-{
- struct symbol *sym;
- struct symtab_and_line start_sal;
- struct cleanup *old_chain;
-
- old_chain = save_current_space_and_thread ();
-
- sym = find_pc_function (sal->pc);
- if (sym != NULL)
- {
- start_sal = find_function_start_sal (sym, 1);
- if (sal->pc < start_sal.pc)
- {
- start_sal.explicit_line = sal->explicit_line;
- start_sal.explicit_pc = sal->explicit_pc;
- *sal = start_sal;
- }
- }
-
- do_cleanups (old_chain);
-}
-
/* Helper function for break_command_1 and disassemble_command. */
void
/* If this SAL corresponds to a breakpoint inserted using
a line number, then skip the function prologue if necessary. */
if (sal->explicit_line)
- {
- /* Preserve the original line number. */
- int saved_line = sal->line;
- skip_prologue_sal (sal);
- sal->line = saved_line;
- }
+ skip_prologue_sal (sal);
}
if (sal->section == 0 && sal->symtab != NULL)
static void
watch_command_1 (char *arg, int accessflag, int from_tty)
{
- struct gdbarch *gdbarch = get_current_arch ();
struct breakpoint *b, *scope_breakpoint = NULL;
struct expression *exp;
struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
catch_fork_kind;
static void
-catch_fork_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
+catch_fork_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
struct gdbarch *gdbarch = get_current_arch ();
char *cond_string = NULL;
}
static void
-catch_exec_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
+catch_exec_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
}
static void
-print_one_exception_catchpoint (struct breakpoint *b, struct bp_location **last_loc)
+print_one_exception_catchpoint (struct breakpoint *b,
+ struct bp_location **last_loc)
{
struct value_print_options opts;
+
get_user_print_options (&opts);
if (opts.addressprint)
{
: _(" (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 tempflag, int from_tty)
{
char *cond_string = NULL;
- struct symtab_and_line *sal = NULL;
if (!arg)
arg = "";
catch_catch_command (char *arg, int from_tty, struct cmd_list_element *command)
{
int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
}
catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
{
int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
}
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
struct symtab_and_line sal;
- enum bptype type;
char *addr_string = NULL;
char *exp_string = NULL;
char *cond_string = NULL;
/* Implement the "catch syscall" command. */
static void
-catch_syscall_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
+catch_syscall_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
{
int tempflag;
VEC(int) *filter;
{
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)
|| !loc->enabled
|| loc->shlib_disabled
|| !breakpoint_address_is_meaningful (b)
- || tracepoint_type (b))
+ || is_tracepoint (b))
continue;
/* Permanent breakpoint should always be inserted. */
update_global_location_list_nothrow (int inserting)
{
struct gdb_exception e;
+
TRY_CATCH (e, RETURN_MASK_ERROR)
update_global_location_list (inserting);
}
bpstat_remove_breakpoint (bpstat bps, struct breakpoint *bpt)
{
bpstat bs;
+
for (bs = bps; bs; bs = bs->next)
if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
{
bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
{
struct breakpoint *bpt = data;
+
bpstat_remove_breakpoint (th->stop_bpstat, bpt);
return 0;
}
delete_breakpoint (struct breakpoint *bpt)
{
struct breakpoint *b;
- struct bp_location *loc, *next;
gdb_assert (bpt != NULL);
break;
}
- free_command_lines (&bpt->commands);
+ decref_counted_command_line (&bpt->commands);
xfree (bpt->cond_string);
xfree (bpt->cond_exp);
xfree (bpt->addr_string);
return make_cleanup (do_delete_breakpoint_cleanup, b);
}
+/* A callback for map_breakpoint_numbers that calls
+ delete_breakpoint. */
+
+static void
+do_delete_breakpoint (struct breakpoint *b, void *ignore)
+{
+ delete_breakpoint (b);
+}
+
void
delete_command (char *arg, int from_tty)
{
ALL_BREAKPOINTS (b)
{
if (b->type != bp_call_dummy
+ && b->type != bp_std_terminate
&& b->type != bp_shlib_event
&& b->type != bp_jit_event
&& b->type != bp_thread_event
&& b->type != bp_overlay_event
&& b->type != bp_longjmp_master
+ && b->type != bp_std_terminate_master
&& b->number >= 0)
{
breaks_to_delete = 1;
ALL_BREAKPOINTS_SAFE (b, temp)
{
if (b->type != bp_call_dummy
+ && b->type != bp_std_terminate
&& b->type != bp_shlib_event
&& b->type != bp_thread_event
&& b->type != bp_jit_event
&& b->type != bp_overlay_event
&& b->type != bp_longjmp_master
+ && b->type != bp_std_terminate_master
&& b->number >= 0)
delete_breakpoint (b);
}
}
}
else
- map_breakpoint_numbers (arg, delete_breakpoint);
+ map_breakpoint_numbers (arg, do_delete_breakpoint, NULL);
}
static int
{
struct bp_location *l;
htab_t htab = htab_create_alloc (13, htab_hash_string,
- (int (*) (const void *, const void *)) streq,
+ (int (*) (const void *,
+ const void *)) streq,
NULL, xcalloc, xfree);
for (l = loc; l != NULL; l = l->next)
{
/* get past catch_errs */
struct breakpoint *b = (struct breakpoint *) bint;
- struct value *mark;
- int i;
int not_found = 0;
int *not_found_ptr = ¬_found;
struct symtabs_and_lines sals = {0};
struct symtabs_and_lines expanded = {0};
char *s;
- enum enable_state save_enable;
struct gdb_exception e;
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
reset later by breakpoint_re_set. */
case bp_overlay_event:
case bp_longjmp_master:
+ case bp_std_terminate_master:
delete_breakpoint (b);
break;
case bp_finish:
case bp_watchpoint_scope:
case bp_call_dummy:
+ case bp_std_terminate:
case bp_step_resume:
case bp_longjmp:
case bp_longjmp_resume:
create_longjmp_master_breakpoint ("_longjmp");
create_longjmp_master_breakpoint ("siglongjmp");
create_longjmp_master_breakpoint ("_siglongjmp");
+ create_std_terminate_master_breakpoint ("std::terminate()");
}
\f
/* Reset the thread number of this breakpoint:
ALL_BREAKPOINTS (b)
if (b->number == bptnum)
{
+ if (is_tracepoint (b))
+ {
+ if (from_tty && count != 0)
+ printf_filtered (_("Ignore count ignored for tracepoint %d."),
+ bptnum);
+ return;
+ }
+
b->ignore_count = count;
if (from_tty)
{
whose numbers are given in ARGS. */
static void
-map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *))
+map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
+ void *),
+ void *data)
{
char *p = args;
char *p1;
{
struct breakpoint *related_breakpoint = b->related_breakpoint;
match = 1;
- function (b);
+ function (b, data);
if (related_breakpoint)
- function (related_breakpoint);
+ function (related_breakpoint, data);
break;
}
if (match == 0)
observer_notify_breakpoint_modified (bpt->number);
}
+/* A callback for map_breakpoint_numbers that calls
+ disable_breakpoint. */
+
+static void
+do_map_disable_breakpoint (struct breakpoint *b, void *ignore)
+{
+ disable_breakpoint (b);
+}
+
static void
disable_command (char *args, int from_tty)
{
struct breakpoint *bpt;
+
if (args == 0)
ALL_BREAKPOINTS (bpt)
switch (bpt->type)
update_global_location_list (0);
}
else
- map_breakpoint_numbers (args, disable_breakpoint);
+ map_breakpoint_numbers (args, do_map_disable_breakpoint, NULL);
}
static void
do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
{
- int target_resources_ok, other_type_used;
- struct value *mark;
+ int target_resources_ok;
if (bpt->type == bp_hardware_breakpoint)
{
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;
do_enable_breakpoint (bpt, bpt->disposition);
}
+/* A callback for map_breakpoint_numbers that calls
+ enable_breakpoint. */
+
+static void
+do_map_enable_breakpoint (struct breakpoint *b, void *ignore)
+{
+ enable_breakpoint (b);
+}
+
/* 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. */
enable_command (char *args, int from_tty)
{
struct breakpoint *bpt;
+
if (args == 0)
ALL_BREAKPOINTS (bpt)
switch (bpt->type)
update_global_location_list (1);
}
else
- map_breakpoint_numbers (args, enable_breakpoint);
+ map_breakpoint_numbers (args, do_map_enable_breakpoint, NULL);
}
static void
-enable_once_breakpoint (struct breakpoint *bpt)
+enable_once_breakpoint (struct breakpoint *bpt, void *ignore)
{
do_enable_breakpoint (bpt, disp_disable);
}
static void
enable_once_command (char *args, int from_tty)
{
- map_breakpoint_numbers (args, enable_once_breakpoint);
+ map_breakpoint_numbers (args, enable_once_breakpoint, NULL);
}
static void
-enable_delete_breakpoint (struct breakpoint *bpt)
+enable_delete_breakpoint (struct breakpoint *bpt, void *ignore)
{
do_enable_breakpoint (bpt, disp_del);
}
static void
enable_delete_command (char *args, int from_tty)
{
- map_breakpoint_numbers (args, enable_delete_breakpoint);
+ map_breakpoint_numbers (args, enable_delete_breakpoint, NULL);
}
\f
static void
decode_line_spec_1 (char *string, int funfirstline)
{
struct symtabs_and_lines sals;
+
if (string == 0)
error (_("Empty line specification."));
if (default_breakpoint_valid)
/* Check whether a software single-step breakpoint is inserted at PC. */
static int
-single_step_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
+single_step_breakpoint_inserted_here_p (struct address_space *aspace,
+ CORE_ADDR pc)
{
int i;
char *text, char *word)
{
const char **list = get_syscall_names ();
+
return (list == NULL) ? NULL : complete_on_enum (list, text, word);
}
set_tracepoint_count (breakpoint_count);
}
+/* Set up a fake reader function that gets command lines from a linked
+ list that was acquired during tracepoint uploading. */
+
+static struct uploaded_tp *this_utp;
+static int next_cmd;
+
+static char *
+read_uploaded_action (void)
+{
+ char *rslt;
+
+ VEC_iterate (char_ptr, this_utp->cmd_strings, next_cmd, rslt);
+
+ next_cmd++;
+
+ return rslt;
+}
+
/* Given information about a tracepoint as recorded on a target (which
can be either a live system or a trace file), attempt to create an
equivalent GDB tracepoint. This is not a reliable process, since
struct breakpoint *
create_tracepoint_from_upload (struct uploaded_tp *utp)
{
- char buf[100];
+ char *addr_str, small_buf[100];
struct breakpoint *tp;
- /* In the absence of a source location, fall back to raw address. */
- sprintf (buf, "*%s", paddress (get_current_arch(), utp->addr));
+ if (utp->at_string)
+ addr_str = utp->at_string;
+ else
+ {
+ /* In the absence of a source location, fall back to raw
+ address. Since there is no way to confirm that the address
+ means the same thing as when the trace was started, warn the
+ user. */
+ warning (_("Uploaded tracepoint %d has no source location, using raw address"),
+ utp->number);
+ sprintf (small_buf, "*%s", hex_string (utp->addr));
+ addr_str = small_buf;
+ }
+
+ /* There's not much we can do with a sequence of bytecodes. */
+ if (utp->cond && !utp->cond_string)
+ warning (_("Uploaded tracepoint %d condition has no source form, ignoring it"),
+ utp->number);
if (!create_breakpoint (get_current_arch (),
- buf,
- NULL, 0, 1 /* parse arg */,
+ addr_str,
+ utp->cond_string, -1, 0 /* parse cond/thread */,
0 /* tempflag */,
(utp->type == bp_fast_tracepoint) /* hardwareflag */,
1 /* traceflag */,
set_tracepoint_count (breakpoint_count);
+ /* Get the tracepoint we just created. */
tp = get_tracepoint (tracepoint_count);
gdb_assert (tp != NULL);
if (utp->pass > 0)
{
- sprintf (buf, "%d %d", utp->pass, tp->number);
+ sprintf (small_buf, "%d %d", utp->pass, tp->number);
- trace_pass_command (buf, 0);
+ trace_pass_command (small_buf, 0);
}
- if (utp->cond)
+ /* If we have uploaded versions of the original commands, set up a
+ special-purpose "reader" function and call the usual command line
+ reader, then pass the result to the breakpoint command-setting
+ function. */
+ if (!VEC_empty (char_ptr, utp->cmd_strings))
{
- printf_filtered ("Want to restore a condition\n");
- }
+ struct command_line *cmd_list;
- if (utp->numactions > 0)
- {
- printf_filtered ("Want to restore action list\n");
- }
+ this_utp = utp;
+ next_cmd = 0;
- if (utp->num_step_actions > 0)
- {
- printf_filtered ("Want to restore action list\n");
+ cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
+
+ breakpoint_set_commands (tp, cmd_list);
}
+ 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);
return tp;
}
static void
tracepoints_info (char *tpnum_exp, int from_tty)
{
- struct breakpoint *b;
- int tps_to_list = 0;
+ int tpnum = -1, num_printed;
+
+ if (tpnum_exp)
+ tpnum = parse_and_eval_long (tpnum_exp);
+
+ num_printed = breakpoint_1 (tpnum, 0, is_tracepoint);
- /* In the no-arguments case, say "No tracepoints" if none found. */
- if (tpnum_exp == 0)
+ if (num_printed == 0)
{
- ALL_TRACEPOINTS (b)
- {
- if (b->number >= 0)
- {
- tps_to_list = 1;
- break;
- }
- }
- if (!tps_to_list)
- {
- ui_out_message (uiout, 0, "No tracepoints.\n");
- return;
- }
+ if (tpnum == -1)
+ ui_out_message (uiout, 0, "No tracepoints.\n");
+ else
+ ui_out_message (uiout, 0, "No tracepoint number %d.\n", tpnum);
}
- /* Otherwise be the same as "info break". */
- breakpoints_info (tpnum_exp, from_tty);
+ default_collect_info ();
}
/* The 'enable trace' command enables tracepoints.
{
ALL_BREAKPOINTS_SAFE (b, temp)
{
- if (tracepoint_type (b)
+ if (is_tracepoint (b)
&& b->number >= 0)
delete_breakpoint (b);
}
}
}
else
- map_breakpoint_numbers (arg, delete_breakpoint);
+ map_breakpoint_numbers (arg, do_delete_breakpoint, NULL);
}
/* Set passcount for tracepoint.
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 action_line *line;
- FILE *fp;
- char *i1 = " ", *i2 = " ";
- char *indent, *actionline, *pathname;
- char tmp[40];
+ int any = 0;
+ char *pathname;
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 = fopen (pathname, "w");
+ fp = gdb_fopen (pathname, "w");
if (!fp)
- error (_("Unable to open file '%s' for saving tracepoints (%s)"),
- args, safe_strerror (errno));
- make_cleanup_fclose (fp);
-
- ALL_TRACEPOINTS (tp)
+ error (_("Unable to open file '%s' for saving (%s)"),
+ filename, safe_strerror (errno));
+ make_cleanup_ui_file_delete (fp);
+
+ if (extra_trace_bits)
+ save_trace_state_variables (fp);
+
+ ALL_BREAKPOINTS (tp)
{
- if (tp->addr_string)
- fprintf (fp, "trace %s\n", tp->addr_string);
+ /* 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->ops != NULL)
+ (tp->ops->print_recreate) (tp, fp);
else
{
- sprintf_vma (tmp, tp->loc->address);
- fprintf (fp, "trace *0x%s\n", 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->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 (fp, " passcount %d\n", tp->pass_count);
+ fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count);
- if (tp->actions)
+ if (tp->commands)
{
- fprintf (fp, " actions\n");
- indent = i1;
- for (line = tp->actions; line; line = line->next)
+ volatile struct gdb_exception ex;
+
+ fprintf_unfiltered (fp, " commands\n");
+
+ ui_out_redirect (uiout, fp);
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
{
- struct cmd_list_element *cmd;
+ print_command_lines (uiout, tp->commands->commands, 2);
+ }
+ ui_out_redirect (uiout, NULL);
- QUIT; /* allow user to bail out with ^C */
- actionline = line->action;
- while (isspace ((int) *actionline))
- actionline++;
+ if (ex.reason < 0)
+ throw_exception (ex);
- fprintf (fp, "%s%s\n", indent, actionline);
- if (*actionline != '#') /* skip for comment lines */
- {
- cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
- if (cmd == 0)
- error (_("Bad action list item: %s"), actionline);
- if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
- indent = i2;
- else if (cmd_cfunc_eq (cmd, end_actions_pseudocommand))
- indent = i1;
- }
- }
+ 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 (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);
an expression is either read or written."));
set_cmd_completer (c, expression_completer);
- add_info ("watchpoints", breakpoints_info,
- _("Synonym for ``info breakpoints''."));
+ add_info ("watchpoints", watchpoints_info, _("\
+Status of watchpoints, or watchpoint number NUMBER."));
+
/* XXX: cagney/2005-02-23: This should be a boolean, and should
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\