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:
Pedro Alves 2010-07-01 10:36:12 +00:00
parent 76fa04a48e
commit 0fb4aa4bfc
26 changed files with 3149 additions and 69 deletions

View file

@ -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

View file

@ -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,

View file

@ -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 = &not_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\

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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, &reg);
}
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;

View file

@ -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, &reg);
}
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;

View file

@ -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)
{

View file

@ -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. */

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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) \

View file

@ -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 (&current_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, _("\

View file

@ -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);