xref: /aosp_15_r20/external/libchrome/base/debug/profiler.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/debug/profiler.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <string>
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include "base/debug/debugging_buildflags.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/process/process_handle.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
13*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
16*635a8641SAndroid Build Coastguard Worker #include "base/win/current_module.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/win/pe_image.h"
18*635a8641SAndroid Build Coastguard Worker #endif  // defined(OS_WIN)
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker // TODO(peria): Enable profiling on Windows.
21*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
22*635a8641SAndroid Build Coastguard Worker #include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/profiler.h"
23*635a8641SAndroid Build Coastguard Worker #endif
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker namespace base {
26*635a8641SAndroid Build Coastguard Worker namespace debug {
27*635a8641SAndroid Build Coastguard Worker 
28*635a8641SAndroid Build Coastguard Worker // TODO(peria): Enable profiling on Windows.
29*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker static int profile_count = 0;
32*635a8641SAndroid Build Coastguard Worker 
StartProfiling(const std::string & name)33*635a8641SAndroid Build Coastguard Worker void StartProfiling(const std::string& name) {
34*635a8641SAndroid Build Coastguard Worker   ++profile_count;
35*635a8641SAndroid Build Coastguard Worker   std::string full_name(name);
36*635a8641SAndroid Build Coastguard Worker   std::string pid = IntToString(GetCurrentProcId());
37*635a8641SAndroid Build Coastguard Worker   std::string count = IntToString(profile_count);
38*635a8641SAndroid Build Coastguard Worker   ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
39*635a8641SAndroid Build Coastguard Worker   ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
40*635a8641SAndroid Build Coastguard Worker   ProfilerStart(full_name.c_str());
41*635a8641SAndroid Build Coastguard Worker }
42*635a8641SAndroid Build Coastguard Worker 
StopProfiling()43*635a8641SAndroid Build Coastguard Worker void StopProfiling() {
44*635a8641SAndroid Build Coastguard Worker   ProfilerFlush();
45*635a8641SAndroid Build Coastguard Worker   ProfilerStop();
46*635a8641SAndroid Build Coastguard Worker }
47*635a8641SAndroid Build Coastguard Worker 
FlushProfiling()48*635a8641SAndroid Build Coastguard Worker void FlushProfiling() {
49*635a8641SAndroid Build Coastguard Worker   ProfilerFlush();
50*635a8641SAndroid Build Coastguard Worker }
51*635a8641SAndroid Build Coastguard Worker 
BeingProfiled()52*635a8641SAndroid Build Coastguard Worker bool BeingProfiled() {
53*635a8641SAndroid Build Coastguard Worker   return ProfilingIsEnabledForAllThreads();
54*635a8641SAndroid Build Coastguard Worker }
55*635a8641SAndroid Build Coastguard Worker 
RestartProfilingAfterFork()56*635a8641SAndroid Build Coastguard Worker void RestartProfilingAfterFork() {
57*635a8641SAndroid Build Coastguard Worker   ProfilerRegisterThread();
58*635a8641SAndroid Build Coastguard Worker }
59*635a8641SAndroid Build Coastguard Worker 
IsProfilingSupported()60*635a8641SAndroid Build Coastguard Worker bool IsProfilingSupported() {
61*635a8641SAndroid Build Coastguard Worker   return true;
62*635a8641SAndroid Build Coastguard Worker }
63*635a8641SAndroid Build Coastguard Worker 
64*635a8641SAndroid Build Coastguard Worker #else
65*635a8641SAndroid Build Coastguard Worker 
66*635a8641SAndroid Build Coastguard Worker void StartProfiling(const std::string& name) {
67*635a8641SAndroid Build Coastguard Worker }
68*635a8641SAndroid Build Coastguard Worker 
69*635a8641SAndroid Build Coastguard Worker void StopProfiling() {
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker 
72*635a8641SAndroid Build Coastguard Worker void FlushProfiling() {
73*635a8641SAndroid Build Coastguard Worker }
74*635a8641SAndroid Build Coastguard Worker 
75*635a8641SAndroid Build Coastguard Worker bool BeingProfiled() {
76*635a8641SAndroid Build Coastguard Worker   return false;
77*635a8641SAndroid Build Coastguard Worker }
78*635a8641SAndroid Build Coastguard Worker 
79*635a8641SAndroid Build Coastguard Worker void RestartProfilingAfterFork() {
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker 
82*635a8641SAndroid Build Coastguard Worker bool IsProfilingSupported() {
83*635a8641SAndroid Build Coastguard Worker   return false;
84*635a8641SAndroid Build Coastguard Worker }
85*635a8641SAndroid Build Coastguard Worker 
86*635a8641SAndroid Build Coastguard Worker #endif
87*635a8641SAndroid Build Coastguard Worker 
88*635a8641SAndroid Build Coastguard Worker #if !defined(OS_WIN)
89*635a8641SAndroid Build Coastguard Worker 
GetProfilerReturnAddrResolutionFunc()90*635a8641SAndroid Build Coastguard Worker ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
91*635a8641SAndroid Build Coastguard Worker   return nullptr;
92*635a8641SAndroid Build Coastguard Worker }
93*635a8641SAndroid Build Coastguard Worker 
GetProfilerDynamicFunctionEntryHookFunc()94*635a8641SAndroid Build Coastguard Worker DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
95*635a8641SAndroid Build Coastguard Worker   return nullptr;
96*635a8641SAndroid Build Coastguard Worker }
97*635a8641SAndroid Build Coastguard Worker 
GetProfilerAddDynamicSymbolFunc()98*635a8641SAndroid Build Coastguard Worker AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
99*635a8641SAndroid Build Coastguard Worker   return nullptr;
100*635a8641SAndroid Build Coastguard Worker }
101*635a8641SAndroid Build Coastguard Worker 
GetProfilerMoveDynamicSymbolFunc()102*635a8641SAndroid Build Coastguard Worker MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
103*635a8641SAndroid Build Coastguard Worker   return nullptr;
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker 
106*635a8641SAndroid Build Coastguard Worker #else  // defined(OS_WIN)
107*635a8641SAndroid Build Coastguard Worker 
108*635a8641SAndroid Build Coastguard Worker namespace {
109*635a8641SAndroid Build Coastguard Worker 
110*635a8641SAndroid Build Coastguard Worker struct FunctionSearchContext {
111*635a8641SAndroid Build Coastguard Worker   const char* name;
112*635a8641SAndroid Build Coastguard Worker   FARPROC function;
113*635a8641SAndroid Build Coastguard Worker };
114*635a8641SAndroid Build Coastguard Worker 
115*635a8641SAndroid Build Coastguard Worker // Callback function to PEImage::EnumImportChunks.
FindResolutionFunctionInImports(const base::win::PEImage & image,const char * module_name,PIMAGE_THUNK_DATA unused_name_table,PIMAGE_THUNK_DATA import_address_table,PVOID cookie)116*635a8641SAndroid Build Coastguard Worker bool FindResolutionFunctionInImports(
117*635a8641SAndroid Build Coastguard Worker     const base::win::PEImage &image, const char* module_name,
118*635a8641SAndroid Build Coastguard Worker     PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table,
119*635a8641SAndroid Build Coastguard Worker     PVOID cookie) {
120*635a8641SAndroid Build Coastguard Worker   FunctionSearchContext* context =
121*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<FunctionSearchContext*>(cookie);
122*635a8641SAndroid Build Coastguard Worker 
123*635a8641SAndroid Build Coastguard Worker   DCHECK(context);
124*635a8641SAndroid Build Coastguard Worker   DCHECK(!context->function);
125*635a8641SAndroid Build Coastguard Worker 
126*635a8641SAndroid Build Coastguard Worker   // Our import address table contains pointers to the functions we import
127*635a8641SAndroid Build Coastguard Worker   // at this point. Let's retrieve the first such function and use it to
128*635a8641SAndroid Build Coastguard Worker   // find the module this import was resolved to by the loader.
129*635a8641SAndroid Build Coastguard Worker   const wchar_t* function_in_module =
130*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<const wchar_t*>(import_address_table->u1.Function);
131*635a8641SAndroid Build Coastguard Worker 
132*635a8641SAndroid Build Coastguard Worker   // Retrieve the module by a function in the module.
133*635a8641SAndroid Build Coastguard Worker   const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
134*635a8641SAndroid Build Coastguard Worker                        GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
135*635a8641SAndroid Build Coastguard Worker   HMODULE module = NULL;
136*635a8641SAndroid Build Coastguard Worker   if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) {
137*635a8641SAndroid Build Coastguard Worker     // This can happen if someone IAT patches us to a thunk.
138*635a8641SAndroid Build Coastguard Worker     return true;
139*635a8641SAndroid Build Coastguard Worker   }
140*635a8641SAndroid Build Coastguard Worker 
141*635a8641SAndroid Build Coastguard Worker   // See whether this module exports the function we're looking for.
142*635a8641SAndroid Build Coastguard Worker   FARPROC exported_func = ::GetProcAddress(module, context->name);
143*635a8641SAndroid Build Coastguard Worker   if (exported_func != NULL) {
144*635a8641SAndroid Build Coastguard Worker     // We found it, return the function and terminate the enumeration.
145*635a8641SAndroid Build Coastguard Worker     context->function = exported_func;
146*635a8641SAndroid Build Coastguard Worker     return false;
147*635a8641SAndroid Build Coastguard Worker   }
148*635a8641SAndroid Build Coastguard Worker 
149*635a8641SAndroid Build Coastguard Worker   // Keep going.
150*635a8641SAndroid Build Coastguard Worker   return true;
151*635a8641SAndroid Build Coastguard Worker }
152*635a8641SAndroid Build Coastguard Worker 
153*635a8641SAndroid Build Coastguard Worker template <typename FunctionType>
FindFunctionInImports(const char * function_name)154*635a8641SAndroid Build Coastguard Worker FunctionType FindFunctionInImports(const char* function_name) {
155*635a8641SAndroid Build Coastguard Worker   base::win::PEImage image(CURRENT_MODULE());
156*635a8641SAndroid Build Coastguard Worker 
157*635a8641SAndroid Build Coastguard Worker   FunctionSearchContext ctx = { function_name, NULL };
158*635a8641SAndroid Build Coastguard Worker   image.EnumImportChunks(FindResolutionFunctionInImports, &ctx);
159*635a8641SAndroid Build Coastguard Worker 
160*635a8641SAndroid Build Coastguard Worker   return reinterpret_cast<FunctionType>(ctx.function);
161*635a8641SAndroid Build Coastguard Worker }
162*635a8641SAndroid Build Coastguard Worker 
163*635a8641SAndroid Build Coastguard Worker }  // namespace
164*635a8641SAndroid Build Coastguard Worker 
GetProfilerReturnAddrResolutionFunc()165*635a8641SAndroid Build Coastguard Worker ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
166*635a8641SAndroid Build Coastguard Worker   return FindFunctionInImports<ReturnAddressLocationResolver>(
167*635a8641SAndroid Build Coastguard Worker       "ResolveReturnAddressLocation");
168*635a8641SAndroid Build Coastguard Worker }
169*635a8641SAndroid Build Coastguard Worker 
GetProfilerDynamicFunctionEntryHookFunc()170*635a8641SAndroid Build Coastguard Worker DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
171*635a8641SAndroid Build Coastguard Worker   return FindFunctionInImports<DynamicFunctionEntryHook>(
172*635a8641SAndroid Build Coastguard Worker       "OnDynamicFunctionEntry");
173*635a8641SAndroid Build Coastguard Worker }
174*635a8641SAndroid Build Coastguard Worker 
GetProfilerAddDynamicSymbolFunc()175*635a8641SAndroid Build Coastguard Worker AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
176*635a8641SAndroid Build Coastguard Worker   return FindFunctionInImports<AddDynamicSymbol>(
177*635a8641SAndroid Build Coastguard Worker       "AddDynamicSymbol");
178*635a8641SAndroid Build Coastguard Worker }
179*635a8641SAndroid Build Coastguard Worker 
GetProfilerMoveDynamicSymbolFunc()180*635a8641SAndroid Build Coastguard Worker MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
181*635a8641SAndroid Build Coastguard Worker   return FindFunctionInImports<MoveDynamicSymbol>(
182*635a8641SAndroid Build Coastguard Worker       "MoveDynamicSymbol");
183*635a8641SAndroid Build Coastguard Worker }
184*635a8641SAndroid Build Coastguard Worker 
185*635a8641SAndroid Build Coastguard Worker #endif  // defined(OS_WIN)
186*635a8641SAndroid Build Coastguard Worker 
187*635a8641SAndroid Build Coastguard Worker }  // namespace debug
188*635a8641SAndroid Build Coastguard Worker }  // namespace base
189