diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-26 04:07:50 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-26 04:07:50 +0000 |
commit | 58580359a452cb7c3b9580edc0843c3ab3d158df (patch) | |
tree | 964dbcc1505f4b9c2bbb5e7a64720861d604c8f3 /base | |
parent | 23872906817de5d402b0c2da6d5f7ee6026378e6 (diff) | |
download | chromium_src-58580359a452cb7c3b9580edc0843c3ab3d158df.zip chromium_src-58580359a452cb7c3b9580edc0843c3ab3d158df.tar.gz chromium_src-58580359a452cb7c3b9580edc0843c3ab3d158df.tar.bz2 |
Move debug-related stuff from base to the base/debug directory and use the
base::debug namespace.
This splits apart debug_util into base/debugger and base/stack_trace
There are still two functions in debug_util that I'm not sure what to do with.
Since this uses the base::debug namespace, I removed the functions in
debugger.h from the static class and just made them free functions in the
namespace.
TEST=it compiles
BUG=none
Review URL: http://codereview.chromium.org/3945002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63859 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 6 | ||||
-rw-r--r-- | base/base.gypi | 22 | ||||
-rw-r--r-- | base/crypto/rsa_private_key_nss.cc | 2 | ||||
-rw-r--r-- | base/debug/debugger.cc | 25 | ||||
-rw-r--r-- | base/debug/debugger.h | 39 | ||||
-rw-r--r-- | base/debug/debugger_posix.cc | 165 | ||||
-rw-r--r-- | base/debug/debugger_win.cc | 112 | ||||
-rw-r--r-- | base/debug/leak_annotations.h (renamed from base/leak_annotations.h) | 8 | ||||
-rw-r--r-- | base/debug/leak_tracker.h (renamed from base/leak_tracker.h) | 12 | ||||
-rw-r--r-- | base/debug/leak_tracker_unittest.cc | 113 | ||||
-rw-r--r-- | base/debug/stack_trace.cc | 21 | ||||
-rw-r--r-- | base/debug/stack_trace.h | 63 | ||||
-rw-r--r-- | base/debug/stack_trace_posix.cc (renamed from base/debug_util_posix.cc) | 131 | ||||
-rw-r--r-- | base/debug/stack_trace_unittest.cc (renamed from base/debug_util_unittest.cc) | 8 | ||||
-rw-r--r-- | base/debug/stack_trace_win.cc (renamed from base/debug_util_win.cc) | 103 | ||||
-rw-r--r-- | base/debug/trace_event.cc (renamed from base/trace_event.cc) | 6 | ||||
-rw-r--r-- | base/debug/trace_event.h (renamed from base/trace_event.h) | 57 | ||||
-rw-r--r-- | base/debug/trace_event_win.cc (renamed from base/trace_event_win.cc) | 29 | ||||
-rw-r--r-- | base/debug/trace_event_win.h (renamed from base/trace_event_win.h) | 37 | ||||
-rw-r--r-- | base/debug/trace_event_win_unittest.cc (renamed from base/trace_event_win_unittest.cc) | 77 | ||||
-rw-r--r-- | base/debug_on_start.cc | 8 | ||||
-rw-r--r-- | base/debug_util.cc | 21 | ||||
-rw-r--r-- | base/debug_util.h | 70 | ||||
-rw-r--r-- | base/debug_util_mac.cc | 1 | ||||
-rw-r--r-- | base/leak_tracker_unittest.cc | 107 | ||||
-rw-r--r-- | base/logging.cc | 15 | ||||
-rw-r--r-- | base/process_util_mac.mm | 36 | ||||
-rw-r--r-- | base/process_util_posix.cc | 4 | ||||
-rw-r--r-- | base/process_util_win.cc | 12 | ||||
-rw-r--r-- | base/test/perf_test_suite.cc | 4 | ||||
-rw-r--r-- | base/test/test_suite.cc | 4 |
31 files changed, 753 insertions, 565 deletions
diff --git a/base/base.gyp b/base/base.gyp index 2de9b4b..6a37f5d 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -75,7 +75,9 @@ 'crypto/signature_verifier_unittest.cc', 'crypto/symmetric_key_unittest.cc', 'data_pack_unittest.cc', - 'debug_util_unittest.cc', + 'debug/leak_tracker_unittest.cc', + 'debug/stack_trace_unittest.cc', + 'debug/trace_event_win_unittest.cc', 'dir_reader_posix_unittest.cc', 'environment_unittest.cc', 'event_trace_consumer_win_unittest.cc', @@ -97,7 +99,6 @@ 'json/json_writer_unittest.cc', 'json/string_escape_unittest.cc', 'lazy_instance_unittest.cc', - 'leak_tracker_unittest.cc', 'linked_list_unittest.cc', 'linked_ptr_unittest.cc', 'lock_unittest.cc', @@ -150,7 +151,6 @@ 'time_win_unittest.cc', 'timer_unittest.cc', 'tools_sanity_unittest.cc', - 'trace_event_win_unittest.cc', 'tracked_objects_unittest.cc', 'tuple_unittest.cc', 'utf_offset_string_conversions_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index d0fa20b..9a32325 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -58,8 +58,19 @@ 'debug_util.cc', 'debug_util.h', 'debug_util_mac.cc', - 'debug_util_posix.cc', - 'debug_util_win.cc', + 'debug/debugger.cc', + 'debug/debugger.h', + 'debug/debugger_posix.cc', + 'debug/debugger_win.cc', + 'debug/leak_annotations.h', + 'debug/leak_tracker.h', + 'debug/stack_trace.cc', + 'debug/stack_trace.h', + 'debug/stack_trace_posix.cc', + 'debug/stack_trace_win.cc', + 'debug/trace_event_win.cc', + 'debug/trace_event.cc', + 'debug/trace_event.h', 'dir_reader_fallback.h', 'dir_reader_linux.h', 'dir_reader_posix.h', @@ -104,8 +115,6 @@ 'json/string_escape.h', 'lazy_instance.cc', 'lazy_instance.h', - 'leak_annotations.h', - 'leak_tracker.h', 'linked_list.h', 'linked_ptr.h', 'lock.cc', @@ -259,9 +268,6 @@ 'time_win.cc', 'timer.cc', 'timer.h', - 'trace_event_win.cc', - 'trace_event.cc', - 'trace_event.h', 'tracked.cc', 'tracked.h', 'tracked_objects.cc', @@ -378,7 +384,7 @@ # regression to page cycler moz. 'sha1_win.cc', 'string16.cc', - 'trace_event.cc', + 'debug/trace_event.cc', ], },], ], diff --git a/base/crypto/rsa_private_key_nss.cc b/base/crypto/rsa_private_key_nss.cc index 13e4f1f..7786521 100644 --- a/base/crypto/rsa_private_key_nss.cc +++ b/base/crypto/rsa_private_key_nss.cc @@ -10,7 +10,7 @@ #include <list> -#include "base/leak_annotations.h" +#include "base/debug/leak_annotations.h" #include "base/logging.h" #include "base/nss_util.h" #include "base/nss_util_internal.h" diff --git a/base/debug/debugger.cc b/base/debug/debugger.cc new file mode 100644 index 0000000..9ca7e8d --- /dev/null +++ b/base/debug/debugger.cc @@ -0,0 +1,25 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/debugger.h" + +#include "base/platform_thread.h" + +namespace base { +namespace debug { + +bool WaitForDebugger(int wait_seconds, bool silent) { + for (int i = 0; i < wait_seconds * 10; ++i) { + if (BeingDebugged()) { + if (!silent) + BreakDebugger(); + return true; + } + PlatformThread::Sleep(100); + } + return false; +} + +} // namespace debug +} // namespace base diff --git a/base/debug/debugger.h b/base/debug/debugger.h new file mode 100644 index 0000000..008d77d --- /dev/null +++ b/base/debug/debugger.h @@ -0,0 +1,39 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a cross platform interface for helper functions related to +// debuggers. You should use this to test if you're running under a debugger, +// and if you would like to yield (breakpoint) into the debugger. + +#ifndef BASE_DEBUG_DEBUGGER_H +#define BASE_DEBUG_DEBUGGER_H +#pragma once + +namespace base { +namespace debug { + +// Starts the registered system-wide JIT debugger to attach it to specified +// process. +bool SpawnDebuggerOnProcess(unsigned process_id); + +// Waits wait_seconds seconds for a debugger to attach to the current process. +// When silent is false, an exception is thrown when a debugger is detected. +bool WaitForDebugger(int wait_seconds, bool silent); + +// Returns true if the given process is being run under a debugger. +// +// On OS X, the underlying mechanism doesn't work when the sandbox is enabled. +// To get around this, this function caches its value. +// +// WARNING: Because of this, on OS X, a call MUST be made to this function +// BEFORE the sandbox is enabled. +bool BeingDebugged(); + +// Break into the debugger, assumes a debugger is present. +void BreakDebugger(); + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_DEBUGGER_H diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc new file mode 100644 index 0000000..a5ab066 --- /dev/null +++ b/base/debug/debugger_posix.cc @@ -0,0 +1,165 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/debugger.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/types.h> +#include <unistd.h> + +#include <string> +#include <vector> + +#if defined(__GLIBCXX__) +#include <cxxabi.h> +#endif + +#if defined(OS_MACOSX) +#include <AvailabilityMacros.h> +#endif + +#include <iostream> + +#include "base/basictypes.h" +#include "base/compat_execinfo.h" +#include "base/eintr_wrapper.h" +#include "base/logging.h" +#include "base/safe_strerror_posix.h" +#include "base/scoped_ptr.h" +#include "base/string_piece.h" +#include "base/stringprintf.h" + +#if defined(USE_SYMBOLIZE) +#include "base/third_party/symbolize/symbolize.h" +#endif + +namespace base { +namespace debug { + +bool SpawnDebuggerOnProcess(unsigned /* process_id */) { + NOTIMPLEMENTED(); + return false; +} + +#if defined(OS_MACOSX) + +// Based on Apple's recommended method as described in +// http://developer.apple.com/qa/qa2004/qa1361.html +bool BeingDebugged() { + // If the process is sandboxed then we can't use the sysctl, so cache the + // value. + static bool is_set = false; + static bool being_debugged = false; + + if (is_set) { + return being_debugged; + } + + // Initialize mib, which tells sysctl what info we want. In this case, + // we're looking for information about a specific process ID. + int mib[] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_PID, + getpid() + }; + + // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and + // binary interfaces may change. + struct kinfo_proc info; + size_t info_size = sizeof(info); + + int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0); + DCHECK_EQ(sysctl_result, 0); + if (sysctl_result != 0) { + is_set = true; + being_debugged = false; + return being_debugged; + } + + // This process is being debugged if the P_TRACED flag is set. + is_set = true; + being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; + return being_debugged; +} + +#elif defined(OS_LINUX) + +// We can look in /proc/self/status for TracerPid. We are likely used in crash +// handling, so we are careful not to use the heap or have side effects. +// Another option that is common is to try to ptrace yourself, but then we +// can't detach without forking(), and that's not so great. +// static +bool BeingDebugged() { + int status_fd = open("/proc/self/status", O_RDONLY); + if (status_fd == -1) + return false; + + // We assume our line will be in the first 1024 characters and that we can + // read this much all at once. In practice this will generally be true. + // This simplifies and speeds up things considerably. + char buf[1024]; + + ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf))); + if (HANDLE_EINTR(close(status_fd)) < 0) + return false; + + if (num_read <= 0) + return false; + + StringPiece status(buf, num_read); + StringPiece tracer("TracerPid:\t"); + + StringPiece::size_type pid_index = status.find(tracer); + if (pid_index == StringPiece::npos) + return false; + + // Our pid is 0 without a debugger, assume this for any pid starting with 0. + pid_index += tracer.size(); + return pid_index < status.size() && status[pid_index] != '0'; +} + +#elif defined(OS_FREEBSD) + +bool DebugUtil::BeingDebugged() { + // TODO(benl): can we determine this under FreeBSD? + NOTIMPLEMENTED(); + return false; +} + +#endif // defined(OS_FREEBSD) + +// We want to break into the debugger in Debug mode, and cause a crash dump in +// Release mode. Breakpad behaves as follows: +// +// +-------+-----------------+-----------------+ +// | OS | Dump on SIGTRAP | Dump on SIGABRT | +// +-------+-----------------+-----------------+ +// | Linux | N | Y | +// | Mac | Y | N | +// +-------+-----------------+-----------------+ +// +// Thus we do the following: +// Linux: Debug mode, send SIGTRAP; Release mode, send SIGABRT. +// Mac: Always send SIGTRAP. + +#if defined(NDEBUG) && !defined(OS_MACOSX) +#define DEBUG_BREAK() abort() +#elif defined(ARCH_CPU_ARM_FAMILY) +#define DEBUG_BREAK() asm("bkpt 0") +#else +#define DEBUG_BREAK() asm("int3") +#endif + +void BreakDebugger() { + DEBUG_BREAK(); +} + +} // namespace debug +} // namespace base diff --git a/base/debug/debugger_win.cc b/base/debug/debugger_win.cc new file mode 100644 index 0000000..d1d47cd --- /dev/null +++ b/base/debug/debugger_win.cc @@ -0,0 +1,112 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/debugger.h" + +#include <windows.h> +#include <dbghelp.h> + +#include "base/basictypes.h" +#include "base/debug_util.h" +#include "base/logging.h" + +namespace base { +namespace debug { + +namespace { + +// Minimalist key reader. +// Note: Does not use the CRT. +bool RegReadString(HKEY root, const wchar_t* subkey, + const wchar_t* value_name, wchar_t* buffer, int* len) { + HKEY key = NULL; + DWORD res = RegOpenKeyEx(root, subkey, 0, KEY_READ, &key); + if (ERROR_SUCCESS != res || key == NULL) + return false; + + DWORD type = 0; + DWORD buffer_size = *len * sizeof(wchar_t); + // We don't support REG_EXPAND_SZ. + res = RegQueryValueEx(key, value_name, NULL, &type, + reinterpret_cast<BYTE*>(buffer), &buffer_size); + if (ERROR_SUCCESS == res && buffer_size != 0 && type == REG_SZ) { + // Make sure the buffer is NULL terminated. + buffer[*len - 1] = 0; + *len = lstrlen(buffer); + RegCloseKey(key); + return true; + } + RegCloseKey(key); + return false; +} + +// Replaces each "%ld" in input per a value. Not efficient but it works. +// Note: Does not use the CRT. +bool StringReplace(const wchar_t* input, int value, wchar_t* output, + int output_len) { + memset(output, 0, output_len*sizeof(wchar_t)); + int input_len = lstrlen(input); + + for (int i = 0; i < input_len; ++i) { + int current_output_len = lstrlen(output); + + if (input[i] == L'%' && input[i + 1] == L'l' && input[i + 2] == L'd') { + // Make sure we have enough place left. + if ((current_output_len + 12) >= output_len) + return false; + + // Cheap _itow(). + wsprintf(output+current_output_len, L"%d", value); + i += 2; + } else { + if (current_output_len >= output_len) + return false; + output[current_output_len] = input[i]; + } + } + return true; +} + +} // namespace + +// Note: Does not use the CRT. +bool SpawnDebuggerOnProcess(unsigned process_id) { + wchar_t reg_value[1026]; + int len = arraysize(reg_value); + if (RegReadString(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", + L"Debugger", reg_value, &len)) { + wchar_t command_line[1026]; + if (StringReplace(reg_value, process_id, command_line, + arraysize(command_line))) { + // We don't mind if the debugger is present because it will simply fail + // to attach to this process. + STARTUPINFO startup_info = {0}; + startup_info.cb = sizeof(startup_info); + PROCESS_INFORMATION process_info = {0}; + + if (CreateProcess(NULL, command_line, NULL, NULL, FALSE, 0, NULL, NULL, + &startup_info, &process_info)) { + CloseHandle(process_info.hThread); + WaitForInputIdle(process_info.hProcess, 10000); + CloseHandle(process_info.hProcess); + return true; + } + } + } + return false; +} + +bool BeingDebugged() { + return ::IsDebuggerPresent() != 0; +} + +void BreakDebugger() { + if (DebugUtil::AreDialogsSuppressed()) + _exit(1); + __debugbreak(); +} + +} // namespace debug +} // namespace base diff --git a/base/leak_annotations.h b/base/debug/leak_annotations.h index dd8280b..e1086fe 100644 --- a/base/leak_annotations.h +++ b/base/debug/leak_annotations.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_LEAK_ANNOTATIONS_H_ -#define BASE_LEAK_ANNOTATIONS_H_ +#ifndef BASE_DEBUG_LEAK_ANNOTATIONS_H_ +#define BASE_DEBUG_LEAK_ANNOTATIONS_H_ #pragma once #include "build/build_config.h" @@ -25,4 +25,4 @@ #endif -#endif // BASE_LEAK_ANNOTATIONS_H_ +#endif // BASE_DEBUG_LEAK_ANNOTATIONS_H_ diff --git a/base/leak_tracker.h b/base/debug/leak_tracker.h index 96d8773..8af82a9 100644 --- a/base/leak_tracker.h +++ b/base/debug/leak_tracker.h @@ -1,9 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_LEAK_TRACKER_H_ -#define BASE_LEAK_TRACKER_H_ +#ifndef BASE_DEBUG_LEAK_TRACKER_H_ +#define BASE_DEBUG_LEAK_TRACKER_H_ #pragma once // Only enable leak tracking in debug builds. @@ -12,7 +12,7 @@ #endif #ifdef ENABLE_LEAK_TRACKER -#include "base/debug_util.h" +#include "base/debug/stack_trace.h" #include "base/linked_list.h" #include "base/logging.h" #endif // ENABLE_LEAK_TRACKER @@ -45,6 +45,7 @@ // If ENABLE_LEAK_TRACKER is not defined, then the check has no effect. namespace base { +namespace debug { #ifndef ENABLE_LEAK_TRACKER @@ -127,6 +128,7 @@ class LeakTracker : public LinkNode<LeakTracker<T> > { #endif // ENABLE_LEAK_TRACKER +} // namespace debug } // namespace base -#endif // BASE_LEAK_TRACKER_H_ +#endif // BASE_DEBUG_LEAK_TRACKER_H_ diff --git a/base/debug/leak_tracker_unittest.cc b/base/debug/leak_tracker_unittest.cc new file mode 100644 index 0000000..2e6a9a5 --- /dev/null +++ b/base/debug/leak_tracker_unittest.cc @@ -0,0 +1,113 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/leak_tracker.h" +#include "base/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace debug { + +namespace { + +class ClassA { + private: + LeakTracker<ClassA> leak_tracker_; +}; + +class ClassB { + private: + LeakTracker<ClassB> leak_tracker_; +}; + +#ifndef ENABLE_LEAK_TRACKER + +// If leak tracking is disabled, we should do nothing. +TEST(LeakTrackerTest, NotEnabled) { + EXPECT_EQ(-1, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(-1, LeakTracker<ClassB>::NumLiveInstances()); + + // Use scoped_ptr so compiler doesn't complain about unused variables. + scoped_ptr<ClassA> a1(new ClassA); + scoped_ptr<ClassB> b1(new ClassB); + scoped_ptr<ClassB> b2(new ClassB); + + EXPECT_EQ(-1, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(-1, LeakTracker<ClassB>::NumLiveInstances()); +} + +#else + +TEST(LeakTrackerTest, Basic) { + { + ClassA a1; + + EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances()); + + ClassB b1; + ClassB b2; + + EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances()); + + scoped_ptr<ClassA> a2(new ClassA); + + EXPECT_EQ(2, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances()); + + a2.reset(); + + EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances()); + } + + EXPECT_EQ(0, LeakTracker<ClassA>::NumLiveInstances()); + EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances()); +} + +// Try some orderings of create/remove to hit different cases in the linked-list +// assembly. +TEST(LeakTrackerTest, LinkedList) { + EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances()); + + scoped_ptr<ClassA> a1(new ClassA); + scoped_ptr<ClassA> a2(new ClassA); + scoped_ptr<ClassA> a3(new ClassA); + scoped_ptr<ClassA> a4(new ClassA); + + EXPECT_EQ(4, LeakTracker<ClassA>::NumLiveInstances()); + + // Remove the head of the list (a1). + a1.reset(); + EXPECT_EQ(3, LeakTracker<ClassA>::NumLiveInstances()); + + // Remove the tail of the list (a4). + a4.reset(); + EXPECT_EQ(2, LeakTracker<ClassA>::NumLiveInstances()); + + // Append to the new tail of the list (a3). + scoped_ptr<ClassA> a5(new ClassA); + EXPECT_EQ(3, LeakTracker<ClassA>::NumLiveInstances()); + + a2.reset(); + a3.reset(); + + EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); + + a5.reset(); + EXPECT_EQ(0, LeakTracker<ClassA>::NumLiveInstances()); +} + +TEST(LeakTrackerTest, NoOpCheckForLeaks) { + // There are no live instances of ClassA, so this should do nothing. + LeakTracker<ClassA>::CheckForLeaks(); +} + +#endif // ENABLE_LEAK_TRACKER + +} // namespace + +} // namespace debug +} // namespace base diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc new file mode 100644 index 0000000..5be4c5c --- /dev/null +++ b/base/debug/stack_trace.cc @@ -0,0 +1,21 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/stack_trace.h" + +namespace base { +namespace debug { + +StackTrace::~StackTrace() { +} + +const void *const *StackTrace::Addresses(size_t* count) { + *count = count_; + if (count_) + return trace_; + return NULL; +} + +} // namespace debug +} // namespace base diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h new file mode 100644 index 0000000..8afc32c --- /dev/null +++ b/base/debug/stack_trace.h @@ -0,0 +1,63 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_STACK_TRACE_H_ +#define BASE_DEBUG_STACK_TRACE_H_ +#pragma once + +#include <iosfwd> + +#include "build/build_config.h" + +#if defined(OS_WIN) +struct _EXCEPTION_POINTERS; +#endif + +namespace base { +namespace debug { + +// A stacktrace can be helpful in debugging. For example, you can include a +// stacktrace member in a object (probably around #ifndef NDEBUG) so that you +// can later see where the given object was created from. +class StackTrace { + public: + // Creates a stacktrace from the current location. + StackTrace(); + +#if defined(OS_WIN) + // Creates a stacktrace for an exception. + // Note: this function will throw an import not found (StackWalk64) exception + // on system without dbghelp 5.1. + StackTrace(_EXCEPTION_POINTERS* exception_pointers); +#endif + + // Copying and assignment are allowed with the default functions. + + ~StackTrace(); + + // Gets an array of instruction pointer values. |*count| will be set to the + // number of elements in the returned array. + const void* const* Addresses(size_t* count); + + // Prints a backtrace to stderr + void PrintBacktrace(); + + // Resolves backtrace to symbols and write to stream. + void OutputToStream(std::ostream* os); + + private: + // From http://msdn.microsoft.com/en-us/library/bb204633.aspx, + // the sum of FramesToSkip and FramesToCapture must be less than 63, + // so set it to 62. Even if on POSIX it could be a larger value, it usually + // doesn't give much more information. + static const int kMaxTraces = 62; + + void* trace_[kMaxTraces]; + int count_; +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_STACK_TRACE_H_ diff --git a/base/debug_util_posix.cc b/base/debug/stack_trace_posix.cc index 7d7aca4..e4b0ef2 100644 --- a/base/debug_util_posix.cc +++ b/base/debug/stack_trace_posix.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug_util.h" +#include "base/debug/stack_trace.h" #include <errno.h> #include <fcntl.h> @@ -39,7 +39,11 @@ #include "base/third_party/symbolize/symbolize.h" #endif +namespace base { +namespace debug { + namespace { + // The prefix used for mangled symbols, per the Itanium C++ ABI: // http://www.codesourcery.com/cxx-abi/abi.html#mangling const char kMangledSymbolPrefix[] = "_Z"; @@ -145,128 +149,6 @@ bool GetBacktraceStrings(void **trace, int size, } // namespace -// static -bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) { - NOTIMPLEMENTED(); - return false; -} - -#if defined(OS_MACOSX) - -// Based on Apple's recommended method as described in -// http://developer.apple.com/qa/qa2004/qa1361.html -// static -bool DebugUtil::BeingDebugged() { - // If the process is sandboxed then we can't use the sysctl, so cache the - // value. - static bool is_set = false; - static bool being_debugged = false; - - if (is_set) { - return being_debugged; - } - - // Initialize mib, which tells sysctl what info we want. In this case, - // we're looking for information about a specific process ID. - int mib[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID, - getpid() - }; - - // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and - // binary interfaces may change. - struct kinfo_proc info; - size_t info_size = sizeof(info); - - int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0); - DCHECK_EQ(sysctl_result, 0); - if (sysctl_result != 0) { - is_set = true; - being_debugged = false; - return being_debugged; - } - - // This process is being debugged if the P_TRACED flag is set. - is_set = true; - being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0; - return being_debugged; -} - -#elif defined(OS_LINUX) - -// We can look in /proc/self/status for TracerPid. We are likely used in crash -// handling, so we are careful not to use the heap or have side effects. -// Another option that is common is to try to ptrace yourself, but then we -// can't detach without forking(), and that's not so great. -// static -bool DebugUtil::BeingDebugged() { - int status_fd = open("/proc/self/status", O_RDONLY); - if (status_fd == -1) - return false; - - // We assume our line will be in the first 1024 characters and that we can - // read this much all at once. In practice this will generally be true. - // This simplifies and speeds up things considerably. - char buf[1024]; - - ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf))); - if (HANDLE_EINTR(close(status_fd)) < 0) - return false; - - if (num_read <= 0) - return false; - - base::StringPiece status(buf, num_read); - base::StringPiece tracer("TracerPid:\t"); - - base::StringPiece::size_type pid_index = status.find(tracer); - if (pid_index == base::StringPiece::npos) - return false; - - // Our pid is 0 without a debugger, assume this for any pid starting with 0. - pid_index += tracer.size(); - return pid_index < status.size() && status[pid_index] != '0'; -} - -#elif defined(OS_FREEBSD) - -bool DebugUtil::BeingDebugged() { - // TODO(benl): can we determine this under FreeBSD? - NOTIMPLEMENTED(); - return false; -} - -#endif // defined(OS_FREEBSD) - -// We want to break into the debugger in Debug mode, and cause a crash dump in -// Release mode. Breakpad behaves as follows: -// -// +-------+-----------------+-----------------+ -// | OS | Dump on SIGTRAP | Dump on SIGABRT | -// +-------+-----------------+-----------------+ -// | Linux | N | Y | -// | Mac | Y | N | -// +-------+-----------------+-----------------+ -// -// Thus we do the following: -// Linux: Debug mode, send SIGTRAP; Release mode, send SIGABRT. -// Mac: Always send SIGTRAP. - -#if defined(NDEBUG) && !defined(OS_MACOSX) -#define DEBUG_BREAK() abort() -#elif defined(ARCH_CPU_ARM_FAMILY) -#define DEBUG_BREAK() asm("bkpt 0") -#else -#define DEBUG_BREAK() asm("int3") -#endif - -// static -void DebugUtil::BreakDebugger() { - DEBUG_BREAK(); -} - StackTrace::StackTrace() { #if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 if (backtrace == NULL) { @@ -312,3 +194,6 @@ void StackTrace::OutputToStream(std::ostream* os) { (*os) << "\t" << trace_strings[i] << "\n"; } } + +} // namespace debug +} // namespace base diff --git a/base/debug_util_unittest.cc b/base/debug/stack_trace_unittest.cc index 8d0deab..e8e1e19 100644 --- a/base/debug_util_unittest.cc +++ b/base/debug/stack_trace_unittest.cc @@ -5,10 +5,13 @@ #include <sstream> #include <string> -#include "base/debug_util.h" +#include "base/debug/stack_trace.h" #include "base/logging.h" #include "testing/gtest/include/gtest/gtest.h" +namespace base { +namespace debug { + // Note: On Linux, this test currently only fully works on Debug builds. // See comments in the #ifdef soup if you intend to change this. // Flaky, crbug.com/32070. @@ -104,3 +107,6 @@ TEST(StackTrace, DebugOutputToStream) { TEST(StackTrace, DebugPrintBacktrace) { StackTrace().PrintBacktrace(); } + +} // namespace debug +} // namespace base diff --git a/base/debug_util_win.cc b/base/debug/stack_trace_win.cc index b60ba31..653d234 100644 --- a/base/debug_util_win.cc +++ b/base/debug/stack_trace_win.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug_util.h" +#include "base/debug/stack_trace.h" #include <windows.h> #include <dbghelp.h> @@ -14,59 +14,10 @@ #include "base/logging.h" #include "base/singleton.h" -namespace { - -// Minimalist key reader. -// Note: Does not use the CRT. -bool RegReadString(HKEY root, const wchar_t* subkey, - const wchar_t* value_name, wchar_t* buffer, int* len) { - HKEY key = NULL; - DWORD res = RegOpenKeyEx(root, subkey, 0, KEY_READ, &key); - if (ERROR_SUCCESS != res || key == NULL) - return false; - - DWORD type = 0; - DWORD buffer_size = *len * sizeof(wchar_t); - // We don't support REG_EXPAND_SZ. - res = RegQueryValueEx(key, value_name, NULL, &type, - reinterpret_cast<BYTE*>(buffer), &buffer_size); - if (ERROR_SUCCESS == res && buffer_size != 0 && type == REG_SZ) { - // Make sure the buffer is NULL terminated. - buffer[*len - 1] = 0; - *len = lstrlen(buffer); - RegCloseKey(key); - return true; - } - RegCloseKey(key); - return false; -} - -// Replaces each "%ld" in input per a value. Not efficient but it works. -// Note: Does not use the CRT. -bool StringReplace(const wchar_t* input, int value, wchar_t* output, - int output_len) { - memset(output, 0, output_len*sizeof(wchar_t)); - int input_len = lstrlen(input); - - for (int i = 0; i < input_len; ++i) { - int current_output_len = lstrlen(output); +namespace base { +namespace debug { - if (input[i] == L'%' && input[i + 1] == L'l' && input[i + 2] == L'd') { - // Make sure we have enough place left. - if ((current_output_len + 12) >= output_len) - return false; - - // Cheap _itow(). - wsprintf(output+current_output_len, L"%d", value); - i += 2; - } else { - if (current_output_len >= output_len) - return false; - output[current_output_len] = input[i]; - } - } - return true; -} +namespace { // SymbolContext is a threadsafe singleton that wraps the DbgHelp Sym* family // of functions. The Sym* family of functions may only be invoked by one @@ -184,47 +135,6 @@ class SymbolContext { } // namespace -// Note: Does not use the CRT. -bool DebugUtil::SpawnDebuggerOnProcess(unsigned process_id) { - wchar_t reg_value[1026]; - int len = arraysize(reg_value); - if (RegReadString(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", - L"Debugger", reg_value, &len)) { - wchar_t command_line[1026]; - if (StringReplace(reg_value, process_id, command_line, - arraysize(command_line))) { - // We don't mind if the debugger is present because it will simply fail - // to attach to this process. - STARTUPINFO startup_info = {0}; - startup_info.cb = sizeof(startup_info); - PROCESS_INFORMATION process_info = {0}; - - if (CreateProcess(NULL, command_line, NULL, NULL, FALSE, 0, NULL, NULL, - &startup_info, &process_info)) { - CloseHandle(process_info.hThread); - WaitForInputIdle(process_info.hProcess, 10000); - CloseHandle(process_info.hProcess); - return true; - } - } - } - return false; -} - -// static -bool DebugUtil::BeingDebugged() { - return ::IsDebuggerPresent() != 0; -} - -// static -void DebugUtil::BreakDebugger() { - if (suppress_dialogs_) - _exit(1); - - __debugbreak(); -} - StackTrace::StackTrace() { // When walking our own stack, use CaptureStackBackTrace(). count_ = CaptureStackBackTrace(0, arraysize(trace_), trace_, NULL); @@ -282,3 +192,6 @@ void StackTrace::OutputToStream(std::ostream* os) { context->OutputTraceToStream(trace_, count_, os); } } + +} // namespace debug +} // namespace base diff --git a/base/trace_event.cc b/base/debug/trace_event.cc index 6388c8c..4d1d315 100644 --- a/base/trace_event.cc +++ b/base/debug/trace_event.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/trace_event.h" +#include "base/debug/trace_event.h" #include "base/format_macros.h" #include "base/file_path.h" @@ -17,6 +17,7 @@ #define USE_UNRELIABLE_NOW namespace base { +namespace debug { static const char* kEventTypeNames[] = { "BEGIN", @@ -161,4 +162,5 @@ void TraceLog::Log(const std::string& msg) { fprintf(log_file_, "%s", msg.c_str()); } -} // namespace base +} // namespace debug +} // namespace base diff --git a/base/trace_event.h b/base/debug/trace_event.h index caa260d..49ba4bd 100644 --- a/base/trace_event.h +++ b/base/debug/trace_event.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,8 +12,8 @@ // trace report. In the future, it may use another mechansim to facilitate // real-time analysis. -#ifndef BASE_TRACE_EVENT_H_ -#define BASE_TRACE_EVENT_H_ +#ifndef BASE_DEBUG_TRACE_EVENT_H_ +#define BASE_DEBUG_TRACE_EVENT_H_ #pragma once #include "build/build_config.h" @@ -26,7 +26,7 @@ // value of the CHROMIUM_ENABLE_TRACE_EVENT define. The Windows implementation // is controlled by Event Tracing for Windows, which will turn tracing on only // if there is someone listening for the events it generates. -#include "base/trace_event_win.h" +#include "base/debug/trace_event_win.h" #else // defined(OS_WIN) #include <string> @@ -52,38 +52,41 @@ // Record that an event (of name, id) has begun. All BEGIN events should have // corresponding END events with a matching (name, id). #define TRACE_EVENT_BEGIN(name, id, extra) \ - Singleton<base::TraceLog>::get()->Trace(name, \ - base::TraceLog::EVENT_BEGIN, \ - reinterpret_cast<const void*>(id), \ - extra, \ - __FILE__, \ - __LINE__) + Singleton<base::debug::TraceLog>::get()->Trace( \ + name, \ + base::debug::TraceLog::EVENT_BEGIN, \ + reinterpret_cast<const void*>(id), \ + extra, \ + __FILE__, \ + __LINE__) // Record that an event (of name, id) has ended. All END events should have // corresponding BEGIN events with a matching (name, id). #define TRACE_EVENT_END(name, id, extra) \ - Singleton<base::TraceLog>::get()->Trace(name, \ - base::TraceLog::EVENT_END, \ - reinterpret_cast<const void*>(id), \ - extra, \ - __FILE__, \ - __LINE__) + Singleton<base::debug::TraceLog>::get()->Trace( \ + name, \ + base::debug::TraceLog::EVENT_END, \ + reinterpret_cast<const void*>(id), \ + extra, \ + __FILE__, \ + __LINE__) // Record that an event (of name, id) with no duration has happened. #define TRACE_EVENT_INSTANT(name, id, extra) \ - Singleton<base::TraceLog>::get()->Trace(name, \ - base::TraceLog::EVENT_INSTANT, \ - reinterpret_cast<const void*>(id), \ - extra, \ - __FILE__, \ - __LINE__) + Singleton<base::debug::TraceLog>::get()->Trace( \ + name, \ + base::debug::TraceLog::EVENT_INSTANT, \ + reinterpret_cast<const void*>(id), \ + extra, \ + __FILE__, \ + __LINE__) #endif // CHROMIUM_ENABLE_TRACE_EVENT namespace base { + class ProcessMetrics; -} -namespace base { +namespace debug { class TraceLog { public: @@ -136,7 +139,9 @@ class TraceLog { RepeatingTimer<TraceLog> timer_; }; -} // namespace base +} // namespace debug +} // namespace base + #endif // defined(OS_WIN) -#endif // BASE_TRACE_EVENT_H_ +#endif // BASE_DEBUG_TRACE_EVENT_H_ diff --git a/base/trace_event_win.cc b/base/debug/trace_event_win.cc index 7217283..129a992 100644 --- a/base/trace_event_win.cc +++ b/base/debug/trace_event_win.cc @@ -1,13 +1,15 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/trace_event_win.h" + +#include "base/debug/trace_event_win.h" #include "base/logging.h" #include "base/singleton.h" #include <initguid.h> // NOLINT namespace base { +namespace debug { // {3DADA31D-19EF-4dc1-B345-037927193422} const GUID kChromeTraceProviderName = { @@ -22,7 +24,7 @@ const GUID kTraceEventClass64 = { 0x97be602d, 0x2930, 0x4ac3, 0x80, 0x46, 0xb6, 0x76, 0x3b, 0x63, 0x1d, 0xfe}; -TraceLog::TraceLog() : EtwTraceProvider(base::kChromeTraceProviderName) { +TraceLog::TraceLog() : EtwTraceProvider(kChromeTraceProviderName) { Register(); } @@ -36,7 +38,7 @@ bool TraceLog::StartTracing() { void TraceLog::TraceEvent(const char* name, size_t name_len, - base::TraceLog::EventType type, + EventType type, const void* id, const char* extra, size_t extra_len) { @@ -48,24 +50,24 @@ void TraceLog::TraceEvent(const char* name, EtwEventType etw_type = 0; switch (type) { - case base::TraceLog::EVENT_BEGIN: - etw_type = base::kTraceEventTypeBegin; + case TraceLog::EVENT_BEGIN: + etw_type = kTraceEventTypeBegin; break; - case base::TraceLog::EVENT_END: - etw_type = base::kTraceEventTypeEnd; + case TraceLog::EVENT_END: + etw_type = kTraceEventTypeEnd; break; - case base::TraceLog::EVENT_INSTANT: - etw_type = base::kTraceEventTypeInstant; + case TraceLog::EVENT_INSTANT: + etw_type = kTraceEventTypeInstant; break; default: NOTREACHED() << "Unknown event type"; - etw_type = base::kTraceEventTypeInstant; + etw_type = kTraceEventTypeInstant; break; } - EtwMofEvent<5> event(base::kTraceEventClass32, + EtwMofEvent<5> event(kTraceEventClass32, etw_type, TRACE_LEVEL_INFORMATION); event.SetField(0, name_len + 1, name); @@ -74,7 +76,7 @@ void TraceLog::TraceEvent(const char* name, // See whether we're to capture a backtrace. void* backtrace[32]; - if (enable_flags() & base::CAPTURE_STACK_TRACE) { + if (enable_flags() & CAPTURE_STACK_TRACE) { DWORD hash = 0; DWORD depth = CaptureStackBackTrace(0, arraysize(backtrace), @@ -110,4 +112,5 @@ void TraceLog::Resurrect() { StaticMemorySingletonTraits<TraceLog>::Resurrect(); } +} // namespace debug } // namespace base diff --git a/base/trace_event_win.h b/base/debug/trace_event_win.h index 77ab3fb..669667b 100644 --- a/base/trace_event_win.h +++ b/base/debug/trace_event_win.h @@ -3,36 +3,40 @@ // found in the LICENSE file. // This file contains the Windows-specific declarations for trace_event.h. -#ifndef BASE_TRACE_EVENT_WIN_H_ -#define BASE_TRACE_EVENT_WIN_H_ +#ifndef BASE_DEBUG_TRACE_EVENT_WIN_H_ +#define BASE_DEBUG_TRACE_EVENT_WIN_H_ #pragma once #include <string> #include "base/event_trace_provider_win.h" #define TRACE_EVENT_BEGIN(name, id, extra) \ - base::TraceLog::Trace(name, \ - base::TraceLog::EVENT_BEGIN, \ - reinterpret_cast<const void*>(id), \ - extra); + base::debug::TraceLog::Trace( \ + name, \ + base::debug::TraceLog::EVENT_BEGIN, \ + reinterpret_cast<const void*>(id), \ + extra); #define TRACE_EVENT_END(name, id, extra) \ - base::TraceLog::Trace(name, \ - base::TraceLog::EVENT_END, \ - reinterpret_cast<const void*>(id), \ - extra); + base::debug::TraceLog::Trace( \ + name, \ + base::debug::TraceLog::EVENT_END, \ + reinterpret_cast<const void*>(id), \ + extra); #define TRACE_EVENT_INSTANT(name, id, extra) \ - base::TraceLog::Trace(name, \ - base::TraceLog::EVENT_INSTANT, \ - reinterpret_cast<const void*>(id), \ - extra); + base::debug::TraceLog::Trace( \ + name, \ + base::debug::TraceLog::EVENT_INSTANT, \ + reinterpret_cast<const void*>(id), \ + extra); // Fwd. template <typename Type> struct StaticMemorySingletonTraits; namespace base { +namespace debug { // This EtwTraceProvider subclass implements ETW logging // for the macros above on Windows. @@ -95,7 +99,7 @@ class TraceLog : public EtwTraceProvider { // string will be used. void TraceEvent(const char* name, size_t name_len, - base::TraceLog::EventType type, + EventType type, const void* id, const char* extra, size_t extra_len); @@ -141,6 +145,7 @@ enum TraceEventFlags { // Forward decl. struct TraceLogSingletonTraits; +} // nemspace debug } // namespace base -#endif // BASE_TRACE_EVENT_WIN_H_ +#endif // BASE_DEBUG_TRACE_EVENT_WIN_H_ diff --git a/base/trace_event_win_unittest.cc b/base/debug/trace_event_win_unittest.cc index 79a48e3..a818b9b 100644 --- a/base/trace_event_win_unittest.cc +++ b/base/debug/trace_event_win_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/trace_event.h" +#include "base/debug/trace_event.h" #include <strstream> @@ -16,7 +16,11 @@ #include "testing/gtest/include/gtest/gtest.h" #include <initguid.h> // NOLINT - must be last include. +namespace base { +namespace debug { + namespace { + using testing::_; using testing::AnyNumber; using testing::InSequence; @@ -81,7 +85,7 @@ class TraceEventTest: public testing::Test { } void SetUp() { - bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA; + bool is_xp = win::GetVersion() < base::win::VERSION_VISTA; if (is_xp) { // Tear down any dangling session from an earlier failing test. @@ -94,10 +98,10 @@ class TraceEventTest: public testing::Test { // start the private, in-proc session, but on XP we need the global // session created and the provider enabled before we register our // provider. - base::TraceLog* tracelog = NULL; + TraceLog* tracelog = NULL; if (!is_xp) { - base::TraceLog::Resurrect(); - tracelog = base::TraceLog::Get(); + TraceLog::Resurrect(); + tracelog = TraceLog::Get(); ASSERT_TRUE(tracelog != NULL); ASSERT_FALSE(tracelog->IsTracing()); } @@ -127,13 +131,13 @@ class TraceEventTest: public testing::Test { // Enable the TraceLog provider GUID. ASSERT_HRESULT_SUCCEEDED( - controller_.EnableProvider(base::kChromeTraceProviderName, + controller_.EnableProvider(kChromeTraceProviderName, TRACE_LEVEL_INFORMATION, 0)); if (is_xp) { - base::TraceLog::Resurrect(); - tracelog = base::TraceLog::Get(); + TraceLog::Resurrect(); + tracelog = TraceLog::Get(); } ASSERT_TRUE(tracelog != NULL); EXPECT_TRUE(tracelog->IsTracing()); @@ -186,7 +190,7 @@ class TraceEventTest: public testing::Test { private: // We want our singleton torn down after each test. - base::ShadowingAtExitManager at_exit_manager_; + ShadowingAtExitManager at_exit_manager_; EtwTraceController controller_; FilePath log_file_; TestEventConsumer consumer_; @@ -202,67 +206,67 @@ TEST_F(TraceEventTest, TraceLog) { InSequence in_sequence; // Full argument version, passing lengths explicitly. - base::TraceLog::Trace(kName, + TraceLog::Trace(kName, strlen(kName), - base::TraceLog::EVENT_BEGIN, + TraceLog::EVENT_BEGIN, kId, kExtra, strlen(kExtra)); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeBegin, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeBegin, kName, strlen(kName), kId, kExtra, strlen(kExtra)); // Const char* version. - base::TraceLog::Trace(static_cast<const char*>(kName), - base::TraceLog::EVENT_END, + TraceLog::Trace(static_cast<const char*>(kName), + TraceLog::EVENT_END, kId, static_cast<const char*>(kExtra)); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeEnd, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeEnd, kName, strlen(kName), kId, kExtra, strlen(kExtra)); // std::string extra version. - base::TraceLog::Trace(static_cast<const char*>(kName), - base::TraceLog::EVENT_INSTANT, + TraceLog::Trace(static_cast<const char*>(kName), + TraceLog::EVENT_INSTANT, kId, std::string(kExtra)); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeInstant, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeInstant, kName, strlen(kName), kId, kExtra, strlen(kExtra)); // Test for sanity on NULL inputs. - base::TraceLog::Trace(NULL, + TraceLog::Trace(NULL, 0, - base::TraceLog::EVENT_BEGIN, + TraceLog::EVENT_BEGIN, kId, NULL, 0); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeBegin, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeBegin, kEmpty, 0, kId, kEmpty, 0); - base::TraceLog::Trace(NULL, + TraceLog::Trace(NULL, -1, - base::TraceLog::EVENT_END, + TraceLog::EVENT_END, kId, NULL, -1); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeEnd, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeEnd, kEmpty, 0, kId, kEmpty, 0); @@ -277,25 +281,28 @@ TEST_F(TraceEventTest, Macros) { InSequence in_sequence; TRACE_EVENT_BEGIN(kName, kId, kExtra); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeBegin, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeBegin, kName, strlen(kName), kId, kExtra, strlen(kExtra)); TRACE_EVENT_END(kName, kId, kExtra); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeEnd, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeEnd, kName, strlen(kName), kId, kExtra, strlen(kExtra)); TRACE_EVENT_INSTANT(kName, kId, kExtra); - ExpectEvent(base::kTraceEventClass32, - base::kTraceEventTypeInstant, + ExpectEvent(kTraceEventClass32, + kTraceEventTypeInstant, kName, strlen(kName), kId, kExtra, strlen(kExtra)); PlayLog(); } + +} // namespace debug +} // namespace base diff --git a/base/debug_on_start.cc b/base/debug_on_start.cc index 9cabde5..15dab05 100644 --- a/base/debug_on_start.cc +++ b/base/debug_on_start.cc @@ -8,7 +8,7 @@ #include "base/base_switches.h" #include "base/basictypes.h" -#include "base/debug_util.h" +#include "base/debug/debugger.h" // Minimalist implementation to try to find a command line argument. We can use // kernel32 exported functions but not the CRT functions because we're too early @@ -56,13 +56,13 @@ int __cdecl DebugOnStart::Init() { // - Do a int3. // It will fails if we run in a sandbox. That is expected. - DebugUtil::SpawnDebuggerOnProcess(GetCurrentProcessId()); + base::debug::SpawnDebuggerOnProcess(GetCurrentProcessId()); // Wait for a debugger to come take us. - DebugUtil::WaitForDebugger(60, false); + base::debug::WaitForDebugger(60, false); } else if (FindArgument(GetCommandLine(), switches::kWaitForDebugger)) { // Wait for a debugger to come take us. - DebugUtil::WaitForDebugger(60, true); + base::debug::WaitForDebugger(60, true); } return 0; } diff --git a/base/debug_util.cc b/base/debug_util.cc index 21f5b70..4773de3 100644 --- a/base/debug_util.cc +++ b/base/debug_util.cc @@ -4,25 +4,4 @@ #include "base/debug_util.h" -#include "base/platform_thread.h" - bool DebugUtil::suppress_dialogs_ = false; - -bool DebugUtil::WaitForDebugger(int wait_seconds, bool silent) { - for (int i = 0; i < wait_seconds * 10; ++i) { - if (BeingDebugged()) { - if (!silent) - BreakDebugger(); - return true; - } - PlatformThread::Sleep(100); - } - return false; -} - -const void *const *StackTrace::Addresses(size_t* count) { - *count = count_; - if (count_) - return trace_; - return NULL; -} diff --git a/base/debug_util.h b/base/debug_util.h index a7dba3a..a643ccf 100644 --- a/base/debug_util.h +++ b/base/debug_util.h @@ -2,78 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This is a cross platform interface for helper functions related to debuggers. -// You should use this to test if you're running under a debugger, and if you -// would like to yield (breakpoint) into the debugger. - #ifndef BASE_DEBUG_UTIL_H_ #define BASE_DEBUG_UTIL_H_ #pragma once -#include <iosfwd> - -#include "base/basictypes.h" - -#if defined(OS_WIN) -struct _EXCEPTION_POINTERS; -#endif - -// A stacktrace can be helpful in debugging. For example, you can include a -// stacktrace member in a object (probably around #ifndef NDEBUG) so that you -// can later see where the given object was created from. -class StackTrace { - public: - // Creates a stacktrace from the current location - StackTrace(); - - // Note that the default copy constructor and assignment constructors - // are OK. - -#if defined(OS_WIN) - // Creates a stacktrace for an exception. - // Note: this function will throw an import not found (StackWalk64) exception - // on system without dbghelp 5.1. - StackTrace(_EXCEPTION_POINTERS* exception_pointers); -#endif - // Gets an array of instruction pointer values. - // count: (output) the number of elements in the returned array - const void *const *Addresses(size_t* count); - // Prints a backtrace to stderr - void PrintBacktrace(); - - // Resolves backtrace to symbols and write to stream. - void OutputToStream(std::ostream* os); - - private: - // From http://msdn.microsoft.com/en-us/library/bb204633.aspx, - // the sum of FramesToSkip and FramesToCapture must be less than 63, - // so set it to 62. Even if on POSIX it could be a larger value, it usually - // doesn't give much more information. - static const int MAX_TRACES = 62; - void* trace_[MAX_TRACES]; - int count_; -}; +#include "build/build_config.h" class DebugUtil { public: - // Starts the registered system-wide JIT debugger to attach it to specified - // process. - static bool SpawnDebuggerOnProcess(unsigned process_id); - - // Waits wait_seconds seconds for a debugger to attach to the current process. - // When silent is false, an exception is thrown when a debugger is detected. - static bool WaitForDebugger(int wait_seconds, bool silent); - - // Are we running under a debugger? - // On OS X, the underlying mechanism doesn't work when the sandbox is enabled. - // To get around this, this function caches its value. - // WARNING: Because of this, on OS X, a call MUST be made to this function - // BEFORE the sandbox is enabled. - static bool BeingDebugged(); - - // Break into the debugger, assumes a debugger is present. - static void BreakDebugger(); - #if defined(OS_MACOSX) // On Mac OS X, it can take a really long time for the OS crash handler to // process a Chrome crash when debugging symbols are available. This @@ -87,6 +23,10 @@ class DebugUtil { suppress_dialogs_ = true; } + static bool AreDialogsSuppressed() { + return suppress_dialogs_; + } + private: // If true, avoid displaying any dialogs that could cause problems // in non-interactive environments. diff --git a/base/debug_util_mac.cc b/base/debug_util_mac.cc index 78679f2..a4eed66 100644 --- a/base/debug_util_mac.cc +++ b/base/debug_util_mac.cc @@ -5,6 +5,7 @@ #include "base/debug_util.h" #include <signal.h> +#include <unistd.h> #include "base/basictypes.h" diff --git a/base/leak_tracker_unittest.cc b/base/leak_tracker_unittest.cc deleted file mode 100644 index 0217b17..0000000 --- a/base/leak_tracker_unittest.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/leak_tracker.h" -#include "base/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class ClassA { - private: - base::LeakTracker<ClassA> leak_tracker_; -}; - -class ClassB { - private: - base::LeakTracker<ClassB> leak_tracker_; -}; - -#ifndef ENABLE_LEAK_TRACKER - -// If leak tracking is disabled, we should do nothing. -TEST(LeakTrackerTest, NotEnabled) { - EXPECT_EQ(-1, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(-1, base::LeakTracker<ClassB>::NumLiveInstances()); - - // Use scoped_ptr so compiler doesn't complain about unused variables. - scoped_ptr<ClassA> a1(new ClassA); - scoped_ptr<ClassB> b1(new ClassB); - scoped_ptr<ClassB> b2(new ClassB); - - EXPECT_EQ(-1, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(-1, base::LeakTracker<ClassB>::NumLiveInstances()); -} - -#else - -TEST(LeakTrackerTest, Basic) { - { - ClassA a1; - - EXPECT_EQ(1, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(0, base::LeakTracker<ClassB>::NumLiveInstances()); - - ClassB b1; - ClassB b2; - - EXPECT_EQ(1, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(2, base::LeakTracker<ClassB>::NumLiveInstances()); - - scoped_ptr<ClassA> a2(new ClassA); - - EXPECT_EQ(2, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(2, base::LeakTracker<ClassB>::NumLiveInstances()); - - a2.reset(); - - EXPECT_EQ(1, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(2, base::LeakTracker<ClassB>::NumLiveInstances()); - } - - EXPECT_EQ(0, base::LeakTracker<ClassA>::NumLiveInstances()); - EXPECT_EQ(0, base::LeakTracker<ClassB>::NumLiveInstances()); -} - -// Try some orderings of create/remove to hit different cases in the linked-list -// assembly. -TEST(LeakTrackerTest, LinkedList) { - EXPECT_EQ(0, base::LeakTracker<ClassB>::NumLiveInstances()); - - scoped_ptr<ClassA> a1(new ClassA); - scoped_ptr<ClassA> a2(new ClassA); - scoped_ptr<ClassA> a3(new ClassA); - scoped_ptr<ClassA> a4(new ClassA); - - EXPECT_EQ(4, base::LeakTracker<ClassA>::NumLiveInstances()); - - // Remove the head of the list (a1). - a1.reset(); - EXPECT_EQ(3, base::LeakTracker<ClassA>::NumLiveInstances()); - - // Remove the tail of the list (a4). - a4.reset(); - EXPECT_EQ(2, base::LeakTracker<ClassA>::NumLiveInstances()); - - // Append to the new tail of the list (a3). - scoped_ptr<ClassA> a5(new ClassA); - EXPECT_EQ(3, base::LeakTracker<ClassA>::NumLiveInstances()); - - a2.reset(); - a3.reset(); - - EXPECT_EQ(1, base::LeakTracker<ClassA>::NumLiveInstances()); - - a5.reset(); - EXPECT_EQ(0, base::LeakTracker<ClassA>::NumLiveInstances()); -} - -TEST(LeakTrackerTest, NoOpCheckForLeaks) { - // There are no live instances of ClassA, so this should do nothing. - base::LeakTracker<ClassA>::CheckForLeaks(); -} - -#endif // ENABLE_LEAK_TRACKER - -} // namespace diff --git a/base/logging.cc b/base/logging.cc index 273162f..a6b52a7 100644 --- a/base/logging.cc +++ b/base/logging.cc @@ -42,7 +42,8 @@ typedef pthread_mutex_t* MutexHandle; #include "base/base_switches.h" #include "base/command_line.h" -#include "base/debug_util.h" +#include "base/debug/debugger.h" +#include "base/debug/stack_trace.h" #include "base/eintr_wrapper.h" #include "base/lock_impl.h" #if defined(OS_POSIX) @@ -220,7 +221,7 @@ class LoggingLock { #if DEBUG // Keep the error code for debugging int error = GetLastError(); // NOLINT - DebugUtil::BreakDebugger(); + base::debug::BreakDebugger(); #endif // Return nicely without putting initialized to true. return; @@ -580,7 +581,7 @@ LogMessage::~LogMessage() { #ifndef NDEBUG if (severity_ == LOG_FATAL) { // Include a stack trace on a fatal. - StackTrace trace; + base::debug::StackTrace trace; stream_ << std::endl; // Newline to separate from log message. trace.OutputToStream(&stream_); } @@ -637,8 +638,8 @@ LogMessage::~LogMessage() { if (severity_ == LOG_FATAL) { // display a message or break into the debugger on a fatal error - if (DebugUtil::BeingDebugged()) { - DebugUtil::BreakDebugger(); + if (base::debug::BeingDebugged()) { + base::debug::BreakDebugger(); } else { if (log_assert_handler) { // make a copy of the string for the handler out of paranoia @@ -653,7 +654,7 @@ LogMessage::~LogMessage() { DisplayDebugMessageInDialog(stream_.str()); #endif // Crash the process to generate a dump. - DebugUtil::BreakDebugger(); + base::debug::BreakDebugger(); } } } else if (severity_ == LOG_ERROR_REPORT) { @@ -792,7 +793,7 @@ void RawLog(int level, const char* message) { } if (level == LOG_FATAL) - DebugUtil::BreakDebugger(); + base::debug::BreakDebugger(); } } // namespace logging diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm index cae47bf..b167aa22 100644 --- a/base/process_util_mac.mm +++ b/base/process_util_mac.mm @@ -23,7 +23,7 @@ #include <new> #include <string> -#include "base/debug_util.h" +#include "base/debug/debugger.h" #include "base/eintr_wrapper.h" #include "base/logging.h" #include "base/string_util.h" @@ -166,7 +166,7 @@ bool ProcessIterator::CheckForNextProcess() { } bool NamedProcessIterator::IncludeEntry() { - return (base::SysWideToUTF8(executable_name_) == entry().exe_file() && + return (SysWideToUTF8(executable_name_) == entry().exe_file() && ProcessIterator::IncludeEntry()); } @@ -187,7 +187,7 @@ ProcessMetrics::ProcessMetrics(ProcessHandle process, last_time_(0), last_system_time_(0), port_provider_(port_provider) { - processor_count_ = base::SysInfo::NumberOfProcessors(); + processor_count_ = SysInfo::NumberOfProcessors(); } // static @@ -402,7 +402,7 @@ void* oom_killer_malloc(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_malloc(zone, size); if (!result && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -411,7 +411,7 @@ void* oom_killer_calloc(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_calloc(zone, num_items, size); if (!result && num_items && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -419,7 +419,7 @@ void* oom_killer_valloc(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_valloc(zone, size); if (!result && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -428,7 +428,7 @@ void* oom_killer_realloc(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_realloc(zone, ptr, size); if (!result && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -441,7 +441,7 @@ void* oom_killer_memalign(struct _malloc_zone_t* zone, // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). if (!result && size && alignment >= sizeof(void*) && (alignment & (alignment - 1)) == 0) { - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); } return result; } @@ -450,7 +450,7 @@ void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_malloc_purgeable(zone, size); if (!result && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -459,7 +459,7 @@ void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_calloc_purgeable(zone, num_items, size); if (!result && num_items && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -467,7 +467,7 @@ void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_valloc_purgeable(zone, size); if (!result && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -476,7 +476,7 @@ void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, size_t size) { void* result = g_old_realloc_purgeable(zone, ptr, size); if (!result && size) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -489,7 +489,7 @@ void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). if (!result && size && alignment >= sizeof(void*) && (alignment & (alignment - 1)) == 0) { - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); } return result; } @@ -497,7 +497,7 @@ void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, // === C++ operator new === void oom_killer_new() { - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); } // === Core Foundation CFAllocators === @@ -513,7 +513,7 @@ void* oom_killer_cfallocator_system_default(CFIndex alloc_size, void* info) { void* result = g_old_cfallocator_system_default(alloc_size, hint, info); if (!result) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -522,7 +522,7 @@ void* oom_killer_cfallocator_malloc(CFIndex alloc_size, void* info) { void* result = g_old_cfallocator_malloc(alloc_size, hint, info); if (!result) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -531,7 +531,7 @@ void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, void* info) { void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); if (!result) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } @@ -544,7 +544,7 @@ id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) { id result = g_old_allocWithZone(self, _cmd, zone); if (!result) - DebugUtil::BreakDebugger(); + debug::BreakDebugger(); return result; } diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc index b1dbabd..07e3125 100644 --- a/base/process_util_posix.cc +++ b/base/process_util_posix.cc @@ -18,7 +18,7 @@ #include "base/command_line.h" #include "base/compiler_specific.h" -#include "base/debug_util.h" +#include "base/debug/stack_trace.h" #include "base/dir_reader_posix.h" #include "base/eintr_wrapper.h" #include "base/logging.h" @@ -103,7 +103,7 @@ int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds, void StackDumpSignalHandler(int signal) { LOG(ERROR) << "Received signal " << signal; - StackTrace().PrintBacktrace(); + debug::StackTrace().PrintBacktrace(); _exit(1); } diff --git a/base/process_util_win.cc b/base/process_util_win.cc index 92077b1..097888e 100644 --- a/base/process_util_win.cc +++ b/base/process_util_win.cc @@ -13,7 +13,7 @@ #include <ios> #include "base/command_line.h" -#include "base/debug_util.h" +#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/scoped_ptr.h" @@ -40,7 +40,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter = NULL; // Prints the exception call stack. // This is the unit tests exception filter. long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) { - StackTrace(info).PrintBacktrace(); + debug::StackTrace(info).PrintBacktrace(); if (g_previous_filter) return g_previous_filter(info); return EXCEPTION_CONTINUE_SEARCH; @@ -155,7 +155,7 @@ bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level) { if (!level) return false; - if (base::win::GetVersion() < base::win::VERSION_VISTA) + if (win::GetVersion() < base::win::VERSION_VISTA) return false; HANDLE process_token; @@ -163,7 +163,7 @@ bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level) { &process_token)) return false; - base::win::ScopedHandle scoped_process_token(process_token); + win::ScopedHandle scoped_process_token(process_token); DWORD token_info_length = 0; if (GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0, @@ -326,8 +326,8 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) { } // Ensure we don't leak the handles. - base::win::ScopedHandle scoped_out_read(out_read); - base::win::ScopedHandle scoped_out_write(out_write); + win::ScopedHandle scoped_out_read(out_read); + win::ScopedHandle scoped_out_write(out_write); // Ensure the read handle to the pipe for STDOUT is not inherited. if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) { diff --git a/base/test/perf_test_suite.cc b/base/test/perf_test_suite.cc index b787add..232766a 100644 --- a/base/test/perf_test_suite.cc +++ b/base/test/perf_test_suite.cc @@ -5,7 +5,7 @@ #include "base/test/perf_test_suite.h" #include "base/command_line.h" -#include "base/debug_util.h" +#include "base/debug/debugger.h" #include "base/file_path.h" #include "base/path_service.h" #include "base/perftimer.h" @@ -34,7 +34,7 @@ void PerfTestSuite::Initialize() { // Raise to high priority to have more precise measurements. Since we don't // aim at 1% precision, it is not necessary to run at realtime level. - if (!DebugUtil::BeingDebugged()) + if (!base::debug::BeingDebugged()) base::RaiseProcessToHighPriority(); } diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc index f2e6069..7d25a60 100644 --- a/base/test/test_suite.cc +++ b/base/test/test_suite.cc @@ -10,6 +10,8 @@ #include "base/command_line.h" #include "base/debug_on_start.h" #include "base/debug_util.h" +#include "base/debug/debugger.h" +#include "base/debug/debugger.h" #include "base/file_path.h" #include "base/i18n/icu_util.h" #include "base/logging.h" @@ -191,7 +193,7 @@ void TestSuite::Initialize() { #endif // defined(OS_WIN) // In some cases, we do not want to see standard error dialogs. - if (!DebugUtil::BeingDebugged() && + if (!base::debug::BeingDebugged() && !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) { SuppressErrorDialogs(); DebugUtil::SuppressDialogs(); |