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 <stddef.h>
11#include <stdint.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include "gwp_asan/definitions.h"
16#include "gwp_asan/optional/backtrace.h"
17#include "gwp_asan/optional/printf.h"
18#include "gwp_asan/options.h"
19
20#if __has_include(<execinfo.h>)
21#include <execinfo.h>
22
23namespace {
24size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
25 static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not void*");
26
27 return backtrace(array: reinterpret_cast<void **>(TraceBuffer), size: Size);
28}
29
30// We don't need any custom handling for the Segv backtrace - the libc unwinder
31// has no problems with unwinding through a signal handler. Force inlining here
32// to avoid the additional frame.
33GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size,
34 void * /*Context*/) {
35 return Backtrace(TraceBuffer, Size);
36}
37
38static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
39 gwp_asan::Printf_t Printf) {
40 if (TraceLength == 0) {
41 Printf(" <not found (does your allocator support backtracing?)>\n\n");
42 return;
43 }
44
45 char **BacktraceSymbols =
46 backtrace_symbols(array: reinterpret_cast<void **>(Trace), size: TraceLength);
47
48 for (size_t i = 0; i < TraceLength; ++i) {
49 if (!BacktraceSymbols)
50 Printf(" #%zu %p\n", i, Trace[i]);
51 else
52 Printf(" #%zu %s\n", i, BacktraceSymbols[i]);
53 }
54
55 Printf("\n");
56 if (BacktraceSymbols)
57 free(ptr: BacktraceSymbols);
58}
59} // anonymous namespace
60
61namespace gwp_asan {
62namespace backtrace {
63
64options::Backtrace_t getBacktraceFunction() { return Backtrace; }
65PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
66SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
67
68} // namespace backtrace
69} // namespace gwp_asan
70
71#else // !__has_include(<execinfo.h>)
72
73// No execinfo.h (e.g. musl libc) -- provide null stubs so GWP-ASan still
74// functions as a guard allocator without stack-trace capture.
75namespace gwp_asan {
76namespace backtrace {
77
78options::Backtrace_t getBacktraceFunction() { return nullptr; }
79PrintBacktrace_t getPrintBacktraceFunction() { return nullptr; }
80SegvBacktrace_t getSegvBacktraceFunction() { return nullptr; }
81
82} // namespace backtrace
83} // namespace gwp_asan
84
85#endif // __has_include(<execinfo.h>)
86