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