diff options
author | Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> | 2010-05-22 19:24:51 +0100 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2010-09-09 16:22:44 -0500 |
commit | 26f7227bfe9a9abee3fe5190cbfc35dd876e06d9 (patch) | |
tree | 8faec109ee82f27d466787dbfa9620682fb76d6e /simpletrace.py | |
parent | 94a420b170b3e997a185a4148accc87bdcd18156 (diff) |
trace: Add simple built-in tracing backend
This patch adds a simple tracer which produces binary trace files. To
try out the simple backend:
$ ./configure --trace-backend=simple
$ make
After running QEMU you can pretty-print the trace:
$ ./simpletrace.py trace-events trace.log
The output of simpletrace.py looks like this:
qemu_realloc 0.699 ptr=0x24363f0 size=0x3 newptr=0x24363f0
qemu_free 0.768 ptr=0x24363f0
^ ^---- timestamp delta (us)
|____ trace event name
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
trace: Make trace record fields 64-bit
Explicitly use 64-bit fields in trace records so that timestamps and
magic numbers work for 32-bit host builds.
Includes fixes from Prerna Saxena <prerna@linux.vnet.ibm.com>.
Signed-off-by: Prerna Saxena <prerna@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Diffstat (limited to 'simpletrace.py')
-rwxr-xr-x | simpletrace.py | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/simpletrace.py b/simpletrace.py new file mode 100755 index 0000000000..c2cf1682d0 --- /dev/null +++ b/simpletrace.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# Pretty-printer for simple trace backend binary trace files +# +# 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. +# +# For help see docs/tracing.txt + +import sys +import struct +import re + +header_event_id = 0xffffffffffffffff +header_magic = 0xf2b177cb0aa429b4 +header_version = 0 + +trace_fmt = '=QQQQQQQQ' +trace_len = struct.calcsize(trace_fmt) +event_re = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\)\s+"([^"]*)"') + +def err(msg): + sys.stderr.write(msg + '\n') + sys.exit(1) + +def parse_events(fobj): + """Parse a trace-events file.""" + + def get_argnames(args): + """Extract argument names from a parameter list.""" + return tuple(arg.split()[-1].lstrip('*') for arg in args.split(',')) + + events = {} + event_num = 0 + for line in fobj: + m = event_re.match(line.strip()) + if m is None: + continue + + disable, name, args, fmt = m.groups() + events[event_num] = (name,) + get_argnames(args) + event_num += 1 + return events + +def read_record(fobj): + """Deserialize a trace record from a file.""" + s = fobj.read(trace_len) + if len(s) != trace_len: + return None + return struct.unpack(trace_fmt, s) + +def read_trace_file(fobj): + """Deserialize trace records from a file.""" + header = read_record(fobj) + if header is None or \ + header[0] != header_event_id or \ + header[1] != header_magic or \ + header[2] != header_version: + err('not a trace file or incompatible version') + + while True: + rec = read_record(fobj) + if rec is None: + break + + yield rec + +class Formatter(object): + def __init__(self, events): + self.events = events + self.last_timestamp = None + + def format_record(self, rec): + if self.last_timestamp is None: + self.last_timestamp = rec[1] + delta_ns = rec[1] - self.last_timestamp + self.last_timestamp = rec[1] + + event = self.events[rec[0]] + fields = [event[0], '%0.3f' % (delta_ns / 1000.0)] + for i in xrange(1, len(event)): + fields.append('%s=0x%x' % (event[i], rec[i + 1])) + return ' '.join(fields) + +if len(sys.argv) != 3: + err('usage: %s <trace-events> <trace-file>' % sys.argv[0]) + +events = parse_events(open(sys.argv[1], 'r')) +formatter = Formatter(events) +for rec in read_trace_file(open(sys.argv[2], 'rb')): + print formatter.format_record(rec) |