1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_PROFILER_STACK_SAMPLING_PROFILER_TEST_UTIL_H_ 6 #define BASE_PROFILER_STACK_SAMPLING_PROFILER_TEST_UTIL_H_ 7 8 #include <memory> 9 #include <vector> 10 11 #include "base/callback.h" 12 #include "base/native_library.h" 13 #include "base/profiler/frame.h" 14 #include "base/profiler/sampling_profiler_thread_token.h" 15 #include "base/profiler/stack_sampling_profiler.h" 16 #include "base/synchronization/waitable_event.h" 17 #include "base/threading/platform_thread.h" 18 19 namespace base { 20 21 class Unwinder; 22 class ModuleCache; 23 24 // A thread to target for profiling that will run the supplied closure. 25 class TargetThread : public PlatformThread::Delegate { 26 public: 27 TargetThread(OnceClosure to_run); 28 ~TargetThread() override; 29 30 // PlatformThread::Delegate: 31 void ThreadMain() override; 32 thread_token()33 SamplingProfilerThreadToken thread_token() const { return thread_token_; } 34 35 private: 36 SamplingProfilerThreadToken thread_token_ = {0}; 37 OnceClosure to_run_; 38 39 DISALLOW_COPY_AND_ASSIGN(TargetThread); 40 }; 41 42 // Addresses near the start and end of a function. 43 struct FunctionAddressRange { 44 const void* start; 45 const void* end; 46 }; 47 48 // Represents a stack unwind scenario to be sampled by the 49 // StackSamplingProfiler. 50 class UnwindScenario { 51 public: 52 // A callback provided by the caller that sets up the unwind scenario, then 53 // calls into the passed closure to wait for a sample to be taken. Returns the 54 // address range of the function that sets up the unwind scenario. The passed 55 // closure will be null when invoked solely to obtain the address range. 56 using SetupFunction = RepeatingCallback<FunctionAddressRange(OnceClosure)>; 57 58 // Events to coordinate the sampling. 59 struct SampleEvents { 60 WaitableEvent ready_for_sample; 61 WaitableEvent sample_finished; 62 }; 63 64 explicit UnwindScenario(const SetupFunction& setup_function); 65 ~UnwindScenario(); 66 67 UnwindScenario(const UnwindScenario&) = delete; 68 UnwindScenario& operator=(const UnwindScenario&) = delete; 69 70 // The address range of the innermost function that waits for the sample. 71 FunctionAddressRange GetWaitForSampleAddressRange() const; 72 73 // The address range of the provided setup function. 74 FunctionAddressRange GetSetupFunctionAddressRange() const; 75 76 // The address range of the outer function that indirectly invokes the setup 77 // function. 78 FunctionAddressRange GetOuterFunctionAddressRange() const; 79 80 // Executes the scenario. 81 void Execute(SampleEvents* events); 82 83 private: 84 static FunctionAddressRange InvokeSetupFunction( 85 const SetupFunction& setup_function, 86 SampleEvents* events); 87 88 static FunctionAddressRange WaitForSample(SampleEvents* events); 89 90 const SetupFunction setup_function_; 91 }; 92 93 // UnwindScenario setup function that calls into |wait_for_sample| without doing 94 // any special unwinding setup, to exercise the "normal" unwind scenario. 95 FunctionAddressRange CallWithPlainFunction(OnceClosure wait_for_sample); 96 97 // Calls into |wait_for_sample| after using alloca(), to test unwinding with a 98 // frame pointer. 99 FunctionAddressRange CallWithAlloca(OnceClosure wait_for_sample); 100 101 // Calls into |wait_for_sample| through a function within another library, to 102 // test unwinding through multiple modules and scenarios involving unloaded 103 // modules. 104 FunctionAddressRange CallThroughOtherLibrary(NativeLibrary library, 105 OnceClosure wait_for_sample); 106 107 // The callback to perform profiling on the provided thread. 108 using ProfileCallback = OnceCallback<void(SamplingProfilerThreadToken)>; 109 110 // Executes |profile_callback| while running |scenario| on the target 111 // thread. Performs all necessary target thread startup and shutdown work before 112 // and afterward. 113 void WithTargetThread(UnwindScenario* scenario, 114 ProfileCallback profile_callback); 115 116 using UnwinderFactory = OnceCallback<std::unique_ptr<Unwinder>()>; 117 118 // Returns the sample seen when taking one sample of |scenario|. 119 std::vector<Frame> SampleScenario( 120 UnwindScenario* scenario, 121 ModuleCache* module_cache, 122 UnwinderFactory aux_unwinder_factory = UnwinderFactory()); 123 124 // Formats a sample into a string that can be output for test diagnostics. 125 std::string FormatSampleForDiagnosticOutput(const std::vector<Frame>& sample); 126 127 // Expects that the stack contains the functions with the specified address 128 // ranges, in the specified order. 129 void ExpectStackContains(const std::vector<Frame>& stack, 130 const std::vector<FunctionAddressRange>& functions); 131 132 // Expects that the stack does not contain the functions with the specified 133 // address ranges. 134 void ExpectStackDoesNotContain( 135 const std::vector<Frame>& stack, 136 const std::vector<FunctionAddressRange>& functions); 137 138 // Loads the other library, which defines a function to be called in the 139 // WITH_OTHER_LIBRARY configuration. 140 NativeLibrary LoadOtherLibrary(); 141 142 uintptr_t GetAddressInOtherLibrary(NativeLibrary library); 143 144 // Creates a list of core unwinders required for StackSamplingProfilerTest. 145 // This is useful notably on Android, which requires ChromeUnwinderAndroid in 146 // addition to the native one. 147 StackSamplingProfiler::UnwindersFactory CreateCoreUnwindersFactoryForTesting( 148 ModuleCache* module_cache); 149 150 } // namespace base 151 152 #endif // BASE_PROFILER_STACK_SAMPLING_PROFILER_TEST_UTIL_H_ 153