#include "jit.h"
#include "xml-syscall.h"
#include "parser-defs.h"
+#include "gdb_regex.h"
+#include "probe.h"
#include "cli/cli-utils.h"
#include "continuations.h"
#include "stack.h"
breakpoints. */
struct breakpoint_ops bkpt_breakpoint_ops;
+/* Breakpoints set on probes. */
+static struct breakpoint_ops bkpt_probe_breakpoint_ops;
+
/* A reference-counted struct command_line. This lets multiple
breakpoints share a single command list. */
struct counted_command_line
/* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */
struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES];
+ /* True if we have looked for longjmp probes. */
+ int longjmp_searched;
+
+ /* SystemTap probe points for longjmp (if any). */
+ VEC (probe_p) *longjmp_probes;
+
/* Minimal symbol for "std::terminate()" (if any). */
struct minimal_symbol *terminate_msym;
/* Minimal symbol for "_Unwind_DebugHook" (if any). */
struct minimal_symbol *exception_msym;
+
+ /* True if we have looked for exception probes. */
+ int exception_searched;
+
+ /* SystemTap probe points for unwinding (if any). */
+ VEC (probe_p) *exception_probes;
};
static const struct objfile_data *breakpoint_objfile_key;
return bp_objfile_data;
}
+static void
+free_breakpoint_probes (struct objfile *obj, void *data)
+{
+ struct breakpoint_objfile_data *bp_objfile_data = data;
+
+ VEC_free (probe_p, bp_objfile_data->longjmp_probes);
+ VEC_free (probe_p, bp_objfile_data->exception_probes);
+}
+
static void
create_overlay_event_breakpoint (void)
{
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");
+ bp_objfile_data->longjmp_searched = 1;
+ }
+
+ if (bp_objfile_data->longjmp_probes != NULL)
+ {
+ int i;
+ struct probe *probe;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
+ for (i = 0;
+ VEC_iterate (probe_p,
+ bp_objfile_data->longjmp_probes,
+ i, probe);
+ ++i)
+ {
+ struct breakpoint *b;
+
+ b = create_internal_breakpoint (gdbarch, probe->address,
+ bp_longjmp_master,
+ &internal_breakpoint_ops);
+ b->addr_string = xstrdup ("-probe-stap libc:longjmp");
+ b->enable_state = bp_disabled;
+ }
+
+ continue;
+ }
+
for (i = 0; i < NUM_LONGJMP_NAMES; i++)
{
struct breakpoint *b;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
+ /* 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");
+ bp_objfile_data->exception_searched = 1;
+ }
+
+ if (bp_objfile_data->exception_probes != NULL)
+ {
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ int i;
+ struct probe *probe;
+
+ for (i = 0;
+ VEC_iterate (probe_p,
+ bp_objfile_data->exception_probes,
+ i, probe);
+ ++i)
+ {
+ struct breakpoint *b;
+
+ b = create_internal_breakpoint (gdbarch, probe->address,
+ bp_exception_master,
+ &internal_breakpoint_ops);
+ b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
+ b->enable_state = bp_disabled;
+ }
+
+ continue;
+ }
+
+ /* Otherwise, try the hook function. */
+
if (msym_not_found_p (bp_objfile_data->exception_msym))
continue;
copy->loc->address = orig->loc->address;
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);
loc->requested_address = sal->pc;
loc->address = adjusted_address;
loc->pspace = sal->pspace;
+ loc->probe = sal->probe;
gdb_assert (loc->pspace != NULL);
loc->section = sal->section;
loc->gdbarch = loc_gdbarch;
enum bptype type_wanted = (flag & BP_HARDWAREFLAG
? bp_hardware_breakpoint
: bp_breakpoint);
+ struct breakpoint_ops *ops;
+ const char *arg_cp = arg;
+
+ /* Matching breakpoints on probes. */
+ if (arg && probe_linespec_to_ops (&arg_cp) != NULL)
+ ops = &bkpt_probe_breakpoint_ops;
+ else
+ ops = &bkpt_breakpoint_ops;
create_breakpoint (get_current_arch (),
arg,
tempflag, type_wanted,
0 /* Ignore count */,
pending_break_support,
- &bkpt_breakpoint_ops,
+ ops,
from_tty,
1 /* enabled */,
0 /* internal */,
/* Nothing to mention. These breakpoints are internal. */
}
+/* Specific methods for probe breakpoints. */
+
+static int
+bkpt_probe_insert_location (struct bp_location *bl)
+{
+ int v = bkpt_insert_location (bl);
+
+ if (v == 0)
+ {
+ /* The insertion was successful, now let's set the probe's semaphore
+ if needed. */
+ bl->probe->pops->set_semaphore (bl->probe, bl->gdbarch);
+ }
+
+ return v;
+}
+
+static int
+bkpt_probe_remove_location (struct bp_location *bl)
+{
+ /* Let's clear the semaphore before removing the location. */
+ bl->probe->pops->clear_semaphore (bl->probe, bl->gdbarch);
+
+ return bkpt_remove_location (bl);
+}
+
+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
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
trace_command (char *arg, int from_tty)
{
+ struct breakpoint_ops *ops;
+ const char *arg_cp = arg;
+
+ if (arg && probe_linespec_to_ops (&arg_cp))
+ ops = &tracepoint_probe_breakpoint_ops;
+ else
+ ops = &tracepoint_breakpoint_ops;
+
if (create_breakpoint (get_current_arch (),
arg,
NULL, 0, 1 /* parse arg */,
bp_tracepoint /* type_wanted */,
0 /* Ignore count */,
pending_break_support,
- &tracepoint_breakpoint_ops,
+ ops,
from_tty,
1 /* enabled */,
0 /* internal */, 0))
ops->print_it = momentary_bkpt_print_it;
ops->print_mention = momentary_bkpt_print_mention;
+ /* Probe breakpoints. */
+ ops = &bkpt_probe_breakpoint_ops;
+ *ops = bkpt_breakpoint_ops;
+ ops->insert_location = bkpt_probe_insert_location;
+ ops->remove_location = bkpt_probe_remove_location;
+ 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->create_breakpoints_sal = tracepoint_create_breakpoints_sal;
ops->decode_linespec = tracepoint_decode_linespec;
+ /* Probe tracepoints. */
+ ops = &tracepoint_probe_breakpoint_ops;
+ *ops = tracepoint_breakpoint_ops;
+ ops->create_sals_from_address = tracepoint_probe_create_sals_from_address;
+ ops->decode_linespec = tracepoint_probe_decode_linespec;
+
/* Static tracepoints with marker (`-m'). */
ops = &strace_marker_breakpoint_ops;
*ops = tracepoint_breakpoint_ops;
observer_attach_inferior_exit (clear_syscall_counts);
observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
- breakpoint_objfile_key = register_objfile_data ();
+ breakpoint_objfile_key
+ = register_objfile_data_with_cleanup (NULL, free_breakpoint_probes);
catch_syscall_inferior_data
= register_inferior_data_with_cleanup (catch_syscall_inferior_data_cleanup);