1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 by the Quassel Project * |
3 | * devel@quassel-irc.org * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) version 3. * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
19 | ***************************************************************************/ |
20 | |
21 | #include "quassel.h" |
22 | |
23 | #if defined(HAVE_EXECINFO) && !defined(Q_OS_MAC) |
24 | # define BUILD_CRASHHANDLER |
25 | # include <execinfo.h> |
26 | # include <dlfcn.h> |
27 | # include <cxxabi.h> |
28 | # include <QFile> |
29 | # include <QTextStream> |
30 | # include <QDebug> |
31 | #endif |
32 | |
33 | void Quassel::logBacktrace(const QString &filename) |
34 | { |
35 | #ifndef BUILD_CRASHHANDLER |
36 | Q_UNUSED(filename) |
37 | #else |
38 | void *callstack[128]; |
39 | int i, frames = backtrace(callstack, 128); |
40 | |
41 | QFile dumpFile(filename); |
42 | dumpFile.open(QIODevice::Append); |
43 | QTextStream dumpStream(&dumpFile); |
44 | |
45 | for (i = 0; i < frames; ++i) { |
46 | Dl_info info; |
47 | dladdr(callstack[i], &info); |
48 | // as a reference: |
49 | // typedef struct |
50 | // { |
51 | // __const char *dli_fname; /* File name of defining object. */ |
52 | // void *dli_fbase; /* Load address of that object. */ |
53 | // __const char *dli_sname; /* Name of nearest symbol. */ |
54 | // void *dli_saddr; /* Exact value of nearest symbol. */ |
55 | // } Dl_info; |
56 | |
57 | #ifdef __LP64__ |
58 | int addrSize = 16; |
59 | #else |
60 | int addrSize = 8; |
61 | #endif |
62 | |
63 | QString funcName; |
64 | if (info.dli_sname) { |
65 | char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0); |
66 | if (func) { |
67 | funcName = QString(func); |
68 | free(func); |
69 | } |
70 | else { |
71 | funcName = QString(info.dli_sname); |
72 | } |
73 | } |
74 | else { |
75 | funcName = QString("0x%1" ).arg((ulong)(info.dli_saddr), addrSize, 16, QLatin1Char('0')); |
76 | } |
77 | |
78 | // prettificating the filename |
79 | QString fileName("???" ); |
80 | if (info.dli_fname) { |
81 | fileName = QString(info.dli_fname); |
82 | int slashPos = fileName.lastIndexOf('/'); |
83 | if (slashPos != -1) |
84 | fileName = fileName.mid(slashPos + 1); |
85 | } |
86 | |
87 | QString debugLine = QString("#%1 %2 0x%3 %4" ).arg(i, 3, 10) |
88 | .arg(fileName, -20) |
89 | .arg((ulong)(callstack[i]), addrSize, 16, QLatin1Char('0')) |
90 | .arg(funcName); |
91 | |
92 | dumpStream << debugLine << "\n" ; |
93 | qDebug() << qPrintable(debugLine); |
94 | } |
95 | dumpFile.close(); |
96 | #endif /* BUILD_CRASHHANDLER */ |
97 | } |
98 | |