summaryrefslogtreecommitdiff
path: root/tools/drmemory/scripts/drmemory_analyze.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/drmemory/scripts/drmemory_analyze.py')
-rw-r--r--tools/drmemory/scripts/drmemory_analyze.py202
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())