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

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