aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/tracepoint.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>2011-11-20 23:59:49 +0000
committerStan Shebs <shebs@codesourcery.com>2011-11-20 23:59:49 +0000
commitf196051f5ee7f3aa3f417611a488ba773878a429 (patch)
tree25de238e78d9db1ad631611a10bcfd298b472a49 /gdb/gdbserver/tracepoint.c
parent9866a1803a670e48d8fedf0e33d0eb5141192318 (diff)
downloadgdb-f196051f5ee7f3aa3f417611a488ba773878a429.zip
gdb-f196051f5ee7f3aa3f417611a488ba773878a429.tar.gz
gdb-f196051f5ee7f3aa3f417611a488ba773878a429.tar.bz2
* NEWS: Mention tracepoint additions.
* breakpoint.h (struct tracepoint): New field traceframe_usage. * breakpoint.c (print_one_breakpoint_location): Identify tracepoints as such when reporting hit counts, report trace buffer usage. (create_tracepoint_from_upload): Copy status info. * tracepoint.h (struct trace_status): Rename error_desc to stop_desc, add fields user_name, notes, start_time, stop_time. (struct uploaded_tp): Add fields hit_count, traceframe_usage. * tracepoint.c (trace_user): New global. (trace_notes): New global. (trace_stop_notes): New global. (start_tracing): Add argument and trace note handling. (stop_tracing): Ditto. (trace_start_command): Add notes argument. (trace_stop_command): Ditto. (trace_status_command): Report additional status info. (trace_status_mi): Similarly. (trace_save): Update, record tracepoint status. (set_disconnected_tracing): Call target method directly. (send_disconnected_tracing_value): Remove. (set_trace_user): New function. (set_trace_notes): New function. (set_trace_stop_notes): New function. (parse_trace_status): Handle additional status. (parse_tracepoint_status): New function. (parse_tracepoint_definition): Call it. (tfile_get_tracepoint_status): New function. (init_tfile_ops): Use it. (_initialize_tracepoint): Add new setshows. * target.h (struct target_ops): New methods to_get_tracepoint_status and to_set_trace_notes. (target_get_tracepoint_status): New macro. (target_set_trace_notes): New macro. * target.c (update_current_target): Add new methods. * remote.c (remote_get_tracepoint_status): New function. (remote_set_trace_notes): New function. (init_remote_ops): Add them. * mi/mi-main.c (mi_cmd_trace_start): Add argument to call. (mi_cmd_trace_stop): Ditto. * tracepoint.c (struct tracepoint): New field traceframe_usage. (tracing_start_time): New global. (tracing_stop_time): New global. (tracing_user_name): New global. (tracing_notes): New global. (tracing_stop_note): New global. (cmd_qtstart): Set traceframe_usage, start_time. (stop_tracing): Set stop_time. (cmd_qtstatus): Report additional status. (cmd_qtp): New function. (handle_tracepoint_query): Call it. (cmd_qtnotes): New function. (handle_tracepoint_general_set): Call it. (get_timestamp): Rename from tsv_get_timestamp. * gdb.texinfo (Starting and Stopping Trace Experiments): Document note-related options and variables. (Tracepoint Packets): Document packet changes. * gdb.trace/tstatus.exp: New. * gdb.trace/actions.c: Include string.h.
Diffstat (limited to 'gdb/gdbserver/tracepoint.c')
-rw-r--r--gdb/gdbserver/tracepoint.c169
1 files changed, 164 insertions, 5 deletions
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index b00df05..e6a5bbc 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -632,6 +632,9 @@ struct tracepoint
Note that while-stepping steps are not counted as "hits". */
long hit_count;
+ /* Cached sum of the sizes of traceframes created by this point. */
+ long traceframe_usage;
+
CORE_ADDR compiled_cond;
/* Link to the next tracepoint in the list. */
@@ -1144,6 +1147,27 @@ static const char *tracing_stop_reason = "tnotrun";
static int tracing_stop_tpnum;
+/* 64-bit timestamps for the trace run's start and finish, expressed
+ in microseconds from the Unix epoch. */
+
+LONGEST tracing_start_time;
+LONGEST tracing_stop_time;
+
+/* The (optional) user-supplied name of the user that started the run.
+ This is an arbitrary string, and may be NULL. */
+
+char *tracing_user_name;
+
+/* Optional user-supplied text describing the run. This is
+ an arbitrary string, and may be NULL. */
+
+char *tracing_notes;
+
+/* Optional user-supplied text explaining a tstop command. This is an
+ arbitrary string, and may be NULL. */
+
+char *tracing_stop_note;
+
#endif
/* Functions local to this file. */
@@ -1266,6 +1290,8 @@ static void download_tracepoint (struct tracepoint *);
static int install_fast_tracepoint (struct tracepoint *, char *errbuf);
#endif
+static LONGEST get_timestamp (void);
+
#if defined(__GNUC__)
# define memory_barrier() asm volatile ("" : : : "memory")
#else
@@ -3027,6 +3053,7 @@ cmd_qtstart (char *packet)
{
/* Ensure all the hit counts start at zero. */
tpoint->hit_count = 0;
+ tpoint->traceframe_usage = 0;
if (tpoint->type == trap_tracepoint)
{
@@ -3103,6 +3130,7 @@ cmd_qtstart (char *packet)
trace_buffer_is_full = 0;
expr_eval_result = expr_eval_no_error;
error_tracepoint = NULL;
+ tracing_start_time = get_timestamp ();
/* Tracing is now active, hits will now start being logged. */
tracing = 1;
@@ -3172,6 +3200,7 @@ stop_tracing (void)
fatal ("Error clearing tracing variable in lib");
}
+ tracing_stop_time = get_timestamp ();
tracing_stop_reason = "t???";
tracing_stop_tpnum = 0;
if (stopping_tracepoint)
@@ -3352,6 +3381,26 @@ static void
cmd_qtstatus (char *packet)
{
char *stop_reason_rsp = NULL;
+ char *buf1, *buf2, *buf3, *str;
+ int slen;
+
+ /* Translate the plain text of the notes back into hex for
+ transmission. */
+
+ str = (tracing_user_name ? tracing_user_name : "");
+ slen = strlen (str);
+ buf1 = (char *) alloca (slen * 2 + 1);
+ hexify (buf1, str, slen);
+
+ str = (tracing_notes ? tracing_notes : "");
+ slen = strlen (str);
+ buf2 = (char *) alloca (slen * 2 + 1);
+ hexify (buf2, str, slen);
+
+ str = (tracing_stop_note ? tracing_stop_note : "");
+ slen = strlen (str);
+ buf3 = (char *) alloca (slen * 2 + 1);
+ hexify (buf3, str, slen);
trace_debug ("Returning trace status as %d, stop reason %s",
tracing, tracing_stop_reason);
@@ -3368,7 +3417,7 @@ cmd_qtstatus (char *packet)
stop_reason_rsp = (char *) tracing_stop_reason;
/* The user visible error string in terror needs to be hex encoded.
- We leave it as plain string in `tracepoint_stop_reason' to ease
+ We leave it as plain string in `tracing_stop_reason' to ease
debugging. */
if (strncmp (stop_reason_rsp, "terror:", strlen ("terror:")) == 0)
{
@@ -3384,19 +3433,58 @@ cmd_qtstatus (char *packet)
convert_int_to_ascii ((gdb_byte *) result_name, p, strlen (result_name));
}
+ /* If this was a forced stop, include any stop note that was supplied. */
+ if (strcmp (stop_reason_rsp, "tstop") == 0)
+ {
+ stop_reason_rsp = alloca (strlen ("tstop:") + strlen (buf3) + 1);
+ strcpy (stop_reason_rsp, "tstop:");
+ strcat (stop_reason_rsp, buf3);
+ }
+
sprintf (packet,
"T%d;"
"%s:%x;"
"tframes:%x;tcreated:%x;"
"tfree:%x;tsize:%s;"
"circular:%d;"
- "disconn:%d",
+ "disconn:%d;"
+ "starttime:%llx;stoptime:%llx;"
+ "username:%s:;notes:%s:",
tracing ? 1 : 0,
stop_reason_rsp, tracing_stop_tpnum,
traceframe_count, traceframes_created,
free_space (), phex_nz (trace_buffer_hi - trace_buffer_lo, 0),
circular_trace_buffer,
- disconnected_tracing);
+ disconnected_tracing,
+ tracing_start_time, tracing_stop_time,
+ buf1, buf2);
+}
+
+static void
+cmd_qtp (char *own_buf)
+{
+ ULONGEST num, addr;
+ struct tracepoint *tpoint;
+ char *packet = own_buf;
+
+ packet += strlen ("qTP:");
+
+ packet = unpack_varlen_hex (packet, &num);
+ ++packet; /* skip a colon */
+ packet = unpack_varlen_hex (packet, &addr);
+
+ /* See if we already have this tracepoint. */
+ tpoint = find_tracepoint (num, addr);
+
+ if (!tpoint)
+ {
+ trace_debug ("Tracepoint error: tracepoint %d at 0x%s not found",
+ (int) num, paddress (addr));
+ write_enn (own_buf);
+ return;
+ }
+
+ sprintf (own_buf, "V%lx:%lx", tpoint->hit_count, tpoint->traceframe_usage);
}
/* State variables to help return all the tracepoint bits. */
@@ -3710,6 +3798,63 @@ cmd_bigqtbuffer (char *own_buf)
write_enn (own_buf);
}
+static void
+cmd_qtnotes (char *own_buf)
+{
+ size_t nbytes;
+ char *saved, *user, *notes, *stopnote;
+ char *packet = own_buf;
+
+ packet += strlen ("QTNotes:");
+
+ while (*packet)
+ {
+ if (strncmp ("user:", packet, strlen ("user:")) == 0)
+ {
+ packet += strlen ("user:");
+ saved = packet;
+ packet = strchr (packet, ';');
+ nbytes = (packet - saved) / 2;
+ user = xmalloc (nbytes + 1);
+ nbytes = unhexify (user, saved, nbytes);
+ user[nbytes] = '\0';
+ ++packet; /* skip the semicolon */
+ trace_debug ("User is '%s'", user);
+ tracing_user_name = user;
+ }
+ else if (strncmp ("notes:", packet, strlen ("notes:")) == 0)
+ {
+ packet += strlen ("notes:");
+ saved = packet;
+ packet = strchr (packet, ';');
+ nbytes = (packet - saved) / 2;
+ notes = xmalloc (nbytes + 1);
+ nbytes = unhexify (notes, saved, nbytes);
+ notes[nbytes] = '\0';
+ ++packet; /* skip the semicolon */
+ trace_debug ("Notes is '%s'", notes);
+ tracing_notes = notes;
+ }
+ else if (strncmp ("tstop:", packet, strlen ("tstop:")) == 0)
+ {
+ packet += strlen ("tstop:");
+ saved = packet;
+ packet = strchr (packet, ';');
+ nbytes = (packet - saved) / 2;
+ stopnote = xmalloc (nbytes + 1);
+ nbytes = unhexify (stopnote, saved, nbytes);
+ stopnote[nbytes] = '\0';
+ ++packet; /* skip the semicolon */
+ trace_debug ("tstop note is '%s'", stopnote);
+ tracing_stop_note = stopnote;
+ }
+ else
+ break;
+ }
+
+ write_ok (own_buf);
+}
+
int
handle_tracepoint_general_set (char *packet)
{
@@ -3774,6 +3919,11 @@ handle_tracepoint_general_set (char *packet)
cmd_bigqtbuffer (packet);
return 1;
}
+ else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0)
+ {
+ cmd_qtnotes (packet);
+ return 1;
+ }
return 0;
}
@@ -3786,6 +3936,11 @@ handle_tracepoint_query (char *packet)
cmd_qtstatus (packet);
return 1;
}
+ else if (strncmp ("qTP:", packet, strlen ("qTP:")) == 0)
+ {
+ cmd_qtp (packet);
+ return 1;
+ }
else if (strcmp ("qTfP", packet) == 0)
{
cmd_qtfp (packet);
@@ -8049,8 +8204,12 @@ initialize_tracepoint_ftlib (void)
#endif /* IN_PROCESS_AGENT */
+/* Return a timestamp, expressed as microseconds of the usual Unix
+ time. (As the result is a 64-bit number, it will not overflow any
+ time soon.) */
+
static LONGEST
-tsv_get_timestamp (void)
+get_timestamp (void)
{
struct timeval tv;
@@ -8074,7 +8233,7 @@ initialize_tracepoint (void)
variable numbered 1, it will be renumbered.) */
create_trace_state_variable (1, 0);
set_trace_state_variable_name (1, "trace_timestamp");
- set_trace_state_variable_getter (1, tsv_get_timestamp);
+ set_trace_state_variable_getter (1, get_timestamp);
#ifdef IN_PROCESS_AGENT
{