enum exception_event_kind
{
EX_EVENT_THROW,
+ EX_EVENT_RETHROW,
EX_EVENT_CATCH
};
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);
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
}
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. */
}
mark_breakpoint_modified (b);
- annotate_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;
}
/* We're completing the expression part. */
- text = skip_spaces (space);
+ text = skip_spaces_const (space);
return expression_completer (cmd, text, word);
}
{
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)
else
while_stepping = c;
}
+
+ validate_actionline (c->line, b);
}
if (while_stepping)
{
decref_counted_command_line (&b->commands);
b->commands = alloc_counted_command_line (commands);
- annotate_breakpoints_changed ();
observer_notify_breakpoint_modified (b);
}
{
struct breakpoint *b = closure;
- validate_actionline (&line, b);
+ validate_actionline (line, b);
}
/* A structure used to pass information through
incref_counted_command_line (info->cmd);
decref_counted_command_line (&b->commands);
b->commands = info->cmd;
- annotate_breakpoints_changed ();
observer_notify_breakpoint_modified (b);
}
}
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,
if (within_current_scope && reparse)
{
- char *s;
+ const char *s;
if (b->exp)
{
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)
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 ();
if (*cmdrest == ',')
++cmdrest;
- cmdrest = skip_spaces (cmdrest);
+ cmdrest = skip_spaces_const (cmdrest);
if (*cmdrest++ != '"')
error (_("No format string following the location"));
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. */
nargs = 0;
while (*cmdrest != '\0')
{
- char *cmd1;
+ const char *cmd1;
cmd1 = cmdrest;
expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
return NULL;
}
+/* See breakpoint.h. */
+
+enum bpstat_signal_value
+bpstat_explains_signal (bpstat bsp)
+{
+ enum bpstat_signal_value result = BPSTAT_SIGNAL_NO;
+
+ for (; bsp != NULL; bsp = bsp->next)
+ {
+ /* Ensure that, if we ever entered this loop, then we at least
+ return BPSTAT_SIGNAL_HIDE. */
+ enum bpstat_signal_value newval = BPSTAT_SIGNAL_HIDE;
+
+ if (bsp->breakpoint_at != NULL)
+ newval = bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at);
+
+ if (newval > result)
+ result = newval;
+ }
+
+ return result;
+}
+
/* 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
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);
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);
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);
- const char *fullname = symtab_to_fullname (sal.symtab);
-
- 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);
}
return bptypes[(int) type].description;
}
+DEF_VEC_I(int);
+
+/* 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 = make_cleanup_ui_out_list_begin_end (uiout,
+ field_name);
+ 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;
+
+ 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
}
- /* 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)
program space. */
if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint)
b->pspace = sal.pspace;
-
- annotate_breakpoints_changed ();
}
/* set_raw_breakpoint is a low level routine for allocating and
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
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,
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;
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;
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);
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)
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)
{
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)
{
return;
}
- end_tok = skip_to_space (tok);
+ end_tok = skip_to_space_const (tok);
toklen = end_tok - tok;
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))
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)
{
/* 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,
lsal = VEC_index (linespec_sals, canonical.sals, 0);
- if (parse_condition_and_thread)
+ if (parse_arg)
{
char *rest;
/* Here we only parse 'arg' to separate condition
}
else
{
+ if (*arg != '\0')
+ error (_("Garbage '%s' at end of location"), arg);
+
/* Create a private copy of condition string. */
if (cond_string)
{
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
{
{
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
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
{
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);
}
case OP_TYPE:
case OP_TYPEOF:
case OP_DECLTYPE:
+ case OP_TYPEID:
case OP_NAME:
case OP_OBJC_NSSTRING:
{
struct cleanup *old_chain;
struct breakpoint *b;
- const struct bp_location *bl;
struct ui_file *stb;
enum print_stop_action result;
struct watchpoint *w;
gdb_assert (bs->bp_location_at != NULL);
- bl = bs->bp_location_at;
b = bs->breakpoint_at;
w = (struct watchpoint *) 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;
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;
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'))
/* 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.
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)
}
install_breakpoint (internal, b, 1);
+ do_cleanups (back_to);
}
/* Return count of debug registers needed to watch the given expression.
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;
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");
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "throw");
- }
- else
- {
- ui_out_field_string (uiout, "what", "exception catch");
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "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,
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];
make_cleanup (VEC_cleanup (breakpoint_p), &found);
for (i = 0; i < sals.nelts; i++)
{
- int is_abs;
+ const char *sal_fullname;
/* If exact pc given, clear bpts at that pc.
If line given (pc == 0), clear all bpts on specified line.
1 0 <can't happen> */
sal = sals.sals[i];
- is_abs = sal.symtab == NULL ? 1 : IS_ABSOLUTE_PATH (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)
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))
- 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)
{
else
printf_unfiltered (_("Deleted breakpoints "));
}
- annotate_breakpoints_changed ();
for (ix = 0; VEC_iterate(breakpoint_p, found, ix, b); ix++)
{
static void
say_where (struct breakpoint *b)
{
- struct ui_out *uiout = current_uiout;
struct value_print_options opts;
get_user_print_options (&opts);
}
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
if (self->cond_bytecode)
free_agent_expr (self->cond_bytecode);
xfree (self->function_name);
- xfree (self->source_file);
}
static const struct bp_location_ops bp_location_ops =
{
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);
internal_error_pure_virtual_called ();
}
-static struct breakpoint_ops base_breakpoint_ops =
+/* The default 'explains_signal' method. */
+
+static enum bpstat_signal_value
+base_breakpoint_explains_signal (struct breakpoint *b)
+{
+ return BPSTAT_SIGNAL_HIDE;
+}
+
+struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
base_breakpoint_allocate_location,
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
+ base_breakpoint_explains_signal
};
/* Default breakpoint_ops methods. */
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;
static enum print_stop_action
internal_bkpt_print_it (bpstat bs)
{
- struct ui_out *uiout = current_uiout;
struct breakpoint *b;
b = bs->breakpoint_at;
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);
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
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))
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
old symtab. */
if (b->cond_string != NULL)
{
- char *s;
+ const char *s;
volatile struct gdb_exception e;
s = b->cond_string;
"crossings of breakpoint %d."),
count, bptnum);
}
- annotate_breakpoints_changed ();
observer_notify_breakpoint_modified (b);
return;
}
bpt->disposition = disposition;
bpt->enable_count = count;
update_global_location_list (1);
- annotate_breakpoints_changed ();
-
+
observer_notify_breakpoint_modified (bpt);
}
/* 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
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;
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)
{
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;
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;
&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,