| #!/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 | --ust] [-h | -c] |
| Generate tracing code for a file on stdin. |
| |
| Backends: |
| --nop Tracing disabled |
| --simple Simple built-in backend |
| --ust LTTng User Space Tracing backend |
| |
| Output formats: |
| -h Generate .h file |
| -c Generate .c file |
| 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 |
| nfields=0 |
| 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" "$name, " |
| 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 |
| } |
| |
| # 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") |
| 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 "}" |
| } |
| |
| # 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 to lineto$1_simple(). |
| # For all other cases, call lineto$1_nop() |
| if [ $backend = "simple" ]; 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 |
| } |
| |
| # Choose backend |
| case "$1" in |
| "--nop" | "--simple" | "--ust") backend="${1#--}" ;; |
| *) usage ;; |
| esac |
| shift |
| |
| case "$1" in |
| "-h") tracetoh ;; |
| "-c") tracetoc ;; |
| "--check-backend") exit 0 ;; # used by ./configure to test for backend |
| *) usage ;; |
| esac |
| |
| exit 0 |