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