From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:48746) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SATT2-0003C5-OG for qemu-devel@nongnu.org; Wed, 21 Mar 2012 17:53:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SATSy-0001Va-BX for qemu-devel@nongnu.org; Wed, 21 Mar 2012 17:53:16 -0400 Received: from roura.ac.upc.edu ([147.83.33.10]:42806 helo=roura.ac.upc.es) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SATSx-0001VV-Ot for qemu-devel@nongnu.org; Wed, 21 Mar 2012 17:53:12 -0400 From: =?utf-8?b?TGx1w61z?= Vilanova Date: Wed, 21 Mar 2012 22:52:33 +0100 Message-Id: <20120321215233.3272.1888.stgit@ginnungagap.bsc.es> In-Reply-To: <20120321215224.3272.37570.stgit@ginnungagap.bsc.es> References: <20120321215224.3272.37570.stgit@ginnungagap.bsc.es> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH v7 01/11] Converting tracetool.sh to tracetool.py List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: stefanha@gmail.com, harsh@linux.vnet.ibm.com, aneesh.kumar@linux.vnet.ibm.com Signed-off-by: Harsh Prateek Bora Signed-off-by: Llu=C3=ADs Vilanova --- Makefile.objs | 6=20 Makefile.target | 10 - configure | 4=20 scripts/tracetool | 648 --------------------------------------------= ------ scripts/tracetool.py | 533 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 543 insertions(+), 658 deletions(-) delete mode 100755 scripts/tracetool create mode 100755 scripts/tracetool.py diff --git a/Makefile.objs b/Makefile.objs index 5f0b3f7..a718963 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -357,12 +357,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 --backe= nd=3D$(TRACE_BACKEND) -h < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h =20 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 --backe= nd=3D$(TRACE_BACKEND) -c < $< > $@," GEN trace.c") @cmp -s $@ trace.c || cp $@ trace.c =20 trace.o: trace.c $(GENERATED_HEADERS) @@ -375,7 +375,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)/con= fig-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 --backe= nd=3D$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace") @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace =20 trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) diff --git a/Makefile.target b/Makefile.target index 1bd25a8..3e42e5a 100644 --- a/Makefile.target +++ b/Makefile.target @@ -59,11 +59,11 @@ TARGET_TYPE=3Dsystem endif =20 $(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) \ + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --backend=3D$(TRACE_BACKEND) \ + --binary=3D$(bindir)/$(QEMU_PROG) \ + --target-arch=3D$(TARGET_ARCH) \ + --target-type=3D$(TARGET_TYPE) \ --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_P= ROG).stp") else stap: diff --git a/configure b/configure index d7631ed..bea4a2c 100755 --- a/configure +++ b/configure @@ -1097,7 +1097,7 @@ echo " --disable-docs disable documentat= ion build" echo " --disable-vhost-net disable vhost-net acceleration support" echo " --enable-vhost-net enable vhost-net acceleration support" echo " --enable-trace-backend=3DB Set trace backend" -echo " Available backends:" $("$source_path"/s= cripts/tracetool --list-backends) +echo " Available backends:" $($python "$source= _path"/scripts/tracetool.py --list-backends) echo " --with-trace-file=3DNAME Full PATH,NAME of file to store trace= s" echo " Default:trace-" echo " --disable-spice disable spice" @@ -2654,7 +2654,7 @@ fi ########################################## # check if trace backend exists =20 -sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend >= /dev/null 2> /dev/null +$python "$source_path/scripts/tracetool.py" "--backend=3D$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 < return 0 if property is present, or 1 otherwise -has_property() -{ - local props prop - props=3D${1%%\(*} - props=3D${props% *} - for prop in $props; do - if [ "$prop" =3D "$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=3D${1#*\(} - args=3D${args%%\)*} - echo "$args" -} - -# Get the argument name list of a trace event -get_argnames() -{ - local nfields field name sep - nfields=3D0 - sep=3D"$2" - for field in $(get_args "$1"); do - nfields=3D$((nfields + 1)) - - # Drop pointer star - field=3D${field#\*} - - # Only argument names have commas at the end - name=3D${field%,} - test "$field" =3D "$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=3D0 - for name in $(get_argnames "$1", ","); do - argc=3D$((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=3D$(get_name "$1") - args=3D$(get_args "$1") - - # Define an empty function for the trace event - cat < -#include "trace/stderr.h" - -extern TraceEvent trace_list[]; -EOF - - stderr_event_num=3D0 -} - -linetoh_stderr() -{ - local name args argnames argc fmt - name=3D$(get_name "$1") - args=3D$(get_args "$1") - argnames=3D$(get_argnames "$1" ",") - argc=3D$(get_argc "$1") - fmt=3D$(get_fmt "$1") - - if [ "$argc" -gt 0 ]; then - argnames=3D", $argnames" - fi - - cat <" - ust_clean_namespace -} - -linetoh_ust() -{ - local name args argnames - name=3D$(get_name "$1") - args=3D$(get_args "$1") - argnames=3D$(get_argnames "$1", ",") - - cat < -$(ust_clean_namespace) -#include "trace.h" -EOF -} - -linetoc_ust() -{ - local name args argnames fmt - name=3D$(get_name "$1") - args=3D$(get_args "$1") - argnames=3D$(get_argnames "$1", ",") - [ -z "$argnames" ] || argnames=3D", $argnames" - fmt=3D$(get_fmt "$1") - - cat < 1: + str.append(name) + return ''.join(str) + else: + return '' + +def get_argc(line): + argc =3D 0 + argnames =3D get_argnames(line) + if argnames: + for name in argnames.split(','): + argc =3D argc + 1 + return argc + +def get_fmt(line, sep=3D')'): + event, sep, fmt =3D line.partition(sep) + return fmt.rstrip('\n') + +def calc_sizeofargs(line): + args =3D get_args(line) + argc =3D get_argc(line) + str =3D [] + newstr =3D "" + if argc > 0: + str =3D args.split(',') + for elem in str: + if is_string(elem): #string + type, sep, var =3D elem.rpartition('*') + newstr =3D newstr+"4 + strlen("+var.lstrip()+") + " + else: + newstr =3D newstr + '8 + ' + newstr =3D newstr + '0' # takes care of last + + return newstr + + +def trace_h_begin(): + print '''#ifndef TRACE_H +#define TRACE_H + +/* This file is autogenerated by tracetool, do not edit. */ + +#include "qemu-common.h"''' + + +def trace_h_end(): + print '#endif /* TRACE_H */' + + +def trace_c_begin(): + print '/* This file is autogenerated by tracetool, do not edit. */' + +def trace_c_end(): + pass # nop, required for trace_gen + +def nop_h(events): + print + for event in events: + print '''static inline void trace_%(name)s(%(args)s) +{ +} +''' % { + 'name': event.name, + 'args': event.args +} + return + +def nop_c(events): + pass # nop, reqd for converters + +def simple_h(events): + print '#include "trace/simple.h"' + print + + for event in events: + if event.argc: + argstr =3D event.argnames.split() + arg_prefix =3D '(uint64_t)(uintptr_t)' + cast_args =3D arg_prefix + arg_prefix.join(argstr) + simple_args =3D (str(event.num) + ', ' + cast_args) + else: + simple_args =3D str(event.num) + + print '''static inline void trace_%(name)s(%(args)s) +{ + trace%(argc)d(%(trace_args)s); +}''' % { + 'name': event.name, + 'args': event.args, + 'argc': event.argc, + 'trace_args': simple_args +} + print + print '#define NR_TRACE_EVENTS %d' % (event.num + 1) + print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];' + + +def is_string(arg): + strtype =3D ('const char*', 'char*', 'const char *', 'char *') + if arg.lstrip().startswith(strtype): + return True + else: + return False + +def simple_c(events): + print '#include "trace.h"' + print + print 'TraceEvent trace_list[] =3D {' + print + + for event in events: + print '{.tp_name =3D "%(name)s", .state=3D0},' % { + 'name': event.name, +} + print + print '};' + +def stderr_h(events): + print '''#include +#include "trace/stderr.h" + +extern TraceEvent trace_list[];''' + for event in events: + argnames =3D event.argnames + if event.argc > 0: + argnames =3D ', ' + event.argnames + else: + argnames =3D '' + print ''' +static inline void trace_%(name)s(%(args)s) +{ + if (trace_list[%(event_num)s].state !=3D 0) { + fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s); + } +}''' % { + 'name': event.name, + 'args': event.args, + 'event_num': event.num, + 'fmt': event.fmt, + 'argnames': argnames +} + print + print '#define NR_TRACE_EVENTS %d' % (event.num + 1) + +def stderr_c(events): + print '''#include "trace.h" + +TraceEvent trace_list[] =3D { +''' + for event in events: + print '{.tp_name =3D "%(name)s", .state=3D0},' % { + 'name': event.name +} + print + print '};' + +def ust_h(events): + print '''#include +#undef mutex_lock +#undef mutex_unlock +#undef inline +#undef wmb''' + + for event in events: + if event.argc > 0: + print ''' +DECLARE_TRACE(ust_%(name)s, TP_PROTO(%(args)s), TP_ARGS(%(argnames)s)); +#define trace_%(name)s trace_ust_%(name)s''' % { + 'name': event.name, + 'args': event.args, + 'argnames': event.argnames +} + else: + print ''' +_DECLARE_TRACEPOINT_NOARGS(ust_%(name)s); +#define trace_%(name)s trace_ust_%(name)s''' % { + 'name': event.name, +} + print + +def ust_c(events): + print '''#include +#undef mutex_lock +#undef mutex_unlock +#undef inline +#undef wmb +#include "trace.h"''' + eventlist =3D list(events) + for event in eventlist: + argnames =3D event.argnames + if event.argc > 0: + argnames =3D ', ' + event.argnames + print ''' +DEFINE_TRACE(ust_%(name)s); + +static void ust_%(name)s_probe(%(args)s) +{ + trace_mark(ust, %(name)s, %(fmt)s%(argnames)s); +}''' % { + 'name': event.name, + 'args': event.args, + 'fmt': event.fmt, + 'argnames': argnames +} + else: + print ''' +DEFINE_TRACE(ust_%(name)s); + +static void ust_%(name)s_probe(%(args)s) +{ + trace_mark(ust, %(name)s, UST_MARKER_NOARGS); +}''' % { + 'name': event.name, + 'args': event.args, +} + + # register probes + print ''' +static void __attribute__((constructor)) trace_init(void) +{''' + for event in eventlist: + print ' register_trace_ust_%(name)s(ust_%(name)s_probe);' % { + 'name': event.name +} + print '}' + +def dtrace_h(events): + print '#include "trace-dtrace.h"' + print + for event in events: + print '''static inline void trace_%(name)s(%(args)s) { + QEMU_%(uppername)s(%(argnames)s); +} +''' % { + 'name': event.name, + 'args': event.args, + 'uppername': event.name.upper(), + 'argnames': event.argnames, +} + +def dtrace_c(events): + pass # No need for function definitions in dtrace backend + +def dtrace_d(events): + print 'provider qemu {' + for event in events: + args =3D event.args + + # DTrace provider syntax expects foo() for empty + # params, not foo(void) + if args =3D=3D 'void': + args =3D '' + + # Define prototype for probe arguments + print ''' + probe %(name)s(%(args)s);''' % { + 'name': event.name, + 'args': args +} + print + print '};' + +def dtrace_stp(events): + for event in events: + # Define prototype for probe arguments + print ''' +probe %(probeprefix)s.%(name)s =3D process("%(binary)s").mark("%(name)s"= ) +{''' % { + 'probeprefix': probeprefix, + 'name': event.name, + 'binary': binary +} + i =3D 1 + if event.argc > 0: + for arg in event.argnames.split(','): + # 'limit' is a reserved keyword + if arg =3D=3D 'limit': + arg =3D '_limit' + print ' %s =3D $arg%d;' % (arg.lstrip(), i) + i +=3D 1 + print '}' + print + +def trace_stap_begin(): + print '/* This file is autogenerated by tracetool, do not edit. */' + +def trace_stap_end(): + pass #nop, reqd for trace_gen + +def trace_d_begin(): + print '/* This file is autogenerated by tracetool, do not edit. */' + +def trace_d_end(): + pass #nop, reqd for trace_gen + + +# Registry of backends and their converter functions +converters =3D { + 'simple': { + 'h': simple_h, + 'c': simple_c, + }, + + 'nop': { + 'h': nop_h, + 'c': nop_c, + }, + + 'stderr': { + 'h': stderr_h, + 'c': stderr_c, + }, + + 'dtrace': { + 'h': dtrace_h, + 'c': dtrace_c, + 'd': dtrace_d, + 'stap': dtrace_stp + }, + + 'ust': { + 'h': ust_h, + 'c': ust_c, + }, + +} + +# Trace file header and footer code generators +trace_gen =3D { + 'h': { + 'begin': trace_h_begin, + 'end': trace_h_end, + }, + 'c': { + 'begin': trace_c_begin, + 'end': trace_c_end, + }, + 'd': { + 'begin': trace_d_begin, + 'end': trace_d_end, + }, + 'stap': { + 'begin': trace_stap_begin, + 'end': trace_stap_end, + }, +} + +# A trace event +class Event(object): + def __init__(self, num, line): + self.num =3D num + self.args =3D get_args(line) + self.arglist =3D self.args.split(',') + self.name =3D get_name(line) + self.argc =3D get_argc(line) + self.argnames =3D get_argnames(line) + self.sizestr =3D calc_sizeofargs(line) + self.fmt =3D get_fmt(line) + self.properties =3D get_properties(line) + +# Generator that yields Event objects given a trace-events file object +def read_events(fobj): + event_num =3D 0 + for line in fobj: + if not line.strip(): + continue + if line.lstrip().startswith('#'): + continue + yield Event(event_num, line) + event_num +=3D 1 + +binary =3D "" +probeprefix =3D "" + +def main(): + global binary, probeprefix + targettype =3D "" + targetarch =3D "" + backend =3D "" + supported_backends =3D ["simple", "nop", "stderr", "dtrace", "ust"] + short_options =3D "hcd" + long_options =3D ["stap", "backend=3D", "binary=3D", "target-arch=3D= ", "target-type=3D", "probe-prefix=3D", "list-backends", "check-backend"] + try: + opts, args =3D getopt.getopt(sys.argv[1:], short_options, long_o= ptions) + except getopt.GetoptError, err: + # print help information and exit: + print str(err) # will print something like "option -a not recogn= ized" + usage() + sys.exit(2) + for opt, arg in opts: + if opt =3D=3D '-h': + output =3D 'h' + elif opt =3D=3D '-c': + output =3D 'c' + elif opt =3D=3D '-d': + output =3D 'd' + elif opt =3D=3D '--stap': + output =3D 'stap' + elif opt =3D=3D '--backend': + backend =3D arg + elif opt =3D=3D '--binary': + binary =3D arg + elif opt =3D=3D '--target-arch': + targetarch =3D arg + elif opt =3D=3D '--target-type': + targettype =3D arg + elif opt =3D=3D '--probe-prefix': + probeprefix =3D arg + elif opt =3D=3D '--list-backends': + print 'simple, nop, stderr, dtrace, ust' + sys.exit(0) + elif opt =3D=3D "--check-backend": + if backend in supported_backends: + sys.exit(0) + else: + sys.exit(1) + else: + #assert False, "unhandled option" + print "unhandled option: ", opt + usage() + + if backend =3D=3D "" or output =3D=3D "": + usage() + sys.exit(0) + + if backend !=3D 'dtrace' and output =3D=3D 'd': + print 'DTrace probe generator not applicable to %s backend' % ba= ckend + sys.exit(1) + + if output =3D=3D 'stap': + if backend !=3D "dtrace": + print 'SystemTAP tapset generator not applicable to %s backe= nd' % backend + sys.exit(1) + if binary =3D=3D "": + print '--binary is required for SystemTAP tapset generator' + sys.exit(1) + if not probeprefix and not targettype: + print '--target-type is required for SystemTAP tapset genera= tor' + sys.exit(1) + if not probeprefix and not targetarch: + print '--target-arch is required for SystemTAP tapset genera= tor' + sys.exit(1) + if probeprefix =3D=3D "": + probeprefix =3D 'qemu.' + targettype + '.' + targetarch + + disabled_events, enabled_events =3D [], [] + for e in read_events(sys.stdin): + if 'disable' in e.properties: + disabled_events.append(e) + else: + enabled_events.append(e) + + trace_gen[output]['begin']() + if output =3D=3D 'h': # disabled events + converters['nop'][output](disabled_events) + converters[backend][output](enabled_events) + trace_gen[output]['end']() + +if __name__ =3D=3D "__main__": + main() +