[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/3] scripts/qemu-gdb: Add support for printing trac
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PATCH 3/3] scripts/qemu-gdb: Add support for printing trace events |
Date: |
Thu, 14 May 2015 17:43:55 +0100 |
Add two new commands to our gdb support:
qemu trace-enable eventname
qemu trace-disable eventname
which allow dynamically enabling and disabling printing of QEMU
trace events during a debugging session. These work with the
"null" trace backend, by putting breakpoints on the stub
trace_eventname() functions.
Signed-off-by: Peter Maydell <address@hidden>
---
scripts/qemu-gdb.py | 4 +-
scripts/qemugdb/trace.py | 188 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 191 insertions(+), 1 deletion(-)
create mode 100644 scripts/qemugdb/trace.py
diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
index 1c94b2a..6d27c06 100644
--- a/scripts/qemu-gdb.py
+++ b/scripts/qemu-gdb.py
@@ -23,7 +23,7 @@ import os, sys
sys.path.append(os.path.dirname(__file__))
-from qemugdb import mtree, coroutine
+from qemugdb import mtree, coroutine, trace
class QemuCommand(gdb.Command):
'''Prefix for QEMU debug support commands'''
@@ -34,3 +34,5 @@ class QemuCommand(gdb.Command):
QemuCommand()
coroutine.CoroutineCommand()
mtree.MtreeCommand()
+trace.TraceEnableCommand()
+trace.TraceDisableCommand()
diff --git a/scripts/qemugdb/trace.py b/scripts/qemugdb/trace.py
new file mode 100644
index 0000000..24543e1
--- /dev/null
+++ b/scripts/qemugdb/trace.py
@@ -0,0 +1,188 @@
+#!/usr/bin/python
+
+# GDB debugging support: selecting printing of trace events
+#
+# Copyright (c) 2015 Linaro Ltd
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see
+# <http://www.gnu.org/licenses/gpl-2.0.html>
+
+# qemu trace-enable trace-event-name
+# qemu trace-disable trace-event-name
+# * enable/disable printing of tracing for QEMU trace events (works
+# even if QEMU was built with the null trace backend; may not work
+# with non-debug QEMU builds)
+
+import gdb
+import re, os
+
+# Assume the trace-events file is at ../../ relative to where we are
+
+trace_events_filename = os.path.join(os.path.dirname(__file__),
+ os.pardir,os.pardir,
+ "trace-events")
+
+def gdb_bp_list():
+ '''Like gdb.breakpoints(), but return empty list if no bps, not None'''
+ # The point is that this is always iterable
+ bplist = gdb.breakpoints()
+ if not bplist:
+ return []
+ return bplist
+
+class TraceEventInfo:
+ def __init__(self, name, formatstring, arglist):
+ self.name = name
+ self.formatstring = formatstring
+ self.arglist = arglist
+ self.argstr = ", ".join(arglist)
+ if self.argstr != "":
+ self.argstr = ", " + self.argstr
+
+# Hash of trace events read in from the 'trace-events' file;
+# values are TraceEventInfo objects
+trace_events = {}
+
+def extract_identifier(s):
+ '''Extract the identifier from a C argument declaration'''
+ # That is, given "const char *filename" return "filename".
+ r = re.sub(r'.*?([a-zA-Z_][a-zA-Z_0-9]*)\s*$', r'\1', s)
+ if r == 'void':
+ return None
+ return r
+
+# Preprocessor symbols which we know about.
+# These should work for both 32 bit and 64 bit Linux, at least.
+# If we needed to, we could determine whether the target was
+# 32 or 64 bit with
+# is_64bit = gdb.lookup_type('void').pointer().sizeof == 8
+# but we can get away without it.
+fmtstr_dict = {
+ "PRIu8":"u",
+ "PRIx32":"x",
+ "PRIu32":"u",
+ "PRId32":"d",
+ "PRIx64":"llx",
+ "PRIu64":"llu",
+ "PRId64":"lld",
+ "PRIxPTR":"llx",
+}
+
+def fixup_fmtstr(s):
+ # fmtstr needs to have leading space and " removed,
+ # trailing " removed, and handling of interpolated PRIxfoo
+ # dealt with (including trailing PRIxfoo)
+ inquotes = False
+ inescape = False
+ new = ""
+ sym = ""
+ for c in s:
+ if inquotes:
+ if inescape:
+ new = new + c
+ inescape = False
+ elif c == '\\':
+ inescape = True
+ new = new + c
+ elif c == '"':
+ inquotes = False
+ sym = ""
+ else:
+ new = new + c
+ else:
+ if c == '"':
+ # end of unquoted section
+ sym = sym.strip()
+ if sym != "":
+ new = new + fmtstr_dict[sym]
+ inquotes = True
+ else:
+ sym = sym + c
+
+ # gdb printf doesn't understand the 'z' length modifier,
+ # so convert to 'l'
+ return re.sub(r'(?<!%)%z', r'%l', new)
+ return new
+
+def read_trace_events_file(filename):
+ '''Populate the trace_events dictionary from the specified file'''
+ global trace_events
+ trace_events = {}
+ f = open(filename)
+ for line in iter(f):
+ try:
+ line = line.strip()
+ if line == "" or line.startswith('#'):
+ continue
+
+ # Very ugly ad-hoc parsing
+ (name, rest) = line.split('(', 1)
+ (rest, fmtstr) = rest.split(')', 1)
+
+ fmtstr = fixup_fmtstr(fmtstr)
+
+ arglist = rest.split(',')
+ arglist = [extract_identifier(x) for x in arglist]
+ arglist = [x for x in arglist if x is not None]
+ trace_events[name] = TraceEventInfo(name, fmtstr, arglist)
+ except:
+ gdb.write('Warning: ignoring line: %s\n' % line)
+ raise
+
+class QemuTraceBreakpoint(gdb.Breakpoint):
+ def __init__(self, eventname):
+ self.event = trace_events[eventname]
+ spec = "trace_" + eventname
+ # might want to make these internal bps later
+ gdb.Breakpoint.__init__(self, spec, gdb.BP_BREAKPOINT, False)
+
+ def stop(self):
+ gdb.write('%s: ' % self.event.name)
+ gdb.execute('printf "%s\\n"%s'
+ % (self.event.formatstring, self.event.argstr))
+ # Tell gdb not to actually stop here
+ return False
+
+class TraceEnableCommand(gdb.Command):
+ '''Enable in-gdb tracing of the specified QEMU trace event'''
+ def __init__(self):
+ gdb.Command.__init__(self, 'qemu trace-enable', gdb.COMMAND_DATA,
+ gdb.COMPLETE_NONE)
+
+ def invoke(self, arg, from_tty):
+ # place breakpoint on function trace_<eventname>
+ # set up breakpoint to print info and continue
+ # add bp to hash table with key being the event name
+ if arg not in trace_events:
+ gdb.write('Unknown trace event %s\n')
+ return
+ gdb.write("Enabled trace event %s\n" % arg)
+ QemuTraceBreakpoint(arg)
+
+class TraceDisableCommand(gdb.Command):
+ '''Disable in-gdb tracing of the specified QEMU trace event'''
+ def __init__(self):
+ gdb.Command.__init__(self, 'qemu trace-disable', gdb.COMMAND_DATA,
+ gdb.COMPLETE_NONE)
+
+ def invoke(self, arg, from_tty):
+ # delete the bp set on trace_<eventname> by the enable command
+ for bp in gdb_bp_list():
+ if isinstance(bp, QemuTraceBreakpoint) and bp.event.name == arg:
+ bp.delete()
+ gdb.write("Disabled trace event %s\n" % arg)
+ return
+ gdb.write("Can't disable trace event %s: unknown or not enabled\n" %
arg)
+
+read_trace_events_file(trace_events_filename)
--
1.9.1
- [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Peter Maydell, 2015/05/14
- [Qemu-devel] [PATCH 1/3] scripts/qemu-gdb: Split MtreeCommand into its own module, Peter Maydell, 2015/05/14
- [Qemu-devel] [PATCH 3/3] scripts/qemu-gdb: Add support for printing trace events,
Peter Maydell <=
- [Qemu-devel] [PATCH 2/3] scripts/qemu-gdb: Split CoroutineCommand into its own file, Peter Maydell, 2015/05/14
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Markus Armbruster, 2015/05/15
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Peter Maydell, 2015/05/15
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Markus Armbruster, 2015/05/15
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Jan Kiszka, 2015/05/15
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Markus Armbruster, 2015/05/15
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Jan Kiszka, 2015/05/15
- Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Markus Armbruster, 2015/05/15
Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Stefan Hajnoczi, 2015/05/18
Re: [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support, Stefan Hajnoczi, 2015/05/18