Annotation of qemu/scripts/tracetool, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.