X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=ab5f3240fb7f967cdca22a0b2ec8e9342901b5e7;hb=623b6bdf12dec583722ca6615e5ff26581597d6c;hp=1158f0e229b24ea63087b60bae438696c5fe01da;hpb=d1cda5d93997962a4289008b871156e5f1ab22e6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 1158f0e229..ab5f3240fb 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -60,11 +60,12 @@ #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" #include "skip.h" -#include "record.h" #include "gdb_regex.h" #include "ax-gdb.h" @@ -112,7 +113,7 @@ static void create_breakpoints_sal_default (struct gdbarch *, enum bpdisp, int, int, int, const struct breakpoint_ops *, - int, int, int); + int, int, int, unsigned); static void decode_linespec_default (struct breakpoint *, char **, struct symtabs_and_lines *); @@ -290,6 +291,9 @@ static struct breakpoint_ops momentary_breakpoint_ops; 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 @@ -404,9 +408,8 @@ show_always_inserted_mode (struct ui_file *file, int from_tty, int breakpoints_always_inserted_mode (void) { - return ((always_inserted_mode == always_inserted_on - || (always_inserted_mode == always_inserted_auto && non_stop)) - && !RECORD_IS_USED); + return (always_inserted_mode == always_inserted_on + || (always_inserted_mode == always_inserted_auto && non_stop)); } static const char condition_evaluation_both[] = "host or target"; @@ -1318,6 +1321,10 @@ bp_location_has_shadow (struct bp_location *bl) /* Update BUF, which is LEN bytes read from the target address MEMADDR, by replacing any memory breakpoints with their shadowed contents. + If READBUF is not NULL, this buffer must not overlap with any of + the breakpoint location's shadow_contents buffers. Otherwise, + a failed assertion internal error will be raised. + The range of shadowed area by each bp_location is: bl->address - bp_location_placed_address_before_address_max up to bl->address + bp_location_shadow_len_after_address_max @@ -1446,6 +1453,12 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, if (readbuf != NULL) { + /* Verify that the readbuf buffer does not overlap with + the shadow_contents buffer. */ + gdb_assert (bl->target_info.shadow_contents >= readbuf + len + || readbuf >= (bl->target_info.shadow_contents + + bl->target_info.shadow_len)); + /* Update the read buffer with this inserted breakpoint's shadow. */ memcpy (readbuf + bp_addr - memaddr, @@ -2082,8 +2095,15 @@ insert_bp_location (struct bp_location *bl, if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update)) return 0; - /* Initialize the target-specific information. */ - memset (&bl->target_info, 0, sizeof (bl->target_info)); + /* Note we don't initialize bl->target_info, as that wipes out + the breakpoint location's shadow_contents if the breakpoint + is still inserted at that location. This in turn breaks + target_read_memory which depends on these buffers when + a memory read is requested at the breakpoint location: + Once the target_info has been wiped, we fail to see that + we have a breakpoint inserted at that address and thus + read the breakpoint instead of returning the data saved in + the breakpoint location's shadow contents. */ bl->target_info.placed_address = bl->address; bl->target_info.placed_address_space = bl->pspace->aspace; bl->target_info.length = bl->length; @@ -2408,6 +2428,19 @@ insert_breakpoints (void) insert_breakpoint_locations (); } +/* Invoke CALLBACK for each of bp_location. */ + +void +iterate_over_bp_locations (walk_bp_location_callback callback) +{ + struct bp_location *loc, **loc_tmp; + + ALL_BP_LOCATIONS (loc, loc_tmp) + { + callback (loc, NULL); + } +} + /* This is used when we need to synch breakpoint conditions between GDB and the target. It is the case with deleting and disabling of breakpoints when using always-inserted mode. */ @@ -2711,11 +2744,23 @@ struct breakpoint_objfile_data /* 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; @@ -2751,6 +2796,15 @@ get_breakpoint_objfile_data (struct objfile *objfile) 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) { @@ -2828,6 +2882,37 @@ create_longjmp_master_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; @@ -2938,6 +3023,40 @@ create_exception_master_breakpoint (void) 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; @@ -3618,7 +3737,7 @@ breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc, in breakpoint.h. */ int -ep_is_catchpoint (struct breakpoint *ep) +is_catchpoint (struct breakpoint *ep) { return (ep->type == bp_catchpoint); } @@ -5260,10 +5379,10 @@ print_breakpoint_location (struct breakpoint *b, } else if (loc) { - struct ui_stream *stb = ui_out_stream_new (uiout); - struct cleanup *stb_chain = make_cleanup_ui_out_stream_delete (stb); + struct ui_file *stb = mem_fileopen (); + struct cleanup *stb_chain = make_cleanup_ui_file_delete (stb); - print_address_symbolic (loc->gdbarch, loc->address, stb->stream, + print_address_symbolic (loc->gdbarch, loc->address, stb, demangle, ""); ui_out_field_stream (uiout, "at", stb); @@ -5583,7 +5702,7 @@ print_one_breakpoint_location (struct breakpoint *b, if (!part_of_multiple && b->hit_count) { /* FIXME should make an annotation for this. */ - if (ep_is_catchpoint (b)) + if (is_catchpoint (b)) ui_out_text (uiout, "\tcatchpoint"); else if (is_tracepoint (b)) ui_out_text (uiout, "\ttracepoint"); @@ -7374,6 +7493,8 @@ 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 @@ -7405,6 +7526,47 @@ dtor_catch_syscall (struct breakpoint *b) base_breakpoint_ops.dtor (b); } +static const struct inferior_data *catch_syscall_inferior_data = NULL; + +struct catch_syscall_inferior_data +{ + /* We keep a count of the number of times the user has requested a + particular syscall to be tracked, and pass this information to the + target. This lets capable targets implement filtering directly. */ + + /* Number of times that "any" syscall is requested. */ + int any_syscall_count; + + /* Count of each system call. */ + VEC(int) *syscalls_counts; + + /* This counts all syscall catch requests, so we can readily determine + if any catching is necessary. */ + int total_syscalls_count; +}; + +static struct catch_syscall_inferior_data* +get_catch_syscall_inferior_data (struct inferior *inf) +{ + struct catch_syscall_inferior_data *inf_data; + + inf_data = inferior_data (inf, catch_syscall_inferior_data); + if (inf_data == NULL) + { + inf_data = XZALLOC (struct catch_syscall_inferior_data); + set_inferior_data (inf, catch_syscall_inferior_data, inf_data); + } + + return inf_data; +} + +static void +catch_syscall_inferior_data_cleanup (struct inferior *inf, void *arg) +{ + xfree (arg); +} + + /* Implement the "insert" breakpoint_ops method for syscall catchpoints. */ @@ -7413,10 +7575,12 @@ insert_catch_syscall (struct bp_location *bl) { struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner; struct inferior *inf = current_inferior (); + struct catch_syscall_inferior_data *inf_data + = get_catch_syscall_inferior_data (inf); - ++inf->total_syscalls_count; + ++inf_data->total_syscalls_count; if (!c->syscalls_to_be_caught) - ++inf->any_syscall_count; + ++inf_data->any_syscall_count; else { int i, iter; @@ -7427,28 +7591,31 @@ insert_catch_syscall (struct bp_location *bl) { int elem; - if (iter >= VEC_length (int, inf->syscalls_counts)) + if (iter >= VEC_length (int, inf_data->syscalls_counts)) { - int old_size = VEC_length (int, inf->syscalls_counts); + int old_size = VEC_length (int, inf_data->syscalls_counts); uintptr_t vec_addr_offset = old_size * ((uintptr_t) sizeof (int)); uintptr_t vec_addr; - VEC_safe_grow (int, inf->syscalls_counts, iter + 1); - vec_addr = (uintptr_t) VEC_address (int, inf->syscalls_counts) + - vec_addr_offset; + VEC_safe_grow (int, inf_data->syscalls_counts, iter + 1); + vec_addr = ((uintptr_t) VEC_address (int, + inf_data->syscalls_counts) + + vec_addr_offset); memset ((void *) vec_addr, 0, (iter + 1 - old_size) * sizeof (int)); } - elem = VEC_index (int, inf->syscalls_counts, iter); - VEC_replace (int, inf->syscalls_counts, iter, ++elem); + elem = VEC_index (int, inf_data->syscalls_counts, iter); + VEC_replace (int, inf_data->syscalls_counts, iter, ++elem); } } return target_set_syscall_catchpoint (PIDGET (inferior_ptid), - inf->total_syscalls_count != 0, - inf->any_syscall_count, - VEC_length (int, inf->syscalls_counts), - VEC_address (int, inf->syscalls_counts)); + inf_data->total_syscalls_count != 0, + inf_data->any_syscall_count, + VEC_length (int, + inf_data->syscalls_counts), + VEC_address (int, + inf_data->syscalls_counts)); } /* Implement the "remove" breakpoint_ops method for syscall @@ -7459,10 +7626,12 @@ remove_catch_syscall (struct bp_location *bl) { struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner; struct inferior *inf = current_inferior (); + struct catch_syscall_inferior_data *inf_data + = get_catch_syscall_inferior_data (inf); - --inf->total_syscalls_count; + --inf_data->total_syscalls_count; if (!c->syscalls_to_be_caught) - --inf->any_syscall_count; + --inf_data->any_syscall_count; else { int i, iter; @@ -7472,20 +7641,21 @@ remove_catch_syscall (struct bp_location *bl) i++) { int elem; - if (iter >= VEC_length (int, inf->syscalls_counts)) + if (iter >= VEC_length (int, inf_data->syscalls_counts)) /* Shouldn't happen. */ continue; - elem = VEC_index (int, inf->syscalls_counts, iter); - VEC_replace (int, inf->syscalls_counts, iter, --elem); + elem = VEC_index (int, inf_data->syscalls_counts, iter); + VEC_replace (int, inf_data->syscalls_counts, iter, --elem); } } return target_set_syscall_catchpoint (PIDGET (inferior_ptid), - inf->total_syscalls_count != 0, - inf->any_syscall_count, - VEC_length (int, inf->syscalls_counts), + inf_data->total_syscalls_count != 0, + inf_data->any_syscall_count, + VEC_length (int, + inf_data->syscalls_counts), VEC_address (int, - inf->syscalls_counts)); + inf_data->syscalls_counts)); } /* Implement the "breakpoint_hit" breakpoint_ops method for syscall @@ -8070,6 +8240,7 @@ momentary_breakpoint_from_master (struct breakpoint *orig, 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); @@ -8155,6 +8326,7 @@ add_location_to_breakpoint (struct breakpoint *b, 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; @@ -8223,7 +8395,8 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, - int enabled, int internal, int display_canonical) + int enabled, int internal, unsigned flags, + int display_canonical) { int i; @@ -8269,6 +8442,9 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch, b->enable_state = enabled ? bp_enabled : bp_disabled; b->disposition = disposition; + if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0) + b->loc->inserted = 1; + if (type == bp_static_tracepoint) { struct tracepoint *t = (struct tracepoint *) b; @@ -8312,6 +8488,8 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch, else { loc = add_location_to_breakpoint (b, &sal); + if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0) + loc->inserted = 1; } if (bp_loc_is_permanent (loc)) @@ -8344,7 +8522,8 @@ create_breakpoint_sal (struct gdbarch *gdbarch, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, - int enabled, int internal, int display_canonical) + int enabled, int internal, unsigned flags, + int display_canonical) { struct breakpoint *b; struct cleanup *old_chain; @@ -8367,7 +8546,8 @@ create_breakpoint_sal (struct gdbarch *gdbarch, type, disposition, thread, task, ignore_count, ops, from_tty, - enabled, internal, display_canonical); + enabled, internal, flags, + display_canonical); discard_cleanups (old_chain); install_breakpoint (internal, b, 0); @@ -8395,7 +8575,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, - int enabled, int internal) + int enabled, int internal, unsigned flags) { int i; struct linespec_sals *lsal; @@ -8419,7 +8599,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch, filter_string, cond_string, type, disposition, thread, task, ignore_count, ops, - from_tty, enabled, internal, + from_tty, enabled, internal, flags, canonical->special_display); discard_cleanups (inner); } @@ -8679,7 +8859,8 @@ create_breakpoint (struct gdbarch *gdbarch, int ignore_count, enum auto_boolean pending_break_support, const struct breakpoint_ops *ops, - int from_tty, int enabled, int internal) + int from_tty, int enabled, int internal, + unsigned flags) { volatile struct gdb_exception e; char *copy_arg = NULL; @@ -8819,7 +9000,7 @@ create_breakpoint (struct gdbarch *gdbarch, cond_string, type_wanted, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, - from_tty, enabled, internal); + from_tty, enabled, internal, flags); } else { @@ -8885,6 +9066,14 @@ break_command_1 (char *arg, int flag, int from_tty) 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, @@ -8892,10 +9081,11 @@ break_command_1 (char *arg, int flag, int from_tty) tempflag, type_wanted, 0 /* Ignore count */, pending_break_support, - &bkpt_breakpoint_ops, + ops, from_tty, 1 /* enabled */, - 0 /* internal */); + 0 /* internal */, + 0); } /* Helper function for break_command_1 and disassemble_command. */ @@ -9144,8 +9334,8 @@ print_one_detail_ranged_breakpoint (const struct breakpoint *b, { CORE_ADDR address_start, address_end; struct bp_location *bl = b->loc; - struct ui_stream *stb = ui_out_stream_new (uiout); - struct cleanup *cleanup = make_cleanup_ui_out_stream_delete (stb); + struct ui_file *stb = mem_fileopen (); + struct cleanup *cleanup = make_cleanup_ui_file_delete (stb); gdb_assert (bl); @@ -9153,7 +9343,7 @@ print_one_detail_ranged_breakpoint (const struct breakpoint *b, address_end = address_start + bl->length - 1; ui_out_text (uiout, "\taddress range: "); - fprintf_unfiltered (stb->stream, "[%s, %s]", + fprintf_unfiltered (stb, "[%s, %s]", print_core_address (bl->gdbarch, address_start), print_core_address (bl->gdbarch, address_end)); ui_out_field_stream (uiout, "addr", stb); @@ -9588,7 +9778,7 @@ print_it_watchpoint (bpstat bs) struct cleanup *old_chain; struct breakpoint *b; const struct bp_location *bl; - struct ui_stream *stb; + struct ui_file *stb; enum print_stop_action result; struct watchpoint *w; struct ui_out *uiout = current_uiout; @@ -9599,8 +9789,8 @@ print_it_watchpoint (bpstat bs) b = bs->breakpoint_at; w = (struct watchpoint *) b; - stb = ui_out_stream_new (uiout); - old_chain = make_cleanup_ui_out_stream_delete (stb); + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); switch (b->type) { @@ -9614,10 +9804,10 @@ print_it_watchpoint (bpstat bs) mention (b); make_cleanup_ui_out_tuple_begin_end (uiout, "value"); ui_out_text (uiout, "\nOld value = "); - watchpoint_value_print (bs->old_val, stb->stream); + watchpoint_value_print (bs->old_val, stb); ui_out_field_stream (uiout, "old", stb); ui_out_text (uiout, "\nNew value = "); - watchpoint_value_print (w->val, stb->stream); + watchpoint_value_print (w->val, stb); ui_out_field_stream (uiout, "new", stb); ui_out_text (uiout, "\n"); /* More than one watchpoint may have been triggered. */ @@ -9632,7 +9822,7 @@ print_it_watchpoint (bpstat bs) mention (b); make_cleanup_ui_out_tuple_begin_end (uiout, "value"); ui_out_text (uiout, "\nValue = "); - watchpoint_value_print (w->val, stb->stream); + watchpoint_value_print (w->val, stb); ui_out_field_stream (uiout, "value", stb); ui_out_text (uiout, "\n"); result = PRINT_UNKNOWN; @@ -9649,7 +9839,7 @@ print_it_watchpoint (bpstat bs) mention (b); make_cleanup_ui_out_tuple_begin_end (uiout, "value"); ui_out_text (uiout, "\nOld value = "); - watchpoint_value_print (bs->old_val, stb->stream); + watchpoint_value_print (bs->old_val, stb); ui_out_field_stream (uiout, "old", stb); ui_out_text (uiout, "\nNew value = "); } @@ -9663,7 +9853,7 @@ print_it_watchpoint (bpstat bs) make_cleanup_ui_out_tuple_begin_end (uiout, "value"); ui_out_text (uiout, "\nValue = "); } - watchpoint_value_print (w->val, stb->stream); + watchpoint_value_print (w->val, stb); ui_out_field_stream (uiout, "new", stb); ui_out_text (uiout, "\n"); result = PRINT_UNKNOWN; @@ -10770,7 +10960,8 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string, AUTO_BOOLEAN_TRUE /* pending */, &gnu_v3_exception_catchpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */); + 0 /* internal */, + 0); return 1; } @@ -11997,7 +12188,7 @@ base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch, int task, int ignore_count, const struct breakpoint_ops *o, int from_tty, int enabled, - int internal) + int internal, unsigned flags) { internal_error_pure_virtual_called (); } @@ -12199,13 +12390,13 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, int enabled, - int internal) + 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); + enabled, internal, flags); } static void @@ -12364,6 +12555,57 @@ momentary_bkpt_print_mention (struct breakpoint *b) /* 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 @@ -12469,13 +12711,13 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, int enabled, - int internal) + 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); + enabled, internal, flags); } static void @@ -12487,6 +12729,30 @@ tracepoint_decode_linespec (struct breakpoint *b, char **s, 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'). */ @@ -12518,7 +12784,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, int enabled, - int internal) + int internal, unsigned flags) { int i; @@ -12547,7 +12813,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch, addr_string, NULL, cond_string, type_wanted, disposition, thread, task, ignore_count, ops, - from_tty, enabled, internal, + 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 @@ -13252,12 +13518,12 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch, int task, int ignore_count, const struct breakpoint_ops *ops, int from_tty, int enabled, - int internal) + int internal, unsigned flags) { create_breakpoints_sal (gdbarch, canonical, cond_string, type_wanted, disposition, thread, task, ignore_count, ops, from_tty, - enabled, internal); + enabled, internal, flags); } /* Decode the line represented by S by calling decode_line_full. This is the @@ -14060,9 +14326,10 @@ is_syscall_catchpoint_enabled (struct breakpoint *bp) int catch_syscall_enabled (void) { - struct inferior *inf = current_inferior (); + struct catch_syscall_inferior_data *inf_data + = get_catch_syscall_inferior_data (current_inferior ()); - return inf->total_syscalls_count != 0; + return inf_data->total_syscalls_count != 0; } int @@ -14117,6 +14384,14 @@ set_tracepoint_count (int num) 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 */, @@ -14124,10 +14399,10 @@ trace_command (char *arg, int from_tty) bp_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - &tracepoint_breakpoint_ops, + ops, from_tty, 1 /* enabled */, - 0 /* internal */)) + 0 /* internal */, 0)) set_tracepoint_count (breakpoint_count); } @@ -14144,7 +14419,7 @@ ftrace_command (char *arg, int from_tty) &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */)) + 0 /* internal */, 0)) set_tracepoint_count (breakpoint_count); } @@ -14172,7 +14447,7 @@ strace_command (char *arg, int from_tty) ops, from_tty, 1 /* enabled */, - 0 /* internal */)) + 0 /* internal */, 0)) set_tracepoint_count (breakpoint_count); } @@ -14237,7 +14512,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) &tracepoint_breakpoint_ops, 0 /* from_tty */, utp->enabled /* enabled */, - 0 /* internal */)) + 0 /* internal */, + CREATE_BREAKPOINT_FLAGS_INSERTED)) return NULL; set_tracepoint_count (breakpoint_count); @@ -14727,9 +15003,12 @@ add_catch_command (char *name, char *docstring, static void clear_syscall_counts (struct inferior *inf) { - inf->total_syscalls_count = 0; - inf->any_syscall_count = 0; - VEC_free (int, inf->syscalls_counts); + struct catch_syscall_inferior_data *inf_data + = get_catch_syscall_inferior_data (inf); + + inf_data->total_syscalls_count = 0; + inf_data->any_syscall_count = 0; + VEC_free (int, inf_data->syscalls_counts); } static void @@ -14855,6 +15134,14 @@ initialize_breakpoint_ops (void) 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; @@ -14902,6 +15189,12 @@ initialize_breakpoint_ops (void) 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; @@ -14980,7 +15273,11 @@ _initialize_breakpoint (void) 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); breakpoint_chain = 0; /* Don't bother to call set_breakpoint_count. $bpnum isn't useful