#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"
static void create_breakpoints_sal_default (struct gdbarch *,
struct linespec_result *,
struct linespec_sals *,
- char *, enum bptype,
+ char *, char *, enum bptype,
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 *);
breakpoints. */
struct breakpoint_ops bkpt_breakpoint_ops;
+/* Breakpoints set on probes. */
+static struct breakpoint_ops bkpt_probe_breakpoint_ops;
+
+/* Dynamic printf class type. */
+static struct breakpoint_ops dprintf_breakpoint_ops;
+
/* A reference-counted struct command_line. This lets multiple
breakpoints share a single command list. */
struct counted_command_line
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";
set_condition_evaluation_mode (char *args, int from_tty,
struct cmd_list_element *c)
{
- struct breakpoint *b;
const char *old_mode, *new_mode;
if ((condition_evaluation_mode_1 == condition_evaluation_target)
new_mode = translate_condition_evaluation_mode (condition_evaluation_mode_1);
old_mode = translate_condition_evaluation_mode (condition_evaluation_mode);
+ /* Flip the switch. Flip it even if OLD_MODE == NEW_MODE as one of the
+ settings was "auto". */
+ condition_evaluation_mode = condition_evaluation_mode_1;
+
/* Only update the mode if the user picked a different one. */
if (new_mode != old_mode)
{
"target" -> "host": Remove all the conditions from the target.
*/
- /* Flip the switch. */
- condition_evaluation_mode = condition_evaluation_mode_1;
-
if (new_mode == condition_evaluation_target)
{
/* Mark everything modified and synch conditions with the
/* 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
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,
is_breakpoint (const struct breakpoint *bpt)
{
return (bpt->type == bp_breakpoint
- || bpt->type == bp_hardware_breakpoint);
+ || bpt->type == bp_hardware_breakpoint
+ || bpt->type == bp_dprintf);
}
/* Return true if BPT is of any hardware watchpoint kind. */
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;
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. */
/* 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;
/* Install a master breakpoint on the unwinder's debug hook. */
-void
+static void
create_exception_master_breakpoint (void)
{
struct objfile *objfile;
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;
(gdb) tar rem :9999 # remote Windows gdbserver.
*/
+ case bp_step_resume:
+
+ /* Also remove step-resume breakpoints. */
+
delete_breakpoint (b);
break;
in breakpoint.h. */
int
-ep_is_catchpoint (struct breakpoint *ep)
+is_catchpoint (struct breakpoint *ep)
{
return (ep->type == bp_catchpoint);
}
PC of the former breakpoint. */
this_action = BPSTAT_WHAT_KEEP_CHECKING;
break;
+
+ case bp_dprintf:
+ this_action = BPSTAT_WHAT_STOP_SILENT;
+ break;
+
default:
internal_error (__FILE__, __LINE__,
_("bpstat_what: unhandled bptype %d"), (int) bptype);
}
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);
{bp_tracepoint, "tracepoint"},
{bp_fast_tracepoint, "fast tracepoint"},
{bp_static_tracepoint, "static tracepoint"},
+ {bp_dprintf, "dprintf"},
{bp_jit_event, "jit events"},
{bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"},
{bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"},
case bp_tracepoint:
case bp_fast_tracepoint:
case bp_static_tracepoint:
+ case bp_dprintf:
case bp_jit_event:
case bp_gnu_ifunc_resolver:
case bp_gnu_ifunc_resolver_return:
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");
case bp_exception_master:
case bp_gnu_ifunc_resolver:
case bp_gnu_ifunc_resolver_return:
+ case bp_dprintf:
loc->loc_type = bp_loc_software_breakpoint;
mark_breakpoint_location_modified (loc);
break;
{
int is_gnu_ifunc;
const char *function_name;
+ CORE_ADDR func_addr;
find_pc_partial_function_gnu_ifunc (loc->address, &function_name,
- NULL, NULL, &is_gnu_ifunc);
+ &func_addr, NULL, &is_gnu_ifunc);
if (is_gnu_ifunc && !explicit_loc)
{
/* Create only the whole new breakpoint of this type but do not
mess more complicated breakpoints with multiple locations. */
b->type = bp_gnu_ifunc_resolver;
+ /* Remember the resolver's address for use by the return
+ breakpoint. */
+ loc->related_address = func_addr;
}
}
}
}
+void
+delete_longjmp_breakpoint_at_next_stop (int thread)
+{
+ struct breakpoint *b, *b_tmp;
+
+ ALL_BREAKPOINTS_SAFE (b, b_tmp)
+ if (b->type == bp_longjmp || b->type == bp_exception)
+ {
+ if (b->thread == thread)
+ b->disposition = disp_del_at_next_stop;
+ }
+}
+
void
enable_overlay_breakpoints (void)
{
struct solib_catchpoint *c;
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- regex_t compiled;
struct cleanup *cleanup;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
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
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. */
{
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;
{
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
{
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;
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
ptid_t ptid;
struct target_waitstatus last;
struct syscall s;
- char *syscall_id;
get_last_target_status (&ptid, &last);
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;
return retval;
}
+/* The style in which to perform a dynamic printf. This is a user
+ option because different output options have different tradeoffs;
+ if GDB does the printing, there is better error handling if there
+ is a problem with any of the arguments, but using an inferior
+ function lets you have special-purpose printers and sending of
+ output to the same place as compiled-in print functions. (Future
+ styles may include the ability to do a target-side printf.) */
+
+static const char dprintf_style_gdb[] = "gdb";
+static const char dprintf_style_call[] = "call";
+static const char *const dprintf_style_enums[] = {
+ dprintf_style_gdb,
+ dprintf_style_call,
+ NULL
+};
+static const char *dprintf_style = dprintf_style_gdb;
+
+/* The function to use for dynamic printf if the preferred style is to
+ call into the inferior. The value is simply a string that is
+ copied into the command, so it can be anything that GDB can
+ evaluate to a callable address, not necessarily a function name. */
+
+static char *dprintf_function = "";
+
+/* The channel to use for dynamic printf if the preferred style is to
+ call into the inferior; if a nonempty string, it will be passed to
+ the call as the first argument, with the format string as the
+ second. As with the dprintf function, this can be anything that
+ GDB knows how to evaluate, so in addition to common choices like
+ "stderr", this could be an app-specific expression like
+ "mystreams[curlogger]". */
+
+static char *dprintf_channel = "";
+
+/* Build a command list for the dprintf corresponding to the current
+ settings of the dprintf style options. */
+
+static void
+update_dprintf_command_list (struct breakpoint *b)
+{
+ char *dprintf_args = b->extra_string;
+ char *printf_line = NULL;
+
+ if (!dprintf_args)
+ return;
+
+ dprintf_args = skip_spaces (dprintf_args);
+
+ /* Allow a comma, as it may have terminated a location, but don't
+ insist on it. */
+ if (*dprintf_args == ',')
+ ++dprintf_args;
+ dprintf_args = skip_spaces (dprintf_args);
+
+ if (*dprintf_args != '"')
+ error (_("Bad format string, missing '\"'."));
+
+ if (strcmp (dprintf_style, "gdb") == 0)
+ printf_line = xstrprintf ("printf %s", dprintf_args);
+ else if (strcmp (dprintf_style, "call") == 0)
+ {
+ if (!dprintf_function)
+ error (_("No function supplied for dprintf call"));
+
+ if (dprintf_channel && strlen (dprintf_channel) > 0)
+ printf_line = xstrprintf ("call (void) %s (%s,%s)",
+ dprintf_function,
+ dprintf_channel,
+ dprintf_args);
+ else
+ printf_line = xstrprintf ("call (void) %s (%s)",
+ dprintf_function,
+ dprintf_args);
+ }
+ else
+ 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;
+
+ 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");
+
+ 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;
+
+ breakpoint_set_commands (b, printf_cmd_line);
+ }
+}
+
+/* Update all dprintf commands, making their command lists reflect
+ current style settings. */
+
+static void
+update_dprintf_commands (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ struct breakpoint *b;
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->type == bp_dprintf)
+ update_dprintf_command_list (b);
+ }
+}
/* Create a breakpoint with SAL as location. Use ADDR_STRING
as textual description of the location, and COND_STRING
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
char *filter, char *cond_string,
+ char *extra_string,
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;
init_raw_breakpoint (b, gdbarch, sal, type, ops);
b->thread = thread;
b->task = task;
-
+
b->cond_string = cond_string;
+ b->extra_string = extra_string;
b->ignore_count = ignore_count;
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;
else
{
loc = add_location_to_breakpoint (b, &sal);
+ if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0)
+ loc->inserted = 1;
}
if (bp_loc_is_permanent (loc))
char *arg = b->cond_string;
loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
- error (_("Garbage %s follows condition"), arg);
+ error (_("Garbage '%s' follows condition"), arg);
+ }
+
+ /* Dynamic printf requires and uses additional arguments on the
+ command line, otherwise it's an error. */
+ if (type == bp_dprintf)
+ {
+ if (b->extra_string)
+ update_dprintf_command_list (b);
+ else
+ error (_("Format string required"));
}
- }
+ else if (b->extra_string)
+ error (_("Garbage '%s' at end of command"), b->extra_string);
+ }
b->display_canonical = display_canonical;
if (addr_string)
create_breakpoint_sal (struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
char *filter, char *cond_string,
+ char *extra_string,
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;
init_breakpoint_sal (b, gdbarch,
sals, addr_string,
- filter, cond_string,
+ filter, cond_string, extra_string,
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);
static void
create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
- char *cond_string,
+ char *cond_string, char *extra_string,
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;
create_breakpoint_sal (gdbarch, lsal->sals,
addr_string,
filter_string,
- cond_string, type, disposition,
+ cond_string, extra_string,
+ type, disposition,
thread, task, ignore_count, ops,
- from_tty, enabled, internal,
+ from_tty, enabled, internal, flags,
canonical->special_display);
discard_cleanups (inner);
}
}
else
{
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
/* Force almost all breakpoints to be in terms of the
current_source_symtab (which is decode_line_1's default).
This should produce the results we want almost all of the
- time while leaving default_breakpoint_* alone. */
- if (last_displayed_sal_is_valid ())
+ time while leaving default_breakpoint_* alone.
+
+ ObjC: However, don't match an Objective-C method name which
+ may have a '+' or '-' succeeded by a '['. */
+ if (last_displayed_sal_is_valid ()
+ && (!cursal.symtab
+ || ((strchr ("+-", (*address)[0]) != NULL)
+ && ((*address)[1] != '['))))
decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
get_last_displayed_symtab (),
get_last_displayed_line (),
canonical, NULL, NULL);
else
decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
- (struct symtab *) NULL, 0,
- canonical, NULL, NULL);
+ cursal.symtab, cursal.line, canonical, NULL, NULL);
}
}
PC identifies the context at which the condition should be parsed.
If no condition is found, *COND_STRING is set to NULL.
If no thread is found, *THREAD is set to -1. */
-static void
-find_condition_and_thread (char *tok, CORE_ADDR pc,
- char **cond_string, int *thread, int *task)
+
+static void
+find_condition_and_thread (char *tok, CORE_ADDR pc,
+ char **cond_string, int *thread, int *task,
+ char **rest)
{
*cond_string = NULL;
*thread = -1;
char *cond_end = NULL;
tok = skip_spaces (tok);
-
+
+ if ((*tok == '"' || *tok == ',') && rest)
+ {
+ *rest = savestring (tok, strlen (tok));
+ return;
+ }
+
end_tok = skip_to_space (tok);
-
+
toklen = end_tok - tok;
-
+
if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
{
struct expression *expr;
expr = parse_exp_1 (&tok, block_for_pc (pc), 0);
xfree (expr);
cond_end = tok;
- *cond_string = savestring (cond_start,
- cond_end - cond_start);
+ *cond_string = savestring (cond_start, cond_end - cond_start);
}
else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
{
char *tmptok;
-
+
tok = end_tok + 1;
tmptok = tok;
*thread = strtol (tok, &tok, 0);
if (!valid_task_id (*task))
error (_("Unknown task %d."), *task);
}
+ else if (rest)
+ {
+ *rest = savestring (tok, strlen (tok));
+ return;
+ }
else
error (_("Junk at end of arguments."));
}
{
VEC(static_tracepoint_marker_p) *markers = NULL;
struct symtabs_and_lines sals;
- struct symtab_and_line sal;
- struct symbol *sym;
struct cleanup *old_chain;
char *p = &(*arg_p)[3];
char *endp;
int
create_breakpoint (struct gdbarch *gdbarch,
- char *arg, char *cond_string, int thread,
+ char *arg, char *cond_string,
+ int thread, char *extra_string,
int parse_condition_and_thread,
int tempflag, enum bptype type_wanted,
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;
struct linespec_result canonical;
struct cleanup *old_chain;
struct cleanup *bkpt_chain = NULL;
- int i;
int pending = 0;
int task = 0;
int prev_bkpt_count = breakpoint_count;
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);
+ &thread, &task, &rest);
if (cond_string)
make_cleanup (xfree, cond_string);
+ if (rest)
+ make_cleanup (xfree, rest);
+ if (rest)
+ extra_string = rest;
}
else
{
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,
- cond_string, type_wanted,
+ cond_string, extra_string, type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops,
- from_tty, enabled, internal);
+ from_tty, enabled, internal, flags);
}
else
{
b->addr_string = copy_arg;
b->cond_string = NULL;
+ b->extra_string = NULL;
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
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,
- NULL, 0, 1 /* parse arg */,
+ NULL, 0, NULL, 1 /* parse arg */,
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. */
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
+dprintf_command (char *arg, int from_tty)
+{
+ create_breakpoint (get_current_arch (),
+ arg,
+ NULL, 0, NULL, 1 /* parse arg */,
+ 0, bp_dprintf,
+ 0 /* Ignore count */,
+ pending_break_support,
+ &dprintf_breakpoint_ops,
+ from_tty,
+ 1 /* enabled */,
+ 0 /* internal */,
+ 0);
+}
+
/* Implement the "breakpoint_hit" breakpoint_ops method for
ranged breakpoints. */
const struct target_waitstatus *ws)
{
if (ws->kind != TARGET_WAITKIND_STOPPED
- || ws->value.sig != TARGET_SIGNAL_TRAP)
+ || ws->value.sig != GDB_SIGNAL_TRAP)
return 0;
return breakpoint_address_match_range (bl->pspace->aspace, bl->address,
{
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);
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);
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;
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)
{
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. */
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;
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 = ");
}
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;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
- struct frame_info *frame = get_selected_frame (NULL);
- struct gdbarch *frame_gdbarch = get_frame_arch (frame);
- struct frame_id stack_frame_id = get_stack_frame_id (frame);
- struct frame_id caller_frame_id = frame_unwind_caller_id (frame);
+ struct frame_info *frame;
+ struct gdbarch *frame_gdbarch;
+ struct frame_id stack_frame_id;
+ struct frame_id caller_frame_id;
struct breakpoint *breakpoint;
struct breakpoint *breakpoint2 = NULL;
struct cleanup *old_chain;
old_chain = make_cleanup (null_cleanup, NULL);
- /* Installing a breakpoint invalidates the frame chain (as it may
- need to switch threads), so do any frame handling first. */
+ /* Note linespec handling above invalidates the frame chain.
+ Installing a breakpoint also invalidates the frame chain (as it
+ may need to switch threads), so do any frame handling before
+ that. */
+
+ frame = get_selected_frame (NULL);
+ frame_gdbarch = get_frame_arch (frame);
+ stack_frame_id = get_stack_frame_id (frame);
+ caller_frame_id = frame_unwind_caller_id (frame);
/* Keep within the current frame, or in frames called by the current
one. */
stack_frame_id, bp_until);
make_cleanup_delete_breakpoint (breakpoint);
- proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+ proceed (-1, GDB_SIGNAL_DEFAULT, 0);
/* If we are running asynchronously, and proceed call above has
actually managed to start the target, arrange for breakpoints to
trigger_func_name = "__cxa_throw";
create_breakpoint (get_current_arch (),
- trigger_func_name, cond_string, -1,
+ 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 /* internal */,
+ 0);
return 1;
}
struct linespec_result *c,
struct linespec_sals *lsal,
char *cond_string,
+ char *extra_string,
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
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 ();
}
struct breakpoint *b = bl->owner;
if (ws->kind != TARGET_WAITKIND_STOPPED
- || ws->value.sig != TARGET_SIGNAL_TRAP)
+ || ws->value.sig != GDB_SIGNAL_TRAP)
return 0;
if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
case bp_hardware_breakpoint:
printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
break;
+ case bp_dprintf:
+ printf_filtered (_("Dprintf %d"), b->number);
+ break;
}
say_where (b);
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
+ char *extra_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)
+ int internal, unsigned flags)
{
create_breakpoints_sal_default (gdbarch, canonical, lsal,
- cond_string, type_wanted,
+ cond_string, extra_string,
+ type_wanted,
disposition, thread, task,
ignore_count, ops, from_tty,
- enabled, internal);
+ enabled, internal, flags);
}
static void
/* 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 linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
+ char *extra_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)
+ int internal, unsigned flags)
{
create_breakpoints_sal_default (gdbarch, canonical, lsal,
- cond_string, type_wanted,
+ cond_string, extra_string,
+ type_wanted,
disposition, thread, task,
ignore_count, ops, from_tty,
- enabled, internal);
+ enabled, internal, flags);
}
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'). */
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
+ char *extra_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)
+ int internal, unsigned flags)
{
int i;
tp = XCNEW (struct tracepoint);
init_breakpoint_sal (&tp->base, gdbarch, expanded,
addr_string, NULL,
- cond_string, type_wanted, disposition,
+ cond_string, extra_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
struct tracepoint *tp = (struct tracepoint *) b;
struct static_tracepoint_marker marker;
CORE_ADDR pc;
- int i;
pc = sal.pc;
if (sal.line)
char *cond_string = 0;
int thread = -1;
int task = 0;
+ char *extra_string = NULL;
find_condition_and_thread (s, sals.sals[0].pc,
- &cond_string, &thread, &task);
+ &cond_string, &thread, &task,
+ &extra_string);
if (cond_string)
b->cond_string = cond_string;
b->thread = thread;
b->task = task;
+ if (extra_string)
+ b->extra_string = extra_string;
b->condition_not_parsed = 0;
}
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
+ char *extra_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)
+ int internal, unsigned flags)
{
create_breakpoints_sal (gdbarch, canonical, cond_string,
+ extra_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
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
}
/* Complete syscall names. Used by "catch syscall". */
-static char **
+static VEC (char_ptr) *
catch_syscall_completer (struct cmd_list_element *cmd,
char *text, char *word)
{
const char **list = get_syscall_names ();
- char **retlist
+ VEC (char_ptr) *retlist
= (list == NULL) ? NULL : complete_on_enum (list, text, word);
xfree (list);
set_internalvar_integer (lookup_internalvar ("tpnum"), num);
}
-void
+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 */,
+ NULL, 0, NULL, 1 /* parse arg */,
0 /* tempflag */,
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);
}
-void
+static void
ftrace_command (char *arg, int from_tty)
{
if (create_breakpoint (get_current_arch (),
arg,
- NULL, 0, 1 /* parse arg */,
+ NULL, 0, NULL, 1 /* parse arg */,
0 /* tempflag */,
bp_fast_tracepoint /* type_wanted */,
0 /* Ignore count */,
&tracepoint_breakpoint_ops,
from_tty,
1 /* enabled */,
- 0 /* internal */))
+ 0 /* internal */, 0))
set_tracepoint_count (breakpoint_count);
}
/* strace command implementation. Creates a static tracepoint. */
-void
+static void
strace_command (char *arg, int from_tty)
{
struct breakpoint_ops *ops;
if (create_breakpoint (get_current_arch (),
arg,
- NULL, 0, 1 /* parse arg */,
+ NULL, 0, NULL, 1 /* parse arg */,
0 /* tempflag */,
bp_static_tracepoint /* type_wanted */,
0 /* Ignore count */,
ops,
from_tty,
1 /* enabled */,
- 0 /* internal */))
+ 0 /* internal */, 0))
set_tracepoint_count (breakpoint_count);
}
if (!create_breakpoint (get_current_arch (),
addr_str,
- utp->cond_string, -1, 0 /* parse cond/thread */,
+ utp->cond_string, -1, NULL,
+ 0 /* parse cond/thread */,
0 /* tempflag */,
utp->type /* type_wanted */,
0 /* Ignore count */,
&tracepoint_breakpoint_ops,
0 /* from_tty */,
utp->enabled /* enabled */,
- 0 /* internal */))
+ 0 /* internal */,
+ CREATE_BREAKPOINT_FLAGS_INSERTED))
return NULL;
set_tracepoint_count (breakpoint_count);
add_catch_command (char *name, char *docstring,
void (*sfunc) (char *args, int from_tty,
struct cmd_list_element *command),
- char **(*completer) (struct cmd_list_element *cmd,
- char *text, char *word),
+ completer_ftype *completer,
void *user_data_catch,
void *user_data_tcatch)
{
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
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;
ops->print_one = print_one_catch_solib;
ops->print_mention = print_mention_catch_solib;
ops->print_recreate = print_recreate_catch_solib;
+
+ ops = &dprintf_breakpoint_ops;
+ *ops = bkpt_base_breakpoint_ops;
+ ops->re_set = bkpt_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;
}
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
&condition_evaluation_mode_1, _("\
Set mode of breakpoint condition evaluation."), _("\
Show mode of breakpoint condition evaluation."), _("\
-When this is set to \"gdb\", breakpoint conditions will be\n\
+When this is set to \"host\", breakpoint conditions will be\n\
evaluated on the host's side by GDB. When it is set to \"target\",\n\
breakpoint conditions will be downloaded to the target (if the target\n\
supports such feature) and conditions will be evaluated on the target's side.\n\
an instruction at any address within the [START-LOCATION, END-LOCATION]\n\
range (including START-LOCATION and END-LOCATION)."));
+ c = add_com ("dprintf", class_breakpoint, dprintf_command, _("\
+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\
+"));
+ set_cmd_completer (c, location_completer);
+
+ add_setshow_enum_cmd ("dprintf-style", class_support,
+ dprintf_style_enums, &dprintf_style, _("\
+Set the style of usage for dynamic printf."), _("\
+Show the style of usage for dynamic printf."), _("\
+This setting chooses how GDB will do a dynamic printf.\n\
+If the value is \"gdb\", then the printing is done by GDB to its own\n\
+console, as with the \"printf\" command.\n\
+If the value is \"call\", the print is done by calling a function in your\n\
+program; by default printf(), but you can choose a different function or\n\
+output stream by setting dprintf-function and dprintf-channel."),
+ update_dprintf_commands, NULL,
+ &setlist, &showlist);
+
+ dprintf_function = xstrdup ("printf");
+ add_setshow_string_cmd ("dprintf-function", class_support,
+ &dprintf_function, _("\
+Set the function to use for dynamic printf"), _("\
+Show the function to use for dynamic printf"), NULL,
+ update_dprintf_commands, NULL,
+ &setlist, &showlist);
+
+ dprintf_channel = xstrdup ("");
+ add_setshow_string_cmd ("dprintf-channel", class_support,
+ &dprintf_channel, _("\
+Set the channel to use for dynamic printf"), _("\
+Show the channel to use for dynamic printf"), NULL,
+ update_dprintf_commands, NULL,
+ &setlist, &showlist);
+
automatic_hardware_breakpoints = 1;
observer_attach_about_to_proceed (breakpoint_about_to_proceed);