| Index: base/debug/profiler.cc
|
| diff --git a/base/debug/profiler.cc b/base/debug/profiler.cc
|
| index be442cf1fd66fc981ebd352bc6601c7b1a7a4fa0..41950575f93d71bc947e164989a66f1b0f52e661 100644
|
| --- a/base/debug/profiler.cc
|
| +++ b/base/debug/profiler.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// 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.
|
|
|
| @@ -10,6 +10,10 @@
|
| #include "base/string_util.h"
|
| #include "base/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/google/profiler.h"
|
| #endif
|
| @@ -68,5 +72,89 @@ 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() {
|
| + HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
|
| + base::win::PEImage image(this_module);
|
| +
|
| + // This should be self-evident, soon as we're executing.
|
| + 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.
|
| + return (image.GetImageSectionHeaderByName(".thunks") != NULL) &&
|
| + (image.GetImageSectionHeaderByName(".syzygy") != NULL);
|
| +}
|
| +
|
| +// 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
|
|
|