-
Notifications
You must be signed in to change notification settings - Fork 499
Expand file tree
/
Copy pathBacktraceHelpers.cxx
More file actions
132 lines (121 loc) · 4.02 KB
/
BacktraceHelpers.cxx
File metadata and controls
132 lines (121 loc) · 4.02 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#include "Framework/BacktraceHelpers.h"
#include <climits>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <cxxabi.h>
#include <execinfo.h>
namespace o2::framework
{
void BacktraceHelpers::demangled_backtrace_symbols(void** stackTrace, unsigned int stackDepth, int fd)
{
char** stackStrings;
stackStrings = backtrace_symbols(stackTrace, stackDepth);
char exe[PATH_MAX];
bool hasExe = false;
int exeSize = 0;
#if __linux__
exeSize = readlink("/proc/self/exe", exe, PATH_MAX);
if (exeSize == -1) {
dprintf(fd, "Unable to detect exectuable name\n");
hasExe = false;
} else {
dprintf(fd, "Executable is %.*s\n", exeSize, exe);
hasExe = true;
}
#endif
// We skip the level 0, which is the actual logging function.
for (size_t i = 1; i < stackDepth; i++) {
size_t sz = 64000; // 64K ought to be enough for our templates...
char* function = static_cast<char*>(malloc(sz));
char *begin = nullptr, *end = nullptr;
// find the last space and address offset surrounding the mangled name
#if __APPLE__
for (char* j = stackStrings[i]; *j; ++j) {
if (*j == ' ' && *(j + 1) != '+') {
begin = j;
} else if (*j == ' ' && *(j + 1) == '+') {
end = j;
break;
}
}
bool tryAddr2Line = false;
#else
for (char* j = stackStrings[i]; j && *j; ++j) {
if (*j == '(') {
begin = j;
} else if (*j == '+') {
end = j;
break;
}
}
bool tryAddr2Line = true;
#endif
if (begin && end) {
// The first byte is a ' ' which we need to skip.
*begin++ = '\0';
*end = '\0';
// found our mangled name, now in [begin, end)
int status;
char* ret = abi::__cxa_demangle(begin, function, &sz, &status);
if (status == 0) {
// return value may be a realloc() of the input
function = ret;
dprintf(fd, " %s: %s\n", stackStrings[i], function);
tryAddr2Line = false;
} else {
tryAddr2Line = true;
}
}
if (tryAddr2Line) {
// didn't find the mangled name, just print the whole line
dprintf(fd, " %s: ", stackStrings[i]);
if (stackTrace[i] && hasExe) {
char syscom[4096 + PATH_MAX];
// Find c++filt from the environment
// This is needed for platforms where we still need c++filt -r
static char const* cxxfilt = getenv("CXXFILT");
if (cxxfilt == nullptr) {
cxxfilt = "c++filt";
}
// Do the same for addr2line, just in case we wanted to pass some options
static char const* addr2line = getenv("ADDR2LINE");
if (addr2line == nullptr) {
addr2line = "addr2line";
}
snprintf(syscom, 4096, "%s %p -p -s -f -e %.*s 2>/dev/null | %s ", addr2line, stackTrace[i], exeSize, exe, cxxfilt); // last parameter is the name of this app
FILE* fp;
char path[1024];
fp = popen(syscom, "r");
if (fp == nullptr) {
// We could not run addr2line, print whatever we have.
// Also free function, which is allocated at the beginning of the loop.
dprintf(fd, "%s\n", begin);
free(function);
continue;
}
while (fgets(path, sizeof(path) - 1, fp) != nullptr) {
dprintf(fd, " %s", path);
}
pclose(fp);
} else {
dprintf(fd, "%s\n", begin);
}
}
free(function);
}
free(stackStrings); // malloc()ed by backtrace_symbols
fsync(fd);
}
} // namespace o2::framework