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