+2010-03-18 Stan Shebs <stan@codesourcery.com>
+ Pedro Alves <pedro@codesourcery.com>
+
+ * target.h (struct target_ops): New method
+ to_set_circular_trace_buffer.
+ (target_set_circular_trace_buffer): New macro.
+ * target.c (update_current_target): Add
+ to_set_circular_trace_buffer, fix to_set_disconnected_tracing
+ default behavior.
+ * remote.c (remote_set_circular_trace_buffer): New function.
+ (init_remote_ops): Add it to vector.
+ * tracepoint.h (struct trace_status): New field traceframes_created,
+ change buffer_size and buffer_free to int.
+ * tracepoint.c (circular_trace_buffer): New global.
+ (start_tracing): Send values of disconnected tracing and circular
+ trace buffer settings.
+ (set_circular_trace_buffer): New function.
+ (parse_trace_state): Handle total space and frames created.
+ (trace_status_command): Display total space and total frames
+ created.
+ (trace_save): Write out new status values.
+ (parse_trace_status): Set traceframe_count, traceframes_created,
+ buffer_free and buffer_size to -1 by default.
+ (_initialize_tracepoint): New setshow for circular-trace-buffer.
+ * NEWS: Mention the circular trace buffer option.
+
2010-03-18 Tom Tromey <tromey@redhat.com>
* infcmd.c (finish_command_continuation): Wrap print_return_value
tracing run at the moment that it was saved. To create a trace
file, use "tsave <filename>", and to use it, do "target tfile
<name>".
-
+
+ ** Circular trace buffer
+
+ You can ask the target agent to handle the trace buffer as a
+ circular buffer, discarding the oldest trace frames to make room for
+ newer ones, by setting circular-trace-buffer to on. This feature may
+ not be available for all target agents.
+
* Changed commands
disassemble
loses its connection to GDB. If 0, the target is to stop tracing
upon disconnection.
+set circular-trace-buffer
+show circular-trace-buffer
+ If set to on, the target is instructed to use a circular trace buffer
+ and discard the oldest trace frames instead of stopping the trace due
+ to a full trace buffer. If set to off, the trace stops when the buffer
+ fills up. Some targets may not support this.
+
set script-extension off|soft|strict
show script-extension
If set to "off", the debugger does not perform any script language
QTDisconnected
Set desired tracing behavior upon disconnection.
+QTBuffer:circular
+ Set the trace buffer to be linear or circular.
+
qTfP, qTsP
Get data about the tracepoints currently in use.
+2010-03-16 Stan Shebs <stan@codesourcery.com>
+
+ * gdb.texinfo (Starting and Stopping Trace Experiments): Describe
+ circular-trace-buffer.
+ (Tracepoint Packets): Describe QTBuffer, and details of the
+ qTStatus reply.
+
2010-03-12 Stan Shebs <stan@codesourcery.com>
Nathan Sidwell <nathan@codesourcery.com>
necessarily heuristic, and it may result in useless tracepoints being
created; you may simply delete them if they are of no use.
+@cindex circular trace buffer
+If your target agent supports a @dfn{circular trace buffer}, then you
+can run a trace experiment indefinitely without filling the trace
+buffer; when space runs out, the agent deletes already-collected trace
+frames, oldest first, until there is enough room to continue
+collecting. This is especially useful if your tracepoints are being
+hit too often, and your trace gets terminated prematurely because the
+buffer is full. To ask for a circular trace buffer, simply set
+@samp{circular_trace_buffer} to on. You can set this at any time,
+including during tracing; if the agent can do it, it will change
+buffer handling on the fly, otherwise it will not take effect until
+the next run.
+
+@table @code
+@item set circular-trace-buffer on
+@itemx set circular-trace-buffer off
+@kindex set circular-trace-buffer
+Choose whether a tracing run should use a linear or circular buffer
+for trace data. A linear buffer will not lose any trace data, but may
+fill up prematurely, while a circular buffer will discard old trace
+data, but it will have always room for the latest tracepoint hits.
+
+@item show circular-trace-buffer
+@kindex show circular-trace-buffer
+Show the current choice for the trace buffer. Note that this may not
+match the agent's current buffer handling, nor is it guaranteed to
+match the setting that might have been in effect during a past run,
+for instance if you are looking at frames from a trace file.
+
+@end table
+
@node Tracepoint Restrictions
@subsection Tracepoint Restrictions
@end table
@item qTBuffer
+@item QTBuffer
@item QTDisconnected
@itemx QTDP
@itemx QTDV
@item qTStatus
Ask the stub if there is a trace experiment running right now.
-Replies:
+The reply has the form:
+
+@table @samp
+
+@item T@var{running}@r{[};@var{field}@r{]}@dots{}
+@var{running} is a single digit @code{1} if the trace is presently
+running, or @code{0} if not. It is followed by semicolon-separated
+optional fields that an agent may use to report additional status.
+
+@end table
+
+If the trace is not running, the agent may report any of several
+explanations as one of the optional fields:
+
+@table @samp
+
+@item tnotrun:0
+No trace has been run yet.
+
+@item tstop:0
+The trace was stopped by a user-originated stop command.
+
+@item tfull:0
+The trace stopped because the trace buffer filled up.
+
+@item tdisconnected:0
+The trace stopped because @value{GDBN} disconnected from the target.
+
+@item tpasscount:@var{tpnum}
+The trace stopped because tracepoint @var{tpnum} exceeded its pass count.
+
+@item tunknown:0
+The trace stopped for some other reason.
+
+@end table
+
+Additional optional fields supply statistical information. Although
+not required, they are extremely useful for users monitoring the
+progress of a trace run. If a trace has stopped, and these numbers
+are reported, they must reflect the state of the just-stopped trace.
+
@table @samp
-@item T0
-There is no trace experiment running.
-@item T1
-There is a trace experiment running.
+
+@item tframes:@var{n}
+The number of trace frames in the buffer.
+
+@item tcreated:@var{n}
+The total number of trace frames created during the run. This may
+be larger than the trace frame count, if the buffer is circular.
+
+@item tsize:@var{n}
+The total size of the trace buffer, in bytes.
+
+@item tfree:@var{n}
+The number of bytes still unused in the buffer.
+
@end table
@item qTV:@var{var}
A reply consisting of just @code{l} indicates that no bytes are
available.
+@item QTBuffer:circular:@var{value}
+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.
+
@end table
@node Host I/O Packets
return -1;
}
+static void
+remote_set_circular_trace_buffer (int val)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ sprintf (rs->buf, "QTBuffer:circular:%x", val);
+ putpkt (rs->buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Target does not support this command."));
+}
+
static void
init_remote_ops (void)
{
remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables;
remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data;
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_core_of_thread = remote_core_of_thread;
}
INHERIT (to_upload_trace_state_variables, t);
INHERIT (to_get_raw_trace_data, t);
INHERIT (to_set_disconnected_tracing, t);
+ INHERIT (to_set_circular_trace_buffer, t);
INHERIT (to_magic, t);
/* Do not inherit to_memory_map. */
/* Do not inherit to_flash_erase. */
tcomplain);
de_fault (to_set_disconnected_tracing,
(void (*) (int))
- tcomplain);
+ target_ignore);
+ de_fault (to_set_circular_trace_buffer,
+ (void (*) (int))
+ target_ignore);
#undef de_fault
/* Finally, position the target-stack beneath the squashed
/* Set the target's tracing behavior in response to unexpected
disconnection - set VAL to 1 to keep tracing, 0 to stop. */
void (*to_set_disconnected_tracing) (int val);
+ void (*to_set_circular_trace_buffer) (int val);
/* Return the processor core that thread PTID was last seen on.
This information is updated only when:
#define target_set_disconnected_tracing(val) \
(*current_target.to_set_disconnected_tracing) (val)
+#define target_set_circular_trace_buffer(val) \
+ (*current_target.to_set_circular_trace_buffer) (val)
+
/* Command logging facility. */
#define target_log_command(p) \
+2010-03-18 Stan Shebs <stan@codesourcery.com>
+
+ * gdb.trace/circ.exp: Test circular-trace-buffer.
+ * gdb.trace/tfile.exp: Update tstatus test.
+
2010-03-18 Joel Brobecker <brobecker@adacore.com>
* gdb.dwarf2/dw2-anonymous-func.S: New file.
if [target_info exists gdb_stub] {
gdb_step_for_stub;
}
+
+gdb_test "set circular-trace-buffer on" "" "set circular-trace-buffer on"
+
+gdb_test "show circular-trace-buffer" "Target's use of circular trace buffer is on." "show circular-trace-buffer (on)"
+
+gdb_test "set circular-trace-buffer off" "" "set circular-trace-buffer off"
+
+gdb_test "show circular-trace-buffer" "Target's use of circular trace buffer is off." "show circular-trace-buffer (off)"
+
# Body of test encased in a proc so we can return prematurely.
if { ![gdb_trace_circular_tests] } then {
# Set trace buffer attributes back to normal
gdb_test "tstatus" \
"Using a trace file.*
Trace stopped by a tstop command.*
-Collected 1 trace frames.*
-Trace buffer has 256 bytes free.*
+Collected 1 trace frame.*
+Trace buffer has 256 bytes of 4096 bytes free \\(93% full\\).*
Looking at trace frame 0, tracepoint .*" \
"tstatus on trace file"
static int disconnected_tracing;
+/* This variable controls whether we ask the target for a linear or
+ circular trace buffer. */
+
+static int circular_trace_buffer;
+
/* ======= Important command functions: ======= */
static void trace_actions_command (char *, int);
static void trace_start_command (char *, int);
/* Tell target to treat text-like sections as transparent. */
target_trace_set_readonly_regions ();
+ /* Set some mode flags. */
+ target_set_disconnected_tracing (disconnected_tracing);
+ target_set_circular_trace_buffer (circular_trace_buffer);
/* Now insert traps and begin collecting data. */
target_trace_start ();
}
}
- if (ts->traceframe_count >= 0)
+ if (ts->traceframes_created >= 0
+ && ts->traceframe_count != ts->traceframes_created)
+ {
+ printf_filtered (_("Buffer contains %d trace frames (of %d created total).\n"),
+ ts->traceframe_count, ts->traceframes_created);
+ }
+ else if (ts->traceframe_count >= 0)
{
printf_filtered (_("Collected %d trace frames.\n"),
ts->traceframe_count);
}
- if (ts->buffer_free)
+ if (ts->buffer_free >= 0)
{
- printf_filtered (_("Trace buffer has %llu bytes free.\n"),
- ts->buffer_free);
+ if (ts->buffer_size >= 0)
+ {
+ printf_filtered (_("Trace buffer has %d bytes of %d bytes free"),
+ ts->buffer_free, ts->buffer_size);
+ if (ts->buffer_size > 0)
+ printf_filtered (_(" (%d%% full)"),
+ ((int) ((((long long) (ts->buffer_size
+ - ts->buffer_free)) * 100)
+ / ts->buffer_size)));
+ printf_filtered (_(".\n"));
+ }
+ else
+ printf_filtered (_("Trace buffer has %d bytes free.\n"),
+ ts->buffer_free);
}
/* Now report on what we're doing with tfind. */
fprintf (fp, "R %x\n", trace_regblock_size);
/* Write out status of the tracing run (aka "tstatus" info). */
- fprintf (fp, "status %c;%s:%x;tframes:%x;tfree:%llx\n",
+ fprintf (fp, "status %c;%s:%x",
(ts->running ? '1' : '0'),
- stop_reason_names[ts->stop_reason], ts->stopping_tracepoint,
- ts->traceframe_count, ts->buffer_free);
+ stop_reason_names[ts->stop_reason], ts->stopping_tracepoint);
+ if (ts->traceframe_count >= 0)
+ fprintf (fp, ";tframes:%x", ts->traceframe_count);
+ if (ts->traceframes_created >= 0)
+ fprintf (fp, ";tcreated:%x", ts->traceframes_created);
+ if (ts->buffer_free >= 0)
+ fprintf (fp, ";tfree:%x", ts->buffer_free);
+ if (ts->buffer_size >= 0)
+ fprintf (fp, ";tsize:%x", ts->buffer_size);
+ fprintf (fp, "\n");
/* Note that we want to upload tracepoints and save those, rather
than simply writing out the local ones, because the user may have
send_disconnected_tracing_value (disconnected_tracing);
}
+static void
+set_circular_trace_buffer (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ target_set_circular_trace_buffer (circular_trace_buffer);
+}
+
/* 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
ts->running_known = 1;
ts->running = (*p++ == '1');
ts->stop_reason = trace_stop_reason_unknown;
+ ts->traceframe_count = -1;
+ ts->traceframes_created = -1;
+ ts->buffer_free = -1;
+ ts->buffer_size = -1;
+
while (*p++)
{
p1 = strchr (p, ':');
p = unpack_varlen_hex (++p1, &val);
ts->stop_reason = tstop_command;
}
- if (strncmp (p, "tframes", p1 - p) == 0)
+ else if (strncmp (p, "tframes", p1 - p) == 0)
{
p = unpack_varlen_hex (++p1, &val);
ts->traceframe_count = val;
}
- if (strncmp (p, "tfree", p1 - p) == 0)
+ else if (strncmp (p, "tcreated", p1 - p) == 0)
+ {
+ p = unpack_varlen_hex (++p1, &val);
+ ts->traceframes_created = val;
+ }
+ else if (strncmp (p, "tfree", p1 - p) == 0)
{
p = unpack_varlen_hex (++p1, &val);
ts->buffer_free = val;
}
+ else if (strncmp (p, "tsize", p1 - p) == 0)
+ {
+ p = unpack_varlen_hex (++p1, &val);
+ ts->buffer_size = val;
+ }
else
{
/* Silently skip unknown optional info. */
&setlist,
&showlist);
+ add_setshow_boolean_cmd ("circular-trace-buffer", no_class,
+ &circular_trace_buffer, _("\
+Set target's use of circular trace buffer."), _("\
+Show target's use of circular trace buffer."), _("\
+Use this to make the trace buffer into a circular buffer,\n\
+which will discard traceframes (oldest first) instead of filling\n\
+up and stopping the trace run."),
+ set_circular_trace_buffer,
+ NULL,
+ &setlist,
+ &showlist);
+
init_tfile_ops ();
add_target (&tfile_ops);
int stopping_tracepoint;
+ /* Number of traceframes currently in the buffer. */
+
int traceframe_count;
- unsigned long long buffer_size;
+ /* Number of traceframes created since start of run. */
+
+ int traceframes_created;
+
+ /* Total size of the target's trace buffer. */
+
+ int buffer_size;
+
+ /* Unused bytes left in the target's trace buffer. */
- unsigned long long buffer_free;
+ int buffer_free;
};
struct trace_status *current_trace_status (void);