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:
parent
76fa04a48e
commit
0fb4aa4bfc
26 changed files with 3149 additions and 69 deletions
|
@ -1,3 +1,91 @@
|
|||
2010-07-01 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
Static tracepoints support.
|
||||
|
||||
* 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.
|
||||
|
||||
2010-06-30 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* python/python-internal.h (_XOPEN_SOURCE): Undefine before
|
||||
|
|
69
gdb/NEWS
69
gdb/NEWS
|
@ -46,6 +46,27 @@
|
|||
thread-specific pointer to the TIB. This feature is also supported
|
||||
when remote debugging using GDBserver.
|
||||
|
||||
* Static tracepoints
|
||||
|
||||
Static tracepoints are calls in the user program into a tracing
|
||||
library. One such library is a port of the LTTng kernel tracer to
|
||||
userspace --- UST (LTTng Userspace Tracer, http://lttng.org/ust).
|
||||
When debugging with GDBserver, GDB now supports combining the GDB
|
||||
tracepoint machinery with such libraries. For example: the user can
|
||||
use GDB to probe a static tracepoint marker (a call from the user
|
||||
program into the tracing library) with the new "strace" command (see
|
||||
"New commands" below). This creates a "static tracepoint" in the
|
||||
breakpoint list, that can be manipulated with the same feature set
|
||||
as fast and regular tracepoints. E.g., collect registers, local and
|
||||
global variables, collect trace state variables, and define
|
||||
tracepoint conditions. In addition, the user can collect extra
|
||||
static tracepoint marker specific data, by collecting the new
|
||||
$_sdata internal variable. When analyzing the trace buffer, you can
|
||||
inspect $_sdata like any other variable available to GDB. For more
|
||||
information, see the "Tracepoints" chapter in GDB user manual. New
|
||||
remote packets have been defined to support static tracepoints, see
|
||||
the "New remote packets" section below.
|
||||
|
||||
* New remote packets
|
||||
|
||||
qGetTIBAddr
|
||||
|
@ -61,23 +82,42 @@ qRelocInsn
|
|||
is particularly useful for stubs that support fast tracepoints. GDB
|
||||
reports support for this feature in the qSupported packet.
|
||||
|
||||
qTfSTM, qTsSTM
|
||||
|
||||
List static tracepoint markers in the target program.
|
||||
|
||||
qTSTMat
|
||||
|
||||
List static tracepoint markers at a given address in the target
|
||||
program.
|
||||
|
||||
qXfer:statictrace:read
|
||||
|
||||
Read the static trace data collected (by a `collect $_sdata'
|
||||
tracepoint action). The remote stub reports support for this packet
|
||||
to gdb's qSupported query.
|
||||
|
||||
* The source command now accepts a -s option to force searching for the
|
||||
script in the source search path even if the script name specifies
|
||||
a directory.
|
||||
|
||||
* New features in the GDB remote stub, GDBserver
|
||||
|
||||
- GDBserver now support tracepoints (including fast tracepoints).
|
||||
The feature is currently supported by the i386-linux and
|
||||
amd64-linux builds. See the "Tracepoints support in gdbserver"
|
||||
section in the manual for more information. GDBserver JIT
|
||||
compiles the tracepoint's conditional agent expression bytecode
|
||||
into native code whenever possible for low overhead dynamic
|
||||
tracepoints conditionals. For such tracepoints, an expression
|
||||
that examines program state is evaluated when the tracepoint is
|
||||
reached, in order to determine whether to capture trace data. If
|
||||
the condition is simple and false, processing the tracepoint
|
||||
finishes very quickly and no data is gathered.
|
||||
- GDBserver now support tracepoints (including fast tracepoints, and
|
||||
static tracepoints). The feature is currently supported by the
|
||||
i386-linux and amd64-linux builds. See the "Tracepoints support
|
||||
in gdbserver" section in the manual for more information.
|
||||
|
||||
GDBserver JIT compiles the tracepoint's conditional agent
|
||||
expression bytecode into native code whenever possible for low
|
||||
overhead dynamic tracepoints conditionals. For such tracepoints,
|
||||
an expression that examines program state is evaluated when the
|
||||
tracepoint is reached, in order to determine whether to capture
|
||||
trace data. If the condition is simple and false, processing the
|
||||
tracepoint finishes very quickly and no data is gathered.
|
||||
|
||||
GDBserver interfaces with the UST (LTTng Userspace Tracer) library
|
||||
for static tracepoints support.
|
||||
|
||||
- GDBserver now supports x86_64 Windows 64-bit debugging.
|
||||
|
||||
|
@ -135,6 +175,13 @@ save breakpoints <filename>
|
|||
`save tracepoints' is a new alias for `save-tracepoints'. The latter
|
||||
is now deprecated.
|
||||
|
||||
info static-tracepoint-markers
|
||||
Display information about static tracepoint markers in the target.
|
||||
|
||||
strace FN | FILE:LINE | *ADDR | -m MARKER_ID
|
||||
Define a static tracepoint by probing a marker at the given
|
||||
function, line, address, or marker ID.
|
||||
|
||||
* Python scripting
|
||||
|
||||
** GDB now provides a new directory location, called the python directory,
|
||||
|
|
438
gdb/breakpoint.c
438
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,6 +7654,51 @@ create_breakpoint (struct gdbarch *gdbarch,
|
|||
make_cleanup (xfree, cond_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
|
@ -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,8 +10075,22 @@ 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -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\
|
||||
|
|
|
@ -129,6 +129,7 @@ enum bptype
|
|||
|
||||
bp_tracepoint,
|
||||
bp_fast_tracepoint,
|
||||
bp_static_tracepoint,
|
||||
|
||||
/* Event for JIT compiled code generation or deletion. */
|
||||
bp_jit_event,
|
||||
|
@ -536,6 +537,18 @@ struct breakpoint
|
|||
|
||||
/* The number of the tracepoint on the target. */
|
||||
int number_on_target;
|
||||
|
||||
/* The static tracepoint marker id, if known. */
|
||||
char *static_trace_marker_id;
|
||||
|
||||
/* LTTng/UST allow more than one marker with the same ID string,
|
||||
although it unadvised because it confuses tools. When setting
|
||||
static tracepoints by marker ID, this will record the index in
|
||||
the array of markers we found for the given marker ID for which
|
||||
this static tracepoint corresponds. When resetting
|
||||
breakpoints, we will use this index to try to find the same
|
||||
marker again. */
|
||||
int static_trace_marker_id_idx;
|
||||
};
|
||||
|
||||
typedef struct breakpoint *breakpoint_p;
|
||||
|
@ -821,7 +834,7 @@ extern void tbreak_command (char *, int);
|
|||
extern 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 wanted_type,
|
||||
int ignore_count,
|
||||
enum auto_boolean pending_break_support,
|
||||
struct breakpoint_ops *ops,
|
||||
|
@ -1044,6 +1057,11 @@ extern VEC(breakpoint_p) *all_tracepoints (void);
|
|||
|
||||
extern int is_tracepoint (const struct breakpoint *b);
|
||||
|
||||
/* Return a vector of all static tracepoints defined at ADDR. The
|
||||
vector is newly allocated; the caller should free when done with
|
||||
it. */
|
||||
extern VEC(breakpoint_p) *static_tracepoints_here (CORE_ADDR addr);
|
||||
|
||||
/* Function that can be passed to read_command_line to validate
|
||||
that each command is suitable for tracepoint command list. */
|
||||
extern void check_tracepoint_command (char *line, void *closure);
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
2010-07-01 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2010-06-29 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* gdb.texinfo (Threads In Python): Fix unmatched @end table.
|
||||
|
|
|
@ -8279,6 +8279,13 @@ to match the format in which the data was printed.
|
|||
The variable @code{$_exitcode} is automatically set to the exit code when
|
||||
the program being debugged terminates.
|
||||
|
||||
@item $_sdata
|
||||
@vindex $_sdata@r{, inspect, convenience variable}
|
||||
The variable @code{$_sdata} contains extra collected static tracepoint
|
||||
data. @xref{Tracepoint Actions,,Tracepoint Action Lists}. Note that
|
||||
@code{$_sdata} could be empty, if not inspecting a trace buffer, or
|
||||
if extra static tracepoint data has not been collected.
|
||||
|
||||
@item $_siginfo
|
||||
@vindex $_siginfo@r{, convenience variable}
|
||||
The variable @code{$_siginfo} contains extra signal information
|
||||
|
@ -9590,6 +9597,27 @@ Some targets may support @dfn{fast tracepoints}, which are inserted in
|
|||
a different way (such as with a jump instead of a trap), that is
|
||||
faster but possibly restricted in where they may be installed.
|
||||
|
||||
@cindex static tracepoints
|
||||
@cindex markers, static tracepoints
|
||||
@cindex probing markers, static tracepoints
|
||||
Regular and fast tracepoints are dynamic tracing facilities, meaning
|
||||
that they can be used to insert tracepoints at (almost) any location
|
||||
in the target. Some targets may also support controlling @dfn{static
|
||||
tracepoints} from @value{GDBN}. With static tracing, a set of
|
||||
instrumentation points, also known as @dfn{markers}, are embedded in
|
||||
the target program, and can be activated or deactivated by name or
|
||||
address. These are usually placed at locations which facilitate
|
||||
investigating what the target is actually doing. @value{GDBN}'s
|
||||
support for static tracing includes being able to list instrumentation
|
||||
points, and attach them with @value{GDBN} defined high level
|
||||
tracepoints that expose the whole range of convenience of
|
||||
@value{GDBN}'s tracepoints support. Namelly, support for collecting
|
||||
registers values and values of global or local (to the instrumentation
|
||||
point) variables; tracepoint conditions and trace state variables.
|
||||
The act of installing a @value{GDBN} static tracepoint on an
|
||||
instrumentation point, or marker, is referred to as @dfn{probing} a
|
||||
static tracepoint marker.
|
||||
|
||||
@code{gdbserver} supports tracepoints on some target systems.
|
||||
@xref{Server,,Tracepoints support in @code{gdbserver}}.
|
||||
|
||||
|
@ -9604,6 +9632,7 @@ conditions and actions.
|
|||
* Trace State Variables::
|
||||
* Tracepoint Actions::
|
||||
* Listing Tracepoints::
|
||||
* Listing Static Tracepoint Markers::
|
||||
* Starting and Stopping Trace Experiments::
|
||||
* Tracepoint Restrictions::
|
||||
@end menu
|
||||
|
@ -9663,6 +9692,65 @@ message.
|
|||
@value{GDBN} handles arguments to @code{ftrace} exactly as for
|
||||
@code{trace}.
|
||||
|
||||
@item strace @var{location} [ if @var{cond} ]
|
||||
@cindex static tracepoint, setting
|
||||
@kindex strace
|
||||
The @code{strace} command sets a static tracepoint. For targets that
|
||||
support it, setting a static tracepoint probes a static
|
||||
instrumentation point, or marker, found at @var{location}. It may not
|
||||
be possible to set a static tracepoint at the desired location, in
|
||||
which case the command will exit with an explanatory message.
|
||||
|
||||
@value{GDBN} handles arguments to @code{strace} exactly as for
|
||||
@code{trace}, with the addition that the user can also specify
|
||||
@code{-m @var{marker}} as @var{location}. This probes the marker
|
||||
identified by the @var{marker} string identifier. This identifier
|
||||
depends on the static tracepoint backend library your program is
|
||||
using. You can find all the marker identifiers in the @samp{ID} field
|
||||
of the @code{info static-tracepoint-markers} command output.
|
||||
@xref{Listing Static Tracepoint Markers,,Listing Static Tracepoint
|
||||
Markers}. For example, in the following small program using the UST
|
||||
tracing engine:
|
||||
|
||||
@smallexample
|
||||
main ()
|
||||
@{
|
||||
trace_mark(ust, bar33, "str %s", "FOOBAZ");
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
the marker id is composed of joining the first two arguments to the
|
||||
@code{trace_mark} call with a slash, which translates to:
|
||||
|
||||
@smallexample
|
||||
(@value{GDBP}) info static-tracepoint-markers
|
||||
Cnt Enb ID Address What
|
||||
1 n ust/bar33 0x0000000000400ddc in main at stexample.c:22
|
||||
Data: "str %s"
|
||||
[etc...]
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
so you may probe the marker above with:
|
||||
|
||||
@smallexample
|
||||
(@value{GDBP}) strace -m ust/bar33
|
||||
@end smallexample
|
||||
|
||||
Static tracepoints accept an extra collect action --- @code{collect
|
||||
$_sdata}. This collects arbitrary user data passed in the probe point
|
||||
call to the tracing library. In the UST example above, you'll see
|
||||
that the third argument to @code{trace_mark} is a printf-like format
|
||||
string. The user data is then the result of running that formating
|
||||
string against the following arguments. Note that @code{info
|
||||
static-tracepoint-markers} command output lists that format string in
|
||||
the @samp{Data:} field.
|
||||
|
||||
You can inspect this data when analyzing the trace buffer, by printing
|
||||
the $_sdata variable like any other variable available to
|
||||
@value{GDBN}. @xref{Tracepoint Actions,,Tracepoint Action Lists}.
|
||||
|
||||
@vindex $tpnum
|
||||
@cindex last tracepoint number
|
||||
@cindex recent tracepoint number
|
||||
|
@ -9899,13 +9987,34 @@ special arguments are supported:
|
|||
|
||||
@table @code
|
||||
@item $regs
|
||||
collect all registers
|
||||
Collect all registers.
|
||||
|
||||
@item $args
|
||||
collect all function arguments
|
||||
Collect all function arguments.
|
||||
|
||||
@item $locals
|
||||
collect all local variables.
|
||||
Collect all local variables.
|
||||
|
||||
@item $_sdata
|
||||
@vindex $_sdata@r{, collect}
|
||||
Collect static tracepoint marker specific data. Only available for
|
||||
static tracepoints. @xref{Tracepoint Actions,,Tracepoint Action
|
||||
Lists}. On the UST static tracepoints library backend, an
|
||||
instrumentation point resembles a @code{printf} function call. The
|
||||
tracing library is able to collect user specified data formatted to a
|
||||
character string using the format provided by the programmer that
|
||||
instrumented the program. Other backends have similar mechanisms.
|
||||
Here's an example of a UST marker call:
|
||||
|
||||
@smallexample
|
||||
const char master_name[] = "$your_name";
|
||||
trace_mark(channel1, marker1, "hello %s", master_name)
|
||||
@end smallexample
|
||||
|
||||
In this case, collecting @code{$_sdata} collects the string
|
||||
@samp{hello $yourname}. When analyzing the trace buffer, you can
|
||||
inspect @samp{$_sdata} like any other variable available to
|
||||
@value{GDBN}.
|
||||
@end table
|
||||
|
||||
You can give several consecutive @code{collect} commands, each one
|
||||
|
@ -10000,6 +10109,60 @@ Num Type Disp Enb Address What
|
|||
This command can be abbreviated @code{info tp}.
|
||||
@end table
|
||||
|
||||
@node Listing Static Tracepoint Markers
|
||||
@subsection Listing Static Tracepoint Markers
|
||||
|
||||
@table @code
|
||||
@kindex info static-tracepoint-markers
|
||||
@cindex information about static tracepoint markers
|
||||
@item info static-tracepoint-markers
|
||||
Display information about all static tracepoint markers defined in the
|
||||
program.
|
||||
|
||||
For each marker, the following columns are printed:
|
||||
|
||||
@table @emph
|
||||
@item Count
|
||||
An incrementing counter, output to help readability. This is not a
|
||||
stable identifier.
|
||||
@item ID
|
||||
The marker ID, as reported by the target.
|
||||
@item Enabled or Disabled
|
||||
Probed markers are tagged with @samp{y}. @samp{n} identifies marks
|
||||
that are not enabled.
|
||||
@item Address
|
||||
Where the marker is in your program, as a memory address.
|
||||
@item What
|
||||
Where the marker is in the source for your program, as a file and line
|
||||
number. If the debug information included in the program does not
|
||||
allow @value{GDBN} to locate the source of the marker, this column
|
||||
will be left blank.
|
||||
@end table
|
||||
|
||||
@noindent
|
||||
In addition, the following information may be printed for each marker:
|
||||
|
||||
@table @emph
|
||||
@item Data
|
||||
User data passed to the tracing library by the marker call. In the
|
||||
UST backend, this is the format string passed as argument to the
|
||||
marker call.
|
||||
@item Static tracepoints probing the marker
|
||||
The list of static tracepoints attached to the marker.
|
||||
@end table
|
||||
|
||||
@smallexample
|
||||
(@value{GDBP}) info static-tracepoint-markers
|
||||
Cnt ID Enb Address What
|
||||
1 ust/bar2 y 0x0000000000400e1a in main at stexample.c:25
|
||||
Data: number1 %d number2 %d
|
||||
Probed by static tracepoints: #2
|
||||
2 ust/bar33 n 0x0000000000400c87 in main at stexample.c:24
|
||||
Data: str %s
|
||||
(@value{GDBP})
|
||||
@end smallexample
|
||||
@end table
|
||||
|
||||
@node Starting and Stopping Trace Experiments
|
||||
@subsection Starting and Stopping Trace Experiments
|
||||
|
||||
|
@ -15848,13 +16011,21 @@ of a multi-process mode debug session.
|
|||
@subsection Tracepoints support in @code{gdbserver}
|
||||
@cindex tracepoints support in @code{gdbserver}
|
||||
|
||||
On some targets, @code{gdbserver} supports tracepoints and fast
|
||||
tracepoints.
|
||||
On some targets, @code{gdbserver} supports tracepoints, fast
|
||||
tracepoints and static tracepoints.
|
||||
|
||||
For fast tracepoints to work, a special library called the
|
||||
For fast or static tracepoints to work, a special library called the
|
||||
@dfn{in-process agent} (IPA), must be loaded in the inferior process.
|
||||
This library is built and distributed as an integral part of
|
||||
@code{gdbserver}.
|
||||
@code{gdbserver}. In addition, support for static tracepoints
|
||||
requires building the in-process agent library with static tracepoints
|
||||
support. At present, the UST (LTTng Userspace Tracer,
|
||||
@url{http://lttng.org/ust}) tracing engine is supported. This support
|
||||
is automatically available if UST development headers are found in the
|
||||
standard include path when @code{gdbserver} is built, or if
|
||||
@code{gdbserver} was explicitly configured using @option{--with-ust}
|
||||
to point at such headers. You can explicitly disable the support
|
||||
using @option{--with-ust=no}.
|
||||
|
||||
There are several ways to load the in-process agent in your program:
|
||||
|
||||
|
@ -15895,10 +16066,10 @@ systems, when you connect to @code{gdbserver} using @code{target
|
|||
remote}, you'll find that the program is stopped at the dynamic
|
||||
loader's entry point, and no shared library has been loaded in the
|
||||
program's address space yet, including the in-process agent. In that
|
||||
case, before being able to use any of the fast tracepoints features,
|
||||
you need to let the loader run and load the shared libraries. The
|
||||
most simple way to do that is to run the program to the main
|
||||
procedure. E.g., if debugging a C or C@t{++} program, start
|
||||
case, before being able to use any of the fast or static tracepoints
|
||||
features, you need to let the loader run and load the shared
|
||||
libraries. The simplest way to do that is to run the program to the
|
||||
main procedure. E.g., if debugging a C or C@t{++} program, start
|
||||
@code{gdbserver} like so:
|
||||
|
||||
@smallexample
|
||||
|
@ -15918,7 +16089,8 @@ $ gdb myprogram
|
|||
The in-process tracing agent library should now be loaded into the
|
||||
process; you can confirm it with the @code{info sharedlibrary}
|
||||
command, which will list @file{libinproctrace.so} as loaded in the
|
||||
process. You are now ready to install fast tracepoints and start
|
||||
process. You are now ready to install fast tracepoints, list static
|
||||
tracepoint markers, probe static tracepoints markers, and start
|
||||
tracing.
|
||||
|
||||
@node Remote Configuration
|
||||
|
@ -16170,6 +16342,10 @@ are:
|
|||
@tab @code{qXfer:memory-map:read}
|
||||
@tab @code{info mem}
|
||||
|
||||
@item @code{read-sdata-object}
|
||||
@tab @code{qXfer:sdata:read}
|
||||
@tab @code{print $_sdata}
|
||||
|
||||
@item @code{read-spu-object}
|
||||
@tab @code{qXfer:spu:read}
|
||||
@tab @code{info spu}
|
||||
|
@ -31958,6 +32134,11 @@ These are the currently defined stub features and their properties:
|
|||
@tab @samp{-}
|
||||
@tab Yes
|
||||
|
||||
@item @samp{qXfer:sdata:read}
|
||||
@tab No
|
||||
@tab @samp{-}
|
||||
@tab Yes
|
||||
|
||||
@item @samp{qXfer:spu:read}
|
||||
@tab No
|
||||
@tab @samp{-}
|
||||
|
@ -32061,6 +32242,10 @@ The remote stub understands the @samp{qXfer:libraries:read} packet
|
|||
The remote stub understands the @samp{qXfer:memory-map:read} packet
|
||||
(@pxref{qXfer memory map read}).
|
||||
|
||||
@item qXfer:sdata:read
|
||||
The remote stub understands the @samp{qXfer:sdata:read} packet
|
||||
(@pxref{qXfer sdata read}).
|
||||
|
||||
@item qXfer:spu:read
|
||||
The remote stub understands the @samp{qXfer:spu:read} packet
|
||||
(@pxref{qXfer spu read}).
|
||||
|
@ -32129,6 +32314,10 @@ the source form of tracepoint definitions.
|
|||
@item QAllow
|
||||
The remote stub understands the @samp{QAllow} packet.
|
||||
|
||||
@item StaticTracepoint
|
||||
@cindex static tracepoints, in remote protocol
|
||||
The remote stub supports static tracepoints.
|
||||
|
||||
@end table
|
||||
|
||||
@item qSymbol::
|
||||
|
@ -32213,6 +32402,9 @@ packets.)
|
|||
@itemx QTro
|
||||
@itemx qTStatus
|
||||
@itemx qTV
|
||||
@itemx qTfSTM
|
||||
@itemx qTsSTM
|
||||
@itemx qTSTMat
|
||||
@xref{Tracepoint Packets}.
|
||||
|
||||
@item qXfer:@var{object}:read:@var{annex}:@var{offset},@var{length}
|
||||
|
@ -32269,6 +32461,18 @@ annex part of the generic @samp{qXfer} packet must be empty
|
|||
This packet is not probed by default; the remote stub must request it,
|
||||
by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
|
||||
|
||||
@item qXfer:sdata:read::@var{offset},@var{length}
|
||||
@anchor{qXfer sdata read}
|
||||
|
||||
Read contents of the extra collected static tracepoint marker
|
||||
information. The annex part of the generic @samp{qXfer} packet must
|
||||
be empty (@pxref{qXfer read}). @xref{Tracepoint Actions,,Tracepoint
|
||||
Action Lists}.
|
||||
|
||||
This packet is not probed by default; the remote stub must request it,
|
||||
by supplying an appropriate @samp{qSupported} response
|
||||
(@pxref{qSupported}).
|
||||
|
||||
@item qXfer:siginfo:read::@var{offset},@var{length}
|
||||
@anchor{qXfer siginfo read}
|
||||
Read contents of the extra signal information on the target
|
||||
|
@ -32808,6 +33012,43 @@ and multiple @code{qTsV} to get additional variables. Replies to
|
|||
these packets follow the syntax of the @code{QTDV} packets that define
|
||||
trace state variables.
|
||||
|
||||
@item qTfSTM
|
||||
@itemx qTsSTM
|
||||
These packets request data about static tracepoint markers that exist
|
||||
in the target program. @value{GDBN} sends @code{qTfSTM} to get the
|
||||
first piece of data, and multiple @code{qTsSTM} to get additional
|
||||
pieces. Replies to these packets take the following form:
|
||||
|
||||
Reply:
|
||||
@table @samp
|
||||
@item m @var{address}:@var{id}:@var{extra}
|
||||
A single marker
|
||||
@item m @var{address}:@var{id}:@var{extra},@var{address}:@var{id}:@var{extra}@dots{}
|
||||
a comma-separated list of markers
|
||||
@item l
|
||||
(lower case letter @samp{L}) denotes end of list.
|
||||
@item E @var{nn}
|
||||
An error occurred. @var{nn} are hex digits.
|
||||
@item
|
||||
An empty reply indicates that the request is not supported by the
|
||||
stub.
|
||||
@end table
|
||||
|
||||
@var{address} is encoded in hex.
|
||||
@var{id} and @var{extra} are strings encoded in hex.
|
||||
|
||||
In response to each query, the target will reply with a list of one or
|
||||
more markers, separated by commas. @value{GDBN} will respond to each
|
||||
reply with a request for more markers (using the @samp{qs} form of the
|
||||
query), until the target responds with @samp{l} (lower-case ell, for
|
||||
@dfn{last}).
|
||||
|
||||
@item qTSTMat:@var{address}
|
||||
This packets requests data about static tracepoint markers in the
|
||||
target program at @var{address}. Replies to this packet follow the
|
||||
syntax of the @samp{qTfSTM} and @code{qTsSTM} packets that list static
|
||||
tracepoint markers.
|
||||
|
||||
@item QTSave:@var{filename}
|
||||
This packet directs the target to save trace data to the file name
|
||||
@var{filename} in the target's filesystem. @var{filename} is encoded
|
||||
|
|
|
@ -1,3 +1,89 @@
|
|||
2010-07-01 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
Static tracepoints, and integration with UST.
|
||||
|
||||
* 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.
|
||||
|
||||
2010-06-20 Ian Lance Taylor <iant@google.com>
|
||||
Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ CC-LD=${CC}
|
|||
INCLUDE_DIR = ${srcdir}/../../include
|
||||
INCLUDE_DEP = $$(INCLUDE_DIR)
|
||||
|
||||
# Where is ust? These will be empty if ust was not available.
|
||||
ustlibs = @ustlibs@
|
||||
ustinc = @ustinc@
|
||||
|
||||
# All the includes used for CFLAGS and for lint.
|
||||
# -I. for config files.
|
||||
# -I${srcdir} for our headers.
|
||||
|
@ -193,14 +197,14 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS)
|
|||
${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
|
||||
$(XM_CLIBS)
|
||||
|
||||
IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o ${IPA_DEPFILES}
|
||||
IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o ${IPA_DEPFILES}
|
||||
|
||||
IPA_LIB=libinproctrace.so
|
||||
|
||||
$(IPA_LIB): $(IPA_OBJS) ${ADD_DEPS} ${CDEPS}
|
||||
rm -f $(IPA_LIB)
|
||||
${CC-LD} -shared -fPIC -Wl,--no-undefined $(INTERNAL_CFLAGS) \
|
||||
$(INTERNAL_LDFLAGS) -o $(IPA_LIB) ${IPA_OBJS}
|
||||
$(INTERNAL_LDFLAGS) -o $(IPA_LIB) ${IPA_OBJS} -ldl -pthread
|
||||
|
||||
# Put the proper machine-specific files first, so M-. on a machine
|
||||
# specific routine gets the one for the correct machine.
|
||||
|
@ -295,9 +299,11 @@ linux_low_h = $(srcdir)/linux-low.h
|
|||
|
||||
nto_low_h = $(srcdir)/nto-low.h
|
||||
|
||||
UST_CFLAGS = $(ustinc) -DCONFIG_UST_GDB_INTEGRATION
|
||||
|
||||
# Note, we only build the IPA if -fvisibility=hidden is supported in
|
||||
# the first place.
|
||||
IPAGENT_CFLAGS = $(CPPFLAGS) $(INTERNAL_CFLAGS) \
|
||||
IPAGENT_CFLAGS = $(CPPFLAGS) $(INTERNAL_CFLAGS) $(UST_CFLAGS) \
|
||||
-fPIC -DGDBSERVER -DIN_PROCESS_AGENT \
|
||||
-fvisibility=hidden
|
||||
|
||||
|
|
|
@ -154,6 +154,9 @@
|
|||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if UST is available */
|
||||
#undef HAVE_UST
|
||||
|
||||
/* Checking if errno must be defined */
|
||||
#undef MUST_DEFINE_ERRNO
|
||||
|
||||
|
|
104
gdb/gdbserver/configure
vendored
104
gdb/gdbserver/configure
vendored
|
@ -601,6 +601,8 @@ RDYNAMIC
|
|||
REPORT_BUGS_TEXI
|
||||
REPORT_BUGS_TO
|
||||
PKGVERSION
|
||||
ustinc
|
||||
ustlibs
|
||||
LIBOBJS
|
||||
INSTALL_DATA
|
||||
INSTALL_SCRIPT
|
||||
|
@ -668,6 +670,9 @@ SHELL'
|
|||
ac_subst_files=''
|
||||
ac_user_opts='
|
||||
enable_option_checking
|
||||
with_ust
|
||||
with_ust_include
|
||||
with_ust_lib
|
||||
with_pkgversion
|
||||
with_bugurl
|
||||
with_libthread_db
|
||||
|
@ -1298,6 +1303,11 @@ if test -n "$ac_init_help"; then
|
|||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||
--with-ust=PATH Specify prefix directory for the installed UST package
|
||||
Equivalent to --with-ust-include=PATH/include
|
||||
plus --with-ust-lib=PATH/lib
|
||||
--with-ust-include=PATH Specify directory for installed UST include files
|
||||
--with-ust-lib=PATH Specify the directory for the installed UST library
|
||||
--with-pkgversion=PKG Use PKG in the version string in place of "GDB"
|
||||
--with-bugurl=URL Direct users to URL to report a bug
|
||||
--with-libthread-db=PATH
|
||||
|
@ -1747,8 +1757,10 @@ $as_echo "$ac_res" >&6; }
|
|||
ac_fn_c_check_decl ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
|
||||
$as_echo_n "checking whether $2 is declared... " >&6; }
|
||||
as_decl_name=`echo $2|sed 's/ *(.*//'`
|
||||
as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
|
||||
$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
|
||||
if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
@ -1758,8 +1770,12 @@ $4
|
|||
int
|
||||
main ()
|
||||
{
|
||||
#ifndef $2
|
||||
(void) $2;
|
||||
#ifndef $as_decl_name
|
||||
#ifdef __cplusplus
|
||||
(void) $as_decl_use;
|
||||
#else
|
||||
(void) $as_decl_name;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
;
|
||||
|
@ -3818,6 +3834,86 @@ done
|
|||
|
||||
|
||||
|
||||
# Check for UST
|
||||
ustlibs=""
|
||||
ustinc=""
|
||||
|
||||
|
||||
# Check whether --with-ust was given.
|
||||
if test "${with_ust+set}" = set; then :
|
||||
withval=$with_ust;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-ust_include was given.
|
||||
if test "${with_ust_include+set}" = set; then :
|
||||
withval=$with_ust_include;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-ust_lib was given.
|
||||
if test "${with_ust_lib+set}" = set; then :
|
||||
withval=$with_ust_lib;
|
||||
fi
|
||||
|
||||
|
||||
case $with_ust in
|
||||
no)
|
||||
ustlibs=
|
||||
ustinc=
|
||||
;;
|
||||
"" | yes)
|
||||
ustlibs=" -lust "
|
||||
ustinc=""
|
||||
;;
|
||||
*)
|
||||
ustlibs="-L$with_ust/lib -lust"
|
||||
ustinc="-I$with_ust/include "
|
||||
;;
|
||||
esac
|
||||
if test "x$with_ust_include" != x; then
|
||||
ustinc="-I$with_ust_include "
|
||||
fi
|
||||
if test "x$with_ust_lib" != x; then
|
||||
ustlibs="-L$with_ust_lib -lust"
|
||||
fi
|
||||
|
||||
if test "x$with_ust" != "xno"; then
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ustinc"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ust" >&5
|
||||
$as_echo_n "checking for ust... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#define CONFIG_UST_GDB_INTEGRATION
|
||||
#include <ust/ust.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; };
|
||||
$as_echo "#define HAVE_UST 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }; ustlibs= ; ustinc=
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
fi
|
||||
|
||||
# Flags needed for UST
|
||||
|
||||
|
||||
|
||||
old_LIBS="$LIBS"
|
||||
LIBS="$LIBS -ldl"
|
||||
for ac_func in dladdr
|
||||
|
|
|
@ -45,6 +45,54 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
|
|||
AC_CHECK_FUNCS(pread pwrite pread64)
|
||||
AC_REPLACE_FUNCS(memmem)
|
||||
|
||||
# Check for UST
|
||||
ustlibs=""
|
||||
ustinc=""
|
||||
|
||||
AC_ARG_WITH(ust, [ --with-ust=PATH Specify prefix directory for the installed UST package
|
||||
Equivalent to --with-ust-include=PATH/include
|
||||
plus --with-ust-lib=PATH/lib])
|
||||
AC_ARG_WITH(ust_include, [ --with-ust-include=PATH Specify directory for installed UST include files])
|
||||
AC_ARG_WITH(ust_lib, [ --with-ust-lib=PATH Specify the directory for the installed UST library])
|
||||
|
||||
case $with_ust in
|
||||
no)
|
||||
ustlibs=
|
||||
ustinc=
|
||||
;;
|
||||
"" | yes)
|
||||
ustlibs=" -lust "
|
||||
ustinc=""
|
||||
;;
|
||||
*)
|
||||
ustlibs="-L$with_ust/lib -lust"
|
||||
ustinc="-I$with_ust/include "
|
||||
;;
|
||||
esac
|
||||
if test "x$with_ust_include" != x; then
|
||||
ustinc="-I$with_ust_include "
|
||||
fi
|
||||
if test "x$with_ust_lib" != x; then
|
||||
ustlibs="-L$with_ust_lib -lust"
|
||||
fi
|
||||
|
||||
if test "x$with_ust" != "xno"; then
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ustinc"
|
||||
AC_MSG_CHECKING([for ust])
|
||||
AC_TRY_COMPILE([
|
||||
#define CONFIG_UST_GDB_INTEGRATION
|
||||
#include <ust/ust.h>
|
||||
],[],
|
||||
[AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_UST, 1, [Define if UST is available])],
|
||||
[AC_MSG_RESULT([no]); ustlibs= ; ustinc= ])
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
fi
|
||||
|
||||
# Flags needed for UST
|
||||
AC_SUBST(ustlibs)
|
||||
AC_SUBST(ustinc)
|
||||
|
||||
dnl dladdr is glibc-specific. It is used by thread-db.c but only for
|
||||
dnl debugging messages. It lives in -ldl which is handled below so we don't
|
||||
dnl use AC_CHECK_LIB (or AC_SEARCH_LIBS) here. Instead we just temporarily
|
||||
|
|
|
@ -75,6 +75,95 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
|
|||
return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
#include <ust/processor.h>
|
||||
|
||||
/* "struct registers" is the UST object type holding the registers at
|
||||
the time of the static tracepoint marker call. This doesn't
|
||||
contain RIP, but we know what it must have been (the marker
|
||||
address). */
|
||||
|
||||
#define ST_REGENTRY(REG) \
|
||||
{ \
|
||||
offsetof (struct registers, REG), \
|
||||
sizeof (((struct registers *) NULL)->REG) \
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
int offset;
|
||||
int size;
|
||||
} x86_64_st_collect_regmap[] =
|
||||
{
|
||||
ST_REGENTRY(rax),
|
||||
ST_REGENTRY(rbx),
|
||||
ST_REGENTRY(rcx),
|
||||
ST_REGENTRY(rdx),
|
||||
ST_REGENTRY(rsi),
|
||||
ST_REGENTRY(rdi),
|
||||
ST_REGENTRY(rbp),
|
||||
ST_REGENTRY(rsp),
|
||||
ST_REGENTRY(r8),
|
||||
ST_REGENTRY(r9),
|
||||
ST_REGENTRY(r10),
|
||||
ST_REGENTRY(r11),
|
||||
ST_REGENTRY(r12),
|
||||
ST_REGENTRY(r13),
|
||||
ST_REGENTRY(r14),
|
||||
ST_REGENTRY(r15),
|
||||
{ -1, 0 },
|
||||
ST_REGENTRY(rflags),
|
||||
ST_REGENTRY(cs),
|
||||
ST_REGENTRY(ss),
|
||||
};
|
||||
|
||||
#define X86_64_NUM_ST_COLLECT_GREGS \
|
||||
(sizeof (x86_64_st_collect_regmap) / sizeof (x86_64_st_collect_regmap[0]))
|
||||
|
||||
/* GDB's RIP register number. */
|
||||
#define AMD64_RIP_REGNUM 16
|
||||
|
||||
void
|
||||
supply_static_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *buf,
|
||||
CORE_ADDR pc)
|
||||
{
|
||||
int i;
|
||||
unsigned long newpc = pc;
|
||||
|
||||
supply_register (regcache, AMD64_RIP_REGNUM, &newpc);
|
||||
|
||||
for (i = 0; i < X86_64_NUM_ST_COLLECT_GREGS; i++)
|
||||
if (x86_64_st_collect_regmap[i].offset != -1)
|
||||
{
|
||||
switch (x86_64_st_collect_regmap[i].size)
|
||||
{
|
||||
case 8:
|
||||
supply_register (regcache, i,
|
||||
((char *) buf)
|
||||
+ x86_64_st_collect_regmap[i].offset);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
unsigned long reg
|
||||
= * (short *) (((char *) buf)
|
||||
+ x86_64_st_collect_regmap[i].offset);
|
||||
reg &= 0xffff;
|
||||
supply_register (regcache, i, ®);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"unhandled register size: %d",
|
||||
x86_64_st_collect_regmap[i].size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
/* This is only needed because reg-i386-linux-lib.o references it. We
|
||||
may use it proper at some point. */
|
||||
const char *gdbserver_xmltarget;
|
||||
|
|
|
@ -110,6 +110,83 @@ gdb_agent_get_raw_reg (unsigned char *raw_regs, int regnum)
|
|||
return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
#include <ust/processor.h>
|
||||
|
||||
/* "struct registers" is the UST object type holding the registers at
|
||||
the time of the static tracepoint marker call. This doesn't
|
||||
contain EIP, but we know what it must have been (the marker
|
||||
address). */
|
||||
|
||||
#define ST_REGENTRY(REG) \
|
||||
{ \
|
||||
offsetof (struct registers, REG), \
|
||||
sizeof (((struct registers *) NULL)->REG) \
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
int offset;
|
||||
int size;
|
||||
} i386_st_collect_regmap[] =
|
||||
{
|
||||
ST_REGENTRY(eax),
|
||||
ST_REGENTRY(ecx),
|
||||
ST_REGENTRY(edx),
|
||||
ST_REGENTRY(ebx),
|
||||
ST_REGENTRY(esp),
|
||||
ST_REGENTRY(ebp),
|
||||
ST_REGENTRY(esi),
|
||||
ST_REGENTRY(edi),
|
||||
{ -1, 0 }, /* eip */
|
||||
ST_REGENTRY(eflags),
|
||||
ST_REGENTRY(cs),
|
||||
ST_REGENTRY(ss),
|
||||
};
|
||||
|
||||
#define i386_NUM_ST_COLLECT_GREGS \
|
||||
(sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
|
||||
|
||||
void
|
||||
supply_static_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *buf,
|
||||
CORE_ADDR pc)
|
||||
{
|
||||
int i;
|
||||
unsigned int newpc = pc;
|
||||
|
||||
supply_register (regcache, I386_EIP_REGNUM, &newpc);
|
||||
|
||||
for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
|
||||
if (i386_st_collect_regmap[i].offset != -1)
|
||||
{
|
||||
switch (i386_st_collect_regmap[i].size)
|
||||
{
|
||||
case 4:
|
||||
supply_register (regcache, i,
|
||||
((char *) buf)
|
||||
+ i386_st_collect_regmap[i].offset);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
unsigned long reg
|
||||
= * (short *) (((char *) buf)
|
||||
+ i386_st_collect_regmap[i].offset);
|
||||
reg &= 0xffff;
|
||||
supply_register (regcache, i, ®);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
internal_error ("unhandled register size: %d",
|
||||
i386_st_collect_regmap[i].size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
|
||||
/* This is only needed because reg-i386-linux-lib.o references it. We
|
||||
may use it proper at some point. */
|
||||
const char *gdbserver_xmltarget;
|
||||
|
|
|
@ -777,6 +777,17 @@ uninsert_breakpoints_at (CORE_ADDR pc)
|
|||
uninsert_raw_breakpoint (bp);
|
||||
}
|
||||
|
||||
void
|
||||
uninsert_all_breakpoints (void)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct raw_breakpoint *bp;
|
||||
|
||||
for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
|
||||
if (bp->inserted)
|
||||
uninsert_raw_breakpoint (bp);
|
||||
}
|
||||
|
||||
static void
|
||||
reinsert_raw_breakpoint (struct raw_breakpoint *bp)
|
||||
{
|
||||
|
@ -816,6 +827,17 @@ reinsert_breakpoints_at (CORE_ADDR pc)
|
|||
reinsert_raw_breakpoint (bp);
|
||||
}
|
||||
|
||||
void
|
||||
reinsert_all_breakpoints (void)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct raw_breakpoint *bp;
|
||||
|
||||
for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
|
||||
if (!bp->inserted)
|
||||
reinsert_raw_breakpoint (bp);
|
||||
}
|
||||
|
||||
void
|
||||
check_breakpoints (CORE_ADDR stop_pc)
|
||||
{
|
||||
|
|
|
@ -78,6 +78,17 @@ void reinsert_breakpoints_at (CORE_ADDR where);
|
|||
|
||||
void uninsert_breakpoints_at (CORE_ADDR where);
|
||||
|
||||
/* Reinsert all breakpoints of the current process (and change their
|
||||
status to inserted). */
|
||||
|
||||
void reinsert_all_breakpoints (void);
|
||||
|
||||
/* Uninsert all breakpoints of the current process (and change their
|
||||
status to uninserted). This still leaves the breakpoints in the
|
||||
table. */
|
||||
|
||||
void uninsert_all_breakpoints (void);
|
||||
|
||||
/* See if any breakpoint claims ownership of STOP_PC. Call the handler for
|
||||
the breakpoint, if found. */
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
|
||||
#if USE_WIN32API
|
||||
# define INVALID_DESCRIPTOR INVALID_SOCKET
|
||||
#else
|
||||
|
@ -371,6 +373,8 @@ fromhex (int a)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const char hexchars[] = "0123456789abcdef";
|
||||
|
||||
static int
|
||||
|
@ -394,6 +398,8 @@ ishex (int ch, int *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
|
||||
int
|
||||
unhexify (char *bin, const char *hex, int count)
|
||||
{
|
||||
|
@ -446,6 +452,8 @@ decode_address_to_semicolon (CORE_ADDR *addrp, const char *start)
|
|||
return end;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Convert number NIB to a hex digit. */
|
||||
|
||||
static int
|
||||
|
@ -457,6 +465,8 @@ tohex (int nib)
|
|||
return 'a' + nib - 10;
|
||||
}
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
|
||||
int
|
||||
hexify (char *hex, const char *bin, int count)
|
||||
{
|
||||
|
@ -600,6 +610,8 @@ try_rle (char *buf, int remaining, unsigned char *csum, char **p)
|
|||
return n + 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *
|
||||
unpack_varlen_hex (char *buff, /* packet to parse */
|
||||
ULONGEST *result)
|
||||
|
@ -617,6 +629,8 @@ unpack_varlen_hex (char *buff, /* packet to parse */
|
|||
return buff;
|
||||
}
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
|
||||
/* Write a PTID to BUF. Returns BUF+CHARACTERS_WRITTEN. */
|
||||
|
||||
char *
|
||||
|
@ -1126,6 +1140,8 @@ write_enn (char *buf)
|
|||
buf[3] = '\0';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
convert_int_to_ascii (const unsigned char *from, char *to, int n)
|
||||
{
|
||||
|
@ -1142,6 +1158,7 @@ convert_int_to_ascii (const unsigned char *from, char *to, int n)
|
|||
*to++ = 0;
|
||||
}
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
|
||||
void
|
||||
convert_ascii_to_int (const char *from, unsigned char *to, int n)
|
||||
|
@ -1841,3 +1858,5 @@ buffer_xml_printf (struct buffer *buffer, const char *format, ...)
|
|||
buffer_grow_str (buffer, prev);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1336,6 +1336,52 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
|||
return;
|
||||
}
|
||||
|
||||
if (strncmp ("qXfer:statictrace:read:", own_buf,
|
||||
sizeof ("qXfer:statictrace:read:") -1) == 0)
|
||||
{
|
||||
unsigned char *data;
|
||||
CORE_ADDR ofs;
|
||||
unsigned int len;
|
||||
char *annex;
|
||||
ULONGEST nbytes;
|
||||
|
||||
require_running (own_buf);
|
||||
|
||||
if (current_traceframe == -1)
|
||||
{
|
||||
write_enn (own_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reject any annex; grab the offset and length. */
|
||||
if (decode_xfer_read (own_buf + sizeof ("qXfer:statictrace:read:") -1,
|
||||
&annex, &ofs, &len) < 0
|
||||
|| annex[0] != '\0')
|
||||
{
|
||||
strcpy (own_buf, "E00");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read one extra byte, as an indicator of whether there is
|
||||
more. */
|
||||
if (len > PBUFSIZ - 2)
|
||||
len = PBUFSIZ - 2;
|
||||
data = malloc (len + 1);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (traceframe_read_sdata (current_traceframe, ofs,
|
||||
data, len + 1, &nbytes))
|
||||
write_enn (own_buf);
|
||||
else if (nbytes > len)
|
||||
*new_packet_len_p = write_qxfer_response (own_buf, data, len, 1);
|
||||
else
|
||||
*new_packet_len_p = write_qxfer_response (own_buf, data, nbytes, 0);
|
||||
|
||||
free (data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Protocol features query. */
|
||||
if (strncmp ("qSupported", own_buf, 10) == 0
|
||||
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
|
||||
|
@ -1433,6 +1479,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
|||
strcat (own_buf, ";DisconnectedTracing+");
|
||||
if (gdb_supports_qRelocInsn && target_supports_fast_tracepoints ())
|
||||
strcat (own_buf, ";FastTracepoints+");
|
||||
strcat (own_buf, ";StaticTracepoints+");
|
||||
strcat (own_buf, ";qXfer:statictrace:read+");
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -542,6 +542,10 @@ int fetch_traceframe_registers (int tfnum,
|
|||
struct regcache *regcache,
|
||||
int regnum);
|
||||
|
||||
int traceframe_read_sdata (int tfnum, ULONGEST offset,
|
||||
unsigned char *buf, ULONGEST length,
|
||||
ULONGEST *nbytes);
|
||||
|
||||
/* If a thread is determined to be collecting a fast tracepoint, this
|
||||
structure holds the collect status. */
|
||||
|
||||
|
@ -569,6 +573,9 @@ int handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc);
|
|||
void initialize_low_tracepoint (void);
|
||||
void supply_fast_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *regs);
|
||||
void supply_static_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *regs,
|
||||
CORE_ADDR pc);
|
||||
#else
|
||||
void stop_tracing (void);
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -75,6 +75,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
|
|||
int enabled = 1;
|
||||
int tracepoint = 0;
|
||||
struct cleanup *back_to;
|
||||
enum bptype type_wanted;
|
||||
|
||||
enum opt
|
||||
{
|
||||
|
@ -151,9 +152,21 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
|
|||
|
||||
back_to = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
|
||||
mi_can_breakpoint_notify = 1;
|
||||
|
||||
/* Note that to request a fast tracepoint, the client uses the
|
||||
"hardware" flag, although there's nothing of hardware related to
|
||||
fast tracepoints -- one can implement slow tracepoints with
|
||||
hardware breakpoints, but fast tracepoints are always software.
|
||||
"fast" is a misnomer, actually, "jump" would be more appropriate.
|
||||
A simulator or an emulator could conceivably implement fast
|
||||
regular non-jump based tracepoints. */
|
||||
type_wanted = (tracepoint
|
||||
? (hardware ? bp_fast_tracepoint : bp_tracepoint)
|
||||
: (hardware ? bp_hardware_breakpoint : bp_breakpoint));
|
||||
|
||||
create_breakpoint (get_current_arch (), address, condition, thread,
|
||||
0 /* condition and thread are valid. */,
|
||||
temp_p, hardware, tracepoint,
|
||||
temp_p, type_wanted,
|
||||
ignore_count,
|
||||
pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
|
||||
NULL, 0, enabled);
|
||||
|
|
|
@ -592,7 +592,7 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
|
|||
create_breakpoint (python_gdbarch,
|
||||
spec, NULL, -1,
|
||||
0,
|
||||
0, 0, 0,
|
||||
0, bp_breakpoint,
|
||||
0,
|
||||
AUTO_BOOLEAN_TRUE,
|
||||
NULL, 0, 1);
|
||||
|
|
156
gdb/remote.c
156
gdb/remote.c
|
@ -322,6 +322,9 @@ struct remote_state
|
|||
/* True if the stub reports support for fast tracepoints. */
|
||||
int fast_tracepoints;
|
||||
|
||||
/* True if the stub reports support for static tracepoints. */
|
||||
int static_tracepoints;
|
||||
|
||||
/* True if the stub can continue running a trace while GDB is
|
||||
disconnected. */
|
||||
int disconnected_tracing;
|
||||
|
@ -1198,6 +1201,7 @@ enum {
|
|||
PACKET_qXfer_spu_write,
|
||||
PACKET_qXfer_osdata,
|
||||
PACKET_qXfer_threads,
|
||||
PACKET_qXfer_statictrace_read,
|
||||
PACKET_qGetTIBAddr,
|
||||
PACKET_qGetTLSAddr,
|
||||
PACKET_qSupported,
|
||||
|
@ -1212,6 +1216,7 @@ enum {
|
|||
PACKET_qAttached,
|
||||
PACKET_ConditionalTracepoints,
|
||||
PACKET_FastTracepoints,
|
||||
PACKET_StaticTracepoints,
|
||||
PACKET_bc,
|
||||
PACKET_bs,
|
||||
PACKET_TracepointSource,
|
||||
|
@ -2772,6 +2777,98 @@ remote_threads_extra_info (struct thread_info *tp)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
remote_static_tracepoint_marker_at (CORE_ADDR addr,
|
||||
struct static_tracepoint_marker *marker)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *p = rs->buf;
|
||||
|
||||
sprintf (p, "qTSTMat:");
|
||||
p += strlen (p);
|
||||
p += hexnumstr (p, addr);
|
||||
putpkt (rs->buf);
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
|
||||
if (*p == 'E')
|
||||
error (_("Remote failure reply: %s"), p);
|
||||
|
||||
if (*p++ == 'm')
|
||||
{
|
||||
parse_static_tracepoint_marker_definition (p, &p, marker);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_current_marker (void *arg)
|
||||
{
|
||||
struct static_tracepoint_marker **marker_p = arg;
|
||||
|
||||
if (*marker_p != NULL)
|
||||
{
|
||||
release_static_tracepoint_marker (*marker_p);
|
||||
xfree (*marker_p);
|
||||
}
|
||||
else
|
||||
*marker_p = NULL;
|
||||
}
|
||||
|
||||
static VEC(static_tracepoint_marker_p) *
|
||||
remote_static_tracepoint_markers_by_strid (const char *strid)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
VEC(static_tracepoint_marker_p) *markers = NULL;
|
||||
struct static_tracepoint_marker *marker = NULL;
|
||||
struct cleanup *old_chain;
|
||||
char *p;
|
||||
|
||||
/* Ask for a first packet of static tracepoint marker
|
||||
definition. */
|
||||
putpkt ("qTfSTM");
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
if (*p == 'E')
|
||||
error (_("Remote failure reply: %s"), p);
|
||||
|
||||
old_chain = make_cleanup (free_current_marker, &marker);
|
||||
|
||||
while (*p++ == 'm')
|
||||
{
|
||||
if (marker == NULL)
|
||||
marker = XCNEW (struct static_tracepoint_marker);
|
||||
|
||||
do
|
||||
{
|
||||
parse_static_tracepoint_marker_definition (p, &p, marker);
|
||||
|
||||
if (strid == NULL || strcmp (strid, marker->str_id) == 0)
|
||||
{
|
||||
VEC_safe_push (static_tracepoint_marker_p,
|
||||
markers, marker);
|
||||
marker = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
release_static_tracepoint_marker (marker);
|
||||
memset (marker, 0, sizeof (*marker));
|
||||
}
|
||||
}
|
||||
while (*p++ == ','); /* comma-separated list */
|
||||
/* Ask for another packet of static tracepoint definition. */
|
||||
putpkt ("qTsSTM");
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
}
|
||||
|
||||
do_cleanups (old_chain);
|
||||
return markers;
|
||||
}
|
||||
|
||||
|
||||
/* Implement the to_get_ada_task_ptid function for the remote targets. */
|
||||
|
||||
static ptid_t
|
||||
|
@ -3551,6 +3648,16 @@ remote_fast_tracepoint_feature (const struct protocol_feature *feature,
|
|||
rs->fast_tracepoints = (support == PACKET_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_static_tracepoint_feature (const struct protocol_feature *feature,
|
||||
enum packet_support support,
|
||||
const char *value)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
|
||||
rs->static_tracepoints = (support == PACKET_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_disconnected_tracing_feature (const struct protocol_feature *feature,
|
||||
enum packet_support support,
|
||||
|
@ -3593,6 +3700,8 @@ static struct protocol_feature remote_protocol_features[] = {
|
|||
PACKET_ConditionalTracepoints },
|
||||
{ "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
|
||||
PACKET_FastTracepoints },
|
||||
{ "StaticTracepoints", PACKET_DISABLE, remote_static_tracepoint_feature,
|
||||
PACKET_StaticTracepoints },
|
||||
{ "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature,
|
||||
-1 },
|
||||
{ "ReverseContinue", PACKET_DISABLE, remote_supported_packet,
|
||||
|
@ -8046,6 +8155,16 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
|
|||
[PACKET_qXfer_siginfo_write]);
|
||||
}
|
||||
|
||||
if (object == TARGET_OBJECT_STATIC_TRACE_DATA)
|
||||
{
|
||||
if (readbuf)
|
||||
return remote_read_qxfer (ops, "statictrace", annex, readbuf, offset, len,
|
||||
&remote_protocol_packets
|
||||
[PACKET_qXfer_statictrace_read]);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Only handle flash writes. */
|
||||
if (writebuf != NULL)
|
||||
{
|
||||
|
@ -9478,6 +9597,14 @@ remote_supports_fast_tracepoints (void)
|
|||
return rs->fast_tracepoints;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_supports_static_tracepoints (void)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
|
||||
return rs->static_tracepoints;
|
||||
}
|
||||
|
||||
static void
|
||||
remote_trace_init (void)
|
||||
{
|
||||
|
@ -9606,6 +9733,25 @@ remote_download_tracepoint (struct breakpoint *t)
|
|||
give up on the trace run. */
|
||||
warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
|
||||
}
|
||||
else if (t->type == bp_static_tracepoint)
|
||||
{
|
||||
/* Only test for support at download time; we may not know
|
||||
target capabilities at definition time. */
|
||||
if (remote_supports_static_tracepoints ())
|
||||
{
|
||||
struct static_tracepoint_marker marker;
|
||||
|
||||
if (target_static_tracepoint_marker_at (tpaddr, &marker))
|
||||
strcat (buf, ":S");
|
||||
else
|
||||
error ("Static tracepoint not valid during download");
|
||||
}
|
||||
else
|
||||
/* Fast tracepoints are functionally identical to regular
|
||||
tracepoints, so don't take lack of support as a reason
|
||||
to give up on the trace run. */
|
||||
error (_("Target does not support static tracepoints"));
|
||||
}
|
||||
/* If the tracepoint has a conditional, make it into an agent
|
||||
expression and append to the definition. */
|
||||
if (loc->cond)
|
||||
|
@ -10101,6 +10247,10 @@ Specify the serial device it is connected to\n\
|
|||
remote_ops.to_verify_memory = remote_verify_memory;
|
||||
remote_ops.to_get_tib_address = remote_get_tib_address;
|
||||
remote_ops.to_set_permissions = remote_set_permissions;
|
||||
remote_ops.to_static_tracepoint_marker_at
|
||||
= remote_static_tracepoint_marker_at;
|
||||
remote_ops.to_static_tracepoint_markers_by_strid
|
||||
= remote_static_tracepoint_markers_by_strid;
|
||||
}
|
||||
|
||||
/* Set up the extended remote vector by making a copy of the standard
|
||||
|
@ -10579,6 +10729,12 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
|
|||
add_packet_config_cmd (&remote_protocol_packets[PACKET_QAllow],
|
||||
"QAllow", "allow", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_StaticTracepoints],
|
||||
"StaticTracepoints", "static-tracepoints", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_statictrace_read],
|
||||
"qXfer:statictrace:read", "read-sdata-object", 0);
|
||||
|
||||
/* Keep the old ``set remote Z-packet ...'' working. Each individual
|
||||
Z sub-packet has its own set and show commands, but users may
|
||||
have sets to this variable in their .gdbinit files (or in their
|
||||
|
|
|
@ -679,6 +679,8 @@ update_current_target (void)
|
|||
INHERIT (to_set_circular_trace_buffer, t);
|
||||
INHERIT (to_get_tib_address, t);
|
||||
INHERIT (to_set_permissions, t);
|
||||
INHERIT (to_static_tracepoint_marker_at, t);
|
||||
INHERIT (to_static_tracepoint_markers_by_strid, t);
|
||||
INHERIT (to_magic, t);
|
||||
/* Do not inherit to_memory_map. */
|
||||
/* Do not inherit to_flash_erase. */
|
||||
|
@ -878,6 +880,12 @@ update_current_target (void)
|
|||
de_fault (to_set_permissions,
|
||||
(void (*) (void))
|
||||
target_ignore);
|
||||
de_fault (to_static_tracepoint_marker_at,
|
||||
(int (*) (CORE_ADDR, struct static_tracepoint_marker *))
|
||||
return_zero);
|
||||
de_fault (to_static_tracepoint_markers_by_strid,
|
||||
(VEC(static_tracepoint_marker_p) * (*) (const char *))
|
||||
tcomplain);
|
||||
#undef de_fault
|
||||
|
||||
/* Finally, position the target-stack beneath the squashed
|
||||
|
|
22
gdb/target.h
22
gdb/target.h
|
@ -35,6 +35,7 @@ struct trace_state_variable;
|
|||
struct trace_status;
|
||||
struct uploaded_tsv;
|
||||
struct uploaded_tp;
|
||||
struct static_tracepoint_marker;
|
||||
|
||||
/* This include file defines the interface between the main part
|
||||
of the debugger, and the part which is target-specific, or
|
||||
|
@ -261,6 +262,8 @@ enum target_object
|
|||
TARGET_OBJECT_SIGNAL_INFO,
|
||||
/* The list of threads that are being debugged. */
|
||||
TARGET_OBJECT_THREADS,
|
||||
/* Collected static trace data. */
|
||||
TARGET_OBJECT_STATIC_TRACE_DATA,
|
||||
/* Possible future objects: TARGET_OBJECT_FILE, ... */
|
||||
};
|
||||
|
||||
|
@ -276,6 +279,9 @@ enum trace_find_type
|
|||
tfind_outside,
|
||||
};
|
||||
|
||||
typedef struct static_tracepoint_marker *static_tracepoint_marker_p;
|
||||
DEF_VEC_P(static_tracepoint_marker_p);
|
||||
|
||||
/* Request that OPS transfer up to LEN 8-bit bytes of the target's
|
||||
OBJECT. The OFFSET, for a seekable object, specifies the
|
||||
starting point. The ANNEX can be used to provide additional
|
||||
|
@ -689,6 +695,16 @@ struct target_ops
|
|||
/* Send the new settings of write permission variables. */
|
||||
void (*to_set_permissions) (void);
|
||||
|
||||
/* Look for a static tracepoint marker at ADDR, and fill in MARKER
|
||||
with its details. Return 1 on success, 0 on failure. */
|
||||
int (*to_static_tracepoint_marker_at) (CORE_ADDR,
|
||||
struct static_tracepoint_marker *marker);
|
||||
|
||||
/* Return a vector of all tracepoints markers string id ID, or all
|
||||
markers if ID is NULL. */
|
||||
VEC(static_tracepoint_marker_p) *(*to_static_tracepoint_markers_by_strid)
|
||||
(const char *id);
|
||||
|
||||
int to_magic;
|
||||
/* Need sub-structure for target machine related rather than comm related?
|
||||
*/
|
||||
|
@ -1384,6 +1400,12 @@ extern int target_search_memory (CORE_ADDR start_addr,
|
|||
#define target_set_permissions() \
|
||||
(*current_target.to_set_permissions) ()
|
||||
|
||||
#define target_static_tracepoint_marker_at(addr, marker) \
|
||||
(*current_target.to_static_tracepoint_marker_at) (addr, marker)
|
||||
|
||||
#define target_static_tracepoint_markers_by_strid(marker_id) \
|
||||
(*current_target.to_static_tracepoint_markers_by_strid) (marker_id)
|
||||
|
||||
/* Command logging facility. */
|
||||
|
||||
#define target_log_command(p) \
|
||||
|
|
303
gdb/tracepoint.c
303
gdb/tracepoint.c
|
@ -47,7 +47,7 @@
|
|||
#include "stack.h"
|
||||
#include "gdbcore.h"
|
||||
#include "remote.h"
|
||||
|
||||
#include "source.h"
|
||||
#include "ax.h"
|
||||
#include "ax-gdb.h"
|
||||
|
||||
|
@ -622,9 +622,10 @@ validate_actionline (char **line, struct breakpoint *t)
|
|||
|
||||
if (*p == '$') /* look for special pseudo-symbols */
|
||||
{
|
||||
if ((0 == strncasecmp ("reg", p + 1, 3)) ||
|
||||
(0 == strncasecmp ("arg", p + 1, 3)) ||
|
||||
(0 == strncasecmp ("loc", p + 1, 3)))
|
||||
if (0 == strncasecmp ("reg", p + 1, 3)
|
||||
|| 0 == strncasecmp ("arg", p + 1, 3)
|
||||
|| 0 == strncasecmp ("loc", p + 1, 3)
|
||||
|| 0 == strncasecmp ("_sdata", p + 1, 6))
|
||||
{
|
||||
p = strchr (p, ',');
|
||||
continue;
|
||||
|
@ -747,6 +748,9 @@ struct collection_list
|
|||
long next_aexpr_elt;
|
||||
struct agent_expr **aexpr_list;
|
||||
|
||||
/* True is the user requested a collection of "$_sdata", "static
|
||||
tracepoint data". */
|
||||
int strace_data;
|
||||
}
|
||||
tracepoint_list, stepping_list;
|
||||
|
||||
|
@ -1086,6 +1090,14 @@ add_local_symbols (struct collection_list *collect,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_static_trace_data (struct collection_list *collection)
|
||||
{
|
||||
if (info_verbose)
|
||||
printf_filtered ("collect static trace data\n");
|
||||
collection->strace_data = 1;
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
static void
|
||||
clear_collection_list (struct collection_list *list)
|
||||
|
@ -1100,6 +1112,7 @@ clear_collection_list (struct collection_list *list)
|
|||
}
|
||||
list->next_aexpr_elt = 0;
|
||||
memset (list->regs_mask, 0, sizeof (list->regs_mask));
|
||||
list->strace_data = 0;
|
||||
}
|
||||
|
||||
/* reduce a collection list to string form (for gdb protocol) */
|
||||
|
@ -1114,9 +1127,19 @@ stringify_collection_list (struct collection_list *list, char *string)
|
|||
char *end;
|
||||
long i;
|
||||
|
||||
count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
|
||||
count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
|
||||
str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
|
||||
|
||||
if (list->strace_data)
|
||||
{
|
||||
if (info_verbose)
|
||||
printf_filtered ("\nCollecting static trace data\n");
|
||||
end = temp_buf;
|
||||
*end++ = 'L';
|
||||
(*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
|
||||
ndx++;
|
||||
}
|
||||
|
||||
for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
|
||||
if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
|
||||
break;
|
||||
|
@ -1276,6 +1299,11 @@ encode_actions_1 (struct command_line *action,
|
|||
'L');
|
||||
action_exp = strchr (action_exp, ','); /* more? */
|
||||
}
|
||||
else if (0 == strncasecmp ("$_sdata", action_exp, 7))
|
||||
{
|
||||
add_static_trace_data (collect);
|
||||
action_exp = strchr (action_exp, ','); /* more? */
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long addr, len;
|
||||
|
@ -3476,6 +3504,11 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
|
|||
p++;
|
||||
p = unpack_varlen_hex (p, &orig_size);
|
||||
}
|
||||
else if (*p == 'S')
|
||||
{
|
||||
type = bp_static_tracepoint;
|
||||
p++;
|
||||
}
|
||||
else if (*p == 'X')
|
||||
{
|
||||
p++;
|
||||
|
@ -4075,12 +4108,266 @@ init_tfile_ops (void)
|
|||
tfile_ops.to_magic = OPS_MAGIC;
|
||||
}
|
||||
|
||||
/* Given a line of text defining a static tracepoint marker, parse it
|
||||
into a "static tracepoint marker" object. Throws an error is
|
||||
parsing fails. If PP is non-null, it points to one past the end of
|
||||
the parsed marker definition. */
|
||||
|
||||
void
|
||||
parse_static_tracepoint_marker_definition (char *line, char **pp,
|
||||
struct static_tracepoint_marker *marker)
|
||||
{
|
||||
char *p, *endp;
|
||||
ULONGEST addr;
|
||||
int end;
|
||||
|
||||
p = line;
|
||||
p = unpack_varlen_hex (p, &addr);
|
||||
p++; /* skip a colon */
|
||||
|
||||
marker->gdbarch = target_gdbarch;
|
||||
marker->address = (CORE_ADDR) addr;
|
||||
|
||||
endp = strchr (p, ':');
|
||||
if (endp == NULL)
|
||||
error ("bad marker definition: %s", line);
|
||||
|
||||
marker->str_id = xmalloc (endp - p + 1);
|
||||
end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2);
|
||||
marker->str_id[end] = '\0';
|
||||
|
||||
p += 2 * end;
|
||||
p++; /* skip a colon */
|
||||
|
||||
marker->extra = xmalloc (strlen (p) + 1);
|
||||
end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2);
|
||||
marker->extra[end] = '\0';
|
||||
|
||||
if (pp)
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
/* Release a static tracepoint marker's contents. Note that the
|
||||
object itself isn't released here. There objects are usually on
|
||||
the stack. */
|
||||
|
||||
void
|
||||
release_static_tracepoint_marker (struct static_tracepoint_marker *marker)
|
||||
{
|
||||
xfree (marker->str_id);
|
||||
marker->str_id = NULL;
|
||||
}
|
||||
|
||||
/* Print MARKER to gdb_stdout. */
|
||||
|
||||
static void
|
||||
print_one_static_tracepoint_marker (int count,
|
||||
struct static_tracepoint_marker *marker)
|
||||
{
|
||||
struct command_line *l;
|
||||
struct symbol *sym;
|
||||
|
||||
char wrap_indent[80];
|
||||
char extra_field_indent[80];
|
||||
struct ui_stream *stb = ui_out_stream_new (uiout);
|
||||
struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
|
||||
struct cleanup *bkpt_chain;
|
||||
VEC(breakpoint_p) *tracepoints;
|
||||
|
||||
struct symtab_and_line sal;
|
||||
|
||||
init_sal (&sal);
|
||||
|
||||
sal.pc = marker->address;
|
||||
|
||||
tracepoints = static_tracepoints_here (marker->address);
|
||||
|
||||
bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker");
|
||||
|
||||
/* A counter field to help readability. This is not a stable
|
||||
identifier! */
|
||||
ui_out_field_int (uiout, "count", count);
|
||||
|
||||
ui_out_field_string (uiout, "marker-id", marker->str_id);
|
||||
|
||||
ui_out_field_fmt (uiout, "enabled", "%c",
|
||||
!VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
|
||||
ui_out_spaces (uiout, 2);
|
||||
|
||||
strcpy (wrap_indent, " ");
|
||||
|
||||
if (gdbarch_addr_bit (marker->gdbarch) <= 32)
|
||||
strcat (wrap_indent, " ");
|
||||
else
|
||||
strcat (wrap_indent, " ");
|
||||
|
||||
strcpy (extra_field_indent, " ");
|
||||
|
||||
ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address);
|
||||
|
||||
sal = find_pc_line (marker->address, 0);
|
||||
sym = find_pc_sect_function (marker->address, NULL);
|
||||
if (sym)
|
||||
{
|
||||
ui_out_text (uiout, "in ");
|
||||
ui_out_field_string (uiout, "func",
|
||||
SYMBOL_PRINT_NAME (sym));
|
||||
ui_out_wrap_hint (uiout, wrap_indent);
|
||||
ui_out_text (uiout, " at ");
|
||||
}
|
||||
else
|
||||
ui_out_field_skip (uiout, "func");
|
||||
|
||||
if (sal.symtab != NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
ui_out_field_skip (uiout, "fullname");
|
||||
|
||||
ui_out_field_int (uiout, "line", sal.line);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui_out_field_skip (uiout, "fullname");
|
||||
ui_out_field_skip (uiout, "line");
|
||||
}
|
||||
|
||||
ui_out_text (uiout, "\n");
|
||||
ui_out_text (uiout, extra_field_indent);
|
||||
ui_out_text (uiout, _("Data: \""));
|
||||
ui_out_field_string (uiout, "extra-data", marker->extra);
|
||||
ui_out_text (uiout, "\"\n");
|
||||
|
||||
if (!VEC_empty (breakpoint_p, tracepoints))
|
||||
{
|
||||
struct cleanup *cleanup_chain;
|
||||
int ix;
|
||||
struct breakpoint *b;
|
||||
|
||||
cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout,
|
||||
"tracepoints-at");
|
||||
|
||||
ui_out_text (uiout, extra_field_indent);
|
||||
ui_out_text (uiout, _("Probed by static tracepoints: "));
|
||||
for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
|
||||
{
|
||||
if (ix > 0)
|
||||
ui_out_text (uiout, ", ");
|
||||
ui_out_text (uiout, "#");
|
||||
ui_out_field_int (uiout, "tracepoint-id", b->number);
|
||||
}
|
||||
|
||||
do_cleanups (cleanup_chain);
|
||||
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
ui_out_field_int (uiout, "number-of-tracepoints",
|
||||
VEC_length(breakpoint_p, tracepoints));
|
||||
else
|
||||
ui_out_text (uiout, "\n");
|
||||
}
|
||||
VEC_free (breakpoint_p, tracepoints);
|
||||
|
||||
do_cleanups (bkpt_chain);
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
|
||||
static void
|
||||
info_static_tracepoint_markers_command (char *arg, int from_tty)
|
||||
{
|
||||
VEC(static_tracepoint_marker_p) *markers;
|
||||
struct cleanup *old_chain;
|
||||
struct static_tracepoint_marker *marker;
|
||||
int i;
|
||||
|
||||
old_chain
|
||||
= make_cleanup_ui_out_table_begin_end (uiout, 5, -1,
|
||||
"StaticTracepointMarkersTable");
|
||||
|
||||
ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt");
|
||||
|
||||
ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID");
|
||||
|
||||
ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");
|
||||
if (gdbarch_addr_bit (target_gdbarch) <= 32)
|
||||
ui_out_table_header (uiout, 10, ui_left, "addr", "Address");
|
||||
else
|
||||
ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
|
||||
ui_out_table_header (uiout, 40, ui_noalign, "what", "What");
|
||||
|
||||
ui_out_table_body (uiout);
|
||||
|
||||
markers = target_static_tracepoint_markers_by_strid (NULL);
|
||||
make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers);
|
||||
|
||||
for (i = 0;
|
||||
VEC_iterate (static_tracepoint_marker_p,
|
||||
markers, i, marker);
|
||||
i++)
|
||||
{
|
||||
print_one_static_tracepoint_marker (i + 1, marker);
|
||||
release_static_tracepoint_marker (marker);
|
||||
}
|
||||
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
|
||||
/* The $_sdata convenience variable is a bit special. We don't know
|
||||
for sure type of the value until we actually have a chance to fetch
|
||||
the data --- the size of the object depends on what has been
|
||||
collected. We solve this by making $_sdata be an internalvar that
|
||||
creates a new value on access. */
|
||||
|
||||
/* Return a new value with the correct type for the sdata object of
|
||||
the current trace frame. Return a void value if there's no object
|
||||
available. */
|
||||
|
||||
static struct value *
|
||||
sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
|
||||
{
|
||||
LONGEST size;
|
||||
gdb_byte *buf;
|
||||
|
||||
/* We need to read the whole object before we know its size. */
|
||||
size = target_read_alloc (¤t_target,
|
||||
TARGET_OBJECT_STATIC_TRACE_DATA,
|
||||
NULL, &buf);
|
||||
if (size >= 0)
|
||||
{
|
||||
struct value *v;
|
||||
struct type *type;
|
||||
|
||||
type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
|
||||
size);
|
||||
v = allocate_value (type);
|
||||
memcpy (value_contents_raw (v), buf, size);
|
||||
xfree (buf);
|
||||
return v;
|
||||
}
|
||||
else
|
||||
return allocate_value (builtin_type (gdbarch)->builtin_void);
|
||||
}
|
||||
|
||||
/* module initialization */
|
||||
void
|
||||
_initialize_tracepoint (void)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
|
||||
/* Explicitly create without lookup, since that tries to create a
|
||||
value with a void typed value, and when we get here, gdbarch
|
||||
isn't initialized yet. At this point, we're quite sure there
|
||||
isn't another convenience variable of the same name. */
|
||||
create_internalvar_type_lazy ("_sdata", sdata_make_value);
|
||||
|
||||
traceframe_number = -1;
|
||||
tracepoint_number = -1;
|
||||
|
||||
|
@ -4141,6 +4428,11 @@ If no arguments are supplied, delete all variables."), &deletelist);
|
|||
|
||||
add_info ("tvariables", tvariables_info, _("\
|
||||
Status of trace state variables and their values.\n\
|
||||
"));
|
||||
|
||||
add_info ("static-tracepoint-markers",
|
||||
info_static_tracepoint_markers_command, _("\
|
||||
List target static tracepoints markers.\n\
|
||||
"));
|
||||
|
||||
add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\
|
||||
|
@ -4223,6 +4515,7 @@ Also accepts the following special arguments:\n\
|
|||
$regs -- all registers.\n\
|
||||
$args -- all function arguments.\n\
|
||||
$locals -- all variables local to the block/function scope.\n\
|
||||
$_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\
|
||||
Note: this command can only be used in a tracepoint \"actions\" list."));
|
||||
|
||||
add_com ("teval", class_trace, teval_pseudocommand, _("\
|
||||
|
|
|
@ -166,6 +166,25 @@ struct uploaded_tsv
|
|||
struct uploaded_tsv *next;
|
||||
};
|
||||
|
||||
/* Struct recording info about a target static tracepoint marker. */
|
||||
|
||||
struct static_tracepoint_marker
|
||||
{
|
||||
struct gdbarch *gdbarch;
|
||||
CORE_ADDR address;
|
||||
|
||||
/* The string ID of the marker. */
|
||||
char *str_id;
|
||||
|
||||
/* Extra target reported info associated with the marker. */
|
||||
char *extra;
|
||||
};
|
||||
|
||||
extern void parse_static_tracepoint_marker_definition
|
||||
(char *line, char **pp,
|
||||
struct static_tracepoint_marker *marker);
|
||||
extern void release_static_tracepoint_marker (struct static_tracepoint_marker *);
|
||||
|
||||
/* A hook used to notify the UI of tracepoint operations. */
|
||||
|
||||
extern void (*deprecated_trace_find_hook) (char *arg, int from_tty);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue