Inexor
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StackWalker_posix.hpp
Go to the documentation of this file.
1 #pragma once
4 
5 #include <execinfo.h>
6 #include <stdlib.h>
7 #include <cxxabi.h>
8 #include <vector>
9 #include <string.h>
10 #include <string>
12 
13 namespace inexor {
14 namespace crashreporter {
15 // TODO: Rewrite the c string splitting with c++.
16 
17 #ifdef DARWIN
18 static inline void demanglesymbol(std::vector<std::string> &output, char *symbol)
19 {
20  char* begin_name = NULL;
21  char* begin_offset = NULL;
22  char* end_offset = NULL;
23 
24  // find parentheses and +address offset surrounding the mangled name
25  for(char *p = symbol; *p; ++p)
26  {
27  if((*p == '_') && (*(p - 1) == ' ')) begin_name = p - 1;
28  else if(*p == '+') begin_offset = p - 1;
29  }
30 
31  if(begin_name && begin_offset && (begin_name < begin_offset))
32  {
33  *begin_name++ = '\0';
34  *begin_offset++ = '\0';
35 
36  // mangled name is now in [begin_name, begin_offset) and caller
37  // offset in [begin_offset, end_offset). now apply __cxa_demangle():
38  int status;
39  size_t funcnamesize = 1024;
40  char funcname[1024];
41 
42  char *shortsymbol = strrchr(symbol, '/'); //not useful info
43  if(shortsymbol) symbol = (shortsymbol + 1);
44 
45  char* ret = abi::__cxa_demangle(begin_name, &funcname[0], &funcnamesize, &status);
46  if(status == 0)
47  {
48  std::string out = inexor::util::fmt << " " << symbol << " " << ret << "\n";
49  output.push_back(std::move(out));
50  }
51  else {
52  // demangling failed. Output function name as a C function with no arguments.
53  std::string out = inexor::util::fmt << " " << symbol << " " << begin_name << "()\n";
54  output.push_back(std::move(out));
55  }
56  }
57  else {
58  // couldn't parse the line? print the whole line.
59  std::string out = inexor::util::fmt << " " << symbol << "\n";
60  output.push_back(std::move(out));
61  }
62 }
63 #else //NOT DARWIN (-> LINUX)
64 
65 static inline void demanglesymbol(std::vector<std::string> &output, char *symbol)
66 {
67  //before: ./module(function+0x15c) [0x8048a6d]
68  char* begin_name = nullptr;
69  char* begin_offset = nullptr;
70  char* end_offset = nullptr;
71 
72  // find parentheses and +address offset surrounding the mangled name
73  for(char *p = symbol; *p; ++p)
74  {
75  if(*p == '(') begin_name = p;
76  else if(*p == '+') begin_offset = p;
77  else if(*p == ')' && (begin_offset || begin_name)) end_offset = p;
78  }
79 
80  if(begin_name && end_offset && (begin_name < end_offset))
81  {
82  *begin_name++ = '\0';
83  *end_offset++ = '\0';
84  if(begin_offset) *begin_offset++ = '\0';
85 
86  // mangled name is now in [begin_name, begin_offset) and caller
87  // offset in [begin_offset, end_offset). now apply __cxa_demangle():
88 
89  int status = 0;
90  size_t funcnamesize = 1024;
91  char funcname[1024];
92 
93  char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
94  char* fname = begin_name;
95  if(status == 0) fname = ret;
96 
97  char *shortsymbol = strrchr(symbol, '/');
98  if(shortsymbol) symbol = (shortsymbol + 1);
99  std::string out = inexor::util::fmt << " " << symbol << " ( " << fname << " )\n";
100  output.push_back(std::move(out));
101  }
102  else {
103  // couldn't parse the line? print the whole line.
104  std::string out = inexor::util::fmt << " " << symbol << "\n";
105  output.push_back(std::move(out));
106  }
107 }
108 #endif // LINUX
109 
110 #define MAX_FRAMES 31
111 
112 static inline void printStackTrace(std::vector<std::string> &output)
113 {
114  output.push_back("stack trace:\n");
115 
116  // storage array for stack trace address data
117  void* addrlist[MAX_FRAMES + 1];
118 
119  // retrieve current stack addresses
120  unsigned int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
121 
122  if(addrlen == 0)
123  {
124  output.push_back(" \n");
125  return;
126  }
127 
128  // resolve addresses into strings containing "filename(function+address)",
129  // Actually it will be ## program address function + offset
130  // this array must be free()-ed
131  char** symbollist = backtrace_symbols(addrlist, addrlen);
132 
133  // iterate over the returned symbol lines. skip the first, it is the
134  // address of this function.
135  for(unsigned int i = 4; i < addrlen; i++)
136  {
137  demanglesymbol(output, symbollist[i]);
138  }
139 
140  free(symbollist);
141 }
142 
143 } // namespace crashreporter
144 } // namespace inexor
145 
static void printStackTrace(std::vector< std::string > &output)
Definition: StackWalker_posix.hpp:112
StringFormatter::FmtMark fmt
Marker that starts formatting a string.
Definition: StringFormatter.cpp:5
#define MAX_FRAMES
Definition: StackWalker_posix.hpp:110
#define NULL
Definition: cube_types.hpp:35
bool move(physent *d, vec &dir)
Definition: physics.cpp:1342
char string[MAXSTRLEN]
cube-strings (char arrays of fixed size).
Definition: cube_types.hpp:18
static void demanglesymbol(std::vector< std::string > &output, char *symbol)
Definition: StackWalker_posix.hpp:65