| /* Everything about breakpoints, for GDB. |
| |
| Copyright (C) 1986-2021 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 "defs.h" |
| #include "arch-utils.h" |
| #include <ctype.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 "gdbcmd.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 "valprint.h" |
| #include "jit.h" |
| #include "parser-defs.h" |
| #include "gdb_regex.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" |
| |
| /* 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 "gdbsupport/gdb_optional.h" |
| |
| /* Prototypes for local functions. */ |
| |
| static void map_breakpoint_numbers (const char *, |
| gdb::function_view<void (breakpoint *)>); |
| |
| static void breakpoint_re_set_default (struct breakpoint *); |
| |
| static void |
| create_sals_from_location_default (struct event_location *location, |
| struct linespec_result *canonical, |
| enum bptype type_wanted); |
| |
| static void create_breakpoints_sal_default (struct gdbarch *, |
| struct linespec_result *, |
| gdb::unique_xmalloc_ptr<char>, |
| gdb::unique_xmalloc_ptr<char>, |
| enum bptype, |
| enum bpdisp, int, int, |
| int, |
| const struct breakpoint_ops *, |
| int, int, int, unsigned); |
| |
| static std::vector<symtab_and_line> decode_location_default |
| (struct breakpoint *b, struct event_location *location, |
| struct program_space *search_pspace); |
| |
| static int can_use_hardware_watchpoint |
| (const std::vector<value_ref_ptr> &vals); |
| |
| static void mention (struct breakpoint *); |
| |
| static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *, |
| enum bptype, |
| const struct breakpoint_ops *); |
| static struct bp_location *add_location_to_breakpoint (struct breakpoint *, |
| const struct symtab_and_line *); |
| |
| /* This function is used in gdbtk sources and thus can not be made |
| static. */ |
| struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch, |
| struct symtab_and_line, |
| enum bptype, |
| const struct breakpoint_ops *); |
| |
| static struct breakpoint * |
| momentary_breakpoint_from_master (struct breakpoint *orig, |
| enum bptype type, |
| const struct breakpoint_ops *ops, |
| int loc_enabled); |
| |
| static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int); |
| |
| static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch, |
| CORE_ADDR bpaddr, |
| enum bptype bptype); |
| |
| static void describe_other_breakpoints (struct gdbarch *, |
| struct program_space *, CORE_ADDR, |
| struct obj_section *, int); |
| |
| static int watchpoint_locations_match (struct bp_location *loc1, |
| struct bp_location *loc2); |
| |
| static int breakpoint_locations_match (struct bp_location *loc1, |
| struct bp_location *loc2, |
| bool sw_hw_bps_match = false); |
| |
| static int breakpoint_location_address_match (struct bp_location *bl, |
| const struct address_space *aspace, |
| CORE_ADDR addr); |
| |
| static int 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 struct bp_location *allocate_bp_location (struct breakpoint *bpt); |
| |
| /* 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 |
| }; |
| |
| 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 1 if B refers to a static tracepoint set by marker ("-m"), zero |
| otherwise. */ |
| |
| static int strace_marker_p (struct breakpoint *b); |
| |
| /* The breakpoint_ops structure to be inherited by all breakpoint_ops |
| that are implemented on top of software or hardware breakpoints |
| (user breakpoints, internal and momentary breakpoints, etc.). */ |
| static struct breakpoint_ops bkpt_base_breakpoint_ops; |
| |
| /* Internal breakpoints class type. */ |
| static struct breakpoint_ops internal_breakpoint_ops; |
| |
| /* Momentary breakpoints class type. */ |
| static struct breakpoint_ops momentary_breakpoint_ops; |
| |
| /* The breakpoint_ops structure to be used in regular user created |
| breakpoints. */ |
| struct breakpoint_ops bkpt_breakpoint_ops; |
| |
| /* Breakpoints set on probes. */ |
| static struct breakpoint_ops bkpt_probe_breakpoint_ops; |
| |
| /* Tracepoints set on probes. */ |
| static struct breakpoint_ops tracepoint_probe_breakpoint_ops; |
| |
| /* Dynamic printf class type. */ |
| struct breakpoint_ops dprintf_breakpoint_ops; |
| |
| /* 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) |
| { |
| fprintf_filtered (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) |
| { |
| fprintf_filtered (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) |
| { |
| fprintf_filtered (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) |
| { |
| fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), |
| value); |
| } |
| |
| /* See breakpoint.h. */ |
| |
| int |
| breakpoints_should_be_inserted_now (void) |
| { |
| if (gdbarch_has_global_breakpoints (target_gdbarch ())) |
| { |
| /* 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 int |
| 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; |
| |
| /* Walk the following statement or block through all breakpoints. |
| ALL_BREAKPOINTS_SAFE does so even if the statement deletes the |
| current breakpoint. */ |
| |
| #define ALL_BREAKPOINTS_SAFE(B,TMP) \ |
| for (B = breakpoint_chain; \ |
| B ? (TMP=B->next, 1): 0; \ |
| B = TMP) |
| |
| /* Chains of all breakpoints defined. */ |
| |
| static struct breakpoint *breakpoint_chain; |
| |
| /* See breakpoint.h. */ |
| |
| breakpoint_range |
| all_breakpoints () |
| { |
| return breakpoint_range (breakpoint_chain); |
| } |
| |
| /* 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 (breakpoint_chain); |
| } |
| |
| /* 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 int |
| 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; |
| } |
| |
| |
| |
| /* 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) |
| fprintf_filtered (file, |
| _("Breakpoint condition evaluation " |
| "mode is %s (currently %s).\n"), |
| value, |
| breakpoint_condition_evaluation_mode ()); |
| else |
| fprintf_filtered (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) |
| printf_filtered (_("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); |
| } |
| |
| void |
| set_breakpoint_condition (struct breakpoint *b, const char *exp, |
| int from_tty, bool force) |
| { |
| if (*exp == 0) |
| { |
| xfree (b->cond_string); |
| b->cond_string = nullptr; |
| |
| if (is_watchpoint (b)) |
| 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) |
| printf_filtered (_("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) |
| printf_filtered (_("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 = 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 (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->next == nullptr && !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. */ |
| xfree (b->cond_string); |
| b->cond_string = xstrdup (exp); |
| b->condition_not_parsed = 0; |
| } |
| mark_breakpoint_modified (b); |
| |
| gdb::observers::breakpoint_modified.notify (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 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); |
| } |
| |
| static bool |
| is_longjmp_type (bptype type) |
| { |
| return type == bp_longjmp || type == bp_exception; |
| } |
| |
| /* 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. */ |
| |
| static std::unique_ptr<breakpoint> |
| new_breakpoint_from_type (bptype type) |
| { |
| breakpoint *b; |
| |
| if (is_tracepoint_type (type)) |
| b = new tracepoint (); |
| else if (is_longjmp_type (type)) |
| b = new longjmp_breakpoint (); |
| else |
| b = new breakpoint (); |
| |
| return std::unique_ptr<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)) |
| { |
| struct tracepoint *t = (struct 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) |
| 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, b); |
| } |
| 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) |
| { |
| 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); |
| gdb::observers::breakpoint_modified.notify (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) |
| gdb::observers::breakpoint_modified.notify (b); |
| } |
| |
| /* Set the thread for this breakpoint. If THREAD is -1, make the |
| breakpoint work for any thread. */ |
| |
| void |
| breakpoint_set_thread (struct breakpoint *b, int thread) |
| { |
| int old_thread = b->thread; |
| |
| b->thread = thread; |
| if (old_thread != thread) |
| gdb::observers::breakpoint_modified.notify (b); |
| } |
| |
| /* Set the task for this breakpoint. If TASK is 0, make the |
| breakpoint work for any task. */ |
| |
| void |
| breakpoint_set_task (struct breakpoint *b, int task) |
| { |
| int old_task = b->task; |
| |
| b->task = task; |
| if (old_task != task) |
| gdb::observers::breakpoint_modified.notify (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) |
| { |
| validate_actionline (line, b); |
| }; |
| 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; |
| gdb::observers::breakpoint_modified.notify (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 non-zero if BL->TARGET_INFO contains valid information. */ |
| |
| static int |
| bp_location_has_shadow (struct bp_location *bl) |
| { |
| if (bl->loc_type != bp_loc_software_breakpoint) |
| return 0; |
| if (!bl->inserted) |
| return 0; |
| if (bl->target_info.shadow_len == 0) |
| /* BL isn't valid, or doesn't shadow memory. */ |
| return 0; |
| return 1; |
| } |
| |
| /* 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, 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 int |
| 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; |
| } |
| |
| /* 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 = allocate_value (value_type (val)); |
| |
| unpack_value_bitfield (bit_val, |
| w->val_bitpos, |
| w->val_bitsize, |
| value_contents_for_printing (val), |
| value_offset (val), |
| val); |
| |
| return bit_val; |
| } |
| |
| /* Allocate a dummy location and add it to B, which must be a software |
| watchpoint. This is required because even if a software watchpoint |
| is not watching any memory, bpstat_stop_status requires a location |
| to be able to report stops. */ |
| |
| static void |
| software_watchpoint_add_no_memory_location (struct breakpoint *b, |
| struct program_space *pspace) |
| { |
| gdb_assert (b->type == bp_watchpoint && b->loc == NULL); |
| |
| b->loc = allocate_bp_location (b); |
| b->loc->pspace = pspace; |
| b->loc->address = -1; |
| b->loc->length = -1; |
| } |
| |
| /* Returns true if B is a software watchpoint that is not watching any |
| memory (e.g., "watch $pc"). */ |
| |
| static bool |
| is_no_memory_software_watchpoint (struct breakpoint *b) |
| { |
| return (b->type == bp_watchpoint |
| && b->loc != NULL |
| && b->loc->next == NULL |
| && b->loc->address == -1 |
| && b->loc->length == -1); |
| } |
| |
| /* Assuming that B is a watchpoint: |
| - Reparse watchpoint expression, if REPARSE is non-zero |
| - 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, int reparse) |
| { |
| int within_current_scope; |
| struct frame_id saved_frame_id; |
| int frame_saved; |
| |
| /* 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; |
| |
| frame_saved = 0; |
| |
| /* Determine if the watchpoint is within scope. */ |
| if (b->exp_valid_block == NULL) |
| within_current_scope = 1; |
| else |
| { |
| struct frame_info *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. */ |
| frame_saved = 1; |
| saved_frame_id = get_frame_id (get_selected_frame (NULL)); |
| |
| 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->loc = NULL; |
| |
| if (within_current_scope && reparse) |
| { |
| const char *s; |
| |
| b->exp.reset (); |
| s = b->exp_string_reparse ? b->exp_string_reparse : b->exp_string; |
| 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; |
| 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->ops->works_in_software_mode (b)) |
| 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 *frame_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; |
| } |
| |
| frame_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 (VALUE_LVAL (v) == lval_memory |
| && (v == val_chain[0] || ! value_lazy (v))) |
| { |
| struct type *vtype = check_typedef (value_type (v)); |
| |
| /* 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; |
| struct bp_location *loc, **tmp; |
| int bitpos = 0, bitsize = 0; |
| |
| if (value_bitsize (v) != 0) |
| { |
| /* Extract the bit parameters out from the bitfield |
| sub-expression. */ |
| bitpos = value_bitpos (v); |
| bitsize = value_bitsize (v); |
| } |
| 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 = value_address (v); |
| 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; |
| |
| loc = allocate_bp_location (b); |
| for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next)) |
| ; |
| *tmp = loc; |
| loc->gdbarch = value_type (v)->arch (); |
| |
| loc->pspace = frame_pspace; |
| loc->address = address_significant (loc->gdbarch, addr); |
| |
| if (bitsize != 0) |
| { |
| /* Just cover the bytes that make up the bitfield. */ |
| loc->length = ((bitpos % 8) + bitsize + 7) / 8; |
| } |
| else |
| loc->length = TYPE_LENGTH (value_type (v)); |
| |
| loc->watchpoint_type = type; |
| } |
| } |
| } |
| |
| /* Change the type of breakpoint between hardware assisted or |
| an ordinary watchpoint depending on the hardware support |
| and free hardware slots. REPARSE is set when the inferior |
| is started. */ |
| if (reparse) |
| { |
| 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) |
| { |
| int sw_mode = b->ops->works_in_software_mode (b); |
| |
| 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. */ |
| b->type = bp_watchpoint; |
| } |
| 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->ops->works_in_software_mode (b)) |
| { |
| 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 |
| b->type = bp_watchpoint; |
| |
| loc_type = (b->type == bp_watchpoint? bp_loc_other |
| : 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->loc == NULL) |
| software_watchpoint_add_no_memory_location (b, frame_pspace); |
| } |
| else if (!within_current_scope) |
| { |
| printf_filtered (_("\ |
| 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); |
| } |
| |
| /* Restore the selected frame. */ |
| if (frame_saved) |
| select_frame (frame_find_by_id (saved_frame_id)); |
| } |
| |
| |
| /* Returns 1 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 int |
| should_be_inserted (struct bp_location *bl) |
| { |
| if (bl->owner == NULL || !breakpoint_enabled (bl->owner)) |
| return 0; |
| |
| if (bl->owner->disposition == disp_del_at_next_stop) |
| return 0; |
| |
| if (!bl->enabled || bl->disabled_by_cond |
| || bl->shlib_disabled || bl->duplicate) |
| return 0; |
| |
| if (user_breakpoint_p (bl->owner) && bl->pspace->executing_startup) |
| return 0; |
| |
| /* 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 0; |
| |
| /* 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, |
| 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 0; |
| } |
| |
| /* 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 0; |
| } |
| |
| return 1; |
| } |
| |
| /* Same as should_be_inserted but does the check assuming |
| that the location is not duplicated. */ |
| |
| static int |
| unduplicated_should_be_inserted (struct bp_location *bl) |
| { |
| int result; |
| const int save_duplicate = bl->duplicate; |
| |
| bl->duplicate = 0; |
| result = should_be_inserted (bl); |
| bl->duplicate = save_duplicate; |
| return result; |
| } |
| |
| /* 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) |
| { |
| int null_condition_or_parse_error = 0; |
| 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 = 1; |
| 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 marge 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), 1); |
| 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) |
| { |
| int null_command_or_parse_error = 0; |
| 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); |
| } |
| |
| /* 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 = 1; |
| 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 (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); |
| } |
| |
| /* 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; |
| |
| /* 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; |
| 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) |
| { |
| fprintf_unfiltered (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->ops->insert_location (bl); |
| if (val) |
| bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR}; |
| } |
| catch (gdb_exception &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) |
| { |
| bp_excpt = std::move (e); |
| } |
| |
| if (bp_excpt.reason != 0) |
| fprintf_unfiltered (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->ops->insert_location (bl); |
| if (val) |
| bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR}; |
| } |
| catch (gdb_exception &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. */ |
| |
| /* 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. */ |
| if (bp_excpt.error == TARGET_CLOSE_ERROR) |
| throw bp_excpt; |
| 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; |
| gdb::observers::breakpoint_modified.notify (bl->owner); |
| if (!*disabled_breaks) |
| { |
| fprintf_unfiltered (tmp_error_stream, |
| "Cannot insert breakpoint %d.\n", |
| bl->owner->number); |
| fprintf_unfiltered (tmp_error_stream, |
| "Temporarily disabling shared " |
| "library breakpoints:\n"); |
| } |
| *disabled_breaks = 1; |
| fprintf_unfiltered (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; |
| fprintf_unfiltered (tmp_error_stream, |
| "Cannot insert hardware breakpoint %d%s", |
| bl->owner->number, |
| bp_excpt.message ? ":" : ".\n"); |
| if (bp_excpt.message != NULL) |
| fprintf_unfiltered (tmp_error_stream, "%s.\n", |
| bp_excpt.what ()); |
| } |
| else |
| { |
| if (bp_excpt.message == NULL) |
| { |
| std::string message |
| = memory_error_message (TARGET_XFER_E_IO, |
| bl->gdbarch, bl->address); |
| |
| fprintf_unfiltered (tmp_error_stream, |
| "Cannot insert breakpoint %d.\n" |
| "%s\n", |
| bl->owner->number, message.c_str ()); |
| } |
| else |
| { |
| fprintf_unfiltered (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 |
| /* NOTE drow/2003-09-08: This state only exists for removing |
| watchpoints. It's not clear that it's necessary... */ |
| && bl->owner->disposition != disp_del_at_next_stop) |
| { |
| int val; |
| |
| gdb_assert (bl->owner->ops != NULL |
| && bl->owner->ops->insert_location != NULL); |
| |
| val = bl->owner->ops->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->ops->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; |
| |
| gdb_assert (bl->owner->ops != NULL |
| && bl->owner->ops->insert_location != NULL); |
| |
| val = bl->owner->ops->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 ()) |
| { |
| struct bp_location *tmp; |
| |
| if (loc->pspace == pspace) |
| { |
| /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */ |
| if (loc->owner->loc == loc) |
| loc->owner->loc = loc->next; |
| else |
| for (tmp = loc->owner->loc; tmp->next != NULL; tmp = tmp->next) |
| if (tmp->next == loc) |
| { |
| tmp->next = loc->next; |
| break; |
| } |
| } |
| } |
| |
| /* 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)) |
| { |
| struct watchpoint *w = (struct watchpoint *) bpt; |
| |
| update_watchpoint (w, 0 /* 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 (target_gdbarch ()) |
| && (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_stream (tmp_error_stream); |
| } |
| } |
| |
| /* 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; |
| |
| 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 (target_gdbarch ()) |
| && (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 ()) |
| { |
| int some_failed = 0; |
| |
| 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 = 1; |
| 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_stream (tmp_error_stream); |
| } |
| } |
| |
| /* 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 |
| remove_threaded_breakpoints (struct thread_info *tp, int silent) |
| { |
| for (breakpoint *b : all_breakpoints_safe ()) |
| { |
| if (b->thread == tp->global_num && user_breakpoint_p (b)) |
| { |
| b->disposition = disp_del_at_next_stop; |
| |
| printf_filtered (_("\ |
| Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"), |
| b->number, print_thread_id (tp)); |
| |
| /* Hide it from the user. */ |
| b->number = 0; |
| } |
| } |
| } |
| |
| /* See breakpoint.h. */ |
| |
| void |
| remove_breakpoints_inf (inferior *inf) |
| { |
| int val; |
| |
| for (bp_location *bl : all_bp_locations ()) |
| { |
| if (bl->pspace != inf->pspace) |
| continue; |
| |
| if (bl->inserted && !bl->target_info.persist) |
| { |
| val = remove_breakpoint (bl); |
| if (val != 0) |
| return; |
| } |
| } |
| } |
| |
| static int internal_breakpoint_number = -1; |
| |
| /* Set the breakpoint number of B, depending on the value of INTERNAL. |
| If INTERNAL is non-zero, the breakpoint number will be populated |
| from internal_breakpoint_number and that variable decremented. |
| Otherwise the breakpoint number will be populated from |
| breakpoint_count and that value incremented. Internal breakpoints |
| do not set the internal var bpnum. */ |
| static void |
| set_breakpoint_number (int internal, struct breakpoint *b) |
| { |
| if (internal) |
| b->number = internal_breakpoint_number--; |
| else |
| { |
| set_breakpoint_count (breakpoint_count + 1); |
| b->number = breakpoint_count; |
| } |
| } |
| |
| static struct breakpoint * |
| create_internal_breakpoint (struct gdbarch *gdbarch, |
| CORE_ADDR address, enum bptype type, |
| const struct breakpoint_ops *ops) |
| { |
| symtab_and_line sal; |
| sal.pc = address; |
| sal.section = find_pc_overlay (sal.pc); |
| sal.pspace = current_program_space; |
| |
| breakpoint *b = set_raw_breakpoint (gdbarch, sal, type, ops); |
| b->number = internal_breakpoint_number--; |
| b->disposition = disp_donttouch; |
| |
| return b; |
| } |
| |
| static const char *const longjmp_names[] = |
| { |
| "longjmp", "_longjmp", "siglongjmp", "_siglongjmp" |
| }; |
| #define NUM_LONGJMP_NAMES ARRAY_SIZE(longjmp_names) |
| |
| /* Per-objfile data private to breakpoint.c. */ |
| struct breakpoint_objfile_data |
| { |
| /* Minimal symbol for "_ovly_debug_event" (if any). */ |
| struct bound_minimal_symbol overlay_msym {}; |
| |
| /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */ |
| struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES] {}; |
| |
| /* True if we have looked for longjmp probes. */ |
| int longjmp_searched = 0; |
| |
| /* SystemTap probe points for longjmp (if any). These are non-owning |
| references. */ |
| std::vector<probe *> longjmp_probes; |
| |
| /* Minimal symbol for "std::terminate()" (if any). */ |
| struct bound_minimal_symbol terminate_msym {}; |
| |
| /* Minimal symbol for "_Unwind_DebugHook" (if any). */ |
| struct bound_minimal_symbol exception_msym {}; |
| |
| /* True if we have looked for exception probes. */ |
| int exception_searched = 0; |
| |
| /* SystemTap probe points for unwinding (if any). These are non-owning |
| references. */ |
| std::vector<probe *> exception_probes; |
| }; |
| |
| static const struct objfile_key<breakpoint_objfile_data> |
| breakpoint_objfile_key; |
| |
| /* Minimal symbol not found sentinel. */ |
| static struct minimal_symbol msym_not_found; |
| |
| /* Returns TRUE if MSYM point to the "not found" sentinel. */ |
| |
| static int |
| msym_not_found_p (const struct minimal_symbol *msym) |
| { |
| return msym == &msym_not_found; |
| } |
| |
| /* Return per-objfile data needed by breakpoint.c. |
| Allocate the data if necessary. */ |
| |
| static struct breakpoint_objfile_data * |
| get_breakpoint_objfile_data (struct objfile *objfile) |
| { |
| struct breakpoint_objfile_data *bp_objfile_data; |
| |
| bp_objfile_data = breakpoint_objfile_key.get (objfile); |
| if (bp_objfile_data == NULL) |
| bp_objfile_data = breakpoint_objfile_key.emplace (objfile); |
| return bp_objfile_data; |
| } |
| |
| static void |
| create_overlay_event_breakpoint (void) |
| { |
| const char *const func_name = "_ovly_debug_event"; |
| |
| for (objfile *objfile : current_program_space->objfiles ()) |
| { |
| struct breakpoint *b; |
| struct breakpoint_objfile_data *bp_objfile_data; |
| CORE_ADDR addr; |
| struct explicit_location explicit_loc; |
| |
| bp_objfile_data = get_breakpoint_objfile_data (objfile); |
| |
| if (msym_not_found_p (bp_objfile_data->overlay_msym.minsym)) |
| continue; |
| |
| if (bp_objfile_data->overlay_msym.minsym == NULL) |
| { |
| struct bound_minimal_symbol m; |
| |
| m = lookup_minimal_symbol_text (func_name, objfile); |
| if (m.minsym == NULL) |
| { |
| /* Avoid future lookups in this objfile. */ |
| bp_objfile_data->overlay_msym.minsym = &msym_not_found; |
| continue; |
| } |
| bp_objfile_data->overlay_msym = m; |
| } |
| |
| addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym); |
| b = create_internal_breakpoint (objfile->arch (), addr, |
| bp_overlay_event, |
| &internal_breakpoint_ops); |
| initialize_explicit_location (&explicit_loc); |
| explicit_loc.function_name = ASTRDUP (func_name); |
| b->location = new_explicit_location (&explicit_loc); |
| |
| if (overlay_debugging == ovly_auto) |
| { |
| b->enable_state = bp_enabled; |
| overlay_events_enabled = 1; |
| } |
| else |
| { |
| b->enable_state = bp_disabled; |
| overlay_events_enabled = 0; |
| } |
| } |
| } |
| |
| /* Install a master longjmp breakpoint for OBJFILE using a probe. Return |
| true if a breakpoint was installed. */ |
| |
| static bool |
| create_longjmp_master_breakpoint_probe (objfile *objfile) |
| { |
| struct gdbarch *gdbarch = objfile->arch (); |
| struct breakpoint_objfile_data *bp_objfile_data |
| = get_breakpoint_objfile_data (objfile); |
| |
| if (!bp_objfile_data->longjmp_searched) |
| { |
| std::vector<probe *> ret |
| = find_probes_in_objfile (objfile, "libc", "longjmp"); |
| |
| if (!ret.empty ()) |
| { |
| /* We are only interested in checking one element. */ |
| probe *p = ret[0]; |
| |
| if (!p->can_evaluate_arguments ()) |
| { |
| /* We cannot use the probe interface here, |
| because it does not know how to evaluate |
| arguments. */ |
| ret.clear (); |
| } |
| } |
| bp_objfile_data->longjmp_probes = ret; |
| bp_objfile_data->longjmp_searched = 1; |
| } |
| |
| if (bp_objfile_data->longjmp_probes.empty ()) |
| return false; |
| |
| for (probe *p : bp_objfile_data->longjmp_probes) |
| { |
| struct breakpoint *b; |
| |
| b = create_internal_breakpoint (gdbarch, |
| p->get_relocated_address (objfile), |
| bp_longjmp_master, |
| &internal_breakpoint_ops); |
| b->location = new_probe_location ("-probe-stap libc:longjmp"); |
| b->enable_state = bp_disabled; |
| } |
| |
| return true; |
| } |
| |
| /* Install master longjmp breakpoints for OBJFILE using longjmp_names. |
| Return true if at least one breakpoint was installed. */ |
| |
| static bool |
| create_longjmp_master_breakpoint_names (objfile *objfile) |
| { |
| struct gdbarch *gdbarch = objfile->arch (); |
| if (!gdbarch_get_longjmp_target_p (gdbarch)) |
| return false; |
| |
| struct breakpoint_objfile_data *bp_objfile_data |
| = get_breakpoint_objfile_data (objfile); |
| unsigned int installed_bp = 0; |
| |
| for (int i = 0; i < NUM_LONGJMP_NAMES; i++) |
| { |
| struct breakpoint *b; |
| const char *func_name; |
| CORE_ADDR addr; |
| struct explicit_location explicit_loc; |
| |
| if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym)) |
| continue; |
| |
| func_name = longjmp_names[i]; |
| if (bp_objfile_data->longjmp_msym[i].minsym == NULL) |
| { |
| struct bound_minimal_symbol m; |
| |
| m = lookup_minimal_symbol_text (func_name, objfile); |
| if (m.minsym == NULL) |
| { |
| /* Prevent future lookups in this objfile. */ |
| bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found; |
|