/* Data structures associated with breakpoints in GDB.
- Copyright (C) 1992-2019 Free Software Foundation, Inc.
+ Copyright (C) 1992-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame.h"
#include "value.h"
-#include "gdbsupport/vec.h"
#include "ax.h"
#include "command.h"
#include "gdbsupport/break-common.h"
#include "location.h"
#include <vector>
#include "gdbsupport/array-view.h"
+#include "gdbsupport/filtered-iterator.h"
+#include "gdbsupport/function-view.h"
+#include "gdbsupport/next-iterator.h"
+#include "gdbsupport/iterator-range.h"
+#include "gdbsupport/refcounted-object.h"
+#include "gdbsupport/safe-iterator.h"
#include "cli/cli-script.h"
struct block;
struct gdbscm_breakpoint_object;
struct number_or_range_parser;
struct thread_info;
-struct bpstats;
+struct bpstat;
struct bp_location;
struct linespec_result;
struct linespec_sals;
bp_loc_other /* Miscellaneous... */
};
-class bp_location
+class bp_location : public refcounted_object
{
public:
bp_location () = default;
/* Construct a bp_location with type TYPE. */
bp_location (breakpoint *owner, bp_loc_type type);
- virtual ~bp_location ();
+ virtual ~bp_location () = default;
/* Chain pointer to the next breakpoint location for
the same parent breakpoint. */
bp_location *next = NULL;
- /* The reference count. */
- int refc = 0;
-
/* Type of this breakpoint location. */
bp_loc_type loc_type {};
agent_expr_up cmd_bytecode;
/* Signals that breakpoint conditions and/or commands need to be
- re-synched with the target. This has no use other than
+ re-synced with the target. This has no use other than
target-side breakpoints. */
bool needs_update = false;
/* Is this particular location enabled. */
bool enabled = false;
- /* Nonzero if this breakpoint is now inserted. */
+ /* Is this particular location disabled because the condition
+ expression is invalid at this location. For a location to be
+ reported as enabled, the ENABLED field above has to be true *and*
+ the DISABLED_BY_COND field has to be false. */
+ bool disabled_by_cond = false;
+
+ /* True if this breakpoint is now inserted. */
bool inserted = false;
- /* Nonzero if this is a permanent breakpoint. There is a breakpoint
+ /* True if this is a permanent breakpoint. There is a breakpoint
instruction hard-wired into the target's code. Don't try to
write another breakpoint instruction on top of it, or restore its
value. Step over it using the architecture's
gdbarch_skip_permanent_breakpoint method. */
bool permanent = false;
- /* Nonzero if this is not the first breakpoint in the list
+ /* True if this is not the first breakpoint in the list
for the given address. location of tracepoint can _never_
be duplicated with other locations of tracepoints and other
kinds of breakpoints, because two locations at the same
with it. */
bound_probe probe {};
- char *function_name = NULL;
+ gdb::unique_xmalloc_ptr<char> function_name;
/* Details of the placed breakpoint, when inserted. */
bp_target_info target_info {};
const struct objfile *objfile = NULL;
};
+/* A policy class for bp_location reference counting. */
+struct bp_location_ref_policy
+{
+ static void incref (bp_location *loc)
+ {
+ loc->incref ();
+ }
+
+ static void decref (bp_location *loc)
+ {
+ gdb_assert (loc->refcount () > 0);
+ loc->decref ();
+ if (loc->refcount () == 0)
+ delete loc;
+ }
+};
+
+/* A gdb::ref_ptr that has been specialized for bp_location. */
+typedef gdb::ref_ptr<bp_location, bp_location_ref_policy>
+ bp_location_ref_ptr;
+
/* The possible return values for print_bpstat, print_it_normal,
print_it_done, print_it_noop. */
enum print_stop_action
int (*breakpoint_hit) (const struct bp_location *bl,
const address_space *aspace,
CORE_ADDR bp_addr,
- const struct target_waitstatus *ws);
+ const target_waitstatus &ws);
/* Check internal conditions of the breakpoint referred to by BS.
If we should not stop for this breakpoint, set BS->stop to 0. */
- void (*check_status) (struct bpstats *bs);
+ void (*check_status) (struct bpstat *bs);
/* Tell how many hardware resources (debug registers) are needed
for this breakpoint. If this function is not provided, then
/* The normal print routine for this breakpoint, called when we
hit it. */
- enum print_stop_action (*print_it) (struct bpstats *bs);
+ enum print_stop_action (*print_it) (struct bpstat *bs);
/* Display information about this breakpoint, for "info
breakpoints". */
`create_sals_from_location_default'.
This function is called inside `create_breakpoint'. */
- void (*create_sals_from_location) (const struct event_location *location,
+ void (*create_sals_from_location) (struct event_location *location,
struct linespec_result *canonical,
enum bptype type_wanted);
This function is called inside `location_to_sals'. */
std::vector<symtab_and_line> (*decode_location)
(struct breakpoint *b,
- const struct event_location *location,
+ struct event_location *location,
struct program_space *search_pspace);
/* Return true if this breakpoint explains a signal. See
/* Called after evaluating the breakpoint's condition,
and only if it evaluated true. */
- void (*after_condition_true) (struct bpstats *bs);
+ void (*after_condition_true) (struct bpstat *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
/* Some targets (e.g., embedded PowerPC) need two debug registers to set
a watchpoint over a memory region. If this flag is true, GDB will use
- only one register per watchpoint, thus assuming that all acesses that
+ only one register per watchpoint, thus assuming that all accesses that
modify a memory location happen at its starting address. */
extern bool target_exact_watchpoints;
+/* bp_location linked list range. */
+
+using bp_location_range = next_range<bp_location>;
+
/* Note that the ->silent field is not currently used by any commands
(though the code is in there if it was to be, and set_raw_breakpoint
does set it to 0). I implemented it because I thought it would be
struct breakpoint
{
- virtual ~breakpoint ();
+ virtual ~breakpoint () = default;
+
+ /* Return a range of this breakpoint's locations. */
+ bp_location_range locations ();
/* Methods associated with this breakpoint. */
const breakpoint_ops *ops = NULL;
int input_radix = 0;
/* String form of the breakpoint condition (malloc'd), or NULL if
there is no condition. */
- char *cond_string = NULL;
+ gdb::unique_xmalloc_ptr<char> cond_string;
/* String form of extra parameters, or NULL if there are none.
Malloc'd. */
- char *extra_string = NULL;
+ gdb::unique_xmalloc_ptr<char> extra_string;
/* Holds the address of the related watchpoint_scope breakpoint when
using watchpoints on local variables (might the concept of a
struct watchpoint : public breakpoint
{
- ~watchpoint () override;
-
/* String form of exp to use for displaying to the user (malloc'd),
or NULL if none. */
- char *exp_string;
+ gdb::unique_xmalloc_ptr<char> exp_string;
/* String form to use for reparsing of EXP (malloc'd) or NULL. */
- char *exp_string_reparse;
+ gdb::unique_xmalloc_ptr<char> exp_string_reparse;
/* The expression we are watching, or NULL if not a watchpoint. */
expression_up exp;
we do not know the value yet or the value was not readable. VAL
is never lazy. */
value_ref_ptr val;
- /* Nonzero if VAL is valid. If VAL_VALID is set but VAL is NULL,
+
+ /* True if VAL is valid. If VAL_VALID is set but VAL is NULL,
then an error occurred reading the value. */
- int val_valid;
+ bool val_valid;
/* When watching the location of a bitfield, contains the offset and size of
the bitfield. Otherwise contains 0. */
CORE_ADDR hw_wp_mask;
};
-/* Given a function FUNC (struct breakpoint *B, void *DATA) and
- USER_DATA, call FUNC for every known breakpoint passing USER_DATA
- as argument.
-
- If FUNC returns 1, the loop stops and the current
- 'struct breakpoint' being processed is returned. If FUNC returns
- zero, the loop continues.
-
- This function returns either a 'struct breakpoint' pointer or NULL.
- It was based on BFD's bfd_sections_find_if function. */
-
-extern struct breakpoint *breakpoint_find_if
- (int (*func) (struct breakpoint *b, void *d), void *user_data);
-
/* Return true if BPT is either a software breakpoint or a hardware
breakpoint. */
status"). This provides the ability to determine whether we have
stopped at a breakpoint, and what we should do about it. */
-typedef struct bpstats *bpstat;
-
/* Clears a chain of bpstat, freeing storage
of each. */
-extern void bpstat_clear (bpstat *);
+extern void bpstat_clear (bpstat **);
/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
is part of the bpstat is copied as well. */
-extern bpstat bpstat_copy (bpstat);
+extern bpstat *bpstat_copy (bpstat *);
/* Build the (raw) bpstat chain for the stop information given by ASPACE,
BP_ADDR, and WS. Returns the head of the bpstat chain. */
-extern bpstat build_bpstat_chain (const address_space *aspace,
+extern bpstat *build_bpstat_chain (const address_space *aspace,
CORE_ADDR bp_addr,
- const struct target_waitstatus *ws);
+ const target_waitstatus &ws);
/* Get a bpstat associated with having just stopped at address
BP_ADDR in thread PTID. STOP_CHAIN may be supplied as a previously
several reasons concurrently.)
Each element of the chain has valid next, breakpoint_at,
- commands, FIXME??? fields. */
+ commands, FIXME??? fields.
+
+ watchpoints_triggered must be called beforehand to set up each
+ watchpoint's watchpoint_triggered value.
-extern bpstat bpstat_stop_status (const address_space *aspace,
+*/
+
+extern bpstat *bpstat_stop_status (const address_space *aspace,
CORE_ADDR pc, thread_info *thread,
- const struct target_waitstatus *ws,
- bpstat stop_chain = NULL);
+ const target_waitstatus &ws,
+ bpstat *stop_chain = nullptr);
+
+/* Like bpstat_stop_status, but clears all watchpoints'
+ watchpoint_triggered flag. Unlike with bpstat_stop_status, there's
+ no need to call watchpoint_triggered beforehand. You'll typically
+ use this variant when handling a known-non-watchpoint event, like a
+ fork or exec event. */
+
+extern bpstat *bpstat_stop_status_nowatch (const address_space *aspace,
+ CORE_ADDR bp_addr,
+ thread_info *thread,
+ const target_waitstatus &ws);
\f
+
+
/* This bpstat_what stuff tells wait_for_inferior what to do with a
breakpoint (a challenging task).
};
/* Tell what to do about this bpstat. */
-struct bpstat_what bpstat_what (bpstat);
+struct bpstat_what bpstat_what (bpstat *);
/* Run breakpoint event callbacks associated with the breakpoints that
triggered. */
-extern void bpstat_run_callbacks (bpstat bs_head);
+extern void bpstat_run_callbacks (bpstat *bs_head);
/* Find the bpstat associated with a breakpoint. NULL otherwise. */
-bpstat bpstat_find_breakpoint (bpstat, struct breakpoint *);
+bpstat *bpstat_find_breakpoint (bpstat *, struct breakpoint *);
/* True if a signal that we got in target_wait() was due to
circumstances explained by the bpstat; the signal is therefore not
random. */
-extern bool bpstat_explains_signal (bpstat, enum gdb_signal);
+extern bool bpstat_explains_signal (bpstat *, enum gdb_signal);
/* True if this bpstat causes a stop. */
-extern bool bpstat_causes_stop (bpstat);
+extern bool bpstat_causes_stop (bpstat *);
/* True if we should step constantly (e.g. watchpoints on machines
without hardware support). This isn't related to a specific bpstat,
/* Print a message indicating what happened. Returns nonzero to
say that only the source line should be printed after this (zero
return means print the frame as well as the source line). */
-extern enum print_stop_action bpstat_print (bpstat, int);
+extern enum print_stop_action bpstat_print (bpstat *, int);
/* Put in *NUM the breakpoint number of the first breakpoint we are
stopped at. *BSP upon return is a bpstat which points to the
Return -1 if stopped at a breakpoint that has been deleted since
we set it.
Return 1 otherwise. */
-extern int bpstat_num (bpstat *, int *);
+extern int bpstat_num (bpstat **, int *);
/* Perform actions associated with the stopped inferior. Actually, we
just use this for breakpoint commands. Perhaps other actions will
print_it_done
};
-struct bpstats
+struct bpstat
{
- bpstats ();
- bpstats (struct bp_location *bl, bpstat **bs_link_pointer);
- ~bpstats ();
+ bpstat ();
+ bpstat (struct bp_location *bl, bpstat ***bs_link_pointer);
- bpstats (const bpstats &);
- bpstats &operator= (const bpstats &) = delete;
+ bpstat (const bpstat &);
+ bpstat &operator= (const bpstat &) = delete;
/* Linked list because there can be more than one breakpoint at
the same place, and a bpstat reflects the fact that all have
been hit. */
- bpstat next;
+ bpstat *next;
/* Location that caused the stop. Locations are refcounted, so
this will never be NULL. Note that this location may end up
What this means is that we should not (in most cases) follow
the `bpstat->bp_location->owner' link, but instead use the
`breakpoint_at' field below. */
- struct bp_location *bp_location_at;
+ bp_location_ref_ptr bp_location_at;
/* Breakpoint that caused the stop. This is nullified if the
breakpoint ends up being deleted. See comments on
/* Prototypes for breakpoint-related functions. */
-/* Return 1 if there's a program/permanent breakpoint planted in
- memory at ADDRESS, return 0 otherwise. */
-
-extern int program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address);
-
extern enum breakpoint_here breakpoint_here_p (const address_space *,
CORE_ADDR);
extern void breakpoint_init_inferior (enum inf_context);
-extern void breakpoint_auto_delete (bpstat);
-
-typedef void (*walk_bp_location_callback) (struct bp_location *, void *);
-
-extern void iterate_over_bp_locations (walk_bp_location_callback);
+extern void breakpoint_auto_delete (bpstat *);
/* Return the chain of command lines to execute when this breakpoint
is hit. */
extern void break_command (const char *, int);
-extern void hbreak_command_wrapper (const char *, int);
-extern void thbreak_command_wrapper (const char *, int);
-extern void rbreak_command_wrapper (const char *, int);
-extern void watch_command_wrapper (const char *, int, int);
-extern void awatch_command_wrapper (const char *, int, int);
-extern void rwatch_command_wrapper (const char *, int, int);
+extern void watch_command_wrapper (const char *, int, bool);
+extern void awatch_command_wrapper (const char *, int, bool);
+extern void rwatch_command_wrapper (const char *, int, bool);
extern void tbreak_command (const char *, int);
extern struct breakpoint_ops base_breakpoint_ops;
extern void
add_catch_command (const char *name, const char *docstring,
- cmd_const_sfunc_ftype *sfunc,
+ cmd_func_ftype *func,
completer_ftype *completer,
void *user_data_catch,
void *user_data_tcatch);
int enabled,
int from_tty);
+/* Initialize a new breakpoint of the bp_catchpoint kind. If TEMP
+ is true, then make the breakpoint temporary. If COND_STRING is
+ not NULL, then store it in the breakpoint. OPS, if not NULL, is
+ the breakpoint_ops structure associated to the catchpoint. */
+
extern void init_catchpoint (struct breakpoint *b,
- struct gdbarch *gdbarch, int tempflag,
+ struct gdbarch *gdbarch, bool temp,
const char *cond_string,
const struct breakpoint_ops *ops);
extern void install_breakpoint (int internal, std::unique_ptr<breakpoint> &&b,
int update_gll);
+/* Returns the breakpoint ops appropriate for use with with LOCATION and
+ according to IS_TRACEPOINT. Use this to ensure, for example, that you pass
+ the correct ops to create_breakpoint for probe locations. If LOCATION is
+ NULL, returns bkpt_breakpoint_ops (or tracepoint_breakpoint_ops, if
+ IS_TRACEPOINT is true). */
+
+extern const struct breakpoint_ops *breakpoint_ops_for_event_location
+ (const struct event_location *location, bool is_tracepoint);
+
/* Flags that can be passed down to create_breakpoint, etc., to affect
breakpoint creation in several ways. */
the condition, thread, and extra string from EXTRA_STRING, ignoring
the similarly named parameters.
+ If FORCE_CONDITION is true, the condition is accepted even when it is
+ invalid at all of the locations. However, if PARSE_EXTRA is non-zero,
+ the FORCE_CONDITION parameter is ignored and the corresponding argument
+ is parsed from EXTRA_STRING.
+
If INTERNAL is non-zero, the breakpoint number will be allocated
from the internal breakpoint count.
Returns true if any breakpoint was created; false otherwise. */
extern int create_breakpoint (struct gdbarch *gdbarch,
- const struct event_location *location,
+ struct event_location *location,
const char *cond_string, int thread,
const char *extra_string,
+ bool force_condition,
int parse_extra,
int tempflag, enum bptype wanted_type,
int ignore_count,
extern void mark_breakpoints_out (void);
extern struct breakpoint *create_jit_event_breakpoint (struct gdbarch *,
- CORE_ADDR);
+ CORE_ADDR);
extern struct breakpoint *create_solib_event_breakpoint (struct gdbarch *,
CORE_ADDR);
extern bool is_catchpoint (struct breakpoint *b);
/* Shared helper function (MI and CLI) for creating and installing
- a shared object event catchpoint. */
-extern void add_solib_catchpoint (const char *arg, int is_load, int is_temp,
- int enabled);
+ a shared object event catchpoint. If IS_LOAD is true then
+ the events to be caught are load events, otherwise they are
+ unload events. If IS_TEMP is true the catchpoint is a
+ temporary one. If ENABLED is true the catchpoint is
+ created in an enabled state. */
+
+extern void add_solib_catchpoint (const char *arg, bool is_load, bool is_temp,
+ bool enabled);
/* Create and insert a new software single step breakpoint for the
current thread. May be called multiple times; each time will add a
otherwise, return false. */
extern int insert_single_step_breakpoints (struct gdbarch *);
-/* Check if any hardware watchpoints have triggered, according to the
- target. */
-int watchpoints_triggered (struct target_waitstatus *);
+/* Check whether any hardware watchpoints have triggered or not,
+ according to the target, and record it in each watchpoint's
+ 'watchpoint_triggered' field. */
+int watchpoints_triggered (const target_waitstatus &);
/* Helper for transparent breakpoint hiding for memory read and write
routines.
in our opinion won't ever trigger. */
extern void breakpoint_retire_moribund (void);
-/* Set break condition of breakpoint B to EXP. */
+/* Set break condition of breakpoint B to EXP.
+ If FORCE, define the condition even if it is invalid in
+ all of the breakpoint locations. */
extern void set_breakpoint_condition (struct breakpoint *b, const char *exp,
- int from_tty);
+ int from_tty, bool force);
+
+/* Set break condition for the breakpoint with number BPNUM to EXP.
+ Raise an error if no breakpoint with the given number is found.
+ Also raise an error if the breakpoint already has stop conditions.
+ If FORCE, define the condition even if it is invalid in
+ all of the breakpoint locations. */
+extern void set_breakpoint_condition (int bpnum, const char *exp,
+ int from_tty, bool force);
/* Checks if we are catching syscalls or not.
Returns 0 if not, greater than 0 if we are. */
/* Checks if we are catching syscalls with the specific
syscall_number. Used for "filtering" the catchpoints.
- Returns 0 if not, greater than 0 if we are. */
-extern int catching_syscall_number (int syscall_number);
+ Returns false if not, true if we are. */
+extern bool catching_syscall_number (int syscall_number);
/* Return a tracepoint with the given number if found. */
extern struct tracepoint *get_tracepoint (int num);
get_tracepoint_by_number (const char **arg,
number_or_range_parser *parser);
-/* Return a vector of all tracepoints currently defined. */
-extern std::vector<breakpoint *> all_tracepoints (void);
-
/* Return true if B is of tracepoint kind. */
extern bool is_tracepoint (const struct breakpoint *b);
DISABLE_COPY_AND_ASSIGN (scoped_rbreak_breakpoints);
};
-/* Breakpoint iterator function.
+/* Breakpoint linked list iterator. */
+
+using breakpoint_iterator = next_iterator<breakpoint>;
+
+/* Breakpoint linked list range. */
+
+using breakpoint_range = iterator_range<breakpoint_iterator>;
+
+/* Return a range to iterate over all breakpoints. */
+
+breakpoint_range all_breakpoints ();
+
+/* Breakpoint linked list range, safe against deletion of the current
+ breakpoint while iterating. */
+
+using breakpoint_safe_range = basic_safe_range<breakpoint_range>;
+
+/* Return a range to iterate over all breakpoints. This range is safe against
+ deletion of the current breakpoint while iterating. */
+
+breakpoint_safe_range all_breakpoints_safe ();
+
+/* Breakpoint filter to only keep tracepoints. */
+
+struct tracepoint_filter
+{
+ bool operator() (breakpoint *b)
+ { return is_tracepoint (b); }
+};
+
+/* Breakpoint linked list iterator, filtering to only keep tracepoints. */
+
+using tracepoint_iterator
+ = filtered_iterator<breakpoint_iterator, tracepoint_filter>;
+
+/* Breakpoint linked list range, filtering to only keep tracepoints. */
+
+using tracepoint_range = iterator_range<tracepoint_iterator>;
+
+/* Return a range to iterate over all tracepoints. */
+
+tracepoint_range all_tracepoints ();
+
+/* Return a range to iterate over all breakpoint locations. */
- Calls a callback function once for each breakpoint, so long as the
- callback function returns false. If the callback function returns
- true, the iteration will end and the current breakpoint will be
- returned. This can be useful for implementing a search for a
- breakpoint with arbitrary attributes, or for applying an operation
- to every breakpoint. */
-extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
- void *), void *);
+const std::vector<bp_location *> &all_bp_locations ();
/* Nonzero if the specified PC cannot be a location where functions
have been inlined. */
extern int pc_at_non_inline_function (const address_space *aspace,
CORE_ADDR pc,
- const struct target_waitstatus *ws);
+ const target_waitstatus &ws);
extern int user_breakpoint_p (struct breakpoint *);