1 //===-- backtrace_sanitizer_common.cpp --------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
14 #include "gwp_asan/optional/backtrace.h"
15 #include "gwp_asan/options.h"
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_flag_parser.h"
18 #include "sanitizer_common/sanitizer_flags.h"
19 #include "sanitizer_common/sanitizer_stacktrace.h"
21 void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc
, uptr bp
,
25 if (!StackTrace::WillUseFastUnwind(request_fast
))
26 return Unwind(max_depth
, pc
, 0, context
, 0, 0, false);
30 GetThreadStackTopAndBottom(/*at_initialization*/ false, &top
, &bottom
);
32 return Unwind(max_depth
, pc
, bp
, context
, top
, bottom
, request_fast
);
36 size_t BacktraceCommon(uintptr_t *TraceBuffer
, size_t Size
, void *Context
) {
37 // Use the slow sanitizer unwinder in the segv handler. Fast frame pointer
38 // unwinders can end up dropping frames because the kernel sigreturn() frame's
39 // return address is the return address at time of fault. This has the result
40 // of never actually capturing the PC where the signal was raised.
41 bool UseFastUnwind
= (Context
== nullptr);
43 __sanitizer::BufferedStackTrace Trace
;
45 if (Size
> __sanitizer::kStackTraceMax
)
46 Size
= __sanitizer::kStackTraceMax
;
48 Trace
.Unwind((__sanitizer::uptr
)__builtin_return_address(0),
49 (__sanitizer::uptr
)__builtin_frame_address(0), Context
,
50 UseFastUnwind
, Size
- 1);
52 memcpy(TraceBuffer
, Trace
.trace
, Trace
.size
* sizeof(uintptr_t));
56 size_t Backtrace(uintptr_t *TraceBuffer
, size_t Size
) {
57 return BacktraceCommon(TraceBuffer
, Size
, nullptr);
60 size_t SegvBacktrace(uintptr_t *TraceBuffer
, size_t Size
, void *Context
) {
61 return BacktraceCommon(TraceBuffer
, Size
, Context
);
64 static void PrintBacktrace(uintptr_t *Trace
, size_t TraceLength
,
65 gwp_asan::Printf_t Printf
) {
66 __sanitizer::StackTrace StackTrace
;
67 StackTrace
.trace
= reinterpret_cast<__sanitizer::uptr
*>(Trace
);
68 StackTrace
.size
= TraceLength
;
70 if (StackTrace
.size
== 0) {
71 Printf(" <unknown (does your allocator support backtracing?)>\n\n");
75 __sanitizer::InternalScopedString buffer
;
76 StackTrace
.PrintTo(&buffer
);
77 Printf("%s\n", buffer
.data());
79 } // anonymous namespace
84 // This function is thread-compatible. It must be synchronised in respect to any
85 // other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
86 // and calls to either of the functions that they return. Furthermore, this may
87 // require synchronisation with any calls to sanitizer_common that use flags.
88 // Generally, this function will be called during the initialisation of the
89 // allocator, which is done in a thread-compatible manner.
90 options::Backtrace_t
getBacktraceFunction() {
91 // The unwinder requires the default flags to be set.
92 __sanitizer::SetCommonFlagsDefaults();
93 __sanitizer::InitializeCommonFlags();
97 PrintBacktrace_t
getPrintBacktraceFunction() { return PrintBacktrace
; }
98 SegvBacktrace_t
getSegvBacktraceFunction() { return SegvBacktrace
; }
100 } // namespace backtrace
101 } // namespace gwp_asan