blob: 5042f230188a960da74c09c85b0804b2436812d9 [file] [log] [blame]
Kostya Serebryanyc7be4072012-08-28 14:27:06 +00001//===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_STACKTRACE_H
14#define SANITIZER_STACKTRACE_H
15
Kostya Serebryany9ada1f32012-08-28 14:48:28 +000016#include "sanitizer_internal_defs.h"
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000017
18namespace __sanitizer {
19
Kostya Serebryany6d924fa2012-09-06 10:57:03 +000020static const uptr kStackTraceMax = 256;
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000021
Sergey Matveev736cf492013-05-08 12:45:55 +000022#if SANITIZER_LINUX && (defined(__arm__) || \
23 defined(__powerpc__) || defined(__powerpc64__) || \
Kostya Serebryany40527a52013-06-03 14:49:25 +000024 defined(__sparc__) || \
25 defined(__mips__))
Alexey Samsonove74968c2013-11-07 06:33:06 +000026# define SANITIZER_CAN_FAST_UNWIND 0
27#elif SANITIZER_WINDOWS
28# define SANITIZER_CAN_FAST_UNWIND 0
Sergey Matveev736cf492013-05-08 12:45:55 +000029#else
Alexey Samsonove74968c2013-11-07 06:33:06 +000030# define SANITIZER_CAN_FAST_UNWIND 1
Sergey Matveev736cf492013-05-08 12:45:55 +000031#endif
32
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000033struct StackTrace {
34 typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
35 int out_size);
Alexey Samsonov1b17f5b2013-11-13 14:46:58 +000036 uptr top_frame_bp;
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000037 uptr size;
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000038 uptr trace[kStackTraceMax];
Alexey Samsonov3e0b8ff2013-10-12 12:40:47 +000039
Alexey Samsonova96c4dc2013-11-01 00:19:46 +000040 // Prints a symbolized stacktrace, followed by an empty line.
Alexey Samsonov7996a2e2013-10-29 05:31:25 +000041 static void PrintStack(const uptr *addr, uptr size,
42 SymbolizeCallback symbolize_callback = 0);
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000043
Alexey Samsonovd09c91a2013-10-14 07:36:10 +000044 void CopyFrom(const uptr *src, uptr src_size) {
Alexey Samsonov1b17f5b2013-11-13 14:46:58 +000045 top_frame_bp = 0;
Alexey Samsonovd09c91a2013-10-14 07:36:10 +000046 size = src_size;
47 if (size > kStackTraceMax) size = kStackTraceMax;
48 for (uptr i = 0; i < size; i++)
49 trace[i] = src[i];
50 }
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000051
Alexey Samsonovf16dc422013-11-07 07:28:33 +000052 static bool WillUseFastUnwind(bool request_fast_unwind) {
53 // Check if fast unwind is available. Fast unwind is the only option on Mac.
54 if (!SANITIZER_CAN_FAST_UNWIND)
55 return false;
56 else if (SANITIZER_MAC)
57 return true;
58 return request_fast_unwind;
59 }
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000060
Alexey Samsonovf16dc422013-11-07 07:28:33 +000061 void Unwind(uptr max_depth, uptr pc, uptr bp, uptr stack_top,
62 uptr stack_bottom, bool request_fast_unwind);
Kostya Serebryanyd7d46502012-11-20 07:00:42 +000063
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000064 static uptr GetCurrentPc();
Alexey Samsonovd2f08ff2012-12-18 09:57:34 +000065 static uptr GetPreviousInstructionPc(uptr pc);
Alexey Samsonovf16dc422013-11-07 07:28:33 +000066
67 private:
68 void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
69 uptr max_depth);
70 void SlowUnwindStack(uptr pc, uptr max_depth);
71 void PopStackFrames(uptr count);
Alexey Samsonov6a58b002013-11-15 10:57:56 +000072 uptr LocatePcInTrace(uptr pc);
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000073};
74
Kostya Serebryanyc7be4072012-08-28 14:27:06 +000075} // namespace __sanitizer
76
77// Use this macro if you want to print stack trace with the caller
78// of the current function in the top frame.
79#define GET_CALLER_PC_BP_SP \
80 uptr bp = GET_CURRENT_FRAME(); \
81 uptr pc = GET_CALLER_PC(); \
82 uptr local_stack; \
83 uptr sp = (uptr)&local_stack
84
85// Use this macro if you want to print stack trace with the current
86// function in the top frame.
87#define GET_CURRENT_PC_BP_SP \
88 uptr bp = GET_CURRENT_FRAME(); \
89 uptr pc = StackTrace::GetCurrentPc(); \
90 uptr local_stack; \
91 uptr sp = (uptr)&local_stack
92
93
94#endif // SANITIZER_STACKTRACE_H