1//===-- backtrace_sanitizer_common.cpp --------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include <assert.h>
10#include <stddef.h>
11#include <stdint.h>
12#include <string.h>
13
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"
20
21void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
22                                                 void *context,
23                                                 bool request_fast,
24                                                 u32 max_depth) {
25  if (!StackTrace::WillUseFastUnwind(request_fast)) {
26    return Unwind(max_depth, pc, bp, context, 0, 0, request_fast);
27  }
28  Unwind(max_depth, pc, 0, context, 0, 0, false);
29}
30
31namespace {
32size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
33  __sanitizer::BufferedStackTrace Trace;
34  Trace.Reset();
35  if (Size > __sanitizer::kStackTraceMax)
36    Size = __sanitizer::kStackTraceMax;
37
38  Trace.Unwind((__sanitizer::uptr)__builtin_return_address(0),
39               (__sanitizer::uptr)__builtin_frame_address(0),
40               /* ucontext */ nullptr,
41               /* fast unwind */ true, Size - 1);
42
43  memcpy(TraceBuffer, Trace.trace, Trace.size * sizeof(uintptr_t));
44  return Trace.size;
45}
46
47static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
48                           gwp_asan::options::Printf_t Printf) {
49  __sanitizer::StackTrace StackTrace;
50  StackTrace.trace = reinterpret_cast<__sanitizer::uptr *>(Trace);
51  StackTrace.size = TraceLength;
52
53  if (StackTrace.size == 0) {
54    Printf("  <unknown (does your allocator support backtracing?)>\n\n");
55    return;
56  }
57
58  StackTrace.Print();
59}
60} // anonymous namespace
61
62namespace gwp_asan {
63namespace options {
64// This function is thread-compatible. It must be synchronised in respect to any
65// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
66// and calls to either of the functions that they return. Furthermore, this may
67// require synchronisation with any calls to sanitizer_common that use flags.
68// Generally, this function will be called during the initialisation of the
69// allocator, which is done in a thread-compatible manner.
70Backtrace_t getBacktraceFunction() {
71  // The unwinder requires the default flags to be set.
72  __sanitizer::SetCommonFlagsDefaults();
73  __sanitizer::InitializeCommonFlags();
74  return Backtrace;
75}
76PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
77} // namespace options
78} // namespace gwp_asan
79