| Index: gdb/breakpoint.c
|
| diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
| index 78fffd34e9eb7233b75c67c29831444210b5617c..111660fce1a090fec4a50628f2e83cab4d11adae 100644
|
| --- a/gdb/breakpoint.c
|
| +++ b/gdb/breakpoint.c
|
| @@ -1,6 +1,6 @@
|
| /* Everything about breakpoints, for GDB.
|
|
|
| - Copyright (C) 1986-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1986-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -35,7 +35,7 @@
|
| #include "gdbthread.h"
|
| #include "target.h"
|
| #include "language.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "gdb-demangle.h"
|
| #include "filenames.h"
|
| #include "annotate.h"
|
| @@ -82,6 +82,14 @@
|
| #include "mi/mi-common.h"
|
| #include "python/python.h"
|
|
|
| +/* Enums for exception-handling support. */
|
| +enum exception_event_kind
|
| +{
|
| + EX_EVENT_THROW,
|
| + EX_EVENT_RETHROW,
|
| + EX_EVENT_CATCH
|
| +};
|
| +
|
| /* Prototypes for local functions. */
|
|
|
| static void enable_delete_command (char *, int);
|
| @@ -111,7 +119,6 @@ static void create_sals_from_address_default (char **,
|
|
|
| static void create_breakpoints_sal_default (struct gdbarch *,
|
| struct linespec_result *,
|
| - struct linespec_sals *,
|
| char *, char *, enum bptype,
|
| enum bpdisp, int, int,
|
| int,
|
| @@ -223,11 +230,6 @@ static void stopin_command (char *arg, int from_tty);
|
|
|
| static void stopat_command (char *arg, int from_tty);
|
|
|
| -static char *ep_parse_optional_if_clause (char **arg);
|
| -
|
| -static void catch_exception_command_1 (enum exception_event_kind ex_event,
|
| - char *arg, int tempflag, int from_tty);
|
| -
|
| static void tcatch_command (char *arg, int from_tty);
|
|
|
| static void detach_single_step_breakpoints (void);
|
| @@ -261,6 +263,8 @@ static void disable_trace_command (char *, int);
|
|
|
| static void trace_pass_command (char *, int);
|
|
|
| +static void set_tracepoint_count (int num);
|
| +
|
| static int is_masked_watchpoint (const struct breakpoint *b);
|
|
|
| static struct bp_location **get_first_locp_gte_addr (CORE_ADDR address);
|
| @@ -270,14 +274,9 @@ static struct bp_location **get_first_locp_gte_addr (CORE_ADDR address);
|
|
|
| static int strace_marker_p (struct breakpoint *b);
|
|
|
| -static void init_catchpoint (struct breakpoint *b,
|
| - struct gdbarch *gdbarch, int tempflag,
|
| - char *cond_string,
|
| - const struct breakpoint_ops *ops);
|
| -
|
| /* The abstract base class all breakpoint_ops structures inherit
|
| from. */
|
| -static struct breakpoint_ops base_breakpoint_ops;
|
| +struct breakpoint_ops base_breakpoint_ops;
|
|
|
| /* The breakpoint_ops structure to be inherited by all breakpoint_ops
|
| that are implemented on top of software or hardware breakpoints
|
| @@ -301,7 +300,7 @@ struct breakpoint_ops bkpt_breakpoint_ops;
|
| static struct breakpoint_ops bkpt_probe_breakpoint_ops;
|
|
|
| /* Dynamic printf class type. */
|
| -static struct breakpoint_ops dprintf_breakpoint_ops;
|
| +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;
|
| @@ -946,7 +945,7 @@ set_breakpoint_condition (struct breakpoint *b, char *exp,
|
| }
|
| else
|
| {
|
| - char *arg = exp;
|
| + const char *arg = exp;
|
|
|
| /* I don't know if it matters whether this is the string the user
|
| typed in or the decompiled expression. */
|
| @@ -981,19 +980,19 @@ set_breakpoint_condition (struct breakpoint *b, char *exp,
|
| }
|
| mark_breakpoint_modified (b);
|
|
|
| - breakpoints_changed ();
|
| observer_notify_breakpoint_modified (b);
|
| }
|
|
|
| /* Completion for the "condition" command. */
|
|
|
| static VEC (char_ptr) *
|
| -condition_completer (struct cmd_list_element *cmd, char *text, char *word)
|
| +condition_completer (struct cmd_list_element *cmd,
|
| + const char *text, const char *word)
|
| {
|
| - char *space;
|
| + const char *space;
|
|
|
| - text = skip_spaces (text);
|
| - space = skip_to_space (text);
|
| + text = skip_spaces_const (text);
|
| + space = skip_to_space_const (text);
|
| if (*space == '\0')
|
| {
|
| int len;
|
| @@ -1012,32 +1011,20 @@ condition_completer (struct cmd_list_element *cmd, char *text, char *word)
|
| len = strlen (text);
|
|
|
| ALL_BREAKPOINTS (b)
|
| - {
|
| - int single = b->loc->next == NULL;
|
| - struct bp_location *loc;
|
| - int count = 1;
|
| -
|
| - for (loc = b->loc; loc; loc = loc->next)
|
| - {
|
| - char location[50];
|
| -
|
| - if (single)
|
| - sprintf (location, "%d", b->number);
|
| - else
|
| - sprintf (location, "%d.%d", b->number, count);
|
| + {
|
| + char number[50];
|
|
|
| - if (strncmp (location, text, len) == 0)
|
| - VEC_safe_push (char_ptr, result, xstrdup (location));
|
| + xsnprintf (number, sizeof (number), "%d", b->number);
|
|
|
| - ++count;
|
| - }
|
| - }
|
| + if (strncmp (number, text, len) == 0)
|
| + VEC_safe_push (char_ptr, result, xstrdup (number));
|
| + }
|
|
|
| return result;
|
| }
|
|
|
| /* We're completing the expression part. */
|
| - text = skip_spaces (space);
|
| + text = skip_spaces_const (space);
|
| return expression_completer (cmd, text, word);
|
| }
|
|
|
| @@ -1137,12 +1124,25 @@ validate_commands_for_breakpoint (struct breakpoint *b,
|
| {
|
| if (is_tracepoint (b))
|
| {
|
| - /* 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 while-stepping's body has
|
| - valid tracing commands excluding nested while-stepping. */
|
| + 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)
|
| @@ -1160,6 +1160,8 @@ validate_commands_for_breakpoint (struct breakpoint *b,
|
| else
|
| while_stepping = c;
|
| }
|
| +
|
| + validate_actionline (c->line, b);
|
| }
|
| if (while_stepping)
|
| {
|
| @@ -1212,7 +1214,6 @@ breakpoint_set_commands (struct breakpoint *b,
|
|
|
| decref_counted_command_line (&b->commands);
|
| b->commands = alloc_counted_command_line (commands);
|
| - breakpoints_changed ();
|
| observer_notify_breakpoint_modified (b);
|
| }
|
|
|
| @@ -1261,7 +1262,7 @@ check_tracepoint_command (char *line, void *closure)
|
| {
|
| struct breakpoint *b = closure;
|
|
|
| - validate_actionline (&line, b);
|
| + validate_actionline (line, b);
|
| }
|
|
|
| /* A structure used to pass information through
|
| @@ -1329,7 +1330,6 @@ do_map_commands_command (struct breakpoint *b, void *data)
|
| incref_counted_command_line (info->cmd);
|
| decref_counted_command_line (&b->commands);
|
| b->commands = info->cmd;
|
| - breakpoints_changed ();
|
| observer_notify_breakpoint_modified (b);
|
| }
|
| }
|
| @@ -1565,7 +1565,7 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
|
| struct gdbarch *gdbarch = bl->gdbarch;
|
| const unsigned char *bp;
|
| CORE_ADDR placed_address = bl->target_info.placed_address;
|
| - unsigned placed_size = bl->target_info.placed_size;
|
| + int placed_size = bl->target_info.placed_size;
|
|
|
| /* Update the shadow with what we want to write to memory. */
|
| memcpy (bl->target_info.shadow_contents + bptoffset,
|
| @@ -1757,7 +1757,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
|
|
| if (within_current_scope && reparse)
|
| {
|
| - char *s;
|
| + const char *s;
|
|
|
| if (b->exp)
|
| {
|
| @@ -1795,11 +1795,19 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
| 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)
|
| + 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->base.ops->works_in_software_mode (&b->base))
|
| + b->base.type = bp_watchpoint;
|
| + else
|
| + error (_("Can't set read/access watchpoint when "
|
| + "hardware watchpoints are disabled."));
|
| + }
|
| }
|
| else if (within_current_scope && b->exp)
|
| {
|
| @@ -1807,7 +1815,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
| struct value *val_chain, *v, *result, *next;
|
| struct program_space *frame_pspace;
|
|
|
| - fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain);
|
| + fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain, 0);
|
|
|
| /* Avoid setting b->val if it's already set. The meaning of
|
| b->val is 'the last value' user saw, and we should update
|
| @@ -1844,11 +1852,10 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
| && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
|
| {
|
| CORE_ADDR addr;
|
| - int len, type;
|
| + int type;
|
| struct bp_location *loc, **tmp;
|
|
|
| addr = value_address (v);
|
| - len = TYPE_LENGTH (value_type (v));
|
| type = hw_write;
|
| if (b->base.type == bp_read_watchpoint)
|
| type = hw_read;
|
| @@ -1863,7 +1870,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
|
|
| loc->pspace = frame_pspace;
|
| loc->address = addr;
|
| - loc->length = len;
|
| + loc->length = TYPE_LENGTH (value_type (v));
|
| loc->watchpoint_type = type;
|
| }
|
| }
|
| @@ -1940,8 +1947,14 @@ update_watchpoint (struct watchpoint *b, int reparse)
|
| }
|
| }
|
| else if (!b->base.ops->works_in_software_mode (&b->base))
|
| - error (_("Expression cannot be implemented with "
|
| - "read/access watchpoint."));
|
| + {
|
| + 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->base.type = bp_watchpoint;
|
|
|
| @@ -2045,7 +2058,6 @@ static struct agent_expr *
|
| parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
|
| {
|
| struct agent_expr *aexpr = NULL;
|
| - struct cleanup *old_chain = NULL;
|
| volatile struct gdb_exception ex;
|
|
|
| if (!cond)
|
| @@ -2084,6 +2096,9 @@ build_target_condition_list (struct bp_location *bl)
|
| int modified = bl->needs_update;
|
| struct bp_location *loc;
|
|
|
| + /* Release conditions left over from a previous insert. */
|
| + VEC_free (agent_expr_p, bl->target_info.conditions);
|
| +
|
| /* This is only meaningful if the target is
|
| evaluating conditions and if the user has
|
| opted for condition evaluation on the target's
|
| @@ -2183,10 +2198,9 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
|
| struct cleanup *old_cleanups = 0;
|
| struct expression *expr, **argvec;
|
| struct agent_expr *aexpr = NULL;
|
| - struct cleanup *old_chain = NULL;
|
| volatile struct gdb_exception ex;
|
| - char *cmdrest;
|
| - char *format_start, *format_end;
|
| + const char *cmdrest;
|
| + const char *format_start, *format_end;
|
| struct format_piece *fpieces;
|
| int nargs;
|
| struct gdbarch *gdbarch = get_current_arch ();
|
| @@ -2198,7 +2212,7 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
|
|
|
| if (*cmdrest == ',')
|
| ++cmdrest;
|
| - cmdrest = skip_spaces (cmdrest);
|
| + cmdrest = skip_spaces_const (cmdrest);
|
|
|
| if (*cmdrest++ != '"')
|
| error (_("No format string following the location"));
|
| @@ -2214,14 +2228,14 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
|
| if (*cmdrest++ != '"')
|
| error (_("Bad format string, non-terminated '\"'."));
|
|
|
| - cmdrest = skip_spaces (cmdrest);
|
| + cmdrest = skip_spaces_const (cmdrest);
|
|
|
| if (!(*cmdrest == ',' || *cmdrest == '\0'))
|
| error (_("Invalid argument syntax"));
|
|
|
| if (*cmdrest == ',')
|
| cmdrest++;
|
| - cmdrest = skip_spaces (cmdrest);
|
| + cmdrest = skip_spaces_const (cmdrest);
|
|
|
| /* For each argument, make an expression. */
|
|
|
| @@ -2231,7 +2245,7 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
|
| nargs = 0;
|
| while (*cmdrest != '\0')
|
| {
|
| - char *cmd1;
|
| + const char *cmd1;
|
|
|
| cmd1 = cmdrest;
|
| expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
|
| @@ -2250,6 +2264,8 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
|
| fpieces, nargs, argvec);
|
| }
|
|
|
| + do_cleanups (old_cleanups);
|
| +
|
| if (ex.reason < 0)
|
| {
|
| /* If we got here, it means the command could not be parsed to a valid
|
| @@ -2258,8 +2274,6 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
|
| return NULL;
|
| }
|
|
|
| - do_cleanups (old_cleanups);
|
| -
|
| /* We have a valid agent expression, return it. */
|
| return aexpr;
|
| }
|
| @@ -2276,6 +2290,9 @@ build_target_command_list (struct bp_location *bl)
|
| int modified = bl->needs_update;
|
| struct bp_location *loc;
|
|
|
| + /* Release commands left over from a previous insert. */
|
| + VEC_free (agent_expr_p, bl->target_info.tcommands);
|
| +
|
| /* For now, limit to agent-style dprintf breakpoints. */
|
| if (bl->owner->type != bp_dprintf
|
| || strcmp (dprintf_style, dprintf_style_agent) != 0)
|
| @@ -2332,11 +2349,11 @@ build_target_command_list (struct bp_location *bl)
|
| {
|
| /* Only go as far as the first NULL bytecode is
|
| located. */
|
| - if (!loc->cond_bytecode)
|
| + if (loc->cmd_bytecode == NULL)
|
| return;
|
|
|
| - free_agent_expr (loc->cond_bytecode);
|
| - loc->cond_bytecode = NULL;
|
| + free_agent_expr (loc->cmd_bytecode);
|
| + loc->cmd_bytecode = NULL;
|
| }
|
| }
|
| }
|
| @@ -2375,9 +2392,12 @@ static int
|
| insert_bp_location (struct bp_location *bl,
|
| struct ui_file *tmp_error_stream,
|
| int *disabled_breaks,
|
| - int *hw_breakpoint_error)
|
| + int *hw_breakpoint_error,
|
| + int *hw_bp_error_explained_already)
|
| {
|
| int val = 0;
|
| + char *hw_bp_err_string = NULL;
|
| + struct gdb_exception e;
|
|
|
| if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
|
| return 0;
|
| @@ -2474,8 +2494,15 @@ insert_bp_location (struct bp_location *bl,
|
| || !(section_is_overlay (bl->section)))
|
| {
|
| /* No overlay handling: just set the breakpoint. */
|
| -
|
| - val = bl->owner->ops->insert_location (bl);
|
| + TRY_CATCH (e, RETURN_MASK_ALL)
|
| + {
|
| + val = bl->owner->ops->insert_location (bl);
|
| + }
|
| + if (e.reason < 0)
|
| + {
|
| + val = 1;
|
| + hw_bp_err_string = (char *) e.message;
|
| + }
|
| }
|
| else
|
| {
|
| @@ -2509,7 +2536,15 @@ insert_bp_location (struct bp_location *bl,
|
| if (section_is_mapped (bl->section))
|
| {
|
| /* Yes. This overlay section is mapped into memory. */
|
| - val = bl->owner->ops->insert_location (bl);
|
| + TRY_CATCH (e, RETURN_MASK_ALL)
|
| + {
|
| + val = bl->owner->ops->insert_location (bl);
|
| + }
|
| + if (e.reason < 0)
|
| + {
|
| + val = 1;
|
| + hw_bp_err_string = (char *) e.message;
|
| + }
|
| }
|
| else
|
| {
|
| @@ -2545,23 +2580,26 @@ insert_bp_location (struct bp_location *bl,
|
| {
|
| if (bl->loc_type == bp_loc_hardware_breakpoint)
|
| {
|
| - *hw_breakpoint_error = 1;
|
| - fprintf_unfiltered (tmp_error_stream,
|
| - "Cannot insert hardware "
|
| - "breakpoint %d.\n",
|
| - bl->owner->number);
|
| + *hw_breakpoint_error = 1;
|
| + *hw_bp_error_explained_already = hw_bp_err_string != NULL;
|
| + fprintf_unfiltered (tmp_error_stream,
|
| + "Cannot insert hardware breakpoint %d%s",
|
| + bl->owner->number, hw_bp_err_string ? ":" : ".\n");
|
| + if (hw_bp_err_string)
|
| + fprintf_unfiltered (tmp_error_stream, "%s.\n", hw_bp_err_string);
|
| }
|
| else
|
| {
|
| + char *message = memory_error_message (TARGET_XFER_E_IO,
|
| + bl->gdbarch, bl->address);
|
| + struct cleanup *old_chain = make_cleanup (xfree, message);
|
| +
|
| fprintf_unfiltered (tmp_error_stream,
|
| - "Cannot insert breakpoint %d.\n",
|
| - bl->owner->number);
|
| - fprintf_filtered (tmp_error_stream,
|
| - "Error accessing memory address ");
|
| - fputs_filtered (paddress (bl->gdbarch, bl->address),
|
| - tmp_error_stream);
|
| - fprintf_filtered (tmp_error_stream, ": %s.\n",
|
| - safe_strerror (val));
|
| + "Cannot insert breakpoint %d.\n"
|
| + "%s\n",
|
| + bl->owner->number, message);
|
| +
|
| + do_cleanups (old_chain);
|
| }
|
|
|
| }
|
| @@ -2741,6 +2779,7 @@ update_inserted_breakpoint_locations (void)
|
| int val = 0;
|
| int disabled_breaks = 0;
|
| int hw_breakpoint_error = 0;
|
| + int hw_bp_details_reported = 0;
|
|
|
| struct ui_file *tmp_error_stream = mem_fileopen ();
|
| struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
|
| @@ -2770,12 +2809,12 @@ update_inserted_breakpoint_locations (void)
|
| 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)
|
| + if (!gdbarch_has_global_breakpoints (target_gdbarch ())
|
| && ptid_equal (inferior_ptid, null_ptid))
|
| continue;
|
|
|
| val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks,
|
| - &hw_breakpoint_error);
|
| + &hw_breakpoint_error, &hw_bp_details_reported);
|
| if (val)
|
| error_flag = val;
|
| }
|
| @@ -2800,6 +2839,7 @@ insert_breakpoint_locations (void)
|
| int val = 0;
|
| int disabled_breaks = 0;
|
| int hw_breakpoint_error = 0;
|
| + int hw_bp_error_explained_already = 0;
|
|
|
| struct ui_file *tmp_error_stream = mem_fileopen ();
|
| struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
|
| @@ -2828,12 +2868,12 @@ insert_breakpoint_locations (void)
|
| 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)
|
| + if (!gdbarch_has_global_breakpoints (target_gdbarch ())
|
| && ptid_equal (inferior_ptid, null_ptid))
|
| continue;
|
|
|
| val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks,
|
| - &hw_breakpoint_error);
|
| + &hw_breakpoint_error, &hw_bp_error_explained_already);
|
| if (val)
|
| error_flag = val;
|
| }
|
| @@ -2878,7 +2918,7 @@ insert_breakpoint_locations (void)
|
| {
|
| /* If a hardware breakpoint or watchpoint was inserted, add a
|
| message about possibly exhausted resources. */
|
| - if (hw_breakpoint_error)
|
| + if (hw_breakpoint_error && !hw_bp_error_explained_already)
|
| {
|
| fprintf_unfiltered (tmp_error_stream,
|
| "Could not insert hardware breakpoints:\n\
|
| @@ -2909,6 +2949,30 @@ remove_breakpoints (void)
|
| 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)
|
| +{
|
| + struct breakpoint *b, *b_tmp;
|
| +
|
| + ALL_BREAKPOINTS_SAFE (b, b_tmp)
|
| + {
|
| + if (b->thread == tp->num && user_breakpoint_p (b))
|
| + {
|
| + b->disposition = disp_del_at_next_stop;
|
| +
|
| + printf_filtered (_("\
|
| +Thread-specific breakpoint %d deleted - thread %d no longer in the thread list.\n"),
|
| + b->number, tp->num);
|
| +
|
| + /* Hide it from the user. */
|
| + b->number = 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| /* Remove breakpoints of process PID. */
|
|
|
| int
|
| @@ -2943,7 +3007,7 @@ reattach_breakpoints (int pid)
|
| struct bp_location *bl, **blp_tmp;
|
| int val;
|
| struct ui_file *tmp_error_stream;
|
| - int dummy1 = 0, dummy2 = 0;
|
| + int dummy1 = 0, dummy2 = 0, dummy3 = 0;
|
| struct inferior *inf;
|
| struct thread_info *tp;
|
|
|
| @@ -2967,7 +3031,7 @@ reattach_breakpoints (int pid)
|
| if (bl->inserted)
|
| {
|
| bl->inserted = 0;
|
| - val = insert_bp_location (bl, tmp_error_stream, &dummy1, &dummy2);
|
| + val = insert_bp_location (bl, tmp_error_stream, &dummy1, &dummy2, &dummy3);
|
| if (val != 0)
|
| {
|
| do_cleanups (old_chain);
|
| @@ -3168,15 +3232,28 @@ create_longjmp_master_breakpoint (void)
|
| struct breakpoint_objfile_data *bp_objfile_data;
|
|
|
| gdbarch = get_objfile_arch (objfile);
|
| - if (!gdbarch_get_longjmp_target_p (gdbarch))
|
| - continue;
|
|
|
| bp_objfile_data = get_breakpoint_objfile_data (objfile);
|
|
|
| if (!bp_objfile_data->longjmp_searched)
|
| {
|
| - bp_objfile_data->longjmp_probes
|
| - = find_probes_in_objfile (objfile, "libc", "longjmp");
|
| + VEC (probe_p) *ret;
|
| +
|
| + ret = find_probes_in_objfile (objfile, "libc", "longjmp");
|
| + if (ret != NULL)
|
| + {
|
| + /* We are only interested in checking one element. */
|
| + struct probe *p = VEC_index (probe_p, ret, 0);
|
| +
|
| + if (!can_evaluate_probe_arguments (p))
|
| + {
|
| + /* We cannot use the probe interface here, because it does
|
| + not know how to evaluate arguments. */
|
| + VEC_free (probe_p, ret);
|
| + ret = NULL;
|
| + }
|
| + }
|
| + bp_objfile_data->longjmp_probes = ret;
|
| bp_objfile_data->longjmp_searched = 1;
|
| }
|
|
|
| @@ -3204,6 +3281,9 @@ create_longjmp_master_breakpoint (void)
|
| continue;
|
| }
|
|
|
| + if (!gdbarch_get_longjmp_target_p (gdbarch))
|
| + continue;
|
| +
|
| for (i = 0; i < NUM_LONGJMP_NAMES; i++)
|
| {
|
| struct breakpoint *b;
|
| @@ -3317,8 +3397,24 @@ create_exception_master_breakpoint (void)
|
| /* We prefer the SystemTap probe point if it exists. */
|
| if (!bp_objfile_data->exception_searched)
|
| {
|
| - bp_objfile_data->exception_probes
|
| - = find_probes_in_objfile (objfile, "libgcc", "unwind");
|
| + VEC (probe_p) *ret;
|
| +
|
| + ret = find_probes_in_objfile (objfile, "libgcc", "unwind");
|
| +
|
| + if (ret != NULL)
|
| + {
|
| + /* We are only interested in checking one element. */
|
| + struct probe *p = VEC_index (probe_p, ret, 0);
|
| +
|
| + if (!can_evaluate_probe_arguments (p))
|
| + {
|
| + /* We cannot use the probe interface here, because it does
|
| + not know how to evaluate arguments. */
|
| + VEC_free (probe_p, ret);
|
| + ret = NULL;
|
| + }
|
| + }
|
| + bp_objfile_data->exception_probes = ret;
|
| bp_objfile_data->exception_searched = 1;
|
| }
|
|
|
| @@ -3500,23 +3596,32 @@ update_breakpoints_after_exec (void)
|
| }
|
|
|
| int
|
| -detach_breakpoints (int pid)
|
| +detach_breakpoints (ptid_t ptid)
|
| {
|
| struct bp_location *bl, **blp_tmp;
|
| int val = 0;
|
| struct cleanup *old_chain = save_inferior_ptid ();
|
| struct inferior *inf = current_inferior ();
|
|
|
| - if (pid == PIDGET (inferior_ptid))
|
| + if (ptid_get_pid (ptid) == ptid_get_pid (inferior_ptid))
|
| error (_("Cannot detach breakpoints of inferior_ptid"));
|
|
|
| /* Set inferior_ptid; remove_breakpoint_1 uses this global. */
|
| - inferior_ptid = pid_to_ptid (pid);
|
| + inferior_ptid = ptid;
|
| ALL_BP_LOCATIONS (bl, blp_tmp)
|
| {
|
| if (bl->pspace != inf->pspace)
|
| continue;
|
|
|
| + /* This function must physically remove breakpoints locations
|
| + from the specified ptid, without modifying the breakpoint
|
| + package's state. Locations of type bp_loc_other are only
|
| + maintained at GDB side. So, there is no need to remove
|
| + these bp_loc_other locations. Moreover, removing these
|
| + would modify the breakpoint package's state. */
|
| + if (bl->loc_type == bp_loc_other)
|
| + continue;
|
| +
|
| if (bl->inserted)
|
| val |= remove_breakpoint_1 (bl, mark_inserted);
|
| }
|
| @@ -3709,7 +3814,7 @@ breakpoint_init_inferior (enum inf_context context)
|
|
|
| /* If breakpoint locations are shared across processes, then there's
|
| nothing to do. */
|
| - if (gdbarch_has_global_breakpoints (target_gdbarch))
|
| + if (gdbarch_has_global_breakpoints (target_gdbarch ()))
|
| return;
|
|
|
| ALL_BP_LOCATIONS (bl, blp_tmp)
|
| @@ -4121,6 +4226,31 @@ bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint)
|
| return NULL;
|
| }
|
|
|
| +/* See breakpoint.h. */
|
| +
|
| +int
|
| +bpstat_explains_signal (bpstat bsp, enum gdb_signal sig)
|
| +{
|
| + for (; bsp != NULL; bsp = bsp->next)
|
| + {
|
| + if (bsp->breakpoint_at == NULL)
|
| + {
|
| + /* A moribund location can never explain a signal other than
|
| + GDB_SIGNAL_TRAP. */
|
| + if (sig == GDB_SIGNAL_TRAP)
|
| + return 1;
|
| + }
|
| + else
|
| + {
|
| + if (bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at,
|
| + sig))
|
| + return 1;
|
| + }
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| /* Put in *NUM the breakpoint number of the first breakpoint we are
|
| stopped at. *BSP upon return is a bpstat which points to the
|
| remaining breakpoints stopped at (but which is not guaranteed to be
|
| @@ -4517,10 +4647,12 @@ bpstat_print (bpstat bs, int kind)
|
| return PRINT_UNKNOWN;
|
| }
|
|
|
| -/* Evaluate the expression EXP and return 1 if value is zero. This is
|
| - used inside a catch_errors to evaluate the breakpoint condition.
|
| +/* Evaluate the expression EXP and return 1 if value is zero.
|
| + This returns the inverse of the condition because it is called
|
| + from catch_errors which returns 0 if an exception happened, and if an
|
| + exception happens we want execution to stop.
|
| The argument is a "struct expression *" that has been cast to a
|
| - "char *" to make it pass through catch_errors. */
|
| + "void *" to make it pass through catch_errors. */
|
|
|
| static int
|
| breakpoint_cond_eval (void *exp)
|
| @@ -4590,7 +4722,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
|
| w->watchpoint_triggered = watch_triggered_unknown;
|
| }
|
|
|
| - return stopped_by_watchpoint;
|
| + return 1;
|
| }
|
|
|
| /* The target could report the data address. Mark watchpoints
|
| @@ -4730,7 +4862,7 @@ watchpoint_check (void *p)
|
| return WP_VALUE_CHANGED;
|
|
|
| mark = value_mark ();
|
| - fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL);
|
| + fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0);
|
|
|
| /* We use value_equal_contents instead of value_equal because
|
| the latter coerces an array to a pointer, thus comparing just
|
| @@ -4967,8 +5099,8 @@ bpstat_check_watchpoint (bpstat bs)
|
| }
|
| }
|
|
|
| -
|
| -/* Check conditions (condition proper, frame, thread and ignore count)
|
| +/* For breakpoints that are currently marked as telling gdb to stop,
|
| + check conditions (condition proper, frame, thread and ignore count)
|
| of breakpoint referred to by BS. If we should not stop for this
|
| breakpoint, set BS->stop to 0. */
|
|
|
| @@ -4978,6 +5110,10 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
|
| int thread_id = pid_to_thread_id (ptid);
|
| const struct bp_location *bl;
|
| struct breakpoint *b;
|
| + int value_is_zero = 0;
|
| + struct expression *cond;
|
| +
|
| + gdb_assert (bs->stop);
|
|
|
| /* BS is built for existing struct breakpoint. */
|
| bl = bs->bp_location_at;
|
| @@ -4991,110 +5127,110 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
|
|
|
| if (frame_id_p (b->frame_id)
|
| && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
|
| - bs->stop = 0;
|
| - else if (bs->stop)
|
| {
|
| - int value_is_zero = 0;
|
| - struct expression *cond;
|
| + bs->stop = 0;
|
| + return;
|
| + }
|
|
|
| - /* Evaluate Python breakpoints that have a "stop"
|
| - method implemented. */
|
| - if (b->py_bp_object)
|
| - bs->stop = gdbpy_should_stop (b->py_bp_object);
|
| + /* If this is a thread-specific breakpoint, don't waste cpu evaluating the
|
| + condition if this isn't the specified thread. */
|
| + if (b->thread != -1 && b->thread != thread_id)
|
| + {
|
| + bs->stop = 0;
|
| + return;
|
| + }
|
|
|
| - if (is_watchpoint (b))
|
| - {
|
| - struct watchpoint *w = (struct watchpoint *) b;
|
| + /* Evaluate Python breakpoints that have a "stop" method implemented. */
|
| + if (b->py_bp_object)
|
| + bs->stop = gdbpy_should_stop (b->py_bp_object);
|
|
|
| - cond = w->cond_exp;
|
| - }
|
| + if (is_watchpoint (b))
|
| + {
|
| + struct watchpoint *w = (struct watchpoint *) b;
|
| +
|
| + cond = w->cond_exp;
|
| + }
|
| + else
|
| + cond = bl->cond;
|
| +
|
| + if (cond && b->disposition != disp_del_at_next_stop)
|
| + {
|
| + int within_current_scope = 1;
|
| + struct watchpoint * w;
|
| +
|
| + /* We use value_mark and value_free_to_mark because it could
|
| + be a long time before we return to the command level and
|
| + call free_all_values. We can't call free_all_values
|
| + because we might be in the middle of evaluating a
|
| + function call. */
|
| + struct value *mark = value_mark ();
|
| +
|
| + if (is_watchpoint (b))
|
| + w = (struct watchpoint *) b;
|
| else
|
| - cond = bl->cond;
|
| + w = NULL;
|
|
|
| - if (cond && b->disposition != disp_del_at_next_stop)
|
| + /* Need to select the frame, with all that implies so that
|
| + the conditions will have the right context. Because we
|
| + use the frame, we will not see an inlined function's
|
| + variables when we arrive at a breakpoint at the start
|
| + of the inlined function; the current frame will be the
|
| + call site. */
|
| + if (w == NULL || w->cond_exp_valid_block == NULL)
|
| + select_frame (get_current_frame ());
|
| + else
|
| {
|
| - int within_current_scope = 1;
|
| - struct watchpoint * w;
|
| -
|
| - /* We use value_mark and value_free_to_mark because it could
|
| - be a long time before we return to the command level and
|
| - call free_all_values. We can't call free_all_values
|
| - because we might be in the middle of evaluating a
|
| - function call. */
|
| - struct value *mark = value_mark ();
|
| -
|
| - if (is_watchpoint (b))
|
| - w = (struct watchpoint *) b;
|
| + struct frame_info *frame;
|
| +
|
| + /* For local watchpoint expressions, which particular
|
| + instance of a local is being watched matters, so we
|
| + keep track of the frame to evaluate the expression
|
| + in. To evaluate the condition however, it doesn't
|
| + really matter which instantiation of the function
|
| + where the condition makes sense triggers the
|
| + watchpoint. This allows an expression like "watch
|
| + global if q > 10" set in `func', catch writes to
|
| + global on all threads that call `func', or catch
|
| + writes on all recursive calls of `func' by a single
|
| + thread. We simply always evaluate the condition in
|
| + the innermost frame that's executing where it makes
|
| + sense to evaluate the condition. It seems
|
| + intuitive. */
|
| + frame = block_innermost_frame (w->cond_exp_valid_block);
|
| + if (frame != NULL)
|
| + select_frame (frame);
|
| else
|
| - w = NULL;
|
| -
|
| - /* Need to select the frame, with all that implies so that
|
| - the conditions will have the right context. Because we
|
| - use the frame, we will not see an inlined function's
|
| - variables when we arrive at a breakpoint at the start
|
| - of the inlined function; the current frame will be the
|
| - call site. */
|
| - if (w == NULL || w->cond_exp_valid_block == NULL)
|
| - select_frame (get_current_frame ());
|
| - else
|
| - {
|
| - struct frame_info *frame;
|
| -
|
| - /* For local watchpoint expressions, which particular
|
| - instance of a local is being watched matters, so we
|
| - keep track of the frame to evaluate the expression
|
| - in. To evaluate the condition however, it doesn't
|
| - really matter which instantiation of the function
|
| - where the condition makes sense triggers the
|
| - watchpoint. This allows an expression like "watch
|
| - global if q > 10" set in `func', catch writes to
|
| - global on all threads that call `func', or catch
|
| - writes on all recursive calls of `func' by a single
|
| - thread. We simply always evaluate the condition in
|
| - the innermost frame that's executing where it makes
|
| - sense to evaluate the condition. It seems
|
| - intuitive. */
|
| - frame = block_innermost_frame (w->cond_exp_valid_block);
|
| - if (frame != NULL)
|
| - select_frame (frame);
|
| - else
|
| - within_current_scope = 0;
|
| - }
|
| - if (within_current_scope)
|
| - value_is_zero
|
| - = catch_errors (breakpoint_cond_eval, cond,
|
| - "Error in testing breakpoint condition:\n",
|
| - RETURN_MASK_ALL);
|
| - else
|
| - {
|
| - warning (_("Watchpoint condition cannot be tested "
|
| - "in the current scope"));
|
| - /* If we failed to set the right context for this
|
| - watchpoint, unconditionally report it. */
|
| - value_is_zero = 0;
|
| - }
|
| - /* FIXME-someday, should give breakpoint #. */
|
| - value_free_to_mark (mark);
|
| - }
|
| -
|
| - if (cond && value_is_zero)
|
| - {
|
| - bs->stop = 0;
|
| + within_current_scope = 0;
|
| }
|
| - else if (b->thread != -1 && b->thread != thread_id)
|
| + if (within_current_scope)
|
| + value_is_zero
|
| + = catch_errors (breakpoint_cond_eval, cond,
|
| + "Error in testing breakpoint condition:\n",
|
| + RETURN_MASK_ALL);
|
| + else
|
| {
|
| - bs->stop = 0;
|
| + warning (_("Watchpoint condition cannot be tested "
|
| + "in the current scope"));
|
| + /* If we failed to set the right context for this
|
| + watchpoint, unconditionally report it. */
|
| + value_is_zero = 0;
|
| }
|
| - else if (b->ignore_count > 0)
|
| - {
|
| - b->ignore_count--;
|
| - annotate_ignore_count_change ();
|
| - bs->stop = 0;
|
| - /* Increase the hit count even though we don't stop. */
|
| - ++(b->hit_count);
|
| - observer_notify_breakpoint_modified (b);
|
| - }
|
| + /* FIXME-someday, should give breakpoint #. */
|
| + value_free_to_mark (mark);
|
| + }
|
| +
|
| + if (cond && value_is_zero)
|
| + {
|
| + bs->stop = 0;
|
| }
|
| + else if (b->ignore_count > 0)
|
| + {
|
| + b->ignore_count--;
|
| + bs->stop = 0;
|
| + /* Increase the hit count even though we don't stop. */
|
| + ++(b->hit_count);
|
| + observer_notify_breakpoint_modified (b);
|
| + }
|
| }
|
|
|
|
|
| @@ -5154,7 +5290,7 @@ bpstat_stop_status (struct address_space *aspace,
|
| if (b->type == bp_hardware_watchpoint && bl != b->loc)
|
| break;
|
|
|
| - if (bl->shlib_disabled)
|
| + if (!bl->enabled || bl->shlib_disabled)
|
| continue;
|
|
|
| if (!bpstat_check_location (bl, aspace, bp_addr, ws))
|
| @@ -5248,6 +5384,8 @@ bpstat_stop_status (struct address_space *aspace,
|
| if (command_line_is_silent (bs->commands
|
| ? bs->commands->commands : NULL))
|
| bs->print = 0;
|
| +
|
| + b->ops->after_condition_true (bs);
|
| }
|
|
|
| }
|
| @@ -5301,25 +5439,6 @@ handle_jit_event (void)
|
| target_terminal_inferior ();
|
| }
|
|
|
| -/* Handle an solib event by calling solib_add. */
|
| -
|
| -void
|
| -handle_solib_event (void)
|
| -{
|
| - clear_program_space_solib_cache (current_inferior ()->pspace);
|
| -
|
| - /* Check for any newly added shared libraries if we're supposed to
|
| - be adding them automatically. Switch terminal for any messages
|
| - produced by breakpoint_re_set. */
|
| - target_terminal_ours_for_output ();
|
| -#ifdef SOLIB_ADD
|
| - SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
|
| -#else
|
| - solib_add (NULL, 0, ¤t_target, auto_solib_add);
|
| -#endif
|
| - target_terminal_inferior ();
|
| -}
|
| -
|
| /* Prepare WHAT final decision for infrun. */
|
|
|
| /* Decide what infrun needs to do with this bpstat. */
|
| @@ -5474,7 +5593,10 @@ bpstat_what (bpstat bs_head)
|
| break;
|
|
|
| case bp_dprintf:
|
| - this_action = BPSTAT_WHAT_STOP_SILENT;
|
| + if (bs->stop)
|
| + this_action = BPSTAT_WHAT_STOP_SILENT;
|
| + else
|
| + this_action = BPSTAT_WHAT_SINGLE;
|
| break;
|
|
|
| default:
|
| @@ -5649,7 +5771,7 @@ print_breakpoint_location (struct breakpoint *b,
|
|
|
| if (b->display_canonical)
|
| ui_out_field_string (uiout, "what", b->addr_string);
|
| - else if (loc && loc->source_file)
|
| + else if (loc && loc->symtab)
|
| {
|
| struct symbol *sym
|
| = find_pc_sect_function (loc->address, loc->section);
|
| @@ -5662,17 +5784,13 @@ print_breakpoint_location (struct breakpoint *b,
|
| ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what"));
|
| ui_out_text (uiout, "at ");
|
| }
|
| - ui_out_field_string (uiout, "file", loc->source_file);
|
| + ui_out_field_string (uiout, "file",
|
| + symtab_to_filename_for_display (loc->symtab));
|
| ui_out_text (uiout, ":");
|
| -
|
| +
|
| if (ui_out_is_mi_like_p (uiout))
|
| - {
|
| - struct symtab_and_line sal = find_pc_line (loc->address, 0);
|
| - char *fullname = symtab_to_fullname (sal.symtab);
|
| -
|
| - if (fullname)
|
| - ui_out_field_string (uiout, "fullname", fullname);
|
| - }
|
| + ui_out_field_string (uiout, "fullname",
|
| + symtab_to_fullname (loc->symtab));
|
|
|
| ui_out_field_int (uiout, "line", loc->line_number);
|
| }
|
| @@ -5757,6 +5875,50 @@ bptype_string (enum bptype type)
|
| return bptypes[(int) type].description;
|
| }
|
|
|
| +/* For MI, output a field named 'thread-groups' with a list as the value.
|
| + For CLI, prefix the list with the string 'inf'. */
|
| +
|
| +static void
|
| +output_thread_groups (struct ui_out *uiout,
|
| + const char *field_name,
|
| + VEC(int) *inf_num,
|
| + int mi_only)
|
| +{
|
| + struct cleanup *back_to;
|
| + int is_mi = ui_out_is_mi_like_p (uiout);
|
| + int inf;
|
| + int i;
|
| +
|
| + /* For backward compatibility, don't display inferiors in CLI unless
|
| + there are several. Always display them for MI. */
|
| + if (!is_mi && mi_only)
|
| + return;
|
| +
|
| + back_to = make_cleanup_ui_out_list_begin_end (uiout, field_name);
|
| +
|
| + for (i = 0; VEC_iterate (int, inf_num, i, inf); ++i)
|
| + {
|
| + if (is_mi)
|
| + {
|
| + char mi_group[10];
|
| +
|
| + xsnprintf (mi_group, sizeof (mi_group), "i%d", inf);
|
| + ui_out_field_string (uiout, NULL, mi_group);
|
| + }
|
| + else
|
| + {
|
| + if (i == 0)
|
| + ui_out_text (uiout, " inf ");
|
| + else
|
| + ui_out_text (uiout, ", ");
|
| +
|
| + ui_out_text (uiout, plongest (inf));
|
| + }
|
| + }
|
| +
|
| + do_cleanups (back_to);
|
| +}
|
| +
|
| /* Print B to gdb_stdout. */
|
|
|
| static void
|
| @@ -5908,35 +6070,30 @@ print_one_breakpoint_location (struct breakpoint *b,
|
| }
|
|
|
|
|
| - /* For backward compatibility, don't display inferiors unless there
|
| - are several. */
|
| - if (loc != NULL
|
| - && !header_of_multiple
|
| - && (allflag
|
| - || (!gdbarch_has_global_breakpoints (target_gdbarch)
|
| - && (number_of_program_spaces () > 1
|
| - || number_of_inferiors () > 1)
|
| - /* LOC is for existing B, it cannot be in
|
| - moribund_locations and thus having NULL OWNER. */
|
| - && loc->owner->type != bp_catchpoint)))
|
| + if (loc != NULL && !header_of_multiple)
|
| {
|
| struct inferior *inf;
|
| - int first = 1;
|
| + VEC(int) *inf_num = NULL;
|
| + int mi_only = 1;
|
|
|
| - for (inf = inferior_list; inf != NULL; inf = inf->next)
|
| + ALL_INFERIORS (inf)
|
| {
|
| if (inf->pspace == loc->pspace)
|
| - {
|
| - if (first)
|
| - {
|
| - first = 0;
|
| - ui_out_text (uiout, " inf ");
|
| - }
|
| - else
|
| - ui_out_text (uiout, ", ");
|
| - ui_out_text (uiout, plongest (inf->num));
|
| - }
|
| + VEC_safe_push (int, inf_num, inf->num);
|
| }
|
| +
|
| + /* For backward compatibility, don't display inferiors in CLI unless
|
| + there are several. Always display for MI. */
|
| + if (allflag
|
| + || (!gdbarch_has_global_breakpoints (target_gdbarch ())
|
| + && (number_of_program_spaces () > 1
|
| + || number_of_inferiors () > 1)
|
| + /* LOC is for existing B, it cannot be in
|
| + moribund_locations and thus having NULL OWNER. */
|
| + && loc->owner->type != bp_catchpoint))
|
| + mi_only = 0;
|
| + output_thread_groups (uiout, "thread-groups", inf_num, mi_only);
|
| + VEC_free (int, inf_num);
|
| }
|
|
|
| if (!part_of_multiple)
|
| @@ -6002,28 +6159,31 @@ print_one_breakpoint_location (struct breakpoint *b,
|
| ui_out_text (uiout, "\n");
|
| }
|
|
|
| - if (!part_of_multiple && b->hit_count)
|
| + if (!part_of_multiple)
|
| {
|
| - /* FIXME should make an annotation for this. */
|
| - if (is_catchpoint (b))
|
| - ui_out_text (uiout, "\tcatchpoint");
|
| - else if (is_tracepoint (b))
|
| - ui_out_text (uiout, "\ttracepoint");
|
| - else
|
| - ui_out_text (uiout, "\tbreakpoint");
|
| - ui_out_text (uiout, " already hit ");
|
| - ui_out_field_int (uiout, "times", b->hit_count);
|
| - if (b->hit_count == 1)
|
| - ui_out_text (uiout, " time\n");
|
| + if (b->hit_count)
|
| + {
|
| + /* FIXME should make an annotation for this. */
|
| + if (is_catchpoint (b))
|
| + ui_out_text (uiout, "\tcatchpoint");
|
| + else if (is_tracepoint (b))
|
| + ui_out_text (uiout, "\ttracepoint");
|
| + else
|
| + ui_out_text (uiout, "\tbreakpoint");
|
| + ui_out_text (uiout, " already hit ");
|
| + ui_out_field_int (uiout, "times", b->hit_count);
|
| + if (b->hit_count == 1)
|
| + ui_out_text (uiout, " time\n");
|
| + else
|
| + ui_out_text (uiout, " times\n");
|
| + }
|
| else
|
| - ui_out_text (uiout, " times\n");
|
| + {
|
| + /* Output the count also if it is zero, but only if this is mi. */
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_int (uiout, "times", b->hit_count);
|
| + }
|
| }
|
| -
|
| - /* Output the count also if it is zero, but only if this is mi.
|
| - FIXME: Should have a better test for this. */
|
| - if (ui_out_is_mi_like_p (uiout))
|
| - if (!part_of_multiple && b->hit_count == 0)
|
| - ui_out_field_int (uiout, "times", b->hit_count);
|
|
|
| if (!part_of_multiple && b->ignore_count)
|
| {
|
| @@ -6061,15 +6221,6 @@ print_one_breakpoint_location (struct breakpoint *b,
|
| ui_out_text (uiout, " bytes\n");
|
| }
|
| }
|
| -
|
| - if (!part_of_multiple && b->extra_string
|
| - && b->type == bp_dprintf && !b->commands)
|
| - {
|
| - annotate_field (7);
|
| - ui_out_text (uiout, "\t(agent printf) ");
|
| - ui_out_field_string (uiout, "printf", b->extra_string);
|
| - ui_out_text (uiout, "\n");
|
| - }
|
|
|
| l = b->commands ? b->commands->commands : NULL;
|
| if (!part_of_multiple && l)
|
| @@ -6093,6 +6244,25 @@ print_one_breakpoint_location (struct breakpoint *b,
|
| ui_out_field_int (uiout, "pass", t->pass_count);
|
| ui_out_text (uiout, " \n");
|
| }
|
| +
|
| + /* Don't display it when tracepoint or tracepoint location is
|
| + pending. */
|
| + if (!header_of_multiple && loc != NULL && !loc->shlib_disabled)
|
| + {
|
| + annotate_field (11);
|
| +
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_string (uiout, "installed",
|
| + loc->inserted ? "y" : "n");
|
| + else
|
| + {
|
| + if (loc->inserted)
|
| + ui_out_text (uiout, "\t");
|
| + else
|
| + ui_out_text (uiout, "\tnot ");
|
| + ui_out_text (uiout, "installed on target\n");
|
| + }
|
| + }
|
| }
|
|
|
| if (ui_out_is_mi_like_p (uiout) && !part_of_multiple)
|
| @@ -6573,7 +6743,7 @@ static int
|
| breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1,
|
| struct address_space *aspace2, CORE_ADDR addr2)
|
| {
|
| - return ((gdbarch_has_global_breakpoints (target_gdbarch)
|
| + return ((gdbarch_has_global_breakpoints (target_gdbarch ())
|
| || aspace1 == aspace2)
|
| && addr1 == addr2);
|
| }
|
| @@ -6588,7 +6758,7 @@ breakpoint_address_match_range (struct address_space *aspace1, CORE_ADDR addr1,
|
| int len1, struct address_space *aspace2,
|
| CORE_ADDR addr2)
|
| {
|
| - return ((gdbarch_has_global_breakpoints (target_gdbarch)
|
| + return ((gdbarch_has_global_breakpoints (target_gdbarch ())
|
| || aspace1 == aspace2)
|
| && addr2 >= addr1 && addr2 < addr1 + len1);
|
| }
|
| @@ -6972,8 +7142,6 @@ init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch,
|
| program space. */
|
| if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint)
|
| b->pspace = sal.pspace;
|
| -
|
| - breakpoints_changed ();
|
| }
|
|
|
| /* set_raw_breakpoint is a low level routine for allocating and
|
| @@ -7312,11 +7480,7 @@ disable_breakpoints_in_shlibs (void)
|
| || (is_tracepoint (b)))
|
| && loc->pspace == current_program_space
|
| && !loc->shlib_disabled
|
| -#ifdef PC_SOLIB
|
| - && PC_SOLIB (loc->address)
|
| -#else
|
| && solib_name_from_address (loc->pspace, loc->address)
|
| -#endif
|
| )
|
| {
|
| loc->shlib_disabled = 1;
|
| @@ -7324,9 +7488,9 @@ disable_breakpoints_in_shlibs (void)
|
| }
|
| }
|
|
|
| -/* Disable any breakpoints and tracepoints that are in an unloaded shared
|
| - library. Only apply to enabled breakpoints, disabled ones can just stay
|
| - disabled. */
|
| +/* Disable any breakpoints and tracepoints that are in SOLIB upon
|
| + notification of unloaded_shlib. Only apply to enabled breakpoints,
|
| + disabled ones can just stay disabled. */
|
|
|
| static void
|
| disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
|
| @@ -7378,33 +7542,93 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
|
| }
|
| }
|
|
|
| -/* FORK & VFORK catchpoints. */
|
| -
|
| -/* An instance of this type is used to represent a fork or vfork
|
| - catchpoint. It includes a "struct breakpoint" as a kind of base
|
| - class; users downcast to "struct breakpoint *" when needed. A
|
| - breakpoint is really of this type iff its ops pointer points to
|
| - CATCH_FORK_BREAKPOINT_OPS. */
|
| +/* Disable any breakpoints and tracepoints in OBJFILE upon
|
| + notification of free_objfile. Only apply to enabled breakpoints,
|
| + disabled ones can just stay disabled. */
|
|
|
| -struct fork_catchpoint
|
| +static void
|
| +disable_breakpoints_in_freed_objfile (struct objfile *objfile)
|
| {
|
| - /* The base class. */
|
| - struct breakpoint base;
|
| + struct breakpoint *b;
|
|
|
| - /* Process id of a child process whose forking triggered this
|
| - catchpoint. This field is only valid immediately after this
|
| - catchpoint has triggered. */
|
| - ptid_t forked_inferior_pid;
|
| -};
|
| + if (objfile == NULL)
|
| + return;
|
|
|
| -/* Implement the "insert" breakpoint_ops method for fork
|
| - catchpoints. */
|
| + /* If the file is a shared library not loaded by the user then
|
| + solib_unloaded was notified and disable_breakpoints_in_unloaded_shlib
|
| + was called. In that case there is no need to take action again. */
|
| + if ((objfile->flags & OBJF_SHARED) && !(objfile->flags & OBJF_USERLOADED))
|
| + return;
|
|
|
| -static int
|
| -insert_catch_fork (struct bp_location *bl)
|
| -{
|
| - return target_insert_fork_catchpoint (PIDGET (inferior_ptid));
|
| -}
|
| + ALL_BREAKPOINTS (b)
|
| + {
|
| + struct bp_location *loc;
|
| + int bp_modified = 0;
|
| +
|
| + if (!is_breakpoint (b) && !is_tracepoint (b))
|
| + continue;
|
| +
|
| + for (loc = b->loc; loc != NULL; loc = loc->next)
|
| + {
|
| + CORE_ADDR loc_addr = loc->address;
|
| +
|
| + if (loc->loc_type != bp_loc_hardware_breakpoint
|
| + && loc->loc_type != bp_loc_software_breakpoint)
|
| + continue;
|
| +
|
| + if (loc->shlib_disabled != 0)
|
| + continue;
|
| +
|
| + if (objfile->pspace != loc->pspace)
|
| + continue;
|
| +
|
| + if (loc->loc_type != bp_loc_hardware_breakpoint
|
| + && loc->loc_type != bp_loc_software_breakpoint)
|
| + continue;
|
| +
|
| + if (is_addr_in_objfile (loc_addr, objfile))
|
| + {
|
| + loc->shlib_disabled = 1;
|
| + loc->inserted = 0;
|
| +
|
| + mark_breakpoint_location_modified (loc);
|
| +
|
| + bp_modified = 1;
|
| + }
|
| + }
|
| +
|
| + if (bp_modified)
|
| + observer_notify_breakpoint_modified (b);
|
| + }
|
| +}
|
| +
|
| +/* FORK & VFORK catchpoints. */
|
| +
|
| +/* An instance of this type is used to represent a fork or vfork
|
| + catchpoint. It includes a "struct breakpoint" as a kind of base
|
| + class; users downcast to "struct breakpoint *" when needed. A
|
| + breakpoint is really of this type iff its ops pointer points to
|
| + CATCH_FORK_BREAKPOINT_OPS. */
|
| +
|
| +struct fork_catchpoint
|
| +{
|
| + /* The base class. */
|
| + struct breakpoint base;
|
| +
|
| + /* Process id of a child process whose forking triggered this
|
| + catchpoint. This field is only valid immediately after this
|
| + catchpoint has triggered. */
|
| + ptid_t forked_inferior_pid;
|
| +};
|
| +
|
| +/* Implement the "insert" breakpoint_ops method for fork
|
| + catchpoints. */
|
| +
|
| +static int
|
| +insert_catch_fork (struct bp_location *bl)
|
| +{
|
| + return target_insert_fork_catchpoint (ptid_get_pid (inferior_ptid));
|
| +}
|
|
|
| /* Implement the "remove" breakpoint_ops method for fork
|
| catchpoints. */
|
| @@ -7412,7 +7636,7 @@ insert_catch_fork (struct bp_location *bl)
|
| static int
|
| remove_catch_fork (struct bp_location *bl)
|
| {
|
| - return target_remove_fork_catchpoint (PIDGET (inferior_ptid));
|
| + return target_remove_fork_catchpoint (ptid_get_pid (inferior_ptid));
|
| }
|
|
|
| /* Implement the "breakpoint_hit" breakpoint_ops method for fork
|
| @@ -7486,6 +7710,9 @@ print_one_catch_fork (struct breakpoint *b, struct bp_location **last_loc)
|
| ptid_get_pid (c->forked_inferior_pid));
|
| ui_out_spaces (uiout, 1);
|
| }
|
| +
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_string (uiout, "catch-type", "fork");
|
| }
|
|
|
| /* Implement the "print_mention" breakpoint_ops method for fork
|
| @@ -7517,7 +7744,7 @@ static struct breakpoint_ops catch_fork_breakpoint_ops;
|
| static int
|
| insert_catch_vfork (struct bp_location *bl)
|
| {
|
| - return target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
|
| + return target_insert_vfork_catchpoint (ptid_get_pid (inferior_ptid));
|
| }
|
|
|
| /* Implement the "remove" breakpoint_ops method for vfork
|
| @@ -7526,7 +7753,7 @@ insert_catch_vfork (struct bp_location *bl)
|
| static int
|
| remove_catch_vfork (struct bp_location *bl)
|
| {
|
| - return target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
|
| + return target_remove_vfork_catchpoint (ptid_get_pid (inferior_ptid));
|
| }
|
|
|
| /* Implement the "breakpoint_hit" breakpoint_ops method for vfork
|
| @@ -7599,6 +7826,9 @@ print_one_catch_vfork (struct breakpoint *b, struct bp_location **last_loc)
|
| ptid_get_pid (c->forked_inferior_pid));
|
| ui_out_spaces (uiout, 1);
|
| }
|
| +
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_string (uiout, "catch-type", "vfork");
|
| }
|
|
|
| /* Implement the "print_mention" breakpoint_ops method for vfork
|
| @@ -7797,6 +8027,10 @@ print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
|
| }
|
| ui_out_field_string (uiout, "what", msg);
|
| xfree (msg);
|
| +
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_string (uiout, "catch-type",
|
| + self->is_load ? "load" : "unload");
|
| }
|
|
|
| static void
|
| @@ -7823,20 +8057,20 @@ print_recreate_catch_solib (struct breakpoint *b, struct ui_file *fp)
|
|
|
| static struct breakpoint_ops catch_solib_breakpoint_ops;
|
|
|
| -/* A helper function that does all the work for "catch load" and
|
| - "catch unload". */
|
| +/* Shared helper function (MI and CLI) for creating and installing
|
| + a shared object event catchpoint. If IS_LOAD is non-zero then
|
| + the events to be caught are load events, otherwise they are
|
| + unload events. If IS_TEMP is non-zero the catchpoint is a
|
| + temporary one. If ENABLED is non-zero the catchpoint is
|
| + created in an enabled state. */
|
|
|
| -static void
|
| -catch_load_or_unload (char *arg, int from_tty, int is_load,
|
| - struct cmd_list_element *command)
|
| +void
|
| +add_solib_catchpoint (char *arg, int is_load, int is_temp, int enabled)
|
| {
|
| struct solib_catchpoint *c;
|
| struct gdbarch *gdbarch = get_current_arch ();
|
| - int tempflag;
|
| struct cleanup *cleanup;
|
|
|
| - tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
|
| -
|
| if (!arg)
|
| arg = "";
|
| arg = skip_spaces (arg);
|
| @@ -7860,13 +8094,30 @@ catch_load_or_unload (char *arg, int from_tty, int is_load,
|
| }
|
|
|
| c->is_load = is_load;
|
| - init_catchpoint (&c->base, gdbarch, tempflag, NULL,
|
| + init_catchpoint (&c->base, gdbarch, is_temp, NULL,
|
| &catch_solib_breakpoint_ops);
|
|
|
| + c->base.enable_state = enabled ? bp_enabled : bp_disabled;
|
| +
|
| discard_cleanups (cleanup);
|
| install_breakpoint (0, &c->base, 1);
|
| }
|
|
|
| +/* A helper function that does all the work for "catch load" and
|
| + "catch unload". */
|
| +
|
| +static void
|
| +catch_load_or_unload (char *arg, int from_tty, int is_load,
|
| + struct cmd_list_element *command)
|
| +{
|
| + int tempflag;
|
| + const int enabled = 1;
|
| +
|
| + tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
|
| +
|
| + add_solib_catchpoint (arg, is_load, tempflag, enabled);
|
| +}
|
| +
|
| static void
|
| catch_load_command_1 (char *arg, int from_tty,
|
| struct cmd_list_element *command)
|
| @@ -7881,8 +8132,6 @@ catch_unload_command_1 (char *arg, int from_tty,
|
| catch_load_or_unload (arg, from_tty, 0, command);
|
| }
|
|
|
| -DEF_VEC_I(int);
|
| -
|
| /* An instance of this type is used to represent a syscall catchpoint.
|
| It includes a "struct breakpoint" as a kind of base class; users
|
| downcast to "struct breakpoint *" when needed. A breakpoint is
|
| @@ -7997,7 +8246,7 @@ insert_catch_syscall (struct bp_location *bl)
|
| }
|
| }
|
|
|
| - return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
|
| + return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
|
| inf_data->total_syscalls_count != 0,
|
| inf_data->any_syscall_count,
|
| VEC_length (int,
|
| @@ -8037,7 +8286,7 @@ remove_catch_syscall (struct bp_location *bl)
|
| }
|
| }
|
|
|
| - return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
|
| + return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
|
| inf_data->total_syscalls_count != 0,
|
| inf_data->any_syscall_count,
|
| VEC_length (int,
|
| @@ -8191,6 +8440,9 @@ print_one_catch_syscall (struct breakpoint *b,
|
| else
|
| ui_out_field_string (uiout, "what", "<any syscall>");
|
| ui_out_text (uiout, "\" ");
|
| +
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_string (uiout, "catch-type", "syscall");
|
| }
|
|
|
| /* Implement the "print_mention" breakpoint_ops method for syscall
|
| @@ -8276,7 +8528,7 @@ syscall_catchpoint_p (struct breakpoint *b)
|
| not NULL, then store it in the breakpoint. OPS, if not NULL, is
|
| the breakpoint_ops structure associated to the catchpoint. */
|
|
|
| -static void
|
| +void
|
| init_catchpoint (struct breakpoint *b,
|
| struct gdbarch *gdbarch, int tempflag,
|
| char *cond_string,
|
| @@ -8298,6 +8550,8 @@ install_breakpoint (int internal, struct breakpoint *b, int update_gll)
|
| {
|
| add_to_breakpoint_chain (b);
|
| set_breakpoint_number (internal, b);
|
| + if (is_tracepoint (b))
|
| + set_tracepoint_count (breakpoint_count);
|
| if (!internal)
|
| mention (b);
|
| observer_notify_breakpoint_created (b);
|
| @@ -8355,13 +8609,13 @@ dtor_catch_exec (struct breakpoint *b)
|
| static int
|
| insert_catch_exec (struct bp_location *bl)
|
| {
|
| - return target_insert_exec_catchpoint (PIDGET (inferior_ptid));
|
| + return target_insert_exec_catchpoint (ptid_get_pid (inferior_ptid));
|
| }
|
|
|
| static int
|
| remove_catch_exec (struct bp_location *bl)
|
| {
|
| - return target_remove_exec_catchpoint (PIDGET (inferior_ptid));
|
| + return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid));
|
| }
|
|
|
| static int
|
| @@ -8426,6 +8680,9 @@ print_one_catch_exec (struct breakpoint *b, struct bp_location **last_loc)
|
| ui_out_field_string (uiout, "what", c->exec_pathname);
|
| ui_out_text (uiout, "\" ");
|
| }
|
| +
|
| + if (ui_out_is_mi_like_p (uiout))
|
| + ui_out_field_string (uiout, "catch-type", "exec");
|
| }
|
|
|
| static void
|
| @@ -8587,9 +8844,9 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
|
| {
|
| struct breakpoint *b;
|
|
|
| - /* If FRAME_ID is valid, it should be a real frame, not an inlined
|
| - one. */
|
| - gdb_assert (!frame_id_inlined_p (frame_id));
|
| + /* If FRAME_ID is valid, it should be a real frame, not an inlined or
|
| + tail-called one. */
|
| + gdb_assert (!frame_id_artificial_p (frame_id));
|
|
|
| b = set_raw_breakpoint (gdbarch, sal, type, &momentary_breakpoint_ops);
|
| b->enable_state = bp_enabled;
|
| @@ -8628,11 +8885,8 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
|
| copy->loc->section = orig->loc->section;
|
| copy->loc->pspace = orig->loc->pspace;
|
| copy->loc->probe = orig->loc->probe;
|
| -
|
| - if (orig->loc->source_file != NULL)
|
| - copy->loc->source_file = xstrdup (orig->loc->source_file);
|
| -
|
| copy->loc->line_number = orig->loc->line_number;
|
| + copy->loc->symtab = orig->loc->symtab;
|
| copy->frame_id = orig->frame_id;
|
| copy->thread = orig->thread;
|
| copy->pspace = orig->pspace;
|
| @@ -8705,9 +8959,12 @@ add_location_to_breakpoint (struct breakpoint *b,
|
| adjusted_address = adjust_breakpoint_address (loc_gdbarch,
|
| sal->pc, b->type);
|
|
|
| + /* Sort the locations by their ADDRESS. */
|
| loc = allocate_bp_location (b);
|
| - for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
|
| + for (tmp = &(b->loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
|
| + tmp = &((*tmp)->next))
|
| ;
|
| + loc->next = *tmp;
|
| *tmp = loc;
|
|
|
| loc->requested_address = sal->pc;
|
| @@ -8717,10 +8974,8 @@ add_location_to_breakpoint (struct breakpoint *b,
|
| gdb_assert (loc->pspace != NULL);
|
| loc->section = sal->section;
|
| loc->gdbarch = loc_gdbarch;
|
| -
|
| - if (sal->symtab != NULL)
|
| - loc->source_file = xstrdup (sal->symtab->filename);
|
| loc->line_number = sal->line;
|
| + loc->symtab = sal->symtab;
|
|
|
| set_breakpoint_location_function (loc,
|
| sal->explicit_pc || sal->explicit_line);
|
| @@ -8823,30 +9078,21 @@ update_dprintf_command_list (struct breakpoint *b)
|
| internal_error (__FILE__, __LINE__,
|
| _("Invalid dprintf style."));
|
|
|
| - /* Manufacture a printf/continue sequence. */
|
| - if (printf_line)
|
| - {
|
| - struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
|
| -
|
| - if (strcmp (dprintf_style, dprintf_style_agent) != 0)
|
| - {
|
| - cont_cmd_line = xmalloc (sizeof (struct command_line));
|
| - cont_cmd_line->control_type = simple_control;
|
| - cont_cmd_line->body_count = 0;
|
| - cont_cmd_line->body_list = NULL;
|
| - cont_cmd_line->next = NULL;
|
| - cont_cmd_line->line = xstrdup ("continue");
|
| - }
|
| + gdb_assert (printf_line != NULL);
|
| + /* Manufacture a printf sequence. */
|
| + {
|
| + struct command_line *printf_cmd_line
|
| + = xmalloc (sizeof (struct command_line));
|
|
|
| - printf_cmd_line = xmalloc (sizeof (struct command_line));
|
| - printf_cmd_line->control_type = simple_control;
|
| - printf_cmd_line->body_count = 0;
|
| - printf_cmd_line->body_list = NULL;
|
| - printf_cmd_line->next = cont_cmd_line;
|
| - printf_cmd_line->line = printf_line;
|
| + printf_cmd_line = xmalloc (sizeof (struct command_line));
|
| + printf_cmd_line->control_type = simple_control;
|
| + printf_cmd_line->body_count = 0;
|
| + printf_cmd_line->body_list = NULL;
|
| + printf_cmd_line->next = NULL;
|
| + printf_cmd_line->line = printf_line;
|
|
|
| - breakpoint_set_commands (b, printf_cmd_line);
|
| - }
|
| + breakpoint_set_commands (b, printf_cmd_line);
|
| + }
|
| }
|
|
|
| /* Update all dprintf commands, making their command lists reflect
|
| @@ -8980,7 +9226,8 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
|
|
|
| if (b->cond_string)
|
| {
|
| - char *arg = b->cond_string;
|
| + const char *arg = b->cond_string;
|
| +
|
| loc->cond = parse_exp_1 (&arg, loc->address,
|
| block_for_pc (loc->address), 0);
|
| if (*arg)
|
| @@ -9115,8 +9362,6 @@ static void
|
| parse_breakpoint_sals (char **address,
|
| struct linespec_result *canonical)
|
| {
|
| - char *addr_start = *address;
|
| -
|
| /* If no arg given, or if first arg is 'if ', use the default
|
| breakpoint. */
|
| if ((*address) == NULL
|
| @@ -9128,21 +9373,27 @@ parse_breakpoint_sals (char **address,
|
| {
|
| struct linespec_sals lsal;
|
| struct symtab_and_line sal;
|
| + CORE_ADDR pc;
|
|
|
| init_sal (&sal); /* Initialize to zeroes. */
|
| lsal.sals.sals = (struct symtab_and_line *)
|
| xmalloc (sizeof (struct symtab_and_line));
|
|
|
| /* Set sal's pspace, pc, symtab, and line to the values
|
| - corresponding to the last call to print_frame_info. */
|
| + corresponding to the last call to print_frame_info.
|
| + Be sure to reinitialize LINE with NOTCURRENT == 0
|
| + as the breakpoint line number is inappropriate otherwise.
|
| + find_pc_line would adjust PC, re-set it back. */
|
| get_last_displayed_sal (&sal);
|
| - sal.section = find_pc_overlay (sal.pc);
|
| + pc = sal.pc;
|
| + sal = find_pc_line (pc, 0);
|
|
|
| /* "break" without arguments is equivalent to "break *PC"
|
| where PC is the last displayed codepoint's address. So
|
| make sure to set sal.explicit_pc to prevent GDB from
|
| trying to expand the list of sals to include all other
|
| instances with the same symtab and line. */
|
| + sal.pc = pc;
|
| sal.explicit_pc = 1;
|
|
|
| lsal.sals.sals[0] = sal;
|
| @@ -9231,6 +9482,14 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
|
| }
|
| }
|
|
|
| +/* Issue an invalid thread ID error. */
|
| +
|
| +static void ATTRIBUTE_NORETURN
|
| +invalid_thread_id_error (int id)
|
| +{
|
| + error (_("Unknown thread %d."), id);
|
| +}
|
| +
|
| /* Given TOK, a string specification of condition and thread, as
|
| accepted by the 'break' command, extract the condition
|
| string and thread number and set *COND_STRING and *THREAD.
|
| @@ -9239,20 +9498,23 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
|
| If no thread is found, *THREAD is set to -1. */
|
|
|
| static void
|
| -find_condition_and_thread (char *tok, CORE_ADDR pc,
|
| +find_condition_and_thread (const char *tok, CORE_ADDR pc,
|
| char **cond_string, int *thread, int *task,
|
| char **rest)
|
| {
|
| *cond_string = NULL;
|
| *thread = -1;
|
| + *task = 0;
|
| + *rest = NULL;
|
| +
|
| while (tok && *tok)
|
| {
|
| - char *end_tok;
|
| + const char *end_tok;
|
| int toklen;
|
| - char *cond_start = NULL;
|
| - char *cond_end = NULL;
|
| + const char *cond_start = NULL;
|
| + const char *cond_end = NULL;
|
|
|
| - tok = skip_spaces (tok);
|
| + tok = skip_spaces_const (tok);
|
|
|
| if ((*tok == '"' || *tok == ',') && rest)
|
| {
|
| @@ -9260,7 +9522,7 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
|
| return;
|
| }
|
|
|
| - end_tok = skip_to_space (tok);
|
| + end_tok = skip_to_space_const (tok);
|
|
|
| toklen = end_tok - tok;
|
|
|
| @@ -9279,24 +9541,24 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
|
| char *tmptok;
|
|
|
| tok = end_tok + 1;
|
| - tmptok = tok;
|
| - *thread = strtol (tok, &tok, 0);
|
| + *thread = strtol (tok, &tmptok, 0);
|
| if (tok == tmptok)
|
| error (_("Junk after thread keyword."));
|
| if (!valid_thread_id (*thread))
|
| - error (_("Unknown thread %d."), *thread);
|
| + invalid_thread_id_error (*thread);
|
| + tok = tmptok;
|
| }
|
| else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
|
| {
|
| char *tmptok;
|
|
|
| tok = end_tok + 1;
|
| - tmptok = tok;
|
| - *task = strtol (tok, &tok, 0);
|
| + *task = strtol (tok, &tmptok, 0);
|
| if (tok == tmptok)
|
| error (_("Junk after task keyword."));
|
| if (!valid_task_id (*task))
|
| error (_("Unknown task %d."), *task);
|
| + tok = tmptok;
|
| }
|
| else if (rest)
|
| {
|
| @@ -9357,20 +9619,20 @@ decode_static_tracepoint_spec (char **arg_p)
|
|
|
| /* Set a breakpoint. This function is shared between CLI and MI
|
| functions for setting a breakpoint. This function has two major
|
| - modes of operations, selected by the PARSE_CONDITION_AND_THREAD
|
| - parameter. If non-zero, the function will parse arg, extracting
|
| - breakpoint location, address and thread. Otherwise, ARG is just
|
| - the location of breakpoint, with condition and thread specified by
|
| - the COND_STRING and THREAD parameters. If INTERNAL is non-zero,
|
| - the breakpoint number will be allocated from the internal
|
| - breakpoint count. Returns true if any breakpoint was created;
|
| - false otherwise. */
|
| + modes of operations, selected by the PARSE_ARG parameter. If
|
| + non-zero, the function will parse ARG, extracting location,
|
| + condition, thread and extra string. Otherwise, ARG is just the
|
| + breakpoint's location, with condition, thread, and extra string
|
| + specified by the COND_STRING, THREAD and EXTRA_STRING parameters.
|
| + If INTERNAL is non-zero, the breakpoint number will be allocated
|
| + from the internal breakpoint count. Returns true if any breakpoint
|
| + was created; false otherwise. */
|
|
|
| int
|
| create_breakpoint (struct gdbarch *gdbarch,
|
| char *arg, char *cond_string,
|
| int thread, char *extra_string,
|
| - int parse_condition_and_thread,
|
| + int parse_arg,
|
| int tempflag, enum bptype type_wanted,
|
| int ignore_count,
|
| enum auto_boolean pending_break_support,
|
| @@ -9484,46 +9746,47 @@ create_breakpoint (struct gdbarch *gdbarch,
|
| breakpoint. */
|
| if (!pending)
|
| {
|
| - struct linespec_sals *lsal;
|
| + if (parse_arg)
|
| + {
|
| + char *rest;
|
| + struct linespec_sals *lsal;
|
|
|
| - lsal = VEC_index (linespec_sals, canonical.sals, 0);
|
| + lsal = VEC_index (linespec_sals, canonical.sals, 0);
|
|
|
| - if (parse_condition_and_thread)
|
| - {
|
| - char *rest;
|
| - /* Here we only parse 'arg' to separate condition
|
| - from thread number, so parsing in context of first
|
| - sal is OK. When setting the breakpoint we'll
|
| - re-parse it in context of each sal. */
|
| - cond_string = NULL;
|
| - thread = -1;
|
| - rest = NULL;
|
| - find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
|
| - &thread, &task, &rest);
|
| - if (cond_string)
|
| - make_cleanup (xfree, cond_string);
|
| - if (rest)
|
| - make_cleanup (xfree, rest);
|
| - if (rest)
|
| - extra_string = rest;
|
| + /* Here we only parse 'arg' to separate condition
|
| + from thread number, so parsing in context of first
|
| + sal is OK. When setting the breakpoint we'll
|
| + re-parse it in context of each sal. */
|
| +
|
| + find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
|
| + &thread, &task, &rest);
|
| + if (cond_string)
|
| + make_cleanup (xfree, cond_string);
|
| + if (rest)
|
| + make_cleanup (xfree, rest);
|
| + if (rest)
|
| + extra_string = rest;
|
| }
|
| else
|
| {
|
| - /* Create a private copy of condition string. */
|
| - if (cond_string)
|
| - {
|
| - cond_string = xstrdup (cond_string);
|
| - make_cleanup (xfree, cond_string);
|
| - }
|
| - /* Create a private copy of any extra string. */
|
| - if (extra_string)
|
| - {
|
| - extra_string = xstrdup (extra_string);
|
| - make_cleanup (xfree, extra_string);
|
| - }
|
| + if (*arg != '\0')
|
| + error (_("Garbage '%s' at end of location"), arg);
|
| +
|
| + /* Create a private copy of condition string. */
|
| + if (cond_string)
|
| + {
|
| + cond_string = xstrdup (cond_string);
|
| + make_cleanup (xfree, cond_string);
|
| + }
|
| + /* Create a private copy of any extra string. */
|
| + if (extra_string)
|
| + {
|
| + extra_string = xstrdup (extra_string);
|
| + make_cleanup (xfree, extra_string);
|
| + }
|
| }
|
|
|
| - ops->create_breakpoints_sal (gdbarch, &canonical, lsal,
|
| + ops->create_breakpoints_sal (gdbarch, &canonical,
|
| cond_string, extra_string, type_wanted,
|
| tempflag ? disp_del : disp_donttouch,
|
| thread, task, ignore_count, ops,
|
| @@ -9548,7 +9811,7 @@ create_breakpoint (struct gdbarch *gdbarch,
|
| init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
|
|
|
| b->addr_string = copy_arg;
|
| - if (parse_condition_and_thread)
|
| + if (parse_arg)
|
| b->cond_string = NULL;
|
| else
|
| {
|
| @@ -9638,7 +9901,7 @@ resolve_sal_pc (struct symtab_and_line *sal)
|
| {
|
| if (!find_line_pc (sal->symtab, sal->line, &pc))
|
| error (_("No line %d in file \"%s\"."),
|
| - sal->line, sal->symtab->filename);
|
| + sal->line, symtab_to_filename_for_display (sal->symtab));
|
| sal->pc = pc;
|
|
|
| /* If this SAL corresponds to a breakpoint inserted using a line
|
| @@ -9660,7 +9923,7 @@ resolve_sal_pc (struct symtab_and_line *sal)
|
| if (sym != NULL)
|
| {
|
| fixup_symbol_section (sym, sal->symtab->objfile);
|
| - sal->section = SYMBOL_OBJ_SECTION (sym);
|
| + sal->section = SYMBOL_OBJ_SECTION (sal->symtab->objfile, sym);
|
| }
|
| else
|
| {
|
| @@ -9669,14 +9932,14 @@ resolve_sal_pc (struct symtab_and_line *sal)
|
| if we have line numbers but no functions (as can
|
| happen in assembly source). */
|
|
|
| - struct minimal_symbol *msym;
|
| + struct bound_minimal_symbol msym;
|
| struct cleanup *old_chain = save_current_space_and_thread ();
|
|
|
| switch_to_program_space_and_thread (sal->pspace);
|
|
|
| msym = lookup_minimal_symbol_by_pc (sal->pc);
|
| - if (msym)
|
| - sal->section = SYMBOL_OBJ_SECTION (msym);
|
| + if (msym.minsym)
|
| + sal->section = SYMBOL_OBJ_SECTION (msym.objfile, msym.minsym);
|
|
|
| do_cleanups (old_chain);
|
| }
|
| @@ -9781,14 +10044,12 @@ stopat_command (char *arg, int from_tty)
|
| break_command_1 (arg, 0, from_tty);
|
| }
|
|
|
| -void dprintf_command (char *arg, int from_tty);
|
| -
|
| /* The dynamic printf command is mostly like a regular breakpoint, but
|
| with a prewired command list consisting of a single output command,
|
| built from extra arguments supplied on the dprintf command
|
| line. */
|
|
|
| -void
|
| +static void
|
| dprintf_command (char *arg, int from_tty)
|
| {
|
| create_breakpoint (get_current_arch (),
|
| @@ -10153,7 +10414,6 @@ watchpoint_exp_is_const (const struct expression *exp)
|
| case BINOP_RANGE:
|
| case TERNOP_COND:
|
| case TERNOP_SLICE:
|
| - case TERNOP_SLICE_COUNT:
|
|
|
| case OP_LONG:
|
| case OP_DOUBLE:
|
| @@ -10161,9 +10421,11 @@ watchpoint_exp_is_const (const struct expression *exp)
|
| case OP_LAST:
|
| case OP_COMPLEX:
|
| case OP_STRING:
|
| - case OP_BITSTRING:
|
| case OP_ARRAY:
|
| case OP_TYPE:
|
| + case OP_TYPEOF:
|
| + case OP_DECLTYPE:
|
| + case OP_TYPEID:
|
| case OP_NAME:
|
| case OP_OBJC_NSSTRING:
|
|
|
| @@ -10173,6 +10435,10 @@ watchpoint_exp_is_const (const struct expression *exp)
|
| case UNOP_ADDR:
|
| case UNOP_HIGH:
|
| case UNOP_CAST:
|
| +
|
| + case UNOP_CAST_TYPE:
|
| + case UNOP_REINTERPRET_CAST:
|
| + case UNOP_DYNAMIC_CAST:
|
| /* Unary, binary and ternary operators: We have to check
|
| their operands. If they are constant, then so is the
|
| result of that operation. For instance, if A and B are
|
| @@ -10345,7 +10611,6 @@ print_it_watchpoint (bpstat bs)
|
| {
|
| struct cleanup *old_chain;
|
| struct breakpoint *b;
|
| - const struct bp_location *bl;
|
| struct ui_file *stb;
|
| enum print_stop_action result;
|
| struct watchpoint *w;
|
| @@ -10353,7 +10618,6 @@ print_it_watchpoint (bpstat bs)
|
|
|
| gdb_assert (bs->bp_location_at != NULL);
|
|
|
| - bl = bs->bp_location_at;
|
| b = bs->breakpoint_at;
|
| w = (struct watchpoint *) b;
|
|
|
| @@ -10502,6 +10766,20 @@ print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp)
|
| print_recreate_thread (b, fp);
|
| }
|
|
|
| +/* Implement the "explains_signal" breakpoint_ops method for
|
| + watchpoints. */
|
| +
|
| +static int
|
| +explains_signal_watchpoint (struct breakpoint *b, enum gdb_signal sig)
|
| +{
|
| + /* A software watchpoint cannot cause a signal other than
|
| + GDB_SIGNAL_TRAP. */
|
| + if (b->type == bp_watchpoint && sig != GDB_SIGNAL_TRAP)
|
| + return 0;
|
| +
|
| + return 1;
|
| +}
|
| +
|
| /* The breakpoint_ops structure to be used in hardware watchpoints. */
|
|
|
| static struct breakpoint_ops watchpoint_breakpoint_ops;
|
| @@ -10698,21 +10976,21 @@ is_masked_watchpoint (const struct breakpoint *b)
|
| hw_read: watch read,
|
| hw_access: watch access (read or write) */
|
| static void
|
| -watch_command_1 (char *arg, int accessflag, int from_tty,
|
| +watch_command_1 (const char *arg, int accessflag, int from_tty,
|
| int just_location, int internal)
|
| {
|
| volatile struct gdb_exception e;
|
| struct breakpoint *b, *scope_breakpoint = NULL;
|
| struct expression *exp;
|
| - struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
|
| + const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
|
| struct value *val, *mark, *result;
|
| struct frame_info *frame;
|
| - char *exp_start = NULL;
|
| - char *exp_end = NULL;
|
| - char *tok, *end_tok;
|
| + const char *exp_start = NULL;
|
| + const char *exp_end = NULL;
|
| + const char *tok, *end_tok;
|
| int toklen = -1;
|
| - char *cond_start = NULL;
|
| - char *cond_end = NULL;
|
| + const char *cond_start = NULL;
|
| + const char *cond_end = NULL;
|
| enum bptype bp_type;
|
| int thread = -1;
|
| int pc = 0;
|
| @@ -10721,15 +10999,19 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
| int use_mask = 0;
|
| CORE_ADDR mask = 0;
|
| struct watchpoint *w;
|
| + char *expression;
|
| + struct cleanup *back_to;
|
|
|
| /* Make sure that we actually have parameters to parse. */
|
| if (arg != NULL && arg[0] != '\0')
|
| {
|
| - char *value_start;
|
| + const char *value_start;
|
| +
|
| + exp_end = arg + strlen (arg);
|
|
|
| /* Look for "parameter value" pairs at the end
|
| of the arguments string. */
|
| - for (tok = arg + strlen (arg) - 1; tok > arg; tok--)
|
| + for (tok = exp_end - 1; tok > arg; tok--)
|
| {
|
| /* Skip whitespace at the end of the argument list. */
|
| while (tok > arg && (*tok == ' ' || *tok == '\t'))
|
| @@ -10774,7 +11056,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
|
|
| /* Check if the thread actually exists. */
|
| if (!valid_thread_id (thread))
|
| - error (_("Unknown thread %d."), thread);
|
| + invalid_thread_id_error (thread);
|
| }
|
| else if (toklen == 4 && !strncmp (tok, "mask", 4))
|
| {
|
| @@ -10799,13 +11081,19 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
|
|
| /* Truncate the string and get rid of the "parameter value" pair before
|
| the arguments string is parsed by the parse_exp_1 function. */
|
| - *tok = '\0';
|
| + exp_end = tok;
|
| }
|
| }
|
| + else
|
| + exp_end = arg;
|
|
|
| - /* Parse the rest of the arguments. */
|
| + /* Parse the rest of the arguments. From here on out, everything
|
| + is in terms of a newly allocated string instead of the original
|
| + ARG. */
|
| innermost_block = NULL;
|
| - exp_start = arg;
|
| + expression = savestring (arg, exp_end - arg);
|
| + back_to = make_cleanup (xfree, expression);
|
| + exp_start = arg = expression;
|
| exp = parse_exp_1 (&arg, 0, 0, 0);
|
| exp_end = arg;
|
| /* Remove trailing whitespace from the expression before saving it.
|
| @@ -10827,7 +11115,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
|
|
| exp_valid_block = innermost_block;
|
| mark = value_mark ();
|
| - fetch_subexp_value (exp, &pc, &val, &result, NULL);
|
| + fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location);
|
|
|
| if (just_location)
|
| {
|
| @@ -10851,8 +11139,8 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
| else if (val != NULL)
|
| release_value (val);
|
|
|
| - tok = skip_spaces (arg);
|
| - end_tok = skip_to_space (tok);
|
| + tok = skip_spaces_const (arg);
|
| + end_tok = skip_to_space_const (tok);
|
|
|
| toklen = end_tok - tok;
|
| if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
|
| @@ -10873,13 +11161,6 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
| if (*tok)
|
| error (_("Junk at end of command."));
|
|
|
| - if (accessflag == hw_read)
|
| - bp_type = bp_read_watchpoint;
|
| - else if (accessflag == hw_access)
|
| - bp_type = bp_access_watchpoint;
|
| - else
|
| - bp_type = bp_hardware_watchpoint;
|
| -
|
| frame = block_innermost_frame (exp_valid_block);
|
|
|
| /* If the expression is "local", then set up a "watchpoint scope"
|
| @@ -10916,7 +11197,17 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
| }
|
| }
|
|
|
| - /* Now set up the breakpoint. */
|
| + /* Now set up the breakpoint. We create all watchpoints as hardware
|
| + watchpoints here even if hardware watchpoints are turned off, a call
|
| + to update_watchpoint later in this function will cause the type to
|
| + drop back to bp_watchpoint (software watchpoint) if required. */
|
| +
|
| + if (accessflag == hw_read)
|
| + bp_type = bp_read_watchpoint;
|
| + else if (accessflag == hw_access)
|
| + bp_type = bp_access_watchpoint;
|
| + else
|
| + bp_type = bp_hardware_watchpoint;
|
|
|
| w = XCNEW (struct watchpoint);
|
| b = &w->base;
|
| @@ -11004,6 +11295,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
|
| }
|
|
|
| install_breakpoint (internal, b, 1);
|
| + do_cleanups (back_to);
|
| }
|
|
|
| /* Return count of debug registers needed to watch the given expression.
|
| @@ -11292,7 +11584,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
|
| it updates arg to point to the first character following the parsed
|
| if clause in the arg string. */
|
|
|
| -static char *
|
| +char *
|
| ep_parse_optional_if_clause (char **arg)
|
| {
|
| char *cond_string;
|
| @@ -11405,172 +11697,6 @@ catch_exec_command_1 (char *arg, int from_tty,
|
| install_breakpoint (0, &c->base, 1);
|
| }
|
|
|
| -static enum print_stop_action
|
| -print_it_exception_catchpoint (bpstat bs)
|
| -{
|
| - struct ui_out *uiout = current_uiout;
|
| - struct breakpoint *b = bs->breakpoint_at;
|
| - int bp_temp, bp_throw;
|
| -
|
| - annotate_catchpoint (b->number);
|
| -
|
| - bp_throw = strstr (b->addr_string, "throw") != NULL;
|
| - if (b->loc->address != b->loc->requested_address)
|
| - breakpoint_adjustment_warning (b->loc->requested_address,
|
| - b->loc->address,
|
| - b->number, 1);
|
| - bp_temp = b->disposition == disp_del;
|
| - ui_out_text (uiout,
|
| - bp_temp ? "Temporary catchpoint "
|
| - : "Catchpoint ");
|
| - if (!ui_out_is_mi_like_p (uiout))
|
| - ui_out_field_int (uiout, "bkptno", b->number);
|
| - ui_out_text (uiout,
|
| - bp_throw ? " (exception thrown), "
|
| - : " (exception caught), ");
|
| - if (ui_out_is_mi_like_p (uiout))
|
| - {
|
| - ui_out_field_string (uiout, "reason",
|
| - async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
|
| - ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
|
| - ui_out_field_int (uiout, "bkptno", b->number);
|
| - }
|
| - return PRINT_SRC_AND_LOC;
|
| -}
|
| -
|
| -static void
|
| -print_one_exception_catchpoint (struct breakpoint *b,
|
| - struct bp_location **last_loc)
|
| -{
|
| - struct value_print_options opts;
|
| - struct ui_out *uiout = current_uiout;
|
| -
|
| - get_user_print_options (&opts);
|
| - if (opts.addressprint)
|
| - {
|
| - annotate_field (4);
|
| - if (b->loc == NULL || b->loc->shlib_disabled)
|
| - ui_out_field_string (uiout, "addr", "<PENDING>");
|
| - else
|
| - ui_out_field_core_addr (uiout, "addr",
|
| - b->loc->gdbarch, b->loc->address);
|
| - }
|
| - annotate_field (5);
|
| - if (b->loc)
|
| - *last_loc = b->loc;
|
| - if (strstr (b->addr_string, "throw") != NULL)
|
| - ui_out_field_string (uiout, "what", "exception throw");
|
| - else
|
| - ui_out_field_string (uiout, "what", "exception catch");
|
| -}
|
| -
|
| -static void
|
| -print_mention_exception_catchpoint (struct breakpoint *b)
|
| -{
|
| - struct ui_out *uiout = current_uiout;
|
| - int bp_temp;
|
| - int bp_throw;
|
| -
|
| - bp_temp = b->disposition == disp_del;
|
| - bp_throw = strstr (b->addr_string, "throw") != NULL;
|
| - ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
|
| - : _("Catchpoint "));
|
| - ui_out_field_int (uiout, "bkptno", b->number);
|
| - ui_out_text (uiout, bp_throw ? _(" (throw)")
|
| - : _(" (catch)"));
|
| -}
|
| -
|
| -/* Implement the "print_recreate" breakpoint_ops method for throw and
|
| - catch catchpoints. */
|
| -
|
| -static void
|
| -print_recreate_exception_catchpoint (struct breakpoint *b,
|
| - struct ui_file *fp)
|
| -{
|
| - int bp_temp;
|
| - int bp_throw;
|
| -
|
| - bp_temp = b->disposition == disp_del;
|
| - bp_throw = strstr (b->addr_string, "throw") != NULL;
|
| - fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
|
| - fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
|
| - print_recreate_thread (b, fp);
|
| -}
|
| -
|
| -static struct breakpoint_ops gnu_v3_exception_catchpoint_ops;
|
| -
|
| -static int
|
| -handle_gnu_v3_exceptions (int tempflag, char *cond_string,
|
| - enum exception_event_kind ex_event, int from_tty)
|
| -{
|
| - char *trigger_func_name;
|
| -
|
| - if (ex_event == EX_EVENT_CATCH)
|
| - trigger_func_name = "__cxa_begin_catch";
|
| - else
|
| - trigger_func_name = "__cxa_throw";
|
| -
|
| - create_breakpoint (get_current_arch (),
|
| - trigger_func_name, cond_string, -1, NULL,
|
| - 0 /* condition and thread are valid. */,
|
| - tempflag, bp_breakpoint,
|
| - 0,
|
| - AUTO_BOOLEAN_TRUE /* pending */,
|
| - &gnu_v3_exception_catchpoint_ops, from_tty,
|
| - 1 /* enabled */,
|
| - 0 /* internal */,
|
| - 0);
|
| -
|
| - return 1;
|
| -}
|
| -
|
| -/* Deal with "catch catch" and "catch throw" commands. */
|
| -
|
| -static void
|
| -catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
|
| - int tempflag, int from_tty)
|
| -{
|
| - char *cond_string = NULL;
|
| -
|
| - if (!arg)
|
| - arg = "";
|
| - arg = skip_spaces (arg);
|
| -
|
| - cond_string = ep_parse_optional_if_clause (&arg);
|
| -
|
| - if ((*arg != '\0') && !isspace (*arg))
|
| - error (_("Junk at end of arguments."));
|
| -
|
| - if (ex_event != EX_EVENT_THROW
|
| - && ex_event != EX_EVENT_CATCH)
|
| - error (_("Unsupported or unknown exception event; cannot catch it"));
|
| -
|
| - if (handle_gnu_v3_exceptions (tempflag, cond_string, ex_event, from_tty))
|
| - return;
|
| -
|
| - warning (_("Unsupported with this platform/compiler combination."));
|
| -}
|
| -
|
| -/* Implementation of "catch catch" command. */
|
| -
|
| -static void
|
| -catch_catch_command (char *arg, int from_tty, struct cmd_list_element *command)
|
| -{
|
| - int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
|
| -
|
| - catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
|
| -}
|
| -
|
| -/* Implementation of "catch throw" command. */
|
| -
|
| -static void
|
| -catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
|
| -{
|
| - int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
|
| -
|
| - catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
|
| -}
|
| -
|
| void
|
| init_ada_exception_breakpoint (struct breakpoint *b,
|
| struct gdbarch *gdbarch,
|
| @@ -11578,6 +11704,7 @@ init_ada_exception_breakpoint (struct breakpoint *b,
|
| char *addr_string,
|
| const struct breakpoint_ops *ops,
|
| int tempflag,
|
| + int enabled,
|
| int from_tty)
|
| {
|
| if (from_tty)
|
| @@ -11600,7 +11727,7 @@ init_ada_exception_breakpoint (struct breakpoint *b,
|
|
|
| init_raw_breakpoint (b, gdbarch, sal, bp_breakpoint, ops);
|
|
|
| - b->enable_state = bp_enabled;
|
| + b->enable_state = enabled ? bp_enabled : bp_disabled;
|
| b->disposition = tempflag ? disp_del : disp_donttouch;
|
| b->addr_string = addr_string;
|
| b->language = language_ada;
|
| @@ -11622,8 +11749,7 @@ catch_syscall_split_args (char *arg)
|
| struct syscall s;
|
|
|
| /* Skip whitespace. */
|
| - while (isspace (*arg))
|
| - arg++;
|
| + arg = skip_spaces (arg);
|
|
|
| for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
|
| cur_name[i] = arg[i];
|
| @@ -11728,7 +11854,7 @@ compare_breakpoints (const void *a, const void *b)
|
| the number 0. */
|
| if (ua < ub)
|
| return -1;
|
| - return ub > ub ? 1 : 0;
|
| + return ua > ub ? 1 : 0;
|
| }
|
|
|
| /* Delete breakpoints by address or line. */
|
| @@ -11750,6 +11876,7 @@ clear_command (char *arg, int from_tty)
|
| sals = decode_line_with_current_source (arg,
|
| (DECODE_LINE_FUNFIRSTLINE
|
| | DECODE_LINE_LIST_MODE));
|
| + make_cleanup (xfree, sals.sals);
|
| default_match = 0;
|
| }
|
| else
|
| @@ -11798,7 +11925,7 @@ clear_command (char *arg, int from_tty)
|
| make_cleanup (VEC_cleanup (breakpoint_p), &found);
|
| for (i = 0; i < sals.nelts; i++)
|
| {
|
| - int is_abs, sal_name_len;
|
| + const char *sal_fullname;
|
|
|
| /* If exact pc given, clear bpts at that pc.
|
| If line given (pc == 0), clear all bpts on specified line.
|
| @@ -11813,8 +11940,8 @@ clear_command (char *arg, int from_tty)
|
| 1 0 <can't happen> */
|
|
|
| sal = sals.sals[i];
|
| - is_abs = sal.symtab == NULL ? 1 : IS_ABSOLUTE_PATH (sal.symtab->filename);
|
| - sal_name_len = is_abs ? 0 : strlen (sal.symtab->filename);
|
| + sal_fullname = (sal.symtab == NULL
|
| + ? NULL : symtab_to_fullname (sal.symtab));
|
|
|
| /* Find all matching breakpoints and add them to 'found'. */
|
| ALL_BREAKPOINTS (b)
|
| @@ -11837,20 +11964,13 @@ clear_command (char *arg, int from_tty)
|
| int line_match = 0;
|
|
|
| if ((default_match || sal.explicit_line)
|
| - && loc->source_file != NULL
|
| - && sal.symtab != NULL
|
| + && loc->symtab != NULL
|
| + && sal_fullname != NULL
|
| && sal.pspace == loc->pspace
|
| - && loc->line_number == sal.line)
|
| - {
|
| - if (filename_cmp (loc->source_file,
|
| - sal.symtab->filename) == 0)
|
| - line_match = 1;
|
| - else if (!IS_ABSOLUTE_PATH (sal.symtab->filename)
|
| - && compare_filenames_for_search (loc->source_file,
|
| - sal.symtab->filename,
|
| - sal_name_len))
|
| - line_match = 1;
|
| - }
|
| + && loc->line_number == sal.line
|
| + && filename_cmp (symtab_to_fullname (loc->symtab),
|
| + sal_fullname) == 0)
|
| + line_match = 1;
|
|
|
| if (pc_match || line_match)
|
| {
|
| @@ -11898,7 +12018,6 @@ clear_command (char *arg, int from_tty)
|
| else
|
| printf_unfiltered (_("Deleted breakpoints "));
|
| }
|
| - breakpoints_changed ();
|
|
|
| for (ix = 0; VEC_iterate(breakpoint_p, found, ix, b); ix++)
|
| {
|
| @@ -12017,7 +12136,7 @@ bp_location_target_extensions_update (void)
|
| static void
|
| download_tracepoint_locations (void)
|
| {
|
| - struct bp_location *bl, **blp_tmp;
|
| + struct breakpoint *b;
|
| struct cleanup *old_chain;
|
|
|
| if (!target_can_download_tracepoint ())
|
| @@ -12025,31 +12144,36 @@ download_tracepoint_locations (void)
|
|
|
| old_chain = save_current_space_and_thread ();
|
|
|
| - ALL_BP_LOCATIONS (bl, blp_tmp)
|
| + ALL_TRACEPOINTS (b)
|
| {
|
| + struct bp_location *bl;
|
| struct tracepoint *t;
|
| + int bp_location_downloaded = 0;
|
|
|
| - if (!is_tracepoint (bl->owner))
|
| - continue;
|
| -
|
| - if ((bl->owner->type == bp_fast_tracepoint
|
| + if ((b->type == bp_fast_tracepoint
|
| ? !may_insert_fast_tracepoints
|
| : !may_insert_tracepoints))
|
| continue;
|
|
|
| - /* In tracepoint, locations are _never_ duplicated, so
|
| - should_be_inserted is equivalent to
|
| - unduplicated_should_be_inserted. */
|
| - if (!should_be_inserted (bl) || bl->inserted)
|
| - continue;
|
| + for (bl = b->loc; bl; bl = bl->next)
|
| + {
|
| + /* In tracepoint, locations are _never_ duplicated, so
|
| + should_be_inserted is equivalent to
|
| + unduplicated_should_be_inserted. */
|
| + if (!should_be_inserted (bl) || bl->inserted)
|
| + continue;
|
|
|
| - switch_to_program_space_and_thread (bl->pspace);
|
| + switch_to_program_space_and_thread (bl->pspace);
|
|
|
| - target_download_tracepoint (bl);
|
| + target_download_tracepoint (bl);
|
|
|
| - bl->inserted = 1;
|
| - t = (struct tracepoint *) bl->owner;
|
| - t->number_on_target = bl->owner->number;
|
| + bl->inserted = 1;
|
| + bp_location_downloaded = 1;
|
| + }
|
| + t = (struct tracepoint *) b;
|
| + t->number_on_target = b->number;
|
| + if (bp_location_downloaded)
|
| + observer_notify_breakpoint_modified (b);
|
| }
|
|
|
| do_cleanups (old_chain);
|
| @@ -12424,7 +12548,7 @@ update_global_location_list (int should_insert)
|
| struct bp_location **loc_first_p;
|
| b = loc->owner;
|
|
|
| - if (!should_be_inserted (loc)
|
| + if (!unduplicated_should_be_inserted (loc)
|
| || !breakpoint_address_is_meaningful (b)
|
| /* Don't detect duplicate for tracepoint locations because they are
|
| never duplicated. See the comments in field `duplicate' of
|
| @@ -12487,7 +12611,7 @@ update_global_location_list (int should_insert)
|
|
|
| if (breakpoints_always_inserted_mode ()
|
| && (have_live_inferiors ()
|
| - || (gdbarch_has_global_breakpoints (target_gdbarch))))
|
| + || (gdbarch_has_global_breakpoints (target_gdbarch ()))))
|
| {
|
| if (should_insert)
|
| insert_breakpoint_locations ();
|
| @@ -12563,7 +12687,6 @@ bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
|
| static void
|
| say_where (struct breakpoint *b)
|
| {
|
| - struct ui_out *uiout = current_uiout;
|
| struct value_print_options opts;
|
|
|
| get_user_print_options (&opts);
|
| @@ -12576,19 +12699,20 @@ say_where (struct breakpoint *b)
|
| }
|
| else
|
| {
|
| - if (opts.addressprint || b->loc->source_file == NULL)
|
| + if (opts.addressprint || b->loc->symtab == NULL)
|
| {
|
| printf_filtered (" at ");
|
| fputs_filtered (paddress (b->loc->gdbarch, b->loc->address),
|
| gdb_stdout);
|
| }
|
| - if (b->loc->source_file)
|
| + if (b->loc->symtab != NULL)
|
| {
|
| /* If there is a single location, we can print the location
|
| more nicely. */
|
| if (b->loc->next == NULL)
|
| printf_filtered (": file %s, line %d.",
|
| - b->loc->source_file, b->loc->line_number);
|
| + symtab_to_filename_for_display (b->loc->symtab),
|
| + b->loc->line_number);
|
| else
|
| /* This is not ideal, but each location may have a
|
| different file name, and this at least reflects the
|
| @@ -12616,7 +12740,9 @@ bp_location_dtor (struct bp_location *self)
|
| if (self->cond_bytecode)
|
| free_agent_expr (self->cond_bytecode);
|
| xfree (self->function_name);
|
| - xfree (self->source_file);
|
| +
|
| + VEC_free (agent_expr_p, self->target_info.conditions);
|
| + VEC_free (agent_expr_p, self->target_info.tcommands);
|
| }
|
|
|
| static const struct bp_location_ops bp_location_ops =
|
| @@ -12632,6 +12758,7 @@ base_breakpoint_dtor (struct breakpoint *self)
|
| {
|
| decref_counted_command_line (&self->commands);
|
| xfree (self->cond_string);
|
| + xfree (self->extra_string);
|
| xfree (self->addr_string);
|
| xfree (self->filter);
|
| xfree (self->addr_string_range_end);
|
| @@ -12739,7 +12866,6 @@ base_breakpoint_create_sals_from_address (char **arg,
|
| static void
|
| base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| struct linespec_result *c,
|
| - struct linespec_sals *lsal,
|
| char *cond_string,
|
| char *extra_string,
|
| enum bptype type_wanted,
|
| @@ -12760,7 +12886,23 @@ base_breakpoint_decode_linespec (struct breakpoint *b, char **s,
|
| internal_error_pure_virtual_called ();
|
| }
|
|
|
| -static struct breakpoint_ops base_breakpoint_ops =
|
| +/* The default 'explains_signal' method. */
|
| +
|
| +static int
|
| +base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
|
| +{
|
| + return 1;
|
| +}
|
| +
|
| +/* The default "after_condition_true" method. */
|
| +
|
| +static void
|
| +base_breakpoint_after_condition_true (struct bpstats *bs)
|
| +{
|
| + /* Nothing to do. */
|
| +}
|
| +
|
| +struct breakpoint_ops base_breakpoint_ops =
|
| {
|
| base_breakpoint_dtor,
|
| base_breakpoint_allocate_location,
|
| @@ -12779,6 +12921,8 @@ static struct breakpoint_ops base_breakpoint_ops =
|
| base_breakpoint_create_sals_from_address,
|
| base_breakpoint_create_breakpoints_sal,
|
| base_breakpoint_decode_linespec,
|
| + base_breakpoint_explains_signal,
|
| + base_breakpoint_after_condition_true,
|
| };
|
|
|
| /* Default breakpoint_ops methods. */
|
| @@ -12822,8 +12966,6 @@ bkpt_breakpoint_hit (const struct bp_location *bl,
|
| struct address_space *aspace, CORE_ADDR bp_addr,
|
| const struct target_waitstatus *ws)
|
| {
|
| - struct breakpoint *b = bl->owner;
|
| -
|
| if (ws->kind != TARGET_WAITKIND_STOPPED
|
| || ws->value.sig != GDB_SIGNAL_TRAP)
|
| return 0;
|
| @@ -12945,7 +13087,6 @@ bkpt_create_sals_from_address (char **arg,
|
| static void
|
| bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| struct linespec_result *canonical,
|
| - struct linespec_sals *lsal,
|
| char *cond_string,
|
| char *extra_string,
|
| enum bptype type_wanted,
|
| @@ -12956,7 +13097,7 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| int from_tty, int enabled,
|
| int internal, unsigned flags)
|
| {
|
| - create_breakpoints_sal_default (gdbarch, canonical, lsal,
|
| + create_breakpoints_sal_default (gdbarch, canonical,
|
| cond_string, extra_string,
|
| type_wanted,
|
| disposition, thread, task,
|
| @@ -13017,7 +13158,6 @@ internal_bkpt_check_status (bpstat bs)
|
| static enum print_stop_action
|
| internal_bkpt_print_it (bpstat bs)
|
| {
|
| - struct ui_out *uiout = current_uiout;
|
| struct breakpoint *b;
|
|
|
| b = bs->breakpoint_at;
|
| @@ -13075,7 +13215,7 @@ static void
|
| momentary_bkpt_re_set (struct breakpoint *b)
|
| {
|
| /* Keep temporary breakpoints, which can be encountered when we step
|
| - over a dlopen call and SOLIB_ADD is resetting the breakpoints.
|
| + over a dlopen call and solib_add is resetting the breakpoints.
|
| Otherwise these should have been blown away via the cleanup chain
|
| or by breakpoint_init_inferior when we rerun the executable. */
|
| }
|
| @@ -13284,7 +13424,6 @@ tracepoint_create_sals_from_address (char **arg,
|
| static void
|
| tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| struct linespec_result *canonical,
|
| - struct linespec_sals *lsal,
|
| char *cond_string,
|
| char *extra_string,
|
| enum bptype type_wanted,
|
| @@ -13295,7 +13434,7 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| int from_tty, int enabled,
|
| int internal, unsigned flags)
|
| {
|
| - create_breakpoints_sal_default (gdbarch, canonical, lsal,
|
| + create_breakpoints_sal_default (gdbarch, canonical,
|
| cond_string, extra_string,
|
| type_wanted,
|
| disposition, thread, task,
|
| @@ -13336,6 +13475,83 @@ tracepoint_probe_decode_linespec (struct breakpoint *b, char **s,
|
|
|
| static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
|
|
|
| +/* Dprintf breakpoint_ops methods. */
|
| +
|
| +static void
|
| +dprintf_re_set (struct breakpoint *b)
|
| +{
|
| + breakpoint_re_set_default (b);
|
| +
|
| + /* This breakpoint could have been pending, and be resolved now, and
|
| + if so, we should now have the extra string. If we don't, the
|
| + dprintf was malformed when created, but we couldn't tell because
|
| + we can't extract the extra string until the location is
|
| + resolved. */
|
| + if (b->loc != NULL && b->extra_string == NULL)
|
| + error (_("Format string required"));
|
| +
|
| + /* 1 - connect to target 1, that can run breakpoint commands.
|
| + 2 - create a dprintf, which resolves fine.
|
| + 3 - disconnect from target 1
|
| + 4 - connect to target 2, that can NOT run breakpoint commands.
|
| +
|
| + After steps #3/#4, you'll want the dprintf command list to
|
| + be updated, because target 1 and 2 may well return different
|
| + answers for target_can_run_breakpoint_commands().
|
| + Given absence of finer grained resetting, we get to do
|
| + it all the time. */
|
| + if (b->extra_string != NULL)
|
| + update_dprintf_command_list (b);
|
| +}
|
| +
|
| +/* Implement the "print_recreate" breakpoint_ops method for dprintf. */
|
| +
|
| +static void
|
| +dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
|
| +{
|
| + fprintf_unfiltered (fp, "dprintf %s%s", tp->addr_string,
|
| + tp->extra_string);
|
| + print_recreate_thread (tp, fp);
|
| +}
|
| +
|
| +/* Implement the "after_condition_true" breakpoint_ops method for
|
| + dprintf.
|
| +
|
| + dprintf's are implemented with regular commands in their command
|
| + list, but we run the commands here instead of before presenting the
|
| + stop to the user, as dprintf's don't actually cause a stop. This
|
| + also makes it so that the commands of multiple dprintfs at the same
|
| + address are all handled. */
|
| +
|
| +static void
|
| +dprintf_after_condition_true (struct bpstats *bs)
|
| +{
|
| + struct cleanup *old_chain;
|
| + struct bpstats tmp_bs = { NULL };
|
| + struct bpstats *tmp_bs_p = &tmp_bs;
|
| +
|
| + /* dprintf's never cause a stop. This wasn't set in the
|
| + check_status hook instead because that would make the dprintf's
|
| + condition not be evaluated. */
|
| + bs->stop = 0;
|
| +
|
| + /* Run the command list here. Take ownership of it instead of
|
| + copying. We never want these commands to run later in
|
| + bpstat_do_actions, if a breakpoint that causes a stop happens to
|
| + be set at same address as this dprintf, or even if running the
|
| + commands here throws. */
|
| + tmp_bs.commands = bs->commands;
|
| + bs->commands = NULL;
|
| + old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
|
| +
|
| + bpstat_do_actions_1 (&tmp_bs_p);
|
| +
|
| + /* 'tmp_bs.commands' will usually be NULL by now, but
|
| + bpstat_do_actions_1 may return early without processing the whole
|
| + list. */
|
| + do_cleanups (old_chain);
|
| +}
|
| +
|
| /* The breakpoint_ops structure to be used on static tracepoints with
|
| markers (`-m'). */
|
|
|
| @@ -13359,7 +13575,6 @@ strace_marker_create_sals_from_address (char **arg,
|
| static void
|
| strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| struct linespec_result *canonical,
|
| - struct linespec_sals *lsal,
|
| char *cond_string,
|
| char *extra_string,
|
| enum bptype type_wanted,
|
| @@ -13371,6 +13586,8 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
|
| int internal, unsigned flags)
|
| {
|
| int i;
|
| + struct linespec_sals *lsal = VEC_index (linespec_sals,
|
| + canonical->sals, 0);
|
|
|
| /* If the user is creating a static tracepoint by marker id
|
| (strace -m MARKER_ID), then store the sals index, so that
|
| @@ -13779,31 +13996,26 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
|
| SYMBOL_PRINT_NAME (sym));
|
| ui_out_text (uiout, " at ");
|
| }
|
| - ui_out_field_string (uiout, "file", sal2.symtab->filename);
|
| + ui_out_field_string (uiout, "file",
|
| + symtab_to_filename_for_display (sal2.symtab));
|
| ui_out_text (uiout, ":");
|
|
|
| if (ui_out_is_mi_like_p (uiout))
|
| {
|
| - char *fullname = symtab_to_fullname (sal2.symtab);
|
| + const char *fullname = symtab_to_fullname (sal2.symtab);
|
|
|
| - if (fullname)
|
| - ui_out_field_string (uiout, "fullname", fullname);
|
| + ui_out_field_string (uiout, "fullname", fullname);
|
| }
|
|
|
| ui_out_field_int (uiout, "line", sal2.line);
|
| ui_out_text (uiout, "\n");
|
|
|
| b->loc->line_number = sal2.line;
|
| -
|
| - xfree (b->loc->source_file);
|
| - if (sym)
|
| - b->loc->source_file = xstrdup (sal2.symtab->filename);
|
| - else
|
| - b->loc->source_file = NULL;
|
| + b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
|
|
|
| xfree (b->addr_string);
|
| b->addr_string = xstrprintf ("%s:%d",
|
| - sal2.symtab->filename,
|
| + symtab_to_filename_for_display (sal2.symtab),
|
| b->loc->line_number);
|
|
|
| /* Might be nice to check if function changed, and warn if
|
| @@ -13889,7 +14101,7 @@ update_breakpoint_locations (struct breakpoint *b,
|
| old symtab. */
|
| if (b->cond_string != NULL)
|
| {
|
| - char *s;
|
| + const char *s;
|
| volatile struct gdb_exception e;
|
|
|
| s = b->cond_string;
|
| @@ -14020,10 +14232,8 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
|
| resolve_sal_pc (&sals.sals[i]);
|
| if (b->condition_not_parsed && s && s[0])
|
| {
|
| - char *cond_string = 0;
|
| - int thread = -1;
|
| - int task = 0;
|
| - char *extra_string = NULL;
|
| + char *cond_string, *extra_string;
|
| + int thread, task;
|
|
|
| find_condition_and_thread (s, sals.sals[0].pc,
|
| &cond_string, &thread, &task,
|
| @@ -14099,7 +14309,6 @@ create_sals_from_address_default (char **arg,
|
| static void
|
| create_breakpoints_sal_default (struct gdbarch *gdbarch,
|
| struct linespec_result *canonical,
|
| - struct linespec_sals *lsal,
|
| char *cond_string,
|
| char *extra_string,
|
| enum bptype type_wanted,
|
| @@ -14215,9 +14424,6 @@ breakpoint_re_set (void)
|
| create_longjmp_master_breakpoint ();
|
| create_std_terminate_master_breakpoint ();
|
| create_exception_master_breakpoint ();
|
| -
|
| - /* While we're at it, reset the skip list too. */
|
| - skip_re_set ();
|
| }
|
|
|
| /* Reset the thread number of this breakpoint:
|
| @@ -14278,7 +14484,6 @@ set_ignore_count (int bptnum, int count, int from_tty)
|
| "crossings of breakpoint %d."),
|
| count, bptnum);
|
| }
|
| - breakpoints_changed ();
|
| observer_notify_breakpoint_modified (b);
|
| return;
|
| }
|
| @@ -14460,25 +14665,35 @@ disable_command (char *args, int from_tty)
|
| if (user_breakpoint_p (bpt))
|
| disable_breakpoint (bpt);
|
| }
|
| - else if (strchr (args, '.'))
|
| + else
|
| {
|
| - struct bp_location *loc = find_location_by_number (args);
|
| - if (loc)
|
| + char *num = extract_arg (&args);
|
| +
|
| + while (num)
|
| {
|
| - if (loc->enabled)
|
| + if (strchr (num, '.'))
|
| {
|
| - loc->enabled = 0;
|
| - mark_breakpoint_location_modified (loc);
|
| + struct bp_location *loc = find_location_by_number (num);
|
| +
|
| + if (loc)
|
| + {
|
| + if (loc->enabled)
|
| + {
|
| + loc->enabled = 0;
|
| + mark_breakpoint_location_modified (loc);
|
| + }
|
| + if (target_supports_enable_disable_tracepoint ()
|
| + && current_trace_status ()->running && loc->owner
|
| + && is_tracepoint (loc->owner))
|
| + target_disable_tracepoint (loc);
|
| + }
|
| + update_global_location_list (0);
|
| }
|
| - if (target_supports_enable_disable_tracepoint ()
|
| - && current_trace_status ()->running && loc->owner
|
| - && is_tracepoint (loc->owner))
|
| - target_disable_tracepoint (loc);
|
| + else
|
| + map_breakpoint_numbers (num, do_map_disable_breakpoint, NULL);
|
| + num = extract_arg (&args);
|
| }
|
| - update_global_location_list (0);
|
| }
|
| - else
|
| - map_breakpoint_numbers (args, do_map_disable_breakpoint, NULL);
|
| }
|
|
|
| static void
|
| @@ -14543,8 +14758,7 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
|
| bpt->disposition = disposition;
|
| bpt->enable_count = count;
|
| update_global_location_list (1);
|
| - breakpoints_changed ();
|
| -
|
| +
|
| observer_notify_breakpoint_modified (bpt);
|
| }
|
|
|
| @@ -14585,25 +14799,35 @@ enable_command (char *args, int from_tty)
|
| if (user_breakpoint_p (bpt))
|
| enable_breakpoint (bpt);
|
| }
|
| - else if (strchr (args, '.'))
|
| + else
|
| {
|
| - struct bp_location *loc = find_location_by_number (args);
|
| - if (loc)
|
| + char *num = extract_arg (&args);
|
| +
|
| + while (num)
|
| {
|
| - if (!loc->enabled)
|
| + if (strchr (num, '.'))
|
| {
|
| - loc->enabled = 1;
|
| - mark_breakpoint_location_modified (loc);
|
| + struct bp_location *loc = find_location_by_number (num);
|
| +
|
| + if (loc)
|
| + {
|
| + if (!loc->enabled)
|
| + {
|
| + loc->enabled = 1;
|
| + mark_breakpoint_location_modified (loc);
|
| + }
|
| + if (target_supports_enable_disable_tracepoint ()
|
| + && current_trace_status ()->running && loc->owner
|
| + && is_tracepoint (loc->owner))
|
| + target_enable_tracepoint (loc);
|
| + }
|
| + update_global_location_list (1);
|
| }
|
| - if (target_supports_enable_disable_tracepoint ()
|
| - && current_trace_status ()->running && loc->owner
|
| - && is_tracepoint (loc->owner))
|
| - target_enable_tracepoint (loc);
|
| + else
|
| + map_breakpoint_numbers (num, do_map_enable_breakpoint, NULL);
|
| + num = extract_arg (&args);
|
| }
|
| - update_global_location_list (1);
|
| }
|
| - else
|
| - map_breakpoint_numbers (args, do_map_enable_breakpoint, NULL);
|
| }
|
|
|
| /* This struct packages up disposition data for application to multiple
|
| @@ -14682,7 +14906,8 @@ show_breakpoint_cmd (char *args, int from_tty)
|
| GDB itself. */
|
|
|
| static void
|
| -invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len,
|
| +invalidate_bp_value_on_memory_change (struct inferior *inferior,
|
| + CORE_ADDR addr, ssize_t len,
|
| const bfd_byte *data)
|
| {
|
| struct breakpoint *bp;
|
| @@ -14931,11 +15156,11 @@ catching_syscall_number (int syscall_number)
|
| /* Complete syscall names. Used by "catch syscall". */
|
| static VEC (char_ptr) *
|
| catch_syscall_completer (struct cmd_list_element *cmd,
|
| - char *text, char *word)
|
| + const char *text, const char *word)
|
| {
|
| const char **list = get_syscall_names ();
|
| VEC (char_ptr) *retlist
|
| - = (list == NULL) ? NULL : complete_on_enum (list, text, word);
|
| + = (list == NULL) ? NULL : complete_on_enum (list, word, word);
|
|
|
| xfree (list);
|
| return retlist;
|
| @@ -14962,35 +15187,33 @@ trace_command (char *arg, int from_tty)
|
| else
|
| ops = &tracepoint_breakpoint_ops;
|
|
|
| - if (create_breakpoint (get_current_arch (),
|
| - arg,
|
| - NULL, 0, NULL, 1 /* parse arg */,
|
| - 0 /* tempflag */,
|
| - bp_tracepoint /* type_wanted */,
|
| - 0 /* Ignore count */,
|
| - pending_break_support,
|
| - ops,
|
| - from_tty,
|
| - 1 /* enabled */,
|
| - 0 /* internal */, 0))
|
| - set_tracepoint_count (breakpoint_count);
|
| + create_breakpoint (get_current_arch (),
|
| + arg,
|
| + NULL, 0, NULL, 1 /* parse arg */,
|
| + 0 /* tempflag */,
|
| + bp_tracepoint /* type_wanted */,
|
| + 0 /* Ignore count */,
|
| + pending_break_support,
|
| + ops,
|
| + from_tty,
|
| + 1 /* enabled */,
|
| + 0 /* internal */, 0);
|
| }
|
|
|
| static void
|
| ftrace_command (char *arg, int from_tty)
|
| {
|
| - if (create_breakpoint (get_current_arch (),
|
| - arg,
|
| - NULL, 0, NULL, 1 /* parse arg */,
|
| - 0 /* tempflag */,
|
| - bp_fast_tracepoint /* type_wanted */,
|
| - 0 /* Ignore count */,
|
| - pending_break_support,
|
| - &tracepoint_breakpoint_ops,
|
| - from_tty,
|
| - 1 /* enabled */,
|
| - 0 /* internal */, 0))
|
| - set_tracepoint_count (breakpoint_count);
|
| + create_breakpoint (get_current_arch (),
|
| + arg,
|
| + NULL, 0, NULL, 1 /* parse arg */,
|
| + 0 /* tempflag */,
|
| + bp_fast_tracepoint /* type_wanted */,
|
| + 0 /* Ignore count */,
|
| + pending_break_support,
|
| + &tracepoint_breakpoint_ops,
|
| + from_tty,
|
| + 1 /* enabled */,
|
| + 0 /* internal */, 0);
|
| }
|
|
|
| /* strace command implementation. Creates a static tracepoint. */
|
| @@ -15007,18 +15230,17 @@ strace_command (char *arg, int from_tty)
|
| else
|
| ops = &tracepoint_breakpoint_ops;
|
|
|
| - if (create_breakpoint (get_current_arch (),
|
| - arg,
|
| - NULL, 0, NULL, 1 /* parse arg */,
|
| - 0 /* tempflag */,
|
| - bp_static_tracepoint /* type_wanted */,
|
| - 0 /* Ignore count */,
|
| - pending_break_support,
|
| - ops,
|
| - from_tty,
|
| - 1 /* enabled */,
|
| - 0 /* internal */, 0))
|
| - set_tracepoint_count (breakpoint_count);
|
| + create_breakpoint (get_current_arch (),
|
| + arg,
|
| + NULL, 0, NULL, 1 /* parse arg */,
|
| + 0 /* tempflag */,
|
| + bp_static_tracepoint /* type_wanted */,
|
| + 0 /* Ignore count */,
|
| + pending_break_support,
|
| + ops,
|
| + from_tty,
|
| + 1 /* enabled */,
|
| + 0 /* internal */, 0);
|
| }
|
|
|
| /* Set up a fake reader function that gets command lines from a linked
|
| @@ -15062,7 +15284,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
|
| warning (_("Uploaded tracepoint %d has no "
|
| "source location, using raw address"),
|
| utp->number);
|
| - sprintf (small_buf, "*%s", hex_string (utp->addr));
|
| + xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (utp->addr));
|
| addr_str = small_buf;
|
| }
|
|
|
| @@ -15087,15 +15309,14 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
|
| CREATE_BREAKPOINT_FLAGS_INSERTED))
|
| return NULL;
|
|
|
| - set_tracepoint_count (breakpoint_count);
|
| -
|
| /* Get the tracepoint we just created. */
|
| tp = get_tracepoint (tracepoint_count);
|
| gdb_assert (tp != NULL);
|
|
|
| if (utp->pass > 0)
|
| {
|
| - sprintf (small_buf, "%d %d", utp->pass, tp->base.number);
|
| + xsnprintf (small_buf, sizeof (small_buf), "%d %d", utp->pass,
|
| + tp->base.number);
|
|
|
| trace_pass_command (small_buf, 0);
|
| }
|
| @@ -15208,7 +15429,7 @@ static void
|
| trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
|
| {
|
| tp->pass_count = count;
|
| - observer_notify_tracepoint_modified (tp->base.number);
|
| + observer_notify_breakpoint_modified (&tp->base);
|
| if (from_tty)
|
| printf_filtered (_("Setting tracepoint %d's passcount to %d\n"),
|
| tp->base.number, count);
|
| @@ -15232,9 +15453,7 @@ trace_pass_command (char *args, int from_tty)
|
|
|
| count = strtoul (args, &args, 10); /* Count comes first, then TP num. */
|
|
|
| - while (*args && isspace ((int) *args))
|
| - args++;
|
| -
|
| + args = skip_spaces (args);
|
| if (*args && strncasecmp (args, "all", 3) == 0)
|
| {
|
| struct breakpoint *b;
|
| @@ -15310,7 +15529,6 @@ get_tracepoint_by_number (char **arg,
|
| struct get_number_or_range_state *state,
|
| int optional_p)
|
| {
|
| - extern int tracepoint_count;
|
| struct breakpoint *t;
|
| int tpnum;
|
| char *instring = arg == NULL ? NULL : *arg;
|
| @@ -15374,7 +15592,6 @@ save_breakpoints (char *filename, int from_tty,
|
| {
|
| struct breakpoint *tp;
|
| int any = 0;
|
| - char *pathname;
|
| struct cleanup *cleanup;
|
| struct ui_file *fp;
|
| int extra_trace_bits = 0;
|
| @@ -15410,9 +15627,9 @@ save_breakpoints (char *filename, int from_tty,
|
| return;
|
| }
|
|
|
| - pathname = tilde_expand (filename);
|
| - cleanup = make_cleanup (xfree, pathname);
|
| - fp = gdb_fopen (pathname, "w");
|
| + filename = tilde_expand (filename);
|
| + cleanup = make_cleanup (xfree, filename);
|
| + fp = gdb_fopen (filename, "w");
|
| if (!fp)
|
| error (_("Unable to open file '%s' for saving (%s)"),
|
| filename, safe_strerror (errno));
|
| @@ -15443,7 +15660,7 @@ save_breakpoints (char *filename, int from_tty,
|
| if (tp->ignore_count)
|
| fprintf_unfiltered (fp, " ignore $bpnum %d\n", tp->ignore_count);
|
|
|
| - if (tp->commands)
|
| + if (tp->type != bp_dprintf && tp->commands)
|
| {
|
| volatile struct gdb_exception ex;
|
|
|
| @@ -15482,9 +15699,9 @@ save_breakpoints (char *filename, int from_tty,
|
| if (extra_trace_bits && *default_collect)
|
| fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
|
|
|
| - do_cleanups (cleanup);
|
| if (from_tty)
|
| printf_filtered (_("Saved to file '%s'.\n"), filename);
|
| + do_cleanups (cleanup);
|
| }
|
|
|
| /* The `save breakpoints' command. */
|
| @@ -15647,6 +15864,18 @@ pc_at_non_inline_function (struct address_space *aspace, CORE_ADDR pc,
|
| return 0;
|
| }
|
|
|
| +/* Remove any references to OBJFILE which is going to be freed. */
|
| +
|
| +void
|
| +breakpoint_free_objfile (struct objfile *objfile)
|
| +{
|
| + struct bp_location **locp, *loc;
|
| +
|
| + ALL_BP_LOCATIONS (loc, locp)
|
| + if (loc->symtab != NULL && loc->symtab->objfile == objfile)
|
| + loc->symtab = NULL;
|
| +}
|
| +
|
| void
|
| initialize_breakpoint_ops (void)
|
| {
|
| @@ -15720,14 +15949,6 @@ initialize_breakpoint_ops (void)
|
| ops->create_sals_from_address = bkpt_probe_create_sals_from_address;
|
| ops->decode_linespec = bkpt_probe_decode_linespec;
|
|
|
| - /* GNU v3 exception catchpoints. */
|
| - ops = &gnu_v3_exception_catchpoint_ops;
|
| - *ops = bkpt_breakpoint_ops;
|
| - ops->print_it = print_it_exception_catchpoint;
|
| - ops->print_one = print_one_exception_catchpoint;
|
| - ops->print_mention = print_mention_exception_catchpoint;
|
| - ops->print_recreate = print_recreate_exception_catchpoint;
|
| -
|
| /* Watchpoints. */
|
| ops = &watchpoint_breakpoint_ops;
|
| *ops = base_breakpoint_ops;
|
| @@ -15742,6 +15963,7 @@ initialize_breakpoint_ops (void)
|
| ops->print_it = print_it_watchpoint;
|
| ops->print_mention = print_mention_watchpoint;
|
| ops->print_recreate = print_recreate_watchpoint;
|
| + ops->explains_signal = explains_signal_watchpoint;
|
|
|
| /* Masked watchpoints. */
|
| ops = &masked_watchpoint_breakpoint_ops;
|
| @@ -15841,13 +16063,18 @@ initialize_breakpoint_ops (void)
|
|
|
| ops = &dprintf_breakpoint_ops;
|
| *ops = bkpt_base_breakpoint_ops;
|
| - ops->re_set = bkpt_re_set;
|
| + ops->re_set = dprintf_re_set;
|
| ops->resources_needed = bkpt_resources_needed;
|
| ops->print_it = bkpt_print_it;
|
| ops->print_mention = bkpt_print_mention;
|
| - ops->print_recreate = bkpt_print_recreate;
|
| + ops->print_recreate = dprintf_print_recreate;
|
| + ops->after_condition_true = dprintf_after_condition_true;
|
| }
|
|
|
| +/* Chain containing all defined "enable breakpoint" subcommands. */
|
| +
|
| +static struct cmd_list_element *enablebreaklist = NULL;
|
| +
|
| void
|
| _initialize_breakpoint (void)
|
| {
|
| @@ -15856,6 +16083,7 @@ _initialize_breakpoint (void)
|
| initialize_breakpoint_ops ();
|
|
|
| observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
|
| + observer_attach_free_objfile (disable_breakpoints_in_freed_objfile);
|
| observer_attach_inferior_exit (clear_syscall_counts);
|
| observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
|
|
|
| @@ -15863,7 +16091,8 @@ _initialize_breakpoint (void)
|
| = register_objfile_data_with_cleanup (NULL, free_breakpoint_probes);
|
|
|
| catch_syscall_inferior_data
|
| - = register_inferior_data_with_cleanup (catch_syscall_inferior_data_cleanup);
|
| + = register_inferior_data_with_cleanup (NULL,
|
| + catch_syscall_inferior_data_cleanup);
|
|
|
| breakpoint_chain = 0;
|
| /* Don't bother to call set_breakpoint_count. $bpnum isn't useful
|
| @@ -16138,19 +16367,6 @@ Set temporary catchpoints to catch events."),
|
| &tcatch_cmdlist, "tcatch ",
|
| 0/*allow-unknown*/, &cmdlist);
|
|
|
| - /* Add catch and tcatch sub-commands. */
|
| - add_catch_command ("catch", _("\
|
| -Catch an exception, when caught."),
|
| - catch_catch_command,
|
| - NULL,
|
| - CATCH_PERMANENT,
|
| - CATCH_TEMPORARY);
|
| - add_catch_command ("throw", _("\
|
| -Catch an exception, when thrown."),
|
| - catch_throw_command,
|
| - NULL,
|
| - CATCH_PERMANENT,
|
| - CATCH_TEMPORARY);
|
| add_catch_command ("fork", _("Catch calls to fork."),
|
| catch_fork_command_1,
|
| NULL,
|
| @@ -16296,6 +16512,7 @@ Delete specified tracepoints.\n\
|
| Arguments are tracepoint numbers, separated by spaces.\n\
|
| No argument means delete all tracepoints."),
|
| &deletelist);
|
| + add_alias_cmd ("tr", "tracepoints", class_trace, 1, &deletelist);
|
|
|
| c = add_cmd ("tracepoints", class_trace, disable_trace_command, _("\
|
| Disable specified tracepoints.\n\
|
| @@ -16434,8 +16651,7 @@ Set a dynamic printf at specified line or function.\n\
|
| dprintf location,format string,arg1,arg2,...\n\
|
| location may be a line number, function name, or \"*\" and an address.\n\
|
| If a line number is specified, break at start of code for that line.\n\
|
| -If a function is specified, break at start of code for that function.\n\
|
| -"));
|
| +If a function is specified, break at start of code for that function."));
|
| set_cmd_completer (c, location_completer);
|
|
|
| add_setshow_enum_cmd ("dprintf-style", class_support,
|
| @@ -16484,4 +16700,5 @@ agent-printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
|
| automatic_hardware_breakpoints = 1;
|
|
|
| observer_attach_about_to_proceed (breakpoint_about_to_proceed);
|
| + observer_attach_thread_exit (remove_threaded_breakpoints);
|
| }
|
|
|