+static void
+bkpt_probe_create_sals_from_address (char **arg,
+ struct linespec_result *canonical,
+ enum bptype type_wanted,
+ char *addr_start, char **copy_arg)
+{
+ struct linespec_sals lsal;
+
+ lsal.sals = parse_probes (arg, canonical);
+
+ *copy_arg = xstrdup (canonical->addr_string);
+ lsal.canonical = xstrdup (*copy_arg);
+
+ VEC_safe_push (linespec_sals, canonical->sals, &lsal);
+}
+
+static void
+bkpt_probe_decode_linespec (struct breakpoint *b, char **s,
+ struct symtabs_and_lines *sals)
+{
+ *sals = parse_probes (s, NULL);
+ if (!sals->sals)
+ error (_("probe not found"));
+}
+
+/* The breakpoint_ops structure to be used in tracepoints. */
+
+static void
+tracepoint_re_set (struct breakpoint *b)
+{
+ breakpoint_re_set_default (b);
+}
+
+static int
+tracepoint_breakpoint_hit (const struct bp_location *bl,
+ struct address_space *aspace, CORE_ADDR bp_addr,
+ const struct target_waitstatus *ws)
+{
+ /* By definition, the inferior does not report stops at
+ tracepoints. */
+ return 0;
+}
+
+static void
+tracepoint_print_one_detail (const struct breakpoint *self,
+ struct ui_out *uiout)
+{
+ struct tracepoint *tp = (struct tracepoint *) self;
+ if (tp->static_trace_marker_id)
+ {
+ gdb_assert (self->type == bp_static_tracepoint);
+
+ ui_out_text (uiout, "\tmarker id is ");
+ ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
+ tp->static_trace_marker_id);
+ ui_out_text (uiout, "\n");
+ }
+}
+
+static void
+tracepoint_print_mention (struct breakpoint *b)
+{
+ if (ui_out_is_mi_like_p (current_uiout))
+ return;
+
+ switch (b->type)
+ {
+ case bp_tracepoint:
+ printf_filtered (_("Tracepoint"));
+ printf_filtered (_(" %d"), b->number);
+ break;
+ case bp_fast_tracepoint:
+ printf_filtered (_("Fast tracepoint"));
+ printf_filtered (_(" %d"), b->number);
+ break;
+ case bp_static_tracepoint:
+ printf_filtered (_("Static tracepoint"));
+ printf_filtered (_(" %d"), b->number);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("unhandled tracepoint type %d"), (int) b->type);
+ }
+
+ say_where (b);
+}
+
+static void
+tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
+{
+ struct tracepoint *tp = (struct tracepoint *) self;
+
+ if (self->type == bp_fast_tracepoint)
+ fprintf_unfiltered (fp, "ftrace");
+ if (self->type == bp_static_tracepoint)
+ fprintf_unfiltered (fp, "strace");
+ else if (self->type == bp_tracepoint)
+ fprintf_unfiltered (fp, "trace");
+ else
+ internal_error (__FILE__, __LINE__,
+ _("unhandled tracepoint type %d"), (int) self->type);
+
+ fprintf_unfiltered (fp, " %s", self->addr_string);
+ print_recreate_thread (self, fp);
+
+ if (tp->pass_count)
+ fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count);
+}
+
+static void
+tracepoint_create_sals_from_address (char **arg,
+ struct linespec_result *canonical,
+ enum bptype type_wanted,
+ char *addr_start, char **copy_arg)
+{
+ create_sals_from_address_default (arg, canonical, type_wanted,
+ addr_start, copy_arg);
+}
+
+static void
+tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
+ struct linespec_result *canonical,
+ struct linespec_sals *lsal,
+ char *cond_string,
+ enum bptype type_wanted,
+ enum bpdisp disposition,
+ int thread,
+ int task, int ignore_count,
+ const struct breakpoint_ops *ops,
+ int from_tty, int enabled,
+ int internal, unsigned flags)
+{
+ create_breakpoints_sal_default (gdbarch, canonical, lsal,
+ cond_string, type_wanted,
+ disposition, thread, task,
+ ignore_count, ops, from_tty,
+ enabled, internal, flags);
+}
+
+static void
+tracepoint_decode_linespec (struct breakpoint *b, char **s,
+ struct symtabs_and_lines *sals)
+{
+ decode_linespec_default (b, s, sals);
+}
+
+struct breakpoint_ops tracepoint_breakpoint_ops;
+
+/* The breakpoint_ops structure to be use on tracepoints placed in a
+ static probe. */
+
+static void
+tracepoint_probe_create_sals_from_address (char **arg,
+ struct linespec_result *canonical,
+ enum bptype type_wanted,
+ char *addr_start, char **copy_arg)
+{
+ /* We use the same method for breakpoint on probes. */
+ bkpt_probe_create_sals_from_address (arg, canonical, type_wanted,
+ addr_start, copy_arg);
+}
+
+static void
+tracepoint_probe_decode_linespec (struct breakpoint *b, char **s,
+ struct symtabs_and_lines *sals)
+{
+ /* We use the same method for breakpoint on probes. */
+ bkpt_probe_decode_linespec (b, s, sals);
+}
+
+static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
+
+/* The breakpoint_ops structure to be used on static tracepoints with
+ markers (`-m'). */
+
+static void
+strace_marker_create_sals_from_address (char **arg,
+ struct linespec_result *canonical,
+ enum bptype type_wanted,
+ char *addr_start, char **copy_arg)
+{
+ struct linespec_sals lsal;
+
+ lsal.sals = decode_static_tracepoint_spec (arg);
+
+ *copy_arg = savestring (addr_start, *arg - addr_start);
+
+ canonical->addr_string = xstrdup (*copy_arg);
+ lsal.canonical = xstrdup (*copy_arg);
+ VEC_safe_push (linespec_sals, canonical->sals, &lsal);
+}
+
+static void
+strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
+ struct linespec_result *canonical,
+ struct linespec_sals *lsal,
+ char *cond_string,
+ enum bptype type_wanted,
+ enum bpdisp disposition,
+ int thread,
+ int task, int ignore_count,
+ const struct breakpoint_ops *ops,
+ int from_tty, int enabled,
+ int internal, unsigned flags)
+{
+ int i;
+
+ /* If the user is creating a static tracepoint by marker id
+ (strace -m MARKER_ID), then store the sals index, so that
+ breakpoint_re_set can try to match up which of the newly
+ found markers corresponds to this one, and, don't try to
+ expand multiple locations for each sal, given than SALS
+ already should contain all sals for MARKER_ID. */
+
+ for (i = 0; i < lsal->sals.nelts; ++i)
+ {
+ struct symtabs_and_lines expanded;
+ struct tracepoint *tp;
+ struct cleanup *old_chain;
+ char *addr_string;
+
+ expanded.nelts = 1;
+ expanded.sals = &lsal->sals.sals[i];
+
+ addr_string = xstrdup (canonical->addr_string);
+ old_chain = make_cleanup (xfree, addr_string);
+
+ tp = XCNEW (struct tracepoint);
+ init_breakpoint_sal (&tp->base, gdbarch, expanded,
+ addr_string, NULL,
+ cond_string, type_wanted, disposition,
+ thread, task, ignore_count, ops,
+ from_tty, enabled, internal, flags,
+ canonical->special_display);
+ /* Given that its possible to have multiple markers with
+ the same string id, if the user is creating a static
+ tracepoint by marker id ("strace -m MARKER_ID"), then
+ store the sals index, so that breakpoint_re_set can
+ try to match up which of the newly found markers
+ corresponds to this one */
+ tp->static_trace_marker_id_idx = i;
+
+ install_breakpoint (internal, &tp->base, 0);
+
+ discard_cleanups (old_chain);
+ }
+}
+
+static void
+strace_marker_decode_linespec (struct breakpoint *b, char **s,
+ struct symtabs_and_lines *sals)
+{
+ struct tracepoint *tp = (struct tracepoint *) b;
+
+ *sals = decode_static_tracepoint_spec (s);
+ if (sals->nelts > tp->static_trace_marker_id_idx)
+ {
+ sals->sals[0] = sals->sals[tp->static_trace_marker_id_idx];
+ sals->nelts = 1;
+ }
+ else
+ error (_("marker %s not found"), tp->static_trace_marker_id);
+}
+
+static struct breakpoint_ops strace_marker_breakpoint_ops;
+
+static int
+strace_marker_p (struct breakpoint *b)
+{
+ return b->ops == &strace_marker_breakpoint_ops;
+}
+
+/* Delete a breakpoint and clean up all traces of it in the data
+ structures. */
+
+void
+delete_breakpoint (struct breakpoint *bpt)
+{
+ struct breakpoint *b;
+
+ gdb_assert (bpt != NULL);
+
+ /* Has this bp already been deleted? This can happen because
+ multiple lists can hold pointers to bp's. bpstat lists are
+ especial culprits.
+
+ One example of this happening is a watchpoint's scope bp. When
+ the scope bp triggers, we notice that the watchpoint is out of
+ scope, and delete it. We also delete its scope bp. But the
+ scope bp is marked "auto-deleting", and is already on a bpstat.
+ That bpstat is then checked for auto-deleting bp's, which are
+ deleted.
+
+ A real solution to this problem might involve reference counts in
+ bp's, and/or giving them pointers back to their referencing
+ bpstat's, and teaching delete_breakpoint to only free a bp's
+ storage when no more references were extent. A cheaper bandaid
+ was chosen. */
+ if (bpt->type == bp_none)
+ return;
+
+ /* At least avoid this stale reference until the reference counting
+ of breakpoints gets resolved. */
+ if (bpt->related_breakpoint != bpt)
+ {
+ struct breakpoint *related;
+ struct watchpoint *w;
+
+ if (bpt->type == bp_watchpoint_scope)
+ w = (struct watchpoint *) bpt->related_breakpoint;
+ else if (bpt->related_breakpoint->type == bp_watchpoint_scope)
+ w = (struct watchpoint *) bpt;
+ else
+ w = NULL;
+ if (w != NULL)
+ watchpoint_del_at_next_stop (w);
+
+ /* Unlink bpt from the bpt->related_breakpoint ring. */
+ for (related = bpt; related->related_breakpoint != bpt;
+ related = related->related_breakpoint);
+ related->related_breakpoint = bpt->related_breakpoint;
+ bpt->related_breakpoint = bpt;
+ }
+
+ /* watch_command_1 creates a watchpoint but only sets its number if
+ update_watchpoint succeeds in creating its bp_locations. If there's
+ a problem in that process, we'll be asked to delete the half-created
+ watchpoint. In that case, don't announce the deletion. */
+ if (bpt->number)
+ observer_notify_breakpoint_deleted (bpt);
+
+ if (breakpoint_chain == bpt)
+ breakpoint_chain = bpt->next;
+
+ ALL_BREAKPOINTS (b)
+ if (b->next == bpt)
+ {
+ b->next = bpt->next;
+ break;
+ }
+
+ /* Be sure no bpstat's are pointing at the breakpoint after it's
+ been freed. */
+ /* FIXME, how can we find all bpstat's? We just check stop_bpstat
+ in all threads for now. Note that we cannot just remove bpstats
+ pointing at bpt from the stop_bpstat list entirely, as breakpoint
+ commands are associated with the bpstat; if we remove it here,
+ then the later call to bpstat_do_actions (&stop_bpstat); in
+ event-top.c won't do anything, and temporary breakpoints with
+ commands won't work. */
+
+ iterate_over_threads (bpstat_remove_breakpoint_callback, bpt);
+
+ /* Now that breakpoint is removed from breakpoint list, update the
+ global location list. This will remove locations that used to
+ belong to this breakpoint. Do this before freeing the breakpoint
+ itself, since remove_breakpoint looks at location's owner. It
+ might be better design to have location completely
+ self-contained, but it's not the case now. */
+ update_global_location_list (0);