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(array: reinterpret_cast<void **>(TraceBuffer), size: 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(array: reinterpret_cast<void **>(Trace), size: 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(ptr: 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