xref: /aosp_15_r20/external/cronet/base/profiler/stack_copier.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 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 #ifndef BASE_PROFILER_STACK_COPIER_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_PROFILER_STACK_COPIER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/profiler/register_context.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace base {
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker class StackBuffer;
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // StackCopier causes a thread to be suspended, copies its stack, and resumes
19*6777b538SAndroid Build Coastguard Worker // the thread's execution. It's intended to provide an abstraction over stack
20*6777b538SAndroid Build Coastguard Worker // copying techniques where the thread suspension is performed directly by the
21*6777b538SAndroid Build Coastguard Worker // profiler thread (Windows and Mac platforms) vs. where the thread suspension
22*6777b538SAndroid Build Coastguard Worker // is performed by the OS through signals (Android).
23*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT StackCopier {
24*6777b538SAndroid Build Coastguard Worker  public:
25*6777b538SAndroid Build Coastguard Worker   // Interface that may be implemented by the caller of CopyStack() to receive a
26*6777b538SAndroid Build Coastguard Worker   // callback when the stack is copied, while the target thread is suspended.
27*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT Delegate {
28*6777b538SAndroid Build Coastguard Worker    public:
~Delegate()29*6777b538SAndroid Build Coastguard Worker     virtual ~Delegate() {}
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker     // Invoked at the time the stack is copied.
32*6777b538SAndroid Build Coastguard Worker     // IMPORTANT NOTE: to avoid deadlock implementations of this interface must
33*6777b538SAndroid Build Coastguard Worker     // not invoke any non-reentrant code that is also invoked by the target
34*6777b538SAndroid Build Coastguard Worker     // thread. In particular, it may not perform any heap allocation or
35*6777b538SAndroid Build Coastguard Worker     // deallocation, including indirectly via use of DCHECK/CHECK or other
36*6777b538SAndroid Build Coastguard Worker     // logging statements.
37*6777b538SAndroid Build Coastguard Worker     virtual void OnStackCopy() = 0;
38*6777b538SAndroid Build Coastguard Worker   };
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker   virtual ~StackCopier();
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker   // Copies the thread's register context into |thread_context|, the stack into
43*6777b538SAndroid Build Coastguard Worker   // |stack_buffer|, and the top of stack address into |stack_top|. Records
44*6777b538SAndroid Build Coastguard Worker   // |timestamp| at the time the stack was copied. delegate->OnStackCopy() will
45*6777b538SAndroid Build Coastguard Worker   // be invoked while the thread is suspended. Returns true if successful.
46*6777b538SAndroid Build Coastguard Worker   virtual bool CopyStack(StackBuffer* stack_buffer,
47*6777b538SAndroid Build Coastguard Worker                          uintptr_t* stack_top,
48*6777b538SAndroid Build Coastguard Worker                          TimeTicks* timestamp,
49*6777b538SAndroid Build Coastguard Worker                          RegisterContext* thread_context,
50*6777b538SAndroid Build Coastguard Worker                          Delegate* delegate) = 0;
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker  protected:
53*6777b538SAndroid Build Coastguard Worker   // If the value at |pointer| points to the original stack, rewrite it to point
54*6777b538SAndroid Build Coastguard Worker   // to the corresponding location in the copied stack.
55*6777b538SAndroid Build Coastguard Worker   //
56*6777b538SAndroid Build Coastguard Worker   // NO HEAP ALLOCATIONS.
57*6777b538SAndroid Build Coastguard Worker   static uintptr_t RewritePointerIfInOriginalStack(
58*6777b538SAndroid Build Coastguard Worker       const uint8_t* original_stack_bottom,
59*6777b538SAndroid Build Coastguard Worker       const uintptr_t* original_stack_top,
60*6777b538SAndroid Build Coastguard Worker       const uint8_t* stack_copy_bottom,
61*6777b538SAndroid Build Coastguard Worker       uintptr_t pointer);
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker   // Copies the stack to a buffer while rewriting possible pointers to locations
64*6777b538SAndroid Build Coastguard Worker   // within the stack to point to the corresponding locations in the copy. This
65*6777b538SAndroid Build Coastguard Worker   // is necessary to handle stack frames with dynamic stack allocation, where a
66*6777b538SAndroid Build Coastguard Worker   // pointer to the beginning of the dynamic allocation area is stored on the
67*6777b538SAndroid Build Coastguard Worker   // stack and/or in a non-volatile register.
68*6777b538SAndroid Build Coastguard Worker   //
69*6777b538SAndroid Build Coastguard Worker   // Eager rewriting of anything that looks like a pointer to the stack, as done
70*6777b538SAndroid Build Coastguard Worker   // in this function, does not adversely affect the stack unwinding. The only
71*6777b538SAndroid Build Coastguard Worker   // other values on the stack the unwinding depends on are return addresses,
72*6777b538SAndroid Build Coastguard Worker   // which should not point within the stack memory. The rewriting is guaranteed
73*6777b538SAndroid Build Coastguard Worker   // to catch all pointers because the stacks are guaranteed by the ABI to be
74*6777b538SAndroid Build Coastguard Worker   // sizeof(uintptr_t*) aligned.
75*6777b538SAndroid Build Coastguard Worker   //
76*6777b538SAndroid Build Coastguard Worker   // |original_stack_bottom| and |original_stack_top| are different pointer
77*6777b538SAndroid Build Coastguard Worker   // types due on their differing guaranteed alignments -- the bottom may only
78*6777b538SAndroid Build Coastguard Worker   // be 1-byte aligned while the top is aligned to double the pointer width.
79*6777b538SAndroid Build Coastguard Worker   //
80*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the bottom address in the copied stack. This value
81*6777b538SAndroid Build Coastguard Worker   // matches the alignment of |original_stack_bottom| to ensure that the stack
82*6777b538SAndroid Build Coastguard Worker   // contents have the same alignment as in the original stack. As a result the
83*6777b538SAndroid Build Coastguard Worker   // value will be different than |stack_buffer_bottom| if
84*6777b538SAndroid Build Coastguard Worker   // |original_stack_bottom| is not aligned to double the pointer width.
85*6777b538SAndroid Build Coastguard Worker   //
86*6777b538SAndroid Build Coastguard Worker   // NO HEAP ALLOCATIONS.
87*6777b538SAndroid Build Coastguard Worker   static const uint8_t* CopyStackContentsAndRewritePointers(
88*6777b538SAndroid Build Coastguard Worker       const uint8_t* original_stack_bottom,
89*6777b538SAndroid Build Coastguard Worker       const uintptr_t* original_stack_top,
90*6777b538SAndroid Build Coastguard Worker       size_t platform_stack_alignment,
91*6777b538SAndroid Build Coastguard Worker       uintptr_t* stack_buffer_bottom);
92*6777b538SAndroid Build Coastguard Worker };
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker }  // namespace base
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker #endif  // BASE_PROFILER_STACK_COPIER_H_
97