#! @PYTHON3@ # # 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()