104 lines
2.8 KiB
Plaintext
Executable File
104 lines
2.8 KiB
Plaintext
Executable File
#! @PYTHON@
|
|
#
|
|
# Copyright (c) 2012 Nicira, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at:
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import optparse
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
addr2line_cache = {} # None if addr2line is missing or broken.
|
|
|
|
|
|
def addr2line(binary, addr):
|
|
global addr2line_cache
|
|
|
|
if addr2line_cache is None:
|
|
return ""
|
|
|
|
if addr in addr2line_cache:
|
|
return addr2line_cache[addr]
|
|
|
|
cmd = ["addr2line", "-f", "-s", "-e", binary, addr]
|
|
try:
|
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE)
|
|
lines = proc.stdout.readlines()
|
|
failed = proc.returncode
|
|
except OSError:
|
|
failed = True
|
|
|
|
if failed:
|
|
addr2line_cache = None
|
|
return ""
|
|
|
|
lines = [l.strip() for l in lines]
|
|
return " ".join(lines)
|
|
|
|
|
|
def main():
|
|
parser = optparse.OptionParser(version='@VERSION@',
|
|
usage="usage: %prog [binary]",
|
|
description="""\
|
|
Parses the output of ovs-appctl backtrace producing a more human readable
|
|
result. Expected usage is for ovs-appctl backtrace to be piped in.""")
|
|
options, args = parser.parse_args()
|
|
|
|
if len(args) > 1:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
if len(args) == 1:
|
|
binary = args[0]
|
|
else:
|
|
binary = "@sbindir@/ovs-vswitchd"
|
|
debug = "/usr/lib/debug%s.debug" % binary
|
|
if os.path.exists(debug):
|
|
binary = debug
|
|
|
|
print "Binary: %s\n" % binary
|
|
|
|
stdin = sys.stdin.read()
|
|
|
|
traces = []
|
|
for trace in stdin.strip().split("\n\n"):
|
|
lines = trace.splitlines()
|
|
match = re.search(r'Count (\d+)', lines[0])
|
|
if match:
|
|
count = int(match.group(1))
|
|
else:
|
|
count = 0
|
|
traces.append((lines[1:], count))
|
|
traces = sorted(traces, key=(lambda x: x[1]), reverse=True)
|
|
|
|
for lines, count in traces:
|
|
longest = max(len(l) for l in lines)
|
|
|
|
print "Backtrace Count: %d" % count
|
|
for line in lines:
|
|
match = re.search(r'\[(0x.*)]', line)
|
|
if match:
|
|
print "%s %s" % (line.ljust(longest),
|
|
addr2line(binary, match.group(1)))
|
|
else:
|
|
print line
|
|
print
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|