Tracing pull request

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJTamnaAAoJEJykq7OBq3PIvIIH/jX2XsOLfCh9GCKxTrFU3mS7
 5/0z9bObS/vWXXVun6DDlrgAUURlmhsm9jiMqpViNHf4AuNCgDkfwrFbrhmd8YPA
 +5Pq4jcpCKaDol/E63DMlUIwMpTwlW46rDoXfLGzHQDW0WBduSrL0qUYjJg0wMOj
 1LCTAQSxNDeumUYfsRWPxThSN0gXgPNIbR5B5OQi2WqGiEB36+nGWdgMzJ34ZHDO
 xql/uLkJsXmX2WFJX7Hr9upxXikRwC0K4B9yTI8ozq7fUQ1hg4WvJ1B/3UxJRv+Y
 QTvqhQ6suPfjoypohdMO7FDITZpFzkimfcGgBje7bBifz6CpluC0ppQyKVC+ic4=
 =kUXD
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging

Tracing pull request

# gpg: Signature made Wed 07 May 2014 18:14:02 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/tracing-pull-request:
  configure: Show trace output file conditionally
  trace: [tracetool] Minimize the amount of per-backend code
  trace: [simple] Bump up log version number
  trace: [tracetool] Change format docs to point to the generated file
  trace: [tracetool] Show list of frontends and backends sorted by name
  trace: [tracetool] Cosmetic changes
  trace: [tracetool] Spacing changes
  trace: [tracetool] Add methods 'Event.copy' and 'Arguments.copy'
  trace: [tracetool] Add method 'Event.api' to build event names

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-05-08 12:38:01 +01:00
commit 43cbeffb19
21 changed files with 357 additions and 427 deletions

2
configure vendored
View File

@ -4153,7 +4153,9 @@ echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net" echo "vhost-net support $vhost_net"
echo "vhost-scsi support $vhost_scsi" echo "vhost-scsi support $vhost_scsi"
echo "Trace backend $trace_backend" echo "Trace backend $trace_backend"
if test "$trace_backend" = "simple"; then
echo "Trace output file $trace_file-<pid>" echo "Trace output file $trace_file-<pid>"
fi
if test "$spice" = "yes"; then if test "$spice" = "yes"; then
echo "spice support $spice ($spice_protocol_version/$spice_server_version)" echo "spice support $spice ($spice_protocol_version/$spice_server_version)"
else else

View File

@ -65,13 +65,13 @@ def read_trace_file(edict, fobj):
header[0] != header_event_id or \ header[0] != header_event_id or \
header[1] != header_magic: header[1] != header_magic:
raise ValueError('Not a valid trace file!') raise ValueError('Not a valid trace file!')
if header[2] != 0 and \
header[2] != 2:
raise ValueError('Unknown version of tracelog format!')
log_version = header[2] log_version = header[2]
if log_version == 0: if log_version not in [0, 2, 3]:
raise ValueError('Older log format, not supported with this QEMU release!') raise ValueError('Unknown version of tracelog format!')
if log_version != 3:
raise ValueError('Log format %d not supported with this QEMU release!'
% log_version)
while True: while True:
rec = read_record(edict, fobj) rec = read_record(edict, fobj)
@ -109,14 +109,10 @@ def process(events, log, analyzer):
if isinstance(log, str): if isinstance(log, str):
log = open(log, 'rb') log = open(log, 'rb')
enabled_events = []
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)") dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
edict = {dropped_event_id: dropped_event} edict = {dropped_event_id: dropped_event}
for e in events: for num, event in enumerate(events):
if 'disable' not in e.properties:
enabled_events.append(e)
for num, event in enumerate(enabled_events):
edict[num] = event edict[num] = event
def build_fn(analyzer, event): def build_fn(analyzer, event):

View File

@ -6,7 +6,7 @@ Machinery for generating tracing-related intermediate files.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -52,6 +52,10 @@ class Arguments:
""" """
self._args = args self._args = args
def copy(self):
"""Create a new copy."""
return Arguments(list(self._args))
@staticmethod @staticmethod
def build(arg_str): def build(arg_str):
"""Build and Arguments instance from an argument string. """Build and Arguments instance from an argument string.
@ -144,7 +148,13 @@ class Event(object):
unknown_props = set(self.properties) - self._VALID_PROPS unknown_props = set(self.properties) - self._VALID_PROPS
if len(unknown_props) > 0: if len(unknown_props) > 0:
raise ValueError("Unknown properties: %s" % ", ".join(unknown_props)) raise ValueError("Unknown properties: %s"
% ", ".join(unknown_props))
def copy(self):
"""Create a new copy."""
return Event(self.name, list(self.properties), self.fmt,
self.args.copy(), self)
@staticmethod @staticmethod
def build(line_str): def build(line_str):
@ -173,6 +183,14 @@ class Event(object):
self.args, self.args,
self.fmt) self.fmt)
QEMU_TRACE = "trace_%(name)s"
def api(self, fmt=None):
if fmt is None:
fmt = Event.QEMU_TRACE
return fmt % {"name": self.name}
def _read_events(fobj): def _read_events(fobj):
res = [] res = []
for line in fobj: for line in fobj:
@ -189,7 +207,7 @@ class TracetoolError (Exception):
pass pass
def try_import(mod_name, attr_name = None, attr_default = None): def try_import(mod_name, attr_name=None, attr_default=None):
"""Try to import a module and get an attribute from it. """Try to import a module and get an attribute from it.
Parameters Parameters
@ -216,7 +234,7 @@ def try_import(mod_name, attr_name = None, attr_default = None):
def generate(fevents, format, backend, def generate(fevents, format, backend,
binary = None, probe_prefix = None): binary=None, probe_prefix=None):
"""Generate the output for the given (format, backend) pair. """Generate the output for the given (format, backend) pair.
Parameters Parameters
@ -238,20 +256,17 @@ def generate(fevents, format, backend,
format = str(format) format = str(format)
if len(format) is 0: if len(format) is 0:
raise TracetoolError("format not set") raise TracetoolError("format not set")
mformat = format.replace("-", "_") if not tracetool.format.exists(format):
if not tracetool.format.exists(mformat):
raise TracetoolError("unknown format: %s" % format) raise TracetoolError("unknown format: %s" % format)
format = format.replace("-", "_")
backend = str(backend) backend = str(backend)
if len(backend) is 0: if len(backend) is 0:
raise TracetoolError("backend not set") raise TracetoolError("backend not set")
mbackend = backend.replace("-", "_") if not tracetool.backend.exists(backend):
if not tracetool.backend.exists(mbackend):
raise TracetoolError("unknown backend: %s" % backend) raise TracetoolError("unknown backend: %s" % backend)
backend = backend.replace("-", "_")
if not tracetool.backend.compatible(mbackend, mformat): backend = tracetool.backend.Wrapper(backend, format)
raise TracetoolError("backend '%s' not compatible with format '%s'" %
(backend, format))
import tracetool.backend.dtrace import tracetool.backend.dtrace
tracetool.backend.dtrace.BINARY = binary tracetool.backend.dtrace.BINARY = binary
@ -259,16 +274,4 @@ def generate(fevents, format, backend,
events = _read_events(fevents) events = _read_events(fevents)
if backend == "nop": tracetool.format.generate(events, format, backend)
( 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)

View File

@ -30,17 +30,24 @@ PUBLIC If exists and is set to 'True', the backend is considered "public".
Backend functions Backend functions
----------------- -----------------
======== ======================================================================= All the following functions are optional, and no output will be generated if
Function Description they do not exist.
======== =======================================================================
<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 Function Description
considered not compatible with the given format. =============================== ==============================================
======== ======================================================================= 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>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -59,7 +66,7 @@ def get_list(only_public = False):
for filename in os.listdir(tracetool.backend.__path__[0]): for filename in os.listdir(tracetool.backend.__path__[0]):
if filename.endswith('.py') and filename != '__init__.py': if filename.endswith('.py') and filename != '__init__.py':
modnames.append(filename.rsplit('.', 1)[0]) modnames.append(filename.rsplit('.', 1)[0])
for modname in modnames: for modname in sorted(modnames):
module = tracetool.try_import("tracetool.backend." + modname) module = tracetool.try_import("tracetool.backend." + modname)
# just in case; should never fail unless non-module files are put there # just in case; should never fail unless non-module files are put there
@ -91,39 +98,24 @@ def exists(name):
return tracetool.try_import("tracetool.backend." + name)[1] return tracetool.try_import("tracetool.backend." + name)[1]
def compatible(backend, format): class Wrapper:
"""Whether a backend is compatible with the given format.""" def __init__(self, backend, format):
if not exists(backend): self._backend = backend.replace("-", "_")
raise ValueError("unknown backend: %s" % backend) self._format = format.replace("-", "_")
assert exists(self._backend)
assert tracetool.format.exists(self._format)
backend = backend.replace("-", "_") def _run_function(self, name, *args, **kwargs):
format = format.replace("-", "_") func = tracetool.try_import("tracetool.backend." + self._backend,
name % self._format, None)[1]
if func is not None:
func(*args, **kwargs)
if backend == "nop": def generate_begin(self, events):
return True self._run_function("generate_%s_begin", events)
else:
func = tracetool.try_import("tracetool.backend." + backend,
format, None)[1]
return func is not None
def generate(self, event):
self._run_function("generate_%s", event)
def _empty(events): def generate_end(self, events):
pass self._run_function("generate_%s_end", events)
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))
backend = backend.replace("-", "_")
format = format.replace("-", "_")
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)

View File

@ -6,7 +6,7 @@ DTrace/SystemTAP backend.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -21,7 +21,7 @@ PUBLIC = True
PROBEPREFIX = None PROBEPREFIX = None
def _probeprefix(): def probeprefix():
if PROBEPREFIX is None: if PROBEPREFIX is None:
raise ValueError("you must set PROBEPREFIX") raise ValueError("you must set PROBEPREFIX")
return PROBEPREFIX return PROBEPREFIX
@ -29,81 +29,18 @@ def _probeprefix():
BINARY = None BINARY = None
def _binary(): def binary():
if BINARY is None: if BINARY is None:
raise ValueError("you must set BINARY") raise ValueError("you must set BINARY")
return BINARY return BINARY
def c(events): def generate_h_begin(events):
pass
def h(events):
out('#include "trace/generated-tracers-dtrace.h"', out('#include "trace/generated-tracers-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 generate_h(event):
def d(events): out(' QEMU_%(uppername)s(%(argnames)s);',
out('provider qemu {') uppername=event.name.upper(),
argnames=", ".join(event.args.names()))
for e in events:
args = str(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('',
'};')
# 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(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():
# Append underscore to reserved keywords
if name in RESERVED_WORDS:
name += '_'
out(' %s = $arg%d;' % (name, i))
i += 1
out('}')
out()

View File

@ -1,23 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Generic event description.
This is a dummy backend to establish appropriate frontend/backend compatibility
checks.
"""
__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"
def events_h(events):
pass
def events_c(events):
pass

View File

@ -19,36 +19,30 @@ from tracetool import out
PUBLIC = True PUBLIC = True
def c(events): def generate_h_begin(events):
pass
def h(events):
out('#include "trace/ftrace.h"', out('#include "trace/ftrace.h"',
'#include "trace/control.h"', '#include "trace/control.h"',
'', '')
)
for e in events:
argnames = ", ".join(e.args.names())
if len(e.args) > 0:
argnames = ", " + argnames
out('static inline void trace_%(name)s(%(args)s)', def generate_h(event):
'{', argnames = ", ".join(event.args.names())
' char ftrace_buf[MAX_TRACE_STRLEN];', if len(event.args) > 0:
' int unused __attribute__ ((unused));', argnames = ", " + argnames
' int trlen;',
' bool _state = trace_event_get_state(%(event_id)s);', out(' {',
' if (_state) {', ' char ftrace_buf[MAX_TRACE_STRLEN];',
' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,', ' int unused __attribute__ ((unused));',
' "%(name)s " %(fmt)s "\\n" %(argnames)s);', ' int trlen;',
' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);', ' if (trace_event_get_state(%(event_id)s)) {',
' unused = write(trace_marker_fd, ftrace_buf, trlen);', ' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,',
' }', ' "%(name)s " %(fmt)s "\\n" %(argnames)s);',
'}', ' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);',
name = e.name, ' unused = write(trace_marker_fd, ftrace_buf, trlen);',
args = e.args, ' }',
event_id = "TRACE_" + e.name.upper(), ' }',
fmt = e.fmt.rstrip("\n"), name=event.name,
argnames = argnames, args=event.args,
) event_id="TRACE_" + event.name.upper(),
fmt=event.fmt.rstrip("\n"),
argnames=argnames)

View File

@ -6,7 +6,7 @@ Simple built-in backend.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -26,76 +26,74 @@ def is_string(arg):
else: else:
return False return False
def c(events):
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"', out('#include "trace.h"',
'#include "trace/control.h"', '#include "trace/control.h"',
'#include "trace/simple.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)
for num, event in enumerate(events): if len(event.args) > 0:
out('void trace_%(name)s(%(args)s)',
'{',
' TraceBufferRecord rec;',
name = event.name,
args = event.args,
)
sizes = []
for type_, name in event.args: for type_, name in event.args:
# string
if is_string(type_): if is_string(type_):
out(' size_t arg%(name)s_len = %(name)s ? MIN(strlen(%(name)s), MAX_TRACE_STRLEN) : 0;', out(' trace_record_write_str(&rec, %(name)s, arg%(name)s_len);',
name = name, name=name)
) # pointer var (not string)
strsizeinfo = "4 + arg%s_len" % name elif type_.endswith('*'):
sizes.append(strsizeinfo) out(' trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)%(name)s);',
name=name)
# primitive data type
else: else:
sizes.append("8") out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);',
sizestr = " + ".join(sizes) name=name)
if len(event.args) == 0:
sizestr = '0'
out(' trace_record_finish(&rec);',
out('', '}',
' TraceEvent *eventp = trace_event_id(%(event_enum)s);', '')
' bool _state = trace_event_get_state_dynamic(eventp);',
' if (!_state) {',
' return;',
' }',
'',
' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
' return; /* Trace Buffer Full, Event Dropped ! */',
' }',
event_enum = 'TRACE_' + event.name.upper(),
event_id = num,
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);',
'}',
'')
def h(events):
for event in events:
out('void trace_%(name)s(%(args)s);',
name = event.name,
args = event.args,
)

View File

@ -6,7 +6,7 @@ Stderr built-in backend.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -19,30 +19,21 @@ from tracetool import out
PUBLIC = True PUBLIC = True
def c(events): def generate_h_begin(events):
pass
def h(events):
out('#include <stdio.h>', out('#include <stdio.h>',
'#include "trace/control.h"', '#include "trace/control.h"',
'', '')
)
for e in events:
argnames = ", ".join(e.args.names())
if len(e.args) > 0:
argnames = ", " + argnames
out('static inline void trace_%(name)s(%(args)s)', def generate_h(event):
'{', argnames = ", ".join(event.args.names())
' bool _state = trace_event_get_state(%(event_id)s);', if len(event.args) > 0:
' if (_state) {', argnames = ", " + argnames
' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
' }', out(' if (trace_event_get_state(%(event_id)s)) {',
'}', ' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
name = e.name, ' }',
args = e.args, event_id="TRACE_" + event.name.upper(),
event_id = "TRACE_" + e.name.upper(), name=event.name,
fmt = e.fmt.rstrip("\n"), fmt=event.fmt.rstrip("\n"),
argnames = argnames, argnames=argnames)
)

View File

@ -6,7 +6,7 @@ LTTng User Space Tracing backend.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -18,65 +18,18 @@ from tracetool import out
PUBLIC = True PUBLIC = True
def c(events):
pass
def generate_h_begin(events):
def h(events):
out('#include <lttng/tracepoint.h>', out('#include <lttng/tracepoint.h>',
'#include "trace/generated-ust-provider.h"', '#include "trace/generated-ust-provider.h"',
'') '')
for e in events:
argnames = ", ".join(e.args.names())
if len(e.args) > 0:
argnames = ", " + argnames
out('static inline void trace_%(name)s(%(args)s)',
'{',
' tracepoint(qemu, %(name)s%(tp_args)s);',
'}',
'',
name = e.name,
args = e.args,
tp_args = argnames,
)
def ust_events_c(events): def generate_h(event):
pass argnames = ", ".join(event.args.names())
if len(event.args) > 0:
argnames = ", " + argnames
def ust_events_h(events): out(' tracepoint(qemu, %(name)s%(tp_args)s);',
for e in events: name=event.name,
if len(e.args) > 0: tp_args=argnames)
out('TRACEPOINT_EVENT(',
' qemu,',
' %(name)s,',
' TP_ARGS(%(args)s),',
' TP_FIELDS(',
name = e.name,
args = ", ".join(", ".join(i) for i in e.args),
)
for t,n in e.args:
if ('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 ('char *' in t) or ('char*' in t):
out(' ctf_string(' + 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,
)

View File

@ -20,21 +20,16 @@ All formats must generate their contents through the 'tracetool.out' routine.
Format functions Format functions
---------------- ----------------
All the following functions are optional, and no output will be generated if ======== ==================================================================
they do not exist.
======== =======================================================================
Function Description Function Description
======== ======================================================================= ======== ==================================================================
begin Called to generate the format-specific file header. generate Called to generate a format-specific file.
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>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -53,7 +48,7 @@ def get_list():
for filename in os.listdir(tracetool.format.__path__[0]): for filename in os.listdir(tracetool.format.__path__[0]):
if filename.endswith('.py') and filename != '__init__.py': if filename.endswith('.py') and filename != '__init__.py':
modnames.append(filename.rsplit('.', 1)[0]) modnames.append(filename.rsplit('.', 1)[0])
for modname in modnames: for modname in sorted(modnames):
module = tracetool.try_import("tracetool.format." + modname) module = tracetool.try_import("tracetool.format." + modname)
# just in case; should never fail unless non-module files are put there # just in case; should never fail unless non-module files are put there
@ -79,25 +74,12 @@ def exists(name):
return tracetool.try_import("tracetool.format." + name)[1] return tracetool.try_import("tracetool.format." + name)[1]
def _empty(events): def generate(events, format, backend):
pass if not exists(format):
raise ValueError("unknown format: %s" % format)
def generate_begin(name, events): format = format.replace("-", "_")
"""Generate the header of the format-specific file.""" func = tracetool.try_import("tracetool.format." + format,
if not exists(name): "generate")[1]
raise ValueError("unknown format: %s" % name) if func is None:
raise AttributeError("format has no 'generate': %s" % format)
name = name.replace("-", "_") func(events, backend)
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)
name = name.replace("-", "_")
func = tracetool.try_import("tracetool.format." + name,
"end", _empty)[1]
func(events)

View File

@ -2,11 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .c file. trace/generated-tracers.c
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -16,5 +16,13 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
def begin(events): def generate(events, backend):
out('/* This file is autogenerated by tracetool, do not edit. */') 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)

View File

@ -2,11 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .d file (DTrace only). trace/generated-tracers.dtrace (DTrace only).
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -16,5 +16,27 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
def begin(events): def generate(events, backend):
out('/* This file is autogenerated by tracetool, do not edit. */') 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 = str(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('',
'};')

View File

@ -2,11 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .c for event description. trace/generated-events.c
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -16,14 +16,13 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
def begin(events): def generate(events, backend):
out('/* This file is autogenerated by tracetool, do not edit. */', out('/* This file is autogenerated by tracetool, do not edit. */',
'', '',
'#include "trace.h"', '#include "trace.h"',
'#include "trace/generated-events.h"', '#include "trace/generated-events.h"',
'#include "trace/control.h"', '#include "trace/control.h"',
'', '')
)
out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {') out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
@ -31,9 +30,7 @@ def begin(events):
out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },', out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
id = "TRACE_" + e.name.upper(), id = "TRACE_" + e.name.upper(),
name = e.name, name = e.name,
sstate = "TRACE_%s_ENABLED" % e.name.upper(), sstate = "TRACE_%s_ENABLED" % e.name.upper())
)
out('};', out('};',
'', '')
)

View File

@ -2,11 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .h for event description. trace/generated-events.h
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -16,15 +16,14 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
def begin(events): def generate(events, backend):
out('/* This file is autogenerated by tracetool, do not edit. */', out('/* This file is autogenerated by tracetool, do not edit. */',
'', '',
'#ifndef TRACE__GENERATED_EVENTS_H', '#ifndef TRACE__GENERATED_EVENTS_H',
'#define TRACE__GENERATED_EVENTS_H', '#define TRACE__GENERATED_EVENTS_H',
'', '',
'#include <stdbool.h>', '#include <stdbool.h>',
'' '')
)
# event identifiers # event identifiers
out('typedef enum {') out('typedef enum {')
@ -33,8 +32,7 @@ def begin(events):
out(' TRACE_%s,' % e.name.upper()) out(' TRACE_%s,' % e.name.upper())
out(' TRACE_EVENT_COUNT', out(' TRACE_EVENT_COUNT',
'} TraceEventID;', '} TraceEventID;')
)
# static state # static state
for e in events: for e in events:
@ -46,5 +44,4 @@ def begin(events):
out('#include "trace/event-internal.h"', out('#include "trace/event-internal.h"',
'', '',
'#endif /* TRACE__GENERATED_EVENTS_H */', '#endif /* TRACE__GENERATED_EVENTS_H */')
)

View File

@ -2,11 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .h file. trace/generated-tracers.h
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -16,23 +16,29 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
def begin(events): def generate(events, backend):
out('/* This file is autogenerated by tracetool, do not edit. */', out('/* This file is autogenerated by tracetool, do not edit. */',
'', '',
'#ifndef TRACE__GENERATED_TRACERS_H', '#ifndef TRACE__GENERATED_TRACERS_H',
'#define TRACE__GENERATED_TRACERS_H', '#define TRACE__GENERATED_TRACERS_H',
'', '',
'#include "qemu-common.h"') '#include "qemu-common.h"',
'')
def end(events): backend.generate_begin(events)
out('#endif /* TRACE__GENERATED_TRACERS_H */')
def nop(events):
for e in events: for e in events:
out('', out('',
'static inline void trace_%(name)s(%(args)s)', 'static inline void %(api)s(%(args)s)',
'{', '{',
'}', api=e.api(),
name = e.name, args=e.args)
args = e.args,
) if "disable" not in e.properties:
backend.generate(e)
out('}')
backend.generate_end(events)
out('#endif /* TRACE__GENERATED_TRACERS_H */')

View File

@ -6,7 +6,7 @@ Generate .stp file (DTrace with SystemTAP only).
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012, 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" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -14,7 +14,43 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
from tracetool.backend.dtrace import binary, probeprefix
def begin(events): # Technically 'self' is not used by systemtap yet, but
out('/* This file is autogenerated by tracetool, do not edit. */') # 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 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():
# Append underscore to reserved keywords
if name in RESERVED_WORDS:
name += '_'
out(' %s = $arg%d;' % (name, i))
i += 1
out('}')
out()

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .c for LTTng ust event description. trace/generated-ust.c
""" """
__author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>" __author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>"
@ -16,7 +16,10 @@ __email__ = "stefanha@redhat.com"
from tracetool import out from tracetool import out
def begin(events): 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. */', out('/* This file is autogenerated by tracetool, do not edit. */',
'', '',
'#define TRACEPOINT_DEFINE', '#define TRACEPOINT_DEFINE',

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Generate .h for LTTng ust event description. trace/generated-ust-provider.h
""" """
__author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>" __author__ = "Mohamad Gebai <mohamad.gebai@polymtl.ca>"
@ -16,7 +16,10 @@ __email__ = "stefanha@redhat.com"
from tracetool import out from tracetool import out
def begin(events): 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. */', out('/* This file is autogenerated by tracetool, do not edit. */',
'', '',
'#undef TRACEPOINT_PROVIDER', '#undef TRACEPOINT_PROVIDER',
@ -50,7 +53,40 @@ def begin(events):
'#endif', '#endif',
'') '')
def end(events): 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))
for t, n in e.args:
if ('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 ('char *' in t) or ('char*' in t):
out(' ctf_string(' + 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 */', out('#endif /* TRACE__GENERATED_UST_H */',
'', '',
'/* This part must be outside ifdef protection */', '/* This part must be outside ifdef protection */',

View File

@ -31,7 +31,7 @@ $(obj)/generated-events.h: $(obj)/generated-events.h-timestamp
$(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events $(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=events-h \ --format=events-h \
--backend=events \ --backend=$(TRACE_BACKEND) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
@ -39,7 +39,7 @@ $(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/conf
$(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events $(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=events-c \ --format=events-c \
--backend=events \ --backend=$(TRACE_BACKEND) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)

View File

@ -28,7 +28,7 @@
#define HEADER_MAGIC 0xf2b177cb0aa429b4ULL #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL
/** Trace file version number, bump if format changes */ /** Trace file version number, bump if format changes */
#define HEADER_VERSION 2 #define HEADER_VERSION 3
/** Records were dropped event ID */ /** Records were dropped event ID */
#define DROPPED_EVENT_ID (~(uint64_t)0 - 1) #define DROPPED_EVENT_ID (~(uint64_t)0 - 1)