Chromium Code Reviews| Index: tools/valgrind/test_suppressions.py |
| diff --git a/tools/valgrind/test_suppressions.py b/tools/valgrind/test_suppressions.py |
| index 75bc6b9227448fc633a8b3d0776fcba075715541..49bcfca2dbce5b49a703efee5009f04acaa9de7a 100755 |
| --- a/tools/valgrind/test_suppressions.py |
| +++ b/tools/valgrind/test_suppressions.py |
| @@ -3,9 +3,11 @@ |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| +import argparse |
| from collections import defaultdict |
| import os |
| import re |
| +import subprocess |
| import sys |
| import suppressions |
| @@ -45,6 +47,46 @@ def ReadReportsFromFile(filename): |
| # The line at the end of the file is assumed to store the URL of the report. |
| return reports,line |
| +def Demangle(names): |
| + """ Demangle a list of C++ symbols, return a list of human-readable symbols. |
| + """ |
| + 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.
|
| + args.extend(names) |
| + pipe = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
| + stdout, _ = pipe.communicate() |
| + demangled = stdout.split("\n") |
| + |
| + # Each line ends with a newline, so the final entry of the split output |
| + # will always be ''. |
| + assert len(demangled) == len(names) + 1 |
| + return demangled[:-1] |
| + |
| +def GetSymbolsFromReport(report): |
| + """Extract all symbols from a suppression report.""" |
| + symbols = [] |
| + prefix = "fun:" |
| + prefix_len = len(prefix) |
| + for line in report.splitlines(): |
| + index = line.find(prefix) |
| + if index != -1: |
| + symbols.append(line[index + prefix_len:]) |
| + return symbols |
| + |
| +def PrintTopSymbols(symbol_reports, top_count): |
| + """Print the |top_count| symbols with the most occurrences.""" |
| + boring_symbols=['malloc', '_Znw*', 'TestBody'] |
| + sorted_reports = sorted(filter(lambda x:x[0] not in boring_symbols, |
| + symbol_reports.iteritems()), |
| + key=lambda x:len(x[1]), reverse=True) |
| + symbols = symbol_reports.keys() |
| + demangled = Demangle(symbols) |
| + assert len(demangled) == len(symbols) |
| + symboltable = dict(zip(symbols, demangled)) |
| + |
| + print "\n" |
| + print "Top %d symbols" % top_count |
| + for (symbol, suppressions) in sorted_reports[:top_count]: |
| + print "%4d occurrences : %s" % (len(suppressions), symboltable[symbol]) |
| def main(argv): |
| supp = suppressions.GetSuppressions() |
| @@ -52,8 +94,17 @@ def main(argv): |
| # all_reports is a map {report: list of urls containing this report} |
| all_reports = defaultdict(list) |
| report_hashes = {} |
| + symbol_reports = defaultdict(list) |
| + |
| + # Create argument parser. |
| + parser = argparse.ArgumentParser() |
| + parser.add_argument('--top-symbols', type=int, default=0, |
| + help='Print a list of the top <n> symbols') |
| + parser.add_argument('reports', metavar='report file', nargs='+', |
| + help='List of report files') |
| + args = parser.parse_args(argv) |
| - for f in argv: |
| + for f in args.reports: |
| f_reports, url = ReadReportsFromFile(f) |
| for (hash, report) in f_reports: |
| all_reports[report] += [url] |
| @@ -95,9 +146,17 @@ def main(argv): |
| print r |
| print "===================================" |
| + if args.top_symbols > 0: |
| + symbols = GetSymbolsFromReport(r) |
| + for symbol in symbols: |
| + symbol_reports[symbol].append(report_hashes[r]) |
| + |
| if reports_count > 0: |
| print ("%d unique reports don't match any of the suppressions" % |
| reports_count) |
| + if args.top_symbols > 0: |
| + PrintTopSymbols(symbol_reports, args.top_symbols) |
| + |
| else: |
| print "Congratulations! All reports are suppressed!" |
| # TODO(timurrrr): also make sure none of the old suppressions |