1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/debug/profiler.h"
6
7 #include "base/allocator/buildflags.h"
8 #include "base/check.h"
9 #include "base/process/process_handle.h"
10 #include "build/build_config.h"
11
12 #if BUILDFLAG(IS_WIN)
13 #include "base/win/current_module.h"
14 #include "base/win/pe_image.h"
15 #endif // BUILDFLAG(IS_WIN)
16
17 namespace base {
18 namespace debug {
19
StartProfiling(const std::string & name)20 void StartProfiling(const std::string& name) {
21 }
22
StopProfiling()23 void StopProfiling() {
24 }
25
FlushProfiling()26 void FlushProfiling() {
27 }
28
BeingProfiled()29 bool BeingProfiled() {
30 return false;
31 }
32
RestartProfilingAfterFork()33 void RestartProfilingAfterFork() {
34 }
35
IsProfilingSupported()36 bool IsProfilingSupported() {
37 return false;
38 }
39
40 #if !BUILDFLAG(IS_WIN)
41
GetProfilerReturnAddrResolutionFunc()42 ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
43 return nullptr;
44 }
45
GetProfilerAddDynamicSymbolFunc()46 AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
47 return nullptr;
48 }
49
GetProfilerMoveDynamicSymbolFunc()50 MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
51 return nullptr;
52 }
53
54 #else // BUILDFLAG(IS_WIN)
55
56 namespace {
57
58 struct FunctionSearchContext {
59 const char* name;
60 FARPROC function;
61 };
62
63 // 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)64 bool FindResolutionFunctionInImports(
65 const base::win::PEImage &image, const char* module_name,
66 PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table,
67 PVOID cookie) {
68 FunctionSearchContext* context =
69 reinterpret_cast<FunctionSearchContext*>(cookie);
70
71 DCHECK(context);
72 DCHECK(!context->function);
73
74 // Our import address table contains pointers to the functions we import
75 // at this point. Let's retrieve the first such function and use it to
76 // find the module this import was resolved to by the loader.
77 const wchar_t* function_in_module =
78 reinterpret_cast<const wchar_t*>(import_address_table->u1.Function);
79
80 // Retrieve the module by a function in the module.
81 const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
82 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
83 HMODULE module = NULL;
84 if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) {
85 // This can happen if someone IAT patches us to a thunk.
86 return true;
87 }
88
89 // See whether this module exports the function we're looking for.
90 FARPROC exported_func = ::GetProcAddress(module, context->name);
91 if (exported_func != NULL) {
92 // We found it, return the function and terminate the enumeration.
93 context->function = exported_func;
94 return false;
95 }
96
97 // Keep going.
98 return true;
99 }
100
101 template <typename FunctionType>
FindFunctionInImports(const char * function_name)102 FunctionType FindFunctionInImports(const char* function_name) {
103 base::win::PEImage image(CURRENT_MODULE());
104
105 FunctionSearchContext ctx = { function_name, NULL };
106 image.EnumImportChunks(FindResolutionFunctionInImports, &ctx, nullptr);
107
108 return reinterpret_cast<FunctionType>(ctx.function);
109 }
110
111 } // namespace
112
GetProfilerReturnAddrResolutionFunc()113 ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
114 return FindFunctionInImports<ReturnAddressLocationResolver>(
115 "ResolveReturnAddressLocation");
116 }
117
GetProfilerAddDynamicSymbolFunc()118 AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
119 return FindFunctionInImports<AddDynamicSymbol>(
120 "AddDynamicSymbol");
121 }
122
GetProfilerMoveDynamicSymbolFunc()123 MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
124 return FindFunctionInImports<MoveDynamicSymbol>(
125 "MoveDynamicSymbol");
126 }
127
128 #endif // BUILDFLAG(IS_WIN)
129
130 } // namespace debug
131 } // namespace base
132