]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/qemu-trace-stap
include/hw/core: Remove i386 conditional on fake_user_interrupt
[mirror_qemu.git] / scripts / qemu-trace-stap
CommitLineData
3f009716 1#!/usr/bin/env python3
62dd1048
DB
2# -*- python -*-
3#
4# Copyright (C) 2019 Red Hat, Inc
5#
6# QEMU SystemTap Trace Tool
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, see <http://www.gnu.org/licenses/>.
20
62dd1048
DB
21import argparse
22import copy
23import os.path
24import re
25import subprocess
26import sys
27
28
29def probe_prefix(binary):
30 dirname, filename = os.path.split(binary)
31 return re.sub("-", ".", filename) + ".log"
32
33
34def which(binary):
35 for path in os.environ["PATH"].split(os.pathsep):
36 if os.path.exists(os.path.join(path, binary)):
37 return os.path.join(path, binary)
38
39 print("Unable to find '%s' in $PATH" % binary)
40 sys.exit(1)
41
42
43def tapset_dir(binary):
44 dirname, filename = os.path.split(binary)
45 if dirname == '':
46 thisfile = which(binary)
47 else:
48 thisfile = os.path.realpath(binary)
49 if not os.path.exists(thisfile):
50 print("Unable to find '%s'" % thisfile)
51 sys.exit(1)
52
53 basedir = os.path.split(thisfile)[0]
54 tapset = os.path.join(basedir, "..", "share", "systemtap", "tapset")
55 return os.path.realpath(tapset)
56
57
62dd1048
DB
58def cmd_run(args):
59 prefix = probe_prefix(args.binary)
60 tapsets = tapset_dir(args.binary)
61
62 if args.verbose:
63 print("Using tapset dir '%s' for binary '%s'" % (tapsets, args.binary))
64
65 probes = []
66 for probe in args.probes:
67 probes.append("probe %s.%s {}" % (prefix, probe))
68 if len(probes) == 0:
69 print("At least one probe pattern must be specified")
70 sys.exit(1)
71
72 script = " ".join(probes)
73 if args.verbose:
74 print("Compiling script '%s'" % script)
75 script = """probe begin { print("Running script, <Ctrl>-c to quit\\n") } """ + script
76
77 # We request an 8MB buffer, since the stap default 1MB buffer
78 # can be easily overflowed by frequently firing QEMU traces
2adf2164 79 stapargs = ["stap", "-s", "8", "-I", tapsets ]
62dd1048
DB
80 if args.pid is not None:
81 stapargs.extend(["-x", args.pid])
82 stapargs.extend(["-e", script])
2adf2164 83 subprocess.call(stapargs)
62dd1048
DB
84
85
86def cmd_list(args):
87 tapsets = tapset_dir(args.binary)
88
89 if args.verbose:
90 print("Using tapset dir '%s' for binary '%s'" % (tapsets, args.binary))
91
92 def print_probes(verbose, name):
93 prefix = probe_prefix(args.binary)
94 offset = len(prefix) + 1
95 script = prefix + "." + name
96
97 if verbose:
98 print("Listing probes with name '%s'" % script)
2adf2164 99 proc = subprocess.Popen(["stap", "-I", tapsets, "-l", script],
3f009716 100 stdout=subprocess.PIPE,
2adf2164 101 universal_newlines=True)
62dd1048
DB
102 out, err = proc.communicate()
103 if proc.returncode != 0:
104 print("No probes found, are the tapsets installed in %s" % tapset_dir(args.binary))
105 sys.exit(1)
106
107 for line in out.splitlines():
108 if line.startswith(prefix):
109 print("%s" % line[offset:])
110
111 if len(args.probes) == 0:
112 print_probes(args.verbose, "*")
113 else:
114 for probe in args.probes:
115 print_probes(args.verbose, probe)
116
117
118def main():
119 parser = argparse.ArgumentParser(description="QEMU SystemTap trace tool")
120 parser.add_argument("-v", "--verbose", help="Print verbose progress info",
121 action='store_true')
122
123 subparser = parser.add_subparsers(help="commands")
124 subparser.required = True
125 subparser.dest = "command"
126
127 runparser = subparser.add_parser("run", help="Run a trace session",
128 formatter_class=argparse.RawDescriptionHelpFormatter,
129 epilog="""
130
131To watch all trace points on the qemu-system-x86_64 binary:
132
133 %(argv0)s run qemu-system-x86_64
134
135To only watch the trace points matching the qio* and qcrypto* patterns
136
137 %(argv0)s run qemu-system-x86_64 'qio*' 'qcrypto*'
138""" % {"argv0": sys.argv[0]})
139 runparser.set_defaults(func=cmd_run)
140 runparser.add_argument("--pid", "-p", dest="pid",
141 help="Restrict tracing to a specific process ID")
142 runparser.add_argument("binary", help="QEMU system or user emulator binary")
143 runparser.add_argument("probes", help="Probe names or wildcards",
144 nargs=argparse.REMAINDER)
145
146 listparser = subparser.add_parser("list", help="List probe points",
147 formatter_class=argparse.RawDescriptionHelpFormatter,
148 epilog="""
149
150To list all trace points on the qemu-system-x86_64 binary:
151
152 %(argv0)s list qemu-system-x86_64
153
154To only list the trace points matching the qio* and qcrypto* patterns
155
156 %(argv0)s list qemu-system-x86_64 'qio*' 'qcrypto*'
157""" % {"argv0": sys.argv[0]})
158 listparser.set_defaults(func=cmd_list)
159 listparser.add_argument("binary", help="QEMU system or user emulator binary")
160 listparser.add_argument("probes", help="Probe names or wildcards",
161 nargs=argparse.REMAINDER)
162
163 args = parser.parse_args()
164
165 args.func(args)
166 sys.exit(0)
167
168if __name__ == '__main__':
169 main()