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