diff options
Diffstat (limited to 'tools/drmemory/scripts/drmemory_analyze.py')
-rw-r--r-- | tools/drmemory/scripts/drmemory_analyze.py | 202 |
1 files changed, 0 insertions, 202 deletions
diff --git a/tools/drmemory/scripts/drmemory_analyze.py b/tools/drmemory/scripts/drmemory_analyze.py deleted file mode 100644 index 29fc0ed4b0..0000000000 --- a/tools/drmemory/scripts/drmemory_analyze.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# drmemory_analyze.py - -''' Given a Dr. Memory output file, parses errors and uniques them.''' - -from collections import defaultdict -import common -import hashlib -import logging -import optparse -import os -import re -import subprocess -import sys -import time - -class DrMemoryError: - def __init__(self, report, suppression, testcase): - self._report = report - self._testcase = testcase - - # Chromium-specific transformations of the suppressions: - # Replace 'any_test.exe' and 'chrome.dll' with '*', then remove the - # Dr.Memory-generated error ids from the name= lines as they don't - # make sense in a multiprocess report. - supp_lines = suppression.split("\n") - for l in xrange(len(supp_lines)): - if supp_lines[l].startswith("name="): - supp_lines[l] = "name=<insert_a_suppression_name_here>" - if supp_lines[l].startswith("chrome.dll!"): - supp_lines[l] = supp_lines[l].replace("chrome.dll!", "*!") - bang_index = supp_lines[l].find("!") - d_exe_index = supp_lines[l].find(".exe!") - if bang_index >= 4 and d_exe_index + 4 == bang_index: - supp_lines[l] = "*" + supp_lines[l][bang_index:] - self._suppression = "\n".join(supp_lines) - - def __str__(self): - output = "" - output += "### BEGIN MEMORY TOOL REPORT (error hash=#%016X#)\n" % \ - self.ErrorHash() - output += self._report + "\n" - if self._testcase: - output += "The report came from the `%s` test.\n" % self._testcase - output += "Suppression (error hash=#%016X#):\n" % self.ErrorHash() - output += (" For more info on using suppressions see " - "http://dev.chromium.org/developers/how-tos/using-drmemory#TOC-Suppressing-error-reports-from-the-\n") - output += "{\n%s\n}\n" % self._suppression - output += "### END MEMORY TOOL REPORT (error hash=#%016X#)\n" % \ - self.ErrorHash() - return output - - # This is a device-independent hash identifying the suppression. - # By printing out this hash we can find duplicate reports between tests and - # different shards running on multiple buildbots - def ErrorHash(self): - return int(hashlib.md5(self._suppression).hexdigest()[:16], 16) - - def __hash__(self): - return hash(self._suppression) - - def __eq__(self, rhs): - return self._suppression == rhs - - -class DrMemoryAnalyzer: - ''' Given a set of Dr.Memory output files, parse all the errors out of - them, unique them and output the results.''' - - def __init__(self): - self.known_errors = set() - self.error_count = 0; - - def ReadLine(self): - self.line_ = self.cur_fd_.readline() - - def ReadSection(self): - result = [self.line_] - self.ReadLine() - while len(self.line_.strip()) > 0: - result.append(self.line_) - self.ReadLine() - return result - - def ParseReportFile(self, filename, testcase): - ret = [] - - # First, read the generated suppressions file so we can easily lookup a - # suppression for a given error. - supp_fd = open(filename.replace("results", "suppress"), 'r') - generated_suppressions = {} # Key -> Error #, Value -> Suppression text. - for line in supp_fd: - # NOTE: this regexp looks fragile. Might break if the generated - # suppression format slightly changes. - m = re.search("# Suppression for Error #([0-9]+)", line.strip()) - if not m: - continue - error_id = int(m.groups()[0]) - assert error_id not in generated_suppressions - # OK, now read the next suppression: - cur_supp = "" - for supp_line in supp_fd: - if supp_line.startswith("#") or supp_line.strip() == "": - break - cur_supp += supp_line - generated_suppressions[error_id] = cur_supp.strip() - supp_fd.close() - - self.cur_fd_ = open(filename, 'r') - while True: - self.ReadLine() - if (self.line_ == ''): break - - match = re.search("^Error #([0-9]+): (.*)", self.line_) - if match: - error_id = int(match.groups()[0]) - self.line_ = match.groups()[1].strip() + "\n" - report = "".join(self.ReadSection()).strip() - suppression = generated_suppressions[error_id] - ret.append(DrMemoryError(report, suppression, testcase)) - - if re.search("SUPPRESSIONS USED:", self.line_): - self.ReadLine() - while self.line_.strip() != "": - line = self.line_.strip() - (count, name) = re.match(" *([0-9\?]+)x(?: \(.*?\))?: (.*)", - line).groups() - if (count == "?"): - # Whole-module have no count available: assume 1 - count = 1 - else: - count = int(count) - self.used_suppressions[name] += count - self.ReadLine() - - if self.line_.startswith("ASSERT FAILURE"): - ret.append(self.line_.strip()) - - self.cur_fd_.close() - return ret - - def Report(self, filenames, testcase, check_sanity): - sys.stdout.flush() - # TODO(timurrrr): support positive tests / check_sanity==True - self.used_suppressions = defaultdict(int) - - to_report = [] - reports_for_this_test = set() - for f in filenames: - cur_reports = self.ParseReportFile(f, testcase) - - # Filter out the reports that were there in previous tests. - for r in cur_reports: - if r in reports_for_this_test: - # A similar report is about to be printed for this test. - pass - elif r in self.known_errors: - # A similar report has already been printed in one of the prev tests. - to_report.append("This error was already printed in some " - "other test, see 'hash=#%016X#'" % r.ErrorHash()) - reports_for_this_test.add(r) - else: - self.known_errors.add(r) - reports_for_this_test.add(r) - to_report.append(r) - - common.PrintUsedSuppressionsList(self.used_suppressions) - - if not to_report: - logging.info("PASS: No error reports found") - return 0 - - sys.stdout.flush() - sys.stderr.flush() - logging.info("Found %i error reports" % len(to_report)) - for report in to_report: - self.error_count += 1 - logging.info("Report #%d\n%s" % (self.error_count, report)) - logging.info("Total: %i error reports" % len(to_report)) - sys.stdout.flush() - return -1 - - -def main(): - '''For testing only. The DrMemoryAnalyze class should be imported instead.''' - parser = optparse.OptionParser("usage: %prog <files to analyze>") - - (options, args) = parser.parse_args() - if len(args) == 0: - parser.error("no filename specified") - filenames = args - - logging.getLogger().setLevel(logging.INFO) - return DrMemoryAnalyzer().Report(filenames, None, False) - - -if __name__ == '__main__': - sys.exit(main()) |