* 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.
+2011-11-20 Stan Shebs <stan@codesourcery.com>
+
+ * 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.
+
2011-11-20 Sanjoy Das <sdas@igalia.com>
* jit.c: Include regcache.h.
string. An optional integer following the "/s" sets a bound on the
number of bytes that will be collected.
+tstart [NOTES]
+ The trace start command now interprets any supplied arguments as a
+ note to be recorded with the trace run, with an effect similar to
+ setting the variable trace-notes.
+
+tstop [NOTES]
+ The trace stop command now interprets any arguments as a note to be
+ mentioned along with the tstatus report that the trace was stopped
+ with a command. The effect is similar to setting the variable
+ trace-stop-notes.
+
* Tracepoints can now be enabled and disabled at any time after a trace
experiment has been started using the standard "enable" and "disable"
commands. It is now possible to start a trace experiment with no enabled
If not set (the default), all source files are assumed to have just
one base name, and gdb will do file name comparisons more efficiently.
+set trace-user
+show trace-user
+set trace-notes
+show trace-notes
+ Set a user name and notes for the current and any future trace runs.
+ This is useful for long-running and/or disconnected traces, to
+ inform others (or yourself) as to who is running the trace, supply
+ contact information, or otherwise explain what is going on.
+
+set trace-stop-notes
+show trace-stop-notes
+ Set a note attached to the trace run, that is displayed when the
+ trace has been stopped by a tstop command. This is useful for
+ instance as an explanation, if you are stopping a trace run that was
+ started by someone else.
+
* New remote packets
QTEnable
Dynamically disable a tracepoint in a started trace experiment.
+QTNotes
+
+ Set the user and notes of the trace run.
+
+qTP
+
+ Query the current status of a tracepoint.
+
qTMinFTPILen
Query the minimum length of instruction at which a fast tracepoint may
/* FIXME should make an annotation for this. */
if (ep_is_catchpoint (b))
ui_out_text (uiout, "\tcatchpoint");
+ else if (is_tracepoint (b))
+ ui_out_text (uiout, "\ttracepoint");
else
ui_out_text (uiout, "\tbreakpoint");
ui_out_text (uiout, " already hit ");
ui_out_text (uiout, " hits\n");
}
+ if (!part_of_multiple && is_tracepoint (b))
+ {
+ struct tracepoint *tp = (struct tracepoint *) b;
+
+ if (tp->traceframe_usage)
+ {
+ ui_out_text (uiout, "\ttrace buffer usage ");
+ ui_out_field_int (uiout, "traceframe-usage", tp->traceframe_usage);
+ ui_out_text (uiout, " bytes\n");
+ }
+ }
+
l = b->commands ? b->commands->commands : NULL;
if (!part_of_multiple && l)
{
"have no source form, ignoring them"),
utp->number);
+ /* Copy any status information that might be available. */
+ tp->base.hit_count = utp->hit_count;
+ tp->traceframe_usage = utp->traceframe_usage;
+
return tp;
}
/* The number of the tracepoint on the target. */
int number_on_target;
+ /* The total space taken by all the trace frames for this
+ tracepoint. */
+ ULONGEST traceframe_usage;
+
/* The static tracepoint marker id, if known. */
char *static_trace_marker_id;
+2011-11-20 Stan Shebs <stan@codesourcery.com>
+
+ * gdb.texinfo (Starting and Stopping Trace Experiments): Document
+ note-related options and variables.
+ (Tracepoint Packets): Document packet changes.
+
2011-11-20 Sanjoy Das <sdas@igalia.com>
* gdb.texinfo (JIT Interface): Add documentation on writing and
@subsection Starting and Stopping Trace Experiments
@table @code
-@kindex tstart
+@kindex tstart [ @var{notes} ]
@cindex start a new trace experiment
@cindex collected data discarded
@item tstart
-This command takes no arguments. It starts the trace experiment, and
-begins collecting data. This has the side effect of discarding all
-the data collected in the trace buffer during the previous trace
-experiment.
-
-@kindex tstop
+This command starts the trace experiment, and begins collecting data.
+It has the side effect of discarding all the data collected in the
+trace buffer during the previous trace experiment. If any arguments
+are supplied, they are taken as a note and stored with the trace
+experiment's state. The notes may be arbitrary text, and are
+especially useful with disconnected tracing in a multi-user context;
+the notes can explain what the trace is doing, supply user contact
+information, and so forth.
+
+@kindex tstop [ @var{notes} ]
@cindex stop a running trace experiment
@item tstop
-This command takes no arguments. It ends the trace experiment, and
-stops collecting data.
+This command stops the trace experiment. If any arguments are
+supplied, they are recorded with the experiment as a note. This is
+useful if you are stopping a trace started by someone else, for
+instance if the trace is interfering with the system's behavior and
+needs to be stopped quickly.
@strong{Note}: a trace experiment and data collection may stop
automatically if any tracepoint's passcount is reached
@end table
+@table @code
+@item set trace-user @var{text}
+@kindex set trace-user
+
+@item show trace-user
+@kindex show trace-user
+
+@item set trace-notes @var{text}
+@kindex set trace-notes
+Set the trace run's notes.
+
+@item show trace-notes
+@kindex show trace-notes
+Show the trace run's notes.
+
+@item set trace-stop-notes @var{text}
+@kindex set trace-stop-notes
+Set the trace run's stop notes. The handling of the note is as for
+@code{tstop} arguments; the set command is convenient way to fix a
+stop note that is mistaken or incomplete.
+
+@item show trace-stop-notes
+@kindex show trace-stop-notes
+Show the trace run's stop notes.
+
+@end table
+
@node Tracepoint Restrictions
@subsection Tracepoint Restrictions
conventions above. Please don't use this packet as a model for new
packets.)
+@item QTNotes
+@item qTP
@item QTSave
@item qTsP
@item qTsV
@item tnotrun:0
No trace has been run yet.
-@item tstop:0
-The trace was stopped by a user-originated stop command.
+@item tstop[:@var{text}]:0
+The trace was stopped by a user-originated stop command. The optional
+@var{text} field is a user-supplied string supplied as part of the
+stop command (for instance, an explanation of why the trace was
+stopped manually). It is hex-encoded.
@item tfull:0
The trace stopped because the trace buffer filled up.
@end table
+@item qTP:@var{tp}:@var{addr}
+@cindex tracepoint status, remote request
+@cindex @samp{qTP} packet
+Ask the stub for the current state of tracepoint number @var{tp} at
+address @var{addr}.
+
+Replies:
+@table @samp
+@item V@var{hits}:@var{usage}
+The tracepoint has been hit @var{hits} times so far during the trace
+run, and accounts for @var{usage} in the trace buffer. Note that
+@code{while-stepping} steps are not counted as separate hits, but the
+steps' space consumption is added into the usage number.
+
+@end table
+
@item qTV:@var{var}
@cindex trace state variable value, remote request
@cindex @samp{qTV} packet
This packet directs the target to use a circular trace buffer if
@var{value} is 1, or a linear buffer if the value is 0.
+@item QTNotes:@r{[}@var{type}:@var{text}@r{]}@r{[};@var{type}:@var{text}@r{]}@dots{}
+This packet adds optional textual notes to the trace run. Allowable
+types include @code{user}, @code{notes}, and @code{tstop}, the
+@var{text} fields are arbitrary strings, hex-encoded.
+
@end table
@subsection Relocate instruction reply packet
+2011-11-17 Stan Shebs <stan@codesourcery.com>
+
+ * 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.
+
2011-11-14 Stan Shebs <stan@codesourcery.com>
Kwok Cheung Yeung <kcy@codesourcery.com>
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. */
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. */
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
{
/* Ensure all the hit counts start at zero. */
tpoint->hit_count = 0;
+ tpoint->traceframe_usage = 0;
if (tpoint->type == trap_tracepoint)
{
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;
fatal ("Error clearing tracing variable in lib");
}
+ tracing_stop_time = get_timestamp ();
tracing_stop_reason = "t???";
tracing_stop_tpnum = 0;
if (stopping_tracepoint)
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);
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)
{
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. */
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)
{
cmd_bigqtbuffer (packet);
return 1;
}
+ else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0)
+ {
+ cmd_qtnotes (packet);
+ return 1;
+ }
return 0;
}
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);
#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;
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
{
void
mi_cmd_trace_start (char *command, char **argv, int argc)
{
- start_tracing ();
+ start_tracing (NULL);
}
void
void
mi_cmd_trace_stop (char *command, char **argv, int argc)
{
- stop_tracing ();
+ stop_tracing (NULL);
trace_status_mi (1);
}
return ts->running;
}
+void
+remote_get_tracepoint_status (struct breakpoint *bp,
+ struct uploaded_tp *utp)
+{
+ struct remote_state *rs = get_remote_state ();
+ char addrbuf[40];
+ char *reply;
+ struct bp_location *loc;
+ struct tracepoint *tp = (struct tracepoint *) bp;
+
+ if (tp)
+ {
+ tp->base.hit_count = 0;
+ tp->traceframe_usage = 0;
+ for (loc = tp->base.loc; loc; loc = loc->next)
+ {
+ /* If the tracepoint was never downloaded, don't go asking for
+ any status. */
+ if (tp->number_on_target == 0)
+ continue;
+ sprintf_vma (addrbuf, loc->address);
+ sprintf (rs->buf, "qTP:%x:%s", tp->number_on_target, addrbuf);
+ putpkt (rs->buf);
+ reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (reply && *reply)
+ {
+ if (*reply == 'V')
+ parse_tracepoint_status (reply + 1, bp, utp);
+ }
+ }
+ }
+ else if (utp)
+ {
+ utp->hit_count = 0;
+ utp->traceframe_usage = 0;
+ sprintf_vma (addrbuf, (long unsigned int) utp->addr);
+ sprintf (rs->buf, "qTP:%x:%s", utp->number, addrbuf);
+ putpkt (rs->buf);
+ reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (reply && *reply)
+ {
+ if (*reply == 'V')
+ parse_tracepoint_status (reply + 1, bp, utp);
+ }
+ }
+}
+
static void
remote_trace_stop (void)
{
}
}
+static int
+remote_set_trace_notes (char *user, char *notes, char *stop_notes)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *reply;
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+ int nbytes;
+
+ buf += xsnprintf (buf, endbuf - buf, "QTNotes:");
+ if (user)
+ {
+ buf += xsnprintf (buf, endbuf - buf, "user:");
+ nbytes = bin2hex (user, buf, 0);
+ buf += 2 * nbytes;
+ *buf++ = ';';
+ }
+ if (notes)
+ {
+ buf += xsnprintf (buf, endbuf - buf, "notes:");
+ nbytes = bin2hex (notes, buf, 0);
+ buf += 2 * nbytes;
+ *buf++ = ';';
+ }
+ if (stop_notes)
+ {
+ buf += xsnprintf (buf, endbuf - buf, "tstop:");
+ nbytes = bin2hex (stop_notes, buf, 0);
+ buf += 2 * nbytes;
+ *buf++ = ';';
+ }
+ /* Ensure the buffer is terminated. */
+ *buf = '\0';
+
+ putpkt (rs->buf);
+ reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (*reply == '\0')
+ return 0;
+
+ if (strcmp (reply, "OK") != 0)
+ error (_("Bogus reply from target: %s"), reply);
+
+ return 1;
+}
+
static void
init_remote_ops (void)
{
remote_ops.to_trace_set_readonly_regions = remote_trace_set_readonly_regions;
remote_ops.to_trace_start = remote_trace_start;
remote_ops.to_get_trace_status = remote_get_trace_status;
+ remote_ops.to_get_tracepoint_status = remote_get_tracepoint_status;
remote_ops.to_trace_stop = remote_trace_stop;
remote_ops.to_trace_find = remote_trace_find;
remote_ops.to_get_trace_state_variable_value
remote_ops.to_get_min_fast_tracepoint_insn_len = remote_get_min_fast_tracepoint_insn_len;
remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer;
+ remote_ops.to_set_trace_notes = remote_set_trace_notes;
remote_ops.to_core_of_thread = remote_core_of_thread;
remote_ops.to_verify_memory = remote_verify_memory;
remote_ops.to_get_tib_address = remote_get_tib_address;
INHERIT (to_trace_set_readonly_regions, t);
INHERIT (to_trace_start, t);
INHERIT (to_get_trace_status, t);
+ INHERIT (to_get_tracepoint_status, t);
INHERIT (to_trace_stop, t);
INHERIT (to_trace_find, t);
INHERIT (to_get_trace_state_variable_value, t);
INHERIT (to_get_min_fast_tracepoint_insn_len, t);
INHERIT (to_set_disconnected_tracing, t);
INHERIT (to_set_circular_trace_buffer, t);
+ INHERIT (to_set_trace_notes, t);
INHERIT (to_get_tib_address, t);
INHERIT (to_set_permissions, t);
INHERIT (to_static_tracepoint_marker_at, t);
de_fault (to_get_trace_status,
(int (*) (struct trace_status *))
return_minus_one);
+ de_fault (to_get_tracepoint_status,
+ (void (*) (struct breakpoint *, struct uploaded_tp *))
+ tcomplain);
de_fault (to_trace_stop,
(void (*) (void))
tcomplain);
de_fault (to_set_circular_trace_buffer,
(void (*) (int))
target_ignore);
+ de_fault (to_set_trace_notes,
+ (int (*) (char *, char *, char *))
+ return_zero);
de_fault (to_get_tib_address,
(int (*) (ptid_t, CORE_ADDR *))
tcomplain);
/* Get the current status of a tracing run. */
int (*to_get_trace_status) (struct trace_status *ts);
+ void (*to_get_tracepoint_status) (struct breakpoint *tp,
+ struct uploaded_tp *utp);
+
/* Stop a trace run. */
void (*to_trace_stop) (void);
void (*to_set_disconnected_tracing) (int val);
void (*to_set_circular_trace_buffer) (int val);
+ /* Add/change textual notes about the trace run, returning 1 if
+ successful, 0 otherwise. */
+ int (*to_set_trace_notes) (char *user, char *notes, char* stopnotes);
+
/* Return the processor core that thread PTID was last seen on.
This information is updated only when:
- update_thread_list is called
#define target_get_trace_status(ts) \
(*current_target.to_get_trace_status) (ts)
+#define target_get_tracepoint_status(tp,utp) \
+ (*current_target.to_get_tracepoint_status) (tp, utp)
+
#define target_trace_stop() \
(*current_target.to_trace_stop) ()
#define target_set_circular_trace_buffer(val) \
(*current_target.to_set_circular_trace_buffer) (val)
+#define target_set_trace_notes(user,notes,stopnotes) \
+ (*current_target.to_set_trace_notes) ((user), (notes), (stopnotes))
+
#define target_get_tib_address(ptid, addr) \
(*current_target.to_get_tib_address) ((ptid), (addr))
+2011-11-20 Stan Shebs <stan@codesourcery.com>
+
+ * gdb.trace/tstatus.exp: New.
+ * gdb.trace/actions.c: Include string.h.
+
2011-11-18 Yao Qi <yao@codesourcery.com>
* gdb.trace/pending.exp: New.
* Test program for trace action commands
*/
+#include <string.h>
+
static char gdb_char_test;
static short gdb_short_test;
static long gdb_long_test;
--- /dev/null
+# Copyright 2011 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "trace-support.exp"
+
+set testfile "actions"
+set executable $testfile
+set srcfile $testfile.c
+set binfile $objdir/$subdir/$testfile
+set expfile tstatus.exp
+
+if [prepare_for_testing $expfile $executable $srcfile \
+ [list debug]] {
+ untested "failed to prepare for trace tests"
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main to check for trace support"
+ return -1
+}
+
+if ![gdb_target_supports_trace] {
+ unsupported "target does not support trace"
+ return -1
+}
+
+set libipa $objdir/../gdbserver/libinproctrace.so
+gdb_load_shlibs $libipa
+
+# Can't use prepare_for_testing, because that splits compiling into
+# building objects and then linking, and we'd fail with "linker input
+# file unused because linking not done" when building the object.
+
+if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable [list debug shlib=$libipa] ] != "" } {
+ untested "failed to compile ftrace tests"
+ return -1
+}
+clean_restart ${executable}
+
+if ![runto_main] {
+ fail "Can't run to main for ftrace tests"
+ return 0
+}
+
+proc run_trace_experiment {} {
+
+# gdb_test_no_output "set debug remote 1" ""
+
+ gdb_test "continue" \
+ ".*Breakpoint \[0-9\]+, begin .*" \
+ "advance to trace begin"
+
+ gdb_test_no_output "tstart my tracing note" "start trace experiment"
+
+ gdb_test "continue" \
+ ".*Breakpoint \[0-9\]+, end .*" \
+ "advance through tracing"
+
+ # Now play with tstatus a bit.
+ # Since note support is optional, we need to match both with and without
+ # cases.
+
+ gdb_test_multiple "tstatus" "check on trace status" {
+ -re "Trace is running.*Trace will stop if GDB disconnects\.\[\r\n\]+Trace notes: my tracing note\.\[\r\n\]+Not looking at any trace frame\..*" {
+ pass "tstatus reports trace note"
+ }
+ -re "Trace is running.*Trace will stop if GDB disconnects\.\[\r\n\]+Not looking at any trace frame.*" {
+ pass "tstatus does not report any trace note"
+ }
+ }
+
+ gdb_test "set trace-notes different note" "" "change tracing note"
+
+ gdb_test_multiple "tstatus" "check on trace status with diff note" {
+ -re "Trace is running.*Trace will stop if GDB disconnects\.\[\r\n\]+Trace notes: different note\.\[\r\n\]+Not looking at any trace frame\..*" {
+ pass "tstatus reports different trace note"
+ }
+ -re "Trace is running.*Trace will stop if GDB disconnects\.\[\r\n\]+Not looking at any trace frame.*" {
+ pass "tstatus does not report any different trace note"
+ }
+ }
+
+ gdb_test "set trace-user me me me" "" "change tracing user"
+
+ gdb_test_multiple "tstatus" "check on trace status with diff note" {
+ -re "Trace is running.*Trace will stop if GDB disconnects\.\[\r\n\]+Trace user is me me me\.\[\r\n\]+Trace notes: different note\.\[\r\n\]+Not looking at any trace frame\..*" {
+ pass "tstatus reports trace user"
+ }
+ -re "Trace is running.*Trace will stop if GDB disconnects\.\[\r\n\]+Not looking at any trace frame.*" {
+ pass "tstatus does not report trace user"
+ }
+ }
+
+ gdb_test_no_output "tstop because I can" "trace stopped with note"
+
+ gdb_test_multiple "tstatus" "check on trace status after stop" {
+ -re "Trace stopped by a tstop command (because I can)\..*Trace will stop if GDB disconnects\.\[\r\n\]+Trace user is me me me\.\[\r\n\]+Trace notes: different note\.\[\r\n\]+Not looking at any trace frame\..*" {
+ pass "tstatus reports trace stop reason"
+ }
+ -re "Trace stopped by a tstop command\..*" {
+ pass "tstatus does not report trace stop reason"
+ }
+ }
+
+ # Tracepoint hit count is optional, so pass it either way.
+
+ gdb_test_multiple "info trace" "show tracepoint state" {
+ -re "actions\.c:\[0-9\]+\[\r\n\]+\[\t ]+tracepoint already hit 1 time\[\r\n\]+\[\t ]+collect parm" {
+ pass "info trace reports tracepoint hit count"
+ }
+ -re "actions\.c:\[0-9\]+\[\r\n\]+\[\t ]+collect parm" {
+ pass "info trace does not report tracepoint hit count"
+ }
+ }
+}
+
+proc test_tracepoints {} {
+
+ gdb_test "break begin" ".*" ""
+
+ gdb_test "break end" ".*" ""
+
+ gdb_test "trace gdb_c_test" "Tracepoint .*" \
+ "tracepoint at gdb_c_test"
+
+ gdb_trace_setactions "collect at set_point: define actions" \
+ "" \
+ "collect parm" "^$"
+ set fastgood 0
+
+ gdb_test_multiple "ftrace gdb_recursion_test" "set fast tracepoint" {
+ -re "May not have a fast tracepoint at .*" {
+ pass "4-byte fast tracepoint could not be set"
+ }
+ -re "Fast tracepoint .*" {
+ pass "4-byte fast tracepoint is set"
+ set fastgood 1
+ }
+ }
+
+ if { $fastgood } {
+
+ gdb_trace_setactions "collect at four_byter: define actions" \
+ "" \
+ "collect globvar, anarg" "^$"
+ }
+
+ run_trace_experiment
+
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+
+if { [gdb_test "info sharedlibrary" ".*libinproctrace\.so.*" "IPA loaded"] != 0 } {
+ untested "Could not find IPA lib loaded"
+ return 1
+}
+
+test_tracepoints
global gdbserver_reconnect_p
if {![info exists gdbserver_reconnect_p] || !$gdbserver_reconnect_p} {
# GDB client could accidentally connect to a stale server.
+ # append gdbserver_command " --debug --once"
append gdbserver_command " --once"
}
static int circular_trace_buffer;
+/* Textual notes applying to the current and/or future trace runs. */
+
+char *trace_user = NULL;
+
+/* Textual notes applying to the current and/or future trace runs. */
+
+char *trace_notes = NULL;
+
+/* Textual notes applying to the stopping of a trace. */
+
+char *trace_stop_notes = NULL;
+
/* ======= Important command functions: ======= */
static void trace_actions_command (char *, int);
static void trace_start_command (char *, int);
static void add_register (struct collection_list *collection,
unsigned int regno);
-extern void send_disconnected_tracing_value (int value);
-
static void free_uploaded_tps (struct uploaded_tp **utpp);
static void free_uploaded_tsvs (struct uploaded_tsv **utsvp);
void
-start_tracing (void)
+start_tracing (char *notes)
{
VEC(breakpoint_p) *tp_vec = NULL;
int ix;
struct breakpoint *b;
struct trace_state_variable *tsv;
int any_enabled = 0, num_to_download = 0;
-
+ int ret;
+
tp_vec = all_tracepoints ();
/* No point in tracing without any tracepoints... */
target_set_disconnected_tracing (disconnected_tracing);
target_set_circular_trace_buffer (circular_trace_buffer);
+ if (!notes)
+ notes = trace_notes;
+ ret = target_set_trace_notes (trace_user, notes, NULL);
+
+ if (!ret && (trace_user || notes))
+ warning ("Target does not support trace user/notes, info ignored");
+
/* Now insert traps and begin collecting data. */
target_trace_start ();
clear_traceframe_info ();
}
-/* tstart command:
-
- Tell target to clear any previous trace experiment.
- Walk the list of tracepoints, and send them (and their actions)
- to the target. If no errors,
- Tell target to start a new trace experiment. */
+/* The tstart command requests the target to start a new trace run.
+ The command passes any arguments it has to the target verbatim, as
+ an optional "trace note". This is useful as for instance a warning
+ to other users if the trace runs disconnected, and you don't want
+ anybody else messing with the target. */
static void
trace_start_command (char *args, int from_tty)
error (_("New trace run not started."));
}
- start_tracing ();
+ start_tracing (args);
}
-/* tstop command */
+/* The tstop command stops the tracing run. The command passes any
+ supplied arguments to the target verbatim as a "stop note"; if the
+ target supports trace notes, then it will be reported back as part
+ of the trace run's status. */
+
static void
trace_stop_command (char *args, int from_tty)
{
if (!current_trace_status ()->running)
error (_("Trace is not running."));
- stop_tracing ();
+ stop_tracing (args);
}
void
-stop_tracing (void)
+stop_tracing (char *note)
{
+ int ret;
+
target_trace_stop ();
+
+ if (!note)
+ note = trace_stop_notes;
+ ret = target_set_trace_notes (NULL, NULL, note);
+
+ if (!ret && note)
+ warning ("Target does not support trace notes, note ignored");
+
/* Should change in response to reply? */
current_trace_status ()->running = 0;
}
trace_status_command (char *args, int from_tty)
{
struct trace_status *ts = current_trace_status ();
- int status;
+ int status, ix;
+ VEC(breakpoint_p) *tp_vec = NULL;
+ struct breakpoint *t;
status = target_get_trace_status (ts);
printf_filtered (_("No trace has been run on the target.\n"));
break;
case tstop_command:
- printf_filtered (_("Trace stopped by a tstop command.\n"));
+ if (ts->stop_desc)
+ printf_filtered (_("Trace stopped by a tstop command (%s).\n"),
+ ts->stop_desc);
+ else
+ printf_filtered (_("Trace stopped by a tstop command.\n"));
break;
case trace_buffer_full:
printf_filtered (_("Trace stopped because the buffer was full.\n"));
if (ts->stopping_tracepoint)
printf_filtered (_("Trace stopped by an "
"error (%s, tracepoint %d).\n"),
- ts->error_desc, ts->stopping_tracepoint);
+ ts->stop_desc, ts->stopping_tracepoint);
else
printf_filtered (_("Trace stopped by an error (%s).\n"),
- ts->error_desc);
+ ts->stop_desc);
break;
case trace_stop_reason_unknown:
printf_filtered (_("Trace stopped for an unknown reason.\n"));
if (ts->circular_buffer)
printf_filtered (_("Trace buffer is circular.\n"));
+ if (ts->user_name && strlen (ts->user_name) > 0)
+ printf_filtered (_("Trace user is %s.\n"), ts->user_name);
+
+ if (ts->notes && strlen (ts->notes) > 0)
+ printf_filtered (_("Trace notes: %s.\n"), ts->notes);
+
/* Now report on what we're doing with tfind. */
if (traceframe_number >= 0)
printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
traceframe_number, tracepoint_number);
else
printf_filtered (_("Not looking at any trace frame.\n"));
+
+ /* Report start/stop times if supplied. */
+ if (ts->start_time)
+ {
+ if (ts->stop_time)
+ {
+ LONGEST run_time = ts->stop_time - ts->start_time;
+
+ /* Reporting a run time is more readable than two long numbers. */
+ printf_filtered (_("Trace started at %ld.%06ld secs, stopped %ld.%06ld secs later.\n"),
+ ts->start_time / 1000000, ts->start_time % 1000000,
+ run_time / 1000000, run_time % 1000000);
+ }
+ else
+ printf_filtered (_("Trace started at %ld.%06ld secs.\n"),
+ ts->start_time / 1000000, ts->start_time % 1000000);
+ }
+ else if (ts->stop_time)
+ printf_filtered (_("Trace stopped at %ld.%06ld secs.\n"),
+ ts->stop_time / 1000000, ts->stop_time % 1000000);
+
+ /* Now report any per-tracepoint status available. */
+ tp_vec = all_tracepoints ();
+
+ for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+ target_get_tracepoint_status (t, NULL);
+
+ VEC_free (breakpoint_p, tp_vec);
}
/* Report the trace status to uiout, in a way suitable for MI, and not
stopping_tracepoint);
if (ts->stop_reason == tracepoint_error)
ui_out_field_string (uiout, "error-description",
- ts->error_desc);
+ ts->stop_desc);
}
}
}
ui_out_field_int (uiout, "disconnected", ts->disconnected_tracing);
ui_out_field_int (uiout, "circular", ts->circular_buffer);
+
+ ui_out_field_string (uiout, "user-name", ts->user_name);
+ ui_out_field_string (uiout, "notes", ts->notes);
+
+ {
+ char buf[100];
+
+ xsnprintf (buf, sizeof buf, "%ld.%06ld",
+ ts->start_time / 1000000, ts->start_time % 1000000);
+ ui_out_field_string (uiout, "start-time", buf);
+ xsnprintf (buf, sizeof buf, "%ld.%06ld",
+ ts->stop_time / 1000000, ts->stop_time % 1000000);
+ ui_out_field_string (uiout, "stop-time", buf);
+ }
}
/* This function handles the details of what to do about an ongoing
(ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
if (ts->stop_reason == tracepoint_error)
{
- char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1);
+ char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1);
- bin2hex ((gdb_byte *) ts->error_desc, buf, 0);
+ bin2hex ((gdb_byte *) ts->stop_desc, buf, 0);
fprintf (fp, ":%s", buf);
}
fprintf (fp, ":%x", ts->stopping_tracepoint);
target_upload_tracepoints (&uploaded_tps);
for (utp = uploaded_tps; utp; utp = utp->next)
+ target_get_tracepoint_status (NULL, utp);
+
+ for (utp = uploaded_tps; utp; utp = utp->next)
{
fprintf (fp, "tp T%x:%s:%c:%x:%x",
utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
buf, MAX_TRACE_UPLOAD);
fprintf (fp, "tp Z%s\n", buf);
}
+ fprintf (fp, "tp V%x:%s:%x:%s\n",
+ utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
+ utp->hit_count,
+ phex_nz (utp->traceframe_usage,
+ sizeof (utp->traceframe_usage)));
}
free_uploaded_tps (&uploaded_tps);
/* Tell the target what to do with an ongoing tracing run if GDB
disconnects for some reason. */
-void
-send_disconnected_tracing_value (int value)
-{
- target_set_disconnected_tracing (value);
-}
-
static void
set_disconnected_tracing (char *args, int from_tty,
struct cmd_list_element *c)
{
- send_disconnected_tracing_value (disconnected_tracing);
+ target_set_disconnected_tracing (disconnected_tracing);
}
static void
target_set_circular_trace_buffer (circular_trace_buffer);
}
+static void
+set_trace_user (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ int ret;
+
+ ret = target_set_trace_notes (trace_user, NULL, NULL);
+
+ if (!ret)
+ warning ("Target does not support trace notes, user ignored");
+}
+
+static void
+set_trace_notes (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ int ret;
+
+ ret = target_set_trace_notes (NULL, trace_notes, NULL);
+
+ if (!ret)
+ warning ("Target does not support trace notes, note ignored");
+}
+
+static void
+set_trace_stop_notes (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ int ret;
+
+ ret = target_set_trace_notes (NULL, NULL, trace_stop_notes);
+
+ if (!ret)
+ warning ("Target does not support trace notes, stop note ignored");
+}
+
/* Convert the memory pointed to by mem into hex, placing result in buf.
* Return a pointer to the last char put in buf (null)
* "stolen" from sparc-stub.c
void
parse_trace_status (char *line, struct trace_status *ts)
{
- char *p = line, *p1, *p2, *p_temp;
+ char *p = line, *p1, *p2, *p3, *p_temp;
+ int end;
ULONGEST val;
ts->running_known = 1;
ts->running = (*p++ == '1');
ts->stop_reason = trace_stop_reason_unknown;
- xfree (ts->error_desc);
- ts->error_desc = NULL;
+ xfree (ts->stop_desc);
+ ts->stop_desc = NULL;
ts->traceframe_count = -1;
ts->traceframes_created = -1;
ts->buffer_free = -1;
ts->buffer_size = -1;
ts->disconnected_tracing = 0;
ts->circular_buffer = 0;
+ xfree (ts->user_name);
+ ts->user_name = NULL;
+ xfree (ts->notes);
+ ts->notes = NULL;
+ ts->start_time = ts->stop_time = 0;
while (*p++)
{
if (p1 == NULL)
error (_("Malformed trace status, at %s\n\
Status line: '%s'\n"), p, line);
+ p3 = strchr (p, ';');
+ if (p3 == NULL)
+ p3 = p + strlen (p);
if (strncmp (p, stop_reason_names[trace_buffer_full], p1 - p) == 0)
{
p = unpack_varlen_hex (++p1, &val);
}
else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0)
{
- p = unpack_varlen_hex (++p1, &val);
+ p2 = strchr (++p1, ':');
+ if (!p2 || p2 > p3)
+ {
+ /*older style*/
+ p2 = p1;
+ }
+ else if (p2 != p1)
+ {
+ ts->stop_desc = xmalloc (strlen (line));
+ end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2);
+ ts->stop_desc[end] = '\0';
+ }
+ else
+ ts->stop_desc = xstrdup ("");
+
+ p = unpack_varlen_hex (++p2, &val);
ts->stop_reason = tstop_command;
}
else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0)
p2 = strchr (++p1, ':');
if (p2 != p1)
{
- int end;
-
- ts->error_desc = xmalloc ((p2 - p1) / 2 + 1);
- end = hex2bin (p1, ts->error_desc, (p2 - p1) / 2);
- ts->error_desc[end] = '\0';
+ ts->stop_desc = xmalloc ((p2 - p1) / 2 + 1);
+ end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2);
+ ts->stop_desc[end] = '\0';
}
else
- ts->error_desc = xstrdup ("");
+ ts->stop_desc = xstrdup ("");
p = unpack_varlen_hex (++p2, &val);
ts->stopping_tracepoint = val;
p = unpack_varlen_hex (++p1, &val);
ts->circular_buffer = val;
}
+ else if (strncmp (p, "starttime", p1 - p) == 0)
+ {
+ p = unpack_varlen_hex (++p1, &val);
+ ts->start_time = val;
+ }
+ else if (strncmp (p, "stoptime", p1 - p) == 0)
+ {
+ p = unpack_varlen_hex (++p1, &val);
+ ts->stop_time = val;
+ }
+ else if (strncmp (p, "username", p1 - p) == 0)
+ {
+ ++p1;
+ ts->user_name = xmalloc (strlen (p) / 2);
+ end = hex2bin (p1, ts->user_name, (p3 - p1) / 2);
+ ts->user_name[end] = '\0';
+ p = p3;
+ }
+ else if (strncmp (p, "notes", p1 - p) == 0)
+ {
+ ++p1;
+ ts->notes = xmalloc (strlen (p) / 2);
+ end = hex2bin (p1, ts->notes, (p3 - p1) / 2);
+ ts->notes[end] = '\0';
+ p = p3;
+ }
else
{
/* Silently skip unknown optional info. */
}
}
+void
+parse_tracepoint_status (char *p, struct breakpoint *bp,
+ struct uploaded_tp *utp)
+{
+ ULONGEST uval;
+ struct tracepoint *tp = (struct tracepoint *) bp;
+
+ p = unpack_varlen_hex (p, &uval);
+ if (tp)
+ tp->base.hit_count += uval;
+ else
+ utp->hit_count += uval;
+ p = unpack_varlen_hex (p + 1, &uval);
+ if (tp)
+ tp->traceframe_usage += uval;
+ else
+ utp->traceframe_usage += uval;
+ /* Ignore any extra, allowing for future extensions. */
+}
+
/* Given a line of text defining a part of a tracepoint, parse it into
an "uploaded tracepoint". */
else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
}
+ else if (piece == 'V')
+ {
+ utp = get_uploaded_tp (num, addr, utpp);
+
+ parse_tracepoint_status (p, NULL, utp);
+ }
else
{
/* Don't error out, the target might be sending us optional
return -1;
}
+static void
+tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp)
+{
+ /* Other bits of trace status were collected as part of opening the
+ trace files, so nothing to do here. */
+}
+
/* Given the position of a traceframe in the file, figure out what
address the frame was collected at. This would normally be the
value of a collected PC register, but if not available, we
tfile_ops.to_xfer_partial = tfile_xfer_partial;
tfile_ops.to_files_info = tfile_files_info;
tfile_ops.to_get_trace_status = tfile_get_trace_status;
+ tfile_ops.to_get_tracepoint_status = tfile_get_tracepoint_status;
tfile_ops.to_trace_find = tfile_trace_find;
tfile_ops.to_get_trace_state_variable_value
= tfile_get_trace_state_variable_value;
add_com ("tstatus", class_trace, trace_status_command,
_("Display the status of the current trace data collection."));
- add_com ("tstop", class_trace, trace_stop_command,
- _("Stop trace data collection."));
+ add_com ("tstop", class_trace, trace_stop_command, _("\
+Stop trace data collection.\n\
+Usage: tstop [ <notes> ... ]\n\
+Any arguments supplied are recorded with the trace as a stop reason and\n\
+reported by tstatus (if the target supports trace notes)."));
- add_com ("tstart", class_trace, trace_start_command,
- _("Start trace data collection."));
+ add_com ("tstart", class_trace, trace_start_command, _("\
+Start trace data collection.\n\
+Usage: tstart [ <notes> ... ]\n\
+Any arguments supplied are recorded with the trace as a note and\n\
+reported by tstatus (if the target supports trace notes)."));
add_com ("end", class_trace, end_actions_pseudocommand, _("\
Ends a list of commands or actions.\n\
&setlist,
&showlist);
+ add_setshow_string_cmd ("trace-user", class_trace,
+ &trace_user, _("\
+Set the user name to use for current and future trace runs"), _("\
+Show the user name to use for current and future trace runs"), NULL,
+ set_trace_user, NULL,
+ &setlist, &showlist);
+
+ add_setshow_string_cmd ("trace-notes", class_trace,
+ &trace_notes, _("\
+Set notes string to use for current and future trace runs"), _("\
+Show the notes string to use for current and future trace runs"), NULL,
+ set_trace_notes, NULL,
+ &setlist, &showlist);
+
+ add_setshow_string_cmd ("trace-stop-notes", class_trace,
+ &trace_stop_notes, _("\
+Set notes string to use for future tstop commands"), _("\
+Show the notes string to use for future tstop commands"), NULL,
+ set_trace_stop_notes, NULL,
+ &setlist, &showlist);
+
init_tfile_ops ();
add_target (&tfile_ops);
/* This is true if the value of the running field is known. */
int running_known;
+ /* This is true when the trace experiment is actually running. */
int running;
enum trace_stop_reason stop_reason;
stop. */
int stopping_tracepoint;
- /* If stop_reason is tracepoint_error, this is a human-readable
- string that describes the error that happened on the target. */
- char *error_desc;
+ /* If stop_reason is tstop_command or tracepoint_error, this is an
+ arbitrary string that may describe the reason for the stop in
+ more detail. */
+
+ char *stop_desc;
/* Number of traceframes currently in the buffer. */
target does not report a value, assume 0. */
int circular_buffer;
+
+ /* The "name" of the person running the trace. This is an
+ arbitrary string. */
+
+ char *user_name;
+
+ /* "Notes" about the trace. This is an arbitrary string not
+ interpreted by GDBserver in any special way. */
+
+ char *notes;
+
+ /* The calendar times at which the trace run started and stopped,
+ both expressed in microseconds of Unix time. */
+
+ LONGEST start_time;
+ LONGEST stop_time;
};
struct trace_status *current_trace_status (void);
/* List of original strings defining the tracepoint's actions. */
VEC(char_ptr) *cmd_strings;
+ /* The tracepoint's current hit count. */
+ int hit_count;
+
+ /* The tracepoint's current traceframe usage. */
+ ULONGEST traceframe_usage;
+
struct uploaded_tp *next;
};
extern void parse_trace_status (char *line, struct trace_status *ts);
+extern void parse_tracepoint_status (char *p, struct breakpoint *tp,
+ struct uploaded_tp *utp);
+
extern void parse_tracepoint_definition (char *line,
struct uploaded_tp **utpp);
extern void parse_tsv_definition (char *line, struct uploaded_tsv **utsvp);
extern void disconnect_tracing (int from_tty);
-extern void start_tracing (void);
-extern void stop_tracing (void);
+extern void start_tracing (char *notes);
+extern void stop_tracing (char *notes);
extern void trace_status_mi (int on_stop);