]> git.proxmox.com Git - ovs.git/blob - utilities/ovs-parse-backtrace.in
Require Python 3 and remove support for Python 2.
[ovs.git] / utilities / ovs-parse-backtrace.in
1 #! @PYTHON3@
2 #
3 # Copyright (c) 2012 Nicira, Inc.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at:
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 import optparse
18 import os
19 import re
20 import subprocess
21 import sys
22
23
24 addr2line_cache = {} # None if addr2line is missing or broken.
25
26
27 def addr2line(binary, addr):
28 global addr2line_cache
29
30 if addr2line_cache is None:
31 return ""
32
33 if addr in addr2line_cache:
34 return addr2line_cache[addr]
35
36 cmd = ["addr2line", "-f", "-s", "-e", binary, addr]
37 try:
38 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
39 stderr=subprocess.PIPE)
40 lines = proc.stdout.readlines()
41 failed = proc.returncode
42 except OSError:
43 failed = True
44
45 if failed:
46 addr2line_cache = None
47 return ""
48
49 lines = [l.strip() for l in lines]
50 return " ".join(lines)
51
52
53 def main():
54 parser = optparse.OptionParser(version='@VERSION@',
55 usage="usage: %prog [binary]",
56 description="""\
57 Parses the output of ovs-appctl backtrace producing a more human readable
58 result. Expected usage is for ovs-appctl backtrace to be piped in.""")
59 options, args = parser.parse_args()
60
61 if len(args) > 1:
62 parser.print_help()
63 sys.exit(1)
64
65 if len(args) == 1:
66 binary = args[0]
67 else:
68 binary = "@sbindir@/ovs-vswitchd"
69 debug = "/usr/lib/debug%s.debug" % binary
70 if os.path.exists(debug):
71 binary = debug
72
73 print "Binary: %s\n" % binary
74
75 stdin = sys.stdin.read()
76
77 traces = []
78 for trace in stdin.strip().split("\n\n"):
79 lines = trace.splitlines()
80 match = re.search(r'Count (\d+)', lines[0])
81 if match:
82 count = int(match.group(1))
83 else:
84 count = 0
85 traces.append((lines[1:], count))
86 traces = sorted(traces, key=(lambda x: x[1]), reverse=True)
87
88 for lines, count in traces:
89 longest = max(len(l) for l in lines)
90
91 print "Backtrace Count: %d" % count
92 for line in lines:
93 match = re.search(r'\[(0x.*)]', line)
94 if match:
95 print "%s %s" % (line.ljust(longest),
96 addr2line(binary, match.group(1)))
97 else:
98 print line
99 print
100
101
102 if __name__ == "__main__":
103 main()