1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/chromium/base/debug/profiler.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/debug/profiler.h" 1.9 + 1.10 +#include <string> 1.11 + 1.12 +#include "base/process/process_handle.h" 1.13 +#include "base/strings/string_util.h" 1.14 +#include "base/strings/stringprintf.h" 1.15 + 1.16 +#if defined(OS_WIN) 1.17 +#include "base/win/pe_image.h" 1.18 +#endif // defined(OS_WIN) 1.19 + 1.20 +#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) 1.21 +#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h" 1.22 +#endif 1.23 + 1.24 +namespace base { 1.25 +namespace debug { 1.26 + 1.27 +#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) 1.28 + 1.29 +static int profile_count = 0; 1.30 + 1.31 +void StartProfiling(const std::string& name) { 1.32 + ++profile_count; 1.33 + std::string full_name(name); 1.34 + std::string pid = StringPrintf("%d", GetCurrentProcId()); 1.35 + std::string count = StringPrintf("%d", profile_count); 1.36 + ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid); 1.37 + ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count); 1.38 + ProfilerStart(full_name.c_str()); 1.39 +} 1.40 + 1.41 +void StopProfiling() { 1.42 + ProfilerFlush(); 1.43 + ProfilerStop(); 1.44 +} 1.45 + 1.46 +void FlushProfiling() { 1.47 + ProfilerFlush(); 1.48 +} 1.49 + 1.50 +bool BeingProfiled() { 1.51 + return ProfilingIsEnabledForAllThreads(); 1.52 +} 1.53 + 1.54 +void RestartProfilingAfterFork() { 1.55 + ProfilerRegisterThread(); 1.56 +} 1.57 + 1.58 +#else 1.59 + 1.60 +void StartProfiling(const std::string& name) { 1.61 +} 1.62 + 1.63 +void StopProfiling() { 1.64 +} 1.65 + 1.66 +void FlushProfiling() { 1.67 +} 1.68 + 1.69 +bool BeingProfiled() { 1.70 + return false; 1.71 +} 1.72 + 1.73 +void RestartProfilingAfterFork() { 1.74 +} 1.75 + 1.76 +#endif 1.77 + 1.78 +#if !defined(OS_WIN) 1.79 + 1.80 +bool IsBinaryInstrumented() { 1.81 + return false; 1.82 +} 1.83 + 1.84 +ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { 1.85 + return NULL; 1.86 +} 1.87 + 1.88 +DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() { 1.89 + return NULL; 1.90 +} 1.91 + 1.92 +AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { 1.93 + return NULL; 1.94 +} 1.95 + 1.96 +MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { 1.97 + return NULL; 1.98 +} 1.99 + 1.100 +#else // defined(OS_WIN) 1.101 + 1.102 +// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx 1.103 +extern "C" IMAGE_DOS_HEADER __ImageBase; 1.104 + 1.105 +bool IsBinaryInstrumented() { 1.106 + enum InstrumentationCheckState { 1.107 + UNINITIALIZED, 1.108 + INSTRUMENTED_IMAGE, 1.109 + NON_INSTRUMENTED_IMAGE, 1.110 + }; 1.111 + 1.112 + static InstrumentationCheckState state = UNINITIALIZED; 1.113 + 1.114 + if (state == UNINITIALIZED) { 1.115 + HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); 1.116 + base::win::PEImage image(this_module); 1.117 + 1.118 + // Check to be sure our image is structured as we'd expect. 1.119 + DCHECK(image.VerifyMagic()); 1.120 + 1.121 + // Syzygy-instrumented binaries contain a PE image section named ".thunks", 1.122 + // and all Syzygy-modified binaries contain the ".syzygy" image section. 1.123 + // This is a very fast check, as it only looks at the image header. 1.124 + if ((image.GetImageSectionHeaderByName(".thunks") != NULL) && 1.125 + (image.GetImageSectionHeaderByName(".syzygy") != NULL)) { 1.126 + state = INSTRUMENTED_IMAGE; 1.127 + } else { 1.128 + state = NON_INSTRUMENTED_IMAGE; 1.129 + } 1.130 + } 1.131 + DCHECK(state != UNINITIALIZED); 1.132 + 1.133 + return state == INSTRUMENTED_IMAGE; 1.134 +} 1.135 + 1.136 +namespace { 1.137 + 1.138 +struct FunctionSearchContext { 1.139 + const char* name; 1.140 + FARPROC function; 1.141 +}; 1.142 + 1.143 +// Callback function to PEImage::EnumImportChunks. 1.144 +bool FindResolutionFunctionInImports( 1.145 + const base::win::PEImage &image, const char* module_name, 1.146 + PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table, 1.147 + PVOID cookie) { 1.148 + FunctionSearchContext* context = 1.149 + reinterpret_cast<FunctionSearchContext*>(cookie); 1.150 + 1.151 + DCHECK_NE(static_cast<FunctionSearchContext*>(NULL), context); 1.152 + DCHECK_EQ(static_cast<FARPROC>(NULL), context->function); 1.153 + 1.154 + // Our import address table contains pointers to the functions we import 1.155 + // at this point. Let's retrieve the first such function and use it to 1.156 + // find the module this import was resolved to by the loader. 1.157 + const wchar_t* function_in_module = 1.158 + reinterpret_cast<const wchar_t*>(import_address_table->u1.Function); 1.159 + 1.160 + // Retrieve the module by a function in the module. 1.161 + const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 1.162 + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; 1.163 + HMODULE module = NULL; 1.164 + if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) { 1.165 + // This can happen if someone IAT patches us to a thunk. 1.166 + return true; 1.167 + } 1.168 + 1.169 + // See whether this module exports the function we're looking for. 1.170 + FARPROC exported_func = ::GetProcAddress(module, context->name); 1.171 + if (exported_func != NULL) { 1.172 + // We found it, return the function and terminate the enumeration. 1.173 + context->function = exported_func; 1.174 + return false; 1.175 + } 1.176 + 1.177 + // Keep going. 1.178 + return true; 1.179 +} 1.180 + 1.181 +template <typename FunctionType> 1.182 +FunctionType FindFunctionInImports(const char* function_name) { 1.183 + if (!IsBinaryInstrumented()) 1.184 + return NULL; 1.185 + 1.186 + HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); 1.187 + base::win::PEImage image(this_module); 1.188 + 1.189 + FunctionSearchContext ctx = { function_name, NULL }; 1.190 + image.EnumImportChunks(FindResolutionFunctionInImports, &ctx); 1.191 + 1.192 + return reinterpret_cast<FunctionType>(ctx.function); 1.193 +} 1.194 + 1.195 +} // namespace 1.196 + 1.197 +ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { 1.198 + return FindFunctionInImports<ReturnAddressLocationResolver>( 1.199 + "ResolveReturnAddressLocation"); 1.200 +} 1.201 + 1.202 +DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() { 1.203 + return FindFunctionInImports<DynamicFunctionEntryHook>( 1.204 + "OnDynamicFunctionEntry"); 1.205 +} 1.206 + 1.207 +AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { 1.208 + return FindFunctionInImports<AddDynamicSymbol>( 1.209 + "AddDynamicSymbol"); 1.210 +} 1.211 + 1.212 +MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { 1.213 + return FindFunctionInImports<MoveDynamicSymbol>( 1.214 + "MoveDynamicSymbol"); 1.215 +} 1.216 + 1.217 +#endif // defined(OS_WIN) 1.218 + 1.219 +} // namespace debug 1.220 +} // namespace base