asan_stack.h revision 302408
1189251Ssam//===-- asan_stack.h --------------------------------------------*- C++ -*-===// 2189251Ssam// 3189251Ssam// The LLVM Compiler Infrastructure 4189251Ssam// 5189251Ssam// This file is distributed under the University of Illinois Open Source 6189251Ssam// License. See LICENSE.TXT for details. 7189251Ssam// 8189251Ssam//===----------------------------------------------------------------------===// 9189251Ssam// 10189251Ssam// This file is a part of AddressSanitizer, an address sanity checker. 11189251Ssam// 12189251Ssam// ASan-private header for asan_stack.cc. 13189251Ssam//===----------------------------------------------------------------------===// 14189251Ssam 15189251Ssam#ifndef ASAN_STACK_H 16189251Ssam#define ASAN_STACK_H 17189251Ssam 18189251Ssam#include "asan_flags.h" 19189251Ssam#include "asan_thread.h" 20189251Ssam#include "sanitizer_common/sanitizer_flags.h" 21189251Ssam#include "sanitizer_common/sanitizer_stacktrace.h" 22189251Ssam 23189251Ssamnamespace __asan { 24189251Ssam 25189251Ssamstatic const u32 kDefaultMallocContextSize = 30; 26189251Ssam 27189251Ssamvoid SetMallocContextSize(u32 size); 28189251Ssamu32 GetMallocContextSize(); 29189251Ssam 30189251Ssam// Get the stack trace with the given pc and bp. 31189251Ssam// The pc will be in the position 0 of the resulting stack trace. 32189251Ssam// The bp may refer to the current frame or to the caller's frame. 33189251SsamALWAYS_INLINE 34189251Ssamvoid GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth, 35189251Ssam uptr pc, uptr bp, void *context, 36189251Ssam bool fast) { 37189251Ssam#if SANITIZER_WINDOWS 38189251Ssam stack->Unwind(max_depth, pc, bp, context, 0, 0, fast); 39189251Ssam#else 40189251Ssam AsanThread *t; 41189251Ssam stack->size = 0; 42189251Ssam if (LIKELY(asan_inited)) { 43189251Ssam if ((t = GetCurrentThread()) && !t->isUnwinding()) { 44189251Ssam // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace() 45189251Ssam // yields the call stack of the signal's handler and not of the code 46189251Ssam // that raised the signal (as it does on Linux). 47189251Ssam if (SANITIZER_FREEBSD && t->isInDeadlySignal()) fast = true; 48189251Ssam uptr stack_top = t->stack_top(); 49189251Ssam uptr stack_bottom = t->stack_bottom(); 50189251Ssam ScopedUnwinding unwind_scope(t); 51189251Ssam stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast); 52189251Ssam } else if (!t && !fast) { 53189251Ssam /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ 54189251Ssam stack->Unwind(max_depth, pc, bp, context, 0, 0, false); 55189251Ssam } 56189251Ssam } 57189251Ssam#endif // SANITIZER_WINDOWS 58189251Ssam} 59189251Ssam 60189251Ssam} // namespace __asan 61189251Ssam 62189251Ssam// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors 63189251Ssam// as early as possible (in functions exposed to the user), as we generally 64189251Ssam// don't want stack trace to contain functions from ASan internals. 65189251Ssam 66189251Ssam#define GET_STACK_TRACE(max_size, fast) \ 67189251Ssam BufferedStackTrace stack; \ 68189251Ssam if (max_size <= 2) { \ 69189251Ssam stack.size = max_size; \ 70189251Ssam if (max_size > 0) { \ 71189251Ssam stack.top_frame_bp = GET_CURRENT_FRAME(); \ 72189251Ssam stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \ 73189251Ssam if (max_size > 1) \ 74189251Ssam stack.trace_buffer[1] = GET_CALLER_PC(); \ 75189251Ssam } \ 76189251Ssam } else { \ 77189251Ssam GetStackTraceWithPcBpAndContext(&stack, max_size, \ 78189251Ssam StackTrace::GetCurrentPc(), \ 79189251Ssam GET_CURRENT_FRAME(), 0, fast); \ 80189251Ssam } 81189251Ssam 82189251Ssam#define GET_STACK_TRACE_FATAL(pc, bp) \ 83189251Ssam BufferedStackTrace stack; \ 84189251Ssam GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \ 85189251Ssam common_flags()->fast_unwind_on_fatal) 86189251Ssam 87189251Ssam#define GET_STACK_TRACE_SIGNAL(sig) \ 88189251Ssam BufferedStackTrace stack; \ 89189251Ssam GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, \ 90189251Ssam (sig).pc, (sig).bp, (sig).context, \ 91189251Ssam common_flags()->fast_unwind_on_fatal) 92189251Ssam 93189251Ssam#define GET_STACK_TRACE_FATAL_HERE \ 94189251Ssam GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) 95189251Ssam 96189251Ssam#define GET_STACK_TRACE_CHECK_HERE \ 97189251Ssam GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check) 98189251Ssam 99189251Ssam#define GET_STACK_TRACE_THREAD \ 100189251Ssam GET_STACK_TRACE(kStackTraceMax, true) 101189251Ssam 102189251Ssam#define GET_STACK_TRACE_MALLOC \ 103189251Ssam GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc) 104189251Ssam 105189251Ssam#define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC 106189251Ssam 107189251Ssam#define PRINT_CURRENT_STACK() \ 108189251Ssam { \ 109189251Ssam GET_STACK_TRACE_FATAL_HERE; \ 110189251Ssam stack.Print(); \ 111189251Ssam } 112189251Ssam 113189251Ssam#define PRINT_CURRENT_STACK_CHECK() \ 114189251Ssam { \ 115189251Ssam GET_STACK_TRACE_CHECK_HERE; \ 116189251Ssam stack.Print(); \ 117189251Ssam } 118189251Ssam 119189251Ssam#endif // ASAN_STACK_H 120189251Ssam