1c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===//
2c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//
3c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//                     The LLVM Compiler Infrastructure
4c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//
5c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// This file is distributed under the University of Illinois Open Source
6c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// License. See LICENSE.TXT for details.
7c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//
8c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//===----------------------------------------------------------------------===//
9c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//
10c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// This file is shared between AddressSanitizer and ThreadSanitizer
11c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// run-time libraries.
12c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany//===----------------------------------------------------------------------===//
13c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany#ifndef SANITIZER_STACKTRACE_H
14c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany#define SANITIZER_STACKTRACE_H
15c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
169ada1f376498647c8035f52b36d98bdf0f6363e6Kostya Serebryany#include "sanitizer_internal_defs.h"
17c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
18c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryanynamespace __sanitizer {
19c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
206d924facc5c979a0d25f484cffcdb51c766ed551Kostya Serebryanystatic const uptr kStackTraceMax = 256;
21c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__powerpc__) || \
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                        defined(__powerpc64__) || defined(__sparc__) || \
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                        defined(__mips__))
25e74968cbb29c80073e4ff440555e35f3fbed2f20Alexey Samsonov# define SANITIZER_CAN_FAST_UNWIND 0
26e74968cbb29c80073e4ff440555e35f3fbed2f20Alexey Samsonov#elif SANITIZER_WINDOWS
27e74968cbb29c80073e4ff440555e35f3fbed2f20Alexey Samsonov# define SANITIZER_CAN_FAST_UNWIND 0
28736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev#else
29e74968cbb29c80073e4ff440555e35f3fbed2f20Alexey Samsonov# define SANITIZER_CAN_FAST_UNWIND 1
30736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev#endif
31736cf49a46b3cc5aa1856762f85e6f2799c24e5aSergey Matveev
32c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryanystruct StackTrace {
33c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
34c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany                                     int out_size);
351b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov  uptr top_frame_bp;
36c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr size;
37c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr trace[kStackTraceMax];
383e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov
39a96c4dc70efa6e45b27640cdd9812e0817c9a75dAlexey Samsonov  // Prints a symbolized stacktrace, followed by an empty line.
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  static void PrintStack(const uptr *addr, uptr size);
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void Print() const {
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    PrintStack(trace, size);
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
44c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
45d09c91ac4e2f544651921b7cb307e8aaae8948d1Alexey Samsonov  void CopyFrom(const uptr *src, uptr src_size) {
461b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov    top_frame_bp = 0;
47d09c91ac4e2f544651921b7cb307e8aaae8948d1Alexey Samsonov    size = src_size;
48d09c91ac4e2f544651921b7cb307e8aaae8948d1Alexey Samsonov    if (size > kStackTraceMax) size = kStackTraceMax;
49d09c91ac4e2f544651921b7cb307e8aaae8948d1Alexey Samsonov    for (uptr i = 0; i < size; i++)
50d09c91ac4e2f544651921b7cb307e8aaae8948d1Alexey Samsonov      trace[i] = src[i];
51d09c91ac4e2f544651921b7cb307e8aaae8948d1Alexey Samsonov  }
52c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
53f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  static bool WillUseFastUnwind(bool request_fast_unwind) {
54f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    // Check if fast unwind is available. Fast unwind is the only option on Mac.
555d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    // It is also the only option on FreeBSD as the slow unwinding that
565d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    // leverages _Unwind_Backtrace() yields the call stack of the signal's
575d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    // handler and not of the code that raised the signal (as it does on Linux).
58f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    if (!SANITIZER_CAN_FAST_UNWIND)
59f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov      return false;
605d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    else if (SANITIZER_MAC != 0 || SANITIZER_FREEBSD != 0)
61f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov      return true;
62f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    return request_fast_unwind;
63f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  }
64f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void Unwind(uptr max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
66f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov              uptr stack_bottom, bool request_fast_unwind);
67f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov
68f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  static uptr GetCurrentPc();
69f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  static uptr GetPreviousInstructionPc(uptr pc);
70f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov
71f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov private:
72064da32709c8bf81283062abc04cf6e88e6c075dAlexey Samsonov  void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
73064da32709c8bf81283062abc04cf6e88e6c075dAlexey Samsonov                       uptr max_depth);
7449d616ec42ab420ce3ebcbe846b21e3729adf5acKostya Serebryany  void SlowUnwindStack(uptr pc, uptr max_depth);
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void SlowUnwindStackWithContext(uptr pc, void *context,
762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                  uptr max_depth);
774b206b33f2ed4e5a06694c9eb388aca6a0c81b58Bill Wendling  void PopStackFrames(uptr count);
786a58b0078a94195f963fede873068d7a0982c509Alexey Samsonov  uptr LocatePcInTrace(uptr pc);
79c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany};
80c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
81c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany}  // namespace __sanitizer
82c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
83c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// Use this macro if you want to print stack trace with the caller
84c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// of the current function in the top frame.
85c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany#define GET_CALLER_PC_BP_SP \
86c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr bp = GET_CURRENT_FRAME();              \
87c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr pc = GET_CALLER_PC();                  \
88c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr local_stack;                           \
89c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr sp = (uptr)&local_stack
90c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
91c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// Use this macro if you want to print stack trace with the current
92c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany// function in the top frame.
93c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany#define GET_CURRENT_PC_BP_SP \
94c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr bp = GET_CURRENT_FRAME();              \
95c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr pc = StackTrace::GetCurrentPc();   \
96c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr local_stack;                           \
97c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany  uptr sp = (uptr)&local_stack
98c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
99c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany
100c7be4077b90cae43f8e6d2d4de66ae64111dd715Kostya Serebryany#endif  // SANITIZER_STACKTRACE_H
101