1*5f757f3fSDimitry Andric //===------------------ sanitizer_unwind_fuchsia.cpp 2*5f757f3fSDimitry Andric //---------------------------===// 3*5f757f3fSDimitry Andric // 4*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*5f757f3fSDimitry Andric // 8*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 9*5f757f3fSDimitry Andric // 10*5f757f3fSDimitry Andric /// Sanitizer unwind Fuchsia specific functions. 11*5f757f3fSDimitry Andric // 12*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 13*5f757f3fSDimitry Andric 14*5f757f3fSDimitry Andric #include "sanitizer_platform.h" 15*5f757f3fSDimitry Andric #if SANITIZER_FUCHSIA 16*5f757f3fSDimitry Andric 17*5f757f3fSDimitry Andric # include <limits.h> 18*5f757f3fSDimitry Andric # include <unwind.h> 19*5f757f3fSDimitry Andric 20*5f757f3fSDimitry Andric # include "sanitizer_common.h" 21*5f757f3fSDimitry Andric # include "sanitizer_stacktrace.h" 22*5f757f3fSDimitry Andric 23*5f757f3fSDimitry Andric namespace __sanitizer { 24*5f757f3fSDimitry Andric 25*5f757f3fSDimitry Andric # if SANITIZER_CAN_SLOW_UNWIND 26*5f757f3fSDimitry Andric struct UnwindTraceArg { 27*5f757f3fSDimitry Andric BufferedStackTrace *stack; 28*5f757f3fSDimitry Andric u32 max_depth; 29*5f757f3fSDimitry Andric }; 30*5f757f3fSDimitry Andric 31*5f757f3fSDimitry Andric _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { 32*5f757f3fSDimitry Andric UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param); 33*5f757f3fSDimitry Andric CHECK_LT(arg->stack->size, arg->max_depth); 34*5f757f3fSDimitry Andric uptr pc = _Unwind_GetIP(ctx); 35*5f757f3fSDimitry Andric if (pc < GetPageSizeCached()) 36*5f757f3fSDimitry Andric return _URC_NORMAL_STOP; 37*5f757f3fSDimitry Andric arg->stack->trace_buffer[arg->stack->size++] = pc; 38*5f757f3fSDimitry Andric return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP 39*5f757f3fSDimitry Andric : _URC_NO_REASON); 40*5f757f3fSDimitry Andric } 41*5f757f3fSDimitry Andric 42*5f757f3fSDimitry Andric void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { 43*5f757f3fSDimitry Andric CHECK_GE(max_depth, 2); 44*5f757f3fSDimitry Andric size = 0; 45*5f757f3fSDimitry Andric UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)}; 46*5f757f3fSDimitry Andric _Unwind_Backtrace(Unwind_Trace, &arg); 47*5f757f3fSDimitry Andric CHECK_GT(size, 0); 48*5f757f3fSDimitry Andric // We need to pop a few frames so that pc is on top. 49*5f757f3fSDimitry Andric uptr to_pop = LocatePcInTrace(pc); 50*5f757f3fSDimitry Andric // trace_buffer[0] belongs to the current function so we always pop it, 51*5f757f3fSDimitry Andric // unless there is only 1 frame in the stack trace (1 frame is always better 52*5f757f3fSDimitry Andric // than 0!). 53*5f757f3fSDimitry Andric PopStackFrames(Min(to_pop, static_cast<uptr>(1))); 54*5f757f3fSDimitry Andric trace_buffer[0] = pc; 55*5f757f3fSDimitry Andric } 56*5f757f3fSDimitry Andric 57*5f757f3fSDimitry Andric void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { 58*5f757f3fSDimitry Andric CHECK(context); 59*5f757f3fSDimitry Andric CHECK_GE(max_depth, 2); 60*5f757f3fSDimitry Andric UNREACHABLE("signal context doesn't exist"); 61*5f757f3fSDimitry Andric } 62*5f757f3fSDimitry Andric # endif // SANITIZER_CAN_SLOW_UNWIND 63*5f757f3fSDimitry Andric 64*5f757f3fSDimitry Andric } // namespace __sanitizer 65*5f757f3fSDimitry Andric 66*5f757f3fSDimitry Andric #endif // SANITIZER_FUCHSIA 67