12.2. Using the collected data

After the tracepoint experiment ends, you use gdb commands for examining the trace data. The basic idea is that each tracepoint collects a trace snapshot every time it is hit and another snapshot every time it single-steps. All these snapshots are consecutively numbered from zero and go into a buffer, and you can examine them later. The way you examine them is to focus on a specific trace snapshot. When the remote stub is focused on a trace snapshot, it will respond to all gdb requests for memory and registers by reading from the buffer which belongs to that snapshot, rather than from real memory or registers of the program being debugged. This means that all gdb commands (print, info registers, backtrace, etc.) will behave as if we were currently debugging the program state as it was when the tracepoint occurred. Any requests for data that are not in the buffer will fail.

12.2.1. tfind n

The basic command for selecting a trace snapshot from the buffer is tfind n, which finds trace snapshot number n, counting from zero. If no argument n is given, the next snapshot is selected.

Here are the various forms of using the tfind command.

tfind start

Find the first snapshot in the buffer. This is a synonym for tfind 0 (since 0 is the number of the first snapshot).

tfind none

Stop debugging trace snapshots, resume live debugging.

tfind end

Same as tfind none.

tfind

No argument means find the next trace snapshot.

tfind -

Find the previous trace snapshot before the current one. This permits retracing earlier steps.

tfind tracepoint num

Find the next snapshot associated with tracepoint num. Search proceeds forward from the last examined trace snapshot. If no argument num is given, it means find the next snapshot collected for the same tracepoint as the current snapshot.

tfind pc addr

Find the next snapshot associated with the value addr of the program counter. Search proceeds forward from the last examined trace snapshot. If no argument addr is given, it means find the next snapshot with the same value of PC as the current snapshot.

tfind outside addr1, addr2

Find the next snapshot whose PC is outside the given range of addresses.

tfind range addr1, addr2

Find the next snapshot whose PC is between addr1 and addr2.

tfind line [file:]n

Find the next snapshot associated with the source line n. If the optional argument file is given, refer to line n in that source file. Search proceeds forward from the last examined trace snapshot. If no argument n is given, it means find the next line other than the one currently being examined; thus saying tfind line repeatedly can appear to have the same effect as stepping from line to line in a live debugging session.

The default arguments for the tfind commands are specifically designed to make it easy to scan through the trace buffer. For instance, tfind with no argument selects the next trace snapshot, and tfind - with no argument selects the previous trace snapshot. So, by giving one tfind command, and then simply hitting [RET] repeatedly you can examine all the trace snapshots in order. Or, by saying tfind - and then hitting [RET] repeatedly you can examine the snapshots in reverse order. The tfind line command with no argument selects the snapshot for the next source line executed. The tfind pc command with no argument selects the next snapshot with the same program counter (PC) as the current frame. The tfind tracepoint command with no argument selects the next trace snapshot collected by the same tracepoint as the current one.

In addition to letting you scan through the trace buffer manually, these commands make it easy to construct gdb scripts that scan through the trace buffer and print out whatever collected data you are interested in. Thus, if we want to examine the PC, FP, and SP registers from each trace frame in the buffer, we can say this:

(gdb) tfind start
(gdb) while ($trace_frame != -1)
> printf "Frame %d, PC = %08X, SP = %08X, FP = %08X\n", \
          $trace_frame, $pc, $sp, $fp
> tfind
> end

Frame 0, PC = 0020DC64, SP = 0030BF3C, FP = 0030BF44
Frame 1, PC = 0020DC6C, SP = 0030BF38, FP = 0030BF44
Frame 2, PC = 0020DC70, SP = 0030BF34, FP = 0030BF44
Frame 3, PC = 0020DC74, SP = 0030BF30, FP = 0030BF44
Frame 4, PC = 0020DC78, SP = 0030BF2C, FP = 0030BF44
Frame 5, PC = 0020DC7C, SP = 0030BF28, FP = 0030BF44
Frame 6, PC = 0020DC80, SP = 0030BF24, FP = 0030BF44
Frame 7, PC = 0020DC84, SP = 0030BF20, FP = 0030BF44
Frame 8, PC = 0020DC88, SP = 0030BF1C, FP = 0030BF44
Frame 9, PC = 0020DC8E, SP = 0030BF18, FP = 0030BF44
Frame 10, PC = 00203F6C, SP = 0030BE3C, FP = 0030BF14

Or, if we want to examine the variable X at each source line in the buffer:

(gdb) tfind start
(gdb) while ($trace_frame != -1)
> printf "Frame %d, X == %d\n", $trace_frame, X
> tfind line
> end

Frame 0, X = 1
Frame 7, X = 2
Frame 13, X = 255

12.2.2. tdump

This command takes no arguments. It prints all the data collected at the current trace snapshot.

(gdb) trace 444
(gdb) actions
Enter actions for tracepoint #2, one per line:
> collect $regs, $locals, $args, gdb_long_test
> end

(gdb) tstart

(gdb) tfind line 444
#0  gdb_test (p1=0x11, p2=0x22, p3=0x33, p4=0x44, p5=0x55, p6=0x66)
at gdb_test.c:444
444        printp( "%s: arguments = 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", )

(gdb) tdump
Data collected at tracepoint 2, trace frame 1:
d0             0xc4aa0085       -995491707
d1             0x18     24
d2             0x80     128
d3             0x33     51
d4             0x71aea3d        119204413
d5             0x22     34
d6             0xe0     224
d7             0x380035 3670069
a0             0x19e24a 1696330
a1             0x3000668        50333288
a2             0x100    256
a3             0x322000 3284992
a4             0x3000698        50333336
a5             0x1ad3cc 1758156
fp             0x30bf3c 0x30bf3c
sp             0x30bf34 0x30bf34
ps             0x0      0
pc             0x20b2c8 0x20b2c8
fpcontrol      0x0      0
fpstatus       0x0      0
fpiaddr        0x0      0
p = 0x20e5b4 "gdb-test"
p1 = (void *) 0x11
p2 = (void *) 0x22
p3 = (void *) 0x33
p4 = (void *) 0x44
p5 = (void *) 0x55
p6 = (void *) 0x66
gdb_long_test = 17 '\021'

(gdb)

12.2.3. save-tracepoints filename

This command saves all current tracepoint definitions together with their actions and passcounts, into a file filename suitable for use in a later debugging session. To read the saved tracepoint definitions, use the source command (refer to Section 22.3 Command files).