|
|
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: ! 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.