#include "memattr.h"
#include "ada-lang.h"
#include "top.h"
+#include "ui.h"
#include "valprint.h"
#include "jit.h"
#include "parser-defs.h"
#include "tid-parse.h"
#include "cli/cli-style.h"
#include "cli/cli-decode.h"
+#include <unordered_set>
/* readline include files */
#include "readline/tilde.h"
#include "progspace-and-thread.h"
#include "gdbsupport/array-view.h"
#include "gdbsupport/gdb_optional.h"
+#include "gdbsupport/common-utils.h"
/* Prototypes for local functions. */
gdb::unique_xmalloc_ptr<char>,
gdb::unique_xmalloc_ptr<char>,
enum bptype,
- enum bpdisp, int, int,
+ enum bpdisp, int, int, int,
int,
int, int, int, unsigned);
UGLL_INSERT
};
+/* Return a textual version of INSERT_MODE. */
+
+static const char *
+ugll_insert_mode_text (ugll_insert_mode insert_mode)
+{
+/* Make sure the compiler warns if a new ugll_insert_mode enumerator is added
+ but not handled here. */
+DIAGNOSTIC_PUSH
+DIAGNOSTIC_ERROR_SWITCH
+ switch (insert_mode)
+ {
+ case UGLL_DONT_INSERT:
+ return "UGLL_DONT_INSERT";
+ case UGLL_MAY_INSERT:
+ return "UGLL_MAY_INSERT";
+ case UGLL_INSERT:
+ return "UGLL_INSERT";
+ }
+DIAGNOSTIC_POP
+
+ gdb_assert_not_reached ("must handle all enum values");
+}
+
+/* Return a textual version of REASON. */
+
+static const char *
+remove_bp_reason_str (remove_bp_reason reason)
+{
+/* Make sure the compiler warns if a new remove_bp_reason enumerator is added
+ but not handled here. */
+DIAGNOSTIC_PUSH
+DIAGNOSTIC_ERROR_SWITCH
+ switch (reason)
+ {
+ case REMOVE_BREAKPOINT:
+ return "regular remove";
+ case DETACH_BREAKPOINT:
+ return "detach";
+ }
+DIAGNOSTIC_POP
+
+ gdb_assert_not_reached ("must handle all enum values");
+}
+
+/* Return a textual version of breakpoint location BL describing number,
+ location and address. */
+
+static std::string
+breakpoint_location_address_str (const bp_location *bl)
+{
+ std::string str = string_printf ("Breakpoint %d (%s) at address %s",
+ bl->owner->number,
+ host_address_to_string (bl),
+ paddress (bl->gdbarch, bl->address));
+
+ std::string loc_string = bl->to_string ();
+ if (!loc_string.empty ())
+ str += string_printf (" %s", loc_string.c_str ());
+
+ return str;
+}
+
static void update_global_location_list (enum ugll_insert_mode);
static void update_global_location_list_nothrow (enum ugll_insert_mode);
disposition = disp_donttouch;
frame_id = frame_id_;
thread = thread_;
+
+ /* The inferior should have been set by the parent constructor. */
+ gdb_assert (inferior == -1);
}
void re_set () override;
const target_waitstatus &ws) override;
int resources_needed (const struct bp_location *) override;
enum print_stop_action print_it (const bpstat *bs) const override;
- bool print_one (bp_location **) const override;
+ bool print_one (const bp_location **) const override;
void print_one_detail (struct ui_out *) const override;
void print_mention () const override;
void print_recreate (struct ui_file *fp) const override;
value);
}
+/* True if breakpoint debug output is enabled. */
+static bool debug_breakpoint = false;
+
+/* Print a "breakpoint" debug statement. */
+#define breakpoint_debug_printf(fmt, ...) \
+ debug_prefixed_printf_cond (debug_breakpoint, "breakpoint", fmt, \
+ ##__VA_ARGS__)
+
+/* "show debug breakpoint" implementation. */
+static void
+show_debug_breakpoint (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file, _("Breakpoint location debugging is %s.\n"), value);
+}
+
/* See breakpoint.h. */
int
/* See description in breakpoint.h. */
bool target_exact_watchpoints = false;
-/* Walk the following statement or block through all breakpoints.
- ALL_BREAKPOINTS_SAFE does so even if the statement deletes the
- current breakpoint. */
-
-#define ALL_BREAKPOINTS_SAFE(B,TMP) \
- for (B = breakpoint_chain; \
- B ? (TMP=B->next, 1): 0; \
- B = TMP)
-
/* Chains of all breakpoints defined. */
-static struct breakpoint *breakpoint_chain;
+static intrusive_list<breakpoint> breakpoint_chain;
/* See breakpoint.h. */
breakpoint_range
all_breakpoints ()
{
- return breakpoint_range (breakpoint_chain);
+ return breakpoint_range (breakpoint_chain.begin (), breakpoint_chain.end ());
}
/* See breakpoint.h. */
tracepoint_range
all_tracepoints ()
{
- return tracepoint_range (breakpoint_chain);
+ return tracepoint_range (tracepoint_iterator (breakpoint_chain.begin ()),
+ tracepoint_iterator (breakpoint_chain.end ()));
}
/* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS. */
void
clear_breakpoint_hit_counts (void)
{
- for (breakpoint *b : all_breakpoints ())
- b->hit_count = 0;
+ for (breakpoint &b : all_breakpoints ())
+ b.hit_count = 0;
}
\f
struct breakpoint *
get_breakpoint (int num)
{
- for (breakpoint *b : all_breakpoints ())
- if (b->number == num)
- return b;
+ for (breakpoint &b : all_breakpoints ())
+ if (b.number == num)
+ return &b;
return nullptr;
}
static bool
has_multiple_locations (int num)
{
- for (breakpoint *b : all_breakpoints ())
- if (b->number == num)
- return b->loc != nullptr && b->loc->next != nullptr;
+ for (breakpoint &b : all_breakpoints ())
+ if (b.number == num)
+ return b.has_multiple_locations ();
return false;
}
if (!is_breakpoint (b))
return;
- for (bp_location *loc : b->locations ())
- loc->condition_changed = condition_modified;
+ for (bp_location &loc : b->locations ())
+ loc.condition_changed = condition_modified;
}
/* Mark location as "conditions have changed" in case the target supports
error (_("Garbage '%s' follows condition"), cond_string);
}
+/* See breakpoint.h. */
+
+void
+notify_breakpoint_modified (breakpoint *b)
+{
+ interps_notify_breakpoint_modified (b);
+ gdb::observers::breakpoint_modified.notify (b);
+}
+
void
set_breakpoint_condition (struct breakpoint *b, const char *exp,
int from_tty, bool force)
else
{
int loc_num = 1;
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b->locations ())
{
- loc->cond.reset ();
- if (loc->disabled_by_cond && loc->enabled)
+ loc.cond.reset ();
+ if (loc.disabled_by_cond && loc.enabled)
gdb_printf (_("Breakpoint %d's condition is now valid at "
"location %d, enabling.\n"),
b->number, loc_num);
- loc->disabled_by_cond = false;
+ loc.disabled_by_cond = false;
loc_num++;
/* No need to free the condition agent expression
the error and the condition string will be rejected.
This two-pass approach is taken to avoid setting the
state of locations in case of a reject. */
- for (bp_location *loc : b->locations ())
+ for (const bp_location &loc : b->locations ())
{
try
{
const char *arg = exp;
- parse_exp_1 (&arg, loc->address,
- block_for_pc (loc->address), 0);
+ parse_exp_1 (&arg, loc.address,
+ block_for_pc (loc.address), 0);
if (*arg != 0)
error (_("Junk at end of expression"));
break;
/* Condition string is invalid. If this happens to
be the last loc, abandon (if not forced) or continue
(if forced). */
- if (loc->next == nullptr && !force)
+ if (&loc == &b->last_loc () && !force)
throw;
}
}
/* If we reach here, the condition is valid at some locations. */
int loc_num = 1;
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b->locations ())
{
- set_breakpoint_location_condition (exp, loc, b->number, loc_num);
+ set_breakpoint_location_condition (exp, &loc, b->number, loc_num);
loc_num++;
}
}
}
mark_breakpoint_modified (b);
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
}
/* See breakpoint.h. */
set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
bool force)
{
- for (breakpoint *b : all_breakpoints ())
- if (b->number == bpnum)
+ for (breakpoint &b : all_breakpoints ())
+ if (b.number == bpnum)
{
/* Check if this breakpoint has a "stop" method implemented in an
extension language. This method and conditions entered into GDB
from the CLI are mutually exclusive. */
const struct extension_language_defn *extlang
- = get_breakpoint_cond_ext_lang (b, EXT_LANG_NONE);
+ = get_breakpoint_cond_ext_lang (&b, EXT_LANG_NONE);
if (extlang != NULL)
{
" a %s stop condition defined for this breakpoint."),
ext_lang_capitalized_name (extlang));
}
- set_breakpoint_condition (b, exp, from_tty, force);
+ set_breakpoint_condition (&b, exp, from_tty, force);
- if (is_breakpoint (b))
+ if (is_breakpoint (&b))
update_global_location_list (UGLL_MAY_INSERT);
return;
/* We're completing the breakpoint number. */
len = strlen (text);
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
char number[50];
- xsnprintf (number, sizeof (number), "%d", b->number);
+ xsnprintf (number, sizeof (number), "%d", b.number);
if (strncmp (number, text, len) == 0)
tracker.add_completion (make_unique_xstrdup (number));
{
std::vector<breakpoint *> found;
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_static_tracepoint
- || b->type == bp_static_marker_tracepoint)
+ for (breakpoint &b : all_breakpoints ())
+ if (b.type == bp_static_tracepoint
+ || b.type == bp_static_marker_tracepoint)
{
- for (bp_location *loc : b->locations ())
- if (loc->address == addr)
- found.push_back (b);
+ for (bp_location &loc : b.locations ())
+ if (loc.address == addr)
+ found.push_back (&b);
}
return found;
validate_commands_for_breakpoint (b, commands.get ());
b->commands = std::move (commands);
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
}
/* Set the internal `silent' flag on the breakpoint. Note that this
b->silent = silent;
if (old_silent != silent)
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
}
/* See breakpoint.h. */
void
breakpoint_set_thread (struct breakpoint *b, int thread)
{
- /* It is invalid to set the thread field to anything other than -1 (which
- means no thread restriction) if a task restriction is already in
- place. */
- gdb_assert (thread == -1 || b->task == -1);
+ /* THREAD should be -1, meaning no thread restriction, or it should be a
+ valid global thread-id, which are greater than zero. */
+ gdb_assert (thread == -1 || thread > 0);
- int old_thread = b->thread;
+ /* It is not valid to set a thread restriction for a breakpoint that
+ already has task or inferior restriction. */
+ gdb_assert (thread == -1 || (b->task == -1 && b->inferior == -1));
+ int old_thread = b->thread;
b->thread = thread;
if (old_thread != thread)
+ notify_breakpoint_modified (b);
+}
+
+/* See breakpoint.h. */
+
+void
+breakpoint_set_inferior (struct breakpoint *b, int inferior)
+{
+ /* INFERIOR should be -1, meaning no inferior restriction, or it should
+ be a valid inferior number, which are greater than zero. */
+ gdb_assert (inferior == -1 || inferior > 0);
+
+ /* It is not valid to set an inferior restriction for a breakpoint that
+ already has a task or thread restriction. */
+ gdb_assert (inferior == -1 || (b->task == -1 && b->thread == -1));
+
+ int old_inferior = b->inferior;
+ b->inferior = inferior;
+ if (old_inferior != inferior)
gdb::observers::breakpoint_modified.notify (b);
}
void
breakpoint_set_task (struct breakpoint *b, int task)
{
- /* It is invalid to set the task field to anything other than -1 (which
- means no task restriction) if a thread restriction is already in
- place. */
- gdb_assert (task == -1 || b->thread == -1);
+ /* TASK should be -1, meaning no task restriction, or it should be a
+ valid task-id, which are greater than zero. */
+ gdb_assert (task == -1 || task > 0);
- int old_task = b->task;
+ /* It is not valid to set a task restriction for a breakpoint that
+ already has a thread or inferior restriction. */
+ gdb_assert (task == -1 || (b->thread == -1 && b->inferior == -1));
+ int old_task = b->task;
b->task = task;
if (old_task != task)
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
}
static void
{
validate_commands_for_breakpoint (b, cmd.get ());
b->commands = cmd;
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
}
});
}
w->related_breakpoint = w;
}
w->disposition = disp_del_at_next_stop;
+ disable_breakpoint (w);
}
/* Extract a bitfield value from value VAL using the bit parameters contained in
if (val == NULL)
return NULL;
- bit_val = allocate_value (val->type ());
+ bit_val = value::allocate (val->type ());
- unpack_value_bitfield (bit_val,
- w->val_bitpos,
- w->val_bitsize,
- value_contents_for_printing (val).data (),
- val->offset (),
- val);
+ val->unpack_bitfield (bit_val,
+ w->val_bitpos,
+ w->val_bitsize,
+ val->contents_for_printing ().data (),
+ val->offset ());
return bit_val;
}
add_dummy_location (struct breakpoint *b,
struct program_space *pspace)
{
- gdb_assert (b->loc == NULL);
+ gdb_assert (!b->has_locations ());
- b->loc = new bp_location (b, bp_loc_other);
- b->loc->pspace = pspace;
+ bp_location *loc = new bp_location (b, bp_loc_other);
+ loc->pspace = pspace;
+ b->add_location (*loc);
}
/* Assuming that B is a watchpoint:
/* We don't free locations. They are stored in the bp_location array
and update_global_location_list will eventually delete them and
remove breakpoints if needed. */
- b->loc = NULL;
+ b->clear_locations ();
if (within_current_scope && reparse)
{
must watch it. If the first value returned is
still lazy, that means an error occurred reading it;
watch it anyway in case it becomes readable. */
- if (VALUE_LVAL (v) == lval_memory
- && (v == val_chain[0] || ! value_lazy (v)))
+ if (v->lval () == lval_memory
+ && (v == val_chain[0] || ! v->lazy ()))
{
struct type *vtype = check_typedef (v->type ());
{
CORE_ADDR addr;
enum target_hw_bp_type type;
- struct bp_location *loc, **tmp;
int bitpos = 0, bitsize = 0;
if (v->bitsize () != 0)
bitsize = b->val_bitsize;
}
- addr = value_address (v);
+ addr = v->address ();
if (bitsize != 0)
{
/* Skip the bytes that don't contain the bitfield. */
else if (b->type == bp_access_watchpoint)
type = hw_access;
- loc = b->allocate_location ();
- for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
- ;
- *tmp = loc;
+ bp_location *loc = b->allocate_location ();
loc->gdbarch = v->type ()->arch ();
-
loc->pspace = frame_pspace;
loc->address
= gdbarch_remove_non_address_bits (loc->gdbarch, addr);
+ b->add_location (*loc);
if (bitsize != 0)
{
}
}
+ /* Helper function to bundle possibly emitting a warning along with
+ changing the type of B to bp_watchpoint. */
+ auto change_type_to_bp_watchpoint = [] (breakpoint *bp)
+ {
+ /* Only warn for breakpoints that have been assigned a +ve number,
+ anything else is either an internal watchpoint (which we don't
+ currently create) or has not yet been finalized, in which case
+ this change of type will be occurring before the user is told
+ the type of this watchpoint. */
+ if (bp->type == bp_hardware_watchpoint && bp->number > 0)
+ warning (_("watchpoint %d downgraded to software watchpoint"),
+ bp->number);
+ bp->type = bp_watchpoint;
+ };
+
/* Change the type of breakpoint between hardware assisted or
an ordinary watchpoint depending on the hardware support and
free hardware slots. Recheck the number of free hardware slots
"resources for this watchpoint."));
/* Downgrade to software watchpoint. */
- b->type = bp_watchpoint;
+ change_type_to_bp_watchpoint (b);
}
else
{
"read/access watchpoint."));
}
else
- b->type = bp_watchpoint;
+ change_type_to_bp_watchpoint (b);
loc_type = (b->type == bp_watchpoint? bp_loc_software_watchpoint
: bp_loc_hardware_watchpoint);
- for (bp_location *bl : b->locations ())
- bl->loc_type = loc_type;
+
+ for (bp_location &bl : b->locations ())
+ bl.loc_type = loc_type;
}
/* If a software watchpoint is not watching any memory, then the
above left it without any location set up. But,
bpstat_stop_status requires a location to be able to report
stops, so make sure there's at least a dummy one. */
- if (b->type == bp_watchpoint && b->loc == NULL)
+ if (b->type == bp_watchpoint && !b->has_locations ())
add_dummy_location (b, frame_pspace);
}
else if (!within_current_scope)
/* No NULL conditions or failed bytecode generation. Build a
condition list for this location's address. If we have software
and hardware locations at the same address, they aren't
- considered duplicates, but we still marge all the conditions
+ considered duplicates, but we still merge all the conditions
anyway, as it's simpler, and doesn't really make a practical
difference. */
for (bp_location *loc : loc_range)
const char *cmd1;
cmd1 = cmdrest;
- expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
+ expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope),
+ PARSER_COMMA_TERMINATES);
argvec.push_back (expr.release ());
cmdrest = cmd1;
if (*cmdrest == ',')
if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
return 0;
+ breakpoint_debug_printf ("%s", breakpoint_location_address_str (bl).c_str ());
+
/* Note we don't initialize bl->target_info, as that wipes out
the breakpoint location's shadow_contents if the breakpoint
is still inserted at that location. This in turn breaks
if (val)
bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
}
- catch (gdb_exception &e)
+ catch (gdb_exception_error &e)
{
rethrow_on_target_close_error (e);
bp_excpt = std::move (e);
{
/* See also: disable_breakpoints_in_shlibs. */
bl->shlib_disabled = 1;
- gdb::observers::breakpoint_modified.notify (bl->owner);
+ notify_breakpoint_modified (bl->owner);
if (!*disabled_breaks)
{
gdb_printf (tmp_error_stream,
}
else if (bl->loc_type == bp_loc_hardware_watchpoint
- /* NOTE drow/2003-09-08: This state only exists for removing
- watchpoints. It's not clear that it's necessary... */
&& bl->owner->disposition != disp_del_at_next_stop)
{
int val;
breakpoint_program_space_exit (struct program_space *pspace)
{
/* Remove any breakpoint that was set through this program space. */
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->pspace == pspace)
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.pspace == pspace)
+ delete_breakpoint (&b);
/* Breakpoints set through other program spaces could have locations
bound to PSPACE as well. Remove those. */
for (bp_location *loc : all_bp_locations ())
- {
- struct bp_location *tmp;
-
- if (loc->pspace == pspace)
- {
- /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */
- if (loc->owner->loc == loc)
- loc->owner->loc = loc->next;
- else
- for (tmp = loc->owner->loc; tmp->next != NULL; tmp = tmp->next)
- if (tmp->next == loc)
- {
- tmp->next = loc->next;
- break;
- }
- }
- }
+ if (loc->pspace == pspace)
+ {
+ /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */
+ loc->owner->unadd_location (*loc);
+ }
/* Now update the global location list to permanently delete the
removed locations above. */
void
insert_breakpoints (void)
{
- for (breakpoint *bpt : all_breakpoints ())
- if (is_hardware_watchpoint (bpt))
+ for (breakpoint &bpt : all_breakpoints ())
+ if (is_hardware_watchpoint (&bpt))
{
- struct watchpoint *w = (struct watchpoint *) bpt;
+ watchpoint &w = gdb::checked_static_cast<watchpoint &> (bpt);
- update_watchpoint (w, false /* don't reparse. */);
+ update_watchpoint (&w, false /* don't reparse. */);
}
/* Updating watchpoints creates new locations, so update the global
if (error_flag)
{
target_terminal::ours_for_output ();
- error_stream (tmp_error_stream);
+ error (("%s"), tmp_error_stream.c_str ());
}
}
&& !valid_global_thread_id (bl->owner->thread))
continue;
+ /* Or inferior specific breakpoints if the inferior no longer
+ exists. */
+ if (bl->owner->inferior != -1
+ && !valid_global_inferior_id (bl->owner->inferior))
+ continue;
+
switch_to_program_space_and_thread (bl->pspace);
/* For targets that support global breakpoints, there's no need
/* If we failed to insert all locations of a watchpoint, remove
them, as half-inserted watchpoint is of limited use. */
- for (breakpoint *bpt : all_breakpoints ())
+ for (breakpoint &bpt : all_breakpoints ())
{
bool some_failed = false;
- if (!is_hardware_watchpoint (bpt))
+ if (!is_hardware_watchpoint (&bpt))
continue;
- if (!breakpoint_enabled (bpt))
+ if (!breakpoint_enabled (&bpt))
continue;
- if (bpt->disposition == disp_del_at_next_stop)
+ if (bpt.disposition == disp_del_at_next_stop)
continue;
-
- for (bp_location *loc : bpt->locations ())
- if (!loc->inserted && should_be_inserted (loc))
+
+ for (bp_location &loc : bpt.locations ())
+ if (!loc.inserted && should_be_inserted (&loc))
{
some_failed = true;
break;
if (some_failed)
{
- for (bp_location *loc : bpt->locations ())
- if (loc->inserted)
- remove_breakpoint (loc);
+ for (bp_location &loc : bpt.locations ())
+ if (loc.inserted)
+ remove_breakpoint (&loc);
hw_breakpoint_error = 1;
tmp_error_stream.printf ("Could not insert "
"hardware watchpoint %d.\n",
- bpt->number);
+ bpt.number);
error_flag = -1;
}
}
You may have requested too many hardware breakpoints/watchpoints.\n");
}
target_terminal::ours_for_output ();
- error_stream (tmp_error_stream);
+ error (("%s"), tmp_error_stream.c_str ());
}
}
static void
remove_threaded_breakpoints (struct thread_info *tp, int silent)
{
- for (breakpoint *b : all_breakpoints_safe ())
+ for (breakpoint &b : all_breakpoints_safe ())
{
- if (b->thread == tp->global_num && user_breakpoint_p (b))
+ if (b.thread == tp->global_num && user_breakpoint_p (&b))
{
- b->disposition = disp_del_at_next_stop;
-
gdb_printf (_("\
Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
- b->number, print_thread_id (tp));
+ b.number, print_thread_id (tp));
+ delete_breakpoint (&b);
+ }
+ }
+}
+
+/* Called when inferior INF has been removed from GDB. Remove associated
+ per-inferior breakpoints. */
- /* Hide it from the user. */
- b->number = 0;
+static void
+remove_inferior_breakpoints (struct inferior *inf)
+{
+ for (breakpoint &b : all_breakpoints_safe ())
+ {
+ if (b.inferior == inf->num && user_breakpoint_p (&b))
+ {
+ /* Tell the user the breakpoint has been deleted. But only for
+ breakpoints that would not normally have been deleted at the
+ next stop anyway. */
+ if (b.disposition != disp_del
+ && b.disposition != disp_del_at_next_stop)
+ gdb_printf (_("\
+Inferior-specific breakpoint %d deleted - inferior %d has been removed.\n"),
+ b.number, inf->num);
+ delete_breakpoint (&b);
}
}
}
{
int val;
+ breakpoint_debug_printf ("inf->num = %d", inf->num);
+
for (bp_location *bl : all_bp_locations ())
{
if (bl->pspace != inf->pspace)
if (bploc->pspace == current_program_space)
gdb_assert (!bploc->inserted);
- for (breakpoint *b : all_breakpoints_safe ())
+ for (breakpoint &b : all_breakpoints_safe ())
{
- if (b->pspace != current_program_space)
+ if (b.pspace != current_program_space)
continue;
/* Solib breakpoints must be explicitly reset after an exec(). */
- if (b->type == bp_shlib_event)
+ if (b.type == bp_shlib_event)
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
/* JIT breakpoints must be explicitly reset after an exec(). */
- if (b->type == bp_jit_event)
+ if (b.type == bp_jit_event)
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
/* 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_std_terminate_master
- || b->type == bp_exception_master)
+ if (b.type == bp_thread_event || b.type == bp_overlay_event
+ || b.type == bp_longjmp_master || b.type == bp_std_terminate_master
+ || b.type == bp_exception_master)
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
/* Step-resume breakpoints are meaningless after an exec(). */
- if (b->type == bp_step_resume || b->type == bp_hp_step_resume)
+ if (b.type == bp_step_resume || b.type == bp_hp_step_resume)
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
/* Just like single-step breakpoints. */
- if (b->type == bp_single_step)
+ if (b.type == bp_single_step)
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
/* Longjmp and longjmp-resume breakpoints are also meaningless
after an exec. */
- if (b->type == bp_longjmp || b->type == bp_longjmp_resume
- || b->type == bp_longjmp_call_dummy
- || b->type == bp_exception || b->type == bp_exception_resume)
+ if (b.type == bp_longjmp || b.type == bp_longjmp_resume
+ || b.type == bp_longjmp_call_dummy
+ || b.type == bp_exception || b.type == bp_exception_resume)
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
- if (b->type == bp_catchpoint)
+ 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
address is probably bogus in the new a.out, unlike e.g., the
solib breakpoints.) */
- if (b->type == bp_finish)
+ if (b.type == bp_finish)
{
continue;
}
/* Without a symbolic address, we have little hope of the
pre-exec() address meaning the same thing in the post-exec()
a.out. */
- if (breakpoint_location_spec_empty_p (b))
+ if (breakpoint_location_spec_empty_p (&b))
{
- delete_breakpoint (b);
+ delete_breakpoint (&b);
continue;
}
}
static int
remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
{
+ breakpoint_debug_printf ("%s due to %s",
+ breakpoint_location_address_str (bl).c_str (),
+ remove_bp_reason_str (reason));
+
int val;
/* BL is never in moribund_locations by our callers. */
mark_breakpoints_out ();
- for (breakpoint *b : all_breakpoints_safe ())
+ for (breakpoint &b : all_breakpoints_safe ())
{
- if (b->loc && b->loc->pspace != pspace)
+ if (b.has_locations () && b.first_loc ().pspace != pspace)
continue;
- switch (b->type)
+ switch (b.type)
{
case bp_call_dummy:
case bp_longjmp_call_dummy:
/* Also remove single-step breakpoints. */
- delete_breakpoint (b);
+ delete_breakpoint (&b);
break;
case bp_watchpoint:
case bp_read_watchpoint:
case bp_access_watchpoint:
{
- struct watchpoint *w = (struct watchpoint *) b;
+ watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
/* Likewise for watchpoints on local expressions. */
- if (w->exp_valid_block != NULL)
- delete_breakpoint (b);
+ if (w.exp_valid_block != NULL)
+ delete_breakpoint (&b);
else
{
/* Get rid of existing locations, which are no longer
update_watchpoint, when the inferior is restarted.
The next update_global_location_list call will
garbage collect them. */
- b->loc = NULL;
+ b.clear_locations ();
if (context == inf_starting)
{
/* Reset val field to force reread of starting value in
insert_breakpoints. */
- w->val.reset (nullptr);
- w->val_valid = false;
+ w.val.reset (nullptr);
+ w.val_valid = false;
}
}
}
hardware_watchpoint_inserted_in_range (const address_space *aspace,
CORE_ADDR addr, ULONGEST len)
{
- for (breakpoint *bpt : all_breakpoints ())
+ for (breakpoint &bpt : all_breakpoints ())
{
- if (bpt->type != bp_hardware_watchpoint
- && bpt->type != bp_access_watchpoint)
+ if (bpt.type != bp_hardware_watchpoint
+ && bpt.type != bp_access_watchpoint)
continue;
- if (!breakpoint_enabled (bpt))
+ if (!breakpoint_enabled (&bpt))
continue;
- for (bp_location *loc : bpt->locations ())
- if (loc->pspace->aspace == aspace && loc->inserted)
+ for (bp_location &loc : bpt.locations ())
+ if (loc.pspace->aspace == aspace && loc.inserted)
{
CORE_ADDR l, h;
/* Check for intersection. */
- l = std::max<CORE_ADDR> (loc->address, addr);
- h = std::min<CORE_ADDR> (loc->address + loc->length, addr + len);
+ l = std::max<CORE_ADDR> (loc.address, addr);
+ h = std::min<CORE_ADDR> (loc.address + loc.length, addr + len);
if (l < h)
return 1;
}
print_it (other.print_it)
{
if (other.old_val != NULL)
- old_val = release_value (value_copy (other.old_val.get ()));
+ old_val = release_value (other.old_val->copy ());
}
/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
const struct breakpoint *b = bs->breakpoint_at;
const struct bp_location *bl = bs->bp_location_at.get ();
- int locno = 0;
-
- if (b != nullptr && b->loc != nullptr && b->loc->next != nullptr)
+ if (b != nullptr && b->has_multiple_locations ())
{
- const bp_location *bl_i;
-
- for (bl_i = b->loc;
- bl_i != bl && bl_i->next != nullptr;
- bl_i = bl_i->next)
- locno++;
+ int locno = 1;
- if (bl_i == bl)
- locno++;
- else
+ for (bp_location &loc : b->locations ())
{
- warning (_("location number not found for breakpoint %d address %s."),
- b->number, paddress (bl->gdbarch, bl->address));
- locno = 0;
+ if (bl == &loc)
+ return locno;
+
+ ++locno;
}
+
+ warning (_("location number not found for breakpoint %d address %s."),
+ b->number, paddress (bl->gdbarch, bl->address));
}
- return locno;
+ return 0;
}
/* See breakpoint.h. */
breakpoint_cond_eval (expression *exp)
{
scoped_value_mark mark;
- return value_true (evaluate_expression (exp));
+ return value_true (exp->evaluate ());
}
/* Allocate a new bpstat. Link it to the FIFO list by BS_LINK_POINTER. */
{
/* We were not stopped by a watchpoint. Mark all watchpoints
as not triggered. */
- for (breakpoint *b : all_breakpoints ())
- if (is_hardware_watchpoint (b))
+ for (breakpoint &b : all_breakpoints ())
+ if (is_hardware_watchpoint (&b))
{
- struct watchpoint *w = (struct watchpoint *) b;
+ watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
- w->watchpoint_triggered = watch_triggered_no;
+ w.watchpoint_triggered = watch_triggered_no;
}
return 0;
{
/* We were stopped by a watchpoint, but we don't know where.
Mark all watchpoints as unknown. */
- for (breakpoint *b : all_breakpoints ())
- if (is_hardware_watchpoint (b))
+ for (breakpoint &b : all_breakpoints ())
+ if (is_hardware_watchpoint (&b))
{
- struct watchpoint *w = (struct watchpoint *) b;
+ watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
- w->watchpoint_triggered = watch_triggered_unknown;
+ w.watchpoint_triggered = watch_triggered_unknown;
}
return 1;
affected by this data address as triggered, and all others as not
triggered. */
- for (breakpoint *b : all_breakpoints ())
- if (is_hardware_watchpoint (b))
+ for (breakpoint &b : all_breakpoints ())
+ if (is_hardware_watchpoint (&b))
{
- struct watchpoint *w = (struct watchpoint *) b;
+ watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
- w->watchpoint_triggered = watch_triggered_no;
- for (bp_location *loc : b->locations ())
+ w.watchpoint_triggered = watch_triggered_no;
+ for (bp_location &loc : b.locations ())
{
- if (is_masked_watchpoint (b))
+ if (is_masked_watchpoint (&b))
{
- CORE_ADDR newaddr = addr & w->hw_wp_mask;
- CORE_ADDR start = loc->address & w->hw_wp_mask;
+ CORE_ADDR newaddr = addr & w.hw_wp_mask;
+ CORE_ADDR start = loc.address & w.hw_wp_mask;
if (newaddr == start)
{
- w->watchpoint_triggered = watch_triggered_yes;
+ w.watchpoint_triggered = watch_triggered_yes;
break;
}
}
/* Exact match not required. Within range is sufficient. */
else if (target_watchpoint_addr_within_range
- (current_inferior ()->top_target (), addr, loc->address,
- loc->length))
+ (current_inferior ()->top_target (), addr, loc.address,
+ loc.length))
{
- w->watchpoint_triggered = watch_triggered_yes;
+ w.watchpoint_triggered = watch_triggered_yes;
break;
}
}
function = get_frame_function (fr);
if (function == NULL
- || !contained_in (b->exp_valid_block, function->value_block ()))
+ || !function->value_block ()->contains (b->exp_valid_block))
within_current_scope = false;
}
{
e = watchpoint_check (bs);
}
- catch (const gdb_exception &ex)
+ catch (const gdb_exception_error &ex)
{
exception_fprintf (gdb_stderr, ex,
"Error evaluating expression "
if (bl->watchpoint_type == hw_read)
{
- for (breakpoint *other_b : all_breakpoints ())
- if (other_b->type == bp_hardware_watchpoint
- || other_b->type == bp_access_watchpoint)
+ for (breakpoint &other_b : all_breakpoints ())
+ if (other_b.type == bp_hardware_watchpoint
+ || other_b.type == bp_access_watchpoint)
{
- struct watchpoint *other_w =
- (struct watchpoint *) other_b;
+ watchpoint &other_w =
+ gdb::checked_static_cast<watchpoint &> (other_b);
- if (other_w->watchpoint_triggered
+ if (other_w.watchpoint_triggered
== watch_triggered_yes)
{
other_write_watchpoint = 1;
evaluating the condition if this isn't the specified
thread/task. */
if ((b->thread != -1 && b->thread != thread->global_num)
+ || (b->inferior != -1 && b->inferior != thread->inf->num)
|| (b->task != -1 && b->task != ada_get_task_number (thread)))
{
infrun_debug_printf ("incorrect thread or task, not stopping");
{
condition_result = breakpoint_cond_eval (cond);
}
- catch (const gdb_exception &ex)
+ catch (const gdb_exception_error &ex)
{
- exception_fprintf (gdb_stderr, ex,
- "Error in testing breakpoint condition:\n");
+ int locno = bpstat_locno (bs);
+ if (locno != 0)
+ exception_fprintf
+ (gdb_stderr, ex,
+ "Error in testing condition for breakpoint %d.%d:\n",
+ b->number, locno);
+ else
+ exception_fprintf
+ (gdb_stderr, ex,
+ "Error in testing condition for breakpoint %d:\n",
+ b->number);
}
}
else
bs->stop = false;
/* Increase the hit count even though we don't stop. */
++(b->hit_count);
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
return;
}
{
bpstat *bs_head = nullptr, **bs_link = &bs_head;
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
- if (!breakpoint_enabled (b))
+ if (!breakpoint_enabled (&b))
continue;
- for (bp_location *bl : b->locations ())
+ for (bp_location &bl : b.locations ())
{
/* For hardware watchpoints, we look only at the first
location. 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)
+ if (b.type == bp_hardware_watchpoint && &bl != &b.first_loc ())
break;
- if (!bl->enabled || bl->disabled_by_cond || bl->shlib_disabled)
+ if (!bl.enabled || bl.disabled_by_cond || bl.shlib_disabled)
continue;
- if (!bpstat_check_location (bl, aspace, bp_addr, ws))
+ if (!bpstat_check_location (&bl, aspace, bp_addr, ws))
continue;
/* Come here if it's a watchpoint, or if the break address
matches. */
- bpstat *bs = new bpstat (bl, &bs_link); /* Alloc a bpstat to
+ bpstat *bs = new bpstat (&bl, &bs_link); /* Alloc a bpstat to
explain stop. */
/* Assume we stop. Should we find a watchpoint that is not
watchpoint as triggered so that we will handle the
out-of-scope event. We'll get to the watchpoint next
iteration. */
- if (b->type == bp_watchpoint_scope && b->related_breakpoint != b)
+ if (b.type == bp_watchpoint_scope && b.related_breakpoint != &b)
{
- struct watchpoint *w = (struct watchpoint *) b->related_breakpoint;
+ struct watchpoint *w = (struct watchpoint *) b.related_breakpoint;
w->watchpoint_triggered = watch_triggered_yes;
}
b->enable_state = bp_disabled;
removed_any = 1;
}
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
if (b->silent)
bs->print = false;
bs->commands = b->commands;
bool
bpstat_should_step ()
{
- for (breakpoint *b : all_breakpoints ())
- if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
+ for (breakpoint &b : all_breakpoints ())
+ if (breakpoint_enabled (&b)
+ && b.type == bp_watchpoint
+ && b.has_locations ())
return true;
return false;
|| !target_supports_evaluation_of_breakpoint_conditions ())
return condition_evaluation_host;
- for (bp_location *bl : b->locations ())
+ for (bp_location &bl : b->locations ())
{
- if (bl->cond_bytecode)
+ if (bl.cond_bytecode)
target_evals++;
else
host_evals++;
/* Print the LOC location out of the list of B->LOC locations. */
static void
-print_breakpoint_location (const breakpoint *b,
- struct bp_location *loc)
+print_breakpoint_location (const breakpoint *b, const bp_location *loc)
{
struct ui_out *uiout = current_uiout;
print_one_breakpoint_location (struct breakpoint *b,
struct bp_location *loc,
int loc_number,
- struct bp_location **last_loc,
+ const bp_location **last_loc,
int allflag, bool raw_loc)
{
struct command_line *l;
/* See comment in print_one_breakpoint concerning treatment of
breakpoints with single disabled location. */
if (loc == NULL
- && (b->loc != NULL
- && (b->loc->next != NULL
- || !b->loc->enabled || b->loc->disabled_by_cond)))
+ && (b->has_locations ()
+ && (b->has_multiple_locations ()
+ || !b->first_loc ().enabled || b->first_loc ().disabled_by_cond)))
header_of_multiple = true;
- if (loc == NULL)
- loc = b->loc;
+
+ if (loc == NULL && b->has_locations ())
+ loc = &b->first_loc ();
annotate_record ();
without a footnote. On the CLI, for enabled locations whose
breakpoint is disabled, display "y-". */
auto get_enable_state = [uiout, loc] () -> const char *
- {
+ {
if (uiout->is_mi_like_p ())
{
if (loc->disabled_by_cond)
if (header_of_multiple)
uiout->field_string ("addr", "<MULTIPLE>",
metadata_style.style ());
- else if (b->loc == NULL || loc->shlib_disabled)
+ else if (!b->has_locations () || loc->shlib_disabled)
uiout->field_string ("addr", "<PENDING>",
metadata_style.style ());
else
annotate_field (5);
if (!header_of_multiple)
print_breakpoint_location (b, loc);
- if (b->loc)
- *last_loc = b->loc;
+ if (b->has_locations ())
+ *last_loc = &b->first_loc ();
}
}
inf_nums.push_back (inf->num);
}
- /* 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 ())
- && (program_spaces.size () > 1
- || number_of_inferiors () > 1)
- /* LOC is for existing B, it cannot be in
- moribund_locations and thus having NULL OWNER. */
- && loc->owner->type != bp_catchpoint))
+ /* 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 ())
+ && (program_spaces.size () > 1
+ || number_of_inferiors () > 1)
+ /* LOC is for existing B, it cannot be in
+ moribund_locations and thus having NULL OWNER. */
+ && loc->owner->type != bp_catchpoint))
mi_only = 0;
output_thread_groups (uiout, "thread-groups", inf_nums, mi_only);
}
For the CLI output, the thread/task information is printed on a
separate line, see the 'stop only in thread' and 'stop only in task'
output below. */
- if (!header_of_multiple && uiout->is_mi_like_p ())
+ if (part_of_multiple && uiout->is_mi_like_p ())
{
if (b->thread != -1)
uiout->field_signed ("thread", b->thread);
else if (b->task != -1)
uiout->field_signed ("task", b->task);
+ else if (b->inferior != -1)
+ uiout->field_signed ("inferior", b->inferior);
}
uiout->text ("\n");
uiout->text ("\n");
}
+ if (!part_of_multiple && b->inferior != -1)
+ {
+ uiout->text ("\tstop only in inferior ");
+ uiout->field_signed ("inferior", b->inferior);
+ uiout->text ("\n");
+ }
+
if (!part_of_multiple)
{
if (b->hit_count)
bool use_fixed_output =
(uiout->test_flags (fix_breakpoint_script_output)
- || fix_breakpoint_script_output_globally);
+ || fix_breakpoint_script_output_globally);
gdb::optional<ui_out_emit_tuple> tuple_emitter;
gdb::optional<ui_out_emit_list> list_emitter;
bool fix_multi_location_breakpoint_output_globally = false;
static void
-print_one_breakpoint (struct breakpoint *b,
- struct bp_location **last_loc,
- int allflag)
+print_one_breakpoint (breakpoint *b, const bp_location **last_loc, int allflag)
{
struct ui_out *uiout = current_uiout;
bool use_fixed_output
&& (!is_catchpoint (b) || is_exception_catchpoint (b)
|| is_ada_exception_catchpoint (b))
&& (allflag
- || (b->loc && (b->loc->next
- || !b->loc->enabled
- || b->loc->disabled_by_cond))))
+ || (b->has_locations ()
+ && (b->has_multiple_locations ()
+ || !b->first_loc ().enabled
+ || b->first_loc ().disabled_by_cond))))
{
gdb::optional<ui_out_emit_list> locations_list;
locations_list.emplace (uiout, "locations");
int n = 1;
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b->locations ())
{
ui_out_emit_tuple loc_tuple_emitter (uiout, NULL);
- print_one_breakpoint_location (b, loc, n, last_loc,
+ print_one_breakpoint_location (b, &loc, n, last_loc,
allflag, allflag);
n++;
}
{
int print_address_bits = 0;
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b->locations ())
{
- if (!bl_address_is_meaningful (loc))
+ if (!bl_address_is_meaningful (&loc))
continue;
- int addr_bit = gdbarch_addr_bit (loc->gdbarch);
+ int addr_bit = gdbarch_addr_bit (loc.gdbarch);
if (addr_bit > print_address_bits)
print_address_bits = addr_bit;
}
void
print_breakpoint (breakpoint *b)
{
- struct bp_location *dummy_loc = NULL;
+ const bp_location *dummy_loc = nullptr;
print_one_breakpoint (b, &dummy_loc, 0);
}
int
pending_breakpoint_p (struct breakpoint *b)
{
- return b->loc == NULL;
+ return !b->has_locations ();
}
/* Print information on breakpoints (including watchpoints and tracepoints).
breakpoint_1 (const char *bp_num_list, bool show_internal,
bool (*filter) (const struct breakpoint *))
{
- struct bp_location *last_loc = NULL;
+ const bp_location *last_loc = nullptr;
int nr_printable_breakpoints;
struct value_print_options opts;
int print_address_bits = 0;
/* Compute the number of rows in the table, as well as the size
required for address fields. */
nr_printable_breakpoints = 0;
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
/* If we have a filter, only list the breakpoints it accepts. */
- if (filter && !filter (b))
+ if (filter && !filter (&b))
continue;
/* If we have a BP_NUM_LIST string, it is a list of breakpoints to
accept. Skip the others. */
if (bp_num_list != NULL && *bp_num_list != '\0')
{
- if (show_internal && parse_and_eval_long (bp_num_list) != b->number)
+ if (show_internal && parse_and_eval_long (bp_num_list) != b.number)
continue;
- if (!show_internal && !number_is_in_list (bp_num_list, b->number))
+ if (!show_internal && !number_is_in_list (bp_num_list, b.number))
continue;
}
- if (show_internal || user_breakpoint_p (b))
+ if (show_internal || user_breakpoint_p (&b))
{
int addr_bit, type_len;
- addr_bit = breakpoint_address_bits (b);
+ addr_bit = breakpoint_address_bits (&b);
if (addr_bit > print_address_bits)
print_address_bits = addr_bit;
- type_len = strlen (bptype_string (b->type));
+ type_len = strlen (bptype_string (b.type));
if (type_len > print_type_col_width)
print_type_col_width = type_len;
if (nr_printable_breakpoints > 0)
annotate_breakpoints_table ();
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
QUIT;
/* If we have a filter, only list the breakpoints it accepts. */
- if (filter && !filter (b))
+ if (filter && !filter (&b))
continue;
/* If we have a BP_NUM_LIST string, it is a list of breakpoints to
{
if (show_internal) /* maintenance info breakpoint */
{
- if (parse_and_eval_long (bp_num_list) != b->number)
+ if (parse_and_eval_long (bp_num_list) != b.number)
continue;
}
else /* all others */
{
- if (!number_is_in_list (bp_num_list, b->number))
+ if (!number_is_in_list (bp_num_list, b.number))
continue;
}
}
/* We only print out user settable breakpoints unless the
show_internal is set. */
- if (show_internal || user_breakpoint_p (b))
+ if (show_internal || user_breakpoint_p (&b))
{
- print_one_breakpoint (b, &last_loc, show_internal);
- for (bp_location *loc : b->locations ())
- if (loc->disabled_by_cond)
+ print_one_breakpoint (&b, &last_loc, show_internal);
+ for (bp_location &loc : b.locations ())
+ if (loc.disabled_by_cond)
has_disabled_by_cond_location = true;
}
}
struct program_space *pspace,
CORE_ADDR pc, struct obj_section *section)
{
- for (bp_location *bl : b->locations ())
+ for (bp_location &bl : b->locations ())
{
- if (bl->pspace == pspace
- && bl->address == pc
- && (!overlay_debugging || bl->section == section))
+ if (bl.pspace == pspace
+ && bl.address == pc
+ && (!overlay_debugging || bl.section == section))
return true;
}
return false;
{
int others = 0;
- for (breakpoint *b : all_breakpoints ())
- others += (user_breakpoint_p (b)
- && breakpoint_has_pc (b, pspace, pc, section));
+ for (breakpoint &b : all_breakpoints ())
+ others += (user_breakpoint_p (&b)
+ && breakpoint_has_pc (&b, pspace, pc, section));
if (others > 0)
{
gdb_printf (_("Note: breakpoint "));
else /* if (others == ???) */
gdb_printf (_("Note: breakpoints "));
- for (breakpoint *b : all_breakpoints ())
- if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section))
+ for (breakpoint &b : all_breakpoints ())
+ if (user_breakpoint_p (&b)
+ && breakpoint_has_pc (&b, pspace, pc, section))
{
others--;
- gdb_printf ("%d", b->number);
- if (b->thread == -1 && thread != -1)
+ gdb_printf ("%d", b.number);
+ if (b.thread == -1 && thread != -1)
gdb_printf (" (all threads)");
- else if (b->thread != -1)
+ else if (b.thread != -1)
{
- struct thread_info *thr = find_thread_global_id (b->thread);
+ struct thread_info *thr = find_thread_global_id (b.thread);
gdb_printf (" (thread %s)", print_thread_id (thr));
}
- else if (b->task != -1)
- gdb_printf (" (task %d)", b->task);
+ else if (b.task != -1)
+ gdb_printf (" (task %d)", b.task);
gdb_printf ("%s%s ",
- ((b->enable_state == bp_disabled
- || b->enable_state == bp_call_disabled)
+ ((b.enable_state == bp_disabled
+ || b.enable_state == bp_call_disabled)
? " (disabled)"
: ""),
(others > 1) ? ","
case bp_gnu_ifunc_resolver_return:
case bp_dprintf:
return bp_loc_software_breakpoint;
+
case bp_hardware_breakpoint:
return bp_loc_hardware_breakpoint;
+
case bp_hardware_watchpoint:
case bp_read_watchpoint:
case bp_access_watchpoint:
return bp_loc_hardware_watchpoint;
+
case bp_watchpoint:
return bp_loc_software_watchpoint;
- case bp_catchpoint:
+
case bp_tracepoint:
case bp_fast_tracepoint:
case bp_static_tracepoint:
case bp_static_marker_tracepoint:
+ return bp_loc_tracepoint;
+
+ case bp_catchpoint:
return bp_loc_other;
+
default:
internal_error (_("unknown breakpoint type"));
}
{
}
+/* See breakpoint.h. */
+
+std::string
+bp_location::to_string () const
+{
+ string_file stb;
+ ui_out_redirect_pop redir (current_uiout, &stb);
+ print_breakpoint_location (this->owner, this);
+ return stb.string ();
+}
+
/* Decrement reference count. If the reference count reaches 0,
destroy the bp_location. Sets *BLP to NULL. */
static breakpoint *
add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b)
{
- struct breakpoint *b1;
- struct breakpoint *result = b.get ();
-
/* Add this breakpoint to the end of the chain so that a list of
breakpoints will come out in order of increasing numbers. */
- b1 = breakpoint_chain;
- if (b1 == 0)
- breakpoint_chain = b.release ();
- else
- {
- while (b1->next)
- b1 = b1->next;
- b1->next = b.release ();
- }
+ breakpoint_chain.push_back (*b.release ());
- return result;
+ return &breakpoint_chain.back ();
}
/* Initialize loc->function_name. */
function_name = loc->msymbol->linkage_name ();
- if (b->type == bp_breakpoint && b->loc == loc
- && loc->next == NULL && b->related_breakpoint == b)
+ if (b->type == bp_breakpoint
+ && b->has_single_location ()
+ && b->related_breakpoint == b)
{
/* Create only the whole new breakpoint of this type but do not
mess more complicated breakpoints with multiple locations. */
we maintain a list of continually-inserted but always disabled
longjmp "master" breakpoints. Here, we simply create momentary
clones of those and enable them for the requested thread. */
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->pspace == current_program_space
- && (b->type == bp_longjmp_master
- || b->type == bp_exception_master))
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.pspace == current_program_space
+ && (b.type == bp_longjmp_master
+ || b.type == bp_exception_master))
{
- enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
+ bptype type = b.type == bp_longjmp_master ? bp_longjmp : bp_exception;
/* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
after their removal. */
- momentary_breakpoint_from_master (b, type, 1, thread);
+ momentary_breakpoint_from_master (&b, type, 1, thread);
}
tp->initiating_frame = frame;
void
delete_longjmp_breakpoint (int thread)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_longjmp || b->type == bp_exception)
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.type == bp_longjmp || b.type == bp_exception)
{
- if (b->thread == thread)
- delete_breakpoint (b);
+ if (b.thread == thread)
+ {
+ gdb_assert (b.inferior == -1);
+ delete_breakpoint (&b);
+ }
}
}
void
delete_longjmp_breakpoint_at_next_stop (int thread)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_longjmp || b->type == bp_exception)
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.type == bp_longjmp || b.type == bp_exception)
{
- if (b->thread == thread)
- b->disposition = disp_del_at_next_stop;
+ if (b.thread == thread)
+ {
+ gdb_assert (b.inferior == -1);
+ b.disposition = disp_del_at_next_stop;
+ }
}
}
{
breakpoint *retval = nullptr;
- for (breakpoint *b : all_breakpoints ())
- if (b->pspace == current_program_space && b->type == bp_longjmp_master)
+ for (breakpoint &b : all_breakpoints ())
+ if (b.pspace == current_program_space && b.type == bp_longjmp_master)
{
int thread = inferior_thread ()->global_num;
breakpoint *new_b
- = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
+ = momentary_breakpoint_from_master (&b, bp_longjmp_call_dummy,
1, thread);
/* Link NEW_B into the chain of RETVAL breakpoints. */
void
check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
{
- struct breakpoint *b, *b_tmp;
+ /* We would need to delete breakpoints other than the current one while
+ iterating, so all_breakpoints_safe is not sufficient to make that safe.
+ Save all breakpoints to delete in that set and delete them at the end. */
+ std::unordered_set<breakpoint *> to_delete;
- ALL_BREAKPOINTS_SAFE (b, b_tmp)
- if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
- {
- struct breakpoint *dummy_b = b->related_breakpoint;
-
- /* Find the bp_call_dummy breakpoint in the list of breakpoints
- chained off b->related_breakpoint. */
- while (dummy_b != b && dummy_b->type != bp_call_dummy)
- dummy_b = dummy_b->related_breakpoint;
-
- /* If there was no bp_call_dummy breakpoint then there's nothing
- more to do. Or, if the dummy frame associated with the
- bp_call_dummy is still on the stack then we need to leave this
- bp_call_dummy in place. */
- if (dummy_b->type != bp_call_dummy
- || frame_find_by_id (dummy_b->frame_id) != NULL)
- continue;
+ for (struct breakpoint &b : all_breakpoints ())
+ {
+ if (b.type == bp_longjmp_call_dummy && b.thread == tp->global_num)
+ {
+ gdb_assert (b.inferior == -1);
+ struct breakpoint *dummy_b = b.related_breakpoint;
- /* We didn't find the dummy frame on the stack, this could be
- because we have longjmp'd to a stack frame that is previous to
- the dummy frame, or it could be because the stack unwind is
- broken at some point between the longjmp frame and the dummy
- frame.
-
- Next we figure out why the stack unwind stopped. If it looks
- like the unwind is complete then we assume the dummy frame has
- been jumped over, however, if the unwind stopped for an
- unexpected reason then we assume the stack unwind is currently
- broken, and that we will (eventually) return to the dummy
- frame.
-
- It might be tempting to consider using frame_id_inner here, but
- that is not safe. There is no guarantee that the stack frames
- we are looking at here are even on the same stack as the
- original dummy frame, hence frame_id_inner can't be used. See
- the comments on frame_id_inner for more details. */
- bool unwind_finished_unexpectedly = false;
- for (frame_info_ptr fi = get_current_frame (); fi != nullptr; )
- {
- frame_info_ptr prev = get_prev_frame (fi);
- if (prev == nullptr)
- {
- /* FI is the last stack frame. Why did this frame not
- unwind further? */
- auto stop_reason = get_frame_unwind_stop_reason (fi);
- if (stop_reason != UNWIND_NO_REASON
- && stop_reason != UNWIND_OUTERMOST)
- unwind_finished_unexpectedly = true;
- }
- fi = prev;
- }
- if (unwind_finished_unexpectedly)
- continue;
+ /* Find the bp_call_dummy breakpoint in the list of breakpoints
+ chained off b->related_breakpoint. */
+ while (dummy_b != &b && dummy_b->type != bp_call_dummy)
+ dummy_b = dummy_b->related_breakpoint;
- dummy_frame_discard (dummy_b->frame_id, tp);
+ /* If there was no bp_call_dummy breakpoint then there's nothing
+ more to do. Or, if the dummy frame associated with the
+ bp_call_dummy is still on the stack then we need to leave this
+ bp_call_dummy in place. */
+ if (dummy_b->type != bp_call_dummy
+ || frame_find_by_id (dummy_b->frame_id) != NULL)
+ continue;
- while (b->related_breakpoint != b)
- {
- if (b_tmp == b->related_breakpoint)
- b_tmp = b->related_breakpoint->next;
- delete_breakpoint (b->related_breakpoint);
- }
- delete_breakpoint (b);
- }
+ /* We didn't find the dummy frame on the stack, this could be
+ because we have longjmp'd to a stack frame that is previous to
+ the dummy frame, or it could be because the stack unwind is
+ broken at some point between the longjmp frame and the dummy
+ frame.
+
+ Next we figure out why the stack unwind stopped. If it looks
+ like the unwind is complete then we assume the dummy frame has
+ been jumped over, however, if the unwind stopped for an
+ unexpected reason then we assume the stack unwind is currently
+ broken, and that we will (eventually) return to the dummy
+ frame.
+
+ It might be tempting to consider using frame_id_inner here, but
+ that is not safe. There is no guarantee that the stack frames
+ we are looking at here are even on the same stack as the
+ original dummy frame, hence frame_id_inner can't be used. See
+ the comments on frame_id_inner for more details. */
+ bool unwind_finished_unexpectedly = false;
+ for (frame_info_ptr fi = get_current_frame (); fi != nullptr; )
+ {
+ frame_info_ptr prev = get_prev_frame (fi);
+ if (prev == nullptr)
+ {
+ /* FI is the last stack frame. Why did this frame not
+ unwind further? */
+ auto stop_reason = get_frame_unwind_stop_reason (fi);
+ if (stop_reason != UNWIND_NO_REASON
+ && stop_reason != UNWIND_OUTERMOST)
+ unwind_finished_unexpectedly = true;
+ }
+ fi = prev;
+ }
+ if (unwind_finished_unexpectedly)
+ continue;
+
+ dummy_frame_discard (dummy_b->frame_id, tp);
+
+ for (breakpoint *related_breakpoint = b.related_breakpoint;
+ related_breakpoint != &b;
+ related_breakpoint = related_breakpoint->related_breakpoint)
+ to_delete.insert (b.related_breakpoint);
+
+ to_delete.insert (&b);
+ }
+ }
+
+ for (breakpoint *b : to_delete)
+ delete_breakpoint (b);
}
void
enable_overlay_breakpoints (void)
{
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_overlay_event)
+ for (breakpoint &b : all_breakpoints ())
+ if (b.type == bp_overlay_event)
{
- b->enable_state = bp_enabled;
+ b.enable_state = bp_enabled;
update_global_location_list (UGLL_MAY_INSERT);
overlay_events_enabled = 1;
}
void
disable_overlay_breakpoints (void)
{
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_overlay_event)
+ for (breakpoint &b : all_breakpoints ())
+ if (b.type == bp_overlay_event)
{
- b->enable_state = bp_disabled;
+ b.enable_state = bp_disabled;
update_global_location_list (UGLL_DONT_INSERT);
overlay_events_enabled = 0;
}
void
set_std_terminate_breakpoint (void)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->pspace == current_program_space
- && b->type == bp_std_terminate_master)
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.pspace == current_program_space
+ && b.type == bp_std_terminate_master)
{
- momentary_breakpoint_from_master (b, bp_std_terminate, 1,
+ momentary_breakpoint_from_master (&b, bp_std_terminate, 1,
inferior_thread ()->global_num);
}
}
void
delete_std_terminate_breakpoint (void)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_std_terminate)
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.type == bp_std_terminate)
+ delete_breakpoint (&b);
}
struct breakpoint *
b->enable_state = bp_enabled;
/* locspec has to be used or breakpoint_re_set will delete me. */
- b->locspec = new_address_location_spec (b->loc->address, NULL, 0);
+ b->locspec = new_address_location_spec (b->first_loc ().address, NULL, 0);
update_global_location_list_nothrow (UGLL_MAY_INSERT);
void
remove_jit_event_breakpoints (void)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_jit_event
- && b->loc->pspace == current_program_space)
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.type == bp_jit_event
+ && b.first_loc ().pspace == current_program_space)
+ delete_breakpoint (&b);
}
void
remove_solib_event_breakpoints (void)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_shlib_event
- && b->loc->pspace == current_program_space)
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.type == bp_shlib_event
+ && b.first_loc ().pspace == current_program_space)
+ delete_breakpoint (&b);
}
/* See breakpoint.h. */
void
remove_solib_event_breakpoints_at_next_stop (void)
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_shlib_event
- && b->loc->pspace == current_program_space)
- b->disposition = disp_del_at_next_stop;
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.type == bp_shlib_event
+ && b.first_loc ().pspace == current_program_space)
+ b.disposition = disp_del_at_next_stop;
}
/* Helper for create_solib_event_breakpoint /
/* Explicitly tell update_global_location_list to insert
locations. */
b = create_solib_event_breakpoint_1 (gdbarch, address, UGLL_INSERT);
- if (!b->loc->inserted)
+ if (!b->first_loc ().inserted)
{
delete_breakpoint (b);
return NULL;
loc->inserted = 0;
/* This may cause duplicate notifications for the same breakpoint. */
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (b);
if (!disabled_shlib_breaks)
{
|| (objfile->flags & OBJF_USERLOADED) == 0)
return;
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
bool bp_modified = false;
- if (!is_breakpoint (b) && !is_tracepoint (b))
+ if (!is_breakpoint (&b) && !is_tracepoint (&b))
continue;
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b.locations ())
{
- CORE_ADDR loc_addr = loc->address;
+ CORE_ADDR loc_addr = loc.address;
- if (loc->loc_type != bp_loc_hardware_breakpoint
- && loc->loc_type != bp_loc_software_breakpoint)
+ if (loc.loc_type != bp_loc_hardware_breakpoint
+ && loc.loc_type != bp_loc_software_breakpoint)
continue;
- if (loc->shlib_disabled != 0)
+ if (loc.shlib_disabled != 0)
continue;
- if (objfile->pspace != loc->pspace)
+ if (objfile->pspace != loc.pspace)
continue;
- if (loc->loc_type != bp_loc_hardware_breakpoint
- && loc->loc_type != bp_loc_software_breakpoint)
+ if (loc.loc_type != bp_loc_hardware_breakpoint
+ && loc.loc_type != bp_loc_software_breakpoint)
continue;
if (is_addr_in_objfile (loc_addr, objfile))
{
- loc->shlib_disabled = 1;
+ loc.shlib_disabled = 1;
/* At this point, we don't know whether the object was
unmapped from the inferior or not, so leave the
inserted flag alone. We'll handle failure to
uninsert quietly, in case the object was indeed
unmapped. */
- mark_breakpoint_location_modified (loc);
+ mark_breakpoint_location_modified (&loc);
bp_modified = true;
}
}
if (bp_modified)
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (&b);
}
}
pspace = current_program_space;
}
+/* Notify interpreters and observers that breakpoint B was created. */
+
+static void
+notify_breakpoint_created (breakpoint *b)
+{
+ interps_notify_breakpoint_created (b);
+ gdb::observers::breakpoint_created.notify (b);
+}
+
breakpoint *
install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_gll)
{
set_tracepoint_count (breakpoint_count);
if (!internal)
mention (b);
- gdb::observers::breakpoint_created.notify (b);
+
+ notify_breakpoint_created (b);
if (update_gll)
update_global_location_list (UGLL_MAY_INSERT);
{
int i = 0;
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
- for (bp_location *bl : b->locations ())
+ for (breakpoint &b : all_breakpoints ())
+ if (b.type == bp_hardware_breakpoint && breakpoint_enabled (&b))
+ for (bp_location &bl : b.locations ())
{
/* Special types of hardware breakpoints may use more than
one register. */
- i += b->resources_needed (bl);
+ i += b.resources_needed (&bl);
}
return i;
if (!breakpoint_enabled (b))
return 0;
- for (bp_location *bl : b->locations ())
+ for (bp_location &bl : b->locations ())
{
/* Special types of hardware watchpoints may use more than
one register. */
- i += b->resources_needed (bl);
+ i += b->resources_needed (&bl);
}
return i;
int i = 0;
*other_type_used = 0;
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
- if (b == except)
+ if (&b == except)
continue;
- if (!breakpoint_enabled (b))
+ if (!breakpoint_enabled (&b))
continue;
- if (b->type == type)
- i += hw_watchpoint_use_count (b);
- else if (is_hardware_watchpoint (b))
+ if (b.type == type)
+ i += hw_watchpoint_use_count (&b);
+ else if (is_hardware_watchpoint (&b))
*other_type_used = 1;
}
void
disable_watchpoints_before_interactive_call_start (void)
{
- for (breakpoint *b : all_breakpoints ())
- if (is_watchpoint (b) && breakpoint_enabled (b))
+ for (breakpoint &b : all_breakpoints ())
+ if (is_watchpoint (&b) && breakpoint_enabled (&b))
{
- b->enable_state = bp_call_disabled;
+ b.enable_state = bp_call_disabled;
update_global_location_list (UGLL_DONT_INSERT);
}
}
void
enable_watchpoints_after_interactive_call_stop (void)
{
- for (breakpoint *b : all_breakpoints ())
- if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
+ for (breakpoint &b : all_breakpoints ())
+ if (is_watchpoint (&b) && b.enable_state == bp_call_disabled)
{
- b->enable_state = bp_enabled;
+ b.enable_state = bp_enabled;
update_global_location_list (UGLL_MAY_INSERT);
}
}
std::unique_ptr<breakpoint> copy
(new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
orig->frame_id, thread));
- copy->loc = copy->allocate_location ();
- set_breakpoint_location_function (copy->loc);
-
- copy->loc->gdbarch = orig->loc->gdbarch;
- copy->loc->requested_address = orig->loc->requested_address;
- copy->loc->address = orig->loc->address;
- copy->loc->section = orig->loc->section;
- copy->loc->pspace = orig->loc->pspace;
- copy->loc->probe = orig->loc->probe;
- copy->loc->line_number = orig->loc->line_number;
- copy->loc->symtab = orig->loc->symtab;
- copy->loc->enabled = loc_enabled;
+ const bp_location &orig_loc = orig->first_loc ();
+ bp_location *copy_loc = copy->allocate_location ();
+ copy->add_location (*copy_loc);
+ set_breakpoint_location_function (copy_loc);
+
+ copy_loc->gdbarch = orig_loc.gdbarch;
+ copy_loc->requested_address = orig_loc.requested_address;
+ copy_loc->address = orig_loc.address;
+ copy_loc->section = orig_loc.section;
+ copy_loc->pspace = orig_loc.pspace;
+ copy_loc->probe = orig_loc.probe;
+ copy_loc->line_number = orig_loc.line_number;
+ copy_loc->symtab = orig_loc.symtab;
+ copy_loc->enabled = loc_enabled;
breakpoint *b = add_to_breakpoint_chain (std::move (copy));
update_global_location_list_nothrow (UGLL_DONT_INSERT);
bp_location *
code_breakpoint::add_location (const symtab_and_line &sal)
{
- struct bp_location *new_loc, **tmp;
CORE_ADDR adjusted_address;
struct gdbarch *loc_gdbarch = get_sal_arch (sal);
sal.pspace);
/* Sort the locations by their ADDRESS. */
- new_loc = allocate_location ();
- for (tmp = &(loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
- tmp = &((*tmp)->next))
- ;
- new_loc->next = *tmp;
- *tmp = new_loc;
+ bp_location *new_loc = this->allocate_location ();
new_loc->requested_address = sal.pc;
new_loc->address = adjusted_address;
new_loc->msymbol = sal.msymbol;
new_loc->objfile = sal.objfile;
+ breakpoint::add_location (*new_loc);
+
set_breakpoint_location_function (new_loc);
/* While by definition, permanent breakpoints are already present in the
update_dprintf_commands (const char *args, int from_tty,
struct cmd_list_element *c)
{
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_dprintf)
- update_dprintf_command_list (b);
+ for (breakpoint &b : all_breakpoints ())
+ if (b.type == bp_dprintf)
+ update_dprintf_command_list (&b);
}
code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
gdb::unique_xmalloc_ptr<char> cond_string_,
gdb::unique_xmalloc_ptr<char> extra_string_,
enum bpdisp disposition_,
- int thread_, int task_, int ignore_count_,
+ int thread_, int task_, int inferior_,
+ int ignore_count_,
int from_tty,
int enabled_, unsigned flags,
int display_canonical_)
gdb_assert (!sals.empty ());
- /* At most one of thread or task can be set on any breakpoint. */
- gdb_assert (thread == -1 || task == -1);
+ /* At most one of thread, task, or inferior can be set on any breakpoint. */
+ gdb_assert (((thread == -1 ? 0 : 1)
+ + (task == -1 ? 0 : 1)
+ + (inferior == -1 ? 0 : 1)) <= 1);
+
thread = thread_;
task = task_;
+ inferior = inferior_;
cond_string = std::move (cond_string_);
extra_string = std::move (extra_string_);
/* The order of the locations is now stable. Set the location
condition using the location's number. */
int loc_num = 1;
- for (bp_location *bl : locations ())
+ for (bp_location &bl : locations ())
{
if (cond_string != nullptr)
- set_breakpoint_location_condition (cond_string.get (), bl,
+ set_breakpoint_location_condition (cond_string.get (), &bl,
number, loc_num);
++loc_num;
if (locspec_ != nullptr)
locspec = std::move (locspec_);
else
- locspec = new_address_location_spec (this->loc->address, NULL, 0);
+ locspec = new_address_location_spec (this->first_loc ().address, NULL, 0);
filter = std::move (filter_);
}
gdb::unique_xmalloc_ptr<char> cond_string,
gdb::unique_xmalloc_ptr<char> extra_string,
enum bptype type, enum bpdisp disposition,
- int thread, int task, int ignore_count,
+ int thread, int task, int inferior, int ignore_count,
int from_tty,
int enabled, int internal, unsigned flags,
int display_canonical)
std::move (cond_string),
std::move (extra_string),
disposition,
- thread, task, ignore_count,
+ thread, task, inferior, ignore_count,
from_tty,
enabled, flags,
display_canonical);
gdb::unique_xmalloc_ptr<char> cond_string,
gdb::unique_xmalloc_ptr<char> extra_string,
enum bptype type, enum bpdisp disposition,
- int thread, int task, int ignore_count,
+ int thread, int task, int inferior,
+ int ignore_count,
int from_tty,
int enabled, int internal, unsigned flags)
{
std::move (cond_string),
std::move (extra_string),
type, disposition,
- thread, task, ignore_count,
+ thread, task, inferior, ignore_count,
from_tty, enabled, internal, flags,
canonical->special_display);
}
}
}
-/* Given TOK, a string specification of condition and thread, as
- accepted by the 'break' command, extract the condition
- string and thread number and set *COND_STRING and *THREAD.
- PC identifies the context at which the condition should be parsed.
- If no condition is found, *COND_STRING is set to NULL.
- If no thread is found, *THREAD is set to -1. */
+/* Given TOK, a string specification of condition and thread, as accepted
+ by the 'break' command, extract the condition string into *COND_STRING.
+ If no condition string is found then *COND_STRING is set to nullptr.
+
+ If the breakpoint specification has an associated thread, task, or
+ inferior, these are extracted into *THREAD, *TASK, and *INFERIOR
+ respectively, otherwise these arguments are set to -1 (for THREAD and
+ INFERIOR) or 0 (for TASK).
+
+ PC identifies the context at which the condition should be parsed. */
static void
find_condition_and_thread (const char *tok, CORE_ADDR pc,
gdb::unique_xmalloc_ptr<char> *cond_string,
- int *thread, int *task,
+ int *thread, int *inferior, int *task,
gdb::unique_xmalloc_ptr<char> *rest)
{
cond_string->reset ();
*thread = -1;
+ *inferior = -1;
*task = -1;
rest->reset ();
bool force = false;
if ((*tok == '"' || *tok == ',') && rest)
{
rest->reset (savestring (tok, strlen (tok)));
- return;
+ break;
}
end_tok = skip_to_space (tok);
if (*task != -1)
error (_("You can specify only one of thread or task."));
+ if (*inferior != -1)
+ error (_("You can specify only one of inferior or thread."));
+
tok = end_tok + 1;
thr = parse_thread_id (tok, &tmptok);
if (tok == tmptok)
*thread = thr->global_num;
tok = tmptok;
}
+ else if (toklen >= 1 && strncmp (tok, "inferior", toklen) == 0)
+ {
+ if (*inferior != -1)
+ error(_("You can specify only one inferior."));
+
+ if (*task != -1)
+ error (_("You can specify only one of inferior or task."));
+
+ if (*thread != -1)
+ error (_("You can specify only one of inferior or thread."));
+
+ char *tmptok;
+ tok = end_tok + 1;
+ *inferior = strtol (tok, &tmptok, 0);
+ if (tok == tmptok)
+ error (_("Junk after inferior keyword."));
+ if (!valid_global_inferior_id (*inferior))
+ error (_("Unknown inferior number %d."), *inferior);
+ tok = tmptok;
+ }
else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
{
char *tmptok;
if (*thread != -1)
error (_("You can specify only one of thread or task."));
+ if (*inferior != -1)
+ error (_("You can specify only one of inferior or task."));
+
tok = end_tok + 1;
*task = strtol (tok, &tmptok, 0);
if (tok == tmptok)
else if (rest)
{
rest->reset (savestring (tok, strlen (tok)));
- return;
+ break;
}
else
error (_("Junk at end of arguments."));
find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
const char *input,
gdb::unique_xmalloc_ptr<char> *cond_string,
- int *thread, int *task,
+ int *thread, int *inferior, int *task,
gdb::unique_xmalloc_ptr<char> *rest)
{
int num_failures = 0;
{
gdb::unique_xmalloc_ptr<char> cond;
int thread_id = -1;
+ int inferior_id = -1;
int task_id = -1;
gdb::unique_xmalloc_ptr<char> remaining;
try
{
find_condition_and_thread (input, sal.pc, &cond, &thread_id,
- &task_id, &remaining);
+ &inferior_id, &task_id, &remaining);
*cond_string = std::move (cond);
- /* At most one of thread or task can be set. */
- gdb_assert (thread_id == -1 || task_id == -1);
+ /* A value of -1 indicates that these fields are unset. At most
+ one of these fields should be set (to a value other than -1)
+ at this point. */
+ gdb_assert (((thread_id == -1 ? 1 : 0)
+ + (task_id == -1 ? 1 : 0)
+ + (inferior_id == -1 ? 1 : 0)) >= 2);
*thread = thread_id;
+ *inferior = inferior_id;
*task = task_id;
*rest = std::move (remaining);
break;
create_breakpoint (struct gdbarch *gdbarch,
location_spec *locspec,
const char *cond_string,
- int thread, const char *extra_string,
+ int thread, int inferior,
+ const char *extra_string,
bool force_condition, int parse_extra,
int tempflag, enum bptype type_wanted,
int ignore_count,
int task = -1;
int prev_bkpt_count = breakpoint_count;
+ gdb_assert (thread == -1 || thread > 0);
+ gdb_assert (inferior == -1 || inferior > 0);
+ gdb_assert (thread == -1 || inferior == -1);
+
gdb_assert (ops != NULL);
/* If extra_string isn't useful, set it to NULL. */
const linespec_sals &lsal = canonical.lsals[0];
find_condition_and_thread_for_sals (lsal.sals, extra_string,
- &cond, &thread, &task, &rest);
+ &cond, &thread, &inferior,
+ &task, &rest);
cond_string_copy = std::move (cond);
extra_string_copy = std::move (rest);
}
std::move (extra_string_copy),
type_wanted,
tempflag ? disp_del : disp_donttouch,
- thread, task, ignore_count,
+ thread, task, inferior, ignore_count,
from_tty, enabled, internal, flags);
}
else
create_breakpoint (get_current_arch (),
locspec.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
+ NULL,
+ -1 /* thread */, -1 /* inferior */,
+ arg, false, 1 /* parse arg */,
tempflag, type_wanted,
0 /* Ignore count */,
pending_break_support,
sal->symtab->compunit ());
if (bv != NULL)
{
- sym = block_linkage_function (b);
+ sym = b->linkage_function ();
if (sym != NULL)
sal->section
= sym->obj_section (sal->symtab->compunit ()->objfile ());
create_breakpoint (get_current_arch (),
locspec.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
+ NULL, -1, -1,
+ arg, false, 1 /* parse arg */,
0, bp_dprintf,
0 /* Ignore count */,
pending_break_support,
enum print_stop_action
ranged_breakpoint::print_it (const bpstat *bs) const
{
- struct bp_location *bl = loc;
struct ui_out *uiout = current_uiout;
gdb_assert (type == bp_hardware_breakpoint);
/* Ranged breakpoints have only one location. */
- gdb_assert (bl && bl->next == NULL);
+ gdb_assert (this->has_single_location ());
annotate_breakpoint (number);
/* Implement the "print_one" method for ranged breakpoints. */
bool
-ranged_breakpoint::print_one (bp_location **last_loc) const
+ranged_breakpoint::print_one (const bp_location **last_loc) const
{
- struct bp_location *bl = loc;
struct value_print_options opts;
struct ui_out *uiout = current_uiout;
/* Ranged breakpoints have only one location. */
- gdb_assert (bl && bl->next == NULL);
+ gdb_assert (this->has_single_location ());
get_user_print_options (&opts);
by ranged_breakpoint::print_one_detail. */
uiout->field_skip ("addr");
annotate_field (5);
- print_breakpoint_location (this, bl);
- *last_loc = bl;
+ print_breakpoint_location (this, &this->first_loc ());
+ *last_loc = &this->first_loc ();
return true;
}
ranged_breakpoint::print_one_detail (struct ui_out *uiout) const
{
CORE_ADDR address_start, address_end;
- struct bp_location *bl = loc;
+ const bp_location &bl = this->first_loc ();
string_file stb;
- gdb_assert (bl);
-
- address_start = bl->address;
- address_end = address_start + bl->length - 1;
+ address_start = bl.address;
+ address_end = address_start + bl.length - 1;
uiout->text ("\taddress range: ");
stb.printf ("[%s, %s]",
- print_core_address (bl->gdbarch, address_start),
- print_core_address (bl->gdbarch, address_end));
+ print_core_address (bl.gdbarch, address_start),
+ print_core_address (bl.gdbarch, address_end));
uiout->field_stream ("addr", stb);
uiout->text ("\n");
}
void
ranged_breakpoint::print_mention () const
{
- struct bp_location *bl = loc;
+ const bp_location &bl = this->first_loc ();
struct ui_out *uiout = current_uiout;
- gdb_assert (bl);
gdb_assert (type == bp_hardware_breakpoint);
uiout->message (_("Hardware assisted ranged breakpoint %d from %s to %s."),
- number, paddress (bl->gdbarch, bl->address),
- paddress (bl->gdbarch, bl->address + bl->length - 1));
+ number, paddress (bl.gdbarch, bl.address),
+ paddress (bl.gdbarch, bl.address + bl.length - 1));
}
/* Implement the "print_recreate" method for ranged breakpoints. */
void
watchpoint::check_status (bpstat *bs)
{
- gdb_assert (is_watchpoint (bs->breakpoint_at));
-
bpstat_check_watchpoint (bs);
}
enum print_stop_action
watchpoint::print_it (const bpstat *bs) const
{
- struct breakpoint *b;
enum print_stop_action result;
struct ui_out *uiout = current_uiout;
gdb_assert (bs->bp_location_at != NULL);
- b = bs->breakpoint_at;
-
- annotate_watchpoint (b->number);
+ annotate_watchpoint (this->number);
maybe_print_thread_hit_breakpoint (uiout);
string_file stb;
gdb::optional<ui_out_emit_tuple> tuple_emitter;
- switch (b->type)
+ switch (this->type)
{
case bp_watchpoint:
case bp_hardware_watchpoint:
if (uiout->is_mi_like_p ())
uiout->field_string
("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
- mention (b);
+ mention (this);
tuple_emitter.emplace (uiout, "value");
uiout->text ("\nOld value = ");
watchpoint_value_print (bs->old_val.get (), &stb);
if (uiout->is_mi_like_p ())
uiout->field_string
("reason", async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
- mention (b);
+ mention (this);
tuple_emitter.emplace (uiout, "value");
uiout->text ("\nValue = ");
watchpoint_value_print (val.get (), &stb);
uiout->field_string
("reason",
async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
- mention (b);
+ mention (this);
tuple_emitter.emplace (uiout, "value");
uiout->text ("\nOld value = ");
watchpoint_value_print (bs->old_val.get (), &stb);
}
else
{
- mention (b);
+ mention (this);
if (uiout->is_mi_like_p ())
uiout->field_string
("reason",
enum print_stop_action
masked_watchpoint::print_it (const bpstat *bs) const
{
- struct breakpoint *b = bs->breakpoint_at;
struct ui_out *uiout = current_uiout;
/* Masked watchpoints have only one location. */
- gdb_assert (b->loc && b->loc->next == NULL);
+ gdb_assert (this->has_single_location ());
- annotate_watchpoint (b->number);
+ annotate_watchpoint (this->number);
maybe_print_thread_hit_breakpoint (uiout);
- switch (b->type)
+ switch (this->type)
{
case bp_hardware_watchpoint:
if (uiout->is_mi_like_p ())
internal_error (_("Invalid hardware watchpoint type."));
}
- mention (b);
+ mention (this);
uiout->text (_("\n\
Check the underlying instruction at PC for the memory\n\
address and value which triggered this watchpoint.\n"));
masked_watchpoint::print_one_detail (struct ui_out *uiout) const
{
/* Masked watchpoints have only one location. */
- gdb_assert (loc && loc->next == NULL);
+ gdb_assert (this->has_single_location ());
uiout->text ("\tmask ");
- uiout->field_core_addr ("mask", loc->gdbarch, hw_wp_mask);
+ uiout->field_core_addr ("mask", this->first_loc ().gdbarch, hw_wp_mask);
uiout->text ("\n");
}
const char *cond_end = NULL;
enum bptype bp_type;
int thread = -1;
+ int inferior = -1;
/* Flag to indicate whether we are going to use masks for
the hardware watchpoint. */
bool use_mask = false;
if (task != -1)
error (_("You can specify only one of thread or task."));
+ if (inferior != -1)
+ error (_("You can specify only one of inferior or thread."));
+
/* Extract the thread ID from the next token. */
thr = parse_thread_id (value_start, &endp);
-
- /* Check if the user provided a valid thread ID. */
- if (*endp != ' ' && *endp != '\t' && *endp != '\0')
- invalid_thread_id_error (value_start);
+ if (value_start == endp)
+ error (_("Junk after thread keyword."));
thread = thr->global_num;
}
if (thread != -1)
error (_("You can specify only one of thread or task."));
+ if (inferior != -1)
+ error (_("You can specify only one of inferior or task."));
+
task = strtol (value_start, &tmp, 0);
if (tmp == value_start)
error (_("Junk after task keyword."));
if (!valid_task_id (task))
error (_("Unknown task %d."), task);
}
+ else if (toklen == 8 && startswith (tok, "inferior"))
+ {
+ /* Support for watchpoints will be added in a later commit. */
+ error (_("Cannot use 'inferior' keyword with watchpoints"));
+ }
else if (toklen == 4 && startswith (tok, "mask"))
{
/* We've found a "mask" token, which means the user wants to
scope_breakpoint->frame_id = caller_frame_id;
/* Set the address at which we will stop. */
- scope_breakpoint->loc->gdbarch = caller_arch;
- scope_breakpoint->loc->requested_address = caller_pc;
- scope_breakpoint->loc->address
- = adjust_breakpoint_address (scope_breakpoint->loc->gdbarch,
- scope_breakpoint->loc->requested_address,
+ bp_location &loc = scope_breakpoint->first_loc ();
+ loc.gdbarch = caller_arch;
+ loc.requested_address = caller_pc;
+ loc.address
+ = adjust_breakpoint_address (loc.gdbarch, loc.requested_address,
scope_breakpoint->type,
current_program_space);
}
/* At most one of thread or task can be set on a watchpoint. */
gdb_assert (thread == -1 || task == -1);
w->thread = thread;
+ w->inferior = inferior;
w->task = task;
w->disposition = disp_donttouch;
w->pspace = current_program_space;
w->cond_exp_valid_block = cond_exp_valid_block;
if (just_location)
{
- struct type *t = val.get ()->type ();
+ struct type *t = val->type ();
CORE_ADDR addr = value_as_address (val.get ());
w->exp_string_reparse
{
struct value *v = iter.get ();
- if (VALUE_LVAL (v) == lval_memory)
+ if (v->lval () == lval_memory)
{
- if (v != head && value_lazy (v))
+ if (v != head && v->lazy ())
/* A lazy memory lvalue in the chain is one that GDB never
needed to fetch; we either just used its address (e.g.,
`a' in `a.b') or we never needed it at all (e.g., `a'
|| (vtype->code () != TYPE_CODE_STRUCT
&& vtype->code () != TYPE_CODE_ARRAY))
{
- CORE_ADDR vaddr = value_address (v);
+ CORE_ADDR vaddr = v->address ();
int len;
int num_regs;
}
}
}
- else if (VALUE_LVAL (v) != not_lval
- && v->deprecated_modifiable () == 0)
+ else if (v->lval () != not_lval && !v->deprecated_modifiable ())
return 0; /* These are values from the history (e.g., $1). */
- else if (VALUE_LVAL (v) == lval_register)
+ else if (v->lval () == lval_register)
return 0; /* Cannot watch a register with a HW watchpoint. */
}
? NULL : symtab_to_fullname (sal.symtab));
/* Find all matching breakpoints and add them to 'found'. */
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
int match = 0;
/* Are we going to delete b? */
- if (b->type != bp_none && !is_watchpoint (b)
- && user_breakpoint_p (b))
+ if (b.type != bp_none && !is_watchpoint (&b)
+ && user_breakpoint_p (&b))
{
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b.locations ())
{
/* If the user specified file:line, don't allow a PC
match. This matches historical gdb behavior. */
int pc_match = (!sal.explicit_line
&& sal.pc
- && (loc->pspace == sal.pspace)
- && (loc->address == sal.pc)
- && (!section_is_overlay (loc->section)
- || loc->section == sal.section));
+ && (loc.pspace == sal.pspace)
+ && (loc.address == sal.pc)
+ && (!section_is_overlay (loc.section)
+ || loc.section == sal.section));
int line_match = 0;
if ((default_match || sal.explicit_line)
- && loc->symtab != NULL
+ && loc.symtab != NULL
&& sal_fullname != NULL
- && sal.pspace == loc->pspace
- && loc->line_number == sal.line
- && filename_cmp (symtab_to_fullname (loc->symtab),
+ && sal.pspace == loc.pspace
+ && loc.line_number == sal.line
+ && filename_cmp (symtab_to_fullname (loc.symtab),
sal_fullname) == 0)
line_match = 1;
}
if (match)
- found.push_back (b);
+ found.push_back (&b);
}
}
&& bs->stop)
delete_breakpoint (bs->breakpoint_at);
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->disposition == disp_del_at_next_stop)
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.disposition == disp_del_at_next_stop)
+ delete_breakpoint (&b);
}
/* A comparison function for bp_location AP and BP being interfaced to
std::sort. Sort elements primarily by their ADDRESS (no matter what
bl_address_is_meaningful says), secondarily by ordering first
- permanent elements and terciarily just ensuring the array is sorted
+ permanent elements and tertiarily just ensuring the array is sorted
stable way despite std::sort being an unstable algorithm. */
static int
scoped_restore_current_pspace_and_thread restore_pspace_thread;
- for (breakpoint *b : all_tracepoints ())
+ for (breakpoint &b : all_tracepoints ())
{
- struct tracepoint *t;
bool bp_location_downloaded = false;
- if ((b->type == bp_fast_tracepoint
+ if ((b.type == bp_fast_tracepoint
? !may_insert_fast_tracepoints
: !may_insert_tracepoints))
continue;
if (can_download_tracepoint == TRIBOOL_FALSE)
break;
- for (bp_location *bl : b->locations ())
+ for (bp_location &bl : b.locations ())
{
/* In tracepoint, locations are _never_ duplicated, so
should_be_inserted is equivalent to
unduplicated_should_be_inserted. */
- if (!should_be_inserted (bl) || bl->inserted)
+ if (!should_be_inserted (&bl) || bl.inserted)
continue;
- switch_to_program_space_and_thread (bl->pspace);
+ switch_to_program_space_and_thread (bl.pspace);
- target_download_tracepoint (bl);
+ target_download_tracepoint (&bl);
- bl->inserted = 1;
+ bl.inserted = 1;
bp_location_downloaded = true;
}
- t = (struct tracepoint *) b;
- t->number_on_target = b->number;
+
+ tracepoint &t = gdb::checked_static_cast<tracepoint &> (b);
+ t.number_on_target = b.number;
if (bp_location_downloaded)
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (&b);
}
}
/* Last breakpoint location program space that was marked for update. */
int last_pspace_num = -1;
+ breakpoint_debug_printf ("insert_mode = %s",
+ ugll_insert_mode_text (insert_mode));
+
/* Used in the duplicates detection below. When iterating over all
bp_locations, points to the first bp_location of a given address.
Breakpoints and watchpoints of different types are never
std::vector<bp_location *> old_locations = std::move (bp_locations);
bp_locations.clear ();
- for (breakpoint *b : all_breakpoints ())
- for (bp_location *loc : b->locations ())
- bp_locations.push_back (loc);
+ for (breakpoint &b : all_breakpoints ())
+ for (bp_location &loc : b.locations ())
+ bp_locations.push_back (&loc);
/* See if we need to "upgrade" a software breakpoint to a hardware
breakpoint. Do this before deciding whether locations are
Note that at this point, old_loc->owner is still
valid, as delete_breakpoint frees the breakpoint
only after calling us. */
- gdb_printf (_("warning: Error removing "
- "breakpoint %d\n"),
- old_loc->owner->number);
+ warning (_("error removing breakpoint %d at %s"),
+ old_loc->owner->number,
+ paddress (old_loc->gdbarch, old_loc->address));
}
removed = true;
}
/* i18n: cagney/2005-02-11: Below needs to be merged into a
single string. */
- if (loc == NULL)
+ if (!this->has_locations ())
{
/* For pending locations, the output differs slightly based
on extra_string. If this is non-NULL, it contains either
}
else
{
- if (opts.addressprint || loc->symtab == NULL)
+ const bp_location &bl = this->first_loc ();
+ if (opts.addressprint || bl.symtab == nullptr)
gdb_printf (" at %ps",
styled_string (address_style.style (),
- paddress (loc->gdbarch,
- loc->address)));
- if (loc->symtab != NULL)
+ paddress (bl.gdbarch,
+ bl.address)));
+ if (bl.symtab != NULL)
{
/* If there is a single location, we can print the location
more nicely. */
- if (loc->next == NULL)
+ if (!this->has_multiple_locations ())
{
const char *filename
- = symtab_to_filename_for_display (loc->symtab);
+ = symtab_to_filename_for_display (bl.symtab);
gdb_printf (": file %ps, line %d.",
styled_string (file_name_style.style (),
filename),
- loc->line_number);
+ bl.line_number);
}
else
/* This is not ideal, but each location may have a
gdb_printf (": %s.", locspec->to_string ());
}
- if (loc->next)
+ if (this->has_multiple_locations ())
{
- struct bp_location *iter = loc;
- int n = 0;
- for (; iter; iter = iter->next)
- ++n;
+ int n = std::distance (m_locations.begin (), m_locations.end ());
gdb_printf (" (%d locations)", n);
}
}
bp_location_range breakpoint::locations () const
{
- return bp_location_range (this->loc);
+ return bp_location_range (m_locations.begin (), m_locations.end ());
}
struct bp_location *
return new bp_location (this);
}
+/* See breakpoint.h. */
+
+void
+breakpoint::add_location (bp_location &loc)
+{
+ gdb_assert (loc.owner == this);
+ gdb_assert (!loc.is_linked ());
+
+ auto ub = std::upper_bound (m_locations.begin (), m_locations.end (),
+ loc,
+ [] (const bp_location &left,
+ const bp_location &right)
+ { return left.address < right.address; });
+ m_locations.insert (ub, loc);
+}
+
+/* See breakpoint.h. */
+
+void
+breakpoint::unadd_location (bp_location &loc)
+{
+ gdb_assert (loc.owner == this);
+ gdb_assert (loc.is_linked ());
+
+ m_locations.erase (m_locations.iterator_to (loc));
+}
+
#define internal_error_pure_virtual_called() \
gdb_assert_not_reached ("pure virtual function called")
/* Print out extra_string if this breakpoint is pending. It might
contain, for example, conditions that were set by the user. */
- if (loc == NULL && extra_string != NULL)
+ if (!this->has_locations () && extra_string != NULL)
gdb_printf (fp, " %s", extra_string.get ());
print_recreate_thread (fp);
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
- int task, int ignore_count,
+ int task, int inferior,
+ int ignore_count,
int from_tty, int enabled,
int internal, unsigned flags)
{
std::move (cond_string),
std::move (extra_string),
disposition,
- thread, task, ignore_count,
+ thread, task, inferior, ignore_count,
from_tty, enabled, flags,
canonical->special_display));
return b->type == bp_static_marker_tracepoint;
}
+/* Notify interpreters and observers that breakpoint B was deleted. */
+
+static void
+notify_breakpoint_deleted (breakpoint *b)
+{
+ interps_notify_breakpoint_deleted (b);
+ gdb::observers::breakpoint_deleted.notify (b);
+}
+
/* Delete a breakpoint and clean up all traces of it in the data
structures. */
a problem in that process, we'll be asked to delete the half-created
watchpoint. In that case, don't announce the deletion. */
if (bpt->number)
- gdb::observers::breakpoint_deleted.notify (bpt);
+ notify_breakpoint_deleted (bpt);
- if (breakpoint_chain == bpt)
- breakpoint_chain = bpt->next;
-
- for (breakpoint *b : all_breakpoints ())
- if (b->next == bpt)
- {
- b->next = bpt->next;
- break;
- }
+ breakpoint_chain.erase (breakpoint_chain.iterator_to (*bpt));
/* Be sure no bpstat's are pointing at the breakpoint after it's
been freed. */
belong to this breakpoint. Do this before freeing the breakpoint
itself, since remove_breakpoint looks at location's owner. It
might be better design to have location completely
- self-contained, but it's not the case now. */
+ self-contained, but it's not the case now.
+
+ Clear the location linked list first, otherwise, the intrusive_list
+ destructor accesses the locations after they are freed. */
+ bpt->clear_locations ();
update_global_location_list (UGLL_DONT_INSERT);
/* On the chance that someone will soon try again to delete this
/* Delete all breakpoints if no argument. Do not delete
internal breakpoints, these have to be deleted with an
explicit breakpoint number argument. */
- for (breakpoint *b : all_breakpoints ())
- if (user_breakpoint_p (b))
+ for (breakpoint &b : all_breakpoints ())
+ if (user_breakpoint_p (&b))
{
breaks_to_delete = 1;
break;
/* Ask user only if there are some breakpoints to delete. */
if (!from_tty
|| (breaks_to_delete && query (_("Delete all breakpoints? "))))
- for (breakpoint *b : all_breakpoints_safe ())
- if (user_breakpoint_p (b))
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (user_breakpoint_p (&b))
+ delete_breakpoint (&b);
}
else
map_breakpoint_numbers
static bool
all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
{
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b->locations ())
if ((pspace == NULL
- || loc->pspace == pspace)
- && !loc->shlib_disabled
- && !loc->pspace->executing_startup)
+ || loc.pspace == pspace)
+ && !loc.shlib_disabled
+ && !loc.pspace->executing_startup)
return false;
return true;
}
/* Subroutine of update_breakpoint_locations to simplify it.
- Return true if multiple fns in list LOC have the same name.
+ Return true if multiple fns in list LOCS have the same name.
Null names are ignored. */
static bool
-ambiguous_names_p (struct bp_location *loc)
+ambiguous_names_p (const bp_location_range &locs)
{
- struct bp_location *l;
htab_up htab (htab_create_alloc (13, htab_hash_string, htab_eq_string, NULL,
xcalloc, xfree));
- for (l = loc; l != NULL; l = l->next)
+ for (const bp_location &l : locs)
{
const char **slot;
- const char *name = l->function_name.get ();
+ const char *name = l.function_name.get ();
/* Allow for some names to be NULL, ignore them. */
if (name == NULL)
uiout->field_signed ("line", sal2.line);
uiout->text ("\n");
- b->loc->line_number = sal2.line;
- b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
+ b->first_loc ().line_number = sal2.line;
+ b->first_loc ().symtab = sym != NULL ? sal2.symtab : NULL;
std::unique_ptr<explicit_location_spec> els
(new explicit_location_spec ());
els->source_filename
= xstrdup (symtab_to_filename_for_display (sal2.symtab));
- els->line_offset.offset = b->loc->line_number;
+ els->line_offset.offset = b->first_loc ().line_number;
els->line_offset.sign = LINE_OFFSET_NONE;
b->locspec = std::move (els);
return sal;
}
-/* Returns true iff locations A and B are sufficiently same that
+/* Returns true iff location lists A and B are sufficiently same that
we don't need to report breakpoint as changed. */
static bool
-locations_are_equal (struct bp_location *a, struct bp_location *b)
+locations_are_equal (const bp_location_list &a, const bp_location_range &b)
{
- while (a && b)
+ auto a_iter = a.begin ();
+ auto b_iter = b.begin ();
+
+ for (; a_iter != a.end () && b_iter != b.end (); ++a_iter, ++b_iter)
{
- if (a->address != b->address)
+ if (a_iter->address != b_iter->address)
return false;
- if (a->shlib_disabled != b->shlib_disabled)
+ if (a_iter->shlib_disabled != b_iter->shlib_disabled)
return false;
- if (a->enabled != b->enabled)
+ if (a_iter->enabled != b_iter->enabled)
return false;
- if (a->disabled_by_cond != b->disabled_by_cond)
+ if (a_iter->disabled_by_cond != b_iter->disabled_by_cond)
return false;
-
- a = a->next;
- b = b->next;
}
- if ((a == NULL) != (b == NULL))
- return false;
-
- return true;
+ return (a_iter == a.end ()) == (b_iter == b.end ());
}
-/* Split all locations of B that are bound to PSPACE out of B's
- location list to a separate list and return that list's head. If
- PSPACE is NULL, hoist out all locations of B. */
+/* See breakpoint.h. */
-static struct bp_location *
-hoist_existing_locations (struct breakpoint *b, struct program_space *pspace)
+bp_location_list
+breakpoint::steal_locations (program_space *pspace)
{
- struct bp_location head;
- struct bp_location *i = b->loc;
- struct bp_location **i_link = &b->loc;
- struct bp_location *hoisted = &head;
-
if (pspace == NULL)
- {
- i = b->loc;
- b->loc = NULL;
- return i;
- }
+ return std::move (m_locations);
- head.next = NULL;
+ bp_location_list ret;
- while (i != NULL)
+ for (auto it = m_locations.begin (); it != m_locations.end (); )
{
- if (i->pspace == pspace)
+ if (it->pspace == pspace)
{
- *i_link = i->next;
- i->next = NULL;
- hoisted->next = i;
- hoisted = i;
+ bp_location &loc = *it;
+ it = m_locations.erase (it);
+ ret.push_back (loc);
}
else
- i_link = &i->next;
- i = *i_link;
+ ++it;
}
- return head.next;
+ return ret;
}
/* Create new breakpoint locations for B (a hardware or software
gdb::array_view<const symtab_and_line> sals,
gdb::array_view<const symtab_and_line> sals_end)
{
- struct bp_location *existing_locations;
-
if (!sals_end.empty () && (sals.size () != 1 || sals_end.size () != 1))
{
/* Ranged breakpoints have only one start location and one end
if (all_locations_are_pending (b, filter_pspace) && sals.empty ())
return;
- existing_locations = hoist_existing_locations (b, filter_pspace);
+ bp_location_list existing_locations = b->steal_locations (filter_pspace);
for (const auto &sal : sals)
{
/* If possible, carry over 'disable' status from existing
breakpoints. */
{
- struct bp_location *e = existing_locations;
/* If there are multiple breakpoints with the same function name,
e.g. for inline functions, comparing function names won't work.
Instead compare pc addresses; this is just a heuristic as things
may have moved, but in practice it gives the correct answer
often enough until a better solution is found. */
- int have_ambiguous_names = ambiguous_names_p (b->loc);
+ int have_ambiguous_names = ambiguous_names_p (b->locations ());
- for (; e; e = e->next)
+ for (const bp_location &e : existing_locations)
{
- if ((!e->enabled || e->disabled_by_cond) && e->function_name)
+ if ((!e.enabled || e.disabled_by_cond) && e.function_name)
{
if (have_ambiguous_names)
{
- for (bp_location *l : b->locations ())
+ for (bp_location &l : b->locations ())
{
/* Ignore software vs hardware location type at
this point, because with "set breakpoint
As mentioned above, this is an heuristic and in
practice should give the correct answer often
enough. */
- if (breakpoint_locations_match (e, l, true))
+ if (breakpoint_locations_match (&e, &l, true))
{
- l->enabled = e->enabled;
- l->disabled_by_cond = e->disabled_by_cond;
+ l.enabled = e.enabled;
+ l.disabled_by_cond = e.disabled_by_cond;
break;
}
}
}
else
{
- for (bp_location *l : b->locations ())
- if (l->function_name
- && strcmp (e->function_name.get (),
- l->function_name.get ()) == 0)
+ for (bp_location &l : b->locations ())
+ if (l.function_name
+ && strcmp (e.function_name.get (),
+ l.function_name.get ()) == 0)
{
- l->enabled = e->enabled;
- l->disabled_by_cond = e->disabled_by_cond;
+ l.enabled = e.enabled;
+ l.disabled_by_cond = e.disabled_by_cond;
break;
}
}
}
}
- if (!locations_are_equal (existing_locations, b->loc))
- gdb::observers::breakpoint_modified.notify (b);
+ if (!locations_are_equal (existing_locations, b->locations ()))
+ notify_breakpoint_modified (b);
}
/* Find the SaL locations corresponding to the given LOCSPEC.
errors. */
if (e.error == NOT_FOUND_ERROR
&& (condition_not_parsed
- || (loc != NULL
+ || (this->has_locations ()
&& search_pspace != NULL
- && loc->pspace != search_pspace)
- || (loc && loc->shlib_disabled)
- || (loc && loc->pspace->executing_startup)
+ && this->first_loc ().pspace != search_pspace)
+ || (this->has_locations () && this->first_loc ().shlib_disabled)
+ || (this->has_locations ()
+ && this->first_loc ().pspace->executing_startup)
|| enable_state == bp_disabled))
not_found_and_ok = true;
if (condition_not_parsed && extra_string != NULL)
{
gdb::unique_xmalloc_ptr<char> local_cond, local_extra;
- int local_thread, local_task;
+ int local_thread, local_task, local_inferior;
find_condition_and_thread_for_sals (sals, extra_string.get (),
&local_cond, &local_thread,
+ &local_inferior,
&local_task, &local_extra);
gdb_assert (cond_string == nullptr);
if (local_cond != nullptr)
breakpoint 1, we'd insert the locations of breakpoint 2, which
hadn't been re-set yet, and thus may have stale locations. */
- for (breakpoint *b : all_breakpoints_safe ())
+ for (breakpoint &b : all_breakpoints_safe ())
{
try
{
- breakpoint_re_set_one (b);
+ breakpoint_re_set_one (&b);
}
catch (const gdb_exception &ex)
{
exception_fprintf (gdb_stderr, ex,
"Error in re-setting breakpoint %d: ",
- b->number);
+ b.number);
}
}
selected as current, and unless this was a vfork will have a
different program space from the original thread. Reset that
as well. */
- b->loc->pspace = current_program_space;
+ b->first_loc ().pspace = current_program_space;
}
}
if (count < 0)
count = 0;
- for (breakpoint *b : all_breakpoints ())
- if (b->number == bptnum)
+ for (breakpoint &b : all_breakpoints ())
+ if (b.number == bptnum)
{
- if (is_tracepoint (b))
+ if (is_tracepoint (&b))
{
if (from_tty && count != 0)
gdb_printf (_("Ignore count ignored for tracepoint %d."),
return;
}
- b->ignore_count = count;
+ b.ignore_count = count;
if (from_tty)
{
if (count == 0)
"crossings of breakpoint %d."),
count, bptnum);
}
- gdb::observers::breakpoint_modified.notify (b);
+ notify_breakpoint_modified (&b);
return;
}
{
bool match = false;
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->number == i)
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (b.number == i)
{
match = true;
- function (b);
+ function (&b);
break;
}
if (!match)
error (_("Bad breakpoint location number '%d'"), loc_num);
int n = 0;
- for (bp_location *loc : b->locations ())
+ for (bp_location &loc : b->locations ())
if (++n == loc_num)
- return loc;
+ return &loc;
error (_("Bad breakpoint location number '%d'"), loc_num);
}
}
update_global_location_list (UGLL_DONT_INSERT);
- gdb::observers::breakpoint_modified.notify (loc->owner);
+ notify_breakpoint_modified (loc->owner);
}
/* Calculates LOC_NUM for LOC by traversing the bp_location chain of LOC's
{
/* Locations use 1-based indexing. */
int loc_num = 1;
- for (bp_location *it : loc->owner->locations ())
+ for (bp_location &it : loc->owner->locations ())
{
- if (it == loc)
+ if (&it == loc)
return loc_num;
loc_num++;
}
target_disable_tracepoint (loc);
update_global_location_list (UGLL_DONT_INSERT);
- gdb::observers::breakpoint_modified.notify (loc->owner);
+ notify_breakpoint_modified (loc->owner);
}
/* Enable or disable a range of breakpoint locations. BP_NUM is the
if (target_supports_enable_disable_tracepoint ()
&& current_trace_status ()->running && is_tracepoint (bpt))
{
- for (bp_location *location : bpt->locations ())
- target_disable_tracepoint (location);
+ for (bp_location &location : bpt->locations ())
+ target_disable_tracepoint (&location);
}
update_global_location_list (UGLL_DONT_INSERT);
- gdb::observers::breakpoint_modified.notify (bpt);
+ notify_breakpoint_modified (bpt);
}
/* Enable or disable the breakpoint(s) or breakpoint location(s)
{
if (args == 0)
{
- for (breakpoint *bpt : all_breakpoints ())
- if (user_breakpoint_p (bpt))
+ for (breakpoint &bpt : all_breakpoints ())
+ if (user_breakpoint_p (&bpt))
{
if (enable)
- enable_breakpoint (bpt);
+ enable_breakpoint (&bpt);
else
- disable_breakpoint (bpt);
+ disable_breakpoint (&bpt);
}
}
else
bpt->enable_state = bp_enabled;
update_watchpoint (w, true /* reparse */);
}
- catch (const gdb_exception &e)
+ catch (const gdb_exception_error &e)
{
bpt->enable_state = orig_enable_state;
exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "),
if (target_supports_enable_disable_tracepoint ()
&& current_trace_status ()->running && is_tracepoint (bpt))
{
- for (bp_location *location : bpt->locations ())
- target_enable_tracepoint (location);
+ for (bp_location &location : bpt->locations ())
+ target_enable_tracepoint (&location);
}
bpt->disposition = disposition;
bpt->enable_count = count;
update_global_location_list (UGLL_MAY_INSERT);
- gdb::observers::breakpoint_modified.notify (bpt);
+ notify_breakpoint_modified (bpt);
}
CORE_ADDR addr, ssize_t len,
const bfd_byte *data)
{
- for (breakpoint *bp : all_breakpoints ())
- if (bp->enable_state == bp_enabled
- && bp->type == bp_hardware_watchpoint)
+ for (breakpoint &bp : all_breakpoints ())
+ if (bp.enable_state == bp_enabled
+ && bp.type == bp_hardware_watchpoint)
{
- struct watchpoint *wp = (struct watchpoint *) bp;
+ watchpoint &wp = gdb::checked_static_cast<watchpoint &> (bp);
- if (wp->val_valid && wp->val != nullptr)
+ if (wp.val_valid && wp.val != nullptr)
{
- for (bp_location *loc : bp->locations ())
- if (loc->loc_type == bp_loc_hardware_watchpoint
- && loc->address + loc->length > addr
- && addr + len > loc->address)
+ for (bp_location &loc : bp.locations ())
+ if (loc.loc_type == bp_loc_hardware_watchpoint
+ && loc.address + loc.length > addr
+ && addr + len > loc.address)
{
- wp->val = NULL;
- wp->val_valid = false;
+ wp.val = NULL;
+ wp.val_valid = false;
}
}
}
const address_space *aspace,
CORE_ADDR pc)
{
- for (bp_location *loc : bp->locations ())
- if (loc->inserted
- && breakpoint_location_address_match (loc, aspace, pc))
+ for (bp_location &loc : bp->locations ())
+ if (loc.inserted
+ && breakpoint_location_address_match (&loc, aspace, pc))
return 1;
return 0;
single_step_breakpoint_inserted_here_p (const address_space *aspace,
CORE_ADDR pc)
{
- for (breakpoint *bpt : all_breakpoints ())
+ for (breakpoint &bpt : all_breakpoints ())
{
- if (bpt->type == bp_single_step
- && breakpoint_has_location_inserted_here (bpt, aspace, pc))
+ if (bpt.type == bp_single_step
+ && breakpoint_has_location_inserted_here (&bpt, aspace, pc))
return 1;
}
return 0;
create_breakpoint (get_current_arch (),
locspec.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
+ NULL, -1, -1, arg, false, 1 /* parse arg */,
0 /* tempflag */,
bp_tracepoint /* type_wanted */,
0 /* Ignore count */,
current_language);
create_breakpoint (get_current_arch (),
locspec.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
+ NULL, -1, -1, arg, false, 1 /* parse arg */,
0 /* tempflag */,
bp_fast_tracepoint /* type_wanted */,
0 /* Ignore count */,
create_breakpoint (get_current_arch (),
locspec.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
+ NULL, -1, -1, arg, false, 1 /* parse arg */,
0 /* tempflag */,
type /* type_wanted */,
0 /* Ignore count */,
current_language);
if (!create_breakpoint (get_current_arch (),
locspec.get (),
- utp->cond_string.get (), -1, addr_str,
+ utp->cond_string.get (), -1, -1, addr_str,
false /* force_condition */,
0 /* parse cond/thread */,
0 /* tempflag */,
Do not delete internal or call-dummy breakpoints, these
have to be deleted with an explicit breakpoint number
argument. */
- for (breakpoint *tp : all_tracepoints ())
- if (is_tracepoint (tp) && user_breakpoint_p (tp))
+ for (breakpoint &tp : all_tracepoints ())
+ if (is_tracepoint (&tp) && user_breakpoint_p (&tp))
{
breaks_to_delete = 1;
break;
if (!from_tty
|| (breaks_to_delete && query (_("Delete all tracepoints? "))))
{
- for (breakpoint *b : all_breakpoints_safe ())
- if (is_tracepoint (b) && user_breakpoint_p (b))
- delete_breakpoint (b);
+ for (breakpoint &b : all_breakpoints_safe ())
+ if (is_tracepoint (&b) && user_breakpoint_p (&b))
+ delete_breakpoint (&b);
}
}
else
trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
{
tp->pass_count = count;
- gdb::observers::breakpoint_modified.notify (tp);
+ notify_breakpoint_modified (tp);
if (from_tty)
gdb_printf (_("Setting tracepoint %d's passcount to %d\n"),
tp->number, count);
static void
trace_pass_command (const char *args, int from_tty)
{
- struct tracepoint *t1;
ULONGEST count;
if (args == 0 || *args == 0)
if (*args)
error (_("Junk at end of arguments."));
- for (breakpoint *b : all_tracepoints ())
+ for (breakpoint &b : all_tracepoints ())
{
- t1 = (struct tracepoint *) b;
- trace_pass_set_count (t1, count, from_tty);
+ tracepoint &t1 = gdb::checked_static_cast<tracepoint &> (b);
+ trace_pass_set_count (&t1, count, from_tty);
}
}
else if (*args == '\0')
{
- t1 = get_tracepoint_by_number (&args, NULL);
+ tracepoint *t1 = get_tracepoint_by_number (&args, NULL);
if (t1)
trace_pass_set_count (t1, count, from_tty);
}
number_or_range_parser parser (args);
while (!parser.finished ())
{
- t1 = get_tracepoint_by_number (&args, &parser);
+ tracepoint *t1 = get_tracepoint_by_number (&args, &parser);
if (t1)
trace_pass_set_count (t1, count, from_tty);
}
struct tracepoint *
get_tracepoint (int num)
{
- for (breakpoint *t : all_tracepoints ())
- if (t->number == num)
- return (struct tracepoint *) t;
+ for (breakpoint &t : all_tracepoints ())
+ if (t.number == num)
+ return gdb::checked_static_cast<tracepoint *> (&t);
return NULL;
}
struct tracepoint *
get_tracepoint_by_number_on_target (int num)
{
- for (breakpoint *b : all_tracepoints ())
+ for (breakpoint &b : all_tracepoints ())
{
- struct tracepoint *t = (struct tracepoint *) b;
+ tracepoint &t = gdb::checked_static_cast<tracepoint &> (b);
- if (t->number_on_target == num)
- return t;
+ if (t.number_on_target == num)
+ return &t;
}
return NULL;
return NULL;
}
- for (breakpoint *t : all_tracepoints ())
- if (t->number == tpnum)
- return (struct tracepoint *) t;
+ for (breakpoint &t : all_tracepoints ())
+ if (t.number == tpnum)
+ return gdb::checked_static_cast<tracepoint *> (&t);
gdb_printf ("No tracepoint number %d.\n", tpnum);
return NULL;
breakpoint::print_recreate_thread (struct ui_file *fp) const
{
if (thread != -1)
- gdb_printf (fp, " thread %d", thread);
+ {
+ struct thread_info *thr = find_thread_global_id (thread);
+ gdb_printf (fp, " thread %s", print_full_thread_id (thr));
+ }
if (task != -1)
gdb_printf (fp, " task %d", task);
error (_("Argument required (file name in which to save)"));
/* See if we have anything to save. */
- for (breakpoint *tp : all_breakpoints ())
+ for (breakpoint &tp : all_breakpoints ())
{
/* Skip internal and momentary breakpoints. */
- if (!user_breakpoint_p (tp))
+ if (!user_breakpoint_p (&tp))
continue;
/* If we have a filter, only save the breakpoints it accepts. */
- if (filter && !filter (tp))
+ if (filter && !filter (&tp))
continue;
any = true;
- if (is_tracepoint (tp))
+ if (is_tracepoint (&tp))
{
extra_trace_bits = 1;
if (extra_trace_bits)
save_trace_state_variables (&fp);
- for (breakpoint *tp : all_breakpoints ())
+ for (breakpoint &tp : all_breakpoints ())
{
/* Skip internal and momentary breakpoints. */
- if (!user_breakpoint_p (tp))
+ if (!user_breakpoint_p (&tp))
continue;
/* If we have a filter, only save the breakpoints it accepts. */
- if (filter && !filter (tp))
+ if (filter && !filter (&tp))
continue;
- tp->print_recreate (&fp);
+ tp.print_recreate (&fp);
/* 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)
- fp.printf (" condition $bpnum %s\n", tp->cond_string.get ());
+ if (tp.cond_string)
+ fp.printf (" condition $bpnum %s\n", tp.cond_string.get ());
- if (tp->ignore_count)
- fp.printf (" ignore $bpnum %d\n", tp->ignore_count);
+ if (tp.ignore_count)
+ fp.printf (" ignore $bpnum %d\n", tp.ignore_count);
- if (tp->type != bp_dprintf && tp->commands)
+ if (tp.type != bp_dprintf && tp.commands)
{
fp.puts (" commands\n");
ui_out_redirect_pop redir (current_uiout, &fp);
- print_command_lines (current_uiout, tp->commands.get (), 2);
+ print_command_lines (current_uiout, tp.commands.get (), 2);
fp.puts (" end\n");
}
- if (tp->enable_state == bp_disabled)
+ if (tp.enable_state == bp_disabled)
fp.puts ("disable $bpnum\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)
+ if (!is_watchpoint (&tp) && tp.has_multiple_locations ())
{
int n = 1;
- for (bp_location *loc : tp->locations ())
+ for (bp_location &loc : tp.locations ())
{
- if (!loc->enabled)
+ if (!loc.enabled)
fp.printf ("disable $bpnum.%d\n", n);
n++;
pc_at_non_inline_function (const address_space *aspace, CORE_ADDR pc,
const target_waitstatus &ws)
{
- for (breakpoint *b : all_breakpoints ())
+ for (breakpoint &b : all_breakpoints ())
{
- if (!is_non_inline_function (b))
+ if (!is_non_inline_function (&b))
continue;
- for (bp_location *bl : b->locations ())
+ for (bp_location &bl : b.locations ())
{
- if (!bl->shlib_disabled
- && bpstat_check_location (bl, aspace, pc, ws))
+ if (!bl.shlib_disabled
+ && bpstat_check_location (&bl, aspace, pc, ws))
return 1;
}
}
gdb::observers::memory_changed.attach (invalidate_bp_value_on_memory_change,
"breakpoint");
- breakpoint_chain = 0;
/* Don't bother to call set_breakpoint_count. $bpnum isn't useful
before a breakpoint is set. */
breakpoint_count = 0;
&breakpoint_set_cmdlist,
&breakpoint_show_cmdlist);
+ add_setshow_boolean_cmd ("breakpoint", class_maintenance,
+ &debug_breakpoint, _("\
+Set breakpoint location debugging."), _("\
+Show breakpoint location debugging."), _("\
+When on, breakpoint location specific debugging is enabled."),
+ NULL,
+ show_debug_breakpoint,
+ &setdebuglist, &showdebuglist);
+
add_setshow_enum_cmd ("condition-evaluation", class_breakpoint,
condition_evaluation_enums,
&condition_evaluation_mode_1, _("\
"breakpoint");
gdb::observers::thread_exit.attach (remove_threaded_breakpoints,
"breakpoint");
+ gdb::observers::inferior_removed.attach (remove_inferior_breakpoints,
+ "breakpoint");
}