This is the mail archive of the
mailing list for the GDB project.
Proposed tracepoint enhancements, general spec
- From: Stan Shebs <stan at codesourcery dot com>
- To: "gdb at sourceware dot org" <gdb at sourceware dot org>
- Date: Mon, 26 Jan 2009 10:34:33 -0800
- Subject: Proposed tracepoint enhancements, general spec
The general specification presumes one already has some familiarity with
the concept, and focusses more on specific things we plan to do,
including protocol and other internal changes. As with the manual
chapter, feedback is most welcome.
Tracepoint Enhancements for GDB
Stan Shebs, CodeSourcery
This is a general specification for enhancements to tracing support
It comes in four main parts: 1) updates and changes to user commands
(CLI), 2) the definition of MI commands, 3) the definition of protocol
changes, and 4) the definition of file format for trace data.
*** Concepts ***
Tracepoints have in the past been treated as their own type of object,
assigned their own space of small integers, managed with separate
commands, and so forth. Tracepoints will become a special type of
breakpoint, which means that tracepoints will share their "number
space" with breakpoints, watchpoints, catchpoints, and so forth. It
also means that many of the existing breakpoint-handling commands can
be used for tracepoints.
Trace state variables are a special class of variables that are
created and managed by target-side code. Their syntax is the same as
that for GDB's convenience variables (a string prefixed with "$"), but
they are stored on the target. They are created implicitly by being
assigned to in conditional and action expressions, or explicitly by
using a "tvariable" command. They are always signed integers, and
always updated in a thread-safe manner. One trace state variable,
$trace_timestamp, is always defined, and is a timestamp captured when
the tracepoint triggered. (The time units are system-specific and not
defined by this spec.)
The allowed expressions in conditions and actions will include
additional types of constructs, namely logical operations,
comparisons, comma, conditional, and assignments. By default,
assignment to registers and target memory is not allowed.
*** Commands ***
** Trace Commands **
trace <sourcepos> [ if <expr> ]
The "trace" command creates tracepoints as presently. It may be
followed with a conditional expression, as in "trace foo.c:24 if x <
0" . (See below for tracepoint conditions.)
ftrace <sourcepos> [ if <expr> ]
The "ftrace" command creates a fast tracepoint. It may not be possible
to create a fast tracepoint at the desired location, in which case the
command will return an error. (The regular trace command may also
create fast tracepoints, at its discretion.) The command may be
condition <num> <expr>
The "condition" command will accept tracepoints in addition to
breakpoints. However, unlike breakpoint conditions, a tracepoint
condition will work by being translated into the form of agent
expression bytecodes, and stored on the target with the rest of the
tracepoint information. The target's stub will evaluate the
expression each time the tracepoint is reached, and will only run the
tracepoint's actions when the expression yields a nonzero value.
Unlike breakpoint conditions, which are evaluated by GDB, tracepoint
conditions are computed and tested only on the target, with no GDB
interaction. This means that any values stored in GDB, such as
convenience variables, will be evaluated once before a trace
experiment and effectively handled as constants during that run.
For instance, suppose the user did the following command:
(gdb) print a->x->y
$45 = 0x43218964
(gdb) trace foo.c:24 if *$45 > 0
defines a tracepoint that will only be hit if the value of memory at
address 0x43218964 is positive.
The "delete tracepoint" command is superseded by the normal "delete"
The "disable tracepoint" command is superseded by the normal "disable"
The "enable tracepoint" command is superseded by the normal "enable"
The "actions" command gains an additional action "do". Its syntax is
"do expr1, expr2, ..." . It simply evaluates each expression, and
ignores the result; its purpose is to support the setting of trace
state variables without having to collect anything. A tracepoint
whose actions are only "do"s will not have any record of being hit
(but note that default-collect, below, may implicitly add data to be
set default-collect <expr1>,<expr2>,...
The "default-collect" variable is a list of expressions to collect by
default at every tracepoint hit. The value of this variable is parsed
and sent to the target at the start of a tracing experiment and
subsequently has the effect of a collect action run before any other
actions in the tracepoint's actions list.
tvariable <name> [ = <expr> ]
The "tvariable" command creates a new trace state variable named
<name> and optionally gives it an initial value computed by evaluating
<expr>. <expr> is evaluated immediately, and the command reports an
error if the value is not an integer. Subsequent "tvariable" commands
using the same <name> just set it to new values.
The "info tvariables" command lists all of the trace state variables
along with their initial values.
The "info tracepoints" command is superseded by the "info breakpoints"
command. The tracepoint condition is displayed just as for breakpoint
conditions, while the action list follows, similarly to a breakpoint's
The "tstart" and "tstop" commands start and stop the tracing
experiment, respectively. When the "tstart" command is given,
tracepoint conditions and actions are compiled into sequences of
bytecodes that the target will interpret, the tracepoint definitions
and trace state variables are downloaded. Then the target-side code
installs traps and/or jump instructions into the program. Although at
this point, the tracepoints may start being hit (since they are being
inserted one at a time), they are all handled as if they were
disabled; only after all tracepoints have been installed can a hit
result in the tracepoint's actions being run.
Once started, the tracing experiment runs independently of GDB's
normal debugging behavior; the program may be continued, stepped, etc,
while tracing is active. The results of collecting program variables
while also modifying them from GDB is undefined.
In addition, tracing will continue even if GDB disconnects from the
target (GDB may request confirmation, however). Additional "tstart"
commands may be given after a trace experiment has started; the effect
is to add or remove any tracepoints that were defined or removed since
the previous "tstart" command.
set circular-trace-buffer <on/off>
The variable "circular-trace-buffer" determines whether the trace
buffer may fill up and end the trace experiment, or may erase old
entries in order to make space for new ones. Note that a large trace
entry may require the deletion of multiple existing entries in order
to make room.
target tfile <filename>
The "target tfile" command instructs GDB to use <filename> as a source
of trace data. The user will then use "tfind" commands as usual to select
particular snapshots. The format of the file is defined below.
*** MI ***
The MI is augmented so as to enable the use of tracepoints from the Eclipse IDE.
The '-break-commands' command will be implemented. The syntax is:
-break-commands <trace/breakpoint number> <command 1> <command 2> ...
The commands may contain only 'do', 'collect', 'while-stepping', and 'end'.
The '-trace-data-find' command accept the same parameters are the CLI
'tfind' command. After this command, GUI is supposed to update all the
state (including frame, threads, and -var-update). For anything that
cannot be obtained, GDB will report an error of the form:
"Information unavailable in the selected tracepoint"
The response for the -trace-data-find is in the form:
The '-trace-data-save' command accepts a filename, and saves all data
there. If filename is "-i" returns a raw string.
*** Remote Protocol ***
** Packets **
The basic tracepoint creation packet gets additional optional fields,
of which the first is the desired type (fast/slow/etc), and the second
is the tracepoint condition, encoded in agent expression bytecodes.
Ask the stub for all the tracepoints it knows about. This is used when
reconnecting to a target; the format of the returned data is the same
as sent by QTDP.
This tells the stub what it is allowed to do; <action> is ReadReg,
WriteReg, ReadMem, WriteMem, etc, while <value> is 0 or 1. (This
packet may not be necessary if the stub is known to not manipulate
registers or memory on its own initiative.)
** Bytecodes **
Logical operations, comparisons, conditional expressions, and the
comma operator can all be implemented using the existing collection of
Pop the number of a trace state variable from the stack, and assign to
it the value now at the top of the stack.
*** Trace File ***
A file of trace data begins with the byte 0x7f (to indicate that it
includes some binary data), followed by the chararacters
'TRACE\n'. Each tracepoint is then listed, with its properties
recorded in ASCII, followed by runs of trace frames, which are
recorded as raw binary assumsing the endianness of the target
Each tracepoint record has the form
where <cond> and <actions> are hex dumps of the agent expression
Groups of trace frames are introduced with two 16-bit words, of which
the first is a tracepoint <num>, followed by a count of frames
following. Each trace frame consists of the raw data as collected
by its tracepoint.
The end of the file is signified with a 32-bit word of all zeros.