]> Git Repo - qemu.git/blob - scripts/qemu-trace-stap
hw/ide/atapi: Use the ldst API
[qemu.git] / scripts / qemu-trace-stap
1 #!/usr/bin/python
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
21 from __future__ import print_function
22
23 import argparse
24 import copy
25 import os.path
26 import re
27 import subprocess
28 import sys
29
30
31 def probe_prefix(binary):
32     dirname, filename = os.path.split(binary)
33     return re.sub("-", ".", filename) + ".log"
34
35
36 def which(binary):
37     for path in os.environ["PATH"].split(os.pathsep):
38         if os.path.exists(os.path.join(path, binary)):
39                 return os.path.join(path, binary)
40
41     print("Unable to find '%s' in $PATH" % binary)
42     sys.exit(1)
43
44
45 def tapset_dir(binary):
46     dirname, filename = os.path.split(binary)
47     if dirname == '':
48         thisfile = which(binary)
49     else:
50         thisfile = os.path.realpath(binary)
51         if not os.path.exists(thisfile):
52             print("Unable to find '%s'" % thisfile)
53             sys.exit(1)
54
55     basedir = os.path.split(thisfile)[0]
56     tapset = os.path.join(basedir, "..", "share", "systemtap", "tapset")
57     return os.path.realpath(tapset)
58
59
60 def tapset_env(tapset_dir):
61     tenv = copy.copy(os.environ)
62     tenv["SYSTEMTAP_TAPSET"] = tapset_dir
63     return tenv
64
65 def cmd_run(args):
66     prefix = probe_prefix(args.binary)
67     tapsets = tapset_dir(args.binary)
68
69     if args.verbose:
70         print("Using tapset dir '%s' for binary '%s'" % (tapsets, args.binary))
71
72     probes = []
73     for probe in args.probes:
74         probes.append("probe %s.%s {}" % (prefix, probe))
75     if len(probes) == 0:
76         print("At least one probe pattern must be specified")
77         sys.exit(1)
78
79     script = " ".join(probes)
80     if args.verbose:
81         print("Compiling script '%s'" % script)
82         script = """probe begin { print("Running script, <Ctrl>-c to quit\\n") } """ + script
83
84     # We request an 8MB buffer, since the stap default 1MB buffer
85     # can be easily overflowed by frequently firing QEMU traces
86     stapargs = ["stap", "-s", "8"]
87     if args.pid is not None:
88         stapargs.extend(["-x", args.pid])
89     stapargs.extend(["-e", script])
90     subprocess.call(stapargs, env=tapset_env(tapsets))
91
92
93 def cmd_list(args):
94     tapsets = tapset_dir(args.binary)
95
96     if args.verbose:
97         print("Using tapset dir '%s' for binary '%s'" % (tapsets, args.binary))
98
99     def print_probes(verbose, name):
100         prefix = probe_prefix(args.binary)
101         offset = len(prefix) + 1
102         script = prefix + "." + name
103
104         if verbose:
105             print("Listing probes with name '%s'" % script)
106         proc = subprocess.Popen(["stap", "-l", script],
107                                 stdout=subprocess.PIPE, env=tapset_env(tapsets))
108         out, err = proc.communicate()
109         if proc.returncode != 0:
110             print("No probes found, are the tapsets installed in %s" % tapset_dir(args.binary))
111             sys.exit(1)
112
113         for line in out.splitlines():
114             if line.startswith(prefix):
115                 print("%s" % line[offset:])
116
117     if len(args.probes) == 0:
118         print_probes(args.verbose, "*")
119     else:
120         for probe in args.probes:
121             print_probes(args.verbose, probe)
122
123
124 def main():
125     parser = argparse.ArgumentParser(description="QEMU SystemTap trace tool")
126     parser.add_argument("-v", "--verbose", help="Print verbose progress info",
127                         action='store_true')
128
129     subparser = parser.add_subparsers(help="commands")
130     subparser.required = True
131     subparser.dest = "command"
132
133     runparser = subparser.add_parser("run", help="Run a trace session",
134                                      formatter_class=argparse.RawDescriptionHelpFormatter,
135                                      epilog="""
136
137 To watch all trace points on the qemu-system-x86_64 binary:
138
139    %(argv0)s run qemu-system-x86_64
140
141 To only watch the trace points matching the qio* and qcrypto* patterns
142
143    %(argv0)s run qemu-system-x86_64 'qio*' 'qcrypto*'
144 """ % {"argv0": sys.argv[0]})
145     runparser.set_defaults(func=cmd_run)
146     runparser.add_argument("--pid", "-p", dest="pid",
147                            help="Restrict tracing to a specific process ID")
148     runparser.add_argument("binary", help="QEMU system or user emulator binary")
149     runparser.add_argument("probes", help="Probe names or wildcards",
150                            nargs=argparse.REMAINDER)
151
152     listparser = subparser.add_parser("list", help="List probe points",
153                                       formatter_class=argparse.RawDescriptionHelpFormatter,
154                                       epilog="""
155
156 To list all trace points on the qemu-system-x86_64 binary:
157
158    %(argv0)s list qemu-system-x86_64
159
160 To only list the trace points matching the qio* and qcrypto* patterns
161
162    %(argv0)s list qemu-system-x86_64 'qio*' 'qcrypto*'
163 """ % {"argv0": sys.argv[0]})
164     listparser.set_defaults(func=cmd_list)
165     listparser.add_argument("binary", help="QEMU system or user emulator binary")
166     listparser.add_argument("probes", help="Probe names or wildcards",
167                             nargs=argparse.REMAINDER)
168
169     args = parser.parse_args()
170
171     args.func(args)
172     sys.exit(0)
173
174 if __name__ == '__main__':
175     main()
This page took 0.03317 seconds and 4 git commands to generate.