stack_sampling_profiler_test_util.h 6.3 KB

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