Statistics
| Branch: | Revision:

root / tracetool @ ea9c1698

History | View | Annotate | Download (6.1 kB)

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