Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import argparse | |
| 6 from collections import defaultdict | 7 from collections import defaultdict |
| 7 import os | 8 import os |
| 8 import re | 9 import re |
| 10 import subprocess | |
| 9 import sys | 11 import sys |
| 10 | 12 |
| 11 import suppressions | 13 import suppressions |
| 12 | 14 |
| 13 | 15 |
| 14 def ReadReportsFromFile(filename): | 16 def ReadReportsFromFile(filename): |
| 15 """ Returns a list of (report_hash, report) and the URL of the report on the | 17 """ Returns a list of (report_hash, report) and the URL of the report on the |
| 16 waterfall. | 18 waterfall. |
| 17 """ | 19 """ |
| 18 input_file = file(filename, 'r') | 20 input_file = file(filename, 'r') |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 38 else: | 40 else: |
| 39 cur_supp += [" "*3 + line] | 41 cur_supp += [" "*3 + line] |
| 40 elif line == "{": | 42 elif line == "{": |
| 41 in_suppression = True | 43 in_suppression = True |
| 42 cur_supp = ["{"] | 44 cur_supp = ["{"] |
| 43 elif line.find("Suppression (error hash=#") == 0: | 45 elif line.find("Suppression (error hash=#") == 0: |
| 44 last_hash = line[25:41] | 46 last_hash = line[25:41] |
| 45 # The line at the end of the file is assumed to store the URL of the report. | 47 # The line at the end of the file is assumed to store the URL of the report. |
| 46 return reports,line | 48 return reports,line |
| 47 | 49 |
| 50 def Demangle(names): | |
| 51 """ Demangle a list of C++ symbols, return a list of human-readable symbols. | |
| 52 """ | |
| 53 args = ['c++filt','-n'] | |
|
Lei Zhang
2013/05/07 21:02:04
more spaces after commas
groby-ooo-7-16
2013/05/07 21:43:34
Done.
| |
| 54 args.extend(names) | |
| 55 pipe = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) | |
| 56 stdout, _ = pipe.communicate() | |
| 57 demangled = stdout.split("\n") | |
| 58 | |
| 59 # Each line ends with a newline, so the final entry of the split output | |
| 60 # will always be ''. | |
| 61 assert len(demangled) == len(names) + 1 | |
| 62 return demangled[:-1] | |
| 63 | |
| 64 def GetSymbolsFromReport(report): | |
| 65 """Extract all symbols from a suppression report.""" | |
| 66 symbols = [] | |
| 67 prefix = "fun:" | |
| 68 prefix_len = len(prefix) | |
| 69 for line in report.splitlines(): | |
| 70 index = line.find(prefix) | |
| 71 if index != -1: | |
| 72 symbols.append(line[index + prefix_len:]) | |
| 73 return symbols | |
| 74 | |
| 75 def PrintTopSymbols(symbol_reports, top_count): | |
| 76 """Print the |top_count| symbols with the most occurrences.""" | |
| 77 boring_symbols=['malloc', '_Znw*', 'TestBody'] | |
| 78 sorted_reports = sorted(filter(lambda x:x[0] not in boring_symbols, | |
| 79 symbol_reports.iteritems()), | |
| 80 key=lambda x:len(x[1]), reverse=True) | |
| 81 symbols = symbol_reports.keys() | |
| 82 demangled = Demangle(symbols) | |
| 83 assert len(demangled) == len(symbols) | |
| 84 symboltable = dict(zip(symbols, demangled)) | |
| 85 | |
| 86 print "\n" | |
| 87 print "Top %d symbols" % top_count | |
| 88 for (symbol, suppressions) in sorted_reports[:top_count]: | |
| 89 print "%4d occurrences : %s" % (len(suppressions), symboltable[symbol]) | |
| 48 | 90 |
| 49 def main(argv): | 91 def main(argv): |
| 50 supp = suppressions.GetSuppressions() | 92 supp = suppressions.GetSuppressions() |
| 51 | 93 |
| 52 # all_reports is a map {report: list of urls containing this report} | 94 # all_reports is a map {report: list of urls containing this report} |
| 53 all_reports = defaultdict(list) | 95 all_reports = defaultdict(list) |
| 54 report_hashes = {} | 96 report_hashes = {} |
| 97 symbol_reports = defaultdict(list) | |
| 55 | 98 |
| 56 for f in argv: | 99 # Create argument parser. |
| 100 parser = argparse.ArgumentParser() | |
| 101 parser.add_argument('--top-symbols', type=int, default=0, | |
| 102 help='Print a list of the top <n> symbols') | |
| 103 parser.add_argument('reports', metavar='report file', nargs='+', | |
| 104 help='List of report files') | |
| 105 args = parser.parse_args(argv) | |
| 106 | |
| 107 for f in args.reports: | |
| 57 f_reports, url = ReadReportsFromFile(f) | 108 f_reports, url = ReadReportsFromFile(f) |
| 58 for (hash, report) in f_reports: | 109 for (hash, report) in f_reports: |
| 59 all_reports[report] += [url] | 110 all_reports[report] += [url] |
| 60 report_hashes[report] = hash | 111 report_hashes[report] = hash |
| 61 | 112 |
| 62 reports_count = 0 | 113 reports_count = 0 |
| 63 for r in all_reports: | 114 for r in all_reports: |
| 64 cur_supp = supp['common_suppressions'] | 115 cur_supp = supp['common_suppressions'] |
| 65 if all([re.search("%20Mac%20|mac_valgrind", url) | 116 if all([re.search("%20Mac%20|mac_valgrind", url) |
| 66 for url in all_reports[r]]): | 117 for url in all_reports[r]]): |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 88 reports_count += 1 | 139 reports_count += 1 |
| 89 print "===================================" | 140 print "===================================" |
| 90 print "This report observed at" | 141 print "This report observed at" |
| 91 for url in all_reports[r]: | 142 for url in all_reports[r]: |
| 92 print " %s" % url | 143 print " %s" % url |
| 93 print "didn't match any suppressions:" | 144 print "didn't match any suppressions:" |
| 94 print "Suppression (error hash=#%s#):" % (report_hashes[r]) | 145 print "Suppression (error hash=#%s#):" % (report_hashes[r]) |
| 95 print r | 146 print r |
| 96 print "===================================" | 147 print "===================================" |
| 97 | 148 |
| 149 if args.top_symbols > 0: | |
| 150 symbols = GetSymbolsFromReport(r) | |
| 151 for symbol in symbols: | |
| 152 symbol_reports[symbol].append(report_hashes[r]) | |
| 153 | |
| 98 if reports_count > 0: | 154 if reports_count > 0: |
| 99 print ("%d unique reports don't match any of the suppressions" % | 155 print ("%d unique reports don't match any of the suppressions" % |
| 100 reports_count) | 156 reports_count) |
| 157 if args.top_symbols > 0: | |
| 158 PrintTopSymbols(symbol_reports, args.top_symbols) | |
| 159 | |
| 101 else: | 160 else: |
| 102 print "Congratulations! All reports are suppressed!" | 161 print "Congratulations! All reports are suppressed!" |
| 103 # TODO(timurrrr): also make sure none of the old suppressions | 162 # TODO(timurrrr): also make sure none of the old suppressions |
| 104 # were narrowed too much. | 163 # were narrowed too much. |
| 105 | 164 |
| 106 | 165 |
| 107 if __name__ == "__main__": | 166 if __name__ == "__main__": |
| 108 main(sys.argv[1:]) | 167 main(sys.argv[1:]) |
| OLD | NEW |