tracetool: dtrace: handle in and next reserved words
[qemu/ar7.git] / scripts / tracetool
blob5e77aa243d25539764491b3968ee19ae210b8808
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')
36 --probe-prefix [prefix] Prefix for dtrace probe names
37 (default: qemu-\$targettype-\$targetarch)
39 EOF
40 exit 1
43 # Print a line without interpreting backslash escapes
45 # The built-in echo command may interpret backslash escapes without an option
46 # to disable this behavior.
47 puts()
49 printf "%s\n" "$1"
52 # Get the name of a trace event
53 get_name()
55 local name
56 name=${1%%\(*}
57 echo "${name##* }"
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
64 has_property()
66 local props prop
67 props=${1%%\(*}
68 props=${props% *}
69 for prop in $props; do
70 if [ "$prop" = "$2" ]; then
71 return 0
73 done
74 return 1
77 # Get the argument list of a trace event, including types and names
78 get_args()
80 local args
81 args=${1#*\(}
82 args=${args%%\)*}
83 echo "$args"
86 # Get the argument name list of a trace event
87 get_argnames()
89 local nfields field name sep
90 nfields=0
91 sep="$2"
92 for field in $(get_args "$1"); do
93 nfields=$((nfields + 1))
95 # Drop pointer star
96 field=${field#\*}
98 # Only argument names have commas at the end
99 name=${field%,}
100 test "$field" = "$name" && continue
102 printf "%s%s " $name $sep
103 done
105 # Last argument name
106 if [ "$nfields" -gt 1 ]
107 then
108 printf "%s" "$name"
112 # Get the number of arguments to a trace event
113 get_argc()
115 local name argc
116 argc=0
117 for name in $(get_argnames "$1", ","); do
118 argc=$((argc + 1))
119 done
120 echo $argc
123 # Get the format string including double quotes for a trace event
124 get_fmt()
126 puts "${1#*)}"
129 linetoh_begin_nop()
131 return
134 linetoh_nop()
136 local name args
137 name=$(get_name "$1")
138 args=$(get_args "$1")
140 # Define an empty function for the trace event
141 cat <<EOF
142 static inline void trace_$name($args)
148 linetoh_end_nop()
150 return
153 linetoc_begin_nop()
155 return
158 linetoc_nop()
160 # No need for function definitions in nop backend
161 return
164 linetod_nop()
166 # Used when "disabled" events are processed
167 return
170 linetostap_nop()
172 # Used when "disabled" events are processed
173 return
176 linetoc_end_nop()
178 return
181 linetoh_begin_simple()
183 cat <<EOF
184 #include "trace/simple.h"
187 simple_event_num=0
190 cast_args_to_uint64_t()
192 local arg
193 for arg in $(get_argnames "$1", ","); do
194 printf "%s" "(uint64_t)(uintptr_t)$arg"
195 done
198 linetoh_simple()
200 local name args argc trace_args
201 name=$(get_name "$1")
202 args=$(get_args "$1")
203 argc=$(get_argc "$1")
205 trace_args="$simple_event_num"
206 if [ "$argc" -gt 0 ]
207 then
208 trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
211 cat <<EOF
212 static inline void trace_$name($args)
214 trace$argc($trace_args);
218 simple_event_num=$((simple_event_num + 1))
221 linetoh_end_simple()
223 cat <<EOF
224 #define NR_TRACE_EVENTS $simple_event_num
225 extern TraceEvent trace_list[NR_TRACE_EVENTS];
229 linetoc_begin_simple()
231 cat <<EOF
232 #include "trace.h"
234 TraceEvent trace_list[] = {
236 simple_event_num=0
240 linetoc_simple()
242 local name
243 name=$(get_name "$1")
244 cat <<EOF
245 {.tp_name = "$name", .state=0},
247 simple_event_num=$((simple_event_num + 1))
250 linetoc_end_simple()
252 cat <<EOF
257 #STDERR
258 linetoh_begin_stderr()
260 cat <<EOF
261 #include <stdio.h>
262 #include "trace/stderr.h"
264 extern TraceEvent trace_list[];
267 stderr_event_num=0
270 linetoh_stderr()
272 local name args argnames argc fmt
273 name=$(get_name "$1")
274 args=$(get_args "$1")
275 argnames=$(get_argnames "$1" ",")
276 argc=$(get_argc "$1")
277 fmt=$(get_fmt "$1")
279 if [ "$argc" -gt 0 ]; then
280 argnames=", $argnames"
283 cat <<EOF
284 static inline void trace_$name($args)
286 if (trace_list[$stderr_event_num].state != 0) {
287 fprintf(stderr, "$name " $fmt "\n" $argnames);
291 stderr_event_num=$((stderr_event_num + 1))
295 linetoh_end_stderr()
297 cat <<EOF
298 #define NR_TRACE_EVENTS $stderr_event_num
302 linetoc_begin_stderr()
304 cat <<EOF
305 #include "trace.h"
307 TraceEvent trace_list[] = {
309 stderr_event_num=0
312 linetoc_stderr()
314 local name
315 name=$(get_name "$1")
316 cat <<EOF
317 {.tp_name = "$name", .state=0},
319 stderr_event_num=$(($stderr_event_num + 1))
322 linetoc_end_stderr()
324 cat <<EOF
328 #END OF STDERR
330 # Clean up after UST headers which pollute the namespace
331 ust_clean_namespace() {
332 cat <<EOF
333 #undef mutex_lock
334 #undef mutex_unlock
335 #undef inline
336 #undef wmb
340 linetoh_begin_ust()
342 echo "#include <ust/tracepoint.h>"
343 ust_clean_namespace
346 linetoh_ust()
348 local name args argnames
349 name=$(get_name "$1")
350 args=$(get_args "$1")
351 argnames=$(get_argnames "$1", ",")
353 cat <<EOF
354 DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
355 #define trace_$name trace_ust_$name
359 linetoh_end_ust()
361 return
364 linetoc_begin_ust()
366 cat <<EOF
367 #include <ust/marker.h>
368 $(ust_clean_namespace)
369 #include "trace.h"
373 linetoc_ust()
375 local name args argnames fmt
376 name=$(get_name "$1")
377 args=$(get_args "$1")
378 argnames=$(get_argnames "$1", ",")
379 [ -z "$argnames" ] || argnames=", $argnames"
380 fmt=$(get_fmt "$1")
382 cat <<EOF
383 DEFINE_TRACE(ust_$name);
385 static void ust_${name}_probe($args)
387 trace_mark(ust, $name, $fmt$argnames);
391 # Collect names for later
392 names="$names $name"
395 linetoc_end_ust()
397 cat <<EOF
398 static void __attribute__((constructor)) trace_init(void)
402 for name in $names; do
403 cat <<EOF
404 register_trace_ust_$name(ust_${name}_probe);
406 done
408 echo "}"
411 linetoh_begin_dtrace()
413 cat <<EOF
414 #include "trace-dtrace.h"
418 linetoh_dtrace()
420 local name args argnames nameupper
421 name=$(get_name "$1")
422 args=$(get_args "$1")
423 argnames=$(get_argnames "$1", ",")
425 nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
427 # Define an empty function for the trace event
428 cat <<EOF
429 static inline void trace_$name($args) {
430 QEMU_${nameupper}($argnames);
435 linetoh_end_dtrace()
437 return
440 linetoc_begin_dtrace()
442 return
445 linetoc_dtrace()
447 # No need for function definitions in dtrace backend
448 return
451 linetoc_end_dtrace()
453 return
456 linetod_begin_dtrace()
458 cat <<EOF
459 provider qemu {
463 linetod_dtrace()
465 local name args
466 name=$(get_name "$1")
467 args=$(get_args "$1")
469 # DTrace provider syntax expects foo() for empty
470 # params, not foo(void)
471 if [ "$args" = "void" ]; then
472 args=""
475 # Define prototype for probe arguments
476 cat <<EOF
477 probe $name($args);
481 linetod_end_dtrace()
483 cat <<EOF
488 linetostap_begin_dtrace()
490 return
493 linetostap_dtrace()
495 local i arg name args arglist
496 name=$(get_name "$1")
497 args=$(get_args "$1")
498 arglist=$(get_argnames "$1", "")
500 # Define prototype for probe arguments
501 cat <<EOF
502 probe $probeprefix.$name = process("$binary").mark("$name")
507 for arg in $arglist
509 # postfix reserved words with '_'
510 case "$arg" in
511 limit|in|next|self)
512 arg="${arg}_"
514 esac
515 cat <<EOF
516 $arg = \$arg$i;
518 i="$((i+1))"
519 done
521 cat <<EOF
526 linetostap_end_dtrace()
528 return
531 # Process stdin by calling begin, line, and end functions for the backend
532 convert()
534 local begin process_line end str name NAME enabled
535 begin="lineto$1_begin_$backend"
536 process_line="lineto$1_$backend"
537 end="lineto$1_end_$backend"
539 "$begin"
541 while read -r str; do
542 # Skip comments and empty lines
543 test -z "${str%%#*}" && continue
545 echo
546 # Process the line. The nop backend handles disabled lines.
547 if has_property "$str" "disable"; then
548 "lineto$1_nop" "$str"
549 enabled=0
550 else
551 "$process_line" "$str"
552 enabled=1
554 if [ "$1" = "h" ]; then
555 name=$(get_name "$str")
556 NAME=$(echo $name | tr '[:lower:]' '[:upper:]')
557 echo "#define TRACE_${NAME}_ENABLED ${enabled}"
559 done
561 echo
562 "$end"
565 tracetoh()
567 cat <<EOF
568 #ifndef TRACE_H
569 #define TRACE_H
571 /* This file is autogenerated by tracetool, do not edit. */
573 #include "qemu-common.h"
575 convert h
576 echo "#endif /* TRACE_H */"
579 tracetoc()
581 echo "/* This file is autogenerated by tracetool, do not edit. */"
582 convert c
585 tracetod()
587 if [ $backend != "dtrace" ]; then
588 echo "DTrace probe generator not applicable to $backend backend"
589 exit 1
591 echo "/* This file is autogenerated by tracetool, do not edit. */"
592 convert d
595 tracetostap()
597 if [ $backend != "dtrace" ]; then
598 echo "SystemTAP tapset generator not applicable to $backend backend"
599 exit 1
601 if [ -z "$binary" ]; then
602 echo "--binary is required for SystemTAP tapset generator"
603 exit 1
605 if [ -z "$probeprefix" -a -z "$targettype" ]; then
606 echo "--target-type is required for SystemTAP tapset generator"
607 exit 1
609 if [ -z "$probeprefix" -a -z "$targetarch" ]; then
610 echo "--target-arch is required for SystemTAP tapset generator"
611 exit 1
613 if [ -z "$probeprefix" ]; then
614 probeprefix="qemu.$targettype.$targetarch";
616 echo "/* This file is autogenerated by tracetool, do not edit. */"
617 convert stap
621 backend=
622 output=
623 binary=
624 targettype=
625 targetarch=
626 probeprefix=
629 until [ -z "$1" ]
631 case "$1" in
632 "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
634 "--binary") shift ; binary="$1" ;;
635 "--target-arch") shift ; targetarch="$1" ;;
636 "--target-type") shift ; targettype="$1" ;;
637 "--probe-prefix") shift ; probeprefix="$1" ;;
639 "-h" | "-c" | "-d") output="${1#-}" ;;
640 "--stap") output="${1#--}" ;;
642 "--check-backend") exit 0 ;; # used by ./configure to test for backend
644 "--list-backends") # used by ./configure to list available backends
645 echo "nop simple stderr ust dtrace"
646 exit 0
650 usage;;
651 esac
652 shift
653 done
655 if [ "$backend" = "" -o "$output" = "" ]; then
656 usage
659 gen="traceto$output"
660 "$gen"
662 exit 0