qBittorrent
stacktrace.h File Reference
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#include <cxxabi.h>
#include <vector>
Include dependency graph for stacktrace.h:

Go to the source code of this file.

Functions

static void print_stacktrace (FILE *out=stderr, unsigned int max_frames=63)
 

Function Documentation

◆ print_stacktrace()

static void print_stacktrace ( FILE *  out = stderr,
unsigned int  max_frames = 63 
)
inlinestatic

Print a demangled stack backtrace of the caller function to FILE* out.

Definition at line 15 of file stacktrace.h.

16 {
17  fprintf(out, "Stack trace:\n");
18 
19  // storage array for stack trace address data
20  std::vector<void *> addrlist(max_frames + 1);
21 
22  // retrieve current stack addresses
23  int addrlen = backtrace(addrlist.data(), addrlist.size());
24 
25  if (addrlen == 0)
26  {
27  fprintf(out, " <empty, possibly corrupt>\n");
28  return;
29  }
30 
31  // resolve addresses into strings containing "filename(function+address)",
32  // this array must be free()-ed
33  char * *symbollist = backtrace_symbols(addrlist.data(), addrlen);
34 
35  // allocate string which will be filled with the demangled function name
36  size_t funcnamesize = 256;
37  char *funcname = static_cast<char *>(malloc(funcnamesize));
38 
39  int functionNamesFound = 0;
40  // iterate over the returned symbol lines. skip the first, it is the
41  // address of this function.
42  for (int i = 2; i < addrlen; i++)
43  {
44  char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
45 
46  // find parentheses and +address offset surrounding the mangled name:
47  // ./module(function+0x15c) [0x8048a6d]
48  // fprintf(out, "%s TT\n", symbollist[i]);
49  for (char *p = symbollist[i]; *p; ++p)
50  {
51  if (*p == '(')
52  {
53  begin_name = p;
54  }
55  else if (*p == '+')
56  {
57  begin_offset = p;
58  }
59  else if ((*p == ')') && begin_offset)
60  {
61  end_offset = p;
62  break;
63  }
64  }
65 
66  if (begin_name && begin_offset && end_offset
67  && (begin_name < begin_offset))
68  {
69  *begin_name++ = '\0';
70  *begin_offset++ = '\0';
71  *end_offset = '\0';
72 
73  // mangled name is now in [begin_name, begin_offset) and caller
74  // offset in [begin_offset, end_offset). now apply
75  // __cxa_demangle():
76 
77  int status;
78  char *ret = abi::__cxa_demangle(begin_name,
79  funcname, &funcnamesize, &status);
80  if (status == 0)
81  {
82  funcname = ret; // use possibly realloc()-ed string
83  fprintf(out, " %s : %s+%s %s\n",
84  symbollist[i], funcname, begin_offset, ++end_offset);
85  }
86  else
87  {
88  // demangling failed. Output function name as a C function with
89  // no arguments.
90  fprintf(out, " %s : %s()+%s %s\n",
91  symbollist[i], begin_name, begin_offset, ++end_offset);
92  }
93  ++functionNamesFound;
94  }
95  else
96  {
97  // couldn't parse the line? print the whole line.
98  fprintf(out, " %s\n", symbollist[i]);
99  }
100  }
101 
102  if (!functionNamesFound)
103  {
104  fprintf(out, "There were no function names found in the stack trace\n."
105  "Seems like debug symbols are not installed, and the stack trace is useless.\n");
106  }
107  if (functionNamesFound < addrlen - 2)
108  {
109  fprintf(out, "Consider installing debug symbols for packages containing files with empty"
110  " function names (i.e. empty braces \"()\") to make your stack trace more useful\n");
111  }
112  free(funcname);
113  free(symbollist);
114 }