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