plebble
stacktrace.h
Go to the documentation of this file.
1 /*
2 -------------------------------------------------------------------------------
3  PLEBBLE
4 -------------------------------------------------------------------------------
5  Copyright (C) 2019-2020 KATLAS Technology. (http://katlastechnology.com)
6  Copyright (C) 2017-2020 Marcos Mayorga. (mm@mm-studios.com)
7 
8  This file is part of our Plebble(R) Platform.
9 
10  The code below cannot be copied, used for any purpose other than the one
11  agreed and/or distributed without the express permission of
12  KATLAS Technology.
13 -------------------------------------------------------------------------------
14 
15 
16 */
17 #ifndef USGOV_49d1d337b2a0fc5c7d3988c513a828859517ba9520f1dbc3182719bf4ee878d6
18 #define USGOV_49d1d337b2a0fc5c7d3988c513a828859517ba9520f1dbc3182719bf4ee878d6
19 
20 // stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
21 // published under the WTFPL v2.0
22 // Print a demangled stack backtrace of the caller function to FILE* out.
23 #include <iostream>
24 
25 #if defined(__GLIBC__)
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <execinfo.h>
30 #include <cxxabi.h>
31 
32 static inline void print_stacktrace_release(std::ostream& out, unsigned int max_frames = 10) {
33  out << "stack trace:" << std::endl;
34 
35  // storage array for stack trace address data
36  void* addrlist[max_frames+1];
37 
38  // retrieve current stack addresses
39  int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
40 
41  if (addrlen == 0) {
42  out << " <empty, possibly corrupt>" << std::endl;
43  return;
44  }
45 
46  // resolve addresses into strings containing "filename(function+address)",
47  // this array must be free()-ed
48  char** symbollist = backtrace_symbols(addrlist, addrlen);
49 
50  // allocate string which will be filled with the demangled function name
51  size_t funcnamesize = 256;
52  char* funcname = (char*)malloc(funcnamesize);
53 
54  // iterate over the returned symbol lines. skip the first, it is the
55  // address of this function.
56  for (int i = 1; i < addrlen; i++) {
57  char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
58 
59  // find parentheses and +address offset surrounding the mangled name:
60  // ./module(function+0x15c) [0x8048a6d]
61  for (char *p = symbollist[i]; *p; ++p)
62  {
63  if (*p == '(')
64  begin_name = p;
65  else if (*p == '+')
66  begin_offset = p;
67  else if (*p == ')' && begin_offset) {
68  end_offset = p;
69  break;
70  }
71  }
72 
73  if (begin_name && begin_offset && end_offset && begin_name < begin_offset) {
74  *begin_name++ = '\0';
75  *begin_offset++ = '\0';
76  *end_offset = '\0';
77  int status;
78  char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
79  if (status == 0) {
80  funcname = ret;
81  out << " " << symbollist[i] << " : " << funcname << "+" << begin_offset << std::endl;
82  }
83  else {
84  out << " " << symbollist[i] << " : " << begin_name << "()+" << begin_offset << std::endl;
85  }
86  }
87  else {
88  out << " " << symbollist[i] << std::endl;
89  }
90  }
91 
92  free(funcname);
93  free(symbollist);
94 }
95 
96 #ifdef DEBUG
97  static inline void print_stacktrace(std::ostream& out, unsigned int max_frames = 10) {
98  print_stacktrace_release(out, max_frames);
99  }
100 #else
101  #define print_stacktrace (void)sizeof
102 #endif
103 #else
104  #define print_stacktrace (void)sizeof
105 #endif
106 #endif
print_stacktrace
#define print_stacktrace
Definition: stacktrace.h:104