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