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