Index: base/debug/profiler.cc |
diff --git a/base/debug/profiler.cc b/base/debug/profiler.cc |
index b14120416eaf247da03592e2ffdc040b8090d6ef..825aa3828b06eaa66a67a1c909964721b07d5f0e 100644 |
--- a/base/debug/profiler.cc |
+++ b/base/debug/profiler.cc |
@@ -1,177 +1,217 @@ |
-// Copyright (c) 2012 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/profiler.h" |
- |
-#include <string> |
- |
-#include "base/process_util.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
- |
-#if defined(OS_WIN) |
-#include "base/win/pe_image.h" |
-#endif // defined(OS_WIN) |
- |
-#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) |
-#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h" |
-#endif |
- |
-namespace base { |
-namespace debug { |
- |
-#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) |
- |
-static int profile_count = 0; |
- |
-void StartProfiling(const std::string& name) { |
- ++profile_count; |
- std::string full_name(name); |
- std::string pid = StringPrintf("%d", GetCurrentProcId()); |
- std::string count = StringPrintf("%d", profile_count); |
- ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid); |
- ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count); |
- ProfilerStart(full_name.c_str()); |
-} |
- |
-void StopProfiling() { |
- ProfilerFlush(); |
- ProfilerStop(); |
-} |
- |
-void FlushProfiling() { |
- ProfilerFlush(); |
-} |
- |
-bool BeingProfiled() { |
- return ProfilingIsEnabledForAllThreads(); |
-} |
- |
-void RestartProfilingAfterFork() { |
- ProfilerRegisterThread(); |
-} |
- |
-#else |
- |
-void StartProfiling(const std::string& name) { |
-} |
- |
-void StopProfiling() { |
-} |
- |
-void FlushProfiling() { |
-} |
- |
-bool BeingProfiled() { |
- return false; |
-} |
- |
-void RestartProfilingAfterFork() { |
-} |
- |
-#endif |
- |
-#if !defined(OS_WIN) |
- |
-bool IsBinaryInstrumented() { |
- return false; |
-} |
- |
-ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { |
- return NULL; |
-} |
- |
-#else // defined(OS_WIN) |
- |
-// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
-extern "C" IMAGE_DOS_HEADER __ImageBase; |
- |
-bool IsBinaryInstrumented() { |
- enum InstrumentationCheckState { |
- UNINITIALIZED, |
- INSTRUMENTED_IMAGE, |
- NON_INSTRUMENTED_IMAGE, |
- }; |
- |
- static InstrumentationCheckState state = UNINITIALIZED; |
- |
- if (state == UNINITIALIZED) { |
- HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
- base::win::PEImage image(this_module); |
- |
- // Check to be sure our image is structured as we'd expect. |
- DCHECK(image.VerifyMagic()); |
- |
- // Syzygy-instrumented binaries contain a PE image section named ".thunks", |
- // and all Syzygy-modified binaries contain the ".syzygy" image section. |
- // This is a very fast check, as it only looks at the image header. |
- if ((image.GetImageSectionHeaderByName(".thunks") != NULL) && |
- (image.GetImageSectionHeaderByName(".syzygy") != NULL)) { |
- state = INSTRUMENTED_IMAGE; |
- } else { |
- state = NON_INSTRUMENTED_IMAGE; |
- } |
- } |
- DCHECK(state != UNINITIALIZED); |
- |
- return state == INSTRUMENTED_IMAGE; |
-} |
- |
-// Callback function to PEImage::EnumImportChunks. |
-static bool FindResolutionFunctionInImports( |
- const base::win::PEImage &image, const char* module_name, |
- PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table, |
- PVOID cookie) { |
- // Our import address table contains pointers to the functions we import |
- // at this point. Let's retrieve the first such function and use it to |
- // find the module this import was resolved to by the loader. |
- const wchar_t* function_in_module = |
- reinterpret_cast<const wchar_t*>(import_address_table->u1.Function); |
- |
- // Retrieve the module by a function in the module. |
- const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | |
- GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; |
- HMODULE module = NULL; |
- if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) { |
- // This can happen if someone IAT patches us to a thunk. |
- return true; |
- } |
- |
- // See whether this module exports the function we're looking for. |
- ReturnAddressLocationResolver exported_func = |
- reinterpret_cast<ReturnAddressLocationResolver>( |
- ::GetProcAddress(module, "ResolveReturnAddressLocation")); |
- |
- if (exported_func != NULL) { |
- ReturnAddressLocationResolver* resolver_func = |
- reinterpret_cast<ReturnAddressLocationResolver*>(cookie); |
- DCHECK(resolver_func != NULL); |
- DCHECK(*resolver_func == NULL); |
- |
- // We found it, return the function and terminate the enumeration. |
- *resolver_func = exported_func; |
- return false; |
- } |
- |
- // Keep going. |
- return true; |
-} |
- |
-ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { |
- if (!IsBinaryInstrumented()) |
- return NULL; |
- |
- HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
- base::win::PEImage image(this_module); |
- |
- ReturnAddressLocationResolver resolver_func = NULL; |
- image.EnumImportChunks(FindResolutionFunctionInImports, &resolver_func); |
- |
- return resolver_func; |
-} |
- |
-#endif // defined(OS_WIN) |
- |
-} // namespace debug |
-} // namespace base |
+// Copyright (c) 2012 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/profiler.h" |
+ |
+#include <string> |
+ |
+#include "base/process_util.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
+ |
+#if defined(OS_WIN) |
+#include "base/win/pe_image.h" |
+#endif // defined(OS_WIN) |
+ |
+#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) |
+#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h" |
+#endif |
+ |
+namespace base { |
+namespace debug { |
+ |
+#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) |
+ |
+static int profile_count = 0; |
+ |
+void StartProfiling(const std::string& name) { |
+ ++profile_count; |
+ std::string full_name(name); |
+ std::string pid = StringPrintf("%d", GetCurrentProcId()); |
+ std::string count = StringPrintf("%d", profile_count); |
+ ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid); |
+ ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count); |
+ ProfilerStart(full_name.c_str()); |
+} |
+ |
+void StopProfiling() { |
+ ProfilerFlush(); |
+ ProfilerStop(); |
+} |
+ |
+void FlushProfiling() { |
+ ProfilerFlush(); |
+} |
+ |
+bool BeingProfiled() { |
+ return ProfilingIsEnabledForAllThreads(); |
+} |
+ |
+void RestartProfilingAfterFork() { |
+ ProfilerRegisterThread(); |
+} |
+ |
+#else |
+ |
+void StartProfiling(const std::string& name) { |
+} |
+ |
+void StopProfiling() { |
+} |
+ |
+void FlushProfiling() { |
+} |
+ |
+bool BeingProfiled() { |
+ return false; |
+} |
+ |
+void RestartProfilingAfterFork() { |
+} |
+ |
+#endif |
+ |
+#if !defined(OS_WIN) |
+ |
+bool IsBinaryInstrumented() { |
+ return false; |
+} |
+ |
+ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { |
+ return NULL; |
+} |
+ |
+DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() { |
+ return NULL; |
+} |
+ |
+AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { |
+ return NULL; |
+} |
+ |
+MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { |
+ return NULL; |
+} |
+ |
+#else // defined(OS_WIN) |
+ |
+// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
+extern "C" IMAGE_DOS_HEADER __ImageBase; |
+ |
+bool IsBinaryInstrumented() { |
+ enum InstrumentationCheckState { |
+ UNINITIALIZED, |
+ INSTRUMENTED_IMAGE, |
+ NON_INSTRUMENTED_IMAGE, |
+ }; |
+ |
+ static InstrumentationCheckState state = UNINITIALIZED; |
+ |
+ if (state == UNINITIALIZED) { |
+ HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
+ base::win::PEImage image(this_module); |
+ |
+ // Check to be sure our image is structured as we'd expect. |
+ DCHECK(image.VerifyMagic()); |
+ |
+ // Syzygy-instrumented binaries contain a PE image section named ".thunks", |
+ // and all Syzygy-modified binaries contain the ".syzygy" image section. |
+ // This is a very fast check, as it only looks at the image header. |
+ if ((image.GetImageSectionHeaderByName(".thunks") != NULL) && |
+ (image.GetImageSectionHeaderByName(".syzygy") != NULL)) { |
+ state = INSTRUMENTED_IMAGE; |
+ } else { |
+ state = NON_INSTRUMENTED_IMAGE; |
+ } |
+ } |
+ DCHECK(state != UNINITIALIZED); |
+ |
+ return state == INSTRUMENTED_IMAGE; |
+} |
+ |
+namespace { |
+ |
+struct FunctionSearchContext { |
+ const char* name; |
+ FARPROC function; |
+}; |
+ |
+// Callback function to PEImage::EnumImportChunks. |
+bool FindResolutionFunctionInImports( |
+ const base::win::PEImage &image, const char* module_name, |
+ PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table, |
+ PVOID cookie) { |
+ FunctionSearchContext* context = |
+ reinterpret_cast<FunctionSearchContext*>(cookie); |
+ |
+ DCHECK_NE(static_cast<FunctionSearchContext*>(NULL), context); |
+ DCHECK_EQ(static_cast<FARPROC>(NULL), context->function); |
+ |
+ // Our import address table contains pointers to the functions we import |
+ // at this point. Let's retrieve the first such function and use it to |
+ // find the module this import was resolved to by the loader. |
+ const wchar_t* function_in_module = |
+ reinterpret_cast<const wchar_t*>(import_address_table->u1.Function); |
+ |
+ // Retrieve the module by a function in the module. |
+ const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; |
+ HMODULE module = NULL; |
+ if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) { |
+ // This can happen if someone IAT patches us to a thunk. |
+ return true; |
+ } |
+ |
+ // See whether this module exports the function we're looking for. |
+ FARPROC exported_func = ::GetProcAddress(module, context->name); |
+ if (exported_func != NULL) { |
+ // We found it, return the function and terminate the enumeration. |
+ context->function = exported_func; |
+ return false; |
+ } |
+ |
+ // Keep going. |
+ return true; |
+} |
+ |
+template <typename FunctionType> |
+FunctionType FindFunctionInImports(const char* function_name) { |
+ if (!IsBinaryInstrumented()) |
+ return NULL; |
+ |
+ HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
+ base::win::PEImage image(this_module); |
+ |
+ FunctionSearchContext ctx = { function_name, NULL }; |
+ image.EnumImportChunks(FindResolutionFunctionInImports, &ctx); |
+ |
+ return reinterpret_cast<FunctionType>(ctx.function); |
+} |
+ |
+} // namespace |
+ |
+ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { |
+ return FindFunctionInImports<ReturnAddressLocationResolver>( |
+ "ResolveReturnAddressLocation"); |
+} |
+ |
+DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() { |
+ return FindFunctionInImports<DynamicFunctionEntryHook>( |
+ "OnDynamicFunctionEntry"); |
+} |
+ |
+AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { |
+ return FindFunctionInImports<AddDynamicSymbol>( |
+ "AddDynamicSymbol"); |
+} |
+ |
+MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { |
+ return FindFunctionInImports<MoveDynamicSymbol>( |
+ "MoveDynamicSymbol"); |
+} |
+ |
+#endif // defined(OS_WIN) |
+ |
+} // namespace debug |
+} // namespace base |