blob: 286035425a67ee4052193b736b416e7af2cb15e2 [file] [log] [blame]
<
/* Everything about breakpoints, for GDB.
Copyright (C) 1986-2024 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "arch-utils.h"
#include <ctype.h>
#include "event-top.h"
#include "exceptions.h"
#include "hashtab.h"
#include "symtab.h"
#include "frame.h"
#include "breakpoint.h"
#include "tracepoint.h"
#include "gdbtypes.h"
#include "expression.h"
#include "gdbcore.h"
#include "cli/cli-cmds.h"
#include "value.h"
#include "command.h"
#include "inferior.h"
#include "infrun.h"
#include "gdbthread.h"
#include "target.h"
#include "language.h"
#include "gdb-demangle.h"
#include "filenames.h"
#include "annotate.h"
#include "symfile.h"
#include "objfiles.h"
#include "source.h"
#include "linespec.h"
#include "completer.h"
#include "ui-out.h"
#include "cli/cli-script.h"
#include "block.h"
#include "solib.h"
#include "solist.h"
#include "observable.h"
#include "memattr.h"
#include "ada-lang.h"
#include "top.h"
#include "ui.h"
#include "valprint.h"
#include "jit.h"
#include "parser-defs.h"
#include "probe.h"
#include "cli/cli-utils.h"
#include "stack.h"
#include "ax-gdb.h"
#include "dummy-frame.h"
#include "interps.h"
#include "gdbsupport/format.h"
#include "thread-fsm.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"
/* readline defines this. */
#undef savestring
#include "mi/mi-common.h"
#include "extension.h"
#include <algorithm>
#include "progspace-and-thread.h"
#include "gdbsupport/array-view.h"
#include <optional>
#include "gdbsupport/common-utils.h"
/* Prototypes for local functions. */
static void map_breakpoint_numbers (const char *,
gdb::function_view<void (breakpoint *)>);
static void
create_sals_from_location_spec_default (location_spec *locspec,
linespec_result *canonical);
static void create_breakpoints_sal (struct gdbarch *,
struct linespec_result *,
gdb::unique_xmalloc_ptr<char>,
gdb::unique_xmalloc_ptr<char>,
enum bptype,
enum bpdisp, int, int, int,
int,
int, int, int, unsigned);
static int can_use_hardware_watchpoint
(const std::vector<value_ref_ptr> &vals);
static void mention (const breakpoint *);
static breakpoint *add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b);
static breakpoint *add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b);
static struct breakpoint *
momentary_breakpoint_from_master (struct breakpoint *orig,
enum bptype type,
int loc_enabled, int thread);
static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, bool);
static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch,
CORE_ADDR bpaddr,
enum bptype bptype,
struct program_space *pspace);
static bool watchpoint_locations_match (const struct bp_location *loc1,
const struct bp_location *loc2);
static bool breakpoint_locations_match (const struct bp_location *loc1,
const struct bp_location *loc2,
bool sw_hw_bps_match = false);
static bool breakpoint_location_address_match (struct bp_location *bl,
const struct address_space *aspace,
CORE_ADDR addr);
static bool breakpoint_location_address_range_overlap (struct bp_location *,
const address_space *,
CORE_ADDR, int);
static int remove_breakpoint (struct bp_location *);
static int remove_breakpoint_1 (struct bp_location *, enum remove_bp_reason);
static enum print_stop_action print_bp_stop_message (bpstat *bs);
static int hw_breakpoint_used_count (void);
static int hw_watchpoint_use_count (struct breakpoint *);
static int hw_watchpoint_used_count_others (struct breakpoint *except,
enum bptype type,
int *other_type_used);
static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp,
int count);
static void decref_bp_location (struct bp_location **loc);
static std::vector<symtab_and_line> bkpt_probe_decode_location_spec
(struct breakpoint *b,
location_spec *locspec,
struct program_space *search_pspace);
static bool bl_address_is_meaningful (bp_location *loc);
static int find_loc_num_by_location (const bp_location *loc);
/* update_global_location_list's modes of operation wrt to whether to
insert locations now. */
enum ugll_insert_mode
{
/* Don't insert any breakpoint locations into the inferior, only
remove already-inserted locations that no longer should be
inserted. Functions that delete a breakpoint or breakpoints
should specify this mode, so that deleting a breakpoint doesn't
have the side effect of inserting the locations of other
breakpoints that are marked not-inserted, but should_be_inserted
returns true on them.
This behavior is useful is situations close to tear-down -- e.g.,
after an exec, while the target still has execution, but
breakpoint shadows of the previous executable image should *NOT*
be restored to the new image; or before detaching, where the
target still has execution and wants to delete breakpoints from
GDB's lists, and all breakpoints had already been removed from
the inferior. */
UGLL_DONT_INSERT,
/* May insert breakpoints iff breakpoints_should_be_inserted_now
claims breakpoints should be inserted now. */
UGLL_MAY_INSERT,
/* Insert locations now, irrespective of
breakpoints_should_be_inserted_now. E.g., say all threads are
stopped right now, and the user did "continue". We need to
insert breakpoints _before_ resuming the target, but
UGLL_MAY_INSERT wouldn't insert them, because
breakpoints_should_be_inserted_now returns false at that point,
as no thread is running yet. */
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);
static void insert_breakpoint_locations (void);
static void trace_pass_command (const char *, int);
static void set_tracepoint_count (int num);
static bool is_masked_watchpoint (const struct breakpoint *b);
/* Return true if B refers to a static tracepoint set by marker ("-m"),
zero otherwise. */
static bool strace_marker_p (struct breakpoint *b);
static void bkpt_probe_create_sals_from_location_spec
(location_spec *locspec,
struct linespec_result *canonical);
const struct breakpoint_ops code_breakpoint_ops =
{
create_sals_from_location_spec_default,
create_breakpoints_sal,
};
/* Breakpoints set on probes. */
static const struct breakpoint_ops bkpt_probe_breakpoint_ops =
{
bkpt_probe_create_sals_from_location_spec,
create_breakpoints_sal,
};
/* Tracepoints set on probes. We use the same methods as for breakpoints
on probes. */
static const struct breakpoint_ops tracepoint_probe_breakpoint_ops =
{
bkpt_probe_create_sals_from_location_spec,
create_breakpoints_sal,
};
/* Implementation of abstract dtors. These must exist to satisfy the
linker. */
breakpoint::~breakpoint ()
{
}
code_breakpoint::~code_breakpoint ()
{
}
catchpoint::~catchpoint ()
{
}
/* The structure to be used in regular breakpoints. */
struct ordinary_breakpoint : public code_breakpoint
{
using code_breakpoint::code_breakpoint;
int resources_needed (const struct bp_location *) override;
enum print_stop_action print_it (const bpstat *bs) const override;
void print_mention () const override;
void print_recreate (struct ui_file *fp) const override;
};
/* Internal breakpoints. These typically have a lifetime the same as
the program, and they end up installed on the breakpoint chain with
a negative breakpoint number. They're visible in "maint info
breakpoints", but not "info breakpoints". */
struct internal_breakpoint : public code_breakpoint
{
internal_breakpoint (struct gdbarch *gdbarch,
enum bptype type, CORE_ADDR address)
: code_breakpoint (gdbarch, type)
{
symtab_and_line sal;
sal.pc = address;
sal.section = find_pc_overlay (sal.pc);
sal.pspace = current_program_space;
add_location (sal);
pspace = current_program_space;
disposition = disp_donttouch;
}
void re_set () override;
void check_status (struct bpstat *bs) override;
enum print_stop_action print_it (const bpstat *bs) const override;
void print_mention () const override;
};
/* Momentary breakpoints. These typically have a lifetime of some run
control command only, are always thread-specific, and have 0 for
breakpoint number. I.e., there can be many momentary breakpoints
on the breakpoint chain and they all same the same number (zero).
They're visible in "maint info breakpoints", but not "info
breakpoints". */
struct momentary_breakpoint : public code_breakpoint
{
momentary_breakpoint (struct gdbarch *gdbarch_, enum bptype bptype,
program_space *pspace_,
const struct frame_id &frame_id_,
int thread_)
: code_breakpoint (gdbarch_, bptype)
{
/* If FRAME_ID is valid, it should be a real frame, not an inlined
or tail-called one. */
gdb_assert (!frame_id_artificial_p (frame_id));
/* Momentary breakpoints are always thread-specific. */
gdb_assert (thread_ > 0);
pspace = pspace_;
enable_state = bp_enabled;
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;
void check_status (struct bpstat *bs) override;
enum print_stop_action print_it (const bpstat *bs) const override;
void print_mention () const override;
};
/* DPrintf breakpoints. */
struct dprintf_breakpoint : public ordinary_breakpoint
{
using ordinary_breakpoint::ordinary_breakpoint;
void re_set () override;
int breakpoint_hit (const struct bp_location *bl,
const address_space *aspace,
CORE_ADDR bp_addr,
const target_waitstatus &ws) override;
void print_recreate (struct ui_file *fp) const override;
void after_condition_true (struct bpstat *bs) override;
};
/* Ranged breakpoints. */
struct ranged_breakpoint : public ordinary_breakpoint
{
explicit ranged_breakpoint (struct gdbarch *gdbarch,
const symtab_and_line &sal_start,
int length,
location_spec_up start_locspec,
location_spec_up end_locspec)
: ordinary_breakpoint (gdbarch, bp_hardware_breakpoint)
{
bp_location *bl = add_location (sal_start);
bl->length = length;
disposition = disp_donttouch;
locspec = std::move (start_locspec);
locspec_range_end = std::move (end_locspec);
}
int breakpoint_hit (const struct bp_location *bl,
const address_space *aspace,
CORE_ADDR bp_addr,
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 (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;
};
/* Static tracepoints with marker (`-m'). */
struct static_marker_tracepoint : public tracepoint
{
using tracepoint::tracepoint;
std::vector<symtab_and_line> decode_location_spec
(struct location_spec *locspec,
struct program_space *search_pspace) override;
};
/* The style in which to perform a dynamic printf. This is a user
option because different output options have different tradeoffs;
if GDB does the printing, there is better error handling if there
is a problem with any of the arguments, but using an inferior
function lets you have special-purpose printers and sending of
output to the same place as compiled-in print functions. */
static const char dprintf_style_gdb[] = "gdb";
static const char dprintf_style_call[] = "call";
static const char dprintf_style_agent[] = "agent";
static const char *const dprintf_style_enums[] = {
dprintf_style_gdb,
dprintf_style_call,
dprintf_style_agent,
NULL
};
static const char *dprintf_style = dprintf_style_gdb;
/* The function to use for dynamic printf if the preferred style is to
call into the inferior. The value is simply a string that is
copied into the command, so it can be anything that GDB can
evaluate to a callable address, not necessarily a function name. */
static std::string dprintf_function = "printf";
/* The channel to use for dynamic printf if the preferred style is to
call into the inferior; if a nonempty string, it will be passed to
the call as the first argument, with the format string as the
second. As with the dprintf function, this can be anything that
GDB knows how to evaluate, so in addition to common choices like
"stderr", this could be an app-specific expression like
"mystreams[curlogger]". */
static std::string dprintf_channel;
/* True if dprintf commands should continue to operate even if GDB
has disconnected. */
static bool disconnected_dprintf = true;
struct command_line *
breakpoint_commands (struct breakpoint *b)
{
return b->commands ? b->commands.get () : NULL;
}
/* Flag indicating that a command has proceeded the inferior past the
current breakpoint. */
static bool breakpoint_proceeded;
const char *
bpdisp_text (enum bpdisp disp)
{
/* NOTE: the following values are a part of MI protocol and
represent values of 'disp' field returned when inferior stops at
a breakpoint. */
static const char * const bpdisps[] = {"del", "dstp", "dis", "keep"};
return bpdisps[(int) disp];
}
/* Prototypes for exported functions. */
/* If FALSE, gdb will not use hardware support for watchpoints, even
if such is available. */
static int can_use_hw_watchpoints;
static void
show_can_use_hw_watchpoints (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
gdb_printf (file,
_("Debugger's willingness to use "
"watchpoint hardware is %s.\n"),
value);
}
/* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints
for unrecognized breakpoint locations.
If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */
static enum auto_boolean pending_break_support;
static void
show_pending_break_support (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
gdb_printf (file,
_("Debugger's behavior regarding "
"pending breakpoints is %s.\n"),
value);
}
/* If true, gdb will automatically use hardware breakpoints for breakpoints
set with "break" but falling in read-only memory.
If false, gdb will warn about such breakpoints, but won't automatically
use hardware breakpoints. */
static bool automatic_hardware_breakpoints;
static void
show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
gdb_printf (file,
_("Automatic usage of hardware breakpoints is %s.\n"),
value);
}
/* If on, GDB keeps breakpoints inserted even if the inferior is
stopped, and immediately inserts any new breakpoints as soon as
they're created. If off (default), GDB keeps breakpoints off of
the target as long as possible. That is, it delays inserting
breakpoints until the next resume, and removes them again when the
target fully stops. This is a bit safer in case GDB crashes while
processing user input. */
static bool always_inserted_mode = false;
static void
show_always_inserted_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
gdb_printf (file, _("Always inserted breakpoint mode is %s.\n"),
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
breakpoints_should_be_inserted_now (void)
{
if (gdbarch_has_global_breakpoints (current_inferior ()->arch ()))
{
/* If breakpoints are global, they should be inserted even if no
thread under gdb's control is running, or even if there are
no threads under GDB's control yet. */
return 1;
}
else
{
if (always_inserted_mode)
{
/* The user wants breakpoints inserted even if all threads
are stopped. */
return 1;
}
for (inferior *inf : all_inferiors ())
if (inf->has_execution ()
&& threads_are_executing (inf->process_target ()))
return 1;
/* Don't remove breakpoints yet if, even though all threads are
stopped, we still have events to process. */
for (thread_info *tp : all_non_exited_threads ())
if (tp->resumed () && tp->has_pending_waitstatus ())
return 1;
}
return 0;
}
static const char condition_evaluation_both[] = "host or target";
/* Modes for breakpoint condition evaluation. */
static const char condition_evaluation_auto[] = "auto";
static const char condition_evaluation_host[] = "host";
static const char condition_evaluation_target[] = "target";
static const char *const condition_evaluation_enums[] = {
condition_evaluation_auto,
condition_evaluation_host,
condition_evaluation_target,
NULL
};
/* Global that holds the current mode for breakpoint condition evaluation. */
static const char *condition_evaluation_mode_1 = condition_evaluation_auto;
/* Global that we use to display information to the user (gets its value from
condition_evaluation_mode_1. */
static const char *condition_evaluation_mode = condition_evaluation_auto;
/* Translate a condition evaluation mode MODE into either "host"
or "target". This is used mostly to translate from "auto" to the
real setting that is being used. It returns the translated
evaluation mode. */
static const char *
translate_condition_evaluation_mode (const char *mode)
{
if (mode == condition_evaluation_auto)
{
if (target_supports_evaluation_of_breakpoint_conditions ())
return condition_evaluation_target;
else
return condition_evaluation_host;
}
else
return mode;
}
/* Discovers what condition_evaluation_auto translates to. */
static const char *
breakpoint_condition_evaluation_mode (void)
{
return translate_condition_evaluation_mode (condition_evaluation_mode);
}
/* Return true if GDB should evaluate breakpoint conditions or false
otherwise. */
static bool
gdb_evaluates_breakpoint_condition_p (void)
{
const char *mode = breakpoint_condition_evaluation_mode ();
return (mode == condition_evaluation_host);
}
/* Are we executing breakpoint commands? */
static int executing_breakpoint_commands;
/* Are overlay event breakpoints enabled? */
static int overlay_events_enabled;
/* See description in breakpoint.h. */
bool target_exact_watchpoints = false;
/* Chains of all breakpoints defined. */
static intrusive_list<breakpoint> breakpoint_chain;
/* See breakpoint.h. */
breakpoint_range
all_breakpoints ()
{
return breakpoint_range (breakpoint_chain.begin (), breakpoint_chain.end ());
}
/* See breakpoint.h. */
breakpoint_safe_range
all_breakpoints_safe ()
{
return breakpoint_safe_range (all_breakpoints ());
}
/* See breakpoint.h. */
tracepoint_range
all_tracepoints ()
{
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. */
static std::vector<bp_location *> bp_locations;
/* See breakpoint.h. */
const std::vector<bp_location *> &
all_bp_locations ()
{
return bp_locations;
}
/* Range to iterate over breakpoint locations at a given address. */
struct bp_locations_at_addr_range
{
using iterator = std::vector<bp_location *>::iterator;
bp_locations_at_addr_range (CORE_ADDR addr)
{
struct compare
{
bool operator() (const bp_location *loc, CORE_ADDR addr_) const
{ return loc->address < addr_; }
bool operator() (CORE_ADDR addr_, const bp_location *loc) const
{ return addr_ < loc->address; }
};
auto it_pair = std::equal_range (bp_locations.begin (), bp_locations.end (),
addr, compare ());
m_begin = it_pair.first;
m_end = it_pair.second;
}
iterator begin () const
{ return m_begin; }
iterator end () const
{ return m_end; }
private:
iterator m_begin;
iterator m_end;
};
/* Return a range to iterate over all breakpoint locations exactly at address
ADDR.
If it's needed to iterate multiple times on the same range, it's possible
to save the range in a local variable and use it multiple times:
auto range = all_bp_locations_at_addr (addr);
for (bp_location *loc : range)
// use loc
for (bp_location *loc : range)
// use loc
This saves a bit of time, as it avoids re-doing the binary searches to find
the range's boundaries. Just remember not to change the bp_locations vector
in the mean time, as it could make the range's iterators stale. */
static bp_locations_at_addr_range
all_bp_locations_at_addr (CORE_ADDR addr)
{
return bp_locations_at_addr_range (addr);
}
/* Maximum alignment offset between bp_target_info.PLACED_ADDRESS and
ADDRESS for the current elements of BP_LOCATIONS which get a valid
result from bp_location_has_shadow. You can use it for roughly
limiting the subrange of BP_LOCATIONS to scan for shadow bytes for
an address you need to read. */
static CORE_ADDR bp_locations_placed_address_before_address_max;
/* Maximum offset plus alignment between bp_target_info.PLACED_ADDRESS
+ bp_target_info.SHADOW_LEN and ADDRESS for the current elements of
BP_LOCATIONS which get a valid result from bp_location_has_shadow.
You can use it for roughly limiting the subrange of BP_LOCATIONS to
scan for shadow bytes for an address you need to read. */
static CORE_ADDR bp_locations_shadow_len_after_address_max;
/* The locations that no longer correspond to any breakpoint, unlinked
from the bp_locations array, but for which a hit may still be
reported by a target. */
static std::vector<bp_location *> moribund_locations;
/* Number of last breakpoint made. */
static int breakpoint_count;
/* The value of `breakpoint_count' before the last command that
created breakpoints. If the last (break-like) command created more
than one breakpoint, then the difference between BREAKPOINT_COUNT
and PREV_BREAKPOINT_COUNT is more than one. */
static int prev_breakpoint_count;
/* Number of last tracepoint made. */
static int tracepoint_count;
static struct cmd_list_element *breakpoint_set_cmdlist;
static struct cmd_list_element *breakpoint_show_cmdlist;
struct cmd_list_element *save_cmdlist;
/* Return whether a breakpoint is an active enabled breakpoint. */
static bool
breakpoint_enabled (struct breakpoint *b)
{
return (b->enable_state == bp_enabled);
}
/* Set breakpoint count to NUM. */
static void
set_breakpoint_count (int num)
{
prev_breakpoint_count = breakpoint_count;
breakpoint_count = num;
set_internalvar_integer (lookup_internalvar ("bpnum"), num);
}
/* Used by `start_rbreak_breakpoints' below, to record the current
breakpoint count before "rbreak" creates any breakpoint. */
static int rbreak_start_breakpoint_count;
/* Called at the start an "rbreak" command to record the first
breakpoint made. */
scoped_rbreak_breakpoints::scoped_rbreak_breakpoints ()
{
rbreak_start_breakpoint_count = breakpoint_count;
}
/* Called at the end of an "rbreak" command to record the last
breakpoint made. */
scoped_rbreak_breakpoints::~scoped_rbreak_breakpoints ()
{
prev_breakpoint_count = rbreak_start_breakpoint_count;
}
/* Used in run_command to zero the hit count when a new run starts. */
void
clear_breakpoint_hit_counts (void)
{
for (breakpoint &b : all_breakpoints ())
b.hit_count = 0;
}
/* Return the breakpoint with the specified number, or NULL
if the number does not refer to an existing breakpoint. */
struct breakpoint *
get_breakpoint (int num)
{
for (breakpoint &b : all_breakpoints ())
if (b.number == num)
return &b;
return nullptr;
}
/* Return TRUE if NUM refer to an existing breakpoint that has
multiple code locations. */
static bool
has_multiple_locations (int num)
{
for (breakpoint &b : all_breakpoints ())
if (b.number == num)
return b.has_multiple_locations ();
return false;
}
/* Mark locations as "conditions have changed" in case the target supports
evaluating conditions on its side. */
static void
mark_breakpoint_modified (struct breakpoint *b)
{
/* This is only meaningful if the target is
evaluating conditions and if the user has
opted for condition evaluation on the target's
side. */
if (gdb_evaluates_breakpoint_condition_p ()
|| !target_supports_evaluation_of_breakpoint_conditions ())
return;
if (!is_breakpoint (b))
return;
for (bp_location &loc : b->locations ())
loc.condition_changed = condition_modified;
}
/* Mark location as "conditions have changed" in case the target supports
evaluating conditions on its side. */
static void
mark_breakpoint_location_modified (struct bp_location *loc)
{
/* This is only meaningful if the target is
evaluating conditions and if the user has
opted for condition evaluation on the target's
side. */
if (gdb_evaluates_breakpoint_condition_p ()
|| !target_supports_evaluation_of_breakpoint_conditions ())
return;
if (!is_breakpoint (loc->owner))
return;
loc->condition_changed = condition_modified;
}
/* Sets the condition-evaluation mode using the static global
condition_evaluation_mode. */
static void
set_condition_evaluation_mode (const char *args, int from_tty,
struct cmd_list_element *c)
{
const char *old_mode, *new_mode;
if ((condition_evaluation_mode_1 == condition_evaluation_target)
&& !target_supports_evaluation_of_breakpoint_conditions ())
{
condition_evaluation_mode_1 = condition_evaluation_mode;
warning (_("Target does not support breakpoint condition evaluation.\n"
"Using host evaluation mode instead."));
return;
}
new_mode = translate_condition_evaluation_mode (condition_evaluation_mode_1);
old_mode = translate_condition_evaluation_mode (condition_evaluation_mode);
/* Flip the switch. Flip it even if OLD_MODE == NEW_MODE as one of the
settings was "auto". */
condition_evaluation_mode = condition_evaluation_mode_1;
/* Only update the mode if the user picked a different one. */
if (new_mode != old_mode)
{
/* If the user switched to a different evaluation mode, we
need to synch the changes with the target as follows:
"host" -> "target": Send all (valid) conditions to the target.
"target" -> "host": Remove all the conditions from the target.
*/
if (new_mode == condition_evaluation_target)
{
/* Mark everything modified and synch conditions with the
target. */
for (bp_location *loc : all_bp_locations ())
mark_breakpoint_location_modified (loc);
}
else
{
/* Manually mark non-duplicate locations to synch conditions
with the target. We do this to remove all the conditions the
target knows about. */
for (bp_location *loc : all_bp_locations ())
if (is_breakpoint (loc->owner) && loc->inserted)
loc->needs_update = 1;
}
/* Do the update. */
update_global_location_list (UGLL_MAY_INSERT);
}
return;
}
/* Shows the current mode of breakpoint condition evaluation. Explicitly shows
what "auto" is translating to. */
static void
show_condition_evaluation_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
if (condition_evaluation_mode == condition_evaluation_auto)
gdb_printf (file,
_("Breakpoint condition evaluation "
"mode is %s (currently %s).\n"),
value,
breakpoint_condition_evaluation_mode ());
else
gdb_printf (file, _("Breakpoint condition evaluation mode is %s.\n"),
value);
}
/* Parse COND_STRING in the context of LOC and set as the condition
expression of LOC. BP_NUM is the number of LOC's owner, LOC_NUM is
the number of LOC within its owner. In case of parsing error, mark
LOC as DISABLED_BY_COND. In case of success, unset DISABLED_BY_COND. */
static void
set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
int bp_num, int loc_num)
{
bool has_junk = false;
try
{
expression_up new_exp = parse_exp_1 (&cond_string, loc->address,
block_for_pc (loc->address), 0);
if (*cond_string != 0)
has_junk = true;
else
{
loc->cond = std::move (new_exp);
if (loc->disabled_by_cond && loc->enabled)
gdb_printf (_("Breakpoint %d's condition is now valid at "
"location %d, enabling.\n"),
bp_num, loc_num);
loc->disabled_by_cond = false;
}
}
catch (const gdb_exception_error &e)
{
if (loc->enabled)
{
/* Warn if a user-enabled location is now becoming disabled-by-cond.
BP_NUM is 0 if the breakpoint is being defined for the first
time using the "break ... if ..." command, and non-zero if
already defined. */
if (bp_num != 0)
warning (_("failed to validate condition at location %d.%d, "
"disabling:\n %s"), bp_num, loc_num, e.what ());
else
warning (_("failed to validate condition at location %d, "
"disabling:\n %s"), loc_num, e.what ());
}
loc->disabled_by_cond = true;
}
if (has_junk)
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)
{
if (*exp == 0)
{
b->cond_string.reset ();
if (is_watchpoint (b))
gdb::checked_static_cast<watchpoint *> (b)->cond_exp.reset ();
else
{
int loc_num = 1;
for (bp_location &loc : b->locations ())
{
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_num++;
/* No need to free the condition agent expression
bytecode (if we have one). We will handle this
when we go through update_global_location_list. */
}
}
if (from_tty)
gdb_printf (_("Breakpoint %d now unconditional.\n"), b->number);
}
else
{
if (is_watchpoint (b))
{
innermost_block_tracker tracker;
const char *arg = exp;
expression_up new_exp = parse_exp_1 (&arg, 0, 0, 0, &tracker);
if (*arg != 0)
error (_("Junk at end of expression"));
watchpoint *w = gdb::checked_static_cast<watchpoint *> (b);
w->cond_exp = std::move (new_exp);
w->cond_exp_valid_block = tracker.block ();
}
else
{
/* Parse and set condition expressions. We make two passes.
In the first, we parse the condition string to see if it
is valid in at least one location. If so, the condition
would be accepted. So we go ahead and set the locations'
conditions. In case no valid case is found, we throw
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 (const bp_location &loc : b->locations ())
{
try
{
const char *arg = exp;
parse_exp_1 (&arg, loc.address,
block_for_pc (loc.address), 0);
if (*arg != 0)
error (_("Junk at end of expression"));
break;
}
catch (const gdb_exception_error &e)
{
/* Condition string is invalid. If this happens to
be the last loc, abandon (if not forced) or continue
(if forced). */
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 ())
{
set_breakpoint_location_condition (exp, &loc, b->number, loc_num);
loc_num++;
}
}
/* We know that the new condition parsed successfully. The
condition string of the breakpoint can be safely updated. */
b->cond_string = make_unique_xstrdup (exp);
b->condition_not_parsed = 0;
}
mark_breakpoint_modified (b);
notify_breakpoint_modified (b);
}
/* See breakpoint.h. */
void
set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
bool force)
{
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);
if (extlang != NULL)
{
error (_("Only one stop condition allowed. There is currently"
" a %s stop condition defined for this breakpoint."),
ext_lang_capitalized_name (extlang));
}
set_breakpoint_condition (&b, exp, from_tty, force);
if (is_breakpoint (&b))
update_global_location_list (UGLL_MAY_INSERT);
return;
}
error (_("No breakpoint number %d."), bpnum);
}
/* The options for the "condition" command. */
struct condition_command_opts
{
/* For "-force". */
bool force_condition = false;
};
static const gdb::option::option_def condition_command_option_defs[] = {
gdb::option::flag_option_def<condition_command_opts> {
"force",
[] (condition_command_opts *opts) { return &opts->force_condition; },
N_("Set the condition even if it is invalid for all current locations."),
},
};
/* Create an option_def_group for the "condition" options, with
CC_OPTS as context. */
static inline gdb::option::option_def_group
make_condition_command_options_def_group (condition_command_opts *cc_opts)
{
return {{condition_command_option_defs}, cc_opts};
}
/* Completion for the "condition" command. */
static void
condition_completer (struct cmd_list_element *cmd,
completion_tracker &tracker,
const char *text, const char * /*word*/)
{
bool has_no_arguments = (*text == '\0');
condition_command_opts cc_opts;
const auto group = make_condition_command_options_def_group (&cc_opts);
if (gdb::option::complete_options
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group))
return;
text = skip_spaces (text);
const char *space = skip_to_space (text);
if (*space == '\0')
{
int len;
if (text[0] == '$')
{
tracker.advance_custom_word_point_by (1);
/* We don't support completion of history indices. */
if (!isdigit (text[1]))
complete_internalvar (tracker, &text[1]);
return;
}
/* Suggest the "-force" flag if no arguments are given. If
arguments were passed, they either already include the flag,
or we are beyond the point of suggesting it because it's
positionally the first argument. */
if (has_no_arguments)
gdb::option::complete_on_all_options (tracker, group);
/* We're completing the breakpoint number. */
len = strlen (text);
for (breakpoint &b : all_breakpoints ())
{
char number[50];
xsnprintf (number, sizeof (number), "%d", b.number);
if (strncmp (number, text, len) == 0)
tracker.add_completion (make_unique_xstrdup (number));
}
return;
}
/* We're completing the expression part. Skip the breakpoint num. */
const char *exp_start = skip_spaces (space);
tracker.advance_custom_word_point_by (exp_start - text);
text = exp_start;
const char *word = advance_to_expression_complete_word_point (tracker, text);
expression_completer (cmd, tracker, text, word);
}
/* condition N EXP -- set break condition of breakpoint N to EXP. */
static void
condition_command (const char *arg, int from_tty)
{
const char *p;
int bnum;
if (arg == 0)
error_no_arg (_("breakpoint number"));
p = arg;
/* Check if the "-force" flag was passed. */
condition_command_opts cc_opts;
const auto group = make_condition_command_options_def_group (&cc_opts);
gdb::option::process_options
(&p, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
bnum = get_number (&p);
if (bnum == 0)
error (_("Bad breakpoint argument: '%s'"), arg);
set_breakpoint_condition (bnum, p, from_tty, cc_opts.force_condition);
}
/* Check that COMMAND do not contain commands that are suitable
only for tracepoints and not suitable for ordinary breakpoints.
Throw if any such commands is found. */
static void
check_no_tracepoint_commands (struct command_line *commands)
{
struct command_line *c;
for (c = commands; c; c = c->next)
{
if (c->control_type == while_stepping_control)
error (_("The 'while-stepping' command can "
"only be used for tracepoints"));
check_no_tracepoint_commands (c->body_list_0.get ());
check_no_tracepoint_commands (c->body_list_1.get ());
/* Not that command parsing removes leading whitespace and comment
lines and also empty lines. So, we only need to check for
command directly. */
if (strstr (c->line, "collect ") == c->line)
error (_("The 'collect' command can only be used for tracepoints"));
if (strstr (c->line, "teval ") == c->line)
error (_("The 'teval' command can only be used for tracepoints"));
}
}
struct longjmp_breakpoint : public momentary_breakpoint
{
using momentary_breakpoint::momentary_breakpoint;
~longjmp_breakpoint () override;
};
/* Encapsulate tests for different types of tracepoints. */
static bool
is_tracepoint_type (bptype type)
{
return (type == bp_tracepoint
|| type == bp_fast_tracepoint
|| type == bp_static_tracepoint
|| type == bp_static_marker_tracepoint);
}
/* See breakpoint.h. */
bool
is_tracepoint (const struct breakpoint *b)
{
return is_tracepoint_type (b->type);
}
/* Factory function to create an appropriate instance of breakpoint given
TYPE. */
template<typename... Arg>
static std::unique_ptr<code_breakpoint>
new_breakpoint_from_type (struct gdbarch *gdbarch, bptype type,
Arg&&... args)
{
code_breakpoint *b;
switch (type)
{
case bp_breakpoint:
case bp_hardware_breakpoint:
b = new ordinary_breakpoint (gdbarch, type,
std::forward<Arg> (args)...);
break;
case bp_fast_tracepoint:
case bp_static_tracepoint:
case bp_tracepoint:
b = new tracepoint (gdbarch, type,
std::forward<Arg> (args)...);
break;
case bp_static_marker_tracepoint:
b = new static_marker_tracepoint (gdbarch, type,
std::forward<Arg> (args)...);
break;
case bp_dprintf:
b = new dprintf_breakpoint (gdbarch, type,
std::forward<Arg> (args)...);
break;
default:
gdb_assert_not_reached ("invalid type");
}
return std::unique_ptr<code_breakpoint> (b);
}
/* A helper function that validates that COMMANDS are valid for a
breakpoint. This function will throw an exception if a problem is
found. */
static void
validate_commands_for_breakpoint (struct breakpoint *b,
struct command_line *commands)
{
if (is_tracepoint (b))
{
tracepoint *t = gdb::checked_static_cast<tracepoint *> (b);
struct command_line *c;
struct command_line *while_stepping = 0;
/* Reset the while-stepping step count. The previous commands
might have included a while-stepping action, while the new
ones might not. */
t->step_count = 0;
/* We need to verify that each top-level element of commands is
valid for tracepoints, that there's at most one
while-stepping element, and that the while-stepping's body
has valid tracing commands excluding nested while-stepping.
We also need to validate the tracepoint action line in the
context of the tracepoint --- validate_actionline actually
has side effects, like setting the tracepoint's
while-stepping STEP_COUNT, in addition to checking if the
collect/teval actions parse and make sense in the
tracepoint's context. */
for (c = commands; c; c = c->next)
{
if (c->control_type == while_stepping_control)
{
if (b->type == bp_fast_tracepoint)
error (_("The 'while-stepping' command "
"cannot be used for fast tracepoint"));
else if (b->type == bp_static_tracepoint
|| b->type == bp_static_marker_tracepoint)
error (_("The 'while-stepping' command "
"cannot be used for static tracepoint"));
if (while_stepping)
error (_("The 'while-stepping' command "
"can be used only once"));
else
while_stepping = c;
}
validate_actionline (c->line, t);
}
if (while_stepping)
{
struct command_line *c2;
gdb_assert (while_stepping->body_list_1 == nullptr);
c2 = while_stepping->body_list_0.get ();
for (; c2; c2 = c2->next)
{
if (c2->control_type == while_stepping_control)
error (_("The 'while-stepping' command cannot be nested"));
}
}
}
else
{
check_no_tracepoint_commands (commands);
}
}
/* Return a vector of all the static tracepoints set at ADDR. The
caller is responsible for releasing the vector. */
std::vector<breakpoint *>
static_tracepoints_here (CORE_ADDR addr)
{
std::vector<breakpoint *> found;
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);
}
return found;
}
/* Set the command list of B to COMMANDS. If breakpoint is tracepoint,
validate that only allowed commands are included. */
void
breakpoint_set_commands (struct breakpoint *b,
counted_command_line &&commands)
{
validate_commands_for_breakpoint (b, commands.get ());
b->commands = std::move (commands);
notify_breakpoint_modified (b);
}
/* Set the internal `silent' flag on the breakpoint. Note that this
is not the same as the "silent" that may appear in the breakpoint's
commands. */
void
breakpoint_set_silent (struct breakpoint *b, int silent)
{
int old_silent = b->silent;
b->silent = silent;
if (old_silent != silent)
notify_breakpoint_modified (b);
}
/* See breakpoint.h. */
void
breakpoint_set_thread (struct breakpoint *b, int thread)
{
/* 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);
/* 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)
notify_breakpoint_modified (b);
}
/* See breakpoint.h. */
void
breakpoint_set_task (struct breakpoint *b, int task)
{
/* 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);
/* 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)
notify_breakpoint_modified (b);
}
static void
commands_command_1 (const char *arg, int from_tty,
struct command_line *control)
{
counted_command_line cmd;
/* cmd_read will be true once we have read cmd. Note that cmd might still be
NULL after the call to read_command_lines if the user provides an empty
list of command by just typing "end". */
bool cmd_read = false;
std::string new_arg;
if (arg == NULL || !*arg)
{
/* Argument not explicitly given. Synthesize it. */
if (breakpoint_count - prev_breakpoint_count > 1)
new_arg = string_printf ("%d-%d", prev_breakpoint_count + 1,
breakpoint_count);
else if (breakpoint_count > 0)
new_arg = string_printf ("%d", breakpoint_count);
}
else
{
/* Create a copy of ARG. This is needed because the "commands"
command may be coming from a script. In that case, the read
line buffer is going to be overwritten in the lambda of
'map_breakpoint_numbers' below when reading the next line
before we are are done parsing the breakpoint numbers. */
new_arg = arg;
}
arg = new_arg.c_str ();
map_breakpoint_numbers
(arg, [&] (breakpoint *b)
{
if (!cmd_read)
{
gdb_assert (cmd == NULL);
if (control != NULL)
cmd = control->body_list_0;
else
{
std::string str
= string_printf (_("Type commands for breakpoint(s) "
"%s, one per line."),
arg);
auto do_validate = [=] (const char *line)
{
tracepoint *t
= gdb::checked_static_cast<tracepoint *> (b);
validate_actionline (line, t);
};
gdb::function_view<void (const char *)> validator;
if (is_tracepoint (b))
validator = do_validate;
cmd = read_command_lines (str.c_str (), from_tty, 1, validator);
}
cmd_read = true;
}
/* If a breakpoint was on the list more than once, we don't need to
do anything. */
if (b->commands != cmd)
{
validate_commands_for_breakpoint (b, cmd.get ());
b->commands = cmd;
notify_breakpoint_modified (b);
}
});
}
static void
commands_command (const char *arg, int from_tty)
{
commands_command_1 (arg, from_tty, NULL);
}
/* Like commands_command, but instead of reading the commands from
input stream, takes them from an already parsed command structure.
This is used by cli-script.c to DTRT with breakpoint commands
that are part of if and while bodies. */
enum command_control_type
commands_from_control_command (const char *arg, struct command_line *cmd)
{
commands_command_1 (arg, 0, cmd);
return simple_control;
}
/* Return true if BL->TARGET_INFO contains valid information. */
static bool
bp_location_has_shadow (struct bp_location *bl)
{
if (bl->loc_type != bp_loc_software_breakpoint)
return false;
if (!bl->inserted)
return false;
if (bl->target_info.shadow_len == 0)
/* BL isn't valid, or doesn't shadow memory. */
return false;
return true;
}
/* Update BUF, which is LEN bytes read from the target address
MEMADDR, by replacing a memory breakpoint with its shadowed
contents.
If READBUF is not NULL, this buffer must not overlap with the of
the breakpoint location's shadow_contents buffer. Otherwise, a
failed assertion internal error will be raised. */
static void
one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
const gdb_byte *writebuf_org,
ULONGEST memaddr, LONGEST len,
struct bp_target_info *target_info,
struct gdbarch *gdbarch)
{
/* Now do full processing of the found relevant range of elements. */
CORE_ADDR bp_addr = 0;
int bp_size = 0;
int bptoffset = 0;
if (!breakpoint_address_match (target_info->placed_address_space, 0,
current_program_space->aspace.get (), 0))
{
/* The breakpoint is inserted in a different address space. */
return;
}
/* Addresses and length of the part of the breakpoint that
we need to copy. */
bp_addr = target_info->placed_address;
bp_size = target_info->shadow_len;
if (bp_addr + bp_size <= memaddr)
{
/* The breakpoint is entirely before the chunk of memory we are
reading. */
return;
}
if (bp_addr >= memaddr + len)
{
/* The breakpoint is entirely after the chunk of memory we are
reading. */
return;
}
/* Offset within shadow_contents. */
if (bp_addr < memaddr)
{
/* Only copy the second part of the breakpoint. */
bp_size -= memaddr - bp_addr;
bptoffset = memaddr - bp_addr;
bp_addr = memaddr;
}
if (bp_addr + bp_size > memaddr + len)
{
/* Only copy the first part of the breakpoint. */
bp_size -= (bp_addr + bp_size) - (memaddr + len);
}
if (readbuf != NULL)
{
/* Verify that the readbuf buffer does not overlap with the
shadow_contents buffer. */
gdb_assert (target_info->shadow_contents >= readbuf + len
|| readbuf >= (target_info->shadow_contents
+ target_info->shadow_len));
/* Update the read buffer with this inserted breakpoint's
shadow. */
memcpy (readbuf + bp_addr - memaddr,
target_info->shadow_contents + bptoffset, bp_size);
}
else
{
const unsigned char *bp;
CORE_ADDR addr = target_info->reqstd_address;
int placed_size;
/* Update the shadow with what we want to write to memory. */
memcpy (target_info->shadow_contents + bptoffset,
writebuf_org + bp_addr - memaddr, bp_size);
/* Determine appropriate breakpoint contents and size for this
address. */
bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &placed_size);
/* Update the final write buffer with this inserted
breakpoint's INSN. */
memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size);
}
}
/* Update BUF, which is LEN bytes read from the target address MEMADDR,
by replacing any memory breakpoints with their shadowed contents.
If READBUF is not NULL, this buffer must not overlap with any of
the breakpoint location's shadow_contents buffers. Otherwise,
a failed assertion internal error will be raised.
The range of shadowed area by each bp_location is:
bl->address - bp_locations_placed_address_before_address_max
up to bl->address + bp_locations_shadow_len_after_address_max
The range we were requested to resolve shadows for is:
memaddr ... memaddr + len
Thus the safe cutoff boundaries for performance optimization are
memaddr + len <= (bl->address
- bp_locations_placed_address_before_address_max)
and:
bl->address + bp_locations_shadow_len_after_address_max <= memaddr */
void
breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
const gdb_byte *writebuf_org,
ULONGEST memaddr, LONGEST len)
{
/* Left boundary, right boundary and median element of our binary
search. */
unsigned bc_l, bc_r, bc;
/* Find BC_L which is a leftmost element which may affect BUF
content. It is safe to report lower value but a failure to
report higher one. */
bc_l = 0;
bc_r = bp_locations.size ();
while (bc_l + 1 < bc_r)
{
struct bp_location *bl;
bc = (bc_l + bc_r) / 2;
bl = bp_locations[bc];
/* Check first BL->ADDRESS will not overflow due to the added
constant. Then advance the left boundary only if we are sure
the BC element can in no way affect the BUF content (MEMADDR
to MEMADDR + LEN range).
Use the BP_LOCATIONS_SHADOW_LEN_AFTER_ADDRESS_MAX safety
offset so that we cannot miss a breakpoint with its shadow
range tail still reaching MEMADDR. */
if ((bl->address + bp_locations_shadow_len_after_address_max
>= bl->address)
&& (bl->address + bp_locations_shadow_len_after_address_max
<= memaddr))
bc_l = bc;
else
bc_r = bc;
}
/* Due to the binary search above, we need to make sure we pick the
first location that's at BC_L's address. E.g., if there are
multiple locations at the same address, BC_L may end up pointing
at a duplicate location, and miss the "master"/"inserted"
location. Say, given locations L1, L2 and L3 at addresses A and
B:
L1@A, L2@A, L3@B, ...
BC_L could end up pointing at location L2, while the "master"
location could be L1. Since the `loc->inserted' flag is only set
on "master" locations, we'd forget to restore the shadow of L1
and L2. */
while (bc_l > 0
&& bp_locations[bc_l]->address == bp_locations[bc_l - 1]->address)
bc_l--;
/* Now do full processing of the found relevant range of elements. */
for (bc = bc_l; bc < bp_locations.size (); bc++)
{
struct bp_location *bl = bp_locations[bc];
/* bp_location array has BL->OWNER always non-NULL. */
if (bl->owner->type == bp_none)
warning (_("reading through apparently deleted breakpoint #%d?"),
bl->owner->number);
/* Performance optimization: any further element can no longer affect BUF
content. */
if (bl->address >= bp_locations_placed_address_before_address_max
&& (memaddr + len
<= (bl->address
- bp_locations_placed_address_before_address_max)))
break;
if (!bp_location_has_shadow (bl))
continue;
one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org,
memaddr, len, &bl->target_info, bl->gdbarch);
}
}
/* See breakpoint.h. */
bool
is_breakpoint (const struct breakpoint *bpt)
{
return (bpt->type == bp_breakpoint
|| bpt->type == bp_hardware_breakpoint
|| bpt->type == bp_dprintf);
}
/* Return true if BPT is of any hardware watchpoint kind. */
static bool
is_hardware_watchpoint (const struct breakpoint *bpt)
{
return (bpt->type == bp_hardware_watchpoint
|| bpt->type == bp_read_watchpoint
|| bpt->type == bp_access_watchpoint);
}
/* See breakpoint.h. */
bool
is_watchpoint (const struct breakpoint *bpt)
{
return (is_hardware_watchpoint (bpt)
|| bpt->type == bp_watchpoint);
}
/* Returns true if the current thread and its running state are safe
to evaluate or update watchpoint B. Watchpoints on local
expressions need to be evaluated in the context of the thread that
was current when the watchpoint was created, and, that thread needs
to be stopped to be able to select the correct frame context.
Watchpoints on global expressions can be evaluated on any thread,
and in any state. It is presently left to the target allowing
memory accesses when threads are running. */
static bool
watchpoint_in_thread_scope (struct watchpoint *b)
{
return (b->pspace == current_program_space
&& (b->watchpoint_thread == null_ptid
|| (inferior_ptid == b->watchpoint_thread
&& !inferior_thread ()->executing ())));
}
/* Set watchpoint B to disp_del_at_next_stop, even including its possible
associated bp_watchpoint_scope breakpoint. */
static void
watchpoint_del_at_next_stop (struct watchpoint *w)
{
if (w->related_breakpoint != w)
{
gdb_assert (w->related_breakpoint->type == bp_watchpoint_scope);
gdb_assert (w->related_breakpoint->related_breakpoint == w);
w->related_breakpoint->disposition = disp_del_at_next_stop;
w->related_breakpoint->related_breakpoint = w->related_breakpoint;
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
watchpoint W. */
static struct value *
extract_bitfield_from_watchpoint_value (struct watchpoint *w, struct value *val)
{
struct value *bit_val;
if (val == NULL)
return NULL;
bit_val = value::allocate (val->type ());
val->unpack_bitfield (bit_val,
w->val_bitpos,
w->val_bitsize,
val->contents_for_printing ().data (),
val->offset ());
return bit_val;
}
/* Allocate a dummy location and add it to B. This is required
because bpstat_stop_status requires a location to be able to report
stops. */
static void
add_dummy_location (struct breakpoint *b,
struct program_space *pspace)
{
gdb_assert (!b->has_locations ());
bp_location *loc = new bp_location (b, bp_loc_other);
loc->pspace = pspace;
b->add_location (*loc);
}
/* Assuming that B is a watchpoint:
- Reparse watchpoint expression, if REPARSE is true
- Evaluate expression and store the result in B->val
- Evaluate the condition if there is one, and store the result
in b->loc->cond.
- Update the list of values that must be watched in B->loc.
If the watchpoint disposition is disp_del_at_next_stop, then do
nothing. If this is local watchpoint that is out of scope, delete
it.
Even with `set breakpoint always-inserted on' the watchpoints are
removed + inserted on each stop here. Normal breakpoints must
never be removed because they might be missed by a running thread
when debugging in non-stop mode. On the other hand, hardware
watchpoints (is_hardware_watchpoint; processed here) are specific
to each LWP since they are stored in each LWP's hardware debug
registers. Therefore, such LWP must be stopped first in order to
be able to modify its hardware watchpoints.
Hardware watchpoints must be reset exactly once after being
presented to the user. It cannot be done sooner, because it would
reset the data used to present the watchpoint hit to the user. And
it must not be done later because it could display the same single
watchpoint hit during multiple GDB stops. Note that the latter is
relevant only to the hardware watchpoint types bp_read_watchpoint
and bp_access_watchpoint. False hit by bp_hardware_watchpoint is
not user-visible - its hit is suppressed if the memory content has
not changed.
The following constraints influence the location where we can reset
hardware watchpoints:
* target_stopped_by_watchpoint and target_stopped_data_address are
called several times when GDB stops.
[linux]
* Multiple hardware watchpoints can be hit at the same time,
causing GDB to stop. GDB only presents one hardware watchpoint
hit at a time as the reason for stopping, and all the other hits
are presented later, one after the other, each time the user
requests the execution to be resumed. Execution is not resumed
for the threads still having pending hit event stored in
LWP_INFO->STATUS. While the watchpoint is already removed from
the inferior on the first stop the thread hit event is kept being
reported from its cached value by linux_nat_stopped_data_address
until the real thread resume happens after the watchpoint gets
presented and thus its LWP_INFO->STATUS gets reset.
Therefore the hardware watchpoint hit can get safely reset on the
watchpoint removal from inferior. */
static void
update_watchpoint (struct watchpoint *b, bool reparse)
{
bool within_current_scope;
/* If this is a local watchpoint, we only want to check if the
watchpoint frame is in scope if the current thread is the thread
that was used to create the watchpoint. */
if (!watchpoint_in_thread_scope (b))
return;
if (b->disposition == disp_del_at_next_stop)
return;
std::optional<scoped_restore_selected_frame> restore_frame;
/* Determine if the watchpoint is within scope. */
if (b->exp_valid_block == NULL)
within_current_scope = true;
else
{
frame_info_ptr fi = get_current_frame ();
struct gdbarch *frame_arch = get_frame_arch (fi);
CORE_ADDR frame_pc = get_frame_pc (fi);
/* If we're at a point where the stack has been destroyed
(e.g. in a function epilogue), unwinding may not work
properly. Do not attempt to recreate locations at this
point. See similar comments in watchpoint_check. */
if (gdbarch_stack_frame_destroyed_p (frame_arch, frame_pc))
return;
/* Save the current frame's ID so we can restore it after
evaluating the watchpoint expression on its own frame. */
/* FIXME drow/2003-09-09: It would be nice if evaluate_expression
took a frame parameter, so that we didn't have to change the
selected frame. */
restore_frame.emplace ();
fi = frame_find_by_id (b->watchpoint_frame);
within_current_scope = (fi != NULL);
if (within_current_scope)
select_frame (fi);
}
/* 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->clear_locations ();
if (within_current_scope && reparse)
{
const char *s;
b->exp.reset ();
s = (b->exp_string_reparse
? b->exp_string_reparse.get ()
: b->exp_string.get ());
b->exp = parse_exp_1 (&s, 0, b->exp_valid_block, 0);
/* If the meaning of expression itself changed, the old value is
no longer relevant. We don't want to report a watchpoint hit
to the user when the old value and the new value may actually
be completely different objects. */
b->val = NULL;
b->val_valid = false;
/* Note that unlike with breakpoints, the watchpoint's condition
expression is stored in the breakpoint object, not in the
locations (re)created below. */
if (b->cond_string != NULL)
{
b->cond_exp.reset ();
s = b->cond_string.get ();
b->cond_exp = parse_exp_1 (&s, 0, b->cond_exp_valid_block, 0);
}
}
/* If we failed to parse the expression, for example because
it refers to a global variable in a not-yet-loaded shared library,
don't try to insert watchpoint. We don't automatically delete
such watchpoint, though, since failure to parse expression
is different from out-of-scope watchpoint. */
if (!target_has_execution ())
{
/* Without execution, memory can't change. No use to try and
set watchpoint locations. The watchpoint will be reset when
the target gains execution, through breakpoint_re_set. */
if (!can_use_hw_watchpoints)
{
if (b->works_in_software_mode ())
b->type = bp_watchpoint;
else
error (_("Can't set read/access watchpoint when "
"hardware watchpoints are disabled."));
}
}
else if (within_current_scope && b->exp)
{
std::vector<value_ref_ptr> val_chain;
struct value *v, *result;
struct program_space *wp_pspace;
fetch_subexp_value (b->exp.get (), b->exp->op.get (), &v, &result,
&val_chain, false);
/* Avoid setting b->val if it's already set. The meaning of
b->val is 'the last value' user saw, and we should update
it only if we reported that last value to user. As it
happens, the code that reports it updates b->val directly.
We don't keep track of the memory value for masked
watchpoints. */
if (!b->val_valid && !is_masked_watchpoint (b))
{
if (b->val_bitsize != 0)
v = extract_bitfield_from_watchpoint_value (b, v);
b->val = release_value (v);
b->val_valid = true;
}
if (b->exp_valid_block == nullptr)
wp_pspace = current_program_space;
else
wp_pspace = get_frame_program_space (get_selected_frame (NULL));
/* Look at each value on the value chain. */
gdb_assert (!val_chain.empty ());
for (const value_ref_ptr &iter : val_chain)
{
v = iter.get ();
/* If it's a memory location, and GDB actually needed
its contents to evaluate the expression, then we
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 (v->lval () == lval_memory
&& (v == val_chain[0] || ! v->lazy ()))
{
struct type *vtype = check_typedef (v->type ());
/* We only watch structs and arrays if user asked
for it explicitly, never if they just happen to
appear in the middle of some value chain. */
if (v == result
|| (vtype->code () != TYPE_CODE_STRUCT
&& vtype->code () != TYPE_CODE_ARRAY))
{
CORE_ADDR addr;
enum target_hw_bp_type type;
int bitpos = 0, bitsize = 0;
if (v->bitsize () != 0)
{
/* Extract the bit parameters out from the bitfield
sub-expression. */
bitpos = v->bitpos ();
bitsize = v->bitsize ();
}
else if (v == result && b->val_bitsize != 0)
{
/* If VAL_BITSIZE != 0 then RESULT is actually a bitfield
lvalue whose bit parameters are saved in the fields
VAL_BITPOS and VAL_BITSIZE. */
bitpos = b->val_bitpos;
bitsize = b->val_bitsize;
}
addr = v->address ();
if (bitsize != 0)
{
/* Skip the bytes that don't contain the bitfield. */
addr += bitpos / 8;
}
type = hw_write;
if (b->type == bp_read_watchpoint)
type = hw_read;
else if (b->type == bp_access_watchpoint)
type = hw_access;
bp_location *loc = b->allocate_location ();
loc->gdbarch = v->type ()->arch ();
loc->pspace = wp_pspace;
loc->address
= gdbarch_remove_non_address_bits (loc->gdbarch, addr);
b->add_location (*loc);
if (bitsize != 0)
{
/* Just cover the bytes that make up the bitfield. */
loc->length = ((bitpos % 8) + bitsize + 7) / 8;
}
else
loc->length = v->type ()->length ();
loc->watchpoint_type = type;
}
}
}
/* 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
as the value chain may have changed. */
{
int reg_cnt;
enum bp_loc_type loc_type;
reg_cnt = can_use_hardware_watchpoint (val_chain);
if (reg_cnt)
{
int i, target_resources_ok, other_type_used;
enum bptype type;
/* Use an exact watchpoint when there's only one memory region to be
watched, and only one debug register is needed to watch it. */
b->exact = target_exact_watchpoints && reg_cnt == 1;
/* We need to determine how many resources are already
used for all other hardware watchpoints plus this one
to see if we still have enough resources to also fit
this watchpoint in as well. */
/* If this is a software watchpoint, we try to turn it
to a hardware one -- count resources as if B was of
hardware watchpoint type. */
type = b->type;
if (type == bp_watchpoint)
type = bp_hardware_watchpoint;
/* This watchpoint may or may not have been placed on
the list yet at this point (it won't be in the list
if we're trying to create it for the first time,
through watch_command), so always account for it
manually. */
/* Count resources used by all watchpoints except B. */
i = hw_watchpoint_used_count_others (b, type, &other_type_used);
/* Add in the resources needed for B. */
i += hw_watchpoint_use_count (b);
target_resources_ok
= target_can_use_hardware_watchpoint (type, i, other_type_used);
if (target_resources_ok <= 0)
{
bool sw_mode = b->works_in_software_mode ();
if (target_resources_ok == 0 && !sw_mode)
error (_("Target does not support this type of "
"hardware watchpoint."));
else if (target_resources_ok < 0 && !sw_mode)
error (_("There are not enough available hardware "
"resources for this watchpoint."));
/* Downgrade to software watchpoint. */
change_type_to_bp_watchpoint (b);
}
else
{
/* If this was a software watchpoint, we've just
found we have enough resources to turn it to a
hardware watchpoint. Otherwise, this is a
nop. */
b->type = type;
}
}
else if (!b->works_in_software_mode ())
{
if (!can_use_hw_watchpoints)
error (_("Can't set read/access watchpoint when "
"hardware watchpoints are disabled."));
else
error (_("Expression cannot be implemented with "
"read/access watchpoint."));
}
else
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;
}
/* 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->has_locations ())
add_dummy_location (b, wp_pspace);
}
else if (!within_current_scope)
{
gdb_printf (_("\
Watchpoint %d deleted because the program has left the block\n\
in which its expression is valid.\n"),
b->number);
watchpoint_del_at_next_stop (b);
}
}
/* Returns true iff breakpoint location should be
inserted in the inferior. We don't differentiate the type of BL's owner
(breakpoint vs. tracepoint), although insert_location in tracepoint's
breakpoint_ops is not defined, because in insert_bp_location,
tracepoint's insert_location will not be called. */
static bool
should_be_inserted (struct bp_location *bl)
{
if (bl->owner == NULL || !breakpoint_enabled (bl->owner))
return false;
if (bl->owner->disposition == disp_del_at_next_stop)
return false;
if (!bl->enabled || bl->disabled_by_cond
|| bl->shlib_disabled || bl->duplicate)
return false;
if (user_breakpoint_p (bl->owner) && bl->pspace->executing_startup)
return false;
/* This is set for example, when we're attached to the parent of a
vfork, and have detached from the child. The child is running
free, and we expect it to do an exec or exit, at which point the
OS makes the parent schedulable again (and the target reports
that the vfork is done). Until the child is done with the shared
memory region, do not insert breakpoints in the parent, otherwise
the child could still trip on the parent's breakpoints. Since
the parent is blocked anyway, it won't miss any breakpoint. */
if (bl->pspace->breakpoints_not_allowed)
return false;
/* Don't insert a breakpoint if we're trying to step past its
location, except if the breakpoint is a single-step breakpoint,
and the breakpoint's thread is the thread which is stepping past
a breakpoint. */
if ((bl->loc_type == bp_loc_software_breakpoint
|| bl->loc_type == bp_loc_hardware_breakpoint)
&& stepping_past_instruction_at (bl->pspace->aspace.get (),
bl->address)
/* The single-step breakpoint may be inserted at the location
we're trying to step if the instruction branches to itself.
However, the instruction won't be executed at all and it may
break the semantics of the instruction, for example, the
instruction is a conditional branch or updates some flags.
We can't fix it unless GDB is able to emulate the instruction
or switch to displaced stepping. */
&& !(bl->owner->type == bp_single_step
&& thread_is_stepping_over_breakpoint (bl->owner->thread)))
{
infrun_debug_printf ("skipping breakpoint: stepping past insn at: %s",
paddress (bl->gdbarch, bl->address));
return false;
}
/* Don't insert watchpoints if we're trying to step past the
instruction that triggered one. */
if ((bl->loc_type == bp_loc_hardware_watchpoint)
&& stepping_past_nonsteppable_watchpoint ())
{
infrun_debug_printf ("stepping past non-steppable watchpoint. "
"skipping watchpoint at %s:%d",
paddress (bl->gdbarch, bl->address), bl->length);
return false;
}
return true;
}
/* Same as should_be_inserted but does the check assuming
that the location is not duplicated. */
static bool
unduplicated_should_be_inserted (struct bp_location *bl)
{
scoped_restore restore_bl_duplicate
= make_scoped_restore (&bl->duplicate, 0);
return should_be_inserted (bl);
}
/* Parses a conditional described by an expression COND into an
agent expression bytecode suitable for evaluation
by the bytecode interpreter. Return NULL if there was
any error during parsing. */
static agent_expr_up
parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
{
if (cond == NULL)
return NULL;
agent_expr_up aexpr;
/* We don't want to stop processing, so catch any errors
that may show up. */
try
{
aexpr = gen_eval_for_expr (scope, cond);
}
catch (const gdb_exception_error &ex)
{
/* If we got here, it means the condition could not be parsed to a valid
bytecode expression and thus can't be evaluated on the target's side.
It's no use iterating through the conditions. */
}
/* We have a valid agent expression. */
return aexpr;
}
/* Based on location BL, create a list of breakpoint conditions to be
passed on to the target. If we have duplicated locations with different
conditions, we will add such conditions to the list. The idea is that the
target will evaluate the list of conditions and will only notify GDB when
one of them is true. */
static void
build_target_condition_list (struct bp_location *bl)
{
bool null_condition_or_parse_error = false;
int modified = bl->needs_update;
/* Release conditions left over from a previous insert. */
bl->target_info.conditions.clear ();
/* This is only meaningful if the target is
evaluating conditions and if the user has
opted for condition evaluation on the target's
side. */
if (gdb_evaluates_breakpoint_condition_p ()
|| !target_supports_evaluation_of_breakpoint_conditions ())
return;
auto loc_range = all_bp_locations_at_addr (bl->address);
/* Do a first pass to check for locations with no assigned
conditions or conditions that fail to parse to a valid agent
expression bytecode. If any of these happen, then it's no use to
send conditions to the target since this location will always
trigger and generate a response back to GDB. Note we consider
all locations at the same address irrespective of type, i.e.,
even if the locations aren't considered duplicates (e.g.,
software breakpoint and hardware breakpoint at the same
address). */
for (bp_location *loc : loc_range)
{
if (is_breakpoint (loc->owner) && loc->pspace->num == bl->pspace->num)
{
if (modified)
{
/* Re-parse the conditions since something changed. In that
case we already freed the condition bytecodes (see
force_breakpoint_reinsertion). We just
need to parse the condition to bytecodes again. */
loc->cond_bytecode = parse_cond_to_aexpr (bl->address,
loc->cond.get ());
}
/* If we have a NULL bytecode expression, it means something
went wrong or we have a null condition expression. */
if (!loc->cond_bytecode)
{
null_condition_or_parse_error = true;
break;
}
}
}
/* If any of these happened, it means we will have to evaluate the conditions
for the location's address on gdb's side. It is no use keeping bytecodes
for all the other duplicate locations, thus we free all of them here.
This is so we have a finer control over which locations' conditions are
being evaluated by GDB or the remote stub. */
if (null_condition_or_parse_error)
{
for (bp_location *loc : loc_range)
{
if (is_breakpoint (loc->owner) && loc->pspace->num == bl->pspace->num)
{
/* Only go as far as the first NULL bytecode is
located. */
if (!loc->cond_bytecode)
return;
loc->cond_bytecode.reset ();
}
}
}
/* 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 merge all the conditions
anyway, as it's simpler, and doesn't really make a practical
difference. */
for (bp_location *loc : loc_range)
if (loc->cond
&& is_breakpoint (loc->owner)
&& loc->pspace->num == bl->pspace->num
&& loc->owner->enable_state == bp_enabled
&& loc->enabled
&& !loc->disabled_by_cond)
{
/* Add the condition to the vector. This will be used later
to send the conditions to the target. */
bl->target_info.conditions.push_back (loc->cond_bytecode.get ());
}
return;
}
/* Parses a command described by string CMD into an agent expression
bytecode suitable for evaluation by the bytecode interpreter.
Return NULL if there was any error during parsing. */
static agent_expr_up
parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
{
const char *cmdrest;
const char *format_start, *format_end;
struct gdbarch *gdbarch = get_current_arch ();
if (cmd == NULL)
return NULL;
cmdrest = cmd;
if (*cmdrest == ',')
++cmdrest;
cmdrest = skip_spaces (cmdrest);
if (*cmdrest++ != '"')
error (_("No format string following the location"));
format_start = cmdrest;
format_pieces fpieces (&cmdrest);
format_end = cmdrest;
if (*cmdrest++ != '"')
error (_("Bad format string, non-terminated '\"'."));
cmdrest = skip_spaces (cmdrest);
if (!(*cmdrest == ',' || *cmdrest == '\0'))
error (_("Invalid argument syntax"));
if (*cmdrest == ',')
cmdrest++;
cmdrest = skip_spaces (cmdrest);
/* For each argument, make an expression. */
std::vector<struct expression *> argvec;
while (*cmdrest != '\0')
{
const char *cmd1;
cmd1 = cmdrest;
expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope),
PARSER_COMMA_TERMINATES);
argvec.push_back (expr.release ());
cmdrest = cmd1;
if (*cmdrest == ',')
++cmdrest;
}
agent_expr_up aexpr;
/* We don't want to stop processing, so catch any errors
that may show up. */
try
{
aexpr = gen_printf (scope, gdbarch, 0, 0,
format_start, format_end - format_start,
argvec.size (), argvec.data ());
}
catch (const gdb_exception_error &ex)
{
/* If we got here, it means the command could not be parsed to a valid
bytecode expression and thus can't be evaluated on the target's side.
It's no use iterating through the other commands. */
}
/* We have a valid agent expression, return it. */
return aexpr;
}
/* Based on location BL, create a list of breakpoint commands to be
passed on to the target. If we have duplicated locations with
different commands, we will add any such to the list. */
static void
build_target_command_list (struct bp_location *bl)
{
bool null_command_or_parse_error = false;
int modified = bl->needs_update;
/* Clear commands left over from a previous insert. */
bl->target_info.tcommands.clear ();
if (!target_can_run_breakpoint_commands ())
return;
/* For now, limit to agent-style dprintf breakpoints. */
if (dprintf_style != dprintf_style_agent)
return;
auto loc_range = all_bp_locations_at_addr (bl->address);
/* For now, if we have any location at the same address that isn't a
dprintf, don't install the target-side commands, as that would
make the breakpoint not be reported to the core, and we'd lose
control. */
for (bp_location *loc : loc_range)
if (is_breakpoint (loc->owner)
&& loc->pspace->num == bl->pspace->num
&& loc->owner->type != bp_dprintf)
return;
/* Do a first pass to check for locations with no assigned
conditions or conditions that fail to parse to a valid agent expression
bytecode. If any of these happen, then it's no use to send conditions
to the target since this location will always trigger and generate a
response back to GDB. */
for (bp_location *loc : loc_range)
{
if (is_breakpoint (loc->owner) && loc->pspace->num == bl->pspace->num)
{
if (modified)
{
/* Re-parse the commands since something changed. In that
case we already freed the command bytecodes (see
force_breakpoint_reinsertion). We just
need to parse the command to bytecodes again. */
loc->cmd_bytecode
= parse_cmd_to_aexpr (bl->address,
loc->owner->extra_string.get ());
}
/* If we have a NULL bytecode expression, it means something
went wrong or we have a null command expression. */
if (!loc->cmd_bytecode)
{
null_command_or_parse_error = true;
break;
}
}
}
/* If anything failed, then we're not doing target-side commands,
and so clean up. */
if (null_command_or_parse_error)
{
for (bp_location *loc : loc_range)
if (is_breakpoint (loc->owner)
&& loc->pspace->num == bl->pspace->num)
{
/* Only go as far as the first NULL bytecode is
located. */
if (loc->cmd_bytecode == NULL)
return;
loc->cmd_bytecode.reset ();
}
}
/* No NULL commands or failed bytecode generation. Build a command
list for all duplicate locations at this location's address.
Note that here we must care for whether the breakpoint location
types are considered duplicates, otherwise, say, if we have a
software and hardware location at the same address, the target
could end up running the commands twice. For the moment, we only
support targets-side commands with dprintf, but it doesn't hurt
to be pedantically correct in case that changes. */
for (bp_location *loc : loc_range)
if (breakpoint_locations_match (bl, loc)
&& loc->owner->extra_string
&& is_breakpoint (loc->owner)
&& loc->pspace->num == bl->pspace->num
&& loc->owner->enable_state == bp_enabled
&& loc->enabled
&& !loc->disabled_by_cond)
{
/* Add the command to the vector. This will be used later
to send the commands to the target. */
bl->target_info.tcommands.push_back (loc->cmd_bytecode.get ());
}
bl->target_info.persist = 0;
/* Maybe flag this location as persistent. */
if (bl->owner->type == bp_dprintf && disconnected_dprintf)
bl->target_info.persist = 1;
}
/* Return the kind of breakpoint on address *ADDR. Get the kind
of breakpoint according to ADDR except single-step breakpoint.
Get the kind of single-step breakpoint according to the current
registers state. */
static int
breakpoint_kind (const struct bp_location *bl, CORE_ADDR *addr)
{
if (bl->owner->type == bp_single_step)
{
struct thread_info *thr = find_thread_global_id (bl->owner->thread);
struct regcache *regcache;
regcache = get_thread_regcache (thr);
return gdbarch_breakpoint_kind_from_current_state (bl->gdbarch,
regcache, addr);
}
else
return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
}
/* Rethrow the currently handled exception, if it's a TARGET_CLOSE_ERROR.
E is either the currently handled exception, or a copy, or a sliced copy,
so we can't rethrow that one, but we can use it to inspect the properties
of the currently handled exception. */
static void
rethrow_on_target_close_error (const gdb_exception &e)
{
if (e.reason == 0)
return;
/* Can't set the breakpoint. */
if (e.error != TARGET_CLOSE_ERROR)
return;
/* If the target has closed then it will have deleted any breakpoints
inserted within the target inferior, as a result any further attempts
to interact with the breakpoint objects is not possible. Just rethrow
the error. Don't use e to rethrow, to prevent object slicing of the
exception. */
throw;
}
/* Insert a low-level "breakpoint" of some type. BL is the breakpoint
location. Any error messages are printed to TMP_ERROR_STREAM; and
DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems.
Returns 0 for success, 1 if the bp_location type is not supported or
-1 for failure.
NOTE drow/2003-09-09: This routine could be broken down to an
object-style method for each breakpoint or catchpoint type. */
static int
insert_bp_location (struct bp_location *bl,
struct ui_file *tmp_error_stream,
int *disabled_breaks,
int *hw_breakpoint_error,
int *hw_bp_error_explained_already)
{
gdb_exception bp_excpt;
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
target_read_memory which depends on these buffers when
a memory read is requested at the breakpoint location:
Once the target_info has been wiped, we fail to see that
we have a breakpoint inserted at that address and thus
read the breakpoint instead of returning the data saved in
the breakpoint location's shadow contents. */
bl->target_info.reqstd_address = bl->address;
bl->target_info.placed_address_space = bl->pspace->aspace.get ();
bl->target_info.length = bl->length;
/* When working with target-side conditions, we must pass all the conditions
for the same breakpoint address down to the target since GDB will not
insert those locations. With a list of breakpoint conditions, the target
can decide when to stop and notify GDB. */
if (is_breakpoint (bl->owner))
{
build_target_condition_list (bl);
build_target_command_list (bl);
/* Reset the modification marker. */
bl->needs_update = 0;
}
/* If "set breakpoint auto-hw" is "on" and a software breakpoint was
set at a read-only address, then a breakpoint location will have
been changed to hardware breakpoint before we get here. If it is
"off" however, error out before actually trying to insert the
breakpoint, with a nicer error message. */
if (bl->loc_type == bp_loc_software_breakpoint
&& !automatic_hardware_breakpoints)
{
mem_region *mr = lookup_mem_region (bl->address);
if (mr != nullptr && mr->attrib.mode != MEM_RW)
{
gdb_printf (tmp_error_stream,
_("Cannot insert breakpoint %d.\n"
"Cannot set software breakpoint "
"at read-only address %s\n"),
bl->owner->number,
paddress (bl->gdbarch, bl->address));
return 1;
}
}
if (bl->loc_type == bp_loc_software_breakpoint
|| bl->loc_type == bp_loc_hardware_breakpoint)
{
/* First check to see if we have to handle an overlay. */
if (overlay_debugging == ovly_off
|| bl->section == NULL
|| !(section_is_overlay (bl->section)))
{
/* No overlay handling: just set the breakpoint. */
try
{
int val;
val = bl->owner->insert_location (bl);
if (val)
bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
}
catch (gdb_exception &e)
{
rethrow_on_target_close_error (e);
bp_excpt = std::move (e);
}
}
else
{
/* This breakpoint is in an overlay section.
Shall we set a breakpoint at the LMA? */
if (!overlay_events_enabled)
{
/* Yes -- overlay event support is not active,
so we must try to set a breakpoint at the LMA.
This will not work for a hardware breakpoint. */
if (bl->loc_type == bp_loc_hardware_breakpoint)
warning (_("hardware breakpoint %d not supported in overlay!"),
bl->owner->number);
else
{
CORE_ADDR addr = overlay_unmapped_address (bl->address,
bl->section);
/* Set a software (trap) breakpoint at the LMA. */
bl->overlay_target_info = bl->target_info;
bl->overlay_target_info.reqstd_address = addr;
/* No overlay handling: just set the breakpoint. */
try
{
int val;
bl->overlay_target_info.kind
= breakpoint_kind (bl, &addr);
bl->overlay_target_info.placed_address = addr;
val = target_insert_breakpoint (bl->gdbarch,
&bl->overlay_target_info);
if (val)
bp_excpt
= gdb_exception {RETURN_ERROR, GENERIC_ERROR};
}
catch (gdb_exception &e)
{
rethrow_on_target_close_error (e);
bp_excpt = std::move (e);
}
if (bp_excpt.reason != 0)
gdb_printf (tmp_error_stream,
"Overlay breakpoint %d "
"failed: in ROM?\n",
bl->owner->number);
}
}
/* Shall we set a breakpoint at the VMA? */
if (section_is_mapped (bl->section))
{
/* Yes. This overlay section is mapped into memory. */
try
{
int val;
val = bl->owner->insert_location (bl);
if (val)
bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
}
catch (gdb_exception_error &e)
{
rethrow_on_target_close_error (e);
bp_excpt = std::move (e);
}
}
else
{
/* No. This breakpoint will not be inserted.
No error, but do not mark the bp as 'inserted'. */
return 0;
}
}
if (bp_excpt.reason != 0)
{
/* Can't set the breakpoint. */
gdb_assert (bl->owner != nullptr);
/* In some cases, we might not be able to insert a
breakpoint in a shared library that has already been
removed, but we have not yet processed the shlib unload
event. Unfortunately, some targets that implement
breakpoint insertion themselves can't tell why the
breakpoint insertion failed (e.g., the remote target
doesn't define error codes), so we must treat generic
errors as memory errors. */
if (bp_excpt.reason == RETURN_ERROR
&& (bp_excpt.error == GENERIC_ERROR
|| bp_excpt.error == MEMORY_ERROR)
&& bl->loc_type == bp_loc_software_breakpoint
&& (solib_name_from_address (bl->pspace, bl->address)
|| shared_objfile_contains_address_p (bl->pspace,
bl->address)))
{
/* See also: disable_breakpoints_in_shlibs. */
bl->shlib_disabled = 1;
notify_breakpoint_modified (bl->owner);
if (!*disabled_breaks)
{
gdb_printf (tmp_error_stream,
"Cannot insert breakpoint %d.\n",
bl->owner->number);
gdb_printf (tmp_error_stream,
"Temporarily disabling shared "
"library breakpoints:\n");
}
*disabled_breaks = 1;
gdb_printf (tmp_error_stream,
"breakpoint #%d\n", bl->owner->number);
return 0;
}
else
{
if (bl->loc_type == bp_loc_hardware_breakpoint)
{
*hw_breakpoint_error = 1;
*hw_bp_error_explained_already = bp_excpt.message != NULL;
gdb_printf (tmp_error_stream,
"Cannot insert hardware breakpoint %d%s",
bl->owner->number,
bp_excpt.message ? ":" : ".\n");
if (bp_excpt.message != NULL)
gdb_printf (tmp_error_stream, "%s.\n",
bp_excpt.what ());
}
else
{
if (bp_excpt.message == NULL)
{
std::string message
= memory_error_message (TARGET_XFER_E_IO,
bl->gdbarch, bl->address);
gdb_printf (tmp_error_stream,
"Cannot insert breakpoint %d.\n"
"%s\n",
bl->owner->number, message.c_str ());
}
else
{
gdb_printf (tmp_error_stream,
"Cannot insert breakpoint %d: %s\n",
bl->owner->number,
bp_excpt.what ());
}
}
return 1;
}
}
else
bl->inserted = 1;
return 0;
}
else if (bl->loc_type == bp_loc_hardware_watchpoint
&& bl->owner->disposition != disp_del_at_next_stop)
{
int val;
val = bl->owner->insert_location (bl);
/* If trying to set a read-watchpoint, and it turns out it's not
supported, try emulating one with an access watchpoint. */
if (val == 1 && bl->watchpoint_type == hw_read)
{
/* But don't try to insert it, if there's already another
hw_access location that would be considered a duplicate
of this one. */
for (bp_location *loc : all_bp_locations ())
if (loc != bl
&& loc->watchpoint_type == hw_access
&& watchpoint_locations_match (bl, loc))
{
bl->duplicate = 1;
bl->inserted = 1;
bl->target_info = loc->target_info;
bl->watchpoint_type = hw_access;
val = 0;
break;
}
if (val == 1)
{
bl->watchpoint_type = hw_access;
val = bl->owner->insert_location (bl);
if (val)
/* Back to the original value. */
bl->watchpoint_type = hw_read;
}
}
bl->inserted = (val == 0);
}
else if (bl->owner->type == bp_catchpoint)
{
int val;
val = bl->owner->insert_location (bl);
if (val)
{
bl->owner->enable_state = bp_disabled;
if (val == 1)
warning (_("\
Error inserting catchpoint %d: Your system does not support this type\n\
of catchpoint."), bl->owner->number);
else
warning (_("Error inserting catchpoint %d."), bl->owner->number);
}
bl->inserted = (val == 0);
/* We've already printed an error message if there was a problem
inserting this catchpoint, and we've disabled the catchpoint,
so just return success. */
return 0;
}
return 0;
}
/* This function is called when program space PSPACE is about to be
deleted. It takes care of updating breakpoints to not reference
PSPACE anymore. */
void
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);
/* Breakpoints set through other program spaces could have locations
bound to PSPACE as well. Remove those. */
for (bp_location *loc : all_bp_locations ())
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. */
update_global_location_list (UGLL_DONT_INSERT);
}
/* Make sure all breakpoints are inserted in inferior.
Throws exception on any error.
A breakpoint that is already inserted won't be inserted
again, so calling this function twice is safe. */
void
insert_breakpoints (void)
{
for (breakpoint &bpt : all_breakpoints ())
if (is_hardware_watchpoint (&bpt))
{
watchpoint &w = gdb::checked_static_cast<watchpoint &> (bpt);
update_watchpoint (&w, false /* don't reparse. */);
}
/* Updating watchpoints creates new locations, so update the global
location list. Explicitly tell ugll to insert locations and
ignore breakpoints_always_inserted_mode. Also,
update_global_location_list tries to "upgrade" software
breakpoints to hardware breakpoints to handle "set breakpoint
auto-hw", so we need to call it even if we don't have new
locations. */
update_global_location_list (UGLL_INSERT);
}
/* This is used when we need to synch breakpoint conditions between GDB and the
target. It is the case with deleting and disabling of breakpoints when using
always-inserted mode. */
static void
update_inserted_breakpoint_locations (void)
{
int error_flag = 0;
int val = 0;
int disabled_breaks = 0;
int hw_breakpoint_error = 0;
int hw_bp_details_reported = 0;
string_file tmp_error_stream;
/* Explicitly mark the warning -- this will only be printed if
there was an error. */
tmp_error_stream.puts ("Warning:\n");
scoped_restore_current_pspace_and_thread restore_pspace_thread;
for (bp_location *bl : all_bp_locations ())
{
/* We only want to update software breakpoints and hardware
breakpoints. */
if (!is_breakpoint (bl->owner))
continue;
/* We only want to update locations that are already inserted
and need updating. This is to avoid unwanted insertion during
deletion of breakpoints. */
if (!bl->inserted || !bl->needs_update)
continue;
switch_to_program_space_and_thread (bl->pspace);
/* For targets that support global breakpoints, there's no need
to select an inferior to insert breakpoint to. In fact, even
if we aren't attached to any process yet, we should still
insert breakpoints. */
if (!gdbarch_has_global_breakpoints (current_inferior ()->arch ())
&& (inferior_ptid == null_ptid || !target_has_execution ()))
continue;
val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
&hw_breakpoint_error, &hw_bp_details_reported);
if (val)
error_flag = val;
}
if (error_flag)
{
target_terminal::ours_for_output ();
error (("%s"), tmp_error_stream.c_str ());
}
}
/* Used when starting or continuing the program. */
static void
insert_breakpoint_locations (void)
{
int error_flag = 0;
int val = 0;
int disabled_breaks = 0;
int hw_breakpoint_error = 0;
int hw_bp_error_explained_already = 0;
string_file tmp_error_stream;
/* Explicitly mark the warning -- this will only be printed if
there was an error. */
tmp_error_stream.puts ("Warning:\n");
scoped_restore_current_pspace_and_thread restore_pspace_thread;
for (bp_location *bl : all_bp_locations ())
{
if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
continue;
/* There is no point inserting thread-specific breakpoints if
the thread no longer exists. ALL_BP_LOCATIONS bp_location
has BL->OWNER always non-NULL. */
if (bl->owner->thread != -1
&& !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
to select an inferior to insert breakpoint to. In fact, even
if we aren't attached to any process yet, we should still
insert breakpoints. */
if (!gdbarch_has_global_breakpoints (current_inferior ()->arch ())
&& (inferior_ptid == null_ptid || !target_has_execution ()))
continue;
val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
&hw_breakpoint_error, &hw_bp_error_explained_already);
if (val)
error_flag = val;
}
/* 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 ())
{
bool some_failed = false;
if (!is_hardware_watchpoint (&bpt))
continue;
if (!breakpoint_enabled (&bpt))
continue;
if (bpt.disposition == disp_del_at_next_stop)
continue;
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);
hw_breakpoint_error = 1;
tmp_error_stream.printf ("Could not insert "
"hardware watchpoint %d.\n",
bpt.number);
error_flag = -1;
}
}
if (error_flag)
{
/* If a hardware breakpoint or watchpoint was inserted, add a
message about possibly exhausted resources. */
if (hw_breakpoint_error && !hw_bp_error_explained_already)
{
tmp_error_stream.printf ("Could not insert hardware breakpoints:\n\
You may have requested too many hardware breakpoints/watchpoints.\n");
}
target_terminal::ours_for_output ();
error (("%s"), tmp_error_stream.c_str ());
}
}
/* Used when the program stops.
Returns zero if successful, or non-zero if there was a problem
removing a breakpoint location. */
int
remove_breakpoints (void)
{
int val = 0;
for (bp_location *bl : all_bp_locations ())
if (bl->inserted && !is_tracepoint (bl->owner))
val |= remove_breakpoint (bl);
return val;
}
/* When a thread exits, remove breakpoints that are related to
that thread. */
static void