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