* [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules @ 2012-03-26 17:37 Lluís Vilanova 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova ` (7 more replies) 0 siblings, 8 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:37 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha A full rewrite of the tracetool script using per-format and per-backend modules, so that it's easier to read and extend it in the future. Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- NOTE: This series applies in current master, ignoring the "Rewrite tracetool using python" series. Changes in v2: * Fixed a strange import error. * Add a pointer to 'tracetool.out' in the format and backend documentation. Lluís Vilanova (8): tracetool: Rewrite infrastructure as python modules tracetool: Add module for the 'c' format tracetool: Add module for the 'h' format tracetool: Add support for the 'stderr' backend tracetool: Add support for the 'simple' backend tracetool: Add support for the 'ust' backend tracetool: Add support for the 'dtrace' backend tracetool: Add MAINTAINERS info MAINTAINERS | 2 Makefile.objs | 6 Makefile.target | 13 - configure | 4 scripts/tracetool | 648 --------------------------------- scripts/tracetool.py | 141 +++++++ scripts/tracetool/__init__.py | 213 +++++++++++ scripts/tracetool/backend/__init__.py | 114 ++++++ scripts/tracetool/backend/dtrace.py | 104 +++++ scripts/tracetool/backend/simple.py | 60 +++ scripts/tracetool/backend/stderr.py | 61 +++ scripts/tracetool/backend/ust.py | 102 +++++ scripts/tracetool/format/__init__.py | 91 +++++ scripts/tracetool/format/c.py | 20 + scripts/tracetool/format/d.py | 20 + scripts/tracetool/format/h.py | 45 ++ scripts/tracetool/format/stap.py | 20 + 17 files changed, 1005 insertions(+), 659 deletions(-) delete mode 100755 scripts/tracetool create mode 100755 scripts/tracetool.py create mode 100644 scripts/tracetool/__init__.py create mode 100644 scripts/tracetool/backend/__init__.py create mode 100644 scripts/tracetool/backend/dtrace.py create mode 100644 scripts/tracetool/backend/simple.py create mode 100644 scripts/tracetool/backend/stderr.py create mode 100644 scripts/tracetool/backend/ust.py create mode 100644 scripts/tracetool/format/__init__.py create mode 100644 scripts/tracetool/format/c.py create mode 100644 scripts/tracetool/format/d.py create mode 100644 scripts/tracetool/format/h.py create mode 100644 scripts/tracetool/format/stap.py ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova @ 2012-03-26 17:37 ` Lluís Vilanova 2012-03-27 15:17 ` Alon Levy ` (2 more replies) 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 2/8] tracetool: Add module for the 'c' format Lluís Vilanova ` (6 subsequent siblings) 7 siblings, 3 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:37 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- Makefile.objs | 6 Makefile.target | 13 - configure | 4 scripts/tracetool | 648 --------------------------------- scripts/tracetool.py | 110 ++++++ scripts/tracetool/__init__.py | 205 ++++++++++ scripts/tracetool/backend/__init__.py | 114 ++++++ scripts/tracetool/format/__init__.py | 91 +++++ 8 files changed, 532 insertions(+), 659 deletions(-) delete mode 100755 scripts/tracetool create mode 100755 scripts/tracetool.py create mode 100644 scripts/tracetool/__init__.py create mode 100644 scripts/tracetool/backend/__init__.py create mode 100644 scripts/tracetool/format/__init__.py diff --git a/Makefile.objs b/Makefile.objs index 226b01d..8e56f48 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -373,12 +373,12 @@ else trace.h: trace.h-timestamp endif trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN trace.c") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") @cmp -s $@ trace.c || cp $@ trace.c trace.o: trace.c $(GENERATED_HEADERS) @@ -391,7 +391,7 @@ trace-dtrace.h: trace-dtrace.dtrace # rule file. So we use '.dtrace' instead trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) diff --git a/Makefile.target b/Makefile.target index 63cf769..fe28e8b 100644 --- a/Makefile.target +++ b/Makefile.target @@ -59,12 +59,13 @@ TARGET_TYPE=system endif $(QEMU_PROG).stp: - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \ - --$(TRACE_BACKEND) \ - --binary $(bindir)/$(QEMU_PROG) \ - --target-arch $(TARGET_ARCH) \ - --target-type $(TARGET_TYPE) \ - --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=stap \ + --backend=$(TRACE_BACKEND) \ + --binary=$(bindir)/$(QEMU_PROG) \ + --target-arch=$(TARGET_ARCH) \ + --target-type=$(TARGET_TYPE) \ + < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") else stap: endif diff --git a/configure b/configure index 8b4e3c1..c2d6117 100755 --- a/configure +++ b/configure @@ -1097,7 +1097,7 @@ echo " --disable-docs disable documentation build" echo " --disable-vhost-net disable vhost-net acceleration support" echo " --enable-vhost-net enable vhost-net acceleration support" echo " --enable-trace-backend=B Set trace backend" -echo " Available backends:" $("$source_path"/scripts/tracetool --list-backends) +echo " Available backends:" $($python "$source_path"/scripts/tracetool.py --list-backends) echo " --with-trace-file=NAME Full PATH,NAME of file to store traces" echo " Default:trace-<pid>" echo " --disable-spice disable spice" @@ -2654,7 +2654,7 @@ fi ########################################## # check if trace backend exists -sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null +$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null if test "$?" -ne 0 ; then echo echo "Error: invalid trace backend" diff --git a/scripts/tracetool b/scripts/tracetool deleted file mode 100755 index 65bd0a1..0000000 --- a/scripts/tracetool +++ /dev/null @@ -1,648 +0,0 @@ -#!/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 -} - -# Print a line without interpreting backslash escapes -# -# The built-in echo command may interpret backslash escapes without an option -# to disable this behavior. -puts() -{ - printf "%s\n" "$1" -} - -# Get the name of a trace event -get_name() -{ - local name - name=${1%%\(*} - echo "${name##* }" -} - -# Get the given property of a trace event -# 1: trace-events line -# 2: property name -# -> return 0 if property is present, or 1 otherwise -has_property() -{ - local props prop - props=${1%%\(*} - props=${props% *} - for prop in $props; do - if [ "$prop" = "$2" ]; then - return 0 - fi - done - return 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 including double quotes for a trace event -get_fmt() -{ - puts "${1#*)}" -} - -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 "trace/simple.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 - name=$(get_name "$1") - args=$(get_args "$1") - argc=$(get_argc "$1") - - 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 - name=$(get_name "$1") - cat <<EOF -{.tp_name = "$name", .state=0}, -EOF - simple_event_num=$((simple_event_num + 1)) -} - -linetoc_end_simple() -{ - cat <<EOF -}; -EOF -} - -#STDERR -linetoh_begin_stderr() -{ - cat <<EOF -#include <stdio.h> -#include "trace/stderr.h" - -extern TraceEvent trace_list[]; -EOF - - stderr_event_num=0 -} - -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) -{ - if (trace_list[$stderr_event_num].state != 0) { - fprintf(stderr, "$name " $fmt "\n" $argnames); - } -} -EOF - stderr_event_num=$((stderr_event_num + 1)) - -} - -linetoh_end_stderr() -{ - cat <<EOF -#define NR_TRACE_EVENTS $stderr_event_num -EOF -} - -linetoc_begin_stderr() -{ - cat <<EOF -#include "trace.h" - -TraceEvent trace_list[] = { -EOF - stderr_event_num=0 -} - -linetoc_stderr() -{ - local name - name=$(get_name "$1") - cat <<EOF -{.tp_name = "$name", .state=0}, -EOF - stderr_event_num=$(($stderr_event_num + 1)) -} - -linetoc_end_stderr() -{ - cat <<EOF -}; -EOF -} -#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 nameupper - name=$(get_name "$1") - args=$(get_args "$1") - argnames=$(get_argnames "$1", ",") - - nameupper=`echo $name | tr '[:lower:]' '[:upper:]'` - - # Define an empty function for the trace event - cat <<EOF -static inline void trace_$name($args) { - 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 - name=$(get_name "$1") - args=$(get_args "$1") - - # 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 - name=$(get_name "$1") - args=$(get_args "$1") - arglist=$(get_argnames "$1", "") - - # 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 name NAME enabled - 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 - - echo - # Process the line. The nop backend handles disabled lines. - if has_property "$str" "disable"; then - "lineto$1_nop" "$str" - enabled=0 - else - "$process_line" "$str" - enabled=1 - fi - if [ "$1" = "h" ]; then - name=$(get_name "$str") - NAME=$(echo $name | tr '[:lower:]' '[:upper:]') - echo "#define TRACE_${NAME}_ENABLED ${enabled}" - 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 diff --git a/scripts/tracetool.py b/scripts/tracetool.py new file mode 100755 index 0000000..22623ae --- /dev/null +++ b/scripts/tracetool.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Foo. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +import sys +import getopt + +from tracetool import error_write, out +import tracetool.backend +import tracetool.format + + +_SCRIPT = "" + +def error_opt(msg = None): + if msg is not None: + error_write("Error: " + msg + "\n") + + backend_descr = "\n".join([ " %-15s %s" % (n, d) + for n,d in tracetool.backend.get_list() ]) + format_descr = "\n".join([ " %-15s %s" % (n, d) + for n,d in tracetool.format.get_list() ]) + error_write("""\ +Usage: %(script)s --format=<format> --backend=<backend> [<options>] + +Backends: +%(backends)s + +Formats: +%(formats)s + +Options: + --help This help message. + --list-backends Print list of available backends. + --check-backend Check if the given backend is valid. +""" % { + "script" : _SCRIPT, + "backends" : backend_descr, + "formats" : format_descr, + }) + + if msg is None: + sys.exit(0) + else: + sys.exit(1) + + +def main(args): + global _SCRIPT + _SCRIPT = sys.argv[0] + + long_opts = [ "backend=", "format=", "help", "list-backends", "check-backend" ] + long_opts += [ "binary=", "target-type=", "target-arch=", "probe-prefix=" ] + + try: + opts, args = getopt.getopt(args[1:], "", long_opts) + except getopt.GetoptError as err: + error_opt(str(err)) + + check_backend = False + arg_backend = "" + arg_format = "" + for opt, arg in opts: + if opt == "--help": + error_opt() + + elif opt == "--backend": + arg_backend = arg + elif opt == "--format": + arg_format = arg + + elif opt == "--list-backends": + public_backends = tracetool.backend.get_list(only_public = True) + out(", ".join([ b for b,_ in public_backends ])) + sys.exit(0) + elif opt == "--check-backend": + check_backend = True + + else: + error_opt("unhandled option: %s" % opt) + + if arg_backend is None: + error_opt("backend not set") + + if check_backend: + if tracetool.backend.exists(arg_backend): + sys.exit(0) + else: + sys.exit(1) + + kwargs = {} + + try: + tracetool.generate(sys.stdin, arg_format, arg_backend, **kwargs) + except tracetool.TracetoolError as e: + error_opt(str(e)) + +if __name__ == "__main__": + main(sys.argv) diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py new file mode 100644 index 0000000..d8e5cdd --- /dev/null +++ b/scripts/tracetool/__init__.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Machinery for generating tracing-related intermediate files. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +import re +import sys + +import tracetool.format +import tracetool.backend + + +def error_write(*lines): + """Write a set of error lines.""" + sys.stderr.writelines("\n".join(lines) + "\n") + +def error(*lines): + """Write a set of error lines and exit.""" + error_write(*lines) + sys.exit(1) + + +def out(*lines): + """Write a set of output lines.""" + sys.stdout.writelines("\n".join(lines) + "\n") + + +class Arguments: + """Event arguments description. + + Parameters + ---------- + arg_str : str + String describing the event arguments. + """ + + def __init__ (self, arg_str): + self._args = [] + for arg in arg_str.split(","): + arg = arg.strip() + parts = arg.split() + head, sep, tail = parts[-1].rpartition("*") + parts = parts[:-1] + if tail == "void": + assert len(parts) == 0 and sep == "" + continue + arg_type = " ".join(parts + [ " ".join([head, sep]).strip() ]).strip() + self._args.append((arg_type, tail)) + + def __iter__(self): + """Iterate over the (type, name) pairs.""" + return iter(self._args) + + def __len__(self): + """Number of arguments.""" + return len(self._args) + + def __str__(self): + """String suitable for declaring function arguments.""" + if len(self._args) == 0: + return "void" + else: + return ", ".join([ " ".join([t, n]) for t,n in self._args ]) + + def names(self): + """List of argument names.""" + return [ name for _, name in self._args ] + + def types(self): + """List of argument types.""" + return [ type_ for type_, _ in self._args ] + + +class Event(object): + """Event description. + + Parameters + ---------- + line : str + Line describing the event. + + Attributes + ---------- + name : str + The event name. + fmt : str + The event format string. + properties : set(str) + Properties of the event. + args : Arguments + The event arguments. + """ + + _CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?") + + _VALID_PROPS = set(["disable"]) + + def __init__(self, line): + m = self._CRE.match(line) + assert m is not None + groups = m.groupdict('') + self.name = groups["name"] + self.fmt = groups["fmt"] + self.properties = groups["props"].split() + self.args = Arguments(groups["args"]) + + unknown_props = set(self.properties) - self._VALID_PROPS + if len(unknown_props) > 0: + raise ValueError("Unknown properties: %s" % ", ".join(unknown_props)) + + +def _read_events(fobj): + res = [] + for line in fobj: + if not line.strip(): + continue + if line.lstrip().startswith('#'): + continue + res.append(Event(line)) + return res + + +class TracetoolError (Exception): + """Exception for calls to generate.""" + pass + + +def try_import(mod_name, attr_name = None, attr_default = None): + """Try to import a module and get an attribute from it. + + Parameters + ---------- + mod_name : str + Module name. + attr_name : str, optional + Name of an attribute in the module. + attr_default : optional + Default value if the attribute does not exist in the module. + + Returns + ------- + A pair indicating whether the module could be imported and the module or + object or attribute value. + """ + mod_name = mod_name.replace("-", "_") + try: + module = __import__(mod_name, fromlist=["__package__"]) + if attr_name is None: + return True, module + return True, getattr(module, str(attr_name), attr_default) + except ImportError: + return False, None + + +def generate(fevents, format, backend, **options): + """Generate the output for the given (format, backend) pair.""" + # fix strange python error (UnboundLocalError tracetool) + import tracetool + + if len(options) > 0: + raise ValueError("unknown options: " + ", ".join(options)) + + format = str(format) + if len(format) is 0: + raise TracetoolError("format not set") + mformat = format.replace("-", "_") + if not tracetool.format.exists(mformat): + raise TracetoolError("unknown format: %s" % format) + + backend = str(backend) + if len(backend) is 0: + raise TracetoolError("backend not set") + mbackend = backend.replace("-", "_") + if not tracetool.backend.exists(mbackend): + raise TracetoolError("unknown backend: %s" % backend) + + if not tracetool.backend.compatible(mbackend, mformat): + raise TracetoolError("backend '%s' not compatible with format '%s'" % + (backend, format)) + + events = _read_events(fevents) + + if backend == "nop": + ( e.properies.add("disable") for e in events ) + + tracetool.format.generate_begin(mformat, events) + tracetool.backend.generate("nop", format, + [ e + for e in events + if "disable" in e.properties ]) + tracetool.backend.generate(backend, format, + [ e + for e in events + if "disable" not in e.properties ]) + tracetool.format.generate_end(mformat, events) diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py new file mode 100644 index 0000000..23cad9f --- /dev/null +++ b/scripts/tracetool/backend/__init__.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Backend management. + + +Creating new backends +--------------------- + +A new backend named 'foo-bar' corresponds to Python module +'tracetool/backend/foo_bar.py'. + +A backend module should provide a docstring, whose first non-empty line will be +considered its short description. + +All backends must generate their contents through the 'tracetool.out' routine. + + +Backend attributes +------------------ + +========= ==================================================================== +Attribute Description +========= ==================================================================== +PUBLIC If exists and is set to 'True', the backend is considered "public". +========= ==================================================================== + + +Backend functions +----------------- + +======== ======================================================================= +Function Description +======== ======================================================================= +<format> Called to generate the format- and backend-specific code for each of + the specified events. If the function does not exist, the backend is + considered not compatible with the given format. +======== ======================================================================= +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +import pkgutil + +import tracetool + + +def get_list(only_public = False): + """Get a list of (name, description) pairs.""" + res = [("nop", "Tracing disabled.")] + for _, modname, _ in pkgutil.iter_modules(tracetool.backend.__path__): + module = tracetool.try_import("tracetool.backend." + modname)[1] + + public = getattr(module, "PUBLIC", False) + if only_public and not public: + continue + + doc = module.__doc__ + if doc is None: + doc = "" + doc = doc.strip().split("\n")[0] + + name = modname.replace("_", "-") + res.append((name, doc)) + return res + + +def exists(name): + """Return whether the given backend exists.""" + if len(name) == 0: + return False + name = name.replace("-", "_") + if name == "nop": + return True + return tracetool.try_import("tracetool.backend." + name)[1] + + +def compatible(backend, format): + """Whether a backend is compatible with the given format.""" + if not exists(backend): + raise ValueError("unknown backend: %s" % backend) + + if backend == "nop": + return True + else: + func = tracetool.try_import("tracetool.backend." + backend, + format, None)[1] + return func is not None + + +def _empty(events): + pass + +def generate(backend, format, events): + """Generate the per-event output for the given (backend, format) pair.""" + if not compatible(backend, format): + raise ValueError("backend '%s' not compatible with format '%s'" % + (backend, format)) + + if backend == "nop": + func = tracetool.try_import("tracetool.format." + format, + "nop", _empty)[1] + else: + func = tracetool.try_import("tracetool.backend." + backend, + format, None)[1] + + func(events) diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/format/__init__.py new file mode 100644 index 0000000..5b37c00 --- /dev/null +++ b/scripts/tracetool/format/__init__.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Format management. + + +Creating new formats +-------------------- + +A new format named 'foo-bar' corresponds to Python module +'tracetool/frontend/foo_bar.py'. + +A frontend module should provide a docstring, whose first non-empty line will be +considered its short description. + +All formats must generate their contents through the 'tracetool.out' routine. + + +Format functions +---------------- + +All the following functions are optional, and no output will be generated if +they do not exist. + +======== ======================================================================= +Function Description +======== ======================================================================= +begin Called to generate the format-specific file header. +end Called to generate the format-specific file footer. +nop Called to generate the per-event contents when the event is disabled or + the selected backend is 'nop'. +======== ======================================================================= +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +import pkgutil + +import tracetool + + +def get_list(): + """Get a list of (name, description) pairs.""" + res = [] + for _, modname, _ in pkgutil.iter_modules(tracetool.format.__path__): + module = tracetool.try_import("tracetool.format." + modname)[1] + + doc = module.__doc__ + if doc is None: + doc = "" + doc = doc.strip().split("\n")[0] + + name = modname.replace("_", "-") + res.append((name, doc)) + return res + + +def exists(name): + """Return whether the given format exists.""" + if len(name) == 0: + return False + return tracetool.try_import("tracetool.format." + name)[1] + + +def _empty(events): + pass + +def generate_begin(name, events): + """Generate the header of the format-specific file.""" + if not exists(name): + raise ValueError("unknown format: %s" % name) + + func = tracetool.try_import("tracetool.format." + name, + "begin", _empty)[1] + func(events) + +def generate_end(name, events): + """Generate the footer of the format-specific file.""" + if not exists(name): + raise ValueError("unknown format: %s" % name) + + func = tracetool.try_import("tracetool.format." + name, + "end", _empty)[1] + func(events) ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova @ 2012-03-27 15:17 ` Alon Levy 2012-03-27 17:47 ` Lluís Vilanova 2012-03-27 15:21 ` Alon Levy 2012-03-27 16:37 ` [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type Alon Levy 2 siblings, 1 reply; 18+ messages in thread From: Alon Levy @ 2012-03-27 15:17 UTC (permalink / raw) To: Lluís Vilanova; +Cc: stefanha, qemu-devel On Mon, Mar 26, 2012 at 07:37:50PM +0200, Lluís Vilanova wrote: > Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> Hi, Some comments inline. Alon > --- > Makefile.objs | 6 > Makefile.target | 13 - > configure | 4 > scripts/tracetool | 648 --------------------------------- > scripts/tracetool.py | 110 ++++++ > scripts/tracetool/__init__.py | 205 ++++++++++ > scripts/tracetool/backend/__init__.py | 114 ++++++ > scripts/tracetool/format/__init__.py | 91 +++++ > 8 files changed, 532 insertions(+), 659 deletions(-) > delete mode 100755 scripts/tracetool > create mode 100755 scripts/tracetool.py > create mode 100644 scripts/tracetool/__init__.py > create mode 100644 scripts/tracetool/backend/__init__.py > create mode 100644 scripts/tracetool/format/__init__.py > > diff --git a/Makefile.objs b/Makefile.objs > index 226b01d..8e56f48 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -373,12 +373,12 @@ else > trace.h: trace.h-timestamp > endif > trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") > @cmp -s $@ trace.h || cp $@ trace.h > > trace.c: trace.c-timestamp > trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN trace.c") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") > @cmp -s $@ trace.c || cp $@ trace.c > > trace.o: trace.c $(GENERATED_HEADERS) > @@ -391,7 +391,7 @@ trace-dtrace.h: trace-dtrace.dtrace > # rule file. So we use '.dtrace' instead > trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp > trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") > @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace > > trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) > diff --git a/Makefile.target b/Makefile.target > index 63cf769..fe28e8b 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -59,12 +59,13 @@ TARGET_TYPE=system > endif > > $(QEMU_PROG).stp: > - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \ > - --$(TRACE_BACKEND) \ > - --binary $(bindir)/$(QEMU_PROG) \ > - --target-arch $(TARGET_ARCH) \ > - --target-type $(TARGET_TYPE) \ > - --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > + --format=stap \ > + --backend=$(TRACE_BACKEND) \ > + --binary=$(bindir)/$(QEMU_PROG) \ > + --target-arch=$(TARGET_ARCH) \ > + --target-type=$(TARGET_TYPE) \ > + < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp") > else > stap: > endif > diff --git a/configure b/configure > index 8b4e3c1..c2d6117 100755 > --- a/configure > +++ b/configure > @@ -1097,7 +1097,7 @@ echo " --disable-docs disable documentation build" > echo " --disable-vhost-net disable vhost-net acceleration support" > echo " --enable-vhost-net enable vhost-net acceleration support" > echo " --enable-trace-backend=B Set trace backend" > -echo " Available backends:" $("$source_path"/scripts/tracetool --list-backends) > +echo " Available backends:" $($python "$source_path"/scripts/tracetool.py --list-backends) > echo " --with-trace-file=NAME Full PATH,NAME of file to store traces" > echo " Default:trace-<pid>" > echo " --disable-spice disable spice" > @@ -2654,7 +2654,7 @@ fi > ########################################## > # check if trace backend exists > > -sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null > +$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null > if test "$?" -ne 0 ; then > echo > echo "Error: invalid trace backend" > diff --git a/scripts/tracetool b/scripts/tracetool > deleted file mode 100755 > index 65bd0a1..0000000 > --- a/scripts/tracetool > +++ /dev/null > @@ -1,648 +0,0 @@ > -#!/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 > -} > - > -# Print a line without interpreting backslash escapes > -# > -# The built-in echo command may interpret backslash escapes without an option > -# to disable this behavior. > -puts() > -{ > - printf "%s\n" "$1" > -} > - > -# Get the name of a trace event > -get_name() > -{ > - local name > - name=${1%%\(*} > - echo "${name##* }" > -} > - > -# Get the given property of a trace event > -# 1: trace-events line > -# 2: property name > -# -> return 0 if property is present, or 1 otherwise > -has_property() > -{ > - local props prop > - props=${1%%\(*} > - props=${props% *} > - for prop in $props; do > - if [ "$prop" = "$2" ]; then > - return 0 > - fi > - done > - return 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 including double quotes for a trace event > -get_fmt() > -{ > - puts "${1#*)}" > -} > - > -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 "trace/simple.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 > - name=$(get_name "$1") > - args=$(get_args "$1") > - argc=$(get_argc "$1") > - > - 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 > - name=$(get_name "$1") > - cat <<EOF > -{.tp_name = "$name", .state=0}, > -EOF > - simple_event_num=$((simple_event_num + 1)) > -} > - > -linetoc_end_simple() > -{ > - cat <<EOF > -}; > -EOF > -} > - > -#STDERR > -linetoh_begin_stderr() > -{ > - cat <<EOF > -#include <stdio.h> > -#include "trace/stderr.h" > - > -extern TraceEvent trace_list[]; > -EOF > - > - stderr_event_num=0 > -} > - > -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) > -{ > - if (trace_list[$stderr_event_num].state != 0) { > - fprintf(stderr, "$name " $fmt "\n" $argnames); > - } > -} > -EOF > - stderr_event_num=$((stderr_event_num + 1)) > - > -} > - > -linetoh_end_stderr() > -{ > - cat <<EOF > -#define NR_TRACE_EVENTS $stderr_event_num > -EOF > -} > - > -linetoc_begin_stderr() > -{ > - cat <<EOF > -#include "trace.h" > - > -TraceEvent trace_list[] = { > -EOF > - stderr_event_num=0 > -} > - > -linetoc_stderr() > -{ > - local name > - name=$(get_name "$1") > - cat <<EOF > -{.tp_name = "$name", .state=0}, > -EOF > - stderr_event_num=$(($stderr_event_num + 1)) > -} > - > -linetoc_end_stderr() > -{ > - cat <<EOF > -}; > -EOF > -} > -#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 nameupper > - name=$(get_name "$1") > - args=$(get_args "$1") > - argnames=$(get_argnames "$1", ",") > - > - nameupper=`echo $name | tr '[:lower:]' '[:upper:]'` > - > - # Define an empty function for the trace event > - cat <<EOF > -static inline void trace_$name($args) { > - 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 > - name=$(get_name "$1") > - args=$(get_args "$1") > - > - # 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 > - name=$(get_name "$1") > - args=$(get_args "$1") > - arglist=$(get_argnames "$1", "") > - > - # 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 name NAME enabled > - 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 > - > - echo > - # Process the line. The nop backend handles disabled lines. > - if has_property "$str" "disable"; then > - "lineto$1_nop" "$str" > - enabled=0 > - else > - "$process_line" "$str" > - enabled=1 > - fi > - if [ "$1" = "h" ]; then > - name=$(get_name "$str") > - NAME=$(echo $name | tr '[:lower:]' '[:upper:]') > - echo "#define TRACE_${NAME}_ENABLED ${enabled}" > - 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 > diff --git a/scripts/tracetool.py b/scripts/tracetool.py > new file mode 100755 > index 0000000..22623ae > --- /dev/null > +++ b/scripts/tracetool.py > @@ -0,0 +1,110 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Foo. Real docstring missing. > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +import sys > +import getopt > + > +from tracetool import error_write, out > +import tracetool.backend > +import tracetool.format > + > + > +_SCRIPT = "" I don't understand the point of this, why not use sys.argv[0] directly? > + > +def error_opt(msg = None): > + if msg is not None: > + error_write("Error: " + msg + "\n") > + > + backend_descr = "\n".join([ " %-15s %s" % (n, d) > + for n,d in tracetool.backend.get_list() ]) > + format_descr = "\n".join([ " %-15s %s" % (n, d) > + for n,d in tracetool.format.get_list() ]) > + error_write("""\ > +Usage: %(script)s --format=<format> --backend=<backend> [<options>] > + > +Backends: > +%(backends)s > + > +Formats: > +%(formats)s > + > +Options: > + --help This help message. > + --list-backends Print list of available backends. > + --check-backend Check if the given backend is valid. > +""" % { > + "script" : _SCRIPT, > + "backends" : backend_descr, > + "formats" : format_descr, > + }) > + > + if msg is None: > + sys.exit(0) > + else: > + sys.exit(1) > + > + > +def main(args): > + global _SCRIPT > + _SCRIPT = sys.argv[0] > + > + long_opts = [ "backend=", "format=", "help", "list-backends", "check-backend" ] > + long_opts += [ "binary=", "target-type=", "target-arch=", "probe-prefix=" ] > + > + try: > + opts, args = getopt.getopt(args[1:], "", long_opts) > + except getopt.GetoptError as err: > + error_opt(str(err)) > + > + check_backend = False > + arg_backend = "" > + arg_format = "" > + for opt, arg in opts: > + if opt == "--help": > + error_opt() > + > + elif opt == "--backend": > + arg_backend = arg > + elif opt == "--format": > + arg_format = arg > + > + elif opt == "--list-backends": > + public_backends = tracetool.backend.get_list(only_public = True) > + out(", ".join([ b for b,_ in public_backends ])) > + sys.exit(0) > + elif opt == "--check-backend": > + check_backend = True > + > + else: > + error_opt("unhandled option: %s" % opt) > + > + if arg_backend is None: > + error_opt("backend not set") > + > + if check_backend: > + if tracetool.backend.exists(arg_backend): > + sys.exit(0) > + else: > + sys.exit(1) > + > + kwargs = {} > + > + try: > + tracetool.generate(sys.stdin, arg_format, arg_backend, **kwargs) > + except tracetool.TracetoolError as e: > + error_opt(str(e)) > + > +if __name__ == "__main__": > + main(sys.argv) > diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py > new file mode 100644 > index 0000000..d8e5cdd > --- /dev/null > +++ b/scripts/tracetool/__init__.py > @@ -0,0 +1,205 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Machinery for generating tracing-related intermediate files. > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +import re > +import sys > + > +import tracetool.format > +import tracetool.backend > + > + > +def error_write(*lines): > + """Write a set of error lines.""" > + sys.stderr.writelines("\n".join(lines) + "\n") > + > +def error(*lines): > + """Write a set of error lines and exit.""" > + error_write(*lines) > + sys.exit(1) > + > + > +def out(*lines): > + """Write a set of output lines.""" > + sys.stdout.writelines("\n".join(lines) + "\n") > + > + > +class Arguments: > + """Event arguments description. > + > + Parameters > + ---------- > + arg_str : str > + String describing the event arguments. > + """ > + > + def __init__ (self, arg_str): > + self._args = [] > + for arg in arg_str.split(","): > + arg = arg.strip() > + parts = arg.split() > + head, sep, tail = parts[-1].rpartition("*") > + parts = parts[:-1] > + if tail == "void": > + assert len(parts) == 0 and sep == "" > + continue > + arg_type = " ".join(parts + [ " ".join([head, sep]).strip() ]).strip() > + self._args.append((arg_type, tail)) > + > + def __iter__(self): > + """Iterate over the (type, name) pairs.""" > + return iter(self._args) > + > + def __len__(self): > + """Number of arguments.""" > + return len(self._args) > + > + def __str__(self): > + """String suitable for declaring function arguments.""" > + if len(self._args) == 0: > + return "void" > + else: > + return ", ".join([ " ".join([t, n]) for t,n in self._args ]) > + > + def names(self): > + """List of argument names.""" > + return [ name for _, name in self._args ] > + > + def types(self): > + """List of argument types.""" > + return [ type_ for type_, _ in self._args ] > + > + > +class Event(object): > + """Event description. > + > + Parameters > + ---------- > + line : str > + Line describing the event. > + > + Attributes > + ---------- > + name : str > + The event name. > + fmt : str > + The event format string. > + properties : set(str) > + Properties of the event. > + args : Arguments > + The event arguments. > + """ > + > + _CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?") > + > + _VALID_PROPS = set(["disable"]) > + > + def __init__(self, line): > + m = self._CRE.match(line) > + assert m is not None > + groups = m.groupdict('') > + self.name = groups["name"] > + self.fmt = groups["fmt"] > + self.properties = groups["props"].split() > + self.args = Arguments(groups["args"]) > + > + unknown_props = set(self.properties) - self._VALID_PROPS > + if len(unknown_props) > 0: > + raise ValueError("Unknown properties: %s" % ", ".join(unknown_props)) > + > + > +def _read_events(fobj): > + res = [] > + for line in fobj: > + if not line.strip(): > + continue > + if line.lstrip().startswith('#'): > + continue Tab got in. > + res.append(Event(line)) > + return res > + > + > +class TracetoolError (Exception): > + """Exception for calls to generate.""" > + pass > + > + > +def try_import(mod_name, attr_name = None, attr_default = None): > + """Try to import a module and get an attribute from it. > + > + Parameters > + ---------- > + mod_name : str > + Module name. > + attr_name : str, optional > + Name of an attribute in the module. > + attr_default : optional > + Default value if the attribute does not exist in the module. > + > + Returns > + ------- > + A pair indicating whether the module could be imported and the module or > + object or attribute value. > + """ > + mod_name = mod_name.replace("-", "_") > + try: > + module = __import__(mod_name, fromlist=["__package__"]) > + if attr_name is None: > + return True, module > + return True, getattr(module, str(attr_name), attr_default) > + except ImportError: > + return False, None > + > + > +def generate(fevents, format, backend, **options): > + """Generate the output for the given (format, backend) pair.""" > + # fix strange python error (UnboundLocalError tracetool) > + import tracetool > + > + if len(options) > 0: > + raise ValueError("unknown options: " + ", ".join(options)) > + > + format = str(format) > + if len(format) is 0: > + raise TracetoolError("format not set") > + mformat = format.replace("-", "_") > + if not tracetool.format.exists(mformat): > + raise TracetoolError("unknown format: %s" % format) > + > + backend = str(backend) > + if len(backend) is 0: > + raise TracetoolError("backend not set") > + mbackend = backend.replace("-", "_") > + if not tracetool.backend.exists(mbackend): > + raise TracetoolError("unknown backend: %s" % backend) > + > + if not tracetool.backend.compatible(mbackend, mformat): > + raise TracetoolError("backend '%s' not compatible with format '%s'" % > + (backend, format)) > + > + events = _read_events(fevents) > + > + if backend == "nop": > + ( e.properies.add("disable") for e in events ) > + > + tracetool.format.generate_begin(mformat, events) > + tracetool.backend.generate("nop", format, > + [ e > + for e in events > + if "disable" in e.properties ]) > + tracetool.backend.generate(backend, format, > + [ e > + for e in events > + if "disable" not in e.properties ]) > + tracetool.format.generate_end(mformat, events) > diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py > new file mode 100644 > index 0000000..23cad9f > --- /dev/null > +++ b/scripts/tracetool/backend/__init__.py > @@ -0,0 +1,114 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Backend management. > + > + > +Creating new backends > +--------------------- > + > +A new backend named 'foo-bar' corresponds to Python module > +'tracetool/backend/foo_bar.py'. > + > +A backend module should provide a docstring, whose first non-empty line will be > +considered its short description. > + > +All backends must generate their contents through the 'tracetool.out' routine. > + > + > +Backend attributes > +------------------ > + > +========= ==================================================================== > +Attribute Description > +========= ==================================================================== > +PUBLIC If exists and is set to 'True', the backend is considered "public". > +========= ==================================================================== > + > + > +Backend functions > +----------------- > + > +======== ======================================================================= > +Function Description > +======== ======================================================================= > +<format> Called to generate the format- and backend-specific code for each of > + the specified events. If the function does not exist, the backend is > + considered not compatible with the given format. > +======== ======================================================================= > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +import pkgutil > + > +import tracetool > + > + > +def get_list(only_public = False): > + """Get a list of (name, description) pairs.""" > + res = [("nop", "Tracing disabled.")] > + for _, modname, _ in pkgutil.iter_modules(tracetool.backend.__path__): > + module = tracetool.try_import("tracetool.backend." + modname)[1] > + Here module can be None if ImportError was raised in try_import. > + public = getattr(module, "PUBLIC", False) public will be False > + if only_public and not public: > + continue continue isn't reached if not only_public (default value) > + > + doc = module.__doc__ > + if doc is None: > + doc = "" > + doc = doc.strip().split("\n")[0] > + > + name = modname.replace("_", "-") > + res.append((name, doc)) > + return res > + > + > +def exists(name): > + """Return whether the given backend exists.""" > + if len(name) == 0: > + return False > + name = name.replace("-", "_") > + if name == "nop": > + return True > + return tracetool.try_import("tracetool.backend." + name)[1] > + > + > +def compatible(backend, format): > + """Whether a backend is compatible with the given format.""" > + if not exists(backend): > + raise ValueError("unknown backend: %s" % backend) > + > + if backend == "nop": > + return True > + else: > + func = tracetool.try_import("tracetool.backend." + backend, > + format, None)[1] > + return func is not None > + > + > +def _empty(events): > + pass > + > +def generate(backend, format, events): > + """Generate the per-event output for the given (backend, format) pair.""" > + if not compatible(backend, format): > + raise ValueError("backend '%s' not compatible with format '%s'" % > + (backend, format)) > + > + if backend == "nop": > + func = tracetool.try_import("tracetool.format." + format, > + "nop", _empty)[1] > + else: > + func = tracetool.try_import("tracetool.backend." + backend, > + format, None)[1] > + > + func(events) > diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/format/__init__.py > new file mode 100644 > index 0000000..5b37c00 > --- /dev/null > +++ b/scripts/tracetool/format/__init__.py > @@ -0,0 +1,91 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Format management. > + > + > +Creating new formats > +-------------------- > + > +A new format named 'foo-bar' corresponds to Python module > +'tracetool/frontend/foo_bar.py'. s/frontend/format/ And in later places. > + > +A frontend module should provide a docstring, whose first non-empty line will be > +considered its short description. > + > +All formats must generate their contents through the 'tracetool.out' routine. > + > + > +Format functions > +---------------- > + > +All the following functions are optional, and no output will be generated if > +they do not exist. > + > +======== ======================================================================= > +Function Description > +======== ======================================================================= > +begin Called to generate the format-specific file header. > +end Called to generate the format-specific file footer. > +nop Called to generate the per-event contents when the event is disabled or > + the selected backend is 'nop'. > +======== ======================================================================= > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +import pkgutil > + > +import tracetool > + > + > +def get_list(): > + """Get a list of (name, description) pairs.""" > + res = [] > + for _, modname, _ in pkgutil.iter_modules(tracetool.format.__path__): > + module = tracetool.try_import("tracetool.format." + modname)[1] > + > + doc = module.__doc__ > + if doc is None: > + doc = "" > + doc = doc.strip().split("\n")[0] > + > + name = modname.replace("_", "-") > + res.append((name, doc)) > + return res > + > + > +def exists(name): > + """Return whether the given format exists.""" > + if len(name) == 0: > + return False > + return tracetool.try_import("tracetool.format." + name)[1] > + > + > +def _empty(events): > + pass > + > +def generate_begin(name, events): > + """Generate the header of the format-specific file.""" > + if not exists(name): > + raise ValueError("unknown format: %s" % name) > + > + func = tracetool.try_import("tracetool.format." + name, > + "begin", _empty)[1] > + func(events) > + > +def generate_end(name, events): > + """Generate the footer of the format-specific file.""" > + if not exists(name): > + raise ValueError("unknown format: %s" % name) > + > + func = tracetool.try_import("tracetool.format." + name, > + "end", _empty)[1] > + func(events) > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules 2012-03-27 15:17 ` Alon Levy @ 2012-03-27 17:47 ` Lluís Vilanova 0 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-27 17:47 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Alon Levy writes: [...] >> + >> + >> +_SCRIPT = "" > I don't understand the point of this, why not use sys.argv[0] directly? [...] >> +def main(args): >> + global _SCRIPT >> + _SCRIPT = sys.argv[0] >> + Well, my idea is that it must work only with the arguments to 'main', without depending on any other system state. BTW, I fixed main to be "_SCRIPT = args[0]" instead of "sys.argv[0]" (otherwise it makes no sense). [...] >> +def get_list(only_public = False): >> + """Get a list of (name, description) pairs.""" >> + res = [("nop", "Tracing disabled.")] >> + for _, modname, _ in pkgutil.iter_modules(tracetool.backend.__path__): >> + module = tracetool.try_import("tracetool.backend." + modname)[1] >> + > Here module can be None if ImportError was raised in try_import. >> + public = getattr(module, "PUBLIC", False) > public will be False Not really; as it only tries to import files stemming from 'pkgutil.iter_modules', this should always succeed. In any case, I put a guard just in case someone puts a non-module file there (which should never happen). >> + if only_public and not public: >> + continue > continue isn't reached if not only_public (default value) Right, 'only_public' is only used sometimes (when handling "--list-backends" cmdline option). I'll send a new version once I put all the changes into my tree. Thanks for all the catches, Lluis -- "And it's much the same thing with knowledge, for whenever you learn something new, the whole world becomes that much richer." -- The Princess of Pure Reason, as told by Norton Juster in The Phantom Tollbooth ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova 2012-03-27 15:17 ` Alon Levy @ 2012-03-27 15:21 ` Alon Levy 2012-03-27 16:37 ` [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type Alon Levy 2 siblings, 0 replies; 18+ messages in thread From: Alon Levy @ 2012-03-27 15:21 UTC (permalink / raw) To: Lluís Vilanova; +Cc: stefanha, qemu-devel On Mon, Mar 26, 2012 at 07:37:50PM +0200, Lluís Vilanova wrote: An additional comment I forgot to add. > Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> > --- [snip] > + def __str__(self): > + """String suitable for declaring function arguments.""" > + if len(self._args) == 0: > + return "void" > + else: > + return ", ".join([ " ".join([t, n]) for t,n in self._args ]) > + Nice to have addition (for debugging mainly): + def __repr__(self): + """String suitable to recreate this instance.""" + return '%s("%s")' % (self.__class__.__name__, str(self)) + > + def names(self): > + """List of argument names.""" > + return [ name for _, name in self._args ] > + > + def types(self): > + """List of argument types.""" > + return [ type_ for type_, _ in self._args ] > + > + > +class Event(object): > + """Event description. > + > + Parameters > + ---------- > + line : str > + Line describing the event. > + > + Attributes > + ---------- > + name : str > + The event name. > + fmt : str > + The event format string. > + properties : set(str) > + Properties of the event. > + args : Arguments > + The event arguments. > + """ > + > + _CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?") > + > + _VALID_PROPS = set(["disable"]) > + > + def __init__(self, line): > + m = self._CRE.match(line) > + assert m is not None > + groups = m.groupdict('') > + self.name = groups["name"] > + self.fmt = groups["fmt"] > + self.properties = groups["props"].split() > + self.args = Arguments(groups["args"]) > + > + unknown_props = set(self.properties) - self._VALID_PROPS > + if len(unknown_props) > 0: > + raise ValueError("Unknown properties: %s" % ", ".join(unknown_props)) > + > + > +def _read_events(fobj): > + res = [] > + for line in fobj: > + if not line.strip(): > + continue > + if line.lstrip().startswith('#'): > + continue > + res.append(Event(line)) > + return res > + > + > +class TracetoolError (Exception): > + """Exception for calls to generate.""" > + pass > + > + > +def try_import(mod_name, attr_name = None, attr_default = None): > + """Try to import a module and get an attribute from it. > + > + Parameters > + ---------- > + mod_name : str > + Module name. > + attr_name : str, optional > + Name of an attribute in the module. > + attr_default : optional > + Default value if the attribute does not exist in the module. > + > + Returns > + ------- > + A pair indicating whether the module could be imported and the module or > + object or attribute value. > + """ > + mod_name = mod_name.replace("-", "_") > + try: > + module = __import__(mod_name, fromlist=["__package__"]) > + if attr_name is None: > + return True, module > + return True, getattr(module, str(attr_name), attr_default) > + except ImportError: > + return False, None > + > + > +def generate(fevents, format, backend, **options): > + """Generate the output for the given (format, backend) pair.""" > + # fix strange python error (UnboundLocalError tracetool) > + import tracetool > + > + if len(options) > 0: > + raise ValueError("unknown options: " + ", ".join(options)) > + > + format = str(format) > + if len(format) is 0: > + raise TracetoolError("format not set") > + mformat = format.replace("-", "_") > + if not tracetool.format.exists(mformat): > + raise TracetoolError("unknown format: %s" % format) > + > + backend = str(backend) > + if len(backend) is 0: > + raise TracetoolError("backend not set") > + mbackend = backend.replace("-", "_") > + if not tracetool.backend.exists(mbackend): > + raise TracetoolError("unknown backend: %s" % backend) > + > + if not tracetool.backend.compatible(mbackend, mformat): > + raise TracetoolError("backend '%s' not compatible with format '%s'" % > + (backend, format)) > + > + events = _read_events(fevents) > + > + if backend == "nop": > + ( e.properies.add("disable") for e in events ) > + > + tracetool.format.generate_begin(mformat, events) > + tracetool.backend.generate("nop", format, > + [ e > + for e in events > + if "disable" in e.properties ]) > + tracetool.backend.generate(backend, format, > + [ e > + for e in events > + if "disable" not in e.properties ]) > + tracetool.format.generate_end(mformat, events) > diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py > new file mode 100644 > index 0000000..23cad9f > --- /dev/null > +++ b/scripts/tracetool/backend/__init__.py > @@ -0,0 +1,114 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Backend management. > + > + > +Creating new backends > +--------------------- > + > +A new backend named 'foo-bar' corresponds to Python module > +'tracetool/backend/foo_bar.py'. > + > +A backend module should provide a docstring, whose first non-empty line will be > +considered its short description. > + > +All backends must generate their contents through the 'tracetool.out' routine. > + > + > +Backend attributes > +------------------ > + > +========= ==================================================================== > +Attribute Description > +========= ==================================================================== > +PUBLIC If exists and is set to 'True', the backend is considered "public". > +========= ==================================================================== > + > + > +Backend functions > +----------------- > + > +======== ======================================================================= > +Function Description > +======== ======================================================================= > +<format> Called to generate the format- and backend-specific code for each of > + the specified events. If the function does not exist, the backend is > + considered not compatible with the given format. > +======== ======================================================================= > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +import pkgutil > + > +import tracetool > + > + > +def get_list(only_public = False): > + """Get a list of (name, description) pairs.""" > + res = [("nop", "Tracing disabled.")] > + for _, modname, _ in pkgutil.iter_modules(tracetool.backend.__path__): > + module = tracetool.try_import("tracetool.backend." + modname)[1] > + > + public = getattr(module, "PUBLIC", False) > + if only_public and not public: > + continue > + > + doc = module.__doc__ > + if doc is None: > + doc = "" > + doc = doc.strip().split("\n")[0] > + > + name = modname.replace("_", "-") > + res.append((name, doc)) > + return res > + > + > +def exists(name): > + """Return whether the given backend exists.""" > + if len(name) == 0: > + return False > + name = name.replace("-", "_") > + if name == "nop": > + return True > + return tracetool.try_import("tracetool.backend." + name)[1] > + > + > +def compatible(backend, format): > + """Whether a backend is compatible with the given format.""" > + if not exists(backend): > + raise ValueError("unknown backend: %s" % backend) > + > + if backend == "nop": > + return True > + else: > + func = tracetool.try_import("tracetool.backend." + backend, > + format, None)[1] > + return func is not None > + > + > +def _empty(events): > + pass > + > +def generate(backend, format, events): > + """Generate the per-event output for the given (backend, format) pair.""" > + if not compatible(backend, format): > + raise ValueError("backend '%s' not compatible with format '%s'" % > + (backend, format)) > + > + if backend == "nop": > + func = tracetool.try_import("tracetool.format." + format, > + "nop", _empty)[1] > + else: > + func = tracetool.try_import("tracetool.backend." + backend, > + format, None)[1] > + > + func(events) > diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/format/__init__.py > new file mode 100644 > index 0000000..5b37c00 > --- /dev/null > +++ b/scripts/tracetool/format/__init__.py > @@ -0,0 +1,91 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Format management. > + > + > +Creating new formats > +-------------------- > + > +A new format named 'foo-bar' corresponds to Python module > +'tracetool/frontend/foo_bar.py'. > + > +A frontend module should provide a docstring, whose first non-empty line will be > +considered its short description. > + > +All formats must generate their contents through the 'tracetool.out' routine. > + > + > +Format functions > +---------------- > + > +All the following functions are optional, and no output will be generated if > +they do not exist. > + > +======== ======================================================================= > +Function Description > +======== ======================================================================= > +begin Called to generate the format-specific file header. > +end Called to generate the format-specific file footer. > +nop Called to generate the per-event contents when the event is disabled or > + the selected backend is 'nop'. > +======== ======================================================================= > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +import pkgutil > + > +import tracetool > + > + > +def get_list(): > + """Get a list of (name, description) pairs.""" > + res = [] > + for _, modname, _ in pkgutil.iter_modules(tracetool.format.__path__): > + module = tracetool.try_import("tracetool.format." + modname)[1] > + > + doc = module.__doc__ > + if doc is None: > + doc = "" > + doc = doc.strip().split("\n")[0] > + > + name = modname.replace("_", "-") > + res.append((name, doc)) > + return res > + > + > +def exists(name): > + """Return whether the given format exists.""" > + if len(name) == 0: > + return False > + return tracetool.try_import("tracetool.format." + name)[1] > + > + > +def _empty(events): > + pass > + > +def generate_begin(name, events): > + """Generate the header of the format-specific file.""" > + if not exists(name): > + raise ValueError("unknown format: %s" % name) > + > + func = tracetool.try_import("tracetool.format." + name, > + "begin", _empty)[1] > + func(events) > + > +def generate_end(name, events): > + """Generate the footer of the format-specific file.""" > + if not exists(name): > + raise ValueError("unknown format: %s" % name) > + > + func = tracetool.try_import("tracetool.format." + name, > + "end", _empty)[1] > + func(events) > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova 2012-03-27 15:17 ` Alon Levy 2012-03-27 15:21 ` Alon Levy @ 2012-03-27 16:37 ` Alon Levy 2012-03-27 18:01 ` Lluís Vilanova 2 siblings, 1 reply; 18+ messages in thread From: Alon Levy @ 2012-03-27 16:37 UTC (permalink / raw) To: qemu-devel, Lluís Vilanova; +Cc: stefanha Signed-off-by: Alon Levy <alevy@redhat.com> --- Makefile.objs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 8e56f48..0e33f4b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -373,12 +373,25 @@ else trace.h: trace.h-timestamp endif trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=h \ + --backend=$(TRACE_BACKEND) \ + --binary=$(bindir)/$(QEMU_PROG) \ + --target-arch=$(TARGET_ARCH) \ + --target-type=$(TARGET_TYPE) \ + --target-type=$(TARGET_TYPE) < $< > $@, \ + " GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=c \ + --backend=$(TRACE_BACKEND) \ + --binary=$(bindir)/$(QEMU_PROG) \ + --target-arch=$(TARGET_ARCH) \ + --target-type=$(TARGET_TYPE) < $< > $@, \ + " GEN trace.c") @cmp -s $@ trace.c || cp $@ trace.c trace.o: trace.c $(GENERATED_HEADERS) @@ -391,7 +404,13 @@ trace-dtrace.h: trace-dtrace.dtrace # rule file. So we use '.dtrace' instead trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=d \ + --backend=$(TRACE_BACKEND) \ + --binary=$(bindir)/$(QEMU_PROG) \ + --target-arch=$(TARGET_ARCH) \ + --target-type=$(TARGET_TYPE) < $< > $@, \ + " GEN trace-dtrace.dtrace") @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) -- 1.7.9.3 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type 2012-03-27 16:37 ` [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type Alon Levy @ 2012-03-27 18:01 ` Lluís Vilanova 2012-03-28 9:35 ` Alon Levy 0 siblings, 1 reply; 18+ messages in thread From: Lluís Vilanova @ 2012-03-27 18:01 UTC (permalink / raw) To: Alon Levy; +Cc: stefanha, qemu-devel Alon Levy writes: > Signed-off-by: Alon Levy <alevy@redhat.com> > --- > Makefile.objs | 25 ++++++++++++++++++++++--- > 1 file changed, 22 insertions(+), 3 deletions(-) > diff --git a/Makefile.objs b/Makefile.objs > index 8e56f48..0e33f4b 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -373,12 +373,25 @@ else > trace.h: trace.h-timestamp > endif > trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > + --format=h \ > + --backend=$(TRACE_BACKEND) \ > + --binary=$(bindir)/$(QEMU_PROG) \ > + --target-arch=$(TARGET_ARCH) \ > + --target-type=$(TARGET_TYPE) \ > + --target-type=$(TARGET_TYPE) < $< > $@, \ > + " GEN trace.h") > @cmp -s $@ trace.h || cp $@ trace.h > trace.c: trace.c-timestamp > trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > + --format=c \ > + --backend=$(TRACE_BACKEND) \ > + --binary=$(bindir)/$(QEMU_PROG) \ > + --target-arch=$(TARGET_ARCH) \ > + --target-type=$(TARGET_TYPE) < $< > $@, \ > + " GEN trace.c") > @cmp -s $@ trace.c || cp $@ trace.c > trace.o: trace.c $(GENERATED_HEADERS) > @@ -391,7 +404,13 @@ trace-dtrace.h: trace-dtrace.dtrace > # rule file. So we use '.dtrace' instead > trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp > trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > + --format=d \ > + --backend=$(TRACE_BACKEND) \ > + --binary=$(bindir)/$(QEMU_PROG) \ > + --target-arch=$(TARGET_ARCH) \ > + --target-type=$(TARGET_TYPE) < $< > $@, \ > + " GEN trace-dtrace.dtrace") > @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace > trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) > -- > 1.7.9.3 I don't see the reason for such a change, as in the current bash code it's not used except when generating files in the 'stap' format. Same applies to your change in tracetool.py when checking the binary/probe/etc options. Lluis -- "And it's much the same thing with knowledge, for whenever you learn something new, the whole world becomes that much richer." -- The Princess of Pure Reason, as told by Norton Juster in The Phantom Tollbooth ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type 2012-03-27 18:01 ` Lluís Vilanova @ 2012-03-28 9:35 ` Alon Levy 2012-03-28 10:29 ` Lluís Vilanova 0 siblings, 1 reply; 18+ messages in thread From: Alon Levy @ 2012-03-28 9:35 UTC (permalink / raw) To: Lluís Vilanova; +Cc: stefanha, qemu-devel On Tue, Mar 27, 2012 at 08:01:54PM +0200, Lluís Vilanova wrote: > Alon Levy writes: > > > Signed-off-by: Alon Levy <alevy@redhat.com> > > --- > > Makefile.objs | 25 ++++++++++++++++++++++--- > > 1 file changed, 22 insertions(+), 3 deletions(-) > > > diff --git a/Makefile.objs b/Makefile.objs > > index 8e56f48..0e33f4b 100644 > > --- a/Makefile.objs > > +++ b/Makefile.objs > > @@ -373,12 +373,25 @@ else > > trace.h: trace.h-timestamp > > endif > > trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > > - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h") > > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > > + --format=h \ > > + --backend=$(TRACE_BACKEND) \ > > + --binary=$(bindir)/$(QEMU_PROG) \ > > + --target-arch=$(TARGET_ARCH) \ > > + --target-type=$(TARGET_TYPE) \ > > + --target-type=$(TARGET_TYPE) < $< > $@, \ > > + " GEN trace.h") > > @cmp -s $@ trace.h || cp $@ trace.h > > > trace.c: trace.c-timestamp > > trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > > - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c") > > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > > + --format=c \ > > + --backend=$(TRACE_BACKEND) \ > > + --binary=$(bindir)/$(QEMU_PROG) \ > > + --target-arch=$(TARGET_ARCH) \ > > + --target-type=$(TARGET_TYPE) < $< > $@, \ > > + " GEN trace.c") > > @cmp -s $@ trace.c || cp $@ trace.c > > > trace.o: trace.c $(GENERATED_HEADERS) > > @@ -391,7 +404,13 @@ trace-dtrace.h: trace-dtrace.dtrace > > # rule file. So we use '.dtrace' instead > > trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp > > trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak > > - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace") > > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ > > + --format=d \ > > + --backend=$(TRACE_BACKEND) \ > > + --binary=$(bindir)/$(QEMU_PROG) \ > > + --target-arch=$(TARGET_ARCH) \ > > + --target-type=$(TARGET_TYPE) < $< > $@, \ > > + " GEN trace-dtrace.dtrace") > > @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace > > > trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) > > -- > > 1.7.9.3 > > I don't see the reason for such a change, as in the current bash code it's not > used except when generating files in the 'stap' format. Have you tried building with trace backend dtrace? without those changed it breaks because tracetool.py requires both target_arch and target_type for dtrace backend. Either change the source or change the invocation. I thought the later is better, hence this patch. > > Same applies to your change in tracetool.py when checking the binary/probe/etc > options. > > > Lluis > > -- > "And it's much the same thing with knowledge, for whenever you learn > something new, the whole world becomes that much richer." > -- The Princess of Pure Reason, as told by Norton Juster in The Phantom > Tollbooth ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type 2012-03-28 9:35 ` Alon Levy @ 2012-03-28 10:29 ` Lluís Vilanova 0 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-28 10:29 UTC (permalink / raw) To: Alon Levy; +Cc: stefanha, qemu-devel Alon Levy writes: [...] >> I don't see the reason for such a change, as in the current bash code it's not >> used except when generating files in the 'stap' format. > Have you tried building with trace backend dtrace? without those changed > it breaks because tracetool.py requires both target_arch and target_type > for dtrace backend. Either change the source or change the invocation. I > thought the later is better, hence this patch. If you're referring to your changes in tracetool.py related to this (when checking binary/prefix/etc), it should be fixed in v3 without resorting to your changes: - if format == "stap": + if arg_format == "stap": Instead of your proposal: - if format == "stap": + if arg_backend == "dtrace": I didn't try to compile the resulting dtrace files (they should be the same), but tracetool does not fail with the aforementioned changes. Thanks, Lluis -- "And it's much the same thing with knowledge, for whenever you learn something new, the whole world becomes that much richer." -- The Princess of Pure Reason, as told by Norton Juster in The Phantom Tollbooth ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 2/8] tracetool: Add module for the 'c' format 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova @ 2012-03-26 17:37 ` Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 3/8] tracetool: Add module for the 'h' format Lluís Vilanova ` (5 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:37 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- scripts/tracetool/format/c.py | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) create mode 100644 scripts/tracetool/format/c.py diff --git a/scripts/tracetool/format/c.py b/scripts/tracetool/format/c.py new file mode 100644 index 0000000..35555ae --- /dev/null +++ b/scripts/tracetool/format/c.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .c file. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */') ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 3/8] tracetool: Add module for the 'h' format 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 2/8] tracetool: Add module for the 'c' format Lluís Vilanova @ 2012-03-26 17:38 ` Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 4/8] tracetool: Add support for the 'stderr' backend Lluís Vilanova ` (4 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:38 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- scripts/tracetool/format/h.py | 45 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 45 insertions(+), 0 deletions(-) create mode 100644 scripts/tracetool/format/h.py diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py new file mode 100644 index 0000000..41a3e2b --- /dev/null +++ b/scripts/tracetool/format/h.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .h file. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#ifndef TRACE_H', + '#define TRACE_H', + '', + '#include "qemu-common.h"') + +def end(events): + for e in events: + if "disable" in e.properties: + enabled = 0 + else: + enabled = 1 + out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled)) + out('', + '#endif /* TRACE_H */') + +def nop(events): + for e in events: + out('', + 'static inline void trace_%(name)s(%(args)s)' % { + 'name': e.name, + 'args': e.args + }, + '{', + '}') ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 4/8] tracetool: Add support for the 'stderr' backend 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova ` (2 preceding siblings ...) 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 3/8] tracetool: Add module for the 'h' format Lluís Vilanova @ 2012-03-26 17:38 ` Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 5/8] tracetool: Add support for the 'simple' backend Lluís Vilanova ` (3 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:38 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- scripts/tracetool/backend/stderr.py | 61 +++++++++++++++++++++++++++++++++++ 1 files changed, 61 insertions(+), 0 deletions(-) create mode 100644 scripts/tracetool/backend/stderr.py diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py new file mode 100644 index 0000000..5f9abcd --- /dev/null +++ b/scripts/tracetool/backend/stderr.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Stderr built-in backend. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +PUBLIC = True + + +def c(events): + out('#include "trace.h"', + '', + 'TraceEvent trace_list[] = {') + + for e in events: + out('{.tp_name = "%(name)s", .state=0},' % + { + 'name': e.name, + }) + + out('};') + +def h(events): + out('#include <stdio.h>', + '#include "trace/stderr.h"', + '', + 'extern TraceEvent trace_list[];') + + for num, e in enumerate(events): + argnames = ", ".join(e.args.names()) + if len(e.args) > 0: + argnames = ", " + argnames + + out(''' +static inline void trace_%(name)s(%(args)s) +{ + if (trace_list[%(event_num)s].state != 0) { + fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s); + } +}''' % { + 'name': e.name, + 'args': e.args, + 'event_num': num, + 'fmt': e.fmt, + 'argnames': argnames, + }) + + out('', + '#define NR_TRACE_EVENTS %d' % len(events)) ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 5/8] tracetool: Add support for the 'simple' backend 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova ` (3 preceding siblings ...) 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 4/8] tracetool: Add support for the 'stderr' backend Lluís Vilanova @ 2012-03-26 17:38 ` Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 6/8] tracetool: Add support for the 'ust' backend Lluís Vilanova ` (2 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:38 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- scripts/tracetool/backend/simple.py | 60 +++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) create mode 100644 scripts/tracetool/backend/simple.py diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py new file mode 100644 index 0000000..fea0a37 --- /dev/null +++ b/scripts/tracetool/backend/simple.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Simple built-in backend. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +PUBLIC = True + + +def c(events): + out('#include "trace.h"', + '', + 'TraceEvent trace_list[] = {') + + for e in events: + out('{.tp_name = "%(name)s", .state=0},' % { + 'name': e.name, + }) + + out('};') + +def h(events): + out('#include "trace/simple.h"', + '') + + for num, e in enumerate(events): + if len(e.args): + argstr = e.args.names() + arg_prefix = ', (uint64_t)(uintptr_t)' + cast_args = arg_prefix + arg_prefix.join(argstr) + simple_args = (str(num) + cast_args) + else: + simple_args = str(num) + + out('''\ +static inline void trace_%(name)s(%(args)s) +{ + trace%(argc)d(%(trace_args)s); +} +''' % { + 'name': e.name, + 'args': e.args, + 'argc': len(e.args), + 'trace_args': simple_args, + }) + + out('#define NR_TRACE_EVENTS %d' % len(events)) + out('extern TraceEvent trace_list[NR_TRACE_EVENTS];') ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 6/8] tracetool: Add support for the 'ust' backend 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova ` (4 preceding siblings ...) 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 5/8] tracetool: Add support for the 'simple' backend Lluís Vilanova @ 2012-03-26 17:38 ` Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 8/8] tracetool: Add MAINTAINERS info Lluís Vilanova 7 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:38 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- scripts/tracetool/backend/ust.py | 102 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 102 insertions(+), 0 deletions(-) create mode 100644 scripts/tracetool/backend/ust.py diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py new file mode 100644 index 0000000..6871373 --- /dev/null +++ b/scripts/tracetool/backend/ust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +LTTng User Space Tracing backend. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +PUBLIC = True + + +def c(events): + out('#include <ust/marker.h>', + '#undef mutex_lock', + '#undef mutex_unlock', + '#undef inline', + '#undef wmb', + '#include "trace.h"') + + for e in events: + argnames = ", ".join(e.args.names()) + if len(e.args) > 0: + argnames = ', ' + argnames + + out(''' +DEFINE_TRACE(ust_%(name)s); + +static void ust_%(name)s_probe(%(args)s) +{ + trace_mark(ust, %(name)s, %(fmt)s%(argnames)s); +}''' % + { + 'name': e.name, + 'args': e.args, + 'fmt': e.fmt, + 'argnames': argnames, + }) + + else: + out(''' +DEFINE_TRACE(ust_%(name)s); + +static void ust_%(name)s_probe(%(args)s) +{ + trace_mark(ust, %(name)s, UST_MARKER_NOARGS); +}''' % + { + 'name': e.name, + 'args': e.args, + }) + + # register probes + out('', + 'static void __attribute__((constructor)) trace_init(void)', + '{') + + for e in events: + out(' register_trace_ust_%(name)s(ust_%(name)s_probe);' % + { + 'name': e.name, + }) + + out('}') + + +def h(events): + out('#include <ust/tracepoint.h>', + '#undef mutex_lock', + '#undef mutex_unlock', + '#undef inline', + '#undef wmb') + + for e in events: + if len(e.args) > 0: + out(''' +DECLARE_TRACE(ust_%(name)s, TP_PROTO(%(args)s), TP_ARGS(%(argnames)s)); +#define trace_%(name)s trace_ust_%(name)s''' % + { + 'name': e.name, + 'args': e.args, + 'argnames': ", ".join(e.args.names()) + }) + + else: + out(''' +_DECLARE_TRACEPOINT_NOARGS(ust_%(name)s); +#define trace_%(name)s trace_ust_%(name)s''' % + { + 'name': e.name, + }) + + out() ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova ` (5 preceding siblings ...) 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 6/8] tracetool: Add support for the 'ust' backend Lluís Vilanova @ 2012-03-26 17:38 ` Lluís Vilanova 2012-03-27 15:19 ` Alon Levy 2012-03-27 16:20 ` Alon Levy 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 8/8] tracetool: Add MAINTAINERS info Lluís Vilanova 7 siblings, 2 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:38 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- scripts/tracetool.py | 31 ++++++++++ scripts/tracetool/__init__.py | 8 +++ scripts/tracetool/backend/dtrace.py | 104 +++++++++++++++++++++++++++++++++++ scripts/tracetool/format/d.py | 20 +++++++ scripts/tracetool/format/stap.py | 20 +++++++ 5 files changed, 183 insertions(+), 0 deletions(-) create mode 100644 scripts/tracetool/backend/dtrace.py create mode 100644 scripts/tracetool/format/d.py create mode 100644 scripts/tracetool/format/stap.py diff --git a/scripts/tracetool.py b/scripts/tracetool.py index 22623ae..2dd9da0 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -44,6 +44,11 @@ Options: --help This help message. --list-backends Print list of available backends. --check-backend Check if the given backend is valid. + --binary <path> Full path to QEMU binary. + --target-type <type> QEMU emulator target type ('system' or 'user'). + --target-arch <arch> QEMU emulator target arch. + --probe-prefix <prefix> Prefix for dtrace probe names + (default: qemu-<target-type>-<target-arch>).\ """ % { "script" : _SCRIPT, "backends" : backend_descr, @@ -71,6 +76,10 @@ def main(args): check_backend = False arg_backend = "" arg_format = "" + binary = None + target_type = None + target_arch = None + probe_prefix = None for opt, arg in opts: if opt == "--help": error_opt() @@ -87,6 +96,15 @@ def main(args): elif opt == "--check-backend": check_backend = True + elif opt == "--binary": + binary = arg + elif opt == '--target-type': + target_type = arg + elif opt == '--target-arch': + target_arch = arg + elif opt == '--probe-prefix': + probe_prefix = arg + else: error_opt("unhandled option: %s" % opt) @@ -101,6 +119,19 @@ def main(args): kwargs = {} + if format == "stap": + if binary is None: + error_opt("--binary is required for SystemTAP tapset generator") + if probe_prefix is None and target_type is None: + error_opt("--target-type is required for SystemTAP tapset generator") + if probe_prefix is None and target_arch is None: + error_opt("--target-arch is required for SystemTAP tapset generator") + + if probe_prefix is None: + probe_prefix = ".".join([ "qemu", target_type, target_arch ]) + kwargs["binary"] = binary + kwargs["probe_prefix"] = probe_prefix + try: tracetool.generate(sys.stdin, arg_format, arg_backend, **kwargs) except tracetool.TracetoolError as e: diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index d8e5cdd..d21f88a 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -167,6 +167,9 @@ def generate(fevents, format, backend, **options): # fix strange python error (UnboundLocalError tracetool) import tracetool + binary = options.pop("binary", None) + probe_prefix = options.pop("probe_prefix", None) + if len(options) > 0: raise ValueError("unknown options: " + ", ".join(options)) @@ -188,6 +191,11 @@ def generate(fevents, format, backend, **options): raise TracetoolError("backend '%s' not compatible with format '%s'" % (backend, format)) + if backend == "dtrace": + import tracetool.backend.dtrace + tracetool.backend.dtrace.BINARY = binary + tracetool.backend.dtrace.PROBEPREFIX = probe_prefix + events = _read_events(fevents) if backend == "nop": diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py new file mode 100644 index 0000000..7c2051c --- /dev/null +++ b/scripts/tracetool/backend/dtrace.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +DTrace/SystemTAP backend. +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +PUBLIC = True + + +PROBEPREFIX = None + +def _probeprefix(): + if PROBEPREFIX is None: + raise ValueError("you must set PROBEPREFIX") + return PROBEPREFIX + + +BINARY = None + +def _binary(): + if BINARY is None: + raise ValueError("you must set BINARY") + return BINARY + + +def c(events): + pass + + +def h(events): + out('#include "trace-dtrace.h"', + '') + + for e in events: + out('''static inline void trace_%(name)s(%(args)s) { + QEMU_%(uppername)s(%(argnames)s); +} +''' % + { + 'name': e.name, + 'args': e.args, + 'uppername': e.name.upper(), + 'argnames': ", ".join(e.args.names()), + }) + + +def d(events): + out('provider qemu {') + + for e in events: + args = e.args + + # DTrace provider syntax expects foo() for empty + # params, not foo(void) + if args == 'void': + args = '' + + # Define prototype for probe arguments + out('', + 'probe %(name)s(%(args)s);' % + { + 'name': e.name, + 'args': args + }) + + out('', + '};') + + +def stap(events): + for e in events: + # Define prototype for probe arguments + out('probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")' % + { + 'probeprefix': _probeprefix(), + 'name': e.name, + 'binary': _binary(), + }, + '{') + + i = 1 + if len(e.args) > 0: + for name in e.args.names(): + # 'limit' is a reserved keyword + if name == 'limit': + name = '_limit' + out(' %s = $arg%d;' % (name.lstrip(), i)) + i += 1 + + out('}') + + out() diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py new file mode 100644 index 0000000..a2d5947 --- /dev/null +++ b/scripts/tracetool/format/d.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .d file (DTrace only). +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */') diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py new file mode 100644 index 0000000..50a4c69 --- /dev/null +++ b/scripts/tracetool/format/stap.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Generate .stp file (DTrace with SystemTAP only). +""" + +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefanha@linux.vnet.ibm.com" + + +from tracetool import out + + +def begin(events): + out('/* This file is autogenerated by tracetool, do not edit. */') ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend Lluís Vilanova @ 2012-03-27 15:19 ` Alon Levy 2012-03-27 16:20 ` Alon Levy 1 sibling, 0 replies; 18+ messages in thread From: Alon Levy @ 2012-03-27 15:19 UTC (permalink / raw) To: Lluís Vilanova; +Cc: stefanha, qemu-devel On Mon, Mar 26, 2012 at 07:38:23PM +0200, Lluís Vilanova wrote: > Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> > --- > scripts/tracetool.py | 31 ++++++++++ > scripts/tracetool/__init__.py | 8 +++ > scripts/tracetool/backend/dtrace.py | 104 +++++++++++++++++++++++++++++++++++ > scripts/tracetool/format/d.py | 20 +++++++ > scripts/tracetool/format/stap.py | 20 +++++++ > 5 files changed, 183 insertions(+), 0 deletions(-) > create mode 100644 scripts/tracetool/backend/dtrace.py > create mode 100644 scripts/tracetool/format/d.py > create mode 100644 scripts/tracetool/format/stap.py > > diff --git a/scripts/tracetool.py b/scripts/tracetool.py > index 22623ae..2dd9da0 100755 > --- a/scripts/tracetool.py > +++ b/scripts/tracetool.py > @@ -44,6 +44,11 @@ Options: > --help This help message. > --list-backends Print list of available backends. > --check-backend Check if the given backend is valid. > + --binary <path> Full path to QEMU binary. > + --target-type <type> QEMU emulator target type ('system' or 'user'). > + --target-arch <arch> QEMU emulator target arch. > + --probe-prefix <prefix> Prefix for dtrace probe names > + (default: qemu-<target-type>-<target-arch>).\ > """ % { > "script" : _SCRIPT, > "backends" : backend_descr, > @@ -71,6 +76,10 @@ def main(args): > check_backend = False > arg_backend = "" > arg_format = "" > + binary = None > + target_type = None > + target_arch = None > + probe_prefix = None > for opt, arg in opts: > if opt == "--help": > error_opt() > @@ -87,6 +96,15 @@ def main(args): > elif opt == "--check-backend": > check_backend = True > > + elif opt == "--binary": > + binary = arg > + elif opt == '--target-type': > + target_type = arg > + elif opt == '--target-arch': > + target_arch = arg > + elif opt == '--probe-prefix': > + probe_prefix = arg > + > else: > error_opt("unhandled option: %s" % opt) > > @@ -101,6 +119,19 @@ def main(args): > > kwargs = {} > > + if format == "stap": > + if binary is None: > + error_opt("--binary is required for SystemTAP tapset generator") > + if probe_prefix is None and target_type is None: > + error_opt("--target-type is required for SystemTAP tapset generator") > + if probe_prefix is None and target_arch is None: > + error_opt("--target-arch is required for SystemTAP tapset generator") > + > + if probe_prefix is None: > + probe_prefix = ".".join([ "qemu", target_type, target_arch ]) > + kwargs["binary"] = binary > + kwargs["probe_prefix"] = probe_prefix > + > try: > tracetool.generate(sys.stdin, arg_format, arg_backend, **kwargs) > except tracetool.TracetoolError as e: > diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py > index d8e5cdd..d21f88a 100644 > --- a/scripts/tracetool/__init__.py > +++ b/scripts/tracetool/__init__.py > @@ -167,6 +167,9 @@ def generate(fevents, format, backend, **options): > # fix strange python error (UnboundLocalError tracetool) > import tracetool > > + binary = options.pop("binary", None) > + probe_prefix = options.pop("probe_prefix", None) > + > if len(options) > 0: > raise ValueError("unknown options: " + ", ".join(options)) > > @@ -188,6 +191,11 @@ def generate(fevents, format, backend, **options): > raise TracetoolError("backend '%s' not compatible with format '%s'" % > (backend, format)) > > + if backend == "dtrace": > + import tracetool.backend.dtrace > + tracetool.backend.dtrace.BINARY = binary > + tracetool.backend.dtrace.PROBEPREFIX = probe_prefix > + > events = _read_events(fevents) > > if backend == "nop": > diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py > new file mode 100644 > index 0000000..7c2051c > --- /dev/null > +++ b/scripts/tracetool/backend/dtrace.py > @@ -0,0 +1,104 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +DTrace/SystemTAP backend. > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +from tracetool import out > + > + > +PUBLIC = True > + > + > +PROBEPREFIX = None > + > +def _probeprefix(): > + if PROBEPREFIX is None: > + raise ValueError("you must set PROBEPREFIX") > + return PROBEPREFIX > + > + > +BINARY = None > + > +def _binary(): > + if BINARY is None: > + raise ValueError("you must set BINARY") > + return BINARY > + > + > +def c(events): > + pass > + > + > +def h(events): > + out('#include "trace-dtrace.h"', > + '') > + > + for e in events: > + out('''static inline void trace_%(name)s(%(args)s) { > + QEMU_%(uppername)s(%(argnames)s); > +} > +''' % > + { > + 'name': e.name, > + 'args': e.args, > + 'uppername': e.name.upper(), > + 'argnames': ", ".join(e.args.names()), > + }) > + > + > +def d(events): > + out('provider qemu {') > + > + for e in events: > + args = e.args > + > + # DTrace provider syntax expects foo() for empty > + # params, not foo(void) > + if args == 'void': This fails. since args is now an Arguments instace. Fixed by changing to: + if str(args) == 'void': > + args = '' > + > + # Define prototype for probe arguments > + out('', > + 'probe %(name)s(%(args)s);' % > + { > + 'name': e.name, > + 'args': args > + }) > + > + out('', > + '};') > + > + > +def stap(events): > + for e in events: > + # Define prototype for probe arguments > + out('probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")' % > + { > + 'probeprefix': _probeprefix(), > + 'name': e.name, > + 'binary': _binary(), > + }, > + '{') > + > + i = 1 > + if len(e.args) > 0: > + for name in e.args.names(): > + # 'limit' is a reserved keyword > + if name == 'limit': > + name = '_limit' > + out(' %s = $arg%d;' % (name.lstrip(), i)) > + i += 1 > + > + out('}') > + > + out() > diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py > new file mode 100644 > index 0000000..a2d5947 > --- /dev/null > +++ b/scripts/tracetool/format/d.py > @@ -0,0 +1,20 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Generate .d file (DTrace only). > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +from tracetool import out > + > + > +def begin(events): > + out('/* This file is autogenerated by tracetool, do not edit. */') > diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py > new file mode 100644 > index 0000000..50a4c69 > --- /dev/null > +++ b/scripts/tracetool/format/stap.py > @@ -0,0 +1,20 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Generate .stp file (DTrace with SystemTAP only). > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +from tracetool import out > + > + > +def begin(events): > + out('/* This file is autogenerated by tracetool, do not edit. */') > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend Lluís Vilanova 2012-03-27 15:19 ` Alon Levy @ 2012-03-27 16:20 ` Alon Levy 1 sibling, 0 replies; 18+ messages in thread From: Alon Levy @ 2012-03-27 16:20 UTC (permalink / raw) To: Lluís Vilanova; +Cc: stefanha, qemu-devel On Mon, Mar 26, 2012 at 07:38:23PM +0200, Lluís Vilanova wrote: > Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> > --- Additional comment inline. > scripts/tracetool.py | 31 ++++++++++ > scripts/tracetool/__init__.py | 8 +++ > scripts/tracetool/backend/dtrace.py | 104 +++++++++++++++++++++++++++++++++++ > scripts/tracetool/format/d.py | 20 +++++++ > scripts/tracetool/format/stap.py | 20 +++++++ > 5 files changed, 183 insertions(+), 0 deletions(-) > create mode 100644 scripts/tracetool/backend/dtrace.py > create mode 100644 scripts/tracetool/format/d.py > create mode 100644 scripts/tracetool/format/stap.py > > diff --git a/scripts/tracetool.py b/scripts/tracetool.py > index 22623ae..2dd9da0 100755 > --- a/scripts/tracetool.py > +++ b/scripts/tracetool.py > @@ -44,6 +44,11 @@ Options: > --help This help message. > --list-backends Print list of available backends. > --check-backend Check if the given backend is valid. > + --binary <path> Full path to QEMU binary. > + --target-type <type> QEMU emulator target type ('system' or 'user'). > + --target-arch <arch> QEMU emulator target arch. > + --probe-prefix <prefix> Prefix for dtrace probe names > + (default: qemu-<target-type>-<target-arch>).\ > """ % { > "script" : _SCRIPT, > "backends" : backend_descr, > @@ -71,6 +76,10 @@ def main(args): > check_backend = False > arg_backend = "" > arg_format = "" > + binary = None > + target_type = None > + target_arch = None > + probe_prefix = None > for opt, arg in opts: > if opt == "--help": > error_opt() > @@ -87,6 +96,15 @@ def main(args): > elif opt == "--check-backend": > check_backend = True > > + elif opt == "--binary": > + binary = arg > + elif opt == '--target-type': > + target_type = arg > + elif opt == '--target-arch': > + target_arch = arg > + elif opt == '--probe-prefix': > + probe_prefix = arg > + > else: > error_opt("unhandled option: %s" % opt) > > @@ -101,6 +119,19 @@ def main(args): > > kwargs = {} > > + if format == "stap": Needs to be + if arg_backed == "dtrace": > + if binary is None: > + error_opt("--binary is required for SystemTAP tapset generator") > + if probe_prefix is None and target_type is None: > + error_opt("--target-type is required for SystemTAP tapset generator") > + if probe_prefix is None and target_arch is None: > + error_opt("--target-arch is required for SystemTAP tapset generator") > + > + if probe_prefix is None: > + probe_prefix = ".".join([ "qemu", target_type, target_arch ]) > + kwargs["binary"] = binary > + kwargs["probe_prefix"] = probe_prefix > + > try: > tracetool.generate(sys.stdin, arg_format, arg_backend, **kwargs) > except tracetool.TracetoolError as e: > diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py > index d8e5cdd..d21f88a 100644 > --- a/scripts/tracetool/__init__.py > +++ b/scripts/tracetool/__init__.py > @@ -167,6 +167,9 @@ def generate(fevents, format, backend, **options): > # fix strange python error (UnboundLocalError tracetool) > import tracetool > > + binary = options.pop("binary", None) > + probe_prefix = options.pop("probe_prefix", None) > + > if len(options) > 0: > raise ValueError("unknown options: " + ", ".join(options)) > > @@ -188,6 +191,11 @@ def generate(fevents, format, backend, **options): > raise TracetoolError("backend '%s' not compatible with format '%s'" % > (backend, format)) > > + if backend == "dtrace": > + import tracetool.backend.dtrace > + tracetool.backend.dtrace.BINARY = binary > + tracetool.backend.dtrace.PROBEPREFIX = probe_prefix > + > events = _read_events(fevents) > > if backend == "nop": > diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py > new file mode 100644 > index 0000000..7c2051c > --- /dev/null > +++ b/scripts/tracetool/backend/dtrace.py > @@ -0,0 +1,104 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +DTrace/SystemTAP backend. > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +from tracetool import out > + > + > +PUBLIC = True > + > + > +PROBEPREFIX = None > + > +def _probeprefix(): > + if PROBEPREFIX is None: > + raise ValueError("you must set PROBEPREFIX") > + return PROBEPREFIX > + > + > +BINARY = None > + > +def _binary(): > + if BINARY is None: > + raise ValueError("you must set BINARY") > + return BINARY > + > + > +def c(events): > + pass > + > + > +def h(events): > + out('#include "trace-dtrace.h"', > + '') > + > + for e in events: > + out('''static inline void trace_%(name)s(%(args)s) { > + QEMU_%(uppername)s(%(argnames)s); > +} > +''' % > + { > + 'name': e.name, > + 'args': e.args, > + 'uppername': e.name.upper(), > + 'argnames': ", ".join(e.args.names()), > + }) > + > + > +def d(events): > + out('provider qemu {') > + > + for e in events: > + args = e.args > + > + # DTrace provider syntax expects foo() for empty > + # params, not foo(void) > + if args == 'void': > + args = '' > + > + # Define prototype for probe arguments > + out('', > + 'probe %(name)s(%(args)s);' % > + { > + 'name': e.name, > + 'args': args > + }) > + > + out('', > + '};') > + > + > +def stap(events): > + for e in events: > + # Define prototype for probe arguments > + out('probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")' % > + { > + 'probeprefix': _probeprefix(), > + 'name': e.name, > + 'binary': _binary(), > + }, > + '{') > + > + i = 1 > + if len(e.args) > 0: > + for name in e.args.names(): > + # 'limit' is a reserved keyword > + if name == 'limit': > + name = '_limit' > + out(' %s = $arg%d;' % (name.lstrip(), i)) > + i += 1 > + > + out('}') > + > + out() > diff --git a/scripts/tracetool/format/d.py b/scripts/tracetool/format/d.py > new file mode 100644 > index 0000000..a2d5947 > --- /dev/null > +++ b/scripts/tracetool/format/d.py > @@ -0,0 +1,20 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Generate .d file (DTrace only). > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +from tracetool import out > + > + > +def begin(events): > + out('/* This file is autogenerated by tracetool, do not edit. */') > diff --git a/scripts/tracetool/format/stap.py b/scripts/tracetool/format/stap.py > new file mode 100644 > index 0000000..50a4c69 > --- /dev/null > +++ b/scripts/tracetool/format/stap.py > @@ -0,0 +1,20 @@ > +#!/usr/bin/env python > +# -*- coding: utf-8 -*- > + > +""" > +Generate .stp file (DTrace with SystemTAP only). > +""" > + > +__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" > +__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" > +__license__ = "GPL version 2 or (at your option) any later version" > + > +__maintainer__ = "Stefan Hajnoczi" > +__email__ = "stefanha@linux.vnet.ibm.com" > + > + > +from tracetool import out > + > + > +def begin(events): > + out('/* This file is autogenerated by tracetool, do not edit. */') > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [RFC PATCH v2 8/8] tracetool: Add MAINTAINERS info 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova ` (6 preceding siblings ...) 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend Lluís Vilanova @ 2012-03-26 17:38 ` Lluís Vilanova 7 siblings, 0 replies; 18+ messages in thread From: Lluís Vilanova @ 2012-03-26 17:38 UTC (permalink / raw) To: qemu-devel; +Cc: stefanha Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- MAINTAINERS | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f83d07c2..0e66dd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -548,6 +548,8 @@ Tracing M: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> S: Maintained F: trace/ +F: scripts/tracetool.py +F: scripts/tracetool/ F: docs/tracing.txt T: git://github.com/stefanha/qemu.git tracing ^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2012-03-28 10:29 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-03-26 17:37 [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules Lluís Vilanova 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as " Lluís Vilanova 2012-03-27 15:17 ` Alon Levy 2012-03-27 17:47 ` Lluís Vilanova 2012-03-27 15:21 ` Alon Levy 2012-03-27 16:37 ` [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type Alon Levy 2012-03-27 18:01 ` Lluís Vilanova 2012-03-28 9:35 ` Alon Levy 2012-03-28 10:29 ` Lluís Vilanova 2012-03-26 17:37 ` [Qemu-devel] [RFC PATCH v2 2/8] tracetool: Add module for the 'c' format Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 3/8] tracetool: Add module for the 'h' format Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 4/8] tracetool: Add support for the 'stderr' backend Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 5/8] tracetool: Add support for the 'simple' backend Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 6/8] tracetool: Add support for the 'ust' backend Lluís Vilanova 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 7/8] tracetool: Add support for the 'dtrace' backend Lluís Vilanova 2012-03-27 15:19 ` Alon Levy 2012-03-27 16:20 ` Alon Levy 2012-03-26 17:38 ` [Qemu-devel] [RFC PATCH v2 8/8] tracetool: Add MAINTAINERS info Lluís Vilanova
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).