15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Runs an exe through Valgrind and puts the intermediate files in a 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)directory. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import datetime 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import glob 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import shutil 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import stat 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import common 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import drmemory_analyze 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import memcheck_analyze 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tsan_analyze 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseTool(object): 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Abstract class for running Valgrind-, PIN-based and other dynamic 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error detector tools. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Always subclass this and implement ToolCommand with framework- and 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool-specific stuff. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_parent_dir = None 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.log_parent_dir = "" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsWindows(): 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # gpu process on Windows Vista+ runs at Low Integrity and can only 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # write to certain directories (http://crbug.com/119131) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(bruening): if scripts die in middle and don't clean up temp 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # dir, we'll accumulate files in profile dir. should remove 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # really old files automatically. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile = os.getenv("USERPROFILE") 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if profile: 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.log_parent_dir = profile + "\\AppData\\LocalLow\\" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(self.log_parent_dir): 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.log_parent_dir = common.NormalizeWindowsPath(self.log_parent_dir) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_parent_dir = self.log_parent_dir 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Generated every time (even when overridden) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.temp_dir = tempfile.mkdtemp(prefix="vg_logs_", dir=temp_parent_dir) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.log_dir = self.temp_dir # overridable by --keep_logs 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.option_parser_hooks = [] 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(glider): we may not need some of the env vars on some of the 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # platforms. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._env = { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "G_SLICE" : "always-malloc", 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NSS_DISABLE_UNLOAD" : "1", 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NSS_DISABLE_ARENA_FREE_LIST" : "1", 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "GTEST_DEATH_TEST_USE_FORK": "1", 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolName(self): 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError, "This method should be implemented " \ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in the tool-specific subclass" 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Analyze(self, check_sanity=False): 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError, "This method should be implemented " \ 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in the tool-specific subclass" 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def RegisterOptionParserHook(self, hook): 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Frameworks and tools can add their own flags to the parser. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.option_parser_hooks.append(hook) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateOptionParser(self): 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Defines Chromium-specific flags. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser = optparse.OptionParser("usage: %prog [options] <program to " 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "test>") 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.disable_interspersed_args() 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.add_option("-t", "--timeout", 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest="timeout", metavar="TIMEOUT", default=10000, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="timeout in seconds for the run (default 10000)") 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) self._parser.add_option("", "--build-dir", 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="the location of the compiler output") 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) self._parser.add_option("", "--source-dir", 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="path to top of source tree for this build" 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(used to normalize source paths in baseline)") 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.add_option("", "--gtest_filter", default="", 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="which test case to run") 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.add_option("", "--gtest_repeat", 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="how many times to run each test") 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.add_option("", "--gtest_print_time", action="store_true", 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="show how long each test takes") 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.add_option("", "--ignore_exit_code", action="store_true", 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="ignore exit code of the test " 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(e.g. test failures)") 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._parser.add_option("", "--keep_logs", action="store_true", 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="store memory tool logs in the <tool>.logs " 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "directory instead of /tmp.\nThis can be " 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "useful for tool developers/maintainers.\n" 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Please note that the <tool>.logs directory " 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "will be clobbered on tool startup.") 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # To add framework- or tool-specific flags, please add a hook using 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # RegisterOptionParserHook in the corresponding subclass. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # See ValgrindTool and ThreadSanitizerBase for examples. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for hook in self.option_parser_hooks: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hook(self, self._parser) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ParseArgv(self, args): 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.CreateOptionParser() 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # self._tool_flags will store those tool flags which we don't parse 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # manually in this script. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._tool_flags = [] 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) known_args = [] 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ We assume that the first argument not starting with "-" is a program 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name and all the following flags should be passed to the program. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TODO(timurrrr): customize optparse instead 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while len(args) > 0 and args[0][:1] == "-": 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arg = args[0] 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (arg == "--"): 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._parser.has_option(arg.split("=")[0]): 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) known_args += [arg] 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._tool_flags += [arg] 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args = args[1:] 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(args) > 0: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) known_args += args 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._options, self._args = self._parser.parse_args(known_args) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._timeout = int(self._options.timeout) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._source_dir = self._options.source_dir 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.keep_logs: 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # log_parent_dir has trailing slash if non-empty 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.log_dir = self.log_parent_dir + "%s.logs" % self.ToolName() 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(self.log_dir): 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutil.rmtree(self.log_dir) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.mkdir(self.log_dir) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Logs are in " + self.log_dir) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._ignore_exit_code = self._options.ignore_exit_code 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.gtest_filter != "": 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._args.append("--gtest_filter=%s" % self._options.gtest_filter) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.gtest_repeat: 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._args.append("--gtest_repeat=%s" % self._options.gtest_repeat) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.gtest_print_time: 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._args.append("--gtest_print_time") 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Setup(self, args): 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.ParseArgv(args) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolCommand(self): 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError, "This method should be implemented " \ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in the tool-specific subclass" 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Cleanup(self): 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # You may override it in the tool-specific subclass 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Execute(self): 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ Execute the app to be tested after successful instrumentation. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Full execution command-line provided by subclassers via proc.""" 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("starting execution...") 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = self.ToolCommand() 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for var in self._env: 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) common.PutEnvAndLog(var, self._env[var]) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return common.RunSubprocess(proc, self._timeout) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def RunTestsAndAnalyze(self, check_sanity): 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exec_retcode = self.Execute() 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) analyze_retcode = self.Analyze(check_sanity) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if analyze_retcode: 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("Analyze failed.") 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Search the log for '[ERROR]' to see the error reports.") 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return analyze_retcode 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if exec_retcode: 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._ignore_exit_code: 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Test execution failed, but the exit code is ignored.") 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("Test execution failed.") 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return exec_retcode 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Test execution completed successfully.") 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not analyze_retcode: 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Analysis completed successfully.") 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Main(self, args, check_sanity, min_runtime_in_seconds): 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Call this to run through the whole process: Setup, Execute, Analyze""" 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time = datetime.datetime.now() 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = -1 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.Setup(args): 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = self.RunTestsAndAnalyze(check_sanity) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutil.rmtree(self.temp_dir, ignore_errors=True) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.Cleanup() 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("Setup failed") 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_time = datetime.datetime.now() 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runtime_in_seconds = (end_time - start_time).seconds 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hours = runtime_in_seconds / 3600 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seconds = runtime_in_seconds % 3600 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minutes = seconds / 60 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) seconds = seconds % 60 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("elapsed time: %02d:%02d:%02d" % (hours, minutes, seconds)) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (min_runtime_in_seconds > 0 and 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runtime_in_seconds < min_runtime_in_seconds): 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("Layout tests finished too quickly. " 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "It should have taken at least %d seconds. " 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Something went wrong?" % min_runtime_in_seconds) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = -1 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retcode 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Run(self, args, module, min_runtime_in_seconds=0): 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MODULES_TO_SANITY_CHECK = ["base"] 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): this is a temporary workaround for http://crbug.com/47844 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.ToolName() == "tsan" and common.IsMac(): 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MODULES_TO_SANITY_CHECK = [] 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check_sanity = module in MODULES_TO_SANITY_CHECK 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.Main(args, check_sanity, min_runtime_in_seconds) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ValgrindTool(BaseTool): 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Abstract class for running Valgrind tools. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Always subclass this and implement ToolSpecificFlags() and 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtendOptionParser() for tool-specific stuff. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ValgrindTool, self).__init__() 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(ValgrindTool.ExtendOptionParser) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def UseXML(self): 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Override if tool prefers nonxml output 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def SelfContained(self): 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Returns true iff the tool is distibuted as a self-contained 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # .sh script (e.g. ThreadSanitizer) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--suppressions", default=[], 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action="append", 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="path to a valgrind suppression file") 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--indirect", action="store_true", 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="set BROWSER_WRAPPER rather than " 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "running valgrind directly") 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--indirect_webkit_layout", action="store_true", 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) help="set --wrapper rather than running Dr. Memory " 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "directly.") 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--trace_children", action="store_true", 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="also trace child processes") 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--num-callers", 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest="num_callers", default=30, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="number of callers to show in stack traces") 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--generate_dsym", action="store_true", 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Generate .dSYM file on Mac if needed. Slow!") 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Setup(self, args): 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not BaseTool.Setup(self, args): 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsMac(): 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.PrepareForTestMac() 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def PrepareForTestMac(self): 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Runs dsymutil if needed. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Valgrind for Mac OS X requires that debugging information be in a .dSYM 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bundle generated by dsymutil. It is not currently able to chase DWARF 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data into .o files like gdb does, so executables without .dSYM bundles or 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with the Chromium-specific "fake_dsym" bundles generated by 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) build/mac/strip_save_dsym won't give source file and line number 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) information in valgrind. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) This function will run dsymutil if the .dSYM bundle is missing or if 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it looks like a fake_dsym. A non-fake dsym that already exists is assumed 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to be up-to-date. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_command = self._args[0] 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dsym_bundle = self._args[0] + '.dSYM' 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dsym_file = os.path.join(dsym_bundle, 'Contents', 'Resources', 'DWARF', 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.path.basename(test_command)) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dsym_info_plist = os.path.join(dsym_bundle, 'Contents', 'Info.plist') 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_dsymutil = True 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saved_test_command = None 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(dsym_file) and os.path.exists(dsym_info_plist): 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Look for the special fake_dsym tag in dsym_info_plist. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dsym_info_plist_contents = open(dsym_info_plist).read() 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not re.search('^\s*<key>fake_dsym</key>$', dsym_info_plist_contents, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re.MULTILINE): 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # fake_dsym is not set, this is a real .dSYM bundle produced by 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # dsymutil. dsymutil does not need to be run again. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_dsymutil = False 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # fake_dsym is set. dsym_file is a copy of the original test_command 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # before it was stripped. Copy it back to test_command so that 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # dsymutil has unstripped input to work with. Move the stripped 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # test_command out of the way, it will be restored when this is 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # done. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saved_test_command = test_command + '.stripped' 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.rename(test_command, saved_test_command) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutil.copyfile(dsym_file, test_command) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutil.copymode(saved_test_command, test_command) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if needs_dsymutil: 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.generate_dsym: 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Remove the .dSYM bundle if it exists. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutil.rmtree(dsym_bundle, True) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dsymutil_command = ['dsymutil', test_command] 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # dsymutil is crazy slow. Ideally we'd have a timeout here, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # but common.RunSubprocess' timeout is only checked 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # after each line of output; dsymutil is silent 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # until the end, and is then killed, which is silly. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) common.RunSubprocess(dsymutil_command) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if saved_test_command: 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.rename(saved_test_command, test_command) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("No real .dSYM for test_command. Line numbers will " 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "not be shown. Either tell xcode to generate .dSYM " 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "file, or use --generate_dsym option to this tool.") 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolCommand(self): 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Get the valgrind command to run.""" 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Note that self._args begins with the exe to be run. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool_name = self.ToolName() 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Construct the valgrind command. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.SelfContained(): 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = ["valgrind-%s.sh" % tool_name] 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if 'CHROME_VALGRIND' in os.environ: 3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) path = os.path.join(os.environ['CHROME_VALGRIND'], "bin", "valgrind") 3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else: 3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) path = "valgrind" 3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) proc = [path, "--tool=%s" % tool_name] 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--num-callers=%i" % int(self._options.num_callers)] 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.trace_children: 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--trace-children=yes"] 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--trace-children-skip='*dbus-daemon*'"] 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--trace-children-skip='*dbus-launch*'"] 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--trace-children-skip='*perl*'"] 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--trace-children-skip='*python*'"] 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # This is really Python, but for some reason Valgrind follows it. 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) proc += ["--trace-children-skip='*lsb_release*'"] 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self.ToolSpecificFlags() 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self._tool_flags 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_count = 0 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for suppression_file in self._options.suppressions: 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(suppression_file): 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_count += 1 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--suppressions=%s" % suppression_file] 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not suppression_count: 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warning("WARNING: NOT USING SUPPRESSIONS!") 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logfilename = self.log_dir + ("/%s." % tool_name) + "%p" 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.UseXML(): 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--xml=yes", "--xml-file=" + logfilename] 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--log-file=" + logfilename] 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The Valgrind command is constructed. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # Valgrind doesn't play nice with the Chrome sandbox. Empty this env var 39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # set by runtest.py to disable the sandbox. 39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if os.environ.get("CHROME_DEVEL_SANDBOX", None): 400a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch logging.info("Removing CHROME_DEVEL_SANDBOX from environment") 40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) os.environ["CHROME_DEVEL_SANDBOX"] = '' 40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Handle --indirect_webkit_layout separately. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.indirect_webkit_layout: 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Need to create the wrapper before modifying |proc|. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wrapper = self.CreateBrowserWrapper(proc, webkit=True) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = self._args 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc.append("--wrapper") 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc.append(wrapper) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.indirect: 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wrapper = self.CreateBrowserWrapper(proc) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.environ["BROWSER_WRAPPER"] = wrapper 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info('export BROWSER_WRAPPER=' + wrapper) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = [] 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self._args 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError, "This method should be implemented " \ 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in the tool-specific subclass" 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateBrowserWrapper(self, proc, webkit=False): 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """The program being run invokes Python or something else that can't stand 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to be valgrinded, and also invokes the Chrome browser. In this case, use a 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) magic wrapper to only valgrind the Chrome browser. Build the wrapper here. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns the path to the wrapper. It's up to the caller to use the wrapper 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) appropriately. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command = " ".join(proc) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Add the PID of the browser wrapper to the logfile names so we can 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # separate log files for different UI tests at the analyze stage. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command = command.replace("%p", "$$.%p") 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (fd, indirect_fname) = tempfile.mkstemp(dir=self.log_dir, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefix="browser_wrapper.", 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text=True) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f = os.fdopen(fd, "w") 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write('#!/bin/bash\n' 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'echo "Started Valgrind wrapper for this test, PID=$$" >&2\n') 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write('DIR=`dirname $0`\n' 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'TESTNAME_FILE=$DIR/testcase.$$.name\n\n') 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if webkit: 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Webkit layout_tests pass the URL as the first line of stdin. 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write('tee $TESTNAME_FILE | %s "$@"\n' % command) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Try to get the test case name by looking at the program arguments. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # i.e. Chromium ui_tests used --test-name arg. 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): This doesn't handle "--test-name Test.Name" 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): ui_tests are dead. Where do we use the non-webkit 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # wrapper now? browser_tests? What do they do? 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write('for arg in $@\ndo\n' 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' if [[ "$arg" =~ --test-name=(.*) ]]\n then\n' 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' echo ${BASH_REMATCH[1]} >$TESTNAME_FILE\n' 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' fi\n' 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'done\n\n' 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '%s "$@"\n' % command) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.close() 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.chmod(indirect_fname, stat.S_IRUSR|stat.S_IXUSR) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return indirect_fname 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateAnalyzer(self): 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError, "This method should be implemented " \ 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in the tool-specific subclass" 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetAnalyzeResults(self, check_sanity=False): 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Glob all the files in the log directory 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filenames = glob.glob(self.log_dir + "/" + self.ToolName() + ".*") 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If we have browser wrapper, the logfiles are named as 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # "toolname.wrapper_PID.valgrind_PID". 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Let's extract the list of wrapper_PIDs and name it ppids 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ppids = set([int(f.split(".")[-2]) \ 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for f in filenames if re.search("\.[0-9]+\.[0-9]+$", f)]) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) analyzer = self.CreateAnalyzer() 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(ppids) == 0: 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Fast path - no browser wrapper was set. 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return analyzer.Report(filenames, None, check_sanity) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = 0 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ppid in ppids: 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcase_name = None 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f = open(self.log_dir + ("/testcase.%d.name" % ppid)) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcase_name = f.read().strip() 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.close() 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wk_layout_prefix="third_party/WebKit/LayoutTests/" 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wk_prefix_at = testcase_name.rfind(wk_layout_prefix) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if wk_prefix_at != -1: 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcase_name = testcase_name[wk_prefix_at + len(wk_layout_prefix):] 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except IOError: 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "=====================================================" 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " Below is the report for valgrind wrapper PID=%d." % ppid 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if testcase_name: 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " It was used while running the `%s` test." % testcase_name 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " You can find the corresponding test" 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " by searching the above log for 'PID=%d'" % ppid 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stdout.flush() 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ppid_filenames = [f for f in filenames \ 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if re.search("\.%d\.[0-9]+$" % ppid, f)] 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # check_sanity won't work with browser wrappers 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert check_sanity == False 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret |= analyzer.Report(ppid_filenames, testcase_name) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "=====================================================" 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stdout.flush() 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ret != 0: 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "" 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "The Valgrind reports are grouped by test names." 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "Each test has its PID printed in the log when the test was run" 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "and at the beginning of its Valgrind report." 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "Hint: you can search for the reports by Ctrl+F -> `=#`" 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stdout.flush() 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# TODO(timurrrr): Split into a separate file. 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Memcheck(ValgrindTool): 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Memcheck 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Dynamic memory error detector for Linux & Mac 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http://valgrind.org/info/tools.html#memcheck 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(Memcheck, self).__init__() 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(Memcheck.ExtendOptionParser) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolName(self): 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "memcheck" 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("--leak-check", "--leak_check", type="string", 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default="yes", # --leak-check=yes is equivalent of =full 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="perform leak checking at the end of the run") 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--show_all_leaks", action="store_true", 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="also show less blatant leaks") 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--track_origins", action="store_true", 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Show whence uninitialized bytes came. 30% slower.") 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = ["--gen-suppressions=all", "--demangle=no"] 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--leak-check=%s" % self._options.leak_check] 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.show_all_leaks: 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--show-reachable=yes"] 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--show-possibly-lost=no"] 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.track_origins: 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--track-origins=yes"] 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(glider): this is a temporary workaround for http://crbug.com/51716 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Let's see whether it helps. 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsMac(): 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--smc-check=all"] 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateAnalyzer(self): 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_gdb = common.IsMac() 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return memcheck_analyze.MemcheckAnalyzer(self._source_dir, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._options.show_all_leaks, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_gdb=use_gdb) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Analyze(self, check_sanity=False): 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = self.GetAnalyzeResults(check_sanity) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ret != 0: 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Please see http://dev.chromium.org/developers/how-tos/" 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "using-valgrind for the info on Memcheck/Valgrind") 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PinTool(BaseTool): 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Abstract class for running PIN tools. 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Always subclass this and implement ToolSpecificFlags() and 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtendOptionParser() for tool-specific stuff. 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def PrepareForTest(self): 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise NotImplementedError, "This method should be implemented " \ 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in the tool-specific subclass" 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolCommand(self): 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Get the PIN command to run.""" 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Construct the PIN command. 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pin_cmd = os.getenv("PIN_COMMAND") 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not pin_cmd: 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise RuntimeError, "Please set PIN_COMMAND environment variable " \ 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "with the path to pin.exe" 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = pin_cmd.split(" ") 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self.ToolSpecificFlags() 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The PIN command is constructed. 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # PIN requires -- to separate PIN flags from the executable name. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # self._args begins with the exe to be run. 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--"] 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self._args 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerBase(object): 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ThreadSanitizer 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Dynamic data race detector for Linux, Mac and Windows. 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http://code.google.com/p/data-race-test/wiki/ThreadSanitizer 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Since TSan works on both Valgrind (Linux, Mac) and PIN (Windows), we need 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to have multiple inheritance 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INFO_MESSAGE="Please see http://dev.chromium.org/developers/how-tos/" \ 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "using-valgrind/threadsanitizer for the info on " \ 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ThreadSanitizer" 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ThreadSanitizerBase, self).__init__() 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(ThreadSanitizerBase.ExtendOptionParser) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolName(self): 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "tsan" 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def UseXML(self): 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def SelfContained(self): 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--hybrid", default="no", 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest="hybrid", 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Finds more data races, may give false positive " 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "reports unless the code is annotated") 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--announce-threads", default="yes", 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest="announce_threads", 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Show the the stack traces of thread creation") 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--free-is-write", default="no", 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest="free_is_write", 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Treat free()/operator delete as memory write. " 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This helps finding more data races, but (currently) " 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "this may give false positive reports on std::string " 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "internals, see http://code.google.com/p/data-race-test" 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/issues/detail?id=40") 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def EvalBoolFlag(self, flag_value): 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flag_value in ["1", "true", "yes"]): 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif (flag_value in ["0", "false", "no"]): 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise RuntimeError, "Can't parse flag value (%s)" % flag_value 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_files = ["ignores.txt"] 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for platform_suffix in common.PlatformNames(): 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_files.append("ignores_%s.txt" % platform_suffix) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ignore_file in ignore_files: 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fullname = os.path.join(self._source_dir, 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "tools", "valgrind", "tsan", ignore_file) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(fullname): 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fullname = common.NormalizeWindowsPath(fullname) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--ignore=%s" % fullname] 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # This should shorten filepaths for local builds. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--file-prefix-to-cut=%s/" % self._source_dir] 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # This should shorten filepaths on bots. 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--file-prefix-to-cut=build/src/"] 6897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret += ["--file-prefix-to-cut=out/Release/../../"] 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # This should shorten filepaths for functions intercepted in TSan. 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--file-prefix-to-cut=scripts/tsan/tsan/"] 6937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret += ["--file-prefix-to-cut=src/tsan/tsan/"] 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--gen-suppressions=true"] 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.EvalBoolFlag(self._options.hybrid): 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--hybrid=yes"] # "no" is the default value for TSAN 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.EvalBoolFlag(self._options.announce_threads): 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--announce-threads"] 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.EvalBoolFlag(self._options.free_is_write): 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--free-is-write=yes"] 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--free-is-write=no"] 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # --show-pc flag is needed for parsing the error logs on Darwin. 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if platform_suffix == 'mac': 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--show-pc=yes"] 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--show-pid=no"] 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boring_callers = common.BoringCallers(mangled=False, use_re_wildcards=False) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): In fact, we want "starting from .." instead of "below .." 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for bc in boring_callers: 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += ["--cut_stack_below=%s" % bc] 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerPosix(ThreadSanitizerBase, ValgrindTool): 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = ThreadSanitizerBase.ToolSpecificFlags(self) 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The -v flag is needed for printing the list of used suppressions and 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # obtaining addresses for loaded shared libraries on Mac. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-v"] 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateAnalyzer(self): 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_gdb = common.IsMac() 7324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return tsan_analyze.TsanAnalyzer(use_gdb) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Analyze(self, check_sanity=False): 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = self.GetAnalyzeResults(check_sanity) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ret != 0: 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info(self.INFO_MESSAGE) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerWindows(ThreadSanitizerBase, PinTool): 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ThreadSanitizerWindows, self).__init__() 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(ThreadSanitizerWindows.ExtendOptionParser) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--suppressions", default=[], 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action="append", 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="path to TSan suppression file") 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) add_env = { 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "CHROME_ALLOCATOR" : "WINHEAP", 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for k,v in add_env.iteritems(): 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.info("export %s=%s", k, v) 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) os.putenv(k, v) 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = ThreadSanitizerBase.ToolSpecificFlags(self) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # On PIN, ThreadSanitizer has its own suppression mechanism 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # and --log-file flag which work exactly on Valgrind. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_count = 0 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for suppression_file in self._options.suppressions: 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(suppression_file): 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_count += 1 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_file = common.NormalizeWindowsPath(suppression_file) 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--suppressions=%s" % suppression_file] 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not suppression_count: 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warning("WARNING: NOT USING SUPPRESSIONS!") 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logfilename = self.log_dir + "/tsan.%p" 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--log-file=" + common.NormalizeWindowsPath(logfilename)] 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): Add flags for Valgrind trace children analog when we 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # start running complex tests (e.g. UI) under TSan/Win. 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Analyze(self, check_sanity=False): 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filenames = glob.glob(self.log_dir + "/tsan.*") 7858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) analyzer = tsan_analyze.TsanAnalyzer() 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = analyzer.Report(filenames, None, check_sanity) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ret != 0: 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info(self.INFO_MESSAGE) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DrMemory(BaseTool): 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Dr.Memory 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Dynamic memory error detector for Windows. 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http://dev.chromium.org/developers/how-tos/using-drmemory 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) It is not very mature at the moment, some things might not work properly. 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, full_mode, pattern_mode): 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(DrMemory, self).__init__() 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.full_mode = full_mode 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.pattern_mode = pattern_mode 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(DrMemory.ExtendOptionParser) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolName(self): 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "drmemory" 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--suppressions", default=[], 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action="append", 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="path to a drmemory suppression file") 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--follow_python", action="store_true", 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, dest="follow_python", 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Monitor python child processes. If off, neither " 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "python children nor any children of python children " 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "will be monitored.") 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--indirect", action="store_true", 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="set BROWSER_WRAPPER rather than " 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "running Dr. Memory directly on the harness") 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parser.add_option("", "--indirect_webkit_layout", action="store_true", 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default=False, 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) help="set --wrapper rather than running valgrind " 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "directly.") 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--use_debug", action="store_true", 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=False, dest="use_debug", 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="Run Dr. Memory debug build") 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--trace_children", action="store_true", 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default=True, 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="TODO: default value differs from Valgrind") 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolCommand(self): 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Get the tool command to run.""" 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # WINHEAP is what Dr. Memory supports as there are issues w/ both 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # jemalloc (http://code.google.com/p/drmemory/issues/detail?id=320) and 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # tcmalloc (http://code.google.com/p/drmemory/issues/detail?id=314) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) add_env = { 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CHROME_ALLOCATOR" : "WINHEAP", 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "JSIMD_FORCEMMX" : "1", # http://code.google.com/p/drmemory/issues/detail?id=540 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for k,v in add_env.iteritems(): 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("export %s=%s", k, v) 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.putenv(k, v) 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drmem_cmd = os.getenv("DRMEMORY_COMMAND") 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not drmem_cmd: 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise RuntimeError, "Please set DRMEMORY_COMMAND environment variable " \ 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "with the path to drmemory.exe" 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = drmem_cmd.split(" ") 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # By default, don't run python (this will exclude python's children as well) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # to reduce runtime. We're not really interested in spending time finding 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # bugs in the python implementation. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # With file-based config we must update the file every time, and 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # it will affect simultaneous drmem uses by this user. While file-based 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # config has many advantages, here we may want this-instance-only 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # (http://code.google.com/p/drmemory/issues/detail?id=334). 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drconfig_cmd = [ proc[0].replace("drmemory.exe", "drconfig.exe") ] 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drconfig_cmd += ["-quiet"] # suppress errors about no 64-bit libs 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) run_drconfig = True 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.follow_python: 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Following python children") 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # -unreg fails if not already registered so query for that first 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query_cmd = drconfig_cmd + ["-isreg", "python.exe"] 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query_proc = subprocess.Popen(query_cmd, stdout=subprocess.PIPE, 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shell=True) 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (query_out, query_err) = query_proc.communicate() 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if re.search("exe not registered", query_out): 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) run_drconfig = False # all set 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drconfig_cmd += ["-unreg", "python.exe"] 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Excluding python children") 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drconfig_cmd += ["-reg", "python.exe", "-norun"] 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if run_drconfig: 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drconfig_retcode = common.RunSubprocess(drconfig_cmd, self._timeout) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if drconfig_retcode: 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("Configuring whether to follow python children failed " \ 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "with %d.", drconfig_retcode) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise RuntimeError, "Configuring python children failed " 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_count = 0 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp_files = self._options.suppressions 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.full_mode: 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp_files += [s.replace(".txt", "_full.txt") for s in supp_files] 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for suppression_file in supp_files: 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(suppression_file): 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppression_count += 1 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-suppress", common.NormalizeWindowsPath(suppression_file)] 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not suppression_count: 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warning("WARNING: NOT USING SUPPRESSIONS!") 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Un-comment to dump Dr.Memory events on error 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #proc += ["-dr_ops", "-dumpcore_mask", "-dr_ops", "0x8bff"] 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Un-comment and comment next line to debug Dr.Memory 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #proc += ["-dr_ops", "-no_hide"] 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #proc += ["-dr_ops", "-msgbox_mask", "-dr_ops", "15"] 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #Proc += ["-dr_ops", "-stderr_mask", "-dr_ops", "15"] 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Ensure we see messages about Dr. Memory crashing! 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-dr_ops", "-stderr_mask", "-dr_ops", "12"] 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._options.use_debug: 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-debug"] 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-logdir", common.NormalizeWindowsPath(self.log_dir)] 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.log_parent_dir: 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # gpu process on Windows Vista+ runs at Low Integrity and can only 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # write to certain directories (http://crbug.com/119131) 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symcache_dir = os.path.join(self.log_parent_dir, "drmemory.symcache") 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif self._options.build_dir: 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The other case is only possible with -t cmdline. 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Anyways, if we omit -symcache_dir the -logdir's value is used which 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # should be fine. 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symcache_dir = os.path.join(self._options.build_dir, "drmemory.symcache") 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if symcache_dir: 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(symcache_dir): 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.mkdir(symcache_dir) 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except OSError: 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warning("Can't create symcache dir?") 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.exists(symcache_dir): 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-symcache_dir", common.NormalizeWindowsPath(symcache_dir)] 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Use -no_summary to suppress DrMemory's summary and init-time 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # notifications. We generate our own with drmemory_analyze.py. 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-batch", "-no_summary"] 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Un-comment to disable interleaved output. Will also suppress error 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # messages normally printed to stderr. 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #proc += ["-quiet", "-no_results_to_stderr"] 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-callstack_max_frames", "40"] 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 938d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) # disable leak scan for now 939d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) proc += ["-no_count_leaks", "-no_leak_scan"] 940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 9411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # crbug.com/413215, no heap mismatch check for Windows release build binary 9421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if common.IsWindows() and "Release" in self._options.build_dir: 9431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci proc += ["-no_check_delete_mismatch"] 9441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # make callstacks easier to read 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-callstack_srcfile_prefix", 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "build\\src,chromium\\src,crt_build\\self_x86"] 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-callstack_modname_hide", 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "*drmemory*,chrome.dll"] 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boring_callers = common.BoringCallers(mangled=False, use_re_wildcards=False) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): In fact, we want "starting from .." instead of "below .." 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-callstack_truncate_below", ",".join(boring_callers)] 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.pattern_mode: 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-pattern", "0xf1fd", "-no_count_leaks", "-redzone_size", "0x20"] 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif not self.full_mode: 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["-light"] 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self._tool_flags 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Dr.Memory requires -- to separate tool flags from the executable name. 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ["--"] 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self._options.indirect or self._options.indirect_webkit_layout: 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): reuse for TSan on Windows 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wrapper_path = os.path.join(self._source_dir, 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "tools", "valgrind", "browser_wrapper_win.py") 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wrapper = " ".join(["python", wrapper_path] + proc) 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.CreateBrowserWrapper(wrapper) 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("browser wrapper = " + " ".join(proc)) 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self._options.indirect_webkit_layout: 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) proc = self._args 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Layout tests want forward slashes. 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wrapper = wrapper.replace('\\', '/') 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) proc += ["--wrapper", wrapper] 9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return proc 9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) proc = [] 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Note that self._args begins with the name of the exe to be run. 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._args[0] = common.NormalizeWindowsPath(self._args[0]) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += self._args 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateBrowserWrapper(self, command): 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.putenv("BROWSER_WRAPPER", command) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Analyze(self, check_sanity=False): 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Use one analyzer for all the log files to avoid printing duplicate reports 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): unify this with Valgrind and other tools when we have 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # http://code.google.com/p/drmemory/issues/detail?id=684 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) analyzer = drmemory_analyze.DrMemoryAnalyzer() 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = 0 9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not self._options.indirect and not self._options.indirect_webkit_layout: 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filenames = glob.glob(self.log_dir + "/*/results.txt") 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = analyzer.Report(filenames, None, check_sanity) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcases = glob.glob(self.log_dir + "/testcase.*.logs") 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If we have browser wrapper, the per-test logdirs are named as 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # "testcase.wrapper_PID.name". 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Let's extract the list of wrapper_PIDs and name it ppids. 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # NOTE: ppids may contain '_', i.e. they are not ints! 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ppids = set([f.split(".")[-2] for f in testcases]) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ppid in ppids: 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcase_name = None 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f = open("%s/testcase.%s.name" % (self.log_dir, ppid)) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcase_name = f.read().strip() 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.close() 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except IOError: 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "=====================================================" 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " Below is the report for drmemory wrapper PID=%s." % ppid 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if testcase_name: 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " It was used while running the `%s` test." % testcase_name 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): hm, the PID line is suppressed on Windows... 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " You can find the corresponding test" 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print " by searching the above log for 'PID=%s'" % ppid 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stdout.flush() 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ppid_filenames = glob.glob("%s/testcase.%s.logs/*/results.txt" % 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (self.log_dir, ppid)) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret |= analyzer.Report(ppid_filenames, testcase_name, False) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print "=====================================================" 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stdout.flush() 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Please see http://dev.chromium.org/developers/how-tos/" 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "using-drmemory for the info on Dr. Memory") 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# RaceVerifier support. See 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# http://code.google.com/p/data-race-test/wiki/RaceVerifier for more details. 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV1Analyzer(tsan_analyze.TsanAnalyzer): 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ TsanAnalyzer that saves race reports to a file. """ 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TMP_FILE = "rvlog.tmp" 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, source_dir, use_gdb): 10458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) super(ThreadSanitizerRV1Analyzer, self).__init__(use_gdb) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.out = open(self.TMP_FILE, "w") 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Report(self, files, testcase, check_sanity=False): 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reports = self.GetReports(files) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for report in reports: 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.out, report 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(reports) > 0: 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("RaceVerifier pass 1 of 2, found %i reports" % len(reports)) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CloseOutputFile(self): 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.out.close() 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV1Mixin(object): 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """RaceVerifier first pass. 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Runs ThreadSanitizer as usual, but hides race reports and collects them in a 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temporary file""" 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ThreadSanitizerRV1Mixin, self).__init__() 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(ThreadSanitizerRV1Mixin.ExtendOptionParser) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.set_defaults(hybrid="yes") 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def CreateAnalyzer(self): 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_gdb = common.IsMac() 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.analyzer = ThreadSanitizerRV1Analyzer(self._source_dir, use_gdb) 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.analyzer 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Cleanup(self): 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ThreadSanitizerRV1Mixin, self).Cleanup() 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.analyzer.CloseOutputFile() 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV2Mixin(object): 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """RaceVerifier second pass.""" 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ThreadSanitizerRV2Mixin, self).__init__() 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.RegisterOptionParserHook(ThreadSanitizerRV2Mixin.ExtendOptionParser) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtendOptionParser(self, parser): 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.add_option("", "--race-verifier-sleep-ms", 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest="race_verifier_sleep_ms", default=10, 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="duration of RaceVerifier delays") 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolSpecificFlags(self): 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc = super(ThreadSanitizerRV2Mixin, self).ToolSpecificFlags() 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc += ['--race-verifier=%s' % ThreadSanitizerRV1Analyzer.TMP_FILE, 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--race-verifier-sleep-ms=%d' % 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int(self._options.race_verifier_sleep_ms)] 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return proc 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Cleanup(self): 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(ThreadSanitizerRV2Mixin, self).Cleanup() 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.unlink(ThreadSanitizerRV1Analyzer.TMP_FILE) 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV1Posix(ThreadSanitizerRV1Mixin, ThreadSanitizerPosix): 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV2Posix(ThreadSanitizerRV2Mixin, ThreadSanitizerPosix): 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV1Windows(ThreadSanitizerRV1Mixin, 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadSanitizerWindows): 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadSanitizerRV2Windows(ThreadSanitizerRV2Mixin, 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadSanitizerWindows): 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pass 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RaceVerifier(object): 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Runs tests under RaceVerifier/Valgrind.""" 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MORE_INFO_URL = "http://code.google.com/p/data-race-test/wiki/RaceVerifier" 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def RV1Factory(self): 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsWindows(): 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ThreadSanitizerRV1Windows() 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ThreadSanitizerRV1Posix() 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def RV2Factory(self): 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsWindows(): 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ThreadSanitizerRV2Windows() 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ThreadSanitizerRV2Posix() 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolName(self): 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "tsan" 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Main(self, args, check_sanity, min_runtime_in_seconds): 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Running a TSan + RaceVerifier test. For more information, " + 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "see " + self.MORE_INFO_URL) 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd1 = self.RV1Factory() 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = cmd1.Main(args, check_sanity, min_runtime_in_seconds) 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Verify race reports, if there are any. 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ret == -1: 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Starting pass 2 of 2. Running the same binary in " + 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "RaceVerifier mode to confirm possible race reports.") 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("For more information, see " + self.MORE_INFO_URL) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd2 = self.RV2Factory() 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = cmd2.Main(args, check_sanity, min_runtime_in_seconds) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("No reports, skipping RaceVerifier second pass") 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("Please see " + self.MORE_INFO_URL + " for more information " + 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "on RaceVerifier") 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Run(self, args, module, min_runtime_in_seconds=0): 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.Main(args, False, min_runtime_in_seconds) 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EmbeddedTool(BaseTool): 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Abstract class for tools embedded directly into the test binary. 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(glider): need to override Execute() and support process chaining here. 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolCommand(self): 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # In the simplest case just the args of the script. 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self._args 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Asan(EmbeddedTool): 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """AddressSanitizer, a memory error detector. 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) More information at 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http://dev.chromium.org/developers/testing/addresssanitizer 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) super(Asan, self).__init__() 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._timeout = 1200 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsMac(): 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._env["DYLD_NO_PIE"] = "1" 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolName(self): 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "asan" 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToolCommand(self): 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(glider): use pipes instead of the ugly wrapper here once they 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # are supported. 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) procs = [os.path.join(self._source_dir, "tools", "valgrind", 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "asan", "asan_wrapper.sh")] 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) procs.extend(self._args) 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return procs 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Analyze(sels, unused_check_sanity): 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ToolFactory: 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Create(self, tool_name): 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "memcheck": 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Memcheck() 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "tsan": 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if common.IsWindows(): 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ThreadSanitizerWindows() 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ThreadSanitizerPosix() 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "drmemory" or tool_name == "drmemory_light": 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): remove support for "drmemory" when buildbots are 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # switched to drmemory_light OR make drmemory==drmemory_full the default 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # mode when the tool is mature enough. 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DrMemory(False, False) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "drmemory_full": 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DrMemory(True, False) 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "drmemory_pattern": 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DrMemory(False, True) 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "tsan_rv": 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RaceVerifier() 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if tool_name == "asan": 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Asan() 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_name = common.PlatformNames()[0] 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except common.NotImplementedError: 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_name = sys.platform + "(Unknown)" 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise RuntimeError, "Unknown tool (tool=%s, platform=%s)" % (tool_name, 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) platform_name) 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CreateTool(tool): 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolFactory().Create(tool) 1237