All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Peter Maydell <peter.maydell@linaro.org>, qemu-devel@nongnu.org
Cc: Stefan Hajnoczi <stefanha@redhat.com>, patches@linaro.org
Subject: Re: [Qemu-devel] [PATCH 3/3] scripts/qemu-gdb: Add support for printing trace events
Date: Tue, 22 Sep 2015 16:52:26 +0200	[thread overview]
Message-ID: <56016B2A.2040803@redhat.com> (raw)
In-Reply-To: <1431621835-7565-4-git-send-email-peter.maydell@linaro.org>



On 14/05/2015 18:43, Peter Maydell wrote:
> 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 <peter.maydell@linaro.org>
> ---
>  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)
> 

Hi Peter,

what happened to this patch?

Paolo

  reply	other threads:[~2015-09-22 14:52 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-14 16:43 [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support Peter Maydell
2015-05-14 16:43 ` [Qemu-devel] [PATCH 1/3] scripts/qemu-gdb: Split MtreeCommand into its own module Peter Maydell
2015-05-14 16:43 ` [Qemu-devel] [PATCH 2/3] scripts/qemu-gdb: Split CoroutineCommand into its own file Peter Maydell
2015-05-14 16:43 ` [Qemu-devel] [PATCH 3/3] scripts/qemu-gdb: Add support for printing trace events Peter Maydell
2015-09-22 14:52   ` Paolo Bonzini [this message]
2015-09-22 15:39     ` Peter Maydell
2015-05-15  7:58 ` [Qemu-devel] [PATCH 0/3] scripts/qemu-gdb: Add event tracing support Markus Armbruster
2015-05-15  9:09   ` Peter Maydell
2015-05-15 12:18     ` Markus Armbruster
2015-05-15 12:39       ` Jan Kiszka
2015-05-15 13:21         ` Markus Armbruster
2015-05-15 13:36           ` Jan Kiszka
2015-05-15 14:18             ` Markus Armbruster
2015-05-18 13:28 ` Stefan Hajnoczi
2015-05-18 13:31 ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56016B2A.2040803@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=patches@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.