From 17a319fdb3120c7891a0f3a85b9e7dabd906a70f Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 31 Jan 2016 19:13:51 +0300 Subject: [PATCH] improved crash reports for linux --- Telegram/SourceFiles/boxes/aboutbox.cpp | 5 +- Telegram/SourceFiles/logs.cpp | 26 ++++-- Telegram/SourceFiles/pspecific_linux.cpp | 113 ++++++++++++++++++++--- Telegram/SourceFiles/window.cpp | 6 +- Telegram/SourceFiles/window.h | 1 + Telegram/Telegram.pro | 6 +- 6 files changed, 129 insertions(+), 28 deletions(-) diff --git a/Telegram/SourceFiles/boxes/aboutbox.cpp b/Telegram/SourceFiles/boxes/aboutbox.cpp index a9bc2e0ad..396d515f4 100644 --- a/Telegram/SourceFiles/boxes/aboutbox.cpp +++ b/Telegram/SourceFiles/boxes/aboutbox.cpp @@ -126,8 +126,7 @@ void AboutBox::dragEnterEvent(QDragEnterEvent *e) { void AboutBox::dropEvent(QDropEvent *e) { if (!_getCrashReportFile(e->mimeData()).isEmpty()) { e->acceptProposedAction(); - psExecTelegram(_getCrashReportFile(e->mimeData())); - App::quit(); + psShowCrash(_getCrashReportFile(e->mimeData())); } } @@ -142,4 +141,4 @@ QString telegramFaqLink() { } } return result; -} \ No newline at end of file +} diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index c660f77b3..6d117dc61 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -709,41 +709,47 @@ namespace SignalHandlers { #if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64 ucontext_t *uc = (ucontext_t*)ucontext; - void *addresses[128] = { 0 }; void *caller = 0; - #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) /* OSX < 10.6 */ #if defined(__x86_64__) - caller = (void*)uap->uc_mcontext->__ss.__rip; + caller = (void*)uc->uc_mcontext->__ss.__rip; #elif defined(__i386__) - caller = (void*)uap->uc_mcontext->__ss.__eip; + caller = (void*)uc->uc_mcontext->__ss.__eip; #else - caller = (void*)uap->uc_mcontext->__ss.__srr0; + caller = (void*)uc->uc_mcontext->__ss.__srr0; #endif #elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) /* OSX >= 10.6 */ #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) caller = (void*)uc->uc_mcontext->__ss.__rip; #else - caller = (void*)uap->uc_mcontext->__ss.__eip; + caller = (void*)uc->uc_mcontext->__ss.__eip; #endif #elif defined(__linux__) /* Linux */ #if defined(__i386__) - caller = (void*)uap->uc_mcontext.gregs[14]; /* Linux 32 */ + caller = (void*)uc->uc_mcontext.gregs[14]; /* Linux 32 */ #elif defined(__X86_64__) || defined(__x86_64__) - caller = (void*)uap->uc_mcontext.gregs[16]; /* Linux 64 */ + caller = (void*)uc->uc_mcontext.gregs[16]; /* Linux 64 */ #elif defined(__ia64__) /* Linux IA64 */ - caller = (void*)uap->uc_mcontext.sc_ip; + caller = (void*)uc->uc_mcontext.sc_ip; #endif #endif + void *addresses[132] = { 0 }; size_t size = backtrace(addresses, 128); /* overwrite sigaction with caller's address */ - if (caller) addresses[1] = caller; + if (caller) { + for (int i = size; i > 1; --i) { + addresses[i + 3] = addresses[i]; + } + addresses[2] = (void*)0x1; + addresses[3] = caller; + addresses[4] = (void*)0x1; + } #ifdef Q_OS_MAC dump() << "\nBase image addresses:\n"; diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index 5134efeaf..54b0227bf 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -979,6 +979,8 @@ void psWriteDump() { } QString demanglestr(const QString &mangled) { + if (mangled.isEmpty()) return mangled; + QByteArray cmd = ("c++filt -n " + mangled).toUtf8(); FILE *f = popen(cmd.constData(), "r"); if (!f) return "BAD_SYMBOL_" + mangled; @@ -994,6 +996,51 @@ QString demanglestr(const QString &mangled) { return result.trimmed(); } +QStringList addr2linestr(uint64 *addresses, int count) { + QStringList result; + if (!count) return result; + + result.reserve(count); + QString cmdstr = "addr2line -e " + escapeShell(cExeDir() + cExeName()); + for (int i = 0; i < count; ++i) { + if (addresses[i]) { + cmdstr += qsl(" 0x%1").arg(addresses[i], 0, 16); + } + } + QByteArray cmd = cmdstr.toUtf8(); + FILE *f = popen(cmd.constData(), "r"); + + QStringList addr2lineResult; + if (f) { + char buffer[4096] = {0}; + while (!feof(f)) { + if (fgets(buffer, 4096, f) != NULL) { + addr2lineResult.push_back(QString::fromUtf8(buffer)); + } + } + pclose(f); + } + for (int i = 0, j = 0; i < count; ++i) { + if (addresses[i]) { + if (j < addr2lineResult.size() && !addr2lineResult.at(j).isEmpty() && !addr2lineResult.at(j).startsWith(qstr("0x"))) { + QString res = addr2lineResult.at(j).trimmed(); + if (int index = res.indexOf(qstr("/Telegram/"))) { + if (index > 0) { + res = res.mid(index + qstr("/Telegram/").size()); + } + } + result.push_back(res); + } else { + result.push_back(QString()); + } + ++j; + } else { + result.push_back(QString()); + } + } + return result; +} + QString _showCrashDump(const QByteArray &crashdump, QString dumpfile) { QString initial = QString::fromUtf8(crashdump), result; QStringList lines = initial.split('\n'); @@ -1001,6 +1048,7 @@ QString _showCrashDump(const QByteArray &crashdump, QString dumpfile) { int32 i = 0, l = lines.size(); while (i < l) { + uint64 addresses[1024] = { 0 }; for (; i < l; ++i) { result.append(lines.at(i)).append('\n'); QString line = lines.at(i).trimmed(); @@ -1010,21 +1058,59 @@ QString _showCrashDump(const QByteArray &crashdump, QString dumpfile) { } } - for (int32 start = i; i < l; ++i) { + int32 start = i; + for (; i < l; ++i) { + QString line = lines.at(i).trimmed(); + if (line.isEmpty()) break; + + QRegularExpressionMatch m1 = QRegularExpression(qsl("^(.+)\\(([^+]+)\\+([^\\)]+)\\)\\[(.+)\\]$")).match(line); + QRegularExpressionMatch m2 = QRegularExpression(qsl("^(.+)\\[(.+)\\]$")).match(line); + QString addrstr = m1.hasMatch() ? m1.captured(4) : (m2.hasMatch() ? m2.captured(2) : QString()); + if (!addrstr.isEmpty()) { + uint64 addr = addrstr.startsWith(qstr("0x")) ? addrstr.mid(2).toULongLong(0, 16) : addrstr.toULongLong(); + if (addr > 1) { + addresses[i - start] = addr; + } + } + } + + QStringList addr2line = addr2linestr(addresses, i - start); + for (i = start; i < l; ++i) { QString line = lines.at(i).trimmed(); if (line.isEmpty()) break; - result.append(qsl("%1. ").arg(i + 1 - start)); + result.append(qsl("\n%1. ").arg(i - start)); if (line.startsWith(qstr("ERROR: "))) { result.append(line).append('\n'); continue; } - QRegularExpressionMatch m = QRegularExpression(qsl("^(.+)\\(([^+]+)\\+([^\\)]+)\\)(.+)$")).match(line); - if (!m.hasMatch()) { + if (line == qstr("[0x1]")) { + result.append(qsl("(0x1 separator)\n")); + continue; + } + + QRegularExpressionMatch m1 = QRegularExpression(qsl("^(.+)\\(([^+]*)\\+([^\\)]+)\\)(.+)$")).match(line); + QRegularExpressionMatch m2 = QRegularExpression(qsl("^(.+)\\[(.+)\\]$")).match(line); + if (!m1.hasMatch() && !m2.hasMatch()) { result.append(qstr("BAD LINE: ")).append(line).append('\n'); continue; } - result.append(demanglestr(m.captured(2))).append(qsl(" + ")).append(m.captured(3)).append(qsl(" (")).append(m.captured(1)).append(qsl(") ")).append(m.captured(4)).append('\n'); + + if (m1.hasMatch()) { + result.append(demanglestr(m1.captured(2))).append(qsl(" + ")).append(m1.captured(3)).append(qsl(" [")).append(m1.captured(1)).append(qsl("] ")); + if (!addr2line.at(i - start).isEmpty() && addr2line.at(i - start) != qsl("??:0")) { + result.append(qsl(" (")).append(addr2line.at(i - start)).append(qsl(")\n")); + } else { + result.append(m1.captured(4)).append(qsl(" (demangled)")).append('\n'); + } + } else { + result.append('[').append(m2.captured(1)).append(']'); + if (!addr2line.at(i - start).isEmpty() && addr2line.at(i - start) != qsl("??:0")) { + result.append(qsl(" (")).append(addr2line.at(i - start)).append(qsl(")\n")); + } else { + result.append(' ').append(m2.captured(2)).append('\n'); + } + } } } return result; @@ -1041,13 +1127,18 @@ int psShowCrash(const QString &crashdump) { text = qsl("ERROR: could not read crash dump file '%1'").arg(QFileInfo(crashdump).absoluteFilePath()); } - QByteArray args[] = { "" }; - int a_argc = 1; - char *a_argv[1] = { args[0].data() }; - QApplication app(a_argc, a_argv); + if (Sandbox::started()) { + ShowCrashReportWindow *wnd = new ShowCrashReportWindow(text); + return 0; + } - ShowCrashReportWindow wnd(text); - return app.exec(); + QByteArray args[] = { "" }; + int a_argc = 1; + char *a_argv[1] = { args[0].data() }; + QApplication app(a_argc, a_argv); + + ShowCrashReportWindow *wnd = new ShowCrashReportWindow(text); + return app.exec(); } bool _removeDirectory(const QString &path) { // from http://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp index e3c2fe3fb..18950d868 100644 --- a/Telegram/SourceFiles/window.cpp +++ b/Telegram/SourceFiles/window.cpp @@ -2113,7 +2113,7 @@ void LastCrashedWindow::onViewReport() { } void LastCrashedWindow::onSaveReport() { - QString to = QFileDialog::getSaveFileName(0, qsl("Telegram Crash Report"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + qsl("/report"), qsl("Telegram crash report (*.telegramcrash)")); + QString to = QFileDialog::getSaveFileName(0, qsl("Telegram Crash Report"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + qsl("/report.telegramcrash"), qsl("Telegram crash report (*.telegramcrash)")); if (!to.isEmpty()) { QFile file(to); if (file.open(QIODevice::WriteOnly)) { @@ -2874,3 +2874,7 @@ ShowCrashReportWindow::ShowCrashReportWindow(const QString &text) void ShowCrashReportWindow::resizeEvent(QResizeEvent *e) { _log.setGeometry(rect().marginsRemoved(QMargins(basicSize(), basicSize(), basicSize(), basicSize()))); } + +void ShowCrashReportWindow::closeEvent(QCloseEvent *e) { + deleteLater(); +} diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h index f7c968ce8..fe3d2da2c 100644 --- a/Telegram/SourceFiles/window.h +++ b/Telegram/SourceFiles/window.h @@ -547,6 +547,7 @@ public: protected: void resizeEvent(QResizeEvent *e); + void closeEvent(QCloseEvent *e); private: diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 96ede8071..64d4739b0 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -281,12 +281,12 @@ QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-v CONFIG(release, debug|release) { QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing + QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g QMAKE_LFLAGS_RELEASE -= -O1 - QMAKE_LFLAGS_RELEASE += -Ofast -flto -rdynamic + QMAKE_LFLAGS_RELEASE += -Ofast -flto -rdynamic -g } CONFIG(debug, debug|release) { - QMAKE_LFLAGS_DEBUG += -rdynamic + QMAKE_LFLAGS_DEBUG += -rdynamic -g } INCLUDEPATH += ./../../Libraries/QtStatic/qtbase/include/QtGui/5.5.1/QtGui\