]> git.proxmox.com Git - qemu.git/blame - scripts/tracetool
Merge remote-tracking branch 'spice/spice.v39' into staging
[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", ",")
fa2d480a 341 [ -z "$argnames" ] || argnames=", $argnames"
7e24e92a
SH
342 fmt=$(get_fmt "$1")
343
344 cat <<EOF
345DEFINE_TRACE(ust_$name);
346
347static void ust_${name}_probe($args)
348{
fa2d480a 349 trace_mark(ust, $name, "$fmt"$argnames);
7e24e92a
SH
350}
351EOF
352
353 # Collect names for later
354 names="$names $name"
355}
356
357linetoc_end_ust()
358{
359 cat <<EOF
360static void __attribute__((constructor)) trace_init(void)
361{
362EOF
363
364 for name in $names; do
365 cat <<EOF
366 register_trace_ust_$name(ust_${name}_probe);
367EOF
368 done
369
370 echo "}"
371}
372
b3d08c02
DB
373linetoh_begin_dtrace()
374{
375 cat <<EOF
376#include "trace-dtrace.h"
377EOF
378}
379
380linetoh_dtrace()
381{
382 local name args argnames state nameupper
383 name=$(get_name "$1")
384 args=$(get_args "$1")
385 argnames=$(get_argnames "$1", ",")
386 state=$(get_state "$1")
387 if [ "$state" = "0" ] ; then
388 name=${name##disable }
389 fi
390
391 nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
392
393 # Define an empty function for the trace event
394 cat <<EOF
395static inline void trace_$name($args) {
396 if (QEMU_${nameupper}_ENABLED()) {
397 QEMU_${nameupper}($argnames);
398 }
399}
400EOF
401}
402
403linetoh_end_dtrace()
404{
405 return
406}
407
408linetoc_begin_dtrace()
409{
410 return
411}
412
413linetoc_dtrace()
414{
415 # No need for function definitions in dtrace backend
416 return
417}
418
419linetoc_end_dtrace()
420{
421 return
422}
423
424linetod_begin_dtrace()
425{
426 cat <<EOF
427provider qemu {
428EOF
429}
430
431linetod_dtrace()
432{
433 local name args state
434 name=$(get_name "$1")
435 args=$(get_args "$1")
436 state=$(get_state "$1")
437 if [ "$state" = "0" ] ; then
438 name=${name##disable }
439 fi
440
441 # DTrace provider syntax expects foo() for empty
442 # params, not foo(void)
443 if [ "$args" = "void" ]; then
444 args=""
445 fi
446
447 # Define prototype for probe arguments
448 cat <<EOF
449 probe $name($args);
450EOF
451}
452
453linetod_end_dtrace()
454{
455 cat <<EOF
456};
457EOF
458}
459
c276b17d
DB
460linetostap_begin_dtrace()
461{
462 return
463}
464
465linetostap_dtrace()
466{
467 local i arg name args arglist state
468 name=$(get_name "$1")
469 args=$(get_args "$1")
470 arglist=$(get_argnames "$1", "")
471 state=$(get_state "$1")
472 if [ "$state" = "0" ] ; then
473 name=${name##disable }
474 fi
475
476 # Define prototype for probe arguments
477 cat <<EOF
e323c93e 478probe $probeprefix.$name = process("$binary").mark("$name")
c276b17d
DB
479{
480EOF
481
482 i=1
483 for arg in $arglist
484 do
485 # 'limit' is a reserved keyword
486 if [ "$arg" = "limit" ]; then
487 arg="_limit"
488 fi
489 cat <<EOF
490 $arg = \$arg$i;
491EOF
fa2d480a 492 i="$((i+1))"
c276b17d
DB
493 done
494
495 cat <<EOF
496}
497EOF
498}
499
500linetostap_end_dtrace()
501{
502 return
503}
504
94a420b1
SH
505# Process stdin by calling begin, line, and end functions for the backend
506convert()
507{
1e2cf2bc 508 local begin process_line end str disable
94a420b1
SH
509 begin="lineto$1_begin_$backend"
510 process_line="lineto$1_$backend"
511 end="lineto$1_end_$backend"
512
513 "$begin"
514
515 while read -r str; do
516 # Skip comments and empty lines
5eb5527b 517 test -z "${str%%#*}" && continue
94a420b1 518
1e2cf2bc
SH
519 # Process the line. The nop backend handles disabled lines.
520 disable=${str%%disable *}
94a420b1 521 echo
1e2cf2bc 522 if test -z "$disable"; then
b3d08c02
DB
523 # Pass the disabled state as an arg for the simple
524 # or DTrace backends which handle it dynamically.
525 # For all other backends, call lineto$1_nop()
526 if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
1e2cf2bc
SH
527 "$process_line" "$str"
528 else
529 "lineto$1_nop" "${str##disable }"
530 fi
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