stack_copier.h 4.1 KB

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