/* Everything about breakpoints, for GDB.
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2021 Free Software Foundation, Inc.
This file is part of GDB.
static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch,
CORE_ADDR bpaddr,
- enum bptype bptype);
+ enum bptype bptype);
static void describe_other_breakpoints (struct gdbarch *,
struct program_space *, CORE_ADDR,
static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp,
int count);
-static void free_bp_location (struct bp_location *loc);
-static void incref_bp_location (struct bp_location *loc);
static void decref_bp_location (struct bp_location **loc);
static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
}
/* If we reach here, the condition is valid at some locations. */
- int loc_num = 1;
- for (bp_location *loc = b->loc; loc != nullptr;
- loc = loc->next, loc_num++)
- set_breakpoint_location_condition (exp, loc, b->number, loc_num);
+ int loc_num = 1;
+ for (bp_location *loc = b->loc; loc != nullptr;
+ loc = loc->next, loc_num++)
+ set_breakpoint_location_condition (exp, loc, b->number, loc_num);
}
/* We know that the new condition parsed successfully. The
gdb::observers::breakpoint_modified.notify (b);
}
+/* The options for the "condition" command. */
+
+struct condition_command_opts
+{
+ /* For "-force". */
+ bool force_condition = false;
+};
+
+static const gdb::option::option_def condition_command_option_defs[] = {
+
+ gdb::option::flag_option_def<condition_command_opts> {
+ "force",
+ [] (condition_command_opts *opts) { return &opts->force_condition; },
+ N_("Set the condition even if it is invalid for all current locations."),
+ },
+
+};
+
+/* Create an option_def_group for the "condition" options, with
+ CC_OPTS as context. */
+
+static inline gdb::option::option_def_group
+make_condition_command_options_def_group (condition_command_opts *cc_opts)
+{
+ return {{condition_command_option_defs}, cc_opts};
+}
+
/* Completion for the "condition" command. */
static void
condition_completer (struct cmd_list_element *cmd,
completion_tracker &tracker,
- const char *text, const char *word)
+ const char *text, const char * /*word*/)
{
- const char *space;
+ bool has_no_arguments = (*text == '\0');
+ condition_command_opts cc_opts;
+ const auto group = make_condition_command_options_def_group (&cc_opts);
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group))
+ return;
text = skip_spaces (text);
- space = skip_to_space (text);
+ const char *space = skip_to_space (text);
if (*space == '\0')
{
int len;
if (text[0] == '$')
{
+ tracker.advance_custom_word_point_by (1);
/* We don't support completion of history indices. */
if (!isdigit (text[1]))
complete_internalvar (tracker, &text[1]);
return;
}
+ /* Suggest the "-force" flag if no arguments are given. If
+ arguments were passed, they either already include the flag,
+ or we are beyond the point of suggesting it because it's
+ positionally the first argument. */
+ if (has_no_arguments)
+ gdb::option::complete_on_all_options (tracker, group);
+
/* We're completing the breakpoint number. */
len = strlen (text);
return;
}
- /* We're completing the expression part. */
- text = skip_spaces (space);
+ /* We're completing the expression part. Skip the breakpoint num. */
+ const char *exp_start = skip_spaces (space);
+ tracker.advance_custom_word_point_by (exp_start - text);
+ text = exp_start;
+ const char *word = advance_to_expression_complete_word_point (tracker, text);
expression_completer (cmd, tracker, text, word);
}
p = arg;
/* Check if the "-force" flag was passed. */
- bool force = false;
- const char *tok = skip_spaces (p);
- const char *end_tok = skip_to_space (tok);
- int toklen = end_tok - tok;
- if (toklen >= 1 && strncmp (tok, "-force", toklen) == 0)
- {
- force = true;
- p = end_tok + 1;
- }
+ condition_command_opts cc_opts;
+ const auto group = make_condition_command_options_def_group (&cc_opts);
+ gdb::option::process_options
+ (&p, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
bnum = get_number (&p);
if (bnum == 0)
" a %s stop condition defined for this breakpoint."),
ext_lang_capitalized_name (extlang));
}
- set_breakpoint_condition (b, p, from_tty, force);
+ set_breakpoint_condition (b, p, from_tty, cc_opts.force_condition);
if (is_breakpoint (b))
update_global_location_list (UGLL_MAY_INSERT);
struct command_line *while_stepping = 0;
/* Reset the while-stepping step count. The previous commands
- might have included a while-stepping action, while the new
- ones might not. */
+ might have included a while-stepping action, while the new
+ ones might not. */
t->step_count = 0;
/* We need to verify that each top-level element of commands is
return;
/* Save the current frame's ID so we can restore it after
- evaluating the watchpoint expression on its own frame. */
+ evaluating the watchpoint expression on its own frame. */
/* FIXME drow/2003-09-09: It would be nice if evaluate_expression
- took a frame parameter, so that we didn't have to change the
- selected frame. */
+ took a frame parameter, so that we didn't have to change the
+ selected frame. */
frame_saved = 1;
saved_frame_id = get_frame_id (get_selected_frame (NULL));
struct value *v, *result;
struct program_space *frame_pspace;
- fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, 0);
+ fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, false);
/* Avoid setting b->val if it's already set. The meaning of
b->val is 'the last value' user saw, and we should update
&& stepping_past_nonsteppable_watchpoint ())
{
infrun_debug_printf ("stepping past non-steppable watchpoint. "
- "skipping watchpoint at %s:%d\n",
+ "skipping watchpoint at %s:%d",
paddress (bl->gdbarch, bl->address), bl->length);
return 0;
}
{
/* Yes. This overlay section is mapped into memory. */
try
- {
+ {
int val;
- val = bl->owner->ops->insert_location (bl);
+ val = bl->owner->ops->insert_location (bl);
if (val)
bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
- }
+ }
catch (gdb_exception &e)
- {
+ {
bp_excpt = std::move (e);
- }
+ }
}
else
{
{
*hw_breakpoint_error = 1;
*hw_bp_error_explained_already = bp_excpt.message != NULL;
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert hardware breakpoint %d%s",
- bl->owner->number,
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert hardware breakpoint %d%s",
+ bl->owner->number,
bp_excpt.message ? ":" : ".\n");
- if (bp_excpt.message != NULL)
- fprintf_unfiltered (tmp_error_stream, "%s.\n",
+ if (bp_excpt.message != NULL)
+ fprintf_unfiltered (tmp_error_stream, "%s.\n",
bp_excpt.what ());
}
else
if (error_flag)
{
/* If a hardware breakpoint or watchpoint was inserted, add a
- message about possibly exhausted resources. */
+ message about possibly exhausted resources. */
if (hw_breakpoint_error && !hw_bp_error_explained_already)
{
tmp_error_stream.printf ("Could not insert hardware breakpoints:\n\
addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
b = create_internal_breakpoint (objfile->arch (), addr,
- bp_overlay_event,
+ bp_overlay_event,
&internal_breakpoint_ops);
initialize_explicit_location (&explicit_loc);
explicit_loc.function_name = ASTRDUP (func_name);
b->location = new_explicit_location (&explicit_loc);
if (overlay_debugging == ovly_auto)
- {
- b->enable_state = bp_enabled;
- overlay_events_enabled = 1;
- }
+ {
+ b->enable_state = bp_enabled;
+ overlay_events_enabled = 1;
+ }
else
{
- b->enable_state = bp_disabled;
- overlay_events_enabled = 0;
+ b->enable_state = bp_disabled;
+ overlay_events_enabled = 0;
}
}
}
-static void
-create_longjmp_master_breakpoint (void)
+/* Install a master longjmp breakpoint for OBJFILE using a probe. Return
+ true if a breakpoint was installed. */
+
+static bool
+create_longjmp_master_breakpoint_probe (objfile *objfile)
{
- scoped_restore_current_program_space restore_pspace;
+ struct gdbarch *gdbarch = objfile->arch ();
+ struct breakpoint_objfile_data *bp_objfile_data
+ = get_breakpoint_objfile_data (objfile);
- for (struct program_space *pspace : program_spaces)
+ if (!bp_objfile_data->longjmp_searched)
{
- set_current_program_space (pspace);
+ std::vector<probe *> ret
+ = find_probes_in_objfile (objfile, "libc", "longjmp");
- for (objfile *objfile : current_program_space->objfiles ())
+ if (!ret.empty ())
{
- int i;
- struct gdbarch *gdbarch;
- struct breakpoint_objfile_data *bp_objfile_data;
+ /* We are only interested in checking one element. */
+ probe *p = ret[0];
- gdbarch = objfile->arch ();
+ if (!p->can_evaluate_arguments ())
+ {
+ /* We cannot use the probe interface here,
+ because it does not know how to evaluate
+ arguments. */
+ ret.clear ();
+ }
+ }
+ bp_objfile_data->longjmp_probes = ret;
+ bp_objfile_data->longjmp_searched = 1;
+ }
- bp_objfile_data = get_breakpoint_objfile_data (objfile);
+ if (bp_objfile_data->longjmp_probes.empty ())
+ return false;
- if (!bp_objfile_data->longjmp_searched)
- {
- std::vector<probe *> ret
- = find_probes_in_objfile (objfile, "libc", "longjmp");
+ for (probe *p : bp_objfile_data->longjmp_probes)
+ {
+ struct breakpoint *b;
- if (!ret.empty ())
- {
- /* We are only interested in checking one element. */
- probe *p = ret[0];
+ b = create_internal_breakpoint (gdbarch,
+ p->get_relocated_address (objfile),
+ bp_longjmp_master,
+ &internal_breakpoint_ops);
+ b->location = new_probe_location ("-probe-stap libc:longjmp");
+ b->enable_state = bp_disabled;
+ }
- if (!p->can_evaluate_arguments ())
- {
- /* We cannot use the probe interface here,
- because it does not know how to evaluate
- arguments. */
- ret.clear ();
- }
- }
- bp_objfile_data->longjmp_probes = ret;
- bp_objfile_data->longjmp_searched = 1;
- }
+ return true;
+}
- if (!bp_objfile_data->longjmp_probes.empty ())
- {
- for (probe *p : bp_objfile_data->longjmp_probes)
- {
- struct breakpoint *b;
-
- b = create_internal_breakpoint (gdbarch,
- p->get_relocated_address (objfile),
- bp_longjmp_master,
- &internal_breakpoint_ops);
- b->location = new_probe_location ("-probe-stap libc:longjmp");
- b->enable_state = bp_disabled;
- }
+/* Install master longjmp breakpoints for OBJFILE using longjmp_names.
+ Return true if at least one breakpoint was installed. */
+static bool
+create_longjmp_master_breakpoint_names (objfile *objfile)
+{
+ struct gdbarch *gdbarch = objfile->arch ();
+ if (!gdbarch_get_longjmp_target_p (gdbarch))
+ return false;
+
+ struct breakpoint_objfile_data *bp_objfile_data
+ = get_breakpoint_objfile_data (objfile);
+ unsigned int installed_bp = 0;
+
+ for (int i = 0; i < NUM_LONGJMP_NAMES; i++)
+ {
+ struct breakpoint *b;
+ const char *func_name;
+ CORE_ADDR addr;
+ struct explicit_location explicit_loc;
+
+ if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
+ continue;
+
+ func_name = longjmp_names[i];
+ if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
+ {
+ struct bound_minimal_symbol m;
+
+ m = lookup_minimal_symbol_text (func_name, objfile);
+ if (m.minsym == NULL)
+ {
+ /* Prevent future lookups in this objfile. */
+ bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
continue;
}
+ bp_objfile_data->longjmp_msym[i] = m;
+ }
- if (!gdbarch_get_longjmp_target_p (gdbarch))
- continue;
+ addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
+ b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
+ &internal_breakpoint_ops);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit_loc);
+ b->enable_state = bp_disabled;
+ installed_bp++;
+ }
- for (i = 0; i < NUM_LONGJMP_NAMES; i++)
- {
- struct breakpoint *b;
- const char *func_name;
- CORE_ADDR addr;
- struct explicit_location explicit_loc;
+ return installed_bp > 0;
+}
- if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
- continue;
+/* Create a master longjmp breakpoint. */
- func_name = longjmp_names[i];
- if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
- {
- struct bound_minimal_symbol m;
+static void
+create_longjmp_master_breakpoint (void)
+{
+ scoped_restore_current_program_space restore_pspace;
- m = lookup_minimal_symbol_text (func_name, objfile);
- if (m.minsym == NULL)
- {
- /* Prevent future lookups in this objfile. */
- bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
- continue;
- }
- bp_objfile_data->longjmp_msym[i] = m;
- }
+ for (struct program_space *pspace : program_spaces)
+ {
+ set_current_program_space (pspace);
- addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
- b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
- &internal_breakpoint_ops);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.function_name = ASTRDUP (func_name);
- b->location = new_explicit_location (&explicit_loc);
- b->enable_state = bp_disabled;
- }
+ for (objfile *obj : current_program_space->objfiles ())
+ {
+ /* Skip separate debug object, it's handled in the loop below. */
+ if (obj->separate_debug_objfile_backlink != nullptr)
+ continue;
+
+ /* Try a probe kind breakpoint on main objfile. */
+ if (create_longjmp_master_breakpoint_probe (obj))
+ continue;
+
+ /* Try longjmp_names kind breakpoints on main and separate_debug
+ objfiles. */
+ for (objfile *debug_objfile : obj->separate_debug_objfiles ())
+ if (create_longjmp_master_breakpoint_names (debug_objfile))
+ break;
}
}
}
}
}
-/* Install a master breakpoint on the unwinder's debug hook. */
+/* Install a master breakpoint on the unwinder's debug hook for OBJFILE using a
+ probe. Return true if a breakpoint was installed. */
-static void
-create_exception_master_breakpoint (void)
+static bool
+create_exception_master_breakpoint_probe (objfile *objfile)
{
- const char *const func_name = "_Unwind_DebugHook";
+ struct breakpoint *b;
+ struct gdbarch *gdbarch;
+ struct breakpoint_objfile_data *bp_objfile_data;
- for (objfile *objfile : current_program_space->objfiles ())
- {
- struct breakpoint *b;
- struct gdbarch *gdbarch;
- struct breakpoint_objfile_data *bp_objfile_data;
- CORE_ADDR addr;
- struct explicit_location explicit_loc;
+ bp_objfile_data = get_breakpoint_objfile_data (objfile);
- bp_objfile_data = get_breakpoint_objfile_data (objfile);
+ /* We prefer the SystemTap probe point if it exists. */
+ if (!bp_objfile_data->exception_searched)
+ {
+ std::vector<probe *> ret
+ = find_probes_in_objfile (objfile, "libgcc", "unwind");
- /* We prefer the SystemTap probe point if it exists. */
- if (!bp_objfile_data->exception_searched)
+ if (!ret.empty ())
{
- std::vector<probe *> ret
- = find_probes_in_objfile (objfile, "libgcc", "unwind");
+ /* We are only interested in checking one element. */
+ probe *p = ret[0];
- if (!ret.empty ())
+ if (!p->can_evaluate_arguments ())
{
- /* We are only interested in checking one element. */
- probe *p = ret[0];
-
- if (!p->can_evaluate_arguments ())
- {
- /* We cannot use the probe interface here, because it does
- not know how to evaluate arguments. */
- ret.clear ();
- }
+ /* We cannot use the probe interface here, because it does
+ not know how to evaluate arguments. */
+ ret.clear ();
}
- bp_objfile_data->exception_probes = ret;
- bp_objfile_data->exception_searched = 1;
}
+ bp_objfile_data->exception_probes = ret;
+ bp_objfile_data->exception_searched = 1;
+ }
- if (!bp_objfile_data->exception_probes.empty ())
- {
- gdbarch = objfile->arch ();
+ if (bp_objfile_data->exception_probes.empty ())
+ return false;
- for (probe *p : bp_objfile_data->exception_probes)
- {
- b = create_internal_breakpoint (gdbarch,
- p->get_relocated_address (objfile),
- bp_exception_master,
- &internal_breakpoint_ops);
- b->location = new_probe_location ("-probe-stap libgcc:unwind");
- b->enable_state = bp_disabled;
- }
+ gdbarch = objfile->arch ();
- continue;
- }
+ for (probe *p : bp_objfile_data->exception_probes)
+ {
+ b = create_internal_breakpoint (gdbarch,
+ p->get_relocated_address (objfile),
+ bp_exception_master,
+ &internal_breakpoint_ops);
+ b->location = new_probe_location ("-probe-stap libgcc:unwind");
+ b->enable_state = bp_disabled;
+ }
- /* Otherwise, try the hook function. */
+ return true;
+}
- if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
- continue;
+/* Install a master breakpoint on the unwinder's debug hook for OBJFILE using
+ _Unwind_DebugHook. Return true if a breakpoint was installed. */
- gdbarch = objfile->arch ();
+static bool
+create_exception_master_breakpoint_hook (objfile *objfile)
+{
+ const char *const func_name = "_Unwind_DebugHook";
+ struct breakpoint *b;
+ struct gdbarch *gdbarch;
+ struct breakpoint_objfile_data *bp_objfile_data;
+ CORE_ADDR addr;
+ struct explicit_location explicit_loc;
- if (bp_objfile_data->exception_msym.minsym == NULL)
- {
- struct bound_minimal_symbol debug_hook;
+ bp_objfile_data = get_breakpoint_objfile_data (objfile);
- debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
- if (debug_hook.minsym == NULL)
- {
- bp_objfile_data->exception_msym.minsym = &msym_not_found;
- continue;
- }
+ if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
+ return false;
+
+ gdbarch = objfile->arch ();
+
+ if (bp_objfile_data->exception_msym.minsym == NULL)
+ {
+ struct bound_minimal_symbol debug_hook;
- bp_objfile_data->exception_msym = debug_hook;
+ debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
+ if (debug_hook.minsym == NULL)
+ {
+ bp_objfile_data->exception_msym.minsym = &msym_not_found;
+ return false;
}
- addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
- addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
- current_top_target ());
- b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
- &internal_breakpoint_ops);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.function_name = ASTRDUP (func_name);
- b->location = new_explicit_location (&explicit_loc);
- b->enable_state = bp_disabled;
+ bp_objfile_data->exception_msym = debug_hook;
+ }
+
+ addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
+ addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
+ current_top_target ());
+ b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
+ &internal_breakpoint_ops);
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit_loc);
+ b->enable_state = bp_disabled;
+
+ return true;
+}
+
+/* Install a master breakpoint on the unwinder's debug hook. */
+
+static void
+create_exception_master_breakpoint (void)
+{
+ for (objfile *obj : current_program_space->objfiles ())
+ {
+ /* Skip separate debug object. */
+ if (obj->separate_debug_objfile_backlink)
+ continue;
+
+ /* Try a probe kind breakpoint. */
+ if (create_exception_master_breakpoint_probe (obj))
+ continue;
+
+ /* Iterate over separate debug objects and try an _Unwind_DebugHook
+ kind breakpoint. */
+ for (objfile *sepdebug = obj->separate_debug_objfile;
+ sepdebug != nullptr; sepdebug = sepdebug->separate_debug_objfile)
+ if (create_exception_master_breakpoint_hook (sepdebug))
+ break;
}
}
if (b->type == bp_catchpoint)
{
- /* For now, none of the bp_catchpoint breakpoints need to
- do anything at this point. In the future, if some of
- the catchpoints need to something, we will need to add
- a new method, and call this method from here. */
- continue;
+ /* For now, none of the bp_catchpoint breakpoints need to
+ do anything at this point. In the future, if some of
+ the catchpoints need to something, we will need to add
+ a new method, and call this method from here. */
+ continue;
}
/* bp_finish is a special case. The only way we ought to be able
bl->owner->number);
}
else if (bl->owner->type == bp_catchpoint
- && breakpoint_enabled (bl->owner)
- && !bl->duplicate)
+ && breakpoint_enabled (bl->owner)
+ && !bl->duplicate)
{
gdb_assert (bl->owner->ops != NULL
&& bl->owner->ops->remove_location != NULL);
return (b->type == bp_catchpoint);
}
-/* Frees any storage that is part of a bpstat. Does not walk the
- 'next' chain. */
-
-bpstats::~bpstats ()
-{
- if (bp_location_at != NULL)
- decref_bp_location (&bp_location_at);
-}
-
/* Clear a bpstat so that it says we are not at any breakpoint.
Also free any storage that is part of a bpstat. */
{
if (other.old_val != NULL)
old_val = release_value (value_copy (other.old_val.get ()));
- incref_bp_location (bp_location_at);
}
/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
/* Take ownership of the BSP's command tree, if it has one.
- The command tree could legitimately contain commands like
- 'step' and 'next', which call clear_proceed_status, which
- frees stop_bpstat's command tree. To make sure this doesn't
- free the tree we're executing out from under us, we need to
- take ownership of the tree ourselves. Since a given bpstat's
- 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. */
+ The command tree could legitimately contain commands like
+ 'step' and 'next', which call clear_proceed_status, which
+ frees stop_bpstat's command tree. To make sure this doesn't
+ free the tree we're executing out from under us, we need to
+ take ownership of the tree ourselves. Since a given bpstat's
+ 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. */
counted_command_line ccmd = bs->commands;
bs->commands = NULL;
if (ccmd != NULL)
case print_it_done:
/* We still want to print the frame, but we already printed the
- relevant messages. */
+ relevant messages. */
return PRINT_SRC_AND_LOC;
break;
bpstats::bpstats (struct bp_location *bl, bpstat **bs_link_pointer)
: next (NULL),
- bp_location_at (bl),
+ bp_location_at (bp_location_ref_ptr::new_reference (bl)),
breakpoint_at (bl->owner),
commands (NULL),
print (0),
stop (0),
print_it (print_it_normal)
{
- incref_bp_location (bl);
**bs_link_pointer = this;
*bs_link_pointer = &next;
}
bpstats::bpstats ()
: next (NULL),
- bp_location_at (NULL),
breakpoint_at (NULL),
commands (NULL),
print (0),
if (within_current_scope)
{
/* We use value_{,free_to_}mark because it could be a *long*
- time before we return to the command level and call
- free_all_values. We can't call free_all_values because we
- might be in the middle of evaluating a function call. */
+ time before we return to the command level and call
+ free_all_values. We can't call free_all_values because we
+ might be in the middle of evaluating a function call. */
int pc = 0;
struct value *mark;
return WP_VALUE_CHANGED;
mark = value_mark ();
- fetch_subexp_value (b->exp.get (), &pc, &new_val, NULL, NULL, 0);
+ fetch_subexp_value (b->exp.get (), &pc, &new_val, NULL, NULL, false);
if (b->val_bitsize != 0)
new_val = extract_bitfield_from_watchpoint_value (b, new_val);
else
{
/* This seems like the only logical thing to do because
- if we temporarily ignored the watchpoint, then when
- we reenter the block in which it is valid it contains
- garbage (in the case of a function, it may have two
- garbage values, one before and one after the prologue).
- So we can't even detect the first assignment to it and
- watch after that (since the garbage may or may not equal
- the first value assigned). */
+ if we temporarily ignored the watchpoint, then when
+ we reenter the block in which it is valid it contains
+ garbage (in the case of a function, it may have two
+ garbage values, one before and one after the prologue).
+ So we can't even detect the first assignment to it and
+ watch after that (since the garbage may or may not equal
+ the first value assigned). */
/* We print all the stop information in
breakpoint_ops->print_it, but in this case, by the time we
call breakpoint_ops->print_it this bp will be deleted
here. */
SWITCH_THRU_ALL_UIS ()
- {
+ {
struct ui_out *uiout = current_uiout;
if (uiout->is_mi_like_p ())
struct watchpoint *b;
/* BS is built for existing struct breakpoint. */
- bl = bs->bp_location_at;
+ bl = bs->bp_location_at.get ();
gdb_assert (bl != NULL);
b = (struct watchpoint *) bs->breakpoint_at;
gdb_assert (b != NULL);
gdb_assert (bs->stop);
/* BS is built for existing struct breakpoint. */
- bl = bs->bp_location_at;
+ bl = bs->bp_location_at.get ();
gdb_assert (bl != NULL);
b = bs->breakpoint_at;
gdb_assert (b != NULL);
inf_nums.push_back (inf->num);
}
- /* For backward compatibility, don't display inferiors in CLI unless
+ /* For backward compatibility, don't display inferiors in CLI unless
there are several. Always display for MI. */
if (allflag
|| (!gdbarch_has_global_breakpoints (target_gdbarch ())
annotate_field (6);
uiout->text ("\tstop only in stack frame at ");
/* FIXME: cagney/2002-12-01: Shouldn't be poking around inside
- the frame ID. */
+ the frame ID. */
uiout->field_core_addr ("frame",
b->gdbarch, b->frame_id.stack_addr);
uiout->text ("\n");
ALL_BREAKPOINTS (b)
others += (user_breakpoint_p (b)
- && breakpoint_has_pc (b, pspace, pc, section));
+ && breakpoint_has_pc (b, pspace, pc, section));
if (others > 0)
{
if (others == 1)
static void
breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
- int bnum, int have_bnum)
+ int bnum, int have_bnum)
{
/* The longest string possibly returned by hex_string_custom
is 50 chars. These must be at least that big for safety. */
strcpy (astr2, hex_string_custom ((unsigned long) to_addr, 8));
if (have_bnum)
warning (_("Breakpoint %d address previously adjusted from %s to %s."),
- bnum, astr1, astr2);
+ bnum, astr1, astr2);
else
warning (_("Breakpoint address adjusted from %s to %s."), astr1, astr2);
}
|| bptype == bp_catchpoint)
{
/* Watchpoints and the various bp_catch_* eventpoints should not
- have their addresses modified. */
+ have their addresses modified. */
return bpaddr;
}
else if (bptype == bp_single_step)
adjusted_bpaddr = address_significant (gdbarch, adjusted_bpaddr);
/* An adjusted breakpoint address can significantly alter
- a user's expectations. Print a warning if an adjustment
+ a user's expectations. Print a warning if an adjustment
is required. */
if (adjusted_bpaddr != bpaddr)
breakpoint_adjustment_warning (bpaddr, adjusted_bpaddr, 0, 0);
|| this->loc_type == bp_loc_hardware_breakpoint)
mark_breakpoint_location_modified (this);
- this->refc = 1;
+ incref ();
}
bp_location::bp_location (breakpoint *owner)
return bpt->ops->allocate_location (bpt);
}
-static void
-free_bp_location (struct bp_location *loc)
-{
- delete loc;
-}
-
-/* Increment reference count. */
-
-static void
-incref_bp_location (struct bp_location *bl)
-{
- ++bl->refc;
-}
-
/* Decrement reference count. If the reference count reaches 0,
destroy the bp_location. Sets *BLP to NULL. */
static void
decref_bp_location (struct bp_location **blp)
{
- gdb_assert ((*blp)->refc > 0);
-
- if (--(*blp)->refc == 0)
- free_bp_location (*blp);
+ bp_location_ref_policy::decref (*blp);
*blp = NULL;
}
mess more complicated breakpoints with multiple locations. */
b->type = bp_gnu_ifunc_resolver;
/* Remember the resolver's address for use by the return
- breakpoint. */
+ breakpoint. */
loc->related_address = loc->address;
}
}
static void
create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch,
bool temp, const char *cond_string,
- const struct breakpoint_ops *ops)
+ const struct breakpoint_ops *ops)
{
std::unique_ptr<fork_catchpoint> c (new fork_catchpoint ());
}
else if (toklen >= 1 && strncmp (tok, "-force-condition", toklen) == 0)
{
- tok = cond_start = end_tok + 1;
+ tok = tok + toklen;
force = true;
}
else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
exception_print (gdb_stderr, e);
- /* If pending breakpoint support is auto query and the user
+ /* If pending breakpoint support is auto query and the user
selects no, then simply return the error code. */
if (pending_break_support == AUTO_BOOLEAN_AUTO
&& !nquery (_("Make %s pending on future shared library load? "),
gdb::unique_xmalloc_ptr<char> extra_string_copy;
if (parse_extra)
- {
+ {
char *rest;
char *cond;
&cond, &thread, &task, &rest);
cond_string_copy.reset (cond);
extra_string_copy.reset (rest);
- }
+ }
else
- {
+ {
if (type_wanted != bp_dprintf
&& extra_string != NULL && *extra_string != '\0')
error (_("Garbage '%s' at end of location"), extra_string);
/* Create a private copy of any extra string. */
if (extra_string)
extra_string_copy.reset (xstrdup (extra_string));
- }
+ }
ops->create_breakpoints_sal (gdbarch, &canonical,
std::move (cond_string_copy),
b->condition_not_parsed = 1;
b->enable_state = enabled ? bp_enabled : bp_disabled;
if ((type_wanted != bp_breakpoint
- && type_wanted != bp_hardware_breakpoint) || thread != -1)
+ && type_wanted != bp_hardware_breakpoint) || thread != -1)
b->pspace = current_program_space;
install_breakpoint (internal, std::move (b), 0);
sal->pc = pc;
/* If this SAL corresponds to a breakpoint inserted using a line
- number, then skip the function prologue if necessary. */
+ number, then skip the function prologue if necessary. */
if (sal->explicit_line)
skip_prologue_sal (sal);
}
else
{
/* It really is worthwhile to have the section, so we'll
- just have to look harder. This case can be executed
- if we have line numbers but no functions (as can
- happen in assembly source). */
+ just have to look harder. This case can be executed
+ if we have line numbers but no functions (as can
+ happen in assembly source). */
scoped_restore_current_pspace_and_thread restore_pspace_thread;
switch_to_program_space_and_thread (sal->pspace);
int hasColon = 0;
/* Look for a ':'. If this is a line number specification, then
- say it is bad, otherwise, it should be an address or
- function/method name. */
+ say it is bad, otherwise, it should be an address or
+ function/method name. */
while (*argptr && !hasColon)
{
hasColon = (*argptr == ':');
int hasColon = 0;
/* Look for a ':'. If there is a '::' then get out, otherwise
- it is probably a line number. */
+ it is probably a line number. */
while (*argptr && !hasColon)
{
hasColon = (*argptr == ':');
some constant expressions and in such case still falsely return
zero. */
-static int
+static bool
watchpoint_exp_is_const (const struct expression *exp)
{
int i = exp->nelts;
if (SYMBOL_CLASS (s) != LOC_BLOCK
&& SYMBOL_CLASS (s) != LOC_CONST
&& SYMBOL_CLASS (s) != LOC_CONST_BYTES)
- return 0;
+ return false;
break;
}
the optimistic approach here: If we don't know something,
then it is not a constant. */
default:
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
/* Watchpoint destructor. */
struct watchpoint *w = (struct watchpoint *) bl->owner;
return target_remove_mask_watchpoint (bl->address, w->hw_wp_mask,
- bl->watchpoint_type);
+ bl->watchpoint_type);
}
/* Implement the "resources_needed" breakpoint_ops method for
}
/* accessflag: hw_write: watch write,
- hw_read: watch read,
+ hw_read: watch read,
hw_access: watch access (read or write) */
static void
watch_command_1 (const char *arg, int accessflag, int from_tty,
- int just_location, int internal)
+ bool just_location, bool internal)
{
struct breakpoint *scope_breakpoint = NULL;
const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
int pc = 0;
/* Flag to indicate whether we are going to use masks for
the hardware watchpoint. */
- int use_mask = 0;
+ bool use_mask = false;
CORE_ADDR mask = 0;
/* Make sure that we actually have parameters to parse. */
if (use_mask)
error(_("You can specify only one mask."));
- use_mask = just_location = 1;
+ use_mask = just_location = true;
mark = value_mark ();
mask_value = parse_to_comma_and_eval (&value_start);
else
{
/* Ahh, memory we actually used! Check if we can cover
- it with hardware watchpoints. */
+ it with hardware watchpoints. */
struct type *vtype = check_typedef (value_type (v));
/* We only watch structs and arrays if user asked for it
}
void
-watch_command_wrapper (const char *arg, int from_tty, int internal)
+watch_command_wrapper (const char *arg, int from_tty, bool internal)
{
watch_command_1 (arg, hw_write, from_tty, 0, internal);
}
+/* Options for the watch, awatch, and rwatch commands. */
+
+struct watch_options
+{
+ /* For -location. */
+ bool location = false;
+};
+
+/* Definitions of options for the "watch", "awatch", and "rwatch" commands.
+
+ Historically GDB always accepted both '-location' and '-l' flags for
+ these commands (both flags being synonyms). When converting to the
+ newer option scheme only '-location' is added here. That's fine (for
+ backward compatibility) as any non-ambiguous prefix of a flag will be
+ accepted, so '-l', '-loc', are now all accepted.
+
+ What this means is that, if in the future, we add any new flag here
+ that starts with '-l' then this will break backward compatibility, so
+ please, don't do that! */
+
+static const gdb::option::option_def watch_option_defs[] = {
+ gdb::option::flag_option_def<watch_options> {
+ "location",
+ [] (watch_options *opt) { return &opt->location; },
+ N_("\
+This evaluates EXPRESSION and watches the memory to which is refers.\n\
+-l can be used as a short form of -location."),
+ },
+};
+
+/* Returns the option group used by 'watch', 'awatch', and 'rwatch'
+ commands. */
+
+static gdb::option::option_def_group
+make_watch_options_def_group (watch_options *opts)
+{
+ return {{watch_option_defs}, opts};
+}
+
/* A helper function that looks for the "-location" argument and then
calls watch_command_1. */
static void
watch_maybe_just_location (const char *arg, int accessflag, int from_tty)
{
- int just_location = 0;
+ watch_options opts;
+ auto grp = make_watch_options_def_group (&opts);
+ gdb::option::process_options
+ (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+ if (arg != nullptr && *arg == '\0')
+ arg = nullptr;
+
+ watch_command_1 (arg, accessflag, from_tty, opts.location, false);
+}
- if (arg
- && (check_for_argument (&arg, "-location", sizeof ("-location") - 1)
- || check_for_argument (&arg, "-l", sizeof ("-l") - 1)))
- just_location = 1;
+/* Command completion for 'watch', 'awatch', and 'rwatch' commands. */
+static void
+watch_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /*word*/)
+{
+ const auto group = make_watch_options_def_group (nullptr);
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
+ return;
- watch_command_1 (arg, accessflag, from_tty, just_location, 0);
+ const char *word = advance_to_expression_complete_word_point (tracker, text);
+ expression_completer (ignore, tracker, text, word);
}
static void
}
void
-rwatch_command_wrapper (const char *arg, int from_tty, int internal)
+rwatch_command_wrapper (const char *arg, int from_tty, bool internal)
{
watch_command_1 (arg, hw_read, from_tty, 0, internal);
}
}
void
-awatch_command_wrapper (const char *arg, int from_tty, int internal)
+awatch_command_wrapper (const char *arg, int from_tty, bool internal)
{
watch_command_1 (arg, hw_access, from_tty, 0, internal);
}
case catch_fork_temporary:
case catch_fork_permanent:
create_fork_vfork_event_catchpoint (gdbarch, temp, cond_string,
- &catch_fork_breakpoint_ops);
+ &catch_fork_breakpoint_ops);
break;
case catch_vfork_temporary:
case catch_vfork_permanent:
create_fork_vfork_event_catchpoint (gdbarch, temp, cond_string,
- &catch_vfork_breakpoint_ops);
+ &catch_vfork_breakpoint_ops);
break;
default:
error (_("unsupported or unknown fork kind; cannot catch it"));
describe_other_breakpoints (loc_gdbarch,
sal.pspace, sal.pc, sal.section, -1);
/* FIXME: brobecker/2006-12-28: Actually, re-implement a special
- version for exception catchpoints, because two catchpoints
- used for different exception names will use the same address.
- In this case, a "breakpoint ... also set at..." warning is
- unproductive. Besides, the warning phrasing is also a bit
- inappropriate, we should use the word catchpoint, and tell
- the user what type of catchpoint it is. The above is good
- enough for now, though. */
+ version for exception catchpoints, because two catchpoints
+ used for different exception names will use the same address.
+ In this case, a "breakpoint ... also set at..." warning is
+ unproductive. Besides, the warning phrasing is also a bit
+ inappropriate, we should use the word catchpoint, and tell
+ the user what type of catchpoint it is. The above is good
+ enough for now, though. */
}
init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
const char *sal_fullname;
/* If exact pc given, clear bpts at that pc.
- If line given (pc == 0), clear all bpts on specified line.
- If defaulting, clear all bpts on default line
- or at default pc.
+ If line given (pc == 0), clear all bpts on specified line.
+ If defaulting, clear all bpts on default line
+ or at default pc.
- defaulting sal.pc != 0 tests to do
+ defaulting sal.pc != 0 tests to do
- 0 1 pc
- 1 1 pc _and_ line
- 0 0 line
- 1 0 <can't happen> */
+ 0 1 pc
+ 1 1 pc _and_ line
+ 0 0 line
+ 1 0 <can't happen> */
sal_fullname = (sal.symtab == NULL
? NULL : symtab_to_fullname (sal.symtab));
gdb_assert (bs->bp_location_at != NULL);
- bl = bs->bp_location_at;
+ bl = bs->bp_location_at.get ();
b = bs->breakpoint_at;
bp_temp = b->disposition == disp_del;
break;
/* This breakpoint is special, it's set up when the inferior
- starts and we really don't want to touch it. */
+ starts and we really don't want to touch it. */
case bp_shlib_event:
/* Like bp_shlib_event, this breakpoint type is special. Once
int breaks_to_delete = 0;
/* Delete all breakpoints if no argument. Do not delete
- internal breakpoints, these have to be deleted with an
- explicit breakpoint number argument. */
+ internal breakpoints, these have to be deleted with an
+ explicit breakpoint number argument. */
ALL_BREAKPOINTS (b)
if (user_breakpoint_p (b))
{
int breaks_to_delete = 0;
/* Delete all breakpoints if no argument.
- Do not delete internal or call-dummy breakpoints, these
- have to be deleted with an explicit breakpoint number
+ Do not delete internal or call-dummy breakpoints, these
+ have to be deleted with an explicit breakpoint number
argument. */
ALL_TRACEPOINTS (b)
if (is_tracepoint (b) && user_breakpoint_p (b))
Give \"silent\" as the first line to make the breakpoint silent;\n\
then no output is printed when it is hit, except what the commands print."));
- c = add_com ("condition", class_breakpoint, condition_command, _("\
+ const auto cc_opts = make_condition_command_options_def_group (nullptr);
+ static std::string condition_command_help
+ = gdb::option::build_help (_("\
Specify breakpoint number N to break only if COND is true.\n\
-Usage is `condition [-force] N COND', where N is an integer and COND\n\
+Usage is `condition [OPTION] N COND', where N is an integer and COND\n\
is an expression to be evaluated whenever breakpoint N is reached.\n\
-With the \"-force\" flag, the condition is defined even when it is\n\
-invalid for all current locations."));
- set_cmd_completer (c, condition_completer);
+\n\
+Options:\n\
+%OPTIONS%"), cc_opts);
+
+ c = add_com ("condition", class_breakpoint, condition_command,
+ condition_command_help.c_str ());
+ set_cmd_completer_handle_brkchars (c, condition_completer);
c = add_com ("tbreak", class_breakpoint, tbreak_command, _("\
Set a temporary breakpoint.\n\
add_catch_command ("fork", _("Catch calls to fork."),
catch_fork_command_1,
- NULL,
+ NULL,
(void *) (uintptr_t) catch_fork_permanent,
(void *) (uintptr_t) catch_fork_temporary);
add_catch_command ("vfork", _("Catch calls to vfork."),
catch_fork_command_1,
- NULL,
+ NULL,
(void *) (uintptr_t) catch_vfork_permanent,
(void *) (uintptr_t) catch_vfork_temporary);
add_catch_command ("exec", _("Catch calls to exec."),
catch_exec_command_1,
- NULL,
+ NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
add_catch_command ("load", _("Catch loads of shared libraries.\n\
CATCH_PERMANENT,
CATCH_TEMPORARY);
- c = add_com ("watch", class_breakpoint, watch_command, _("\
-Set a watchpoint for an expression.\n\
-Usage: watch [-l|-location] EXPRESSION\n\
-A watchpoint stops execution of your program whenever the value of\n\
-an expression changes.\n\
-If -l or -location is given, this evaluates EXPRESSION and watches\n\
-the memory to which it refers."));
- set_cmd_completer (c, expression_completer);
-
- c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
-Set a read watchpoint for an expression.\n\
-Usage: rwatch [-l|-location] EXPRESSION\n\
-A watchpoint stops execution of your program whenever the value of\n\
-an expression is read.\n\
-If -l or -location is given, this evaluates EXPRESSION and watches\n\
-the memory to which it refers."));
- set_cmd_completer (c, expression_completer);
-
- c = add_com ("awatch", class_breakpoint, awatch_command, _("\
-Set a watchpoint for an expression.\n\
-Usage: awatch [-l|-location] EXPRESSION\n\
+ const auto opts = make_watch_options_def_group (nullptr);
+
+ static const std::string watch_help = gdb::option::build_help (_("\
+Set a watchpoint for EXPRESSION.\n\
+Usage: watch [-location] EXPRESSION\n\
+\n\
+Options:\n\
+%OPTIONS%\n\
+\n\
A watchpoint stops execution of your program whenever the value of\n\
-an expression is either read or written.\n\
-If -l or -location is given, this evaluates EXPRESSION and watches\n\
-the memory to which it refers."));
- set_cmd_completer (c, expression_completer);
+an expression changes."), opts);
+ c = add_com ("watch", class_breakpoint, watch_command,
+ watch_help.c_str ());
+ set_cmd_completer_handle_brkchars (c, watch_command_completer);
+
+ static const std::string rwatch_help = gdb::option::build_help (_("\
+Set a read watchpoint for EXPRESSION.\n\
+Usage: rwatch [-location] EXPRESSION\n\
+\n\
+Options:\n\
+%OPTIONS%\n\
+\n\
+A read watchpoint stops execution of your program whenever the value of\n\
+an expression is read."), opts);
+ c = add_com ("rwatch", class_breakpoint, rwatch_command,
+ rwatch_help.c_str ());
+ set_cmd_completer_handle_brkchars (c, watch_command_completer);
+
+ static const std::string awatch_help = gdb::option::build_help (_("\
+Set an access watchpoint for EXPRESSION.\n\
+Usage: awatch [-location] EXPRESSION\n\
+\n\
+Options:\n\
+%OPTIONS%\n\
+\n\
+An access watchpoint stops execution of your program whenever the value\n\
+of an expression is either read or written."), opts);
+ c = add_com ("awatch", class_breakpoint, awatch_command,
+ awatch_help.c_str ());
+ set_cmd_completer_handle_brkchars (c, watch_command_completer);
add_info ("watchpoints", info_watchpoints_command, _("\
Status of specified watchpoints (all watchpoints if no argument)."));
LINENUM, for that line in the current file,\n\
FILE:LINENUM, for that line in that file,\n\
+OFFSET, for that number of lines after the current line\n\
- or the start of the range\n\
+ or the start of the range\n\
FUNCTION, for the first line in that function,\n\
FILE:FUNCTION, to distinguish among like-named static functions.\n\
*ADDRESS, for the instruction at that address.\n\