xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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/optional/backtrace.h"
17 #include "gwp_asan/options.h"
18 
19 namespace {
20 void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
21   // Grab (what seems to be) one more trace than we need. TraceBuffer needs to
22   // be null-terminated, but we wish to remove the frame of this function call.
23   static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not void*");
24   int NumTraces =
25       backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
26 
27   // Now shift the entire trace one place to the left and null-terminate.
28   memmove(TraceBuffer, TraceBuffer + 1, NumTraces * sizeof(void *));
29   TraceBuffer[NumTraces - 1] = 0;
30 }
31 
32 static void PrintBacktrace(uintptr_t *Trace,
33                            gwp_asan::options::Printf_t Printf) {
34   size_t NumTraces = 0;
35   for (; Trace[NumTraces] != 0; ++NumTraces) {
36   }
37 
38   if (NumTraces == 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), NumTraces);
45 
46   for (size_t i = 0; i < NumTraces; ++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 
59 namespace gwp_asan {
60 namespace options {
61 Backtrace_t getBacktraceFunction() { return Backtrace; }
62 PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
63 } // namespace options
64 } // namespace gwp_asan
65