pci: Fix memory leak
[qemu.git] / scripts / tracetool
blobe04668322d08c46151e78f2cc97b80de00a512c6
1 #!/bin/sh
3 # Code generator for trace events
5 # Copyright IBM, Corp. 2010
7 # This work is licensed under the terms of the GNU GPL, version 2. See
8 # the COPYING file in the top-level directory.
10 # Disable pathname expansion, makes processing text with '*' characters simpler
11 set -f
13 usage()
15 cat >&2 <<EOF
16 usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
17 Generate tracing code for a file on stdin.
19 Backends:
20 --nop Tracing disabled
21 --simple Simple built-in backend
22 --stderr Stderr built-in backend
23 --ust LTTng User Space Tracing backend
24 --dtrace DTrace/SystemTAP backend
26 Output formats:
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)
32 Options:
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')
37 EOF
38 exit 1
41 # Get the name of a trace event
42 get_name()
44 echo ${1%%\(*}
47 # Get the argument list of a trace event, including types and names
48 get_args()
50 local args
51 args=${1#*\(}
52 args=${args%\)*}
53 echo "$args"
56 # Get the argument name list of a trace event
57 get_argnames()
59 local nfields field name sep
60 nfields=0
61 sep="$2"
62 for field in $(get_args "$1"); do
63 nfields=$((nfields + 1))
65 # Drop pointer star
66 field=${field#\*}
68 # Only argument names have commas at the end
69 name=${field%,}
70 test "$field" = "$name" && continue
72 printf "%s%s " $name $sep
73 done
75 # Last argument name
76 if [ "$nfields" -gt 1 ]
77 then
78 printf "%s" "$name"
82 # Get the number of arguments to a trace event
83 get_argc()
85 local name argc
86 argc=0
87 for name in $(get_argnames "$1", ","); do
88 argc=$((argc + 1))
89 done
90 echo $argc
93 # Get the format string for a trace event
94 get_fmt()
96 local fmt
97 fmt=${1#*\"}
98 fmt=${fmt%\"*}
99 echo "$fmt"
102 # Get the state of a trace event
103 get_state()
105 local str disable state
106 str=$(get_name "$1")
107 disable=${str##disable }
108 if [ "$disable" = "$str" ] ; then
109 state=1
110 else
111 state=0
113 echo "$state"
116 linetoh_begin_nop()
118 return
121 linetoh_nop()
123 local name args
124 name=$(get_name "$1")
125 args=$(get_args "$1")
127 # Define an empty function for the trace event
128 cat <<EOF
129 static inline void trace_$name($args)
135 linetoh_end_nop()
137 return
140 linetoc_begin_nop()
142 return
145 linetoc_nop()
147 # No need for function definitions in nop backend
148 return
151 linetoc_end_nop()
153 return
156 linetoh_begin_simple()
158 cat <<EOF
159 #include "simpletrace.h"
162 simple_event_num=0
165 cast_args_to_uint64_t()
167 local arg
168 for arg in $(get_argnames "$1", ","); do
169 printf "%s" "(uint64_t)(uintptr_t)$arg"
170 done
173 linetoh_simple()
175 local name args argc trace_args state
176 name=$(get_name "$1")
177 args=$(get_args "$1")
178 argc=$(get_argc "$1")
179 state=$(get_state "$1")
180 if [ "$state" = "0" ]; then
181 name=${name##disable }
184 trace_args="$simple_event_num"
185 if [ "$argc" -gt 0 ]
186 then
187 trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
190 cat <<EOF
191 static inline void trace_$name($args)
193 trace$argc($trace_args);
197 simple_event_num=$((simple_event_num + 1))
200 linetoh_end_simple()
202 cat <<EOF
203 #define NR_TRACE_EVENTS $simple_event_num
204 extern TraceEvent trace_list[NR_TRACE_EVENTS];
208 linetoc_begin_simple()
210 cat <<EOF
211 #include "trace.h"
213 TraceEvent trace_list[] = {
215 simple_event_num=0
219 linetoc_simple()
221 local name state
222 name=$(get_name "$1")
223 state=$(get_state "$1")
224 if [ "$state" = "0" ] ; then
225 name=${name##disable }
227 cat <<EOF
228 {.tp_name = "$name", .state=$state},
230 simple_event_num=$((simple_event_num + 1))
233 linetoc_end_simple()
235 cat <<EOF
240 #STDERR
241 linetoh_begin_stderr()
243 cat <<EOF
244 #include <stdio.h>
248 linetoh_stderr()
250 local name args argnames argc fmt
251 name=$(get_name "$1")
252 args=$(get_args "$1")
253 argnames=$(get_argnames "$1" ",")
254 argc=$(get_argc "$1")
255 fmt=$(get_fmt "$1")
257 if [ "$argc" -gt 0 ]; then
258 argnames=", $argnames"
261 cat <<EOF
262 static inline void trace_$name($args)
264 fprintf(stderr, "$name $fmt\n" $argnames);
269 linetoh_end_stderr()
271 return
274 linetoc_begin_stderr()
276 return
279 linetoc_stderr()
281 return
284 linetoc_end_stderr()
286 return
288 #END OF STDERR
290 # Clean up after UST headers which pollute the namespace
291 ust_clean_namespace() {
292 cat <<EOF
293 #undef mutex_lock
294 #undef mutex_unlock
295 #undef inline
296 #undef wmb
300 linetoh_begin_ust()
302 echo "#include <ust/tracepoint.h>"
303 ust_clean_namespace
306 linetoh_ust()
308 local name args argnames
309 name=$(get_name "$1")
310 args=$(get_args "$1")
311 argnames=$(get_argnames "$1", ",")
313 cat <<EOF
314 DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
315 #define trace_$name trace_ust_$name
319 linetoh_end_ust()
321 return
324 linetoc_begin_ust()
326 cat <<EOF
327 #include <ust/marker.h>
328 $(ust_clean_namespace)
329 #include "trace.h"
333 linetoc_ust()
335 local name args argnames fmt
336 name=$(get_name "$1")
337 args=$(get_args "$1")
338 argnames=$(get_argnames "$1", ",")
339 fmt=$(get_fmt "$1")
341 cat <<EOF
342 DEFINE_TRACE(ust_$name);
344 static void ust_${name}_probe($args)
346 trace_mark(ust, $name, "$fmt", $argnames);
350 # Collect names for later
351 names="$names $name"
354 linetoc_end_ust()
356 cat <<EOF
357 static void __attribute__((constructor)) trace_init(void)
361 for name in $names; do
362 cat <<EOF
363 register_trace_ust_$name(ust_${name}_probe);
365 done
367 echo "}"
370 linetoh_begin_dtrace()
372 cat <<EOF
373 #include "trace-dtrace.h"
377 linetoh_dtrace()
379 local name args argnames state nameupper
380 name=$(get_name "$1")
381 args=$(get_args "$1")
382 argnames=$(get_argnames "$1", ",")
383 state=$(get_state "$1")
384 if [ "$state" = "0" ] ; then
385 name=${name##disable }
388 nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
390 # Define an empty function for the trace event
391 cat <<EOF
392 static inline void trace_$name($args) {
393 if (QEMU_${nameupper}_ENABLED()) {
394 QEMU_${nameupper}($argnames);
400 linetoh_end_dtrace()
402 return
405 linetoc_begin_dtrace()
407 return
410 linetoc_dtrace()
412 # No need for function definitions in dtrace backend
413 return
416 linetoc_end_dtrace()
418 return
421 linetod_begin_dtrace()
423 cat <<EOF
424 provider qemu {
428 linetod_dtrace()
430 local name args state
431 name=$(get_name "$1")
432 args=$(get_args "$1")
433 state=$(get_state "$1")
434 if [ "$state" = "0" ] ; then
435 name=${name##disable }
438 # DTrace provider syntax expects foo() for empty
439 # params, not foo(void)
440 if [ "$args" = "void" ]; then
441 args=""
444 # Define prototype for probe arguments
445 cat <<EOF
446 probe $name($args);
450 linetod_end_dtrace()
452 cat <<EOF
457 linetostap_begin_dtrace()
459 return
462 linetostap_dtrace()
464 local i arg name args arglist state
465 name=$(get_name "$1")
466 args=$(get_args "$1")
467 arglist=$(get_argnames "$1", "")
468 state=$(get_state "$1")
469 if [ "$state" = "0" ] ; then
470 name=${name##disable }
473 # Define prototype for probe arguments
474 cat <<EOF
475 probe qemu.$targettype.$targetarch.$name = process("$binary").mark("$name")
480 for arg in $arglist
482 # 'limit' is a reserved keyword
483 if [ "$arg" = "limit" ]; then
484 arg="_limit"
486 cat <<EOF
487 $arg = \$arg$i;
489 i="$((i+1))"
490 done
492 cat <<EOF
497 linetostap_end_dtrace()
499 return
502 # Process stdin by calling begin, line, and end functions for the backend
503 convert()
505 local begin process_line end str disable
506 begin="lineto$1_begin_$backend"
507 process_line="lineto$1_$backend"
508 end="lineto$1_end_$backend"
510 "$begin"
512 while read -r str; do
513 # Skip comments and empty lines
514 test -z "${str%%#*}" && continue
516 # Process the line. The nop backend handles disabled lines.
517 disable=${str%%disable *}
518 echo
519 if test -z "$disable"; then
520 # Pass the disabled state as an arg for the simple
521 # or DTrace backends which handle it dynamically.
522 # For all other backends, call lineto$1_nop()
523 if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
524 "$process_line" "$str"
525 else
526 "lineto$1_nop" "${str##disable }"
528 else
529 "$process_line" "$str"
531 done
533 echo
534 "$end"
537 tracetoh()
539 cat <<EOF
540 #ifndef TRACE_H
541 #define TRACE_H
543 /* This file is autogenerated by tracetool, do not edit. */
545 #include "qemu-common.h"
547 convert h
548 echo "#endif /* TRACE_H */"
551 tracetoc()
553 echo "/* This file is autogenerated by tracetool, do not edit. */"
554 convert c
557 tracetod()
559 if [ $backend != "dtrace" ]; then
560 echo "DTrace probe generator not applicable to $backend backend"
561 exit 1
563 echo "/* This file is autogenerated by tracetool, do not edit. */"
564 convert d
567 tracetostap()
569 if [ $backend != "dtrace" ]; then
570 echo "SystemTAP tapset generator not applicable to $backend backend"
571 exit 1
573 if [ -z "$binary" ]; then
574 echo "--binary is required for SystemTAP tapset generator"
575 exit 1
577 if [ -z "$targettype" ]; then
578 echo "--target-type is required for SystemTAP tapset generator"
579 exit 1
581 if [ -z "$targetarch" ]; then
582 echo "--target-arch is required for SystemTAP tapset generator"
583 exit 1
585 echo "/* This file is autogenerated by tracetool, do not edit. */"
586 convert stap
590 backend=
591 output=
592 binary=
593 targettype=
594 targetarch=
597 until [ -z "$1" ]
599 case "$1" in
600 "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
602 "--binary") shift ; binary="$1" ;;
603 "--target-arch") shift ; targetarch="$1" ;;
604 "--target-type") shift ; targettype="$1" ;;
606 "-h" | "-c" | "-d") output="${1#-}" ;;
607 "--stap") output="${1#--}" ;;
609 "--check-backend") exit 0 ;; # used by ./configure to test for backend
611 "--list-backends") # used by ./configure to list available backends
612 echo "nop simple stderr ust dtrace"
613 exit 0
617 usage;;
618 esac
619 shift
620 done
622 if [ "$backend" = "" -o "$output" = "" ]; then
623 usage
626 gen="traceto$output"
627 "$gen"
629 exit 0