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 | |
|
Lei Zhang
2013/05/07 20:39:56
Is everyone running an OS on their desktop with Py
groby-ooo-7-16
2013/05/07 20:57:59
Seems to be the case.
On 2013/05/07 20:39:56, Lei
| |
| 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'] | |
| 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 | |
|
Lei Zhang
2013/05/07 20:39:56
style nit: spaces around +
groby-ooo-7-16
2013/05/07 20:57:59
Done.
| |
| 62 return demangled[:-1] | |
| 63 | |
| 64 def GetSymbolsFromReport(report): | |
| 65 """Extract all symbols from a suppression report.""" | |
| 66 symbols = [] | |
| 67 for line in report.splitlines(): | |
| 68 index = line.find('fun:') | |
| 69 if index != -1: | |
| 70 symbols.append(line[index+4:]) | |
|
Lei Zhang
2013/05/07 20:39:56
index + len('fun:'), or have some constant that in
groby-ooo-7-16
2013/05/07 20:57:59
Done.
| |
| 71 return symbols | |
| 72 | |
| 73 def PrintTopSymbols(symbol_reports, top_count): | |
| 74 """Print the |top_count| symbols with the most occurrences.""" | |
| 75 boring_symbols=['malloc', '_Znw*', 'TestBody'] | |
|
Lei Zhang
2013/05/07 20:39:56
Use BoringCallers() in common.py?
groby-ooo-7-16
2013/05/07 20:57:59
BoringCallers ignores different boringness. Per of
| |
| 76 sorted_reports = sorted(filter(lambda x:x[0] not in boring_symbols, | |
| 77 symbol_reports.iteritems()), | |
| 78 key=lambda x:len(x[1]), reverse=True) | |
| 79 symbols = symbol_reports.keys() | |
| 80 demangled = Demangle(symbols) | |
| 81 assert len(demangled) == len(symbols) | |
| 82 symboltable = dict(zip(symbols,demangled)) | |
|
Lei Zhang
2013/05/07 20:39:56
style nit: space after comma.
groby-ooo-7-16
2013/05/07 20:57:59
Done.
| |
| 83 | |
| 84 print "\n" | |
| 85 print "Top %d symbols" % top_count | |
| 86 for (symbol, suppressions) in sorted_reports[:top_count]: | |
| 87 print "%4d occurrences : %s" % (len(suppressions), symboltable[symbol]) | |
| 48 | 88 |
| 49 def main(argv): | 89 def main(argv): |
| 50 supp = suppressions.GetSuppressions() | 90 supp = suppressions.GetSuppressions() |
| 51 | 91 |
| 52 # all_reports is a map {report: list of urls containing this report} | 92 # all_reports is a map {report: list of urls containing this report} |
| 53 all_reports = defaultdict(list) | 93 all_reports = defaultdict(list) |
| 54 report_hashes = {} | 94 report_hashes = {} |
| 95 symbol_reports = defaultdict(list) | |
| 55 | 96 |
| 56 for f in argv: | 97 # Create argument parser. |
| 98 parser = argparse.ArgumentParser() | |
| 99 parser.add_argument('--top-symbols', type=int, default=0, | |
| 100 help='Print a list of the top <n> symbols') | |
| 101 parser.add_argument('reports', metavar='report file', nargs='+', | |
| 102 help='List of report files') | |
| 103 args = parser.parse_args(argv) | |
| 104 | |
| 105 for f in args.reports: | |
| 57 f_reports, url = ReadReportsFromFile(f) | 106 f_reports, url = ReadReportsFromFile(f) |
| 58 for (hash, report) in f_reports: | 107 for (hash, report) in f_reports: |
| 59 all_reports[report] += [url] | 108 all_reports[report] += [url] |
| 60 report_hashes[report] = hash | 109 report_hashes[report] = hash |
| 61 | 110 |
| 62 reports_count = 0 | 111 reports_count = 0 |
| 63 for r in all_reports: | 112 for r in all_reports: |
| 64 cur_supp = supp['common_suppressions'] | 113 cur_supp = supp['common_suppressions'] |
| 65 if all([re.search("%20Mac%20|mac_valgrind", url) | 114 if all([re.search("%20Mac%20|mac_valgrind", url) |
| 66 for url in all_reports[r]]): | 115 for url in all_reports[r]]): |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 88 reports_count += 1 | 137 reports_count += 1 |
| 89 print "===================================" | 138 print "===================================" |
| 90 print "This report observed at" | 139 print "This report observed at" |
| 91 for url in all_reports[r]: | 140 for url in all_reports[r]: |
| 92 print " %s" % url | 141 print " %s" % url |
| 93 print "didn't match any suppressions:" | 142 print "didn't match any suppressions:" |
| 94 print "Suppression (error hash=#%s#):" % (report_hashes[r]) | 143 print "Suppression (error hash=#%s#):" % (report_hashes[r]) |
| 95 print r | 144 print r |
| 96 print "===================================" | 145 print "===================================" |
| 97 | 146 |
| 147 if args.top_symbols > 0: | |
| 148 symbols = GetSymbolsFromReport(r) | |
| 149 for symbol in symbols: | |
| 150 symbol_reports[symbol].append(report_hashes[r]) | |
| 151 | |
| 98 if reports_count > 0: | 152 if reports_count > 0: |
| 99 print ("%d unique reports don't match any of the suppressions" % | 153 print ("%d unique reports don't match any of the suppressions" % |
| 100 reports_count) | 154 reports_count) |
| 155 if args.top_symbols > 0: | |
| 156 PrintTopSymbols(symbol_reports, args.top_symbols) | |
| 157 | |
| 101 else: | 158 else: |
| 102 print "Congratulations! All reports are suppressed!" | 159 print "Congratulations! All reports are suppressed!" |
| 103 # TODO(timurrrr): also make sure none of the old suppressions | 160 # TODO(timurrrr): also make sure none of the old suppressions |
| 104 # were narrowed too much. | 161 # were narrowed too much. |
| 105 | 162 |
| 106 | 163 |
| 107 if __name__ == "__main__": | 164 if __name__ == "__main__": |
| 108 main(sys.argv[1:]) | 165 main(sys.argv[1:]) |
| OLD | NEW |