1. Build with the 'simple' trace backend:
- ./configure --trace-backend=simple
+ ./configure --enable-trace-backend=simple
make
2. Create a file with the events you want to trace:
4. Pretty-print the binary trace file:
- ./simpletrace.py trace-events trace-*
+ ./scripts/simpletrace.py trace-events trace-*
== Trace events ==
file. Each trace event declaration names the event, its arguments, and the
format string which can be used for pretty-printing:
- qemu_malloc(size_t size, void *ptr) "size %zu ptr %p"
- qemu_free(void *ptr) "ptr %p"
+ qemu_vmalloc(size_t size, void *ptr) "size %zu ptr %p"
+ qemu_vfree(void *ptr) "ptr %p"
The "trace-events" file is processed by the "tracetool" script during build to
generate code for the trace events. Trace events are invoked directly from
#include "trace.h" /* needed for trace event prototype */
- void *qemu_malloc(size_t size)
+ void *qemu_vmalloc(size_t size)
{
void *ptr;
- if (!size && !allow_zero_malloc()) {
- abort();
+ size_t align = QEMU_VMALLOC_ALIGN;
+
+ if (size < align) {
+ align = getpagesize();
}
- ptr = oom_check(malloc(size ? size : 1));
- trace_qemu_malloc(size, ptr); /* <-- trace event */
+ ptr = qemu_memalign(align, size);
+ trace_qemu_vmalloc(size, ptr);
return ptr;
}
cannot include all user-defined struct declarations and it is therefore
necessary to use void * for pointers to structs.
- Pointers (including char *) cannot be dereferenced easily (or at all) in
- some trace backends. If pointers are used, ensure they are meaningful by
- themselves and do not assume the data they point to will be traced. Do
- not pass in string arguments.
-
* For everything else, use primitive scalar types (char, int, long) with the
appropriate signedness.
4. Name trace events after their function. If there are multiple trace events
in one function, append a unique distinguisher at the end of the name.
-5. If specific trace events are going to be called a huge number of times, this
- might have a noticeable performance impact even when the trace events are
- programmatically disabled. In this case you should declare the trace event
- with the "disable" property, which will effectively disable it at compile
- time (using the "nop" backend).
-
== Generic interface and monitor commands ==
You can programmatically query and control the dynamic state of trace events
means disabled.
* trace-event NAME on|off
- Enable/disable a given trace event.
+ Enable/disable a given trace event or a group of events having common prefix
+ through wildcard.
The "-trace events=<file>" command line argument can be used to enable the
events listed in <file> from the very beginning of the program. This file must
contain one event name per line.
+A basic wildcard matching is supported in both the monitor command "trace
+-event" and the events list file. That means you can enable/disable the events
+having a common prefix in a batch. For example, virtio-blk trace events could
+be enabled using:
+ trace-event virtio_blk_* on
+
+If a line in the "-trace events=<file>" file begins with a '-', the trace event
+will be disabled instead of enabled. This is useful when a wildcard was used
+to enable an entire family of events but one noisy event needs to be disabled.
+
== Trace backends ==
The "tracetool" script automates tedious trace event code generation and also
trace backends but it is portable. This is the recommended trace backend
unless you have specific needs for more advanced backends.
-==== Monitor commands ====
-
-* info trace
- Display the contents of trace buffer. This command dumps the trace buffer
- with simple formatting. For full pretty-printing, use the simpletrace.py
- script on a binary trace file.
+The "simple" backend currently does not capture string arguments, it simply
+records the char* pointer value instead of the string that is pointed to.
- The trace buffer is written into until full. The full trace buffer is
- flushed and emptied. This means the 'info trace' will display few or no
- entries if the buffer has just been flushed.
+==== Monitor commands ====
* trace-file on|off|flush|set <path>
Enable/disable/flush the trace file or set the trace file name.
simpletrace.py script. The script takes the "trace-events" file and the binary
trace:
- ./simpletrace.py trace-events trace-12345
+ ./scripts/simpletrace.py trace-events trace-12345
You must ensure that the same "trace-events" file was used to build QEMU,
otherwise trace event declarations may have changed and output will not be
--target-type system \
--target-arch x86_64 \
<trace-events >qemu.stp
+
+== Trace event properties ==
+
+Each event in the "trace-events" file can be prefixed with a space-separated
+list of zero or more of the following event properties.
+
+=== "disable" ===
+
+If a specific trace event is going to be invoked a huge number of times, this
+might have a noticeable performance impact even when the event is
+programmatically disabled.
+
+In this case you should declare such event with the "disable" property. This
+will effectively disable the event at compile time (by using the "nop" backend),
+thus having no performance impact at all on regular builds (i.e., unless you
+edit the "trace-events" file).
+
+In addition, there might be cases where relatively complex computations must be
+performed to generate values that are only used as arguments for a trace
+function. In these cases you can use the macro 'TRACE_${EVENT_NAME}_ENABLED' to
+guard such computations and avoid its compilation when the event is disabled:
+
+ #include "trace.h" /* needed for trace event prototype */
+
+ void *qemu_vmalloc(size_t size)
+ {
+ void *ptr;
+ size_t align = QEMU_VMALLOC_ALIGN;
+
+ if (size < align) {
+ align = getpagesize();
+ }
+ ptr = qemu_memalign(align, size);
+ if (TRACE_QEMU_VMALLOC_ENABLED) { /* preprocessor macro */
+ void *complex;
+ /* some complex computations to produce the 'complex' value */
+ trace_qemu_vmalloc(size, ptr, complex);
+ }
+ return ptr;
+ }