def __init__(self): temp_parent_dir = None self.log_parent_dir = "" if common.IsWindows(): # gpu process on Windows Vista+ runs at Low Integrity and can only # write to certain directories (http://crbug.com/119131) # # TODO(bruening): if scripts die in middle and don't clean up temp # dir, we'll accumulate files in profile dir. should remove # really old files automatically. profile = os.getenv("USERPROFILE") if profile: self.log_parent_dir = profile + "\\AppData\\LocalLow\\" if os.path.exists(self.log_parent_dir): self.log_parent_dir = common.NormalizeWindowsPath(self.log_parent_dir) temp_parent_dir = self.log_parent_dir # Generated every time (even when overridden) self.temp_dir = tempfile.mkdtemp(prefix="vg_logs_", dir=temp_parent_dir) self.log_dir = self.temp_dir # overridable by --keep_logs self.option_parser_hooks = [] # TODO(glider): we may not need some of the env vars on some of the # platforms. self._env = { "G_SLICE" : "always-malloc", "NSS_DISABLE_UNLOAD" : "1", "NSS_DISABLE_ARENA_FREE_LIST" : "1", "GTEST_DEATH_TEST_USE_FORK": "1", }
def Create(self, tool_name): if tool_name == "memcheck": return Memcheck() if tool_name == "tsan": if common.IsWindows(): return ThreadSanitizerWindows() else: return ThreadSanitizerPosix() if tool_name == "drmemory" or tool_name == "drmemory_light": # TODO(timurrrr): remove support for "drmemory" when buildbots are # switched to drmemory_light OR make drmemory==drmemory_full the default # mode when the tool is mature enough. return DrMemory(False, False) if tool_name == "drmemory_full": return DrMemory(True, False) if tool_name == "drmemory_pattern": return DrMemory(False, True) if tool_name == "tsan_rv": return RaceVerifier() if tool_name == "asan": return Asan() try: platform_name = common.PlatformNames()[0] except common.NotImplementedError: platform_name = sys.platform + "(Unknown)" raise RuntimeError, "Unknown tool (tool=%s, platform=%s)" % (tool_name, platform_name)
def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None): '''Generates the default command array that most tests will use.''' if exe and common.IsWindows(): exe += '.exe' cmd = list(self._command_preamble) # Find all suppressions matching the following pattern: # tools/valgrind/TOOL/suppressions[_PLATFORM].txt # and list them with --suppressions= prefix. script_dir = path_utils.ScriptDir() suppression_file = os.path.join(script_dir, "..", "suppressions.txt") if os.path.exists(suppression_file): cmd.append("--suppressions=%s" % suppression_file) # Platform-specific suppression for platform in common.PlatformNames(): platform_suppression_file = \ os.path.join(script_dir, "..", 'suppressions_%s.txt' % platform) if os.path.exists(platform_suppression_file): cmd.append("--suppressions=%s" % platform_suppression_file) if self._options.valgrind_tool_flags: cmd += self._options.valgrind_tool_flags.split(" ") if self._options.keep_logs: cmd += ["--keep_logs"] if valgrind_test_args != None: for arg in valgrind_test_args: cmd.append(arg) if exe: self._EnsureBuildDirFound() exe_path = os.path.join(self._options.build_dir, exe) if not os.path.exists(exe_path): raise ExecutableNotFound("Couldn't find '%s'" % exe_path) cmd.append(exe_path) # Valgrind runs tests slowly, so slow tests hurt more; show elapased time # so we can find the slowpokes. cmd.append("--gtest_print_time") # Built-in test launcher for gtest-based executables runs tests using # multiple process by default. Force the single-process mode back. cmd.append("--single-process-tests") if self._options.gtest_repeat: cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat) if self._options.gtest_shuffle: cmd.append("--gtest_shuffle") if self._options.gtest_break_on_failure: cmd.append("--gtest_break_on_failure") if self._options.test_launcher_bot_mode: cmd.append("--test-launcher-bot-mode") if self._options.test_launcher_total_shards is not None: cmd.append("--test-launcher-total-shards=%d" % self._options.test_launcher_total_shards) if self._options.test_launcher_shard_index is not None: cmd.append("--test-launcher-shard-index=%d" % self._options.test_launcher_shard_index) return cmd
def ParseReportFile(self, filename): '''Parses a report file and returns a list of ThreadSanitizer reports. Args: filename: report filename. Returns: list of (list of (str iff self._use_gdb, _StackTraceLine otherwise)). ''' ret = [] self.cur_fd_ = open(filename, 'r') while True: # Read ThreadSanitizer reports. self.ReadLine() if not self.line_: break while True: tmp = [] while re.search(TsanAnalyzer.RACE_VERIFIER_LINE, self.line_): tmp.append(self.line_) self.ReadLine() while re.search(TsanAnalyzer.THREAD_CREATION_STR, self.line_): tmp.extend(self.ReadSection()) if re.search(TsanAnalyzer.TSAN_RACE_DESCRIPTION, self.line_): tmp.extend(self.ReadSection()) ret.append( tmp ) # includes RaceVerifier and thread creation stacks elif (re.search(TsanAnalyzer.TSAN_WARNING_DESCRIPTION, self.line_) and not common.IsWindows() ): # workaround for http://crbug.com/53198 tmp.extend(self.ReadSection()) ret.append(tmp) else: break tmp = [] if re.search(TsanAnalyzer.TSAN_ASSERTION, self.line_): tmp.extend(self.ReadTillTheEnd()) ret.append(tmp) break match = re.search("used_suppression:\s+([0-9]+)\s(.*)", self.line_) if match: count, supp_name = match.groups() count = int(count) if supp_name in self.used_suppressions: self.used_suppressions[supp_name] += count else: self.used_suppressions[supp_name] = count self.cur_fd_.close() return ret
def _DefaultCommand(self, tool, module, exe=None, valgrind_test_args=None): '''Generates the default command array that most tests will use.''' if exe and common.IsWindows(): exe = exe + '.exe' if not self._options.build_dir: if common.IsWine(): self._options.build_dir = os.path.join( self._source_dir, "chrome", "Debug") else: dirs = [ os.path.join(self._source_dir, "xcodebuild", "Debug"), os.path.join(self._source_dir, "out", "Debug"), os.path.join(self._source_dir, "build", "Debug"), ] if exe: self._options.build_dir = FindDirContainingNewestFile(dirs, exe) else: self._options.build_dir = FindNewestDir(dirs) cmd = list(self._command_preamble) # Find all suppressions matching the following pattern: # tools/valgrind/TOOL/suppressions[_PLATFORM].txt # and list them with --suppressions= prefix. script_dir = path_utils.ScriptDir() tool_name = tool.ToolName(); suppression_file = os.path.join(script_dir, tool_name, "suppressions.txt") if os.path.exists(suppression_file): cmd.append("--suppressions=%s" % suppression_file) # Platform-specific suppression for platform in common.PlatformNames(): platform_suppression_file = \ os.path.join(script_dir, tool_name, 'suppressions_%s.txt' % platform) if os.path.exists(platform_suppression_file): cmd.append("--suppressions=%s" % platform_suppression_file) if self._options.valgrind_tool_flags: cmd += self._options.valgrind_tool_flags.split(" ") if valgrind_test_args != None: for arg in valgrind_test_args: cmd.append(arg) if exe: if common.IsWine(): cmd.append(os.environ.get('WINE')) exe = exe + '.exe' cmd.append(os.path.join(self._options.build_dir, exe)) # Valgrind runs tests slowly, so slow tests hurt more; show elapased time # so we can find the slowpokes. cmd.append("--gtest_print_time") if self._options.gtest_repeat: cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat) return cmd
def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None): '''Generates the default command array that most tests will use.''' if exe and common.IsWindows(): exe += '.exe' cmd = list(self._command_preamble) # Find all suppressions matching the following pattern: # tools/valgrind/TOOL/suppressions[_PLATFORM].txt # and list them with --suppressions= prefix. script_dir = path_utils.ScriptDir() tool_name = tool.ToolName() suppression_file = os.path.join(script_dir, tool_name, "suppressions.txt") if os.path.exists(suppression_file): cmd.append("--suppressions=%s" % suppression_file) # Platform-specific suppression for platform in common.PlatformNames(): platform_suppression_file = \ os.path.join(script_dir, tool_name, 'suppressions_%s.txt' % platform) if os.path.exists(platform_suppression_file): cmd.append("--suppressions=%s" % platform_suppression_file) if self._options.valgrind_tool_flags: cmd += self._options.valgrind_tool_flags.split(" ") if self._options.keep_logs: cmd += ["--keep_logs"] if valgrind_test_args != None: for arg in valgrind_test_args: cmd.append(arg) if exe: self._EnsureBuildDirFound() cmd.append(os.path.join(self._options.build_dir, exe)) # Valgrind runs tests slowly, so slow tests hurt more; show elapased time # so we can find the slowpokes. cmd.append("--gtest_print_time") if self._options.gtest_repeat: cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat) return cmd
def ToolCommand(self): """Get the tool command to run.""" # WINHEAP is what Dr. Memory supports as there are issues w/ both # jemalloc (http://code.google.com/p/drmemory/issues/detail?id=320) and # tcmalloc (http://code.google.com/p/drmemory/issues/detail?id=314) add_env = { "CHROME_ALLOCATOR" : "WINHEAP", "JSIMD_FORCEMMX" : "1", # http://code.google.com/p/drmemory/issues/detail?id=540 } for k,v in add_env.iteritems(): logging.info("export %s=%s", k, v) os.putenv(k, v) drmem_cmd = os.getenv("DRMEMORY_COMMAND") if not drmem_cmd: raise RuntimeError, "Please set DRMEMORY_COMMAND environment variable " \ "with the path to drmemory.exe" proc = drmem_cmd.split(" ") # By default, don't run python (this will exclude python's children as well) # to reduce runtime. We're not really interested in spending time finding # bugs in the python implementation. # With file-based config we must update the file every time, and # it will affect simultaneous drmem uses by this user. While file-based # config has many advantages, here we may want this-instance-only # (http://code.google.com/p/drmemory/issues/detail?id=334). drconfig_cmd = [ proc[0].replace("drmemory.exe", "drconfig.exe") ] drconfig_cmd += ["-quiet"] # suppress errors about no 64-bit libs run_drconfig = True if self._options.follow_python: logging.info("Following python children") # -unreg fails if not already registered so query for that first query_cmd = drconfig_cmd + ["-isreg", "python.exe"] query_proc = subprocess.Popen(query_cmd, stdout=subprocess.PIPE, shell=True) (query_out, query_err) = query_proc.communicate() if re.search("exe not registered", query_out): run_drconfig = False # all set else: drconfig_cmd += ["-unreg", "python.exe"] else: logging.info("Excluding python children") drconfig_cmd += ["-reg", "python.exe", "-norun"] if run_drconfig: drconfig_retcode = common.RunSubprocess(drconfig_cmd, self._timeout) if drconfig_retcode: logging.error("Configuring whether to follow python children failed " \ "with %d.", drconfig_retcode) raise RuntimeError, "Configuring python children failed " suppression_count = 0 supp_files = self._options.suppressions if self.full_mode: supp_files += [s.replace(".txt", "_full.txt") for s in supp_files] for suppression_file in supp_files: if os.path.exists(suppression_file): suppression_count += 1 proc += ["-suppress", common.NormalizeWindowsPath(suppression_file)] if not suppression_count: logging.warning("WARNING: NOT USING SUPPRESSIONS!") # Un-comment to dump Dr.Memory events on error #proc += ["-dr_ops", "-dumpcore_mask", "-dr_ops", "0x8bff"] # Un-comment and comment next line to debug Dr.Memory #proc += ["-dr_ops", "-no_hide"] #proc += ["-dr_ops", "-msgbox_mask", "-dr_ops", "15"] #Proc += ["-dr_ops", "-stderr_mask", "-dr_ops", "15"] # Ensure we see messages about Dr. Memory crashing! proc += ["-dr_ops", "-stderr_mask", "-dr_ops", "12"] if self._options.use_debug: proc += ["-debug"] proc += ["-logdir", common.NormalizeWindowsPath(self.log_dir)] if self.log_parent_dir: # gpu process on Windows Vista+ runs at Low Integrity and can only # write to certain directories (http://crbug.com/119131) symcache_dir = os.path.join(self.log_parent_dir, "drmemory.symcache") elif self._options.build_dir: # The other case is only possible with -t cmdline. # Anyways, if we omit -symcache_dir the -logdir's value is used which # should be fine. symcache_dir = os.path.join(self._options.build_dir, "drmemory.symcache") if symcache_dir: if not os.path.exists(symcache_dir): try: os.mkdir(symcache_dir) except OSError: logging.warning("Can't create symcache dir?") if os.path.exists(symcache_dir): proc += ["-symcache_dir", common.NormalizeWindowsPath(symcache_dir)] # Use -no_summary to suppress DrMemory's summary and init-time # notifications. We generate our own with drmemory_analyze.py. proc += ["-batch", "-no_summary"] # Un-comment to disable interleaved output. Will also suppress error # messages normally printed to stderr. #proc += ["-quiet", "-no_results_to_stderr"] proc += ["-callstack_max_frames", "40"] # disable leak scan for now proc += ["-no_count_leaks", "-no_leak_scan"] # crbug.com/413215, no heap mismatch check for Windows release build binary if common.IsWindows() and "Release" in self._options.build_dir: proc += ["-no_check_delete_mismatch"] # make callstacks easier to read proc += ["-callstack_srcfile_prefix", "build\\src,chromium\\src,crt_build\\self_x86"] proc += ["-callstack_modname_hide", "*drmemory*,chrome.dll"] boring_callers = common.BoringCallers(mangled=False, use_re_wildcards=False) # TODO(timurrrr): In fact, we want "starting from .." instead of "below .." proc += ["-callstack_truncate_below", ",".join(boring_callers)] if self.pattern_mode: proc += ["-pattern", "0xf1fd", "-no_count_leaks", "-redzone_size", "0x20"] elif not self.full_mode: proc += ["-light"] proc += self._tool_flags # Dr.Memory requires -- to separate tool flags from the executable name. proc += ["--"] if self._options.indirect or self._options.indirect_webkit_layout: # TODO(timurrrr): reuse for TSan on Windows wrapper_path = os.path.join(self._source_dir, "tools", "valgrind", "browser_wrapper_win.py") wrapper = " ".join(["python", wrapper_path] + proc) self.CreateBrowserWrapper(wrapper) logging.info("browser wrapper = " + " ".join(proc)) if self._options.indirect_webkit_layout: proc = self._args # Layout tests want forward slashes. wrapper = wrapper.replace('\\', '/') proc += ["--wrapper", wrapper] return proc else: proc = [] # Note that self._args begins with the name of the exe to be run. self._args[0] = common.NormalizeWindowsPath(self._args[0]) proc += self._args return proc
def RV2Factory(self): if common.IsWindows(): return ThreadSanitizerRV2Windows() else: return ThreadSanitizerRV2Posix()
def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None): '''Generates the default command array that most tests will use.''' if exe and common.IsWindows(): exe += '.exe' cmd = list(self._command_preamble) # Find all suppressions matching the following pattern: # tools/valgrind/TOOL/suppressions[_PLATFORM].txt # and list them with --suppressions= prefix. script_dir = path_utils.ScriptDir() tool_name = tool.ToolName() suppression_file = os.path.join(script_dir, tool_name, "suppressions.txt") if os.path.exists(suppression_file): cmd.append("--suppressions=%s" % suppression_file) # Platform-specific suppression for platform in common.PlatformNames(): platform_suppression_file = \ os.path.join(script_dir, tool_name, 'suppressions_%s.txt' % platform) if os.path.exists(platform_suppression_file): cmd.append("--suppressions=%s" % platform_suppression_file) if tool_name == "drmemory": if self._options.drmemory_ops: # prepending " " to avoid Dr. Memory's option confusing optparse cmd += ["--drmemory_ops", " " + self._options.drmemory_ops] if self._options.valgrind_tool_flags: cmd += self._options.valgrind_tool_flags.split(" ") if self._options.keep_logs: cmd += ["--keep_logs"] if valgrind_test_args != None: for arg in valgrind_test_args: cmd.append(arg) if exe: self._EnsureBuildDirFound() exe_path = os.path.join(self._options.build_dir, exe) if not os.path.exists(exe_path): raise ExecutableNotFound("Couldn't find '%s'" % exe_path) # Make sure we don't try to test ASan-built binaries # with other dynamic instrumentation-based tools. # TODO(timurrrr): also check TSan and MSan? # `nm` might not be available, so use try-except. try: # Do not perform this check on OS X, as 'nm' on 10.6 can't handle # binaries built with Clang 3.5+. if not common.IsMac(): nm_output = subprocess.check_output(["nm", exe_path]) if nm_output.find("__asan_init") != -1: raise BadBinary( "You're trying to run an executable instrumented " "with AddressSanitizer under %s. Please provide " "an uninstrumented executable." % tool_name) except OSError: pass cmd.append(exe_path) # Valgrind runs tests slowly, so slow tests hurt more; show elapased time # so we can find the slowpokes. cmd.append("--gtest_print_time") # Built-in test launcher for gtest-based executables runs tests using # multiple process by default. Force the single-process mode back. cmd.append("--single-process-tests") if self._options.gtest_repeat: cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat) if self._options.gtest_shuffle: cmd.append("--gtest_shuffle") if self._options.gtest_break_on_failure: cmd.append("--gtest_break_on_failure") if self._options.test_launcher_bot_mode: cmd.append("--test-launcher-bot-mode") if self._options.test_launcher_total_shards is not None: cmd.append("--test-launcher-total-shards=%d" % self._options.test_launcher_total_shards) if self._options.test_launcher_shard_index is not None: cmd.append("--test-launcher-shard-index=%d" % self._options.test_launcher_shard_index) return cmd