profiler.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/profiler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_handle.h"
105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/pe_image.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(peria): Enable profiling on Windows.
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace debug {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(peria): Enable profiling on Windows.
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int profile_count = 0;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StartProfiling(const std::string& name) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++profile_count;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string full_name(name);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string pid = StringPrintf("%d", GetCurrentProcId());
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string count = StringPrintf("%d", profile_count);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfilerStart(full_name.c_str());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StopProfiling() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfilerFlush();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfilerStop();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FlushProfiling() {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfilerFlush();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BeingProfiled() {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProfilingIsEnabledForAllThreads();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RestartProfilingAfterFork() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfilerRegisterThread();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StartProfiling(const std::string& name) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StopProfiling() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FlushProfiling() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BeingProfiled() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RestartProfilingAfterFork() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_WIN)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsBinaryInstrumented() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return NULL;
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochAddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return NULL;
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochMoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return NULL;
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // defined(OS_WIN)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" IMAGE_DOS_HEADER __ImageBase;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsBinaryInstrumented() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum InstrumentationCheckState {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNINITIALIZED,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INSTRUMENTED_IMAGE,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NON_INSTRUMENTED_IMAGE,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static InstrumentationCheckState state = UNINITIALIZED;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state == UNINITIALIZED) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::win::PEImage image(this_module);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check to be sure our image is structured as we'd expect.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(image.VerifyMagic());
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Syzygy-instrumented binaries contain a PE image section named ".thunks",
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and all Syzygy-modified binaries contain the ".syzygy" image section.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is a very fast check, as it only looks at the image header.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((image.GetImageSectionHeaderByName(".thunks") != NULL) &&
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (image.GetImageSectionHeaderByName(".syzygy") != NULL)) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state = INSTRUMENTED_IMAGE;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state = NON_INSTRUMENTED_IMAGE;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state != UNINITIALIZED);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state == INSTRUMENTED_IMAGE;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace {
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstruct FunctionSearchContext {
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const char* name;
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FARPROC function;
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch};
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback function to PEImage::EnumImportChunks.
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool FindResolutionFunctionInImports(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::win::PEImage &image, const char* module_name,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PVOID cookie) {
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FunctionSearchContext* context =
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      reinterpret_cast<FunctionSearchContext*>(cookie);
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_NE(static_cast<FunctionSearchContext*>(NULL), context);
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(static_cast<FARPROC>(NULL), context->function);
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our import address table contains pointers to the functions we import
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // at this point. Let's retrieve the first such function and use it to
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // find the module this import was resolved to by the loader.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* function_in_module =
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const wchar_t*>(import_address_table->u1.Function);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve the module by a function in the module.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE module = NULL;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This can happen if someone IAT patches us to a thunk.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See whether this module exports the function we're looking for.
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FARPROC exported_func = ::GetProcAddress(module, context->name);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exported_func != NULL) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We found it, return the function and terminate the enumeration.
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    context->function = exported_func;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep going.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochtemplate <typename FunctionType>
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochFunctionType FindFunctionInImports(const char* function_name) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsBinaryInstrumented())
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::PEImage image(this_module);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FunctionSearchContext ctx = { function_name, NULL };
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  image.EnumImportChunks(FindResolutionFunctionInImports, &ctx);
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return reinterpret_cast<FunctionType>(ctx.function);
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return FindFunctionInImports<ReturnAddressLocationResolver>(
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      "ResolveReturnAddressLocation");
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return FindFunctionInImports<DynamicFunctionEntryHook>(
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      "OnDynamicFunctionEntry");
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochAddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return FindFunctionInImports<AddDynamicSymbol>(
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      "AddDynamicSymbol");
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochMoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return FindFunctionInImports<MoveDynamicSymbol>(
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      "MoveDynamicSymbol");
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace debug
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
220