File:  [Qemu by Fabrice Bellard] / qemu / scripts / tracetool
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:42:41 2018 UTC (3 years, 4 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

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

unix.superglobalmegacorp.com