-
Notifications
You must be signed in to change notification settings - Fork 0
/
BackTrace.cc
85 lines (67 loc) · 2.37 KB
/
BackTrace.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "BackTrace.hh"
#ifndef _XOPEN_SOURCE
void BackTrace::print (ostream& os) {
cerr << "backtrace not avail" << endl;
}
#else
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <unistd.h>
#include <cxxabi.h>
// Implementation based on
// http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
void BackTrace::print (ostream& os) {
cerr << "[bt]: BackTrace for process " << getpid() << ":" << endl;
const int length = 50;
void* array[length];
int size = backtrace(array, length);
char** messages = backtrace_symbols(array, size);
// skip first stack frame (points here)
for (int i = 1; i < size and messages != NULL; ++i) {
char *mangled_name = 0;
char *offset_begin = 0;
char *offset_end = 0;
// find parantheses and +address offset surrounding mangled name
for (char *p = messages[i]; *p; ++p) {
if (*p == '(') {
mangled_name = p;
} else if (*p == '+') {
offset_begin = p;
} else if (*p == ')') {
offset_end = p;
break;
}
}
// if the line could be processed, attempt to demangle the symbol
if (mangled_name and offset_begin and offset_end and mangled_name < offset_begin){
*mangled_name++ = '\0';
*offset_begin++ = '\0';
*offset_end++ = '\0';
int status;
char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
// if demangling is successful, output the demangled function name
if (status == 0) {
os << "[bt]: (" << i << ") " << messages[i] << " : "
<< real_name << "+" << offset_begin << offset_end
<< endl;
}
// otherwise, output the mangled function name
else {
os << "[bt]: (" << i << ") " << messages[i] << " : "
<< mangled_name << "+" << offset_begin << offset_end
<< endl;
}
free(real_name);
}
// otherwise, print the whole line
else {
os << "[bt]: (" << i << ") " << messages[i] << endl;
}
}
os << endl;
free(messages);
}
#endif