aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/qemu-trace-stap
diff options
context:
space:
mode:
authorTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
committerTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
commite02cda008591317b1625707ff8e115a4841aa889 (patch)
treeaee302e3cf8b59ec2d32ec481be3d1afddfc8968 /scripts/qemu-trace-stap
parentcc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff)
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback design to work with QEMU and rust-vmm vhost-user backend without require any changes. Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'scripts/qemu-trace-stap')
-rwxr-xr-xscripts/qemu-trace-stap169
1 files changed, 169 insertions, 0 deletions
diff --git a/scripts/qemu-trace-stap b/scripts/qemu-trace-stap
new file mode 100755
index 000000000..eb6e951ff
--- /dev/null
+++ b/scripts/qemu-trace-stap
@@ -0,0 +1,169 @@
+#!/usr/bin/env python3
+# -*- python -*-
+#
+# Copyright (C) 2019 Red Hat, Inc
+#
+# QEMU SystemTap Trace Tool
+#
+# 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/>.
+
+import argparse
+import copy
+import os.path
+import re
+import subprocess
+import sys
+
+
+def probe_prefix(binary):
+ dirname, filename = os.path.split(binary)
+ return re.sub("-", ".", filename) + ".log"
+
+
+def which(binary):
+ for path in os.environ["PATH"].split(os.pathsep):
+ if os.path.exists(os.path.join(path, binary)):
+ return os.path.join(path, binary)
+
+ print("Unable to find '%s' in $PATH" % binary)
+ sys.exit(1)
+
+
+def tapset_dir(binary):
+ dirname, filename = os.path.split(binary)
+ if dirname == '':
+ thisfile = which(binary)
+ else:
+ thisfile = os.path.realpath(binary)
+ if not os.path.exists(thisfile):
+ print("Unable to find '%s'" % thisfile)
+ sys.exit(1)
+
+ basedir = os.path.split(thisfile)[0]
+ tapset = os.path.join(basedir, "..", "share", "systemtap", "tapset")
+ return os.path.realpath(tapset)
+
+
+def cmd_run(args):
+ prefix = probe_prefix(args.binary)
+ tapsets = tapset_dir(args.binary)
+
+ if args.verbose:
+ print("Using tapset dir '%s' for binary '%s'" % (tapsets, args.binary))
+
+ probes = []
+ for probe in args.probes:
+ probes.append("probe %s.%s {}" % (prefix, probe))
+ if len(probes) == 0:
+ print("At least one probe pattern must be specified")
+ sys.exit(1)
+
+ script = " ".join(probes)
+ if args.verbose:
+ print("Compiling script '%s'" % script)
+ script = """probe begin { print("Running script, <Ctrl>-c to quit\\n") } """ + script
+
+ # We request an 8MB buffer, since the stap default 1MB buffer
+ # can be easily overflowed by frequently firing QEMU traces
+ stapargs = ["stap", "-s", "8", "-I", tapsets ]
+ if args.pid is not None:
+ stapargs.extend(["-x", args.pid])
+ stapargs.extend(["-e", script])
+ subprocess.call(stapargs)
+
+
+def cmd_list(args):
+ tapsets = tapset_dir(args.binary)
+
+ if args.verbose:
+ print("Using tapset dir '%s' for binary '%s'" % (tapsets, args.binary))
+
+ def print_probes(verbose, name):
+ prefix = probe_prefix(args.binary)
+ offset = len(prefix) + 1
+ script = prefix + "." + name
+
+ if verbose:
+ print("Listing probes with name '%s'" % script)
+ proc = subprocess.Popen(["stap", "-I", tapsets, "-l", script],
+ stdout=subprocess.PIPE,
+ universal_newlines=True)
+ out, err = proc.communicate()
+ if proc.returncode != 0:
+ print("No probes found, are the tapsets installed in %s" % tapset_dir(args.binary))
+ sys.exit(1)
+
+ for line in out.splitlines():
+ if line.startswith(prefix):
+ print("%s" % line[offset:])
+
+ if len(args.probes) == 0:
+ print_probes(args.verbose, "*")
+ else:
+ for probe in args.probes:
+ print_probes(args.verbose, probe)
+
+
+def main():
+ parser = argparse.ArgumentParser(description="QEMU SystemTap trace tool")
+ parser.add_argument("-v", "--verbose", help="Print verbose progress info",
+ action='store_true')
+
+ subparser = parser.add_subparsers(help="commands")
+ subparser.required = True
+ subparser.dest = "command"
+
+ runparser = subparser.add_parser("run", help="Run a trace session",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog="""
+
+To watch all trace points on the qemu-system-x86_64 binary:
+
+ %(argv0)s run qemu-system-x86_64
+
+To only watch the trace points matching the qio* and qcrypto* patterns
+
+ %(argv0)s run qemu-system-x86_64 'qio*' 'qcrypto*'
+""" % {"argv0": sys.argv[0]})
+ runparser.set_defaults(func=cmd_run)
+ runparser.add_argument("--pid", "-p", dest="pid",
+ help="Restrict tracing to a specific process ID")
+ runparser.add_argument("binary", help="QEMU system or user emulator binary")
+ runparser.add_argument("probes", help="Probe names or wildcards",
+ nargs=argparse.REMAINDER)
+
+ listparser = subparser.add_parser("list", help="List probe points",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog="""
+
+To list all trace points on the qemu-system-x86_64 binary:
+
+ %(argv0)s list qemu-system-x86_64
+
+To only list the trace points matching the qio* and qcrypto* patterns
+
+ %(argv0)s list qemu-system-x86_64 'qio*' 'qcrypto*'
+""" % {"argv0": sys.argv[0]})
+ listparser.set_defaults(func=cmd_list)
+ listparser.add_argument("binary", help="QEMU system or user emulator binary")
+ listparser.add_argument("probes", help="Probe names or wildcards",
+ nargs=argparse.REMAINDER)
+
+ args = parser.parse_args()
+
+ args.func(args)
+ sys.exit(0)
+
+if __name__ == '__main__':
+ main()