sanitizer_stacktrace.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is shared between AddressSanitizer and ThreadSanitizer
  9. // run-time libraries.
  10. //===----------------------------------------------------------------------===//
  11. #ifndef SANITIZER_STACKTRACE_H
  12. #define SANITIZER_STACKTRACE_H
  13. #include "sanitizer_internal_defs.h"
  14. namespace __sanitizer {
  15. static const uptr kStackTraceMax = 256;
  16. #if SANITIZER_LINUX && (defined(__aarch64__) || defined(__powerpc__) || \
  17. defined(__powerpc64__) || defined(__sparc__) || \
  18. defined(__mips__))
  19. # define SANITIZER_CAN_FAST_UNWIND 0
  20. #elif SANITIZER_WINDOWS
  21. # define SANITIZER_CAN_FAST_UNWIND 0
  22. #else
  23. # define SANITIZER_CAN_FAST_UNWIND 1
  24. #endif
  25. // Fast unwind is the only option on Mac for now; we will need to
  26. // revisit this macro when slow unwind works on Mac, see
  27. // https://code.google.com/p/address-sanitizer/issues/detail?id=137
  28. #if SANITIZER_MAC
  29. # define SANITIZER_CAN_SLOW_UNWIND 0
  30. #else
  31. # define SANITIZER_CAN_SLOW_UNWIND 1
  32. #endif
  33. struct StackTrace {
  34. const uptr *trace;
  35. uptr size;
  36. StackTrace() : trace(nullptr), size(0) {}
  37. StackTrace(const uptr *trace, uptr size) : trace(trace), size(size) {}
  38. // Prints a symbolized stacktrace, followed by an empty line.
  39. void Print() const;
  40. static bool WillUseFastUnwind(bool request_fast_unwind) {
  41. if (!SANITIZER_CAN_FAST_UNWIND)
  42. return false;
  43. else if (!SANITIZER_CAN_SLOW_UNWIND)
  44. return true;
  45. return request_fast_unwind;
  46. }
  47. static uptr GetCurrentPc();
  48. static uptr GetPreviousInstructionPc(uptr pc);
  49. typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
  50. int out_size);
  51. };
  52. // StackTrace that owns the buffer used to store the addresses.
  53. struct BufferedStackTrace : public StackTrace {
  54. uptr trace_buffer[kStackTraceMax];
  55. uptr top_frame_bp; // Optional bp of a top frame.
  56. BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {}
  57. void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
  58. void Unwind(uptr max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
  59. uptr stack_bottom, bool request_fast_unwind);
  60. private:
  61. void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
  62. uptr max_depth);
  63. void SlowUnwindStack(uptr pc, uptr max_depth);
  64. void SlowUnwindStackWithContext(uptr pc, void *context,
  65. uptr max_depth);
  66. void PopStackFrames(uptr count);
  67. uptr LocatePcInTrace(uptr pc);
  68. BufferedStackTrace(const BufferedStackTrace &);
  69. void operator=(const BufferedStackTrace &);
  70. };
  71. } // namespace __sanitizer
  72. // Use this macro if you want to print stack trace with the caller
  73. // of the current function in the top frame.
  74. #define GET_CALLER_PC_BP_SP \
  75. uptr bp = GET_CURRENT_FRAME(); \
  76. uptr pc = GET_CALLER_PC(); \
  77. uptr local_stack; \
  78. uptr sp = (uptr)&local_stack
  79. #define GET_CALLER_PC_BP \
  80. uptr bp = GET_CURRENT_FRAME(); \
  81. uptr pc = GET_CALLER_PC();
  82. // Use this macro if you want to print stack trace with the current
  83. // function in the top frame.
  84. #define GET_CURRENT_PC_BP_SP \
  85. uptr bp = GET_CURRENT_FRAME(); \
  86. uptr pc = StackTrace::GetCurrentPc(); \
  87. uptr local_stack; \
  88. uptr sp = (uptr)&local_stack
  89. #endif // SANITIZER_STACKTRACE_H