nicira-ext: Fix comment on NXAST_STACK_PUSH and NXAST_STACK_POP.
[sliver-openvswitch.git] / utilities / ovs-parse-backtrace.in
1 #! @PYTHON@
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()