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); |
} |