unwinder.h 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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_UNWINDER_H_
  5. #define BASE_PROFILER_UNWINDER_H_
  6. #include <vector>
  7. #include "base/base_export.h"
  8. #include "base/profiler/frame.h"
  9. #include "base/profiler/module_cache.h"
  10. #include "base/profiler/register_context.h"
  11. namespace base {
  12. // The result of attempting to unwind stack frames.
  13. enum class UnwindResult {
  14. // The end of the stack was reached successfully.
  15. kCompleted,
  16. // The walk reached a frame that it doesn't know how to unwind, but might be
  17. // unwindable by the other native/aux unwinder.
  18. kUnrecognizedFrame,
  19. // The walk was aborted and is not resumable.
  20. kAborted,
  21. };
  22. // Unwinder provides an interface for stack frame unwinder implementations for
  23. // use with the StackSamplingProfiler. Initialize() must be invoked prior to the
  24. // invocation of any other function on the interface. The profiler is expected
  25. // to call CanUnwind() to determine if the Unwinder thinks it can unwind from
  26. // the frame represented by the context values, then TryUnwind() to attempt the
  27. // unwind.
  28. class BASE_EXPORT Unwinder {
  29. public:
  30. virtual ~Unwinder() = default;
  31. // Initializes this unwinder to use |module_cache| in subsequent methods
  32. // UpdateModules() and TryUnwinder(). This unwinder may add any modules it
  33. // recognizes or register a module factory to the ModuleCache. |module_cache|
  34. // must outlive this Unwinder.
  35. void Initialize(ModuleCache* module_cache);
  36. // Invoked at the time the stack is captured. IMPORTANT NOTE: this function is
  37. // invoked while the target thread is suspended. To avoid deadlock it must not
  38. // invoke any non-reentrant code that is also invoked by the target thread. In
  39. // particular, it may not perform any heap allocation or deallocation,
  40. // including indirectly via use of DCHECK/CHECK or other logging statements.
  41. virtual void OnStackCapture() {}
  42. // Allows the unwinder to update ModuleCache with any modules it's responsible
  43. // for. Invoked for each sample between OnStackCapture() and the initial
  44. // invocations of CanUnwindFrom()/TryUnwind().
  45. virtual void UpdateModules() {}
  46. // Returns true if the unwinder recognizes the code referenced by
  47. // |current_frame| as code from which it should be able to unwind. When
  48. // multiple unwinders are in use, each should return true for a disjoint set
  49. // of frames. Note that if the unwinder returns true it may still legitmately
  50. // fail to unwind; e.g. in the case of a native unwind for a function that
  51. // doesn't have unwind information.
  52. virtual bool CanUnwindFrom(const Frame& current_frame) const = 0;
  53. // Attempts to unwind the frame represented by the context values.
  54. // Walks the native frames on the stack pointed to by the stack pointer in
  55. // |thread_context|, appending the frames to |stack|. When invoked
  56. // stack->back() contains the frame corresponding to the state in
  57. // |thread_context|.
  58. // Precondition: RegisterContextStackPointer(thread_context) is less than
  59. // |stack_top|.
  60. // Postcondition: If the implementation returns UNRECOGNIZED_FRAME, indicating
  61. // that it successfully unwound, RegisterContextStackPointer(thread_context)
  62. // is greater than the previous value and less than |stack_top|.
  63. virtual UnwindResult TryUnwind(RegisterContext* thread_context,
  64. uintptr_t stack_top,
  65. std::vector<Frame>* stack) const = 0;
  66. Unwinder(const Unwinder&) = delete;
  67. Unwinder& operator=(const Unwinder&) = delete;
  68. protected:
  69. Unwinder() = default;
  70. // Invoked to allow the unwinder to add any modules it recognizes or register
  71. // a module factory to the ModuleCache.
  72. virtual void InitializeModules() {}
  73. ModuleCache* module_cache() const { return module_cache_; }
  74. private:
  75. ModuleCache* module_cache_ = nullptr;
  76. };
  77. } // namespace base
  78. #endif // BASE_PROFILER_UNWINDER_H_