mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-03 13:23:00 +08:00
Static tracepoints support, and UST integration.
gdb/gdbserver/ * configure.ac: Handle --with-ust. substitute ustlibs and ustinc. * mem-break.c (uninsert_all_breakpoints) (reinsert_all_breakpoints): New. * mem-break.h (reinsert_all_breakpoints, uninsert_all_breakpoints): * tracepoint.c (ust_loaded, helper_thread_id, cmd_buf): New. (gdb_agent_ust_loaded, helper_thread_id) (gdb_agent_helper_thread_id): New macros. (struct ipa_sym_addresses): Add addr_ust_loaded, addr_helper_thread_id, addr_cmd_buf. (symbol_list): Add ust_loaded, helper_thread_id, cmd_buf. (in_process_agent_loaded_ust): New. (write_e_ust_not_loaded): New. (maybe_write_ipa_ust_not_loaded): New. (struct collect_static_trace_data_action): New. (enum tracepoint_type) <static_tracepoint>: New. (struct tracepoint) <handle>: Mention static tracepoints. (struct static_tracepoint_ctx): New. (CMD_BUF_SIZE): New. (add_tracepoint_action): Handle static tracepoint actions. (unprobe_marker_at): New. (clear_installed_tracepoints): Handle static tracepoints. (cmd_qtdp): Handle static tracepoints. (probe_marker_at): New. (cmd_qtstart): Handle static tracepoints. (response_tracepoint): Handle static tracepoints. (cmd_qtfstm, cmd_qtsstm, cmd_qtstmat): New. (handle_tracepoint_query): Handle qTfSTM, qTsSTM and qTSTMat. (get_context_regcache): Handle static tracepoints. (do_action_at_tracepoint): Handle static tracepoint actions. (traceframe_find_block_type): Handle static trace data blocks. (traceframe_read_sdata): New. (download_tracepoints): Download static tracepoint actions. [HAVE_UST] Include ust/ust.h, dlfcn.h, sys/socket.h, and sys/un.h. (GDB_PROBE_NAME): New. (ust_ops): New. (GET_UST_SYM): New. (USTF): New. (dlsym_ust): New. (ust_marker_to_static_tracepoint): New. (gdb_probe): New. (collect_ust_data_at_tracepoint): New. (gdb_ust_probe): New. (UNIX_PATH_MAX, SOCK_DIR): New. (gdb_ust_connect_sync_socket): New. (resume_thread, stop_thread): New. (run_inferior_command): New. (init_named_socket): New. (gdb_ust_socket_init): New. (cstr_to_hexstr): New. (next_st): New. (first_marker, next_marker): New. (response_ust_marker): New. (cmd_qtfstm, cmd_qtsstm): New. (unprobe_marker_at, probe_marker_at): New. (cmd_qtstmat, gdb_ust_thread): New. (gdb_ust_init): New. (initialize_tracepoint_ftlib): Call gdb_ust_init. * linux-amd64-ipa.c [HAVE_UST]: Include ust/processor.h (ST_REGENTRY): New. (x86_64_st_collect_regmap): New. (X86_64_NUM_ST_COLLECT_GREGS): New. (AMD64_RIP_REGNUM): New. (supply_static_tracepoint_registers): New. * linux-i386-ipa.c [HAVE_UST]: Include ust/processor.h (ST_REGENTRY): New. (i386_st_collect_regmap): New. (i386_NUM_ST_COLLECT_GREGS): New. (supply_static_tracepoint_registers): New. * server.c (handle_query): Handle qXfer:statictrace:read. <qSupported>: Report support for StaticTracepoints, and qXfer:statictrace:read features. * server.h (traceframe_read_sdata) (supply_static_tracepoint_registers): Declare. * remote-utils.c (convert_int_to_ascii, hexchars, ishex, tohex) (unpack_varlen_hex): Include in IPA build. * Makefile.in (ustlibs, ustinc): New. (IPA_OBJS): Add remote-utils-ipa.o. ($(IPA_LIB)): Link -ldl and -lpthread. (UST_CFLAGS): New. (IPAGENT_CFLAGS): Add UST_CFLAGS. * config.in, configure: Regenerate. gdb/ * NEWS: Mention new support for static tracepoints. (New packets): Mention qTfSTM, qTsSTM, qTSTMat and qXfer:statictrace:read. (New features in the GDB remote stub, GDBserver): Mention static tracepoints support using an UST based backend. (New commands): Mention "info static-tracepoint-markers" and "strace". * breakpoint.c (is_marker_spec): New. (is_tracepoint): Handle static tracepoints. (validate_commands_for_breakpoint): Static tracepoints can't do while-stepping. (static_tracepoints_here): New. (bpstat_what): Handle static tracepoints. (print_one_breakpoint_location, allocate_bp_location, mention): Ditto. (create_breakpoint_sal): Ditto. (decode_static_tracepoint_spec): New. (create_breakpoint): Replace `hardwareflag', and `traceflag' with `type_wanted'. Adjust. Handle static tracepoint marker locations. (break_command_1): Adjust. (update_static_tracepoint): New. (update_breakpoint_locations): Handle static tracepoints. (breakpoint_re_set_one): Handle static tracepoint marker locations. (disable_command, enable_command): Handle static tracepoints. (trace_command, ftrace_command): Adjust. (strace_command): New. (create_tracepoint_from_upload): Adjust. (save_breakpoints): Handle static tracepoints. (_initialize_breakpoint): Install the "strace" command. * breakpoint.h (enum bptype): New bp_static_tracepoint type. (struct breakpoint): New fields static_trace_marker_id and static_trace_marker_id_idx. (breakpoints_here_p): Declare. (create_breakpoint): Adjust. (static_tracepoints_here): Declare. * remote.c (struct remote_state) <static_tracepoints>: New field. (PACKET_qXfer_statictrace_read, PACKET_StaticTracepoints): New. (remote_static_tracepoint_marker_at): New. (remote_static_tracepoint_markers_by_strid): New. (remote_static_tracepoint_feature): New. (remote_disconnected_tracing_feature): Handle "StaticTracepoints". (remote_xfer_partial): Handle TARGET_OBJECT_STATIC_TRACE_DATA. (remote_supports_static_tracepoints): New. (remote_download_tracepoint): Download static tracepoints. (init_remote_ops): Install remote_static_tracepoint_marker_at and remote_static_tracepoint_markers_by_strid. (_initialize_remote): Install set|show remote static-tracepoints, and set|show remote read-sdata-object commands. * target.c (update_current_target): Inherit and default to_static_tracepoint_marker_at, and to_static_tracepoint_markers_by_strid. * target.h (static_tracepoint_marker): Forward declare. (enum target_object): New object TARGET_OBJECT_STATIC_TRACE_DATA. (static_tracepoint_marker_p): New typedef. (DEF_VEC_P(static_tracepoint_marker_p)): New VEC type. (struct target_ops): New fields to_static_tracepoint_marker_at and to_static_tracepoint_markers_by_strid. (target_static_tracepoint_marker_at) (target_static_tracepoint_markers_by_strid): New. * tracepoint.c: Include source.h. (validate_actionline): Handle $_sdata. (struct collection_list): New field strace_data. (add_static_trace_data): New. (clear_collection_list): Clear strace_data. (stringify_collection_list): Account for a possible static trace data collection. (encode_actions_1): Encode an $_sdata collection. (parse_tracepoint_definition): Handle static tracepoints. (parse_static_tracepoint_marker_definition): New. (release_static_tracepoint_marker): New. (print_one_static_tracepoint_marker): New. (info_static_tracepoint_markers_command): New. (sdata_make_value): New. (_initialize_tracepoint): Create the $_sdata convenience variable. Add the "info static-tracepoint-markers" command. Mention $_sdata in the "collect" command's help output. * tracepoint.h (struct static_tracepoint_marker): New. (parse_static_tracepoint_marker_definition) (release_static_tracepoint_marker): Declare. * mi/mi-cmd-break.c (mi_cmd_break_insert): Adjust. * python/py-breakpoint.c (bppy_new): Adjust. doc/ * gdb.texinfo (Convenience Variables): Document $_sdata. (Commands to Set Tracepoints): Describe static tracepoints. Add `Listing Static Tracepoint Markers' menu entry. Document "strace". (Tracepoint Action Lists): Document collecting $_sdata. (Listing Static Tracepoint Markers): New subsection. (Tracepoints support in gdbserver): Mention static tracepoints. (remote packets, enabling and disabling): Mention read-sdata-object. (General Query Packets) <qSupported>: Document qXfer:sdata:read and StaticTracepoint. Mention qTfSTM, qTsSTM and qTSTMat as tracepoint packets. Document qXfer:sdata:read. (Tracepoint packets): Document qTfSTM, qTsSTM and qTSTMat.
This commit is contained in:
450
gdb/breakpoint.c
450
gdb/breakpoint.c
@ -230,6 +230,11 @@ static void disable_trace_command (char *, int);
|
||||
|
||||
static void trace_pass_command (char *, int);
|
||||
|
||||
/* Assuming we're creating a static tracepoint, does S look like a
|
||||
static tracepoint marker spec ("-m MARKER_ID")? */
|
||||
#define is_marker_spec(s) \
|
||||
(strncmp (s, "-m", 2) == 0 && ((s)[2] == ' ' || (s)[2] == '\t'))
|
||||
|
||||
/* A reference-counted struct command_line. This lets multiple
|
||||
breakpoints share a single command list. */
|
||||
struct counted_command_line
|
||||
@ -839,7 +844,9 @@ check_no_tracepoint_commands (struct command_line *commands)
|
||||
int
|
||||
is_tracepoint (const struct breakpoint *b)
|
||||
{
|
||||
return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
|
||||
return (b->type == bp_tracepoint
|
||||
|| b->type == bp_fast_tracepoint
|
||||
|| b->type == bp_static_tracepoint);
|
||||
}
|
||||
|
||||
/* A helper function that validsates that COMMANDS are valid for a
|
||||
@ -863,7 +870,11 @@ validate_commands_for_breakpoint (struct breakpoint *b,
|
||||
if (c->control_type == while_stepping_control)
|
||||
{
|
||||
if (b->type == bp_fast_tracepoint)
|
||||
error (_("The 'while-stepping' command cannot be used for fast tracepoint"));
|
||||
error (_("\
|
||||
The 'while-stepping' command cannot be used for fast tracepoint"));
|
||||
else if (b->type == bp_static_tracepoint)
|
||||
error (_("\
|
||||
The 'while-stepping' command cannot be used for static tracepoint"));
|
||||
|
||||
if (while_stepping)
|
||||
error (_("The 'while-stepping' command can be used only once"));
|
||||
@ -890,6 +901,27 @@ validate_commands_for_breakpoint (struct breakpoint *b,
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a vector of all the static tracepoints set at ADDR. The
|
||||
caller is responsible for releasing the vector. */
|
||||
|
||||
VEC(breakpoint_p) *
|
||||
static_tracepoints_here (CORE_ADDR addr)
|
||||
{
|
||||
struct breakpoint *b;
|
||||
VEC(breakpoint_p) *found = 0;
|
||||
struct bp_location *loc;
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
if (b->type == bp_static_tracepoint)
|
||||
{
|
||||
for (loc = b->loc; loc; loc = loc->next)
|
||||
if (loc->address == addr)
|
||||
VEC_safe_push(breakpoint_p, found, b);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* Set the command list of B to COMMANDS. If breakpoint is tracepoint,
|
||||
validate that only allowed commands are included.
|
||||
*/
|
||||
@ -4349,6 +4381,7 @@ bpstat_what (bpstat bs)
|
||||
break;
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_static_tracepoint:
|
||||
/* Tracepoint hits should not be reported back to GDB, and
|
||||
if one got through somehow, it should have been filtered
|
||||
out already. */
|
||||
@ -4514,6 +4547,7 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||
{bp_catchpoint, "catchpoint"},
|
||||
{bp_tracepoint, "tracepoint"},
|
||||
{bp_fast_tracepoint, "fast tracepoint"},
|
||||
{bp_static_tracepoint, "static tracepoint"},
|
||||
{bp_jit_event, "jit events"},
|
||||
};
|
||||
|
||||
@ -4646,6 +4680,7 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||
case bp_std_terminate_master:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_static_tracepoint:
|
||||
case bp_jit_event:
|
||||
if (opts.addressprint)
|
||||
{
|
||||
@ -4716,6 +4751,16 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||
|
||||
ui_out_text (uiout, "\n");
|
||||
|
||||
if (!part_of_multiple && b->static_trace_marker_id)
|
||||
{
|
||||
gdb_assert (b->type == bp_static_tracepoint);
|
||||
|
||||
ui_out_text (uiout, "\tmarker id is ");
|
||||
ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
|
||||
b->static_trace_marker_id);
|
||||
ui_out_text (uiout, "\n");
|
||||
}
|
||||
|
||||
if (part_of_multiple && frame_id_p (b->frame_id))
|
||||
{
|
||||
annotate_field (6);
|
||||
@ -5372,6 +5417,7 @@ allocate_bp_location (struct breakpoint *bpt)
|
||||
case bp_catchpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_static_tracepoint:
|
||||
loc->loc_type = bp_loc_other;
|
||||
break;
|
||||
default:
|
||||
@ -6748,6 +6794,16 @@ mention (struct breakpoint *b)
|
||||
printf_filtered (_(" %d"), b->number);
|
||||
say_where = 1;
|
||||
break;
|
||||
case bp_static_tracepoint:
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
{
|
||||
say_where = 0;
|
||||
break;
|
||||
}
|
||||
printf_filtered (_("Static tracepoint"));
|
||||
printf_filtered (_(" %d"), b->number);
|
||||
say_where = 1;
|
||||
break;
|
||||
|
||||
case bp_until:
|
||||
case bp_finish:
|
||||
@ -6927,9 +6983,47 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
|
||||
b->ignore_count = ignore_count;
|
||||
b->enable_state = enabled ? bp_enabled : bp_disabled;
|
||||
b->disposition = disposition;
|
||||
|
||||
b->pspace = sals.sals[0].pspace;
|
||||
|
||||
if (type == bp_static_tracepoint)
|
||||
{
|
||||
struct static_tracepoint_marker marker;
|
||||
|
||||
if (is_marker_spec (addr_string))
|
||||
{
|
||||
/* We already know the marker exists, otherwise, we
|
||||
wouldn't see a sal for it. */
|
||||
char *p = &addr_string[3];
|
||||
char *endp;
|
||||
char *marker_str;
|
||||
int i;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
endp = p;
|
||||
while (*endp != ' ' && *endp != '\t' && *endp != '\0')
|
||||
endp++;
|
||||
|
||||
marker_str = savestring (p, endp - p);
|
||||
b->static_trace_marker_id = marker_str;
|
||||
|
||||
printf_filtered (_("Probed static tracepoint marker \"%s\"\n"),
|
||||
b->static_trace_marker_id);
|
||||
}
|
||||
else if (target_static_tracepoint_marker_at (sal.pc, &marker))
|
||||
{
|
||||
b->static_trace_marker_id = xstrdup (marker.str_id);
|
||||
release_static_tracepoint_marker (&marker);
|
||||
|
||||
printf_filtered (_("Probed static tracepoint marker \"%s\"\n"),
|
||||
b->static_trace_marker_id);
|
||||
}
|
||||
else
|
||||
warning (_("\
|
||||
Couldn't determine the static tracepoint marker to probe"));
|
||||
}
|
||||
|
||||
if (enabled && b->pspace->executing_startup
|
||||
&& (b->type == bp_breakpoint
|
||||
|| b->type == bp_hardware_breakpoint))
|
||||
@ -7341,6 +7435,58 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode a static tracepoint marker spec. */
|
||||
|
||||
static struct symtabs_and_lines
|
||||
decode_static_tracepoint_spec (char **arg_p)
|
||||
{
|
||||
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;
|
||||
char *marker_str;
|
||||
int i;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
endp = p;
|
||||
while (*endp != ' ' && *endp != '\t' && *endp != '\0')
|
||||
endp++;
|
||||
|
||||
marker_str = savestring (p, endp - p);
|
||||
old_chain = make_cleanup (xfree, marker_str);
|
||||
|
||||
markers = target_static_tracepoint_markers_by_strid (marker_str);
|
||||
if (VEC_empty(static_tracepoint_marker_p, markers))
|
||||
error (_("No known static tracepoint marker named %s"), marker_str);
|
||||
|
||||
sals.nelts = VEC_length(static_tracepoint_marker_p, markers);
|
||||
sals.sals = xmalloc (sizeof *sals.sals * sals.nelts);
|
||||
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
{
|
||||
struct static_tracepoint_marker *marker;
|
||||
|
||||
marker = VEC_index (static_tracepoint_marker_p, markers, i);
|
||||
|
||||
init_sal (&sals.sals[i]);
|
||||
|
||||
sals.sals[i] = find_pc_line (marker->address, 0);
|
||||
sals.sals[i].pc = marker->address;
|
||||
|
||||
release_static_tracepoint_marker (marker);
|
||||
}
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
*arg_p = endp;
|
||||
return sals;
|
||||
}
|
||||
|
||||
/* Set a breakpoint. This function is shared between CLI and MI
|
||||
functions for setting a breakpoint. This function has two major
|
||||
modes of operations, selected by the PARSE_CONDITION_AND_THREAD
|
||||
@ -7354,7 +7500,7 @@ int
|
||||
create_breakpoint (struct gdbarch *gdbarch,
|
||||
char *arg, char *cond_string, int thread,
|
||||
int parse_condition_and_thread,
|
||||
int tempflag, int hardwareflag, int traceflag,
|
||||
int tempflag, enum bptype type_wanted,
|
||||
int ignore_count,
|
||||
enum auto_boolean pending_break_support,
|
||||
struct breakpoint_ops *ops,
|
||||
@ -7373,7 +7519,6 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||
int i;
|
||||
int pending = 0;
|
||||
int not_found = 0;
|
||||
enum bptype type_wanted;
|
||||
int task = 0;
|
||||
int prev_bkpt_count = breakpoint_count;
|
||||
|
||||
@ -7386,6 +7531,19 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||
parse_args.addr_string_p = &addr_string;
|
||||
parse_args.not_found_ptr = ¬_found;
|
||||
|
||||
if (type_wanted == bp_static_tracepoint && is_marker_spec (arg))
|
||||
{
|
||||
int i;
|
||||
|
||||
sals = decode_static_tracepoint_spec (&arg);
|
||||
|
||||
copy_arg = savestring (addr_start, arg - addr_start);
|
||||
addr_string = xcalloc (sals.nelts, sizeof (char **));
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
addr_string[i] = xstrdup (copy_arg);
|
||||
goto done;
|
||||
}
|
||||
|
||||
e = catch_exception (uiout, do_captured_parse_breakpoint,
|
||||
&parse_args, RETURN_MASK_ALL);
|
||||
|
||||
@ -7432,6 +7590,8 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||
return 0;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
/* Create a chain of things that always need to be cleaned up. */
|
||||
old_chain = make_cleanup (null_cleanup, 0);
|
||||
|
||||
@ -7463,10 +7623,6 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||
if (!pending)
|
||||
breakpoint_sals_to_pc (&sals);
|
||||
|
||||
type_wanted = (traceflag
|
||||
? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint)
|
||||
: (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
|
||||
|
||||
/* Fast tracepoints may have additional restrictions on location. */
|
||||
if (type_wanted == bp_fast_tracepoint)
|
||||
check_fast_tracepoint_sals (gdbarch, &sals);
|
||||
@ -7498,10 +7654,55 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||
make_cleanup (xfree, cond_string);
|
||||
}
|
||||
}
|
||||
create_breakpoints_sal (gdbarch, sals, addr_string, cond_string,
|
||||
type_wanted, tempflag ? disp_del : disp_donttouch,
|
||||
thread, task, ignore_count, ops, from_tty,
|
||||
enabled);
|
||||
|
||||
/* 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. */
|
||||
if (type_wanted == bp_static_tracepoint
|
||||
&& is_marker_spec (addr_string[0]))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sals.nelts; ++i)
|
||||
{
|
||||
struct symtabs_and_lines expanded;
|
||||
struct breakpoint *tp;
|
||||
struct cleanup *old_chain;
|
||||
|
||||
expanded.nelts = 1;
|
||||
expanded.sals = xmalloc (sizeof (struct symtab_and_line));
|
||||
expanded.sals[0] = sals.sals[i];
|
||||
old_chain = make_cleanup (xfree, expanded.sals);
|
||||
|
||||
create_breakpoint_sal (gdbarch, expanded, addr_string[i],
|
||||
cond_string, type_wanted,
|
||||
tempflag ? disp_del : disp_donttouch,
|
||||
thread, task, ignore_count, ops,
|
||||
from_tty, enabled);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/* Get the tracepoint we just created. */
|
||||
tp = get_breakpoint (breakpoint_count);
|
||||
gdb_assert (tp != NULL);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
create_breakpoints_sal (gdbarch, sals, addr_string, cond_string,
|
||||
type_wanted, tempflag ? disp_del : disp_donttouch,
|
||||
thread, task, ignore_count, ops, from_tty,
|
||||
enabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7559,13 +7760,15 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||
static void
|
||||
break_command_1 (char *arg, int flag, int from_tty)
|
||||
{
|
||||
int hardwareflag = flag & BP_HARDWAREFLAG;
|
||||
int tempflag = flag & BP_TEMPFLAG;
|
||||
enum bptype type_wanted = (flag & BP_HARDWAREFLAG
|
||||
? bp_hardware_breakpoint
|
||||
: bp_breakpoint);
|
||||
|
||||
create_breakpoint (get_current_arch (),
|
||||
arg,
|
||||
NULL, 0, 1 /* parse arg */,
|
||||
tempflag, hardwareflag, 0 /* traceflag */,
|
||||
tempflag, type_wanted,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL /* breakpoint_ops */,
|
||||
@ -8538,7 +8741,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
|
||||
create_breakpoint (get_current_arch (),
|
||||
trigger_func_name, cond_string, -1,
|
||||
0 /* condition and thread are valid. */,
|
||||
tempflag, 0, 0,
|
||||
tempflag, bp_breakpoint,
|
||||
0,
|
||||
AUTO_BOOLEAN_TRUE /* pending */,
|
||||
&gnu_v3_exception_catchpoint_ops, from_tty,
|
||||
@ -9590,6 +9793,139 @@ ambiguous_names_p (struct bp_location *loc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When symbols change, it probably means the sources changed as well,
|
||||
and it might mean the static tracepoint markers are no longer at
|
||||
the same address or line numbers they used to be at last we
|
||||
checked. Losing your static tracepoints whenever you rebuild is
|
||||
undesirable. This function tries to resync/rematch gdb static
|
||||
tracepoints with the markers on the target, for static tracepoints
|
||||
that have not been set by marker id. Static tracepoint that have
|
||||
been set by marker id are reset by marker id in breakpoint_re_set.
|
||||
The heuristic is:
|
||||
|
||||
1) For a tracepoint set at a specific address, look for a marker at
|
||||
the old PC. If one is found there, assume to be the same marker.
|
||||
If the name / string id of the marker found is different from the
|
||||
previous known name, assume that means the user renamed the marker
|
||||
in the sources, and output a warning.
|
||||
|
||||
2) For a tracepoint set at a given line number, look for a marker
|
||||
at the new address of the old line number. If one is found there,
|
||||
assume to be the same marker. If the name / string id of the
|
||||
marker found is different from the previous known name, assume that
|
||||
means the user renamed the marker in the sources, and output a
|
||||
warning.
|
||||
|
||||
3) If a marker is no longer found at the same address or line, it
|
||||
may mean the marker no longer exists. But it may also just mean
|
||||
the code changed a bit. Maybe the user added a few lines of code
|
||||
that made the marker move up or down (in line number terms). Ask
|
||||
the target for info about the marker with the string id as we knew
|
||||
it. If found, update line number and address in the matching
|
||||
static tracepoint. This will get confused if there's more than one
|
||||
marker with the same ID (possible in UST, although unadvised
|
||||
precisely because it confuses tools). */
|
||||
|
||||
static struct symtab_and_line
|
||||
update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
|
||||
{
|
||||
struct static_tracepoint_marker marker;
|
||||
CORE_ADDR pc;
|
||||
int i;
|
||||
|
||||
pc = sal.pc;
|
||||
if (sal.line)
|
||||
find_line_pc (sal.symtab, sal.line, &pc);
|
||||
|
||||
if (target_static_tracepoint_marker_at (pc, &marker))
|
||||
{
|
||||
if (strcmp (b->static_trace_marker_id, marker.str_id) != 0)
|
||||
warning (_("static tracepoint %d changed probed marker from %s to %s"),
|
||||
b->number,
|
||||
b->static_trace_marker_id, marker.str_id);
|
||||
|
||||
xfree (b->static_trace_marker_id);
|
||||
b->static_trace_marker_id = xstrdup (marker.str_id);
|
||||
release_static_tracepoint_marker (&marker);
|
||||
|
||||
return sal;
|
||||
}
|
||||
|
||||
/* Old marker wasn't found on target at lineno. Try looking it up
|
||||
by string ID. */
|
||||
if (!sal.explicit_pc
|
||||
&& sal.line != 0
|
||||
&& sal.symtab != NULL
|
||||
&& b->static_trace_marker_id != NULL)
|
||||
{
|
||||
VEC(static_tracepoint_marker_p) *markers;
|
||||
|
||||
markers
|
||||
= target_static_tracepoint_markers_by_strid (b->static_trace_marker_id);
|
||||
|
||||
if (!VEC_empty(static_tracepoint_marker_p, markers))
|
||||
{
|
||||
struct symtab_and_line sal;
|
||||
struct symbol *sym;
|
||||
struct static_tracepoint_marker *marker;
|
||||
|
||||
marker = VEC_index (static_tracepoint_marker_p, markers, 0);
|
||||
|
||||
xfree (b->static_trace_marker_id);
|
||||
b->static_trace_marker_id = xstrdup (marker->str_id);
|
||||
|
||||
warning (_("marker for static tracepoint %d (%s) not "
|
||||
"found at previous line number"),
|
||||
b->number, b->static_trace_marker_id);
|
||||
|
||||
init_sal (&sal);
|
||||
|
||||
sal.pc = marker->address;
|
||||
|
||||
sal = find_pc_line (marker->address, 0);
|
||||
sym = find_pc_sect_function (marker->address, NULL);
|
||||
ui_out_text (uiout, "Now in ");
|
||||
if (sym)
|
||||
{
|
||||
ui_out_field_string (uiout, "func",
|
||||
SYMBOL_PRINT_NAME (sym));
|
||||
ui_out_text (uiout, " at ");
|
||||
}
|
||||
ui_out_field_string (uiout, "file", sal.symtab->filename);
|
||||
ui_out_text (uiout, ":");
|
||||
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
{
|
||||
char *fullname = symtab_to_fullname (sal.symtab);
|
||||
|
||||
if (fullname)
|
||||
ui_out_field_string (uiout, "fullname", fullname);
|
||||
}
|
||||
|
||||
ui_out_field_int (uiout, "line", sal.line);
|
||||
ui_out_text (uiout, "\n");
|
||||
|
||||
b->line_number = sal.line;
|
||||
|
||||
xfree (b->source_file);
|
||||
if (sym)
|
||||
b->source_file = xstrdup (sal.symtab->filename);
|
||||
else
|
||||
b->source_file = NULL;
|
||||
|
||||
xfree (b->addr_string);
|
||||
b->addr_string = xstrprintf ("%s:%d",
|
||||
sal.symtab->filename, b->line_number);
|
||||
|
||||
/* Might be nice to check if function changed, and warn if
|
||||
so. */
|
||||
|
||||
release_static_tracepoint_marker (marker);
|
||||
}
|
||||
}
|
||||
return sal;
|
||||
}
|
||||
|
||||
static void
|
||||
update_breakpoint_locations (struct breakpoint *b,
|
||||
struct symtabs_and_lines sals)
|
||||
@ -9692,7 +10028,6 @@ update_breakpoint_locations (struct breakpoint *b,
|
||||
update_global_location_list (1);
|
||||
}
|
||||
|
||||
|
||||
/* Reset a breakpoint given it's struct breakpoint * BINT.
|
||||
The value we return ends up being the return value from catch_errors.
|
||||
Unused in this case. */
|
||||
@ -9709,6 +10044,7 @@ breakpoint_re_set_one (void *bint)
|
||||
char *s;
|
||||
struct gdb_exception e;
|
||||
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
|
||||
int marker_spec = 0;
|
||||
|
||||
switch (b->type)
|
||||
{
|
||||
@ -9720,6 +10056,7 @@ breakpoint_re_set_one (void *bint)
|
||||
case bp_hardware_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_static_tracepoint:
|
||||
/* Do not attempt to re-set breakpoints disabled during startup. */
|
||||
if (b->enable_state == bp_startup_disabled)
|
||||
return 0;
|
||||
@ -9738,10 +10075,24 @@ breakpoint_re_set_one (void *bint)
|
||||
save_current_space_and_thread ();
|
||||
switch_to_program_space_and_thread (b->pspace);
|
||||
|
||||
marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s);
|
||||
|
||||
TRY_CATCH (e, RETURN_MASK_ERROR)
|
||||
{
|
||||
sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
|
||||
not_found_ptr);
|
||||
if (marker_spec)
|
||||
{
|
||||
sals = decode_static_tracepoint_spec (&s);
|
||||
if (sals.nelts > b->static_trace_marker_id_idx)
|
||||
{
|
||||
sals.sals[0] = sals.sals[b->static_trace_marker_id_idx];
|
||||
sals.nelts = 1;
|
||||
}
|
||||
else
|
||||
error (_("marker %s not found"), b->static_trace_marker_id);
|
||||
}
|
||||
else
|
||||
sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
|
||||
not_found_ptr);
|
||||
}
|
||||
if (e.reason < 0)
|
||||
{
|
||||
@ -9791,6 +10142,9 @@ breakpoint_re_set_one (void *bint)
|
||||
b->condition_not_parsed = 0;
|
||||
}
|
||||
|
||||
if (b->type == bp_static_tracepoint && !marker_spec)
|
||||
sals.sals[0] = update_static_tracepoint (b, sals.sals[0]);
|
||||
|
||||
expanded = expand_line_sal_maybe (sals.sals[0]);
|
||||
}
|
||||
|
||||
@ -10143,6 +10497,7 @@ disable_command (char *args, int from_tty)
|
||||
case bp_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_static_tracepoint:
|
||||
case bp_catchpoint:
|
||||
case bp_hardware_breakpoint:
|
||||
case bp_watchpoint:
|
||||
@ -10243,6 +10598,7 @@ enable_command (char *args, int from_tty)
|
||||
case bp_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_static_tracepoint:
|
||||
case bp_catchpoint:
|
||||
case bp_hardware_breakpoint:
|
||||
case bp_watchpoint:
|
||||
@ -10576,8 +10932,8 @@ trace_command (char *arg, int from_tty)
|
||||
if (create_breakpoint (get_current_arch (),
|
||||
arg,
|
||||
NULL, 0, 1 /* parse arg */,
|
||||
0 /* tempflag */, 0 /* hardwareflag */,
|
||||
1 /* traceflag */,
|
||||
0 /* tempflag */,
|
||||
bp_tracepoint /* type_wanted */,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL,
|
||||
@ -10592,8 +10948,26 @@ ftrace_command (char *arg, int from_tty)
|
||||
if (create_breakpoint (get_current_arch (),
|
||||
arg,
|
||||
NULL, 0, 1 /* parse arg */,
|
||||
0 /* tempflag */, 1 /* hardwareflag */,
|
||||
1 /* traceflag */,
|
||||
0 /* tempflag */,
|
||||
bp_fast_tracepoint /* type_wanted */,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL,
|
||||
from_tty,
|
||||
1 /* enabled */))
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
/* strace command implementation. Creates a static tracepoint. */
|
||||
|
||||
void
|
||||
strace_command (char *arg, int from_tty)
|
||||
{
|
||||
if (create_breakpoint (get_current_arch (),
|
||||
arg,
|
||||
NULL, 0, 1 /* parse arg */,
|
||||
0 /* tempflag */,
|
||||
bp_static_tracepoint /* type_wanted */,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL,
|
||||
@ -10655,8 +11029,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
|
||||
addr_str,
|
||||
utp->cond_string, -1, 0 /* parse cond/thread */,
|
||||
0 /* tempflag */,
|
||||
(utp->type == bp_fast_tracepoint) /* hardwareflag */,
|
||||
1 /* traceflag */,
|
||||
utp->type /* type_wanted */,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL,
|
||||
@ -10978,6 +11351,8 @@ save_breakpoints (char *filename, int from_tty,
|
||||
{
|
||||
if (tp->type == bp_fast_tracepoint)
|
||||
fprintf_unfiltered (fp, "ftrace");
|
||||
if (tp->type == bp_static_tracepoint)
|
||||
fprintf_unfiltered (fp, "strace");
|
||||
else if (tp->type == bp_tracepoint)
|
||||
fprintf_unfiltered (fp, "trace");
|
||||
else if (tp->type == bp_breakpoint && tp->disposition == disp_del)
|
||||
@ -11562,6 +11937,31 @@ BREAK_ARGS_HELP ("ftrace") "\n\
|
||||
Do \"help tracepoints\" for info on other tracepoint commands."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
|
||||
c = add_com ("strace", class_breakpoint, strace_command, _("\
|
||||
Set a static tracepoint at specified line, function or marker.\n\
|
||||
\n\
|
||||
strace [LOCATION] [if CONDITION]\n\
|
||||
LOCATION may be a line number, function name, \"*\" and an address,\n\
|
||||
or -m MARKER_ID.\n\
|
||||
If a line number is specified, probe the marker at start of code\n\
|
||||
for that line. If a function is specified, probe the marker at start\n\
|
||||
of code for that function. If an address is specified, probe the marker\n\
|
||||
at that exact address. If a marker id is specified, probe the marker\n\
|
||||
with that name. With no LOCATION, uses current execution address of\n\
|
||||
the selected stack frame.\n\
|
||||
Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
|
||||
This collects arbitrary user data passed in the probe point call to the\n\
|
||||
tracing library. You can inspect it when analyzing the trace buffer,\n\
|
||||
by printing the $_sdata variable like any other convenience variable.\n\
|
||||
\n\
|
||||
CONDITION is a boolean expression.\n\
|
||||
\n\
|
||||
Multiple tracepoints at one place are permitted, and useful if conditional.\n\
|
||||
\n\
|
||||
Do \"help breakpoints\" for info on other commands dealing with breakpoints.\n\
|
||||
Do \"help tracepoints\" for info on other tracepoint commands."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
|
||||
add_info ("tracepoints", tracepoints_info, _("\
|
||||
Status of tracepoints, or tracepoint number NUMBER.\n\
|
||||
Convenience variable \"$tpnum\" contains the number of the\n\
|
||||
|
Reference in New Issue
Block a user