| Index: tools/valgrind/test_suppressions.py
|
| diff --git a/tools/valgrind/test_suppressions.py b/tools/valgrind/test_suppressions.py
|
| index 75bc6b9227448fc633a8b3d0776fcba075715541..5eeab9962e2dbcf03d1af74b345c22b29f9a5604 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']
|
| + 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
|
|
|