分类: C/C++
2008-12-29 14:02:13
Some program behaviors can be analyzed only by collecting data over long periods of time for later analysis. Other problems occur in sections of code that are too time-sensative to be debugged interactively. In these cases, tracing may be more appropriate than breakpoint debugging.
This section discusses the following topics.
Like a breakpoint, a tracepoint makes your program stop whenever a certain point in the program is reached. However, while a breakpoint stops the program for a "long" time (while GDB prompts you and lets you type commands), a tracepoint stops the program for only a "short" time, after which the program gets to continue with minimal disruption of its behavior. During this "short" interval, the trace mechanism records the fact that it has been there (ie. that the tracepoint was executed), and may also perform certain actions that you've requested such as recording the values of selected variables and registers. Thus it's not well defined how long a "short" time is, but in any event it will be thousands of times shorter than the time required for a human to do the same tasks interactively.
As with breakpoints, GDB assigns a number to each tracepoint when you create it. Like breakpoint numbers, tracepoint numbers are successive integers starting from one. Many of the commands associated with tracepoints use the tracepoint number to identify which tracepoint to delete, disable, etc.
A trace experiment must involve each of the following steps: defining the tracepoints and actions, running the experiment, and reviewing the results. Many of the commands defined below (such as setting and deleting tracepoints) have no real effect until you actually begin running the trace experiment. Moreover, many of them also have no effect during an already running trace experiment. Once a trace experiment is running, changing the tracepoints or their attributes will have no effect unles you stop the experiment and start it again.
Tracepoints are set with the trace command (abbreviated tr). The debugger convenience variable '$tpnum' records the tracepoint number of the most recently set tracepoint; see for a discussion of what you can do with convenience variables.
The location of a tracepoint can be specified in exactly the same ways as the location of a breakpoint, here reproduced for convenience.
Some programming languages (notably C++) permit a single function name to be defined several times, for application in different contexts. This is called overloading. Tracepoints on overloaded functions behave exactly like breakpoints do (see "Breakpoint menus" in the GDB manual (available at )). Any tracepoint's definition can be permanently discarded using the delete tracepoint command (abbreviated del tr). Give the tracepoint number(s) of the tracepoint(s) that you want to delete. A deleted tracepoint no longer exists, in contrast with a disabled tracepoint (which can be re-enabled). Use the info tracepoints command to discover the numbers of your tracepoints.
NOTE: this command has no effect on a running trace experiment.
NOTE: these commands have no effect on a running trace experiment.
Any number of tracepoints may have passcounts of any integer value. When the first tracepoint reaches its passcount, the trace experiment will terminate.
To clear a passcount, set it to zero.
NOTE: this command has no effect on a running trace experiment.
The actions at a tracepoint may also include single-stepping for some number of machine instructions, collecting data at each step. In this mode you can collect the changes in registers or variables over a range of instructions.
Here are the commands for defining the actions for a tracepoint.
end
Specify a list of actions for tracepoint number tpnum. The actions themselves appear on the following lines. Type a line containing just end to terminate the actions. To remove all actions from a tracepoint, type actions [tpnum] and follow it immediately with end; that is, give no actions. With no tpnum argument, actions refers to the last tracepoint set.
while-stepping <n>
collect [exprs]
end
After collecting any data requested at the tracepoint itself, execute <n> machine instructions, collecting the following expressions after each instruction. Each step will generate a separate trace event in the trace buffer (see ).
NOTE: these commands have no effect on a running trace experiment.
Use this command to list all existing tracepoints and their attributes.You start and stop trace collection by using the tstart and tstop commands.
NOTE: trace data collection may also be stopped automatically if any tracepoint's passcount is reached. It may also stop automatically if the trace buffer becomes full, unles the trace buffer is set to operate in a continuous "circular buffer" mode.
Note also that starting trace collection has the side effect of discarding any old trace data in the buffer, so that the buffer starts out empty each time. You may stop a trace experiment and still look at your saved data, but as soon as you start a new trace experiment, the previously collected data will be irretrievably gone.
While a trace experiment is running, every time a tracepoint is executed generates a trace event, and every trace event generates a data record called a trace frame in a buffer called the trace buffer. If a tracepoint's actions include single-stepping, each single-step also generates a trace event and a trace frame.Each trace frame has a sequential identifying number starting from zero, plus the address (PC) of the event. In addition, the trace frame contains any values collected by the actions for the corresponding tracepoint.
The basic commands for selecting a trace frame and extracting data from it are tfind and tdump. In addition, several built-in GDB variables are provided for identifying the currently selected trace frame.
However, many people find that the most useful way to review the collected data is interactively. Whenever you use the tfind command, GDB displays the source line corresponding to the selected trace frame, just as if you had stepped to that line or hit a breakpoint there. The next tfind command takes you to the next source line, very much like stepping. At each trace frame, you can use all of the customary GDB commands to examine the data collected, very much as you could if you were sitting at a breakpoint, except that you can only examine values that you collected earlier by listing them in the action lists of your tracepoints.
Once you have defined a set of tracepoints and actions, you may want to save them to be used later in another debug session. The save-trace command saves all tracepoints, passcounts and actions as a GDB command file, which can be imported later by using the source command (See "Command files" in the GDB manual (available at )).