]> Git Repo - qemu.git/blob - tracetool
virtio: fix up VQ checks
[qemu.git] / tracetool
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
11 set -f
12
13 usage()
14 {
15     cat >&2 <<EOF
16 usage: $0 [--nop | --simple | --ust] [-h | -c]
17 Generate tracing code for a file on stdin.
18
19 Backends:
20   --nop     Tracing disabled
21   --simple  Simple built-in backend
22   --ust     LTTng User Space Tracing backend
23
24 Output formats:
25   -h    Generate .h file
26   -c    Generate .c file
27 EOF
28     exit 1
29 }
30
31 # Get the name of a trace event
32 get_name()
33 {
34     echo ${1%%\(*}
35 }
36
37 # Get the argument list of a trace event, including types and names
38 get_args()
39 {
40     local args
41     args=${1#*\(}
42     args=${args%\)*}
43     echo "$args"
44 }
45
46 # Get the argument name list of a trace event
47 get_argnames()
48 {
49     local nfields field name
50     nfields=0
51     for field in $(get_args "$1"); do
52         nfields=$((nfields + 1))
53
54         # Drop pointer star
55         field=${field#\*}
56
57         # Only argument names have commas at the end
58         name=${field%,}
59         test "$field" = "$name" && continue
60
61         printf "%s" "$name, "
62     done
63
64     # Last argument name
65     if [ "$nfields" -gt 1 ]
66     then
67         printf "%s" "$name"
68     fi
69 }
70
71 # Get the number of arguments to a trace event
72 get_argc()
73 {
74     local name argc
75     argc=0
76     for name in $(get_argnames "$1"); do
77         argc=$((argc + 1))
78     done
79     echo $argc
80 }
81
82 # Get the format string for a trace event
83 get_fmt()
84 {
85     local fmt
86     fmt=${1#*\"}
87     fmt=${fmt%\"*}
88     echo "$fmt"
89 }
90
91 # Get the state of a trace event
92 get_state()
93 {
94     local str disable state
95     str=$(get_name "$1")
96     disable=${str##disable }
97     if [ "$disable" = "$str" ] ; then
98         state=1
99     else
100         state=0
101     fi
102     echo "$state"
103 }
104
105 linetoh_begin_nop()
106 {
107     return
108 }
109
110 linetoh_nop()
111 {
112     local name args
113     name=$(get_name "$1")
114     args=$(get_args "$1")
115
116     # Define an empty function for the trace event
117     cat <<EOF
118 static inline void trace_$name($args)
119 {
120 }
121 EOF
122 }
123
124 linetoh_end_nop()
125 {
126     return
127 }
128
129 linetoc_begin_nop()
130 {
131     return
132 }
133
134 linetoc_nop()
135 {
136     # No need for function definitions in nop backend
137     return
138 }
139
140 linetoc_end_nop()
141 {
142     return
143 }
144
145 linetoh_begin_simple()
146 {
147     cat <<EOF
148 #include "simpletrace.h"
149 EOF
150
151     simple_event_num=0
152 }
153
154 cast_args_to_uint64_t()
155 {
156     local arg
157     for arg in $(get_argnames "$1"); do
158         printf "%s" "(uint64_t)(uintptr_t)$arg"
159     done
160 }
161
162 linetoh_simple()
163 {
164     local name args argc trace_args state
165     name=$(get_name "$1")
166     args=$(get_args "$1")
167     argc=$(get_argc "$1")
168     state=$(get_state "$1")
169     if [ "$state" = "0" ]; then
170         name=${name##disable }
171     fi
172
173     trace_args="$simple_event_num"
174     if [ "$argc" -gt 0 ]
175     then
176         trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
177     fi
178
179     cat <<EOF
180 static inline void trace_$name($args)
181 {
182     trace$argc($trace_args);
183 }
184 EOF
185
186     simple_event_num=$((simple_event_num + 1))
187 }
188
189 linetoh_end_simple()
190 {
191     cat <<EOF
192 #define NR_TRACE_EVENTS $simple_event_num
193 extern TraceEvent trace_list[NR_TRACE_EVENTS];
194 EOF
195 }
196
197 linetoc_begin_simple()
198 {
199     cat <<EOF
200 #include "trace.h"
201
202 TraceEvent trace_list[] = {
203 EOF
204     simple_event_num=0
205
206 }
207
208 linetoc_simple()
209 {
210     local name state
211     name=$(get_name "$1")
212     state=$(get_state "$1")
213     if [ "$state" = "0" ] ; then
214         name=${name##disable }
215     fi
216     cat <<EOF
217 {.tp_name = "$name", .state=$state},
218 EOF
219     simple_event_num=$((simple_event_num + 1))
220 }
221
222 linetoc_end_simple()
223 {
224     cat <<EOF
225 };
226 EOF
227 }
228
229 # Clean up after UST headers which pollute the namespace
230 ust_clean_namespace() {
231     cat <<EOF
232 #undef mutex_lock
233 #undef mutex_unlock
234 #undef inline
235 #undef wmb
236 EOF
237 }
238
239 linetoh_begin_ust()
240 {
241     echo "#include <ust/tracepoint.h>"
242     ust_clean_namespace
243 }
244
245 linetoh_ust()
246 {
247     local name args argnames
248     name=$(get_name "$1")
249     args=$(get_args "$1")
250     argnames=$(get_argnames "$1")
251
252     cat <<EOF
253 DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
254 #define trace_$name trace_ust_$name
255 EOF
256 }
257
258 linetoh_end_ust()
259 {
260     return
261 }
262
263 linetoc_begin_ust()
264 {
265     cat <<EOF
266 #include <ust/marker.h>
267 $(ust_clean_namespace)
268 #include "trace.h"
269 EOF
270 }
271
272 linetoc_ust()
273 {
274     local name args argnames fmt
275     name=$(get_name "$1")
276     args=$(get_args "$1")
277     argnames=$(get_argnames "$1")
278     fmt=$(get_fmt "$1")
279
280     cat <<EOF
281 DEFINE_TRACE(ust_$name);
282
283 static void ust_${name}_probe($args)
284 {
285     trace_mark(ust, $name, "$fmt", $argnames);
286 }
287 EOF
288
289     # Collect names for later
290     names="$names $name"
291 }
292
293 linetoc_end_ust()
294 {
295     cat <<EOF
296 static void __attribute__((constructor)) trace_init(void)
297 {
298 EOF
299
300     for name in $names; do
301         cat <<EOF
302     register_trace_ust_$name(ust_${name}_probe);
303 EOF
304     done
305
306     echo "}"
307 }
308
309 # Process stdin by calling begin, line, and end functions for the backend
310 convert()
311 {
312     local begin process_line end str disable
313     begin="lineto$1_begin_$backend"
314     process_line="lineto$1_$backend"
315     end="lineto$1_end_$backend"
316
317     "$begin"
318
319     while read -r str; do
320         # Skip comments and empty lines
321         test -z "${str%%#*}" && continue
322
323         # Process the line.  The nop backend handles disabled lines.
324         disable=${str%%disable *}
325         echo
326         if test -z "$disable"; then
327             # Pass the disabled state as an arg to lineto$1_simple().
328             # For all other cases, call lineto$1_nop()
329             if [ $backend = "simple" ]; then
330                 "$process_line" "$str"
331             else
332                 "lineto$1_nop" "${str##disable }"
333             fi
334         else
335             "$process_line" "$str"
336         fi
337     done
338
339     echo
340     "$end"
341 }
342
343 tracetoh()
344 {
345     cat <<EOF
346 #ifndef TRACE_H
347 #define TRACE_H
348
349 /* This file is autogenerated by tracetool, do not edit. */
350
351 #include "qemu-common.h"
352 EOF
353     convert h
354     echo "#endif /* TRACE_H */"
355 }
356
357 tracetoc()
358 {
359     echo "/* This file is autogenerated by tracetool, do not edit. */"
360     convert c
361 }
362
363 # Choose backend
364 case "$1" in
365 "--nop" | "--simple" | "--ust") backend="${1#--}" ;;
366 *) usage ;;
367 esac
368 shift
369
370 case "$1" in
371 "-h") tracetoh ;;
372 "-c") tracetoc ;;
373 "--check-backend") exit 0 ;; # used by ./configure to test for backend
374 *) usage ;;
375 esac
376
377 exit 0
This page took 0.044282 seconds and 4 git commands to generate.