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. * gdb.texinfo (Starting and Stopping Trace Experiments): Describe circular-trace-buffer. (Tracepoint Packets): Describe QTBuffer, and details of the qTStatus reply. * gdb.trace/circ.exp: Test circular-trace-buffer. * gdb.trace/tfile.exp: Update tstatus test.
This commit is contained in:
parent
576ee33af3
commit
4daf5ac07e
@ -1,3 +1,29 @@
|
||||
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
|
||||
|
19
gdb/NEWS
19
gdb/NEWS
@ -114,7 +114,14 @@ Renesas RX rx
|
||||
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
|
||||
@ -215,6 +222,13 @@ show disconnected-tracing
|
||||
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
|
||||
@ -258,6 +272,9 @@ qTV
|
||||
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.
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
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>
|
||||
|
||||
|
@ -9836,6 +9836,37 @@ which to specify that tracepoint. This matching-up process is
|
||||
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
|
||||
|
||||
@ -30603,6 +30634,7 @@ encoded). @value{GDBN} will continue to supply the values of symbols
|
||||
@end table
|
||||
|
||||
@item qTBuffer
|
||||
@item QTBuffer
|
||||
@item QTDisconnected
|
||||
@itemx QTDP
|
||||
@itemx QTDV
|
||||
@ -31087,12 +31119,62 @@ continue the tracing run, while 0 tells the target to stop tracing if
|
||||
@item qTStatus
|
||||
Ask the stub if there is a trace experiment running right now.
|
||||
|
||||
Replies:
|
||||
The reply has the form:
|
||||
|
||||
@table @samp
|
||||
@item T0
|
||||
There is no trace experiment running.
|
||||
@item T1
|
||||
There is a trace experiment running.
|
||||
|
||||
@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 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}
|
||||
@ -31147,6 +31229,10 @@ in a packet; it is not an error to return fewer than were asked for.
|
||||
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
|
||||
|
13
gdb/remote.c
13
gdb/remote.c
@ -9658,6 +9658,18 @@ remote_core_of_thread (struct target_ops *ops, ptid_t ptid)
|
||||
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)
|
||||
{
|
||||
@ -9736,6 +9748,7 @@ Specify the serial device it is connected to\n\
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -659,6 +659,7 @@ update_current_target (void)
|
||||
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. */
|
||||
@ -848,7 +849,10 @@ update_current_target (void)
|
||||
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
|
||||
|
@ -664,6 +664,7 @@ struct target_ops
|
||||
/* 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:
|
||||
@ -1359,6 +1360,9 @@ extern int target_search_memory (CORE_ADDR start_addr,
|
||||
#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) \
|
||||
|
@ -1,3 +1,8 @@
|
||||
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.
|
||||
|
@ -197,6 +197,15 @@ gdb_load $binfile
|
||||
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
|
||||
|
@ -78,8 +78,8 @@ gdb_test "tfind" "Target failed to find requested trace frame." \
|
||||
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"
|
||||
|
||||
|
@ -153,6 +153,11 @@ char *default_collect = "";
|
||||
|
||||
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);
|
||||
@ -1579,6 +1584,9 @@ trace_start_command (char *args, int from_tty)
|
||||
|
||||
/* 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 ();
|
||||
@ -1668,16 +1676,34 @@ trace_status_command (char *args, int from_tty)
|
||||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
@ -2438,10 +2464,18 @@ trace_save_command (char *args, int from_tty)
|
||||
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
|
||||
@ -2546,6 +2580,13 @@ set_disconnected_tracing (char *args, int from_tty,
|
||||
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
|
||||
@ -3059,6 +3100,11 @@ parse_trace_status (char *line, struct trace_status *ts)
|
||||
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, ':');
|
||||
@ -3086,16 +3132,26 @@ Status line: '%s'\n"), p, line);
|
||||
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. */
|
||||
@ -3819,6 +3875,18 @@ trace data collected in the meantime."),
|
||||
&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);
|
||||
|
@ -95,11 +95,21 @@ struct trace_status
|
||||
|
||||
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. */
|
||||
|
||||
unsigned long long buffer_free;
|
||||
int traceframes_created;
|
||||
|
||||
/* Total size of the target's trace buffer. */
|
||||
|
||||
int buffer_size;
|
||||
|
||||
/* Unused bytes left in the target's trace buffer. */
|
||||
|
||||
int buffer_free;
|
||||
};
|
||||
|
||||
struct trace_status *current_trace_status (void);
|
||||
|
Loading…
Reference in New Issue
Block a user