]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/tracetool
docs/tracing.txt: minor documentation fixes
[mirror_qemu.git] / scripts / tracetool
CommitLineData
94a420b1
SH
1#!/bin/sh
2#
3# Code generator for trace events
4#
5# Copyright IBM, Corp. 2010
6#
7# This work is licensed under the terms of the GNU GPL, version 2. See
8# the COPYING file in the top-level directory.
9
10# Disable pathname expansion, makes processing text with '*' characters simpler
11set -f
12
13usage()
14{
15 cat >&2 <<EOF
320fba2a 16usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
94a420b1
SH
17Generate tracing code for a file on stdin.
18
19Backends:
26f7227b
SH
20 --nop Tracing disabled
21 --simple Simple built-in backend
320fba2a 22 --stderr Stderr built-in backend
7e24e92a 23 --ust LTTng User Space Tracing backend
b3d08c02 24 --dtrace DTrace/SystemTAP backend
94a420b1
SH
25
26Output formats:
c276b17d
DB
27 -h Generate .h file
28 -c Generate .c file
29 -d Generate .d file (DTrace only)
30 --stap Generate .stp file (DTrace with SystemTAP only)
31
32Options:
e323c93e
JS
33 --binary [path] Full path to QEMU binary
34 --target-arch [arch] QEMU emulator target arch
35 --target-type [type] QEMU emulator target type ('system' or 'user')
36 --probe-prefix [prefix] Prefix for dtrace probe names
37 (default: qemu-\$targettype-\$targetarch)
c276b17d 38
94a420b1
SH
39EOF
40 exit 1
41}
42
43# Get the name of a trace event
44get_name()
45{
46 echo ${1%%\(*}
47}
48
49# Get the argument list of a trace event, including types and names
50get_args()
51{
52 local args
53 args=${1#*\(}
1a96dd47 54 args=${args%%\)*}
94a420b1
SH
55 echo "$args"
56}
57
58# Get the argument name list of a trace event
59get_argnames()
60{
b3d08c02 61 local nfields field name sep
94a420b1 62 nfields=0
b3d08c02 63 sep="$2"
94a420b1
SH
64 for field in $(get_args "$1"); do
65 nfields=$((nfields + 1))
66
67 # Drop pointer star
68 field=${field#\*}
69
70 # Only argument names have commas at the end
71 name=${field%,}
72 test "$field" = "$name" && continue
73
b3d08c02 74 printf "%s%s " $name $sep
94a420b1
SH
75 done
76
77 # Last argument name
78 if [ "$nfields" -gt 1 ]
79 then
80 printf "%s" "$name"
81 fi
82}
83
26f7227b
SH
84# Get the number of arguments to a trace event
85get_argc()
86{
87 local name argc
88 argc=0
b3d08c02 89 for name in $(get_argnames "$1", ","); do
26f7227b
SH
90 argc=$((argc + 1))
91 done
92 echo $argc
93}
94
94a420b1
SH
95# Get the format string for a trace event
96get_fmt()
97{
98 local fmt
99 fmt=${1#*\"}
100 fmt=${fmt%\"*}
101 echo "$fmt"
102}
103
1e2cf2bc
SH
104# Get the state of a trace event
105get_state()
106{
107 local str disable state
108 str=$(get_name "$1")
109 disable=${str##disable }
110 if [ "$disable" = "$str" ] ; then
111 state=1
112 else
113 state=0
114 fi
115 echo "$state"
116}
117
94a420b1
SH
118linetoh_begin_nop()
119{
120 return
121}
122
123linetoh_nop()
124{
125 local name args
126 name=$(get_name "$1")
127 args=$(get_args "$1")
128
129 # Define an empty function for the trace event
130 cat <<EOF
131static inline void trace_$name($args)
132{
133}
134EOF
135}
136
137linetoh_end_nop()
138{
139 return
140}
141
142linetoc_begin_nop()
143{
144 return
145}
146
147linetoc_nop()
148{
149 # No need for function definitions in nop backend
150 return
151}
152
153linetoc_end_nop()
154{
155 return
156}
157
26f7227b
SH
158linetoh_begin_simple()
159{
160 cat <<EOF
161#include "simpletrace.h"
162EOF
163
164 simple_event_num=0
165}
166
167cast_args_to_uint64_t()
168{
169 local arg
b3d08c02 170 for arg in $(get_argnames "$1", ","); do
26f7227b
SH
171 printf "%s" "(uint64_t)(uintptr_t)$arg"
172 done
173}
174
175linetoh_simple()
176{
1e2cf2bc 177 local name args argc trace_args state
26f7227b
SH
178 name=$(get_name "$1")
179 args=$(get_args "$1")
180 argc=$(get_argc "$1")
1e2cf2bc
SH
181 state=$(get_state "$1")
182 if [ "$state" = "0" ]; then
183 name=${name##disable }
184 fi
26f7227b
SH
185
186 trace_args="$simple_event_num"
187 if [ "$argc" -gt 0 ]
188 then
189 trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
190 fi
191
192 cat <<EOF
193static inline void trace_$name($args)
194{
195 trace$argc($trace_args);
196}
197EOF
198
199 simple_event_num=$((simple_event_num + 1))
200}
201
202linetoh_end_simple()
203{
22890ab5
PS
204 cat <<EOF
205#define NR_TRACE_EVENTS $simple_event_num
206extern TraceEvent trace_list[NR_TRACE_EVENTS];
207EOF
26f7227b
SH
208}
209
210linetoc_begin_simple()
211{
22890ab5
PS
212 cat <<EOF
213#include "trace.h"
214
215TraceEvent trace_list[] = {
216EOF
217 simple_event_num=0
218
26f7227b
SH
219}
220
221linetoc_simple()
222{
1e2cf2bc 223 local name state
22890ab5 224 name=$(get_name "$1")
1e2cf2bc
SH
225 state=$(get_state "$1")
226 if [ "$state" = "0" ] ; then
227 name=${name##disable }
228 fi
22890ab5 229 cat <<EOF
1e2cf2bc 230{.tp_name = "$name", .state=$state},
22890ab5
PS
231EOF
232 simple_event_num=$((simple_event_num + 1))
26f7227b
SH
233}
234
235linetoc_end_simple()
236{
22890ab5
PS
237 cat <<EOF
238};
239EOF
26f7227b
SH
240}
241
320fba2a
FC
242#STDERR
243linetoh_begin_stderr()
244{
245 cat <<EOF
246#include <stdio.h>
247EOF
248}
249
250linetoh_stderr()
251{
252 local name args argnames argc fmt
253 name=$(get_name "$1")
254 args=$(get_args "$1")
255 argnames=$(get_argnames "$1" ",")
256 argc=$(get_argc "$1")
257 fmt=$(get_fmt "$1")
258
259 if [ "$argc" -gt 0 ]; then
260 argnames=", $argnames"
261 fi
262
263 cat <<EOF
264static inline void trace_$name($args)
265{
266 fprintf(stderr, "$name $fmt\n" $argnames);
267}
268EOF
269}
270
271linetoh_end_stderr()
272{
273return
274}
275
276linetoc_begin_stderr()
277{
278return
279}
280
281linetoc_stderr()
282{
283return
284}
285
286linetoc_end_stderr()
287{
288return
289}
290#END OF STDERR
291
7e24e92a
SH
292# Clean up after UST headers which pollute the namespace
293ust_clean_namespace() {
294 cat <<EOF
295#undef mutex_lock
296#undef mutex_unlock
297#undef inline
298#undef wmb
299EOF
300}
301
302linetoh_begin_ust()
303{
304 echo "#include <ust/tracepoint.h>"
305 ust_clean_namespace
306}
307
308linetoh_ust()
309{
310 local name args argnames
311 name=$(get_name "$1")
312 args=$(get_args "$1")
b3d08c02 313 argnames=$(get_argnames "$1", ",")
7e24e92a
SH
314
315 cat <<EOF
ea9c1698 316DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
7e24e92a
SH
317#define trace_$name trace_ust_$name
318EOF
319}
320
321linetoh_end_ust()
322{
323 return
324}
325
326linetoc_begin_ust()
327{
328 cat <<EOF
329#include <ust/marker.h>
330$(ust_clean_namespace)
331#include "trace.h"
332EOF
333}
334
335linetoc_ust()
336{
337 local name args argnames fmt
338 name=$(get_name "$1")
339 args=$(get_args "$1")
b3d08c02 340 argnames=$(get_argnames "$1", ",")
7e24e92a
SH
341 fmt=$(get_fmt "$1")
342
343 cat <<EOF
344DEFINE_TRACE(ust_$name);
345
346static void ust_${name}_probe($args)
347{
348 trace_mark(ust, $name, "$fmt", $argnames);
349}
350EOF
351
352 # Collect names for later
353 names="$names $name"
354}
355
356linetoc_end_ust()
357{
358 cat <<EOF
359static void __attribute__((constructor)) trace_init(void)
360{
361EOF
362
363 for name in $names; do
364 cat <<EOF
365 register_trace_ust_$name(ust_${name}_probe);
366EOF
367 done
368
369 echo "}"
370}
371
b3d08c02
DB
372linetoh_begin_dtrace()
373{
374 cat <<EOF
375#include "trace-dtrace.h"
376EOF
377}
378
379linetoh_dtrace()
380{
381 local name args argnames state nameupper
382 name=$(get_name "$1")
383 args=$(get_args "$1")
384 argnames=$(get_argnames "$1", ",")
385 state=$(get_state "$1")
386 if [ "$state" = "0" ] ; then
387 name=${name##disable }
388 fi
389
390 nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
391
392 # Define an empty function for the trace event
393 cat <<EOF
394static inline void trace_$name($args) {
395 if (QEMU_${nameupper}_ENABLED()) {
396 QEMU_${nameupper}($argnames);
397 }
398}
399EOF
400}
401
402linetoh_end_dtrace()
403{
404 return
405}
406
407linetoc_begin_dtrace()
408{
409 return
410}
411
412linetoc_dtrace()
413{
414 # No need for function definitions in dtrace backend
415 return
416}
417
418linetoc_end_dtrace()
419{
420 return
421}
422
423linetod_begin_dtrace()
424{
425 cat <<EOF
426provider qemu {
427EOF
428}
429
430linetod_dtrace()
431{
432 local name args state
433 name=$(get_name "$1")
434 args=$(get_args "$1")
435 state=$(get_state "$1")
436 if [ "$state" = "0" ] ; then
437 name=${name##disable }
438 fi
439
440 # DTrace provider syntax expects foo() for empty
441 # params, not foo(void)
442 if [ "$args" = "void" ]; then
443 args=""
444 fi
445
446 # Define prototype for probe arguments
447 cat <<EOF
448 probe $name($args);
449EOF
450}
451
452linetod_end_dtrace()
453{
454 cat <<EOF
455};
456EOF
457}
458
c276b17d
DB
459linetostap_begin_dtrace()
460{
461 return
462}
463
464linetostap_dtrace()
465{
466 local i arg name args arglist state
467 name=$(get_name "$1")
468 args=$(get_args "$1")
469 arglist=$(get_argnames "$1", "")
470 state=$(get_state "$1")
471 if [ "$state" = "0" ] ; then
472 name=${name##disable }
473 fi
474
475 # Define prototype for probe arguments
476 cat <<EOF
e323c93e 477probe $probeprefix.$name = process("$binary").mark("$name")
c276b17d
DB
478{
479EOF
480
481 i=1
482 for arg in $arglist
483 do
484 # 'limit' is a reserved keyword
485 if [ "$arg" = "limit" ]; then
486 arg="_limit"
487 fi
488 cat <<EOF
489 $arg = \$arg$i;
490EOF
491 i="$((i+1))"
492 done
493
494 cat <<EOF
495}
496EOF
497}
498
499linetostap_end_dtrace()
500{
501 return
502}
503
94a420b1
SH
504# Process stdin by calling begin, line, and end functions for the backend
505convert()
506{
1e2cf2bc 507 local begin process_line end str disable
94a420b1
SH
508 begin="lineto$1_begin_$backend"
509 process_line="lineto$1_$backend"
510 end="lineto$1_end_$backend"
511
512 "$begin"
513
514 while read -r str; do
515 # Skip comments and empty lines
5eb5527b 516 test -z "${str%%#*}" && continue
94a420b1 517
1e2cf2bc
SH
518 # Process the line. The nop backend handles disabled lines.
519 disable=${str%%disable *}
94a420b1 520 echo
1e2cf2bc 521 if test -z "$disable"; then
b3d08c02
DB
522 # Pass the disabled state as an arg for the simple
523 # or DTrace backends which handle it dynamically.
524 # For all other backends, call lineto$1_nop()
525 if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
1e2cf2bc
SH
526 "$process_line" "$str"
527 else
528 "lineto$1_nop" "${str##disable }"
529 fi
530 else
531 "$process_line" "$str"
532 fi
94a420b1
SH
533 done
534
535 echo
536 "$end"
537}
538
539tracetoh()
540{
541 cat <<EOF
542#ifndef TRACE_H
543#define TRACE_H
544
545/* This file is autogenerated by tracetool, do not edit. */
546
547#include "qemu-common.h"
548EOF
549 convert h
550 echo "#endif /* TRACE_H */"
551}
552
553tracetoc()
554{
555 echo "/* This file is autogenerated by tracetool, do not edit. */"
556 convert c
557}
558
b3d08c02
DB
559tracetod()
560{
561 if [ $backend != "dtrace" ]; then
562 echo "DTrace probe generator not applicable to $backend backend"
563 exit 1
564 fi
565 echo "/* This file is autogenerated by tracetool, do not edit. */"
566 convert d
567}
568
c276b17d
DB
569tracetostap()
570{
571 if [ $backend != "dtrace" ]; then
572 echo "SystemTAP tapset generator not applicable to $backend backend"
573 exit 1
574 fi
575 if [ -z "$binary" ]; then
576 echo "--binary is required for SystemTAP tapset generator"
577 exit 1
578 fi
e323c93e 579 if [ -z "$probeprefix" -a -z "$targettype" ]; then
c276b17d
DB
580 echo "--target-type is required for SystemTAP tapset generator"
581 exit 1
582 fi
e323c93e 583 if [ -z "$probeprefix" -a -z "$targetarch" ]; then
c276b17d
DB
584 echo "--target-arch is required for SystemTAP tapset generator"
585 exit 1
586 fi
e323c93e
JS
587 if [ -z "$probeprefix" ]; then
588 probeprefix="qemu.$targettype.$targetarch";
589 fi
c276b17d
DB
590 echo "/* This file is autogenerated by tracetool, do not edit. */"
591 convert stap
592}
593
594
595backend=
596output=
597binary=
598targettype=
599targetarch=
e323c93e 600probeprefix=
c276b17d
DB
601
602
603until [ -z "$1" ]
604do
605 case "$1" in
320fba2a 606 "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
c276b17d
DB
607
608 "--binary") shift ; binary="$1" ;;
609 "--target-arch") shift ; targetarch="$1" ;;
610 "--target-type") shift ; targettype="$1" ;;
e323c93e 611 "--probe-prefix") shift ; probeprefix="$1" ;;
c276b17d
DB
612
613 "-h" | "-c" | "-d") output="${1#-}" ;;
614 "--stap") output="${1#--}" ;;
615
616 "--check-backend") exit 0 ;; # used by ./configure to test for backend
617
320fba2a
FC
618 "--list-backends") # used by ./configure to list available backends
619 echo "nop simple stderr ust dtrace"
620 exit 0
621 ;;
622
c276b17d
DB
623 *)
624 usage;;
625 esac
626 shift
627done
628
629if [ "$backend" = "" -o "$output" = "" ]; then
630 usage
631fi
632
633gen="traceto$output"
634"$gen"
94a420b1
SH
635
636exit 0