1//===-- backtrace_linux_libc.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 <execinfo.h>
11#include <stddef.h>
12#include <stdint.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "gwp_asan/definitions.h"
17#include "gwp_asan/optional/backtrace.h"
18#include "gwp_asan/optional/printf.h"
19#include "gwp_asan/options.h"
20
21namespace {
22size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
23  static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not void*");
24
25  return backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
26}
27
28// We don't need any custom handling for the Segv backtrace - the libc unwinder
29// has no problems with unwinding through a signal handler. Force inlining here
30// to avoid the additional frame.
31GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size,
32                                            void * /*Context*/) {
33  return Backtrace(TraceBuffer, Size);
34}
35
36static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
37                           gwp_asan::Printf_t Printf) {
38  if (TraceLength == 0) {
39    Printf("  <not found (does your allocator support backtracing?)>\n\n");
40    return;
41  }
42
43  char **BacktraceSymbols =
44      backtrace_symbols(reinterpret_cast<void **>(Trace), TraceLength);
45
46  for (size_t i = 0; i < TraceLength; ++i) {
47    if (!BacktraceSymbols)
48      Printf("  #%zu %p\n", i, Trace[i]);
49    else
50      Printf("  #%zu %s\n", i, BacktraceSymbols[i]);
51  }
52
53  Printf("\n");
54  if (BacktraceSymbols)
55    free(BacktraceSymbols);
56}
57} // anonymous namespace
58
59namespace gwp_asan {
60namespace backtrace {
61
62options::Backtrace_t getBacktraceFunction() { return Backtrace; }
63PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
64SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
65
66} // namespace backtrace
67} // namespace gwp_asan
68