summaryrefslogtreecommitdiffstats
path: root/qemu/scripts/tracetool
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/scripts/tracetool
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/scripts/tracetool')
-rw-r--r--qemu/scripts/tracetool/__init__.py366
-rw-r--r--qemu/scripts/tracetool/backend/__init__.py123
-rw-r--r--qemu/scripts/tracetool/backend/dtrace.py46
-rw-r--r--qemu/scripts/tracetool/backend/ftrace.py48
-rw-r--r--qemu/scripts/tracetool/backend/simple.py99
-rw-r--r--qemu/scripts/tracetool/backend/stderr.py47
-rw-r--r--qemu/scripts/tracetool/backend/ust.py35
-rw-r--r--qemu/scripts/tracetool/format/__init__.py85
-rw-r--r--qemu/scripts/tracetool/format/c.py28
-rw-r--r--qemu/scripts/tracetool/format/d.py54
-rw-r--r--qemu/scripts/tracetool/format/events_c.py36
-rw-r--r--qemu/scripts/tracetool/format/events_h.py52
-rw-r--r--qemu/scripts/tracetool/format/h.py44
-rw-r--r--qemu/scripts/tracetool/format/simpletrace_stap.py71
-rw-r--r--qemu/scripts/tracetool/format/stap.py61
-rw-r--r--qemu/scripts/tracetool/format/tcg_h.py57
-rw-r--r--qemu/scripts/tracetool/format/tcg_helper_c.py50
-rw-r--r--qemu/scripts/tracetool/format/tcg_helper_h.py50
-rw-r--r--qemu/scripts/tracetool/format/tcg_helper_wrapper_h.py70
-rw-r--r--qemu/scripts/tracetool/format/ust_events_c.py33
-rw-r--r--qemu/scripts/tracetool/format/ust_events_h.py100
-rw-r--r--qemu/scripts/tracetool/transform.py166
22 files changed, 1721 insertions, 0 deletions
diff --git a/qemu/scripts/tracetool/__init__.py b/qemu/scripts/tracetool/__init__.py
new file mode 100644
index 000000000..181675f00
--- /dev/null
+++ b/qemu/scripts/tracetool/__init__.py
@@ -0,0 +1,366 @@
+#!/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-2014, 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 weakref
+
+import tracetool.format
+import tracetool.backend
+import tracetool.transform
+
+
+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, **kwargs):
+ """Write a set of output lines.
+
+ You can use kwargs as a shorthand for mapping variables when formating all
+ the strings in lines.
+ """
+ lines = [ l % kwargs for l in lines ]
+ sys.stdout.writelines("\n".join(lines) + "\n")
+
+
+class Arguments:
+ """Event arguments description."""
+
+ def __init__(self, args):
+ """
+ Parameters
+ ----------
+ args :
+ List of (type, name) tuples.
+ """
+ self._args = args
+
+ def copy(self):
+ """Create a new copy."""
+ return Arguments(list(self._args))
+
+ @staticmethod
+ def build(arg_str):
+ """Build and Arguments instance from an argument string.
+
+ Parameters
+ ----------
+ arg_str : str
+ String describing the event arguments.
+ """
+ res = []
+ for arg in arg_str.split(","):
+ arg = arg.strip()
+ if arg == 'void':
+ continue
+
+ if '*' in arg:
+ arg_type, identifier = arg.rsplit('*', 1)
+ arg_type += '*'
+ identifier = identifier.strip()
+ else:
+ arg_type, identifier = arg.rsplit(None, 1)
+
+ res.append((arg_type, identifier))
+ return Arguments(res)
+
+ 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 __repr__(self):
+ """Evaluable string representation for this object."""
+ return "Arguments(\"%s\")" % 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 ]
+
+ def transform(self, *trans):
+ """Return a new Arguments instance with transformed types.
+
+ The types in the resulting Arguments instance are transformed according
+ to tracetool.transform.transform_type.
+ """
+ res = []
+ for type_, name in self._args:
+ res.append((tracetool.transform.transform_type(type_, *trans),
+ name))
+ return Arguments(res)
+
+
+class Event(object):
+ """Event description.
+
+ 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>[\w\s]+)\s+)?"
+ "(?P<name>\w+)"
+ "\((?P<args>[^)]*)\)"
+ "\s*"
+ "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
+ "\s*")
+
+ _VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec"])
+
+ def __init__(self, name, props, fmt, args, orig=None):
+ """
+ Parameters
+ ----------
+ name : string
+ Event name.
+ props : list of str
+ Property names.
+ fmt : str, list of str
+ Event printing format (or formats).
+ args : Arguments
+ Event arguments.
+ orig : Event or None
+ Original Event before transformation.
+
+ """
+ self.name = name
+ self.properties = props
+ self.fmt = fmt
+ self.args = args
+
+ if orig is None:
+ self.original = weakref.ref(self)
+ else:
+ self.original = orig
+
+ unknown_props = set(self.properties) - self._VALID_PROPS
+ if len(unknown_props) > 0:
+ raise ValueError("Unknown properties: %s"
+ % ", ".join(unknown_props))
+ assert isinstance(self.fmt, str) or len(self.fmt) == 2
+
+ def copy(self):
+ """Create a new copy."""
+ return Event(self.name, list(self.properties), self.fmt,
+ self.args.copy(), self)
+
+ @staticmethod
+ def build(line_str):
+ """Build an Event instance from a string.
+
+ Parameters
+ ----------
+ line_str : str
+ Line describing the event.
+ """
+ m = Event._CRE.match(line_str)
+ assert m is not None
+ groups = m.groupdict('')
+
+ name = groups["name"]
+ props = groups["props"].split()
+ fmt = groups["fmt"]
+ fmt_trans = groups["fmt_trans"]
+ if len(fmt_trans) > 0:
+ fmt = [fmt_trans, fmt]
+ args = Arguments.build(groups["args"])
+
+ if "tcg-trans" in props:
+ raise ValueError("Invalid property 'tcg-trans'")
+ if "tcg-exec" in props:
+ raise ValueError("Invalid property 'tcg-exec'")
+ if "tcg" not in props and not isinstance(fmt, str):
+ raise ValueError("Only events with 'tcg' property can have two formats")
+ if "tcg" in props and isinstance(fmt, str):
+ raise ValueError("Events with 'tcg' property must have two formats")
+
+ return Event(name, props, fmt, args)
+
+ def __repr__(self):
+ """Evaluable string representation for this object."""
+ if isinstance(self.fmt, str):
+ fmt = self.fmt
+ else:
+ fmt = "%s, %s" % (self.fmt[0], self.fmt[1])
+ return "Event('%s %s(%s) %s')" % (" ".join(self.properties),
+ self.name,
+ self.args,
+ fmt)
+
+ _FMT = re.compile("(%[\d\.]*\w+|%.*PRI\S+)")
+
+ def formats(self):
+ """List of argument print formats."""
+ assert not isinstance(self.fmt, list)
+ return self._FMT.findall(self.fmt)
+
+ QEMU_TRACE = "trace_%(name)s"
+ QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
+
+ def api(self, fmt=None):
+ if fmt is None:
+ fmt = Event.QEMU_TRACE
+ return fmt % {"name": self.name}
+
+ def transform(self, *trans):
+ """Return a new Event with transformed Arguments."""
+ return Event(self.name,
+ list(self.properties),
+ self.fmt,
+ self.args.transform(*trans),
+ self)
+
+
+def _read_events(fobj):
+ events = []
+ for line in fobj:
+ if not line.strip():
+ continue
+ if line.lstrip().startswith('#'):
+ continue
+
+ event = Event.build(line)
+
+ # transform TCG-enabled events
+ if "tcg" not in event.properties:
+ events.append(event)
+ else:
+ event_trans = event.copy()
+ event_trans.name += "_trans"
+ event_trans.properties += ["tcg-trans"]
+ event_trans.fmt = event.fmt[0]
+ args_trans = []
+ for atrans, aorig in zip(
+ event_trans.transform(tracetool.transform.TCG_2_HOST).args,
+ event.args):
+ if atrans == aorig:
+ args_trans.append(atrans)
+ event_trans.args = Arguments(args_trans)
+ event_trans = event_trans.copy()
+
+ event_exec = event.copy()
+ event_exec.name += "_exec"
+ event_exec.properties += ["tcg-exec"]
+ event_exec.fmt = event.fmt[1]
+ event_exec = event_exec.transform(tracetool.transform.TCG_2_HOST)
+
+ new_event = [event_trans, event_exec]
+ event.event_trans, event.event_exec = new_event
+
+ events.extend(new_event)
+
+ return events
+
+
+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.
+ """
+ try:
+ module = __import__(mod_name, globals(), locals(), ["__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, backends,
+ binary=None, probe_prefix=None):
+ """Generate the output for the given (format, backends) pair.
+
+ Parameters
+ ----------
+ fevents : file
+ Event description file.
+ format : str
+ Output format name.
+ backends : list
+ Output backend names.
+ binary : str or None
+ See tracetool.backend.dtrace.BINARY.
+ probe_prefix : str or None
+ See tracetool.backend.dtrace.PROBEPREFIX.
+ """
+ # fix strange python error (UnboundLocalError tracetool)
+ import tracetool
+
+ format = str(format)
+ if len(format) is 0:
+ raise TracetoolError("format not set")
+ if not tracetool.format.exists(format):
+ raise TracetoolError("unknown format: %s" % format)
+
+ if len(backends) is 0:
+ raise TracetoolError("no backends specified")
+ for backend in backends:
+ if not tracetool.backend.exists(backend):
+ raise TracetoolError("unknown backend: %s" % backend)
+ backend = tracetool.backend.Wrapper(backends, format)
+
+ import tracetool.backend.dtrace
+ tracetool.backend.dtrace.BINARY = binary
+ tracetool.backend.dtrace.PROBEPREFIX = probe_prefix
+
+ events = _read_events(fevents)
+
+ tracetool.format.generate(events, format, backend)
diff --git a/qemu/scripts/tracetool/backend/__init__.py b/qemu/scripts/tracetool/backend/__init__.py
new file mode 100644
index 000000000..d4b6dab9c
--- /dev/null
+++ b/qemu/scripts/tracetool/backend/__init__.py
@@ -0,0 +1,123 @@
+#!/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
+-----------------
+
+All the following functions are optional, and no output will be generated if
+they do not exist.
+
+=============================== ==============================================
+Function Description
+=============================== ==============================================
+generate_<format>_begin(events) Generate backend- and format-specific file
+ header contents.
+generate_<format>_end(events) Generate backend- and format-specific file
+ footer contents.
+generate_<format>(event) Generate backend- and format-specific contents
+ for the given event.
+=============================== ==============================================
+
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 os
+
+import tracetool
+
+
+def get_list(only_public = False):
+ """Get a list of (name, description) pairs."""
+ res = [("nop", "Tracing disabled.")]
+ modnames = []
+ for filename in os.listdir(tracetool.backend.__path__[0]):
+ if filename.endswith('.py') and filename != '__init__.py':
+ modnames.append(filename.rsplit('.', 1)[0])
+ for modname in sorted(modnames):
+ module = tracetool.try_import("tracetool.backend." + modname)
+
+ # just in case; should never fail unless non-module files are put there
+ if not module[0]:
+ continue
+ module = module[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
+ if name == "nop":
+ return True
+ name = name.replace("-", "_")
+ return tracetool.try_import("tracetool.backend." + name)[1]
+
+
+class Wrapper:
+ def __init__(self, backends, format):
+ self._backends = [backend.replace("-", "_") for backend in backends]
+ self._format = format.replace("-", "_")
+ for backend in self._backends:
+ assert exists(backend)
+ assert tracetool.format.exists(self._format)
+
+ def _run_function(self, name, *args, **kwargs):
+ for backend in self._backends:
+ func = tracetool.try_import("tracetool.backend." + backend,
+ name % self._format, None)[1]
+ if func is not None:
+ func(*args, **kwargs)
+
+ def generate_begin(self, events):
+ self._run_function("generate_%s_begin", events)
+
+ def generate(self, event):
+ self._run_function("generate_%s", event)
+
+ def generate_end(self, events):
+ self._run_function("generate_%s_end", events)
diff --git a/qemu/scripts/tracetool/backend/dtrace.py b/qemu/scripts/tracetool/backend/dtrace.py
new file mode 100644
index 000000000..fabfe9988
--- /dev/null
+++ b/qemu/scripts/tracetool/backend/dtrace.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+DTrace/SystemTAP backend.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate_h_begin(events):
+ out('#include "trace/generated-tracers-dtrace.h"',
+ '')
+
+
+def generate_h(event):
+ out(' QEMU_%(uppername)s(%(argnames)s);',
+ uppername=event.name.upper(),
+ argnames=", ".join(event.args.names()))
diff --git a/qemu/scripts/tracetool/backend/ftrace.py b/qemu/scripts/tracetool/backend/ftrace.py
new file mode 100644
index 000000000..d798c7134
--- /dev/null
+++ b/qemu/scripts/tracetool/backend/ftrace.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Ftrace built-in backend.
+"""
+
+__author__ = "Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com>"
+__copyright__ = "Copyright (C) 2013 Hitachi, Ltd."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+
+
+PUBLIC = True
+
+
+def generate_h_begin(events):
+ out('#include "trace/ftrace.h"',
+ '#include "trace/control.h"',
+ '')
+
+
+def generate_h(event):
+ argnames = ", ".join(event.args.names())
+ if len(event.args) > 0:
+ argnames = ", " + argnames
+
+ out(' {',
+ ' char ftrace_buf[MAX_TRACE_STRLEN];',
+ ' int unused __attribute__ ((unused));',
+ ' int trlen;',
+ ' if (trace_event_get_state(%(event_id)s)) {',
+ ' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,',
+ ' "%(name)s " %(fmt)s "\\n" %(argnames)s);',
+ ' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);',
+ ' unused = write(trace_marker_fd, ftrace_buf, trlen);',
+ ' }',
+ ' }',
+ name=event.name,
+ args=event.args,
+ event_id="TRACE_" + event.name.upper(),
+ fmt=event.fmt.rstrip("\n"),
+ argnames=argnames)
diff --git a/qemu/scripts/tracetool/backend/simple.py b/qemu/scripts/tracetool/backend/simple.py
new file mode 100644
index 000000000..e8c2cd57e
--- /dev/null
+++ b/qemu/scripts/tracetool/backend/simple.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Simple built-in backend.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 is_string(arg):
+ strtype = ('const char*', 'char*', 'const char *', 'char *')
+ if arg.lstrip().startswith(strtype):
+ return True
+ else:
+ return False
+
+
+def generate_h_begin(events):
+ for event in events:
+ out('void _simple_%(api)s(%(args)s);',
+ api=event.api(),
+ args=event.args)
+ out('')
+
+
+def generate_h(event):
+ out(' _simple_%(api)s(%(args)s);',
+ api=event.api(),
+ args=", ".join(event.args.names()))
+
+
+def generate_c_begin(events):
+ out('#include "trace.h"',
+ '#include "trace/control.h"',
+ '#include "trace/simple.h"',
+ '')
+
+
+def generate_c(event):
+ out('void _simple_%(api)s(%(args)s)',
+ '{',
+ ' TraceBufferRecord rec;',
+ api=event.api(),
+ args=event.args)
+ sizes = []
+ for type_, name in event.args:
+ if is_string(type_):
+ out(' size_t arg%(name)s_len = %(name)s ? MIN(strlen(%(name)s), MAX_TRACE_STRLEN) : 0;',
+ name=name)
+ strsizeinfo = "4 + arg%s_len" % name
+ sizes.append(strsizeinfo)
+ else:
+ sizes.append("8")
+ sizestr = " + ".join(sizes)
+ if len(event.args) == 0:
+ sizestr = '0'
+
+
+ out('',
+ ' if (!trace_event_get_state(%(event_id)s)) {',
+ ' return;',
+ ' }',
+ '',
+ ' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
+ ' return; /* Trace Buffer Full, Event Dropped ! */',
+ ' }',
+ event_id='TRACE_' + event.name.upper(),
+ size_str=sizestr)
+
+ if len(event.args) > 0:
+ for type_, name in event.args:
+ # string
+ if is_string(type_):
+ out(' trace_record_write_str(&rec, %(name)s, arg%(name)s_len);',
+ name=name)
+ # pointer var (not string)
+ elif type_.endswith('*'):
+ out(' trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)%(name)s);',
+ name=name)
+ # primitive data type
+ else:
+ out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);',
+ name=name)
+
+ out(' trace_record_finish(&rec);',
+ '}',
+ '')
diff --git a/qemu/scripts/tracetool/backend/stderr.py b/qemu/scripts/tracetool/backend/stderr.py
new file mode 100644
index 000000000..ca5805462
--- /dev/null
+++ b/qemu/scripts/tracetool/backend/stderr.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Stderr built-in backend.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate_h_begin(events):
+ out('#include <stdio.h>',
+ '#include <sys/time.h>',
+ '#include <sys/types.h>',
+ '#include <unistd.h>',
+ '#include "trace/control.h"',
+ '')
+
+
+def generate_h(event):
+ argnames = ", ".join(event.args.names())
+ if len(event.args) > 0:
+ argnames = ", " + argnames
+
+ out(' if (trace_event_get_state(%(event_id)s)) {',
+ ' struct timeval _now;',
+ ' gettimeofday(&_now, NULL);',
+ ' fprintf(stderr, "%%d@%%zd.%%06zd:%(name)s " %(fmt)s "\\n",',
+ ' getpid(),',
+ ' (size_t)_now.tv_sec, (size_t)_now.tv_usec',
+ ' %(argnames)s);',
+ ' }',
+ event_id="TRACE_" + event.name.upper(),
+ name=event.name,
+ fmt=event.fmt.rstrip("\n"),
+ argnames=argnames)
diff --git a/qemu/scripts/tracetool/backend/ust.py b/qemu/scripts/tracetool/backend/ust.py
new file mode 100644
index 000000000..2f8f44abd
--- /dev/null
+++ b/qemu/scripts/tracetool/backend/ust.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+LTTng User Space Tracing backend.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate_h_begin(events):
+ out('#include <lttng/tracepoint.h>',
+ '#include "trace/generated-ust-provider.h"',
+ '')
+
+
+def generate_h(event):
+ argnames = ", ".join(event.args.names())
+ if len(event.args) > 0:
+ argnames = ", " + argnames
+
+ out(' tracepoint(qemu, %(name)s%(tp_args)s);',
+ name=event.name,
+ tp_args=argnames)
diff --git a/qemu/scripts/tracetool/format/__init__.py b/qemu/scripts/tracetool/format/__init__.py
new file mode 100644
index 000000000..812570ff6
--- /dev/null
+++ b/qemu/scripts/tracetool/format/__init__.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Format management.
+
+
+Creating new formats
+--------------------
+
+A new format named 'foo-bar' corresponds to Python module
+'tracetool/format/foo_bar.py'.
+
+A format 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
+----------------
+
+======== ==================================================================
+Function Description
+======== ==================================================================
+generate Called to generate a format-specific file.
+======== ==================================================================
+
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 os
+
+import tracetool
+
+
+def get_list():
+ """Get a list of (name, description) pairs."""
+ res = []
+ modnames = []
+ for filename in os.listdir(tracetool.format.__path__[0]):
+ if filename.endswith('.py') and filename != '__init__.py':
+ modnames.append(filename.rsplit('.', 1)[0])
+ for modname in sorted(modnames):
+ module = tracetool.try_import("tracetool.format." + modname)
+
+ # just in case; should never fail unless non-module files are put there
+ if not module[0]:
+ continue
+ module = module[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
+ name = name.replace("-", "_")
+ return tracetool.try_import("tracetool.format." + name)[1]
+
+
+def generate(events, format, backend):
+ if not exists(format):
+ raise ValueError("unknown format: %s" % format)
+ format = format.replace("-", "_")
+ func = tracetool.try_import("tracetool.format." + format,
+ "generate")[1]
+ if func is None:
+ raise AttributeError("format has no 'generate': %s" % format)
+ func(events, backend)
diff --git a/qemu/scripts/tracetool/format/c.py b/qemu/scripts/tracetool/format/c.py
new file mode 100644
index 000000000..699598fb0
--- /dev/null
+++ b/qemu/scripts/tracetool/format/c.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-tracers.c
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '')
+ backend.generate_begin(events)
+ for event in events:
+ backend.generate(event)
+ backend.generate_end(events)
diff --git a/qemu/scripts/tracetool/format/d.py b/qemu/scripts/tracetool/format/d.py
new file mode 100644
index 000000000..c77d5b7ab
--- /dev/null
+++ b/qemu/scripts/tracetool/format/d.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-tracers.dtrace (DTrace only).
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+
+
+# Reserved keywords from
+# https://wikis.oracle.com/display/DTrace/Types,+Operators+and+Expressions
+RESERVED_WORDS = (
+ 'auto', 'goto', 'sizeof', 'break', 'if', 'static', 'case', 'import',
+ 'string', 'char', 'inline', 'stringof', 'const', 'int', 'struct',
+ 'continue', 'long', 'switch', 'counter', 'offsetof', 'this',
+ 'default', 'probe', 'translator', 'do', 'provider', 'typedef',
+ 'double', 'register', 'union', 'else', 'restrict', 'unsigned',
+ 'enum', 'return', 'void', 'extern', 'self', 'volatile', 'float',
+ 'short', 'while', 'for', 'signed', 'xlate',
+)
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */'
+ '',
+ 'provider qemu {')
+
+ for e in events:
+ args = []
+ for type_, name in e.args:
+ if name in RESERVED_WORDS:
+ name += '_'
+ args.append(type_ + ' ' + name)
+
+ # Define prototype for probe arguments
+ out('',
+ 'probe %(name)s(%(args)s);',
+ name=e.name,
+ args=','.join(args))
+
+ out('',
+ '};')
diff --git a/qemu/scripts/tracetool/format/events_c.py b/qemu/scripts/tracetool/format/events_c.py
new file mode 100644
index 000000000..2d97fa310
--- /dev/null
+++ b/qemu/scripts/tracetool/format/events_c.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-events.c
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#include "trace.h"',
+ '#include "trace/generated-events.h"',
+ '#include "trace/control.h"',
+ '')
+
+ out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
+
+ for e in events:
+ out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
+ id = "TRACE_" + e.name.upper(),
+ name = e.name,
+ sstate = "TRACE_%s_ENABLED" % e.name.upper())
+
+ out('};',
+ '')
diff --git a/qemu/scripts/tracetool/format/events_h.py b/qemu/scripts/tracetool/format/events_h.py
new file mode 100644
index 000000000..9f114a349
--- /dev/null
+++ b/qemu/scripts/tracetool/format/events_h.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-events.h
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#ifndef TRACE__GENERATED_EVENTS_H',
+ '#define TRACE__GENERATED_EVENTS_H',
+ '',
+ '#include <stdbool.h>',
+ '')
+
+ # event identifiers
+ out('typedef enum {')
+
+ for e in events:
+ out(' TRACE_%s,' % e.name.upper())
+
+ out(' TRACE_EVENT_COUNT',
+ '} TraceEventID;')
+
+ # static state
+ for e in events:
+ if 'disable' in e.properties:
+ enabled = 0
+ else:
+ enabled = 1
+ if "tcg-trans" in e.properties:
+ # a single define for the two "sub-events"
+ out('#define TRACE_%(name)s_ENABLED %(enabled)d',
+ name=e.original.original.name.upper(),
+ enabled=enabled)
+ out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
+
+ out('#include "trace/event-internal.h"',
+ '',
+ '#endif /* TRACE__GENERATED_EVENTS_H */')
diff --git a/qemu/scripts/tracetool/format/h.py b/qemu/scripts/tracetool/format/h.py
new file mode 100644
index 000000000..9b3943002
--- /dev/null
+++ b/qemu/scripts/tracetool/format/h.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-tracers.h
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#ifndef TRACE__GENERATED_TRACERS_H',
+ '#define TRACE__GENERATED_TRACERS_H',
+ '',
+ '#include "qemu-common.h"',
+ '')
+
+ backend.generate_begin(events)
+
+ for e in events:
+ out('',
+ 'static inline void %(api)s(%(args)s)',
+ '{',
+ api=e.api(),
+ args=e.args)
+
+ if "disable" not in e.properties:
+ backend.generate(e)
+
+ out('}')
+
+ backend.generate_end(events)
+
+ out('#endif /* TRACE__GENERATED_TRACERS_H */')
diff --git a/qemu/scripts/tracetool/format/simpletrace_stap.py b/qemu/scripts/tracetool/format/simpletrace_stap.py
new file mode 100644
index 000000000..7e44bc181
--- /dev/null
+++ b/qemu/scripts/tracetool/format/simpletrace_stap.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .stp file that outputs simpletrace binary traces (DTrace with SystemTAP only).
+"""
+
+__author__ = "Stefan Hajnoczi <redhat.com>"
+__copyright__ = "Copyright (C) 2014, Red Hat, Inc."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+from tracetool.backend.dtrace import binary, probeprefix
+from tracetool.backend.simple import is_string
+from tracetool.format.stap import stap_escape
+
+
+def generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '')
+
+ for event_id, e in enumerate(events):
+ if 'disable' in e.properties:
+ continue
+
+ out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
+ '{',
+ probeprefix=probeprefix(),
+ name=e.name)
+
+ # Calculate record size
+ sizes = ['24'] # sizeof(TraceRecord)
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ out(' try {',
+ ' arg%(name)s_str = %(name)s ? user_string_n(%(name)s, 512) : "<null>"',
+ ' } catch {}',
+ ' arg%(name)s_len = strlen(arg%(name)s_str)',
+ name=name)
+ sizes.append('4 + arg%s_len' % name)
+ else:
+ sizes.append('8')
+ sizestr = ' + '.join(sizes)
+
+ # Generate format string and value pairs for record header and arguments
+ fields = [('8b', str(event_id)),
+ ('8b', 'gettimeofday_ns()'),
+ ('4b', sizestr),
+ ('4b', 'pid()')]
+ for type_, name in e.args:
+ name = stap_escape(name)
+ if is_string(type_):
+ fields.extend([('4b', 'arg%s_len' % name),
+ ('.*s', 'arg%s_len, arg%s_str' % (name, name))])
+ else:
+ fields.append(('8b', name))
+
+ # Emit the entire record in a single SystemTap printf()
+ fmt_str = '%'.join(fmt for fmt, _ in fields)
+ arg_str = ', '.join(arg for _, arg in fields)
+ out(' printf("%%%(fmt_str)s", %(arg_str)s)',
+ fmt_str=fmt_str, arg_str=arg_str)
+
+ out('}')
+
+ out()
diff --git a/qemu/scripts/tracetool/format/stap.py b/qemu/scripts/tracetool/format/stap.py
new file mode 100644
index 000000000..9e780f1b0
--- /dev/null
+++ b/qemu/scripts/tracetool/format/stap.py
@@ -0,0 +1,61 @@
+#!/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-2014, 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
+from tracetool.backend.dtrace import binary, probeprefix
+
+
+# Technically 'self' is not used by systemtap yet, but
+# they recommended we keep it in the reserved list anyway
+RESERVED_WORDS = (
+ 'break', 'catch', 'continue', 'delete', 'else', 'for',
+ 'foreach', 'function', 'global', 'if', 'in', 'limit',
+ 'long', 'next', 'probe', 'return', 'self', 'string',
+ 'try', 'while'
+ )
+
+
+def stap_escape(identifier):
+ # Append underscore to reserved keywords
+ if identifier in RESERVED_WORDS:
+ return identifier + '_'
+ return identifier
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '')
+
+ 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():
+ name = stap_escape(name)
+ out(' %s = $arg%d;' % (name, i))
+ i += 1
+
+ out('}')
+
+ out()
diff --git a/qemu/scripts/tracetool/format/tcg_h.py b/qemu/scripts/tracetool/format/tcg_h.py
new file mode 100644
index 000000000..f676b6662
--- /dev/null
+++ b/qemu/scripts/tracetool/format/tcg_h.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h file for TCG code generation.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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 generate(events, backend):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '/* You must include this file after the inclusion of helper.h */',
+ '',
+ '#ifndef TRACE__GENERATED_TCG_TRACERS_H',
+ '#define TRACE__GENERATED_TCG_TRACERS_H',
+ '',
+ '#include <stdint.h>',
+ '',
+ '#include "trace.h"',
+ '#include "exec/helper-proto.h"',
+ '',
+ )
+
+ for e in events:
+ # just keep one of them
+ if "tcg-trans" not in e.properties:
+ continue
+
+ # get the original event definition
+ e = e.original.original
+
+ out('static inline void %(name_tcg)s(%(args)s)',
+ '{',
+ name_tcg=e.api(e.QEMU_TRACE_TCG),
+ args=e.args)
+
+ if "disable" not in e.properties:
+ out(' %(name_trans)s(%(argnames_trans)s);',
+ ' gen_helper_%(name_exec)s(%(argnames_exec)s);',
+ name_trans=e.event_trans.api(e.QEMU_TRACE),
+ name_exec=e.event_exec.api(e.QEMU_TRACE),
+ argnames_trans=", ".join(e.event_trans.args.names()),
+ argnames_exec=", ".join(e.event_exec.args.names()))
+
+ out('}')
+
+ out('',
+ '#endif /* TRACE__GENERATED_TCG_TRACERS_H */')
diff --git a/qemu/scripts/tracetool/format/tcg_helper_c.py b/qemu/scripts/tracetool/format/tcg_helper_c.py
new file mode 100644
index 000000000..96655a059
--- /dev/null
+++ b/qemu/scripts/tracetool/format/tcg_helper_c.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers.c.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#include "qemu-common.h"',
+ '#include "trace.h"',
+ '#include "exec/helper-proto.h"',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ values = ["(%s)%s" % (t, n)
+ for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
+
+ out('void %(name_tcg)s(%(args)s)',
+ '{',
+ ' %(name)s(%(values)s);',
+ '}',
+ name_tcg="helper_%s_proxy" % e.api(),
+ name=e.api(),
+ args=e_args.transform(HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF),
+ values=", ".join(values),
+ )
diff --git a/qemu/scripts/tracetool/format/tcg_helper_h.py b/qemu/scripts/tracetool/format/tcg_helper_h.py
new file mode 100644
index 000000000..a8ba7ba8e
--- /dev/null
+++ b/qemu/scripts/tracetool/format/tcg_helper_h.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers.h.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ # TCG helper proxy declaration
+ fmt = "DEF_HELPER_FLAGS_%(argc)d(%(name)s, %(flags)svoid%(types)s)"
+ args = e_args.transform(HOST_2_TCG_COMPAT, HOST_2_TCG,
+ TCG_2_TCG_HELPER_DECL)
+ types = ", ".join(args.types())
+ if types != "":
+ types = ", " + types
+
+ flags = "TCG_CALL_NO_RWG, "
+
+ out(fmt,
+ flags=flags,
+ argc=len(args),
+ name=e.api() + "_proxy",
+ types=types,
+ )
diff --git a/qemu/scripts/tracetool/format/tcg_helper_wrapper_h.py b/qemu/scripts/tracetool/format/tcg_helper_wrapper_h.py
new file mode 100644
index 000000000..cac5a878f
--- /dev/null
+++ b/qemu/scripts/tracetool/format/tcg_helper_wrapper_h.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate trace/generated-helpers-wrappers.h.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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
+from tracetool.transform import *
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disable" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#define tcg_temp_new_nop(v) (v)',
+ '#define tcg_temp_free_nop(v)',
+ '',
+ )
+
+ for e in events:
+ if "tcg-exec" not in e.properties:
+ continue
+
+ # tracetool.generate always transforms types to host
+ e_args = e.original.args
+
+ # mixed-type to TCG helper bridge
+ args_tcg_compat = e_args.transform(HOST_2_TCG_COMPAT)
+
+ code_new = [
+ "%(tcg_type)s __%(name)s = %(tcg_func)s(%(name)s);" %
+ {"tcg_type": transform_type(type_, HOST_2_TCG),
+ "tcg_func": transform_type(type_, HOST_2_TCG_TMP_NEW),
+ "name": name}
+ for (type_, name) in args_tcg_compat
+ ]
+
+ code_free = [
+ "%(tcg_func)s(__%(name)s);" %
+ {"tcg_func": transform_type(type_, HOST_2_TCG_TMP_FREE),
+ "name": name}
+ for (type_, name) in args_tcg_compat
+ ]
+
+ gen_name = "gen_helper_" + e.api()
+
+ out('static inline void %(name)s(%(args)s)',
+ '{',
+ ' %(code_new)s',
+ ' %(proxy_name)s(%(tmp_names)s);',
+ ' %(code_free)s',
+ '}',
+ name=gen_name,
+ args=e_args,
+ proxy_name=gen_name + "_proxy",
+ code_new="\n ".join(code_new),
+ code_free="\n ".join(code_free),
+ tmp_names=", ".join(["__%s" % name for _, name in e_args]),
+ )
diff --git a/qemu/scripts/tracetool/format/ust_events_c.py b/qemu/scripts/tracetool/format/ust_events_c.py
new file mode 100644
index 000000000..bc970936b
--- /dev/null
+++ b/qemu/scripts/tracetool/format/ust_events_c.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-ust.c
+"""
+
+__author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>"
+__copyright__ = "Copyright 2012, Mohamad Gebai <mohamad.gebai@polymtl.ca>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disabled" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#define TRACEPOINT_DEFINE',
+ '#define TRACEPOINT_CREATE_PROBES',
+ '',
+ '/* If gcc version 4.7 or older is used, LTTng ust gives a warning when compiling with',
+ ' -Wredundant-decls.',
+ ' */',
+ '#pragma GCC diagnostic ignored "-Wredundant-decls"',
+ '',
+ '#include "generated-ust-provider.h"')
diff --git a/qemu/scripts/tracetool/format/ust_events_h.py b/qemu/scripts/tracetool/format/ust_events_h.py
new file mode 100644
index 000000000..3e8a7cdf1
--- /dev/null
+++ b/qemu/scripts/tracetool/format/ust_events_h.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+trace/generated-ust-provider.h
+"""
+
+__author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>"
+__copyright__ = "Copyright 2012, Mohamad Gebai <mohamad.gebai@polymtl.ca>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+
+
+def generate(events, backend):
+ events = [e for e in events
+ if "disabled" not in e.properties]
+
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#undef TRACEPOINT_PROVIDER',
+ '#define TRACEPOINT_PROVIDER qemu',
+ '',
+ '#undef TRACEPOINT_INCLUDE_FILE',
+ '#define TRACEPOINT_INCLUDE_FILE ./generated-ust-provider.h',
+ '',
+ '#if !defined (TRACE__GENERATED_UST_H) || defined(TRACEPOINT_HEADER_MULTI_READ)',
+ '#define TRACE__GENERATED_UST_H',
+ '',
+ '#include "qemu-common.h"',
+ '#include <lttng/tracepoint.h>',
+ '',
+ '/*',
+ ' * LTTng ust 2.0 does not allow you to use TP_ARGS(void) for tracepoints',
+ ' * requiring no arguments. We define these macros introduced in more recent'
+ ' * versions of LTTng ust as a workaround',
+ ' */',
+ '#ifndef _TP_EXPROTO1',
+ '#define _TP_EXPROTO1(a) void',
+ '#endif',
+ '#ifndef _TP_EXDATA_PROTO1',
+ '#define _TP_EXDATA_PROTO1(a) void *__tp_data',
+ '#endif',
+ '#ifndef _TP_EXDATA_VAR1',
+ '#define _TP_EXDATA_VAR1(a) __tp_data',
+ '#endif',
+ '#ifndef _TP_EXVAR1',
+ '#define _TP_EXVAR1(a)',
+ '#endif',
+ '')
+
+ for e in events:
+ if len(e.args) > 0:
+ out('TRACEPOINT_EVENT(',
+ ' qemu,',
+ ' %(name)s,',
+ ' TP_ARGS(%(args)s),',
+ ' TP_FIELDS(',
+ name=e.name,
+ args=", ".join(", ".join(i) for i in e.args))
+
+ types = e.args.types()
+ names = e.args.names()
+ fmts = e.formats()
+ for t,n,f in zip(types, names, fmts):
+ if ('char *' in t) or ('char*' in t):
+ out(' ctf_string(' + n + ', ' + n + ')')
+ elif ("%p" in f) or ("x" in f) or ("PRIx" in f):
+ out(' ctf_integer_hex('+ t + ', ' + n + ', ' + n + ')')
+ elif ("ptr" in t) or ("*" in t):
+ out(' ctf_integer_hex('+ t + ', ' + n + ', ' + n + ')')
+ elif ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
+ out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')')
+ elif ('double' in t) or ('float' in t):
+ out(' ctf_float(' + t + ', ' + n + ', ' + n + ')')
+ elif ('void *' in t) or ('void*' in t):
+ out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')')
+
+ out(' )',
+ ')',
+ '')
+
+ else:
+ out('TRACEPOINT_EVENT(',
+ ' qemu,',
+ ' %(name)s,',
+ ' TP_ARGS(void),',
+ ' TP_FIELDS()',
+ ')',
+ '',
+ name=e.name)
+
+ out('#endif /* TRACE__GENERATED_UST_H */',
+ '',
+ '/* This part must be outside ifdef protection */',
+ '#include <lttng/tracepoint-event.h>')
diff --git a/qemu/scripts/tracetool/transform.py b/qemu/scripts/tracetool/transform.py
new file mode 100644
index 000000000..fc5e679ed
--- /dev/null
+++ b/qemu/scripts/tracetool/transform.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Type-transformation rules.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2014, 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"
+
+
+def _transform_type(type_, trans):
+ if isinstance(trans, str):
+ return trans
+ elif isinstance(trans, dict):
+ if type_ in trans:
+ return _transform_type(type_, trans[type_])
+ elif None in trans:
+ return _transform_type(type_, trans[None])
+ else:
+ return type_
+ elif callable(trans):
+ return trans(type_)
+ else:
+ raise ValueError("Invalid type transformation rule: %s" % trans)
+
+
+def transform_type(type_, *trans):
+ """Return a new type transformed according to the given rules.
+
+ Applies each of the transformation rules in trans in order.
+
+ If an element of trans is a string, return it.
+
+ If an element of trans is a function, call it with type_ as its only
+ argument.
+
+ If an element of trans is a dict, search type_ in its keys. If type_ is
+ a key, use the value as a transformation rule for type_. Otherwise, if
+ None is a key use the value as a transformation rule for type_.
+
+ Otherwise, return type_.
+
+ Parameters
+ ----------
+ type_ : str
+ Type to transform.
+ trans : list of function or dict
+ Type transformation rules.
+ """
+ if len(trans) == 0:
+ raise ValueError
+ res = type_
+ for t in trans:
+ res = _transform_type(res, t)
+ return res
+
+
+##################################################
+# tcg -> host
+
+def _tcg_2_host(type_):
+ if type_ == "TCGv":
+ # force a fixed-size type (target-independent)
+ return "uint64_t"
+ else:
+ return type_
+
+TCG_2_HOST = {
+ "TCGv_i32": "uint32_t",
+ "TCGv_i64": "uint64_t",
+ "TCGv_ptr": "void *",
+ None: _tcg_2_host,
+ }
+
+
+##################################################
+# host -> host compatible with tcg sizes
+
+HOST_2_TCG_COMPAT = {
+ "uint8_t": "uint32_t",
+ }
+
+
+##################################################
+# host/tcg -> tcg
+
+def _host_2_tcg(type_):
+ if type_.startswith("TCGv"):
+ return type_
+ raise ValueError("Don't know how to translate '%s' into a TCG type\n" % type_)
+
+HOST_2_TCG = {
+ "uint32_t": "TCGv_i32",
+ "uint64_t": "TCGv_i64",
+ "void *" : "TCGv_ptr",
+ None: _host_2_tcg,
+ }
+
+
+##################################################
+# tcg -> tcg helper definition
+
+def _tcg_2_helper_def(type_):
+ if type_ == "TCGv":
+ return "target_ulong"
+ else:
+ return type_
+
+TCG_2_TCG_HELPER_DEF = {
+ "TCGv_i32": "uint32_t",
+ "TCGv_i64": "uint64_t",
+ "TCGv_ptr": "void *",
+ None: _tcg_2_helper_def,
+ }
+
+
+##################################################
+# tcg -> tcg helper declaration
+
+def _tcg_2_tcg_helper_decl_error(type_):
+ raise ValueError("Don't know how to translate type '%s' into a TCG helper declaration type\n" % type_)
+
+TCG_2_TCG_HELPER_DECL = {
+ "TCGv" : "tl",
+ "TCGv_ptr": "ptr",
+ "TCGv_i32": "i32",
+ "TCGv_i64": "i64",
+ None: _tcg_2_tcg_helper_decl_error,
+ }
+
+
+##################################################
+# host/tcg -> tcg temporal constant allocation
+
+def _host_2_tcg_tmp_new(type_):
+ if type_.startswith("TCGv"):
+ return "tcg_temp_new_nop"
+ raise ValueError("Don't know how to translate type '%s' into a TCG temporal allocation" % type_)
+
+HOST_2_TCG_TMP_NEW = {
+ "uint32_t": "tcg_const_i32",
+ "uint64_t": "tcg_const_i64",
+ "void *" : "tcg_const_ptr",
+ None: _host_2_tcg_tmp_new,
+ }
+
+
+##################################################
+# host/tcg -> tcg temporal constant deallocation
+
+def _host_2_tcg_tmp_free(type_):
+ if type_.startswith("TCGv"):
+ return "tcg_temp_free_nop"
+ raise ValueError("Don't know how to translate type '%s' into a TCG temporal deallocation" % type_)
+
+HOST_2_TCG_TMP_FREE = {
+ "uint32_t": "tcg_temp_free_i32",
+ "uint64_t": "tcg_temp_free_i64",
+ "void *" : "tcg_temp_free_ptr",
+ None: _host_2_tcg_tmp_free,
+ }