Thrill  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
backtrace.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * tlx/backtrace.cpp
3  *
4  * Part of tlx - http://panthema.net/tlx
5  *
6  * Copyright (C) 2008-2017 Timo Bingmann <[email protected]>
7  *
8  * All rights reserved. Published under the Boost Software License, Version 1.0
9  ******************************************************************************/
10 
11 #include <tlx/backtrace.hpp>
12 
13 #include <tlx/unused.hpp>
14 
15 #include <cstdarg>
16 #include <cstdio>
17 #include <cstdlib>
18 
19 #if __linux__
20 
21 #include <cxxabi.h>
22 #include <execinfo.h>
23 
24 #endif
25 
26 namespace tlx {
27 
28 void print_raw_backtrace(FILE* out, unsigned int max_frames,
29  const char* fmt, ...) {
30  va_list args;
31  va_start(args, fmt);
32 
33  vfprintf(out, fmt, args);
34 
35 #if __linux__
36 
37  // storage array for stack trace address data
38  void** addrlist = reinterpret_cast<void**>(
39  alloca(sizeof(void*) * max_frames));
40 
41  // retrieve current stack addresses
42  int addrlen = backtrace(addrlist, max_frames);
43 
44  for (int i = 1; i < addrlen; ++i) {
45  if (addrlist[i] == nullptr)
46  break;
47 
48  fprintf(out, " %p", addrlist[i]);
49  }
50 
51  fprintf(out, "\n");
52 
53 #else
54 
55  fprintf(out, "(backtrace not supported on this platform)\n");
56  tlx::unused(max_frames);
57 
58 #endif
59 
60  va_end(args);
61 }
62 
63 void print_raw_backtrace(FILE* out, unsigned int max_frames) {
64  return print_raw_backtrace(out, max_frames, "backtrace:");
65 }
66 
67 void print_cxx_backtrace(FILE* out, unsigned int max_frames) {
68  fprintf(out, "backtrace:\n");
69 
70 #if __linux__
71 
72  // storage array for stack trace address data
73  void** addrlist = reinterpret_cast<void**>(
74  alloca(sizeof(void*) * max_frames));
75 
76  // retrieve current stack addresses
77  int addrlen = backtrace(addrlist, max_frames);
78 
79  if (addrlen == 0) {
80  fprintf(out, " <empty, possibly corrupt>\n");
81  return;
82  }
83 
84  // resolve addresses into strings containing "filename(function+address)",
85  // this array must be free()-ed
86  char** symbollist = backtrace_symbols(addrlist, addrlen);
87 
88  // allocate string which will be filled with the demangled function name
89  size_t funcnamesize = 256;
90  char* funcname = (char*)malloc(funcnamesize);
91 
92  // iterate over the returned symbol lines. skip the first, it is the
93  // address of this function.
94  for (int i = 1; i < addrlen; i++)
95  {
96  char* begin_name = 0, * begin_offset = 0, * end_offset = 0;
97 
98  // find parentheses and +address offset surrounding the mangled name:
99  // ./module(function+0x15c) [0x8048a6d]
100  for (char* p = symbollist[i]; *p; ++p)
101  {
102  if (*p == '(')
103  begin_name = p;
104  else if (*p == '+')
105  begin_offset = p;
106  else if (*p == ')' && begin_offset) {
107  end_offset = p;
108  break;
109  }
110  }
111 
112  if (begin_name && begin_offset && end_offset
113  && begin_name < begin_offset)
114  {
115  *begin_name++ = '\0';
116  *begin_offset++ = '\0';
117  *end_offset = '\0';
118 
119  // mangled name is now in [begin_name, begin_offset) and caller
120  // offset in [begin_offset, end_offset). now apply
121  // __cxa_demangle():
122 
123  int status;
124  char* ret = abi::__cxa_demangle(begin_name,
125  funcname, &funcnamesize, &status);
126  if (status == 0) {
127  funcname = ret; // use possibly realloc()-ed string
128  fprintf(out, " %s : %s+%s\n",
129  symbollist[i], funcname, begin_offset);
130  }
131  else {
132  // demangling failed. Output function name as a C function with
133  // no arguments.
134  fprintf(out, " %s : %s()+%s\n",
135  symbollist[i], begin_name, begin_offset);
136  }
137  }
138  else
139  {
140  // couldn't parse the line? print the whole line.
141  fprintf(out, " %s\n", symbollist[i]);
142  }
143  }
144 
145  free(funcname);
146  free(symbollist);
147 
148 #else
149 
150  fprintf(out, " (not supported on this platform)\n");
151  tlx::unused(max_frames);
152 
153 #endif
154 }
155 
156 } // namespace tlx
157 
158 /******************************************************************************/
void unused(Types &&...)
Definition: unused.hpp:20
void * malloc(size_t size) NOEXCEPT
exported malloc symbol that overrides loading from libc
void free(void *ptr) NOEXCEPT
exported free symbol that overrides loading from libc
void print_cxx_backtrace(FILE *out, unsigned int max_frames)
Print a demangled stack backtrace of the caller function to FILE* out.
Definition: backtrace.cpp:67
void print_raw_backtrace(FILE *out, unsigned int max_frames, const char *fmt,...)
Print a plain hex stack backtrace of the called function to FILE* out, prefixed with the given printf...
Definition: backtrace.cpp:28