123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- #!/bin/sh
- #
- # Code generator for trace events
- #
- # Copyright IBM, Corp. 2010
- #
- # This work is licensed under the terms of the GNU GPL, version 2. See
- # the COPYING file in the top-level directory.
- # Disable pathname expansion, makes processing text with '*' characters simpler
- set -f
- usage()
- {
- cat >&2 <<EOF
- usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
- Generate tracing code for a file on stdin.
- Backends:
- --nop Tracing disabled
- --simple Simple built-in backend
- --stderr Stderr built-in backend
- --ust LTTng User Space Tracing backend
- --dtrace DTrace/SystemTAP backend
- Output formats:
- -h Generate .h file
- -c Generate .c file
- -d Generate .d file (DTrace only)
- --stap Generate .stp file (DTrace with SystemTAP only)
- Options:
- --binary [path] Full path to QEMU binary
- --target-arch [arch] QEMU emulator target arch
- --target-type [type] QEMU emulator target type ('system' or 'user')
- --probe-prefix [prefix] Prefix for dtrace probe names
- (default: qemu-\$targettype-\$targetarch)
- EOF
- exit 1
- }
- # Get the name of a trace event
- get_name()
- {
- echo ${1%%\(*}
- }
- # Get the argument list of a trace event, including types and names
- get_args()
- {
- local args
- args=${1#*\(}
- args=${args%%\)*}
- echo "$args"
- }
- # Get the argument name list of a trace event
- get_argnames()
- {
- local nfields field name sep
- nfields=0
- sep="$2"
- for field in $(get_args "$1"); do
- nfields=$((nfields + 1))
- # Drop pointer star
- field=${field#\*}
- # Only argument names have commas at the end
- name=${field%,}
- test "$field" = "$name" && continue
- printf "%s%s " $name $sep
- done
- # Last argument name
- if [ "$nfields" -gt 1 ]
- then
- printf "%s" "$name"
- fi
- }
- # Get the number of arguments to a trace event
- get_argc()
- {
- local name argc
- argc=0
- for name in $(get_argnames "$1", ","); do
- argc=$((argc + 1))
- done
- echo $argc
- }
- # Get the format string for a trace event
- get_fmt()
- {
- local fmt
- fmt=${1#*\"}
- fmt=${fmt%\"*}
- echo "$fmt"
- }
- # Get the state of a trace event
- get_state()
- {
- local str disable state
- str=$(get_name "$1")
- disable=${str##disable }
- if [ "$disable" = "$str" ] ; then
- state=1
- else
- state=0
- fi
- echo "$state"
- }
- linetoh_begin_nop()
- {
- return
- }
- linetoh_nop()
- {
- local name args
- name=$(get_name "$1")
- args=$(get_args "$1")
- # Define an empty function for the trace event
- cat <<EOF
- static inline void trace_$name($args)
- {
- }
- EOF
- }
- linetoh_end_nop()
- {
- return
- }
- linetoc_begin_nop()
- {
- return
- }
- linetoc_nop()
- {
- # No need for function definitions in nop backend
- return
- }
- linetoc_end_nop()
- {
- return
- }
- linetoh_begin_simple()
- {
- cat <<EOF
- #include "simpletrace.h"
- EOF
- simple_event_num=0
- }
- cast_args_to_uint64_t()
- {
- local arg
- for arg in $(get_argnames "$1", ","); do
- printf "%s" "(uint64_t)(uintptr_t)$arg"
- done
- }
- linetoh_simple()
- {
- local name args argc trace_args state
- name=$(get_name "$1")
- args=$(get_args "$1")
- argc=$(get_argc "$1")
- state=$(get_state "$1")
- if [ "$state" = "0" ]; then
- name=${name##disable }
- fi
- trace_args="$simple_event_num"
- if [ "$argc" -gt 0 ]
- then
- trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
- fi
- cat <<EOF
- static inline void trace_$name($args)
- {
- trace$argc($trace_args);
- }
- EOF
- simple_event_num=$((simple_event_num + 1))
- }
- linetoh_end_simple()
- {
- cat <<EOF
- #define NR_TRACE_EVENTS $simple_event_num
- extern TraceEvent trace_list[NR_TRACE_EVENTS];
- EOF
- }
- linetoc_begin_simple()
- {
- cat <<EOF
- #include "trace.h"
- TraceEvent trace_list[] = {
- EOF
- simple_event_num=0
- }
- linetoc_simple()
- {
- local name state
- name=$(get_name "$1")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
- cat <<EOF
- {.tp_name = "$name", .state=$state},
- EOF
- simple_event_num=$((simple_event_num + 1))
- }
- linetoc_end_simple()
- {
- cat <<EOF
- };
- EOF
- }
- #STDERR
- linetoh_begin_stderr()
- {
- cat <<EOF
- #include <stdio.h>
- EOF
- }
- linetoh_stderr()
- {
- local name args argnames argc fmt
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1" ",")
- argc=$(get_argc "$1")
- fmt=$(get_fmt "$1")
- if [ "$argc" -gt 0 ]; then
- argnames=", $argnames"
- fi
- cat <<EOF
- static inline void trace_$name($args)
- {
- fprintf(stderr, "$name $fmt\n" $argnames);
- }
- EOF
- }
- linetoh_end_stderr()
- {
- return
- }
- linetoc_begin_stderr()
- {
- return
- }
- linetoc_stderr()
- {
- return
- }
- linetoc_end_stderr()
- {
- return
- }
- #END OF STDERR
- # Clean up after UST headers which pollute the namespace
- ust_clean_namespace() {
- cat <<EOF
- #undef mutex_lock
- #undef mutex_unlock
- #undef inline
- #undef wmb
- EOF
- }
- linetoh_begin_ust()
- {
- echo "#include <ust/tracepoint.h>"
- ust_clean_namespace
- }
- linetoh_ust()
- {
- local name args argnames
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1", ",")
- cat <<EOF
- DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
- #define trace_$name trace_ust_$name
- EOF
- }
- linetoh_end_ust()
- {
- return
- }
- linetoc_begin_ust()
- {
- cat <<EOF
- #include <ust/marker.h>
- $(ust_clean_namespace)
- #include "trace.h"
- EOF
- }
- linetoc_ust()
- {
- local name args argnames fmt
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1", ",")
- [ -z "$argnames" ] || argnames=", $argnames"
- fmt=$(get_fmt "$1")
- cat <<EOF
- DEFINE_TRACE(ust_$name);
- static void ust_${name}_probe($args)
- {
- trace_mark(ust, $name, "$fmt"$argnames);
- }
- EOF
- # Collect names for later
- names="$names $name"
- }
- linetoc_end_ust()
- {
- cat <<EOF
- static void __attribute__((constructor)) trace_init(void)
- {
- EOF
- for name in $names; do
- cat <<EOF
- register_trace_ust_$name(ust_${name}_probe);
- EOF
- done
- echo "}"
- }
- linetoh_begin_dtrace()
- {
- cat <<EOF
- #include "trace-dtrace.h"
- EOF
- }
- linetoh_dtrace()
- {
- local name args argnames state nameupper
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1", ",")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
- nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
- # Define an empty function for the trace event
- cat <<EOF
- static inline void trace_$name($args) {
- if (QEMU_${nameupper}_ENABLED()) {
- QEMU_${nameupper}($argnames);
- }
- }
- EOF
- }
- linetoh_end_dtrace()
- {
- return
- }
- linetoc_begin_dtrace()
- {
- return
- }
- linetoc_dtrace()
- {
- # No need for function definitions in dtrace backend
- return
- }
- linetoc_end_dtrace()
- {
- return
- }
- linetod_begin_dtrace()
- {
- cat <<EOF
- provider qemu {
- EOF
- }
- linetod_dtrace()
- {
- local name args state
- name=$(get_name "$1")
- args=$(get_args "$1")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
- # DTrace provider syntax expects foo() for empty
- # params, not foo(void)
- if [ "$args" = "void" ]; then
- args=""
- fi
- # Define prototype for probe arguments
- cat <<EOF
- probe $name($args);
- EOF
- }
- linetod_end_dtrace()
- {
- cat <<EOF
- };
- EOF
- }
- linetostap_begin_dtrace()
- {
- return
- }
- linetostap_dtrace()
- {
- local i arg name args arglist state
- name=$(get_name "$1")
- args=$(get_args "$1")
- arglist=$(get_argnames "$1", "")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
- # Define prototype for probe arguments
- cat <<EOF
- probe $probeprefix.$name = process("$binary").mark("$name")
- {
- EOF
- i=1
- for arg in $arglist
- do
- # 'limit' is a reserved keyword
- if [ "$arg" = "limit" ]; then
- arg="_limit"
- fi
- cat <<EOF
- $arg = \$arg$i;
- EOF
- i="$((i+1))"
- done
- cat <<EOF
- }
- EOF
- }
- linetostap_end_dtrace()
- {
- return
- }
- # Process stdin by calling begin, line, and end functions for the backend
- convert()
- {
- local begin process_line end str disable
- begin="lineto$1_begin_$backend"
- process_line="lineto$1_$backend"
- end="lineto$1_end_$backend"
- "$begin"
- while read -r str; do
- # Skip comments and empty lines
- test -z "${str%%#*}" && continue
- # Process the line. The nop backend handles disabled lines.
- disable=${str%%disable *}
- echo
- if test -z "$disable"; then
- # Pass the disabled state as an arg for the simple
- # or DTrace backends which handle it dynamically.
- # For all other backends, call lineto$1_nop()
- if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
- "$process_line" "$str"
- else
- "lineto$1_nop" "${str##disable }"
- fi
- else
- "$process_line" "$str"
- fi
- done
- echo
- "$end"
- }
- tracetoh()
- {
- cat <<EOF
- #ifndef TRACE_H
- #define TRACE_H
- /* This file is autogenerated by tracetool, do not edit. */
- #include "qemu-common.h"
- EOF
- convert h
- echo "#endif /* TRACE_H */"
- }
- tracetoc()
- {
- echo "/* This file is autogenerated by tracetool, do not edit. */"
- convert c
- }
- tracetod()
- {
- if [ $backend != "dtrace" ]; then
- echo "DTrace probe generator not applicable to $backend backend"
- exit 1
- fi
- echo "/* This file is autogenerated by tracetool, do not edit. */"
- convert d
- }
- tracetostap()
- {
- if [ $backend != "dtrace" ]; then
- echo "SystemTAP tapset generator not applicable to $backend backend"
- exit 1
- fi
- if [ -z "$binary" ]; then
- echo "--binary is required for SystemTAP tapset generator"
- exit 1
- fi
- if [ -z "$probeprefix" -a -z "$targettype" ]; then
- echo "--target-type is required for SystemTAP tapset generator"
- exit 1
- fi
- if [ -z "$probeprefix" -a -z "$targetarch" ]; then
- echo "--target-arch is required for SystemTAP tapset generator"
- exit 1
- fi
- if [ -z "$probeprefix" ]; then
- probeprefix="qemu.$targettype.$targetarch";
- fi
- echo "/* This file is autogenerated by tracetool, do not edit. */"
- convert stap
- }
- backend=
- output=
- binary=
- targettype=
- targetarch=
- probeprefix=
- until [ -z "$1" ]
- do
- case "$1" in
- "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
- "--binary") shift ; binary="$1" ;;
- "--target-arch") shift ; targetarch="$1" ;;
- "--target-type") shift ; targettype="$1" ;;
- "--probe-prefix") shift ; probeprefix="$1" ;;
- "-h" | "-c" | "-d") output="${1#-}" ;;
- "--stap") output="${1#--}" ;;
- "--check-backend") exit 0 ;; # used by ./configure to test for backend
- "--list-backends") # used by ./configure to list available backends
- echo "nop simple stderr ust dtrace"
- exit 0
- ;;
- *)
- usage;;
- esac
- shift
- done
- if [ "$backend" = "" -o "$output" = "" ]; then
- usage
- fi
- gen="traceto$output"
- "$gen"
- exit 0
|