diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/CMakeLists.txt drkonqi-5.18.3+p20.04+git20200328.1643/CMakeLists.txt --- drkonqi-5.18.3+p20.04+git20200311.0743/CMakeLists.txt 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/CMakeLists.txt 2020-03-28 16:43:56.000000000 +0000 @@ -5,7 +5,7 @@ set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.12.0") -set(KF5_MIN_VERSION "5.61.0") +set(KF5_MIN_VERSION "5.69.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) @@ -27,7 +27,7 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS I18n CoreAddons Service ConfigWidgets JobWidgets KIO Crash Completion WidgetsAddons Wallet - Notifications IdleTime WindowSystem) + Notifications IdleTime WindowSystem SyntaxHighlighting) find_package(Qt5X11Extras ${QT_MIN_VERSION} CONFIG) set_package_properties(Qt5X11Extras PROPERTIES TYPE RECOMMENDED PURPOSE "Recommended for better integration on X11.") diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/debian/changelog drkonqi-5.18.3+p20.04+git20200328.1643/debian/changelog --- drkonqi-5.18.3+p20.04+git20200311.0743/debian/changelog 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/debian/changelog 2020-03-28 16:43:57.000000000 +0000 @@ -1,12 +1,14 @@ -drkonqi (5.18.3+p20.04+git20200311.0743-0) focal; urgency=high +drkonqi (5.18.3+p20.04+git20200328.1643-0) focal; urgency=high - [ Rik Mills ] - * New upstream release (5.18.3) - - [ Kubuntu CI ] * Automatic Ubuntu CI Build - -- Kubuntu CI Wed, 11 Mar 2020 07:43:56 +0000 + -- Kubuntu CI Sat, 28 Mar 2020 16:43:57 +0000 + +drkonqi (5.18.3-0ubuntu1) focal; urgency=medium + + * New upstream release (5.18.3) + + -- Rik Mills Tue, 10 Mar 2020 18:07:01 +0000 drkonqi (5.18.2-0ubuntu1) focal; urgency=medium diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/backtracegenerator.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/backtracegenerator.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/backtracegenerator.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/backtracegenerator.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -92,9 +92,15 @@ m_temp->write("\n", 1); m_temp->flush(); + auto preamble = new QTemporaryFile(m_proc); + preamble->open(); + preamble->write(m_debugger.preambleCommands().toUtf8()); + preamble->write("\n", 1); + preamble->flush(); + // start the debugger QString str = m_debugger.command(); - Debugger::expandString(str, Debugger::ExpansionUsageShell, m_temp->fileName()); + Debugger::expandString(str, Debugger::ExpansionUsageShell, m_temp->fileName(), preamble->fileName()); *m_proc << KShell::splitArgs(str); m_proc->setOutputChannelMode(KProcess::OnlyStdoutChannel); @@ -102,7 +108,7 @@ // check if the debugger should take its input from a file we'll generate, // and take the appropriate steps if so QString stdinFile = m_debugger.backendValueOfParameter(QStringLiteral("ExecInputFile")); - Debugger::expandString(stdinFile, Debugger::ExpansionUsageShell, m_temp->fileName()); + Debugger::expandString(stdinFile, Debugger::ExpansionUsageShell, m_temp->fileName(), preamble->fileName()); if (!stdinFile.isEmpty() && QFile::exists(stdinFile)) { m_proc->setStandardInputFile(stdinFile); } @@ -182,7 +188,7 @@ QString tmp(QStringLiteral("Application: %progname (%execname), signal: %signame\n")); Debugger::expandString(tmp); - m_parsedBacktrace = tmp + m_parser->parsedBacktrace(); + m_parsedBacktrace = tmp + m_parser->informationLines() + m_parser->parsedBacktrace(); m_state = Loaded; #ifdef BACKTRACE_PARSER_DEBUG diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/backtracewidget.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/backtracewidget.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/backtracewidget.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/backtracewidget.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -21,9 +21,14 @@ #include #include +#include #include #include +#include +#include +#include +#include #include #include "drkonqi.h" @@ -33,7 +38,6 @@ #include "parser/backtraceparser.h" #include "drkonqi_globals.h" #include "debuggermanager.h" -#include "gdbhighlighter.h" static const char extraDetailsLabelMargin[] = " margin: 5px; "; @@ -221,8 +225,14 @@ // highlight if possible if (m_btGenerator->debugger().codeName() == QLatin1String("gdb")) { - m_highlighter = new GdbHighlighter(ui.m_backtraceEdit->document(), - m_btGenerator->parser()->parsedBacktraceLines()); + KSyntaxHighlighting::Repository repository; + m_highlighter = new KSyntaxHighlighting::SyntaxHighlighter(ui.m_backtraceEdit->document()); + m_highlighter->setTheme((palette().color(QPalette::Base).lightness() < 128) + ? repository.defaultTheme(KSyntaxHighlighting::Repository::DarkTheme) + : repository.defaultTheme(KSyntaxHighlighting::Repository::LightTheme)); + + const auto def = repository.definitionForName(QStringLiteral("GDB Backtrace")); + m_highlighter->setDefinition(def); } BacktraceParser * btParser = m_btGenerator->parser(); @@ -322,11 +332,6 @@ void BacktraceWidget::backtraceNewLine(const QString & line) { - // We absolutely must not have a highlighter attached. The highlighter has - // a static list of lines to highlight from. When we are loading lines - // this static list does not match reality breaking text length expectations - // and resulting in segfaults. - Q_ASSERT(!m_highlighter); //While loading the backtrace (unparsed) a new line was sent from the debugger, append it ui.m_backtraceEdit->append(line.trimmed()); } diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/backtracewidget.h drkonqi-5.18.3+p20.04+git20200328.1643/src/backtracewidget.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/backtracewidget.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/backtracewidget.h 2020-03-28 16:43:56.000000000 +0000 @@ -25,7 +25,9 @@ #include "debugpackageinstaller.h" #include "ui_backtracewidget.h" -class QSyntaxHighlighter; +namespace KSyntaxHighlighting { + class SyntaxHighlighter; +} class BacktraceRatingWidget; class BacktraceGenerator; @@ -54,7 +56,7 @@ BacktraceGenerator * m_btGenerator = nullptr; Ui::Form ui; BacktraceRatingWidget * m_backtraceRatingWidget = nullptr; - QSyntaxHighlighter *m_highlighter = nullptr; + KSyntaxHighlighting::SyntaxHighlighter *m_highlighter = nullptr; DebugPackageInstaller * m_debugPackageInstaller = nullptr; void setAsLoading(); diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/bugzillaintegration/bugzillalib.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/bugzillaintegration/bugzillalib.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/bugzillaintegration/bugzillalib.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/bugzillaintegration/bugzillalib.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -22,6 +22,7 @@ #include "bugzillalib.h" #include +#include #include "libbugzilla/clients/commentclient.h" #include "libbugzilla/connection.h" @@ -138,11 +139,10 @@ // the change should actually be implemented. const int nVersionParts = 3; - QString seps = QLatin1String("[._-]"); #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList digits = version.split(QRegExp(seps), QString::SkipEmptyParts); + QStringList digits = version.split(QRegularExpression(QStringLiteral("[._-]")), QString::SkipEmptyParts); #else - QStringList digits = version.split(QRegExp(seps), Qt::SkipEmptyParts); + QStringList digits = version.split(QRegularExpression(QStringLiteral("[._-]")), Qt::SkipEmptyParts); #endif while (digits.count() < nVersionParts) { digits << QLatin1String("0"); diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/CMakeLists.txt drkonqi-5.18.3+p20.04+git20200328.1643/src/CMakeLists.txt --- drkonqi-5.18.3+p20.04+git20200311.0743/src/CMakeLists.txt 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/CMakeLists.txt 2020-03-28 16:43:56.000000000 +0000 @@ -37,7 +37,6 @@ ptracer.cpp debuggermanager.cpp applicationdetailsexamples.cpp - gdbhighlighter.cpp statusnotifier.cpp ) @@ -104,6 +103,8 @@ KF5::Notifications # for status notifier KF5::IdleTime # hide status notifier only if user saw it + KF5::SyntaxHighlighting # Backtrace Highlighting + drkonqi_backtrace_parser qbugzilla ) diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/external/cdbrc drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/external/cdbrc --- drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/external/cdbrc 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/external/cdbrc 2020-03-28 16:43:56.000000000 +0000 @@ -26,6 +26,7 @@ Name[pt_BR]=cdb Name[ru]=cdb Name[sk]=cdb +Name[sl]=cdb Name[sv]=cdb Name[tg]=cdb Name[uk]=cdb diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/external/lldbrc drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/external/lldbrc --- drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/external/lldbrc 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/external/lldbrc 2020-03-28 16:43:56.000000000 +0000 @@ -26,6 +26,7 @@ Name[pt_BR]=lldb Name[ru]=lldb Name[sk]=lldb +Name[sl]=lldb Name[sv]=lldb Name[tg]=lldb Name[uk]=lldb diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/external.mac/lldbrc drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/external.mac/lldbrc --- drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/external.mac/lldbrc 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/external.mac/lldbrc 2020-03-28 16:43:56.000000000 +0000 @@ -26,6 +26,7 @@ Name[pt_BR]=lldb Name[ru]=lldb Name[sk]=lldb +Name[sl]=lldb Name[sv]=lldb Name[tg]=lldb Name[uk]=lldb diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/internal/cdbrc drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/internal/cdbrc --- drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/internal/cdbrc 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/internal/cdbrc 2020-03-28 16:43:56.000000000 +0000 @@ -26,6 +26,7 @@ Name[pt_BR]=cdb Name[ru]=cdb Name[sk]=cdb +Name[sl]=cdb Name[sv]=cdb Name[tg]=cdb Name[uk]=cdb diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/internal/gdbrc drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/internal/gdbrc --- drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/internal/gdbrc 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/internal/gdbrc 2020-03-28 16:43:56.000000000 +0000 @@ -74,5 +74,6 @@ Backends=KCrash [KCrash] -Exec=gdb -nw -n -batch -x %tempfile -p %pid %execpath -BatchCommands=set width 200\nthread\nthread apply all bt +Exec=gdb -nw -n -batch -x %preamblefile -x %tempfile -p %pid %execpath +PreambleCommands=set width 200\nprintf "KCRASH_INFO_MESSAGE: Content of s_kcrashErrorMessage: %s\\n", s_kcrashErrorMessage +BatchCommands=thread\nthread apply all bt diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/internal/lldbrc drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/internal/lldbrc --- drkonqi-5.18.3+p20.04+git20200311.0743/src/data/debuggers/internal/lldbrc 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/data/debuggers/internal/lldbrc 2020-03-28 16:43:56.000000000 +0000 @@ -26,6 +26,7 @@ Name[pt_BR]=lldb Name[ru]=lldb Name[sk]=lldb +Name[sl]=lldb Name[sv]=lldb Name[tg]=lldb Name[uk]=lldb @@ -38,4 +39,4 @@ [KCrash] Exec=lldb -p %pid ExecInputFile=%tempfile -BatchCommands=settings set term-width 200\nthread info\nbt all\ndetach +BatchCommands=settings set term-width 200\nthread info\nbt all diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/debugger.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/debugger.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/debugger.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/debugger.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -103,6 +103,12 @@ ? m_config->group(m_backend).readPathEntry("BatchCommands", QString()) : QString(); } +QString Debugger::preambleCommands() const +{ + return (isValid() && m_config->hasGroup(m_backend)) + ? m_config->group(m_backend).readPathEntry("PreambleCommands", QString()) + : QString(); +} bool Debugger::runInTerminal() const { @@ -119,7 +125,7 @@ } //static -void Debugger::expandString(QString & str, ExpandStringUsage usage, const QString & tempFile) +void Debugger::expandString(QString & str, ExpandStringUsage usage, const QString & tempFile, const QString & preambleFile) { const CrashedApplication *appInfo = DrKonqi::crashedApplication(); const QHash map = { @@ -130,6 +136,7 @@ { QLatin1String("signame"), appInfo->signalName() }, { QLatin1String("pid"), QString::number(appInfo->pid()) }, { QLatin1String("tempfile"), tempFile }, + { QLatin1String("preamblefile"), preambleFile }, { QLatin1String("thread"), QString::number(appInfo->thread()) }, }; diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/debugger.h drkonqi-5.18.3+p20.04+git20200328.1643/src/debugger.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/debugger.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/debugger.h 2020-03-28 16:43:56.000000000 +0000 @@ -67,6 +67,11 @@ */ QString backtraceBatchCommands() const; + /** Returns the commands that should be given to the debugger before + * getting the backtrace + */ + QString preambleCommands() const; + /** If this is an external debugger, it returns whether it should be run in a terminal or not */ bool runInTerminal() const; @@ -79,7 +84,7 @@ }; static void expandString(QString & str, ExpandStringUsage usage = ExpansionUsagePlainText, - const QString & tempFile = QString()); + const QString & tempFile = QString(), const QString & preambleFile = QString()); private: static QList availableDebuggers(const QString &path, const QString & backend); diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/drkonqidialog.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/drkonqidialog.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/drkonqidialog.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/drkonqidialog.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -161,10 +161,12 @@ " PID: %2 Signal: %3 (%4) " "Time: %5 %6", crashedApp->fakeExecutableBaseName(), - crashedApp->pid(), + // prevent number localization by ki18n + QString::number(crashedApp->pid()), crashedApp->signalName(), #if defined(Q_OS_UNIX) - crashedApp->signalNumber(), + // prevent number localization by ki18n + QString::number(crashedApp->signalNumber()), #else //windows uses weird big numbers for exception codes, //so it doesn't make sense to display them in decimal diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/gdbhighlighter.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/gdbhighlighter.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/gdbhighlighter.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/gdbhighlighter.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -/* - Copyright (C) 2010 Milian Wolff - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "gdbhighlighter.h" - -#include - -#include - -GdbHighlighter::GdbHighlighter(QTextDocument* parent, const QList & gdbLines) - : QSyntaxHighlighter(parent) -{ - // setup line lookup - int l = 0; - foreach(const BacktraceLine& line, gdbLines) { - lines.insert(l, line); - l += line.toString().count(QLatin1Char('\n')); - } - - // setup formats - KColorScheme scheme(QPalette::Active); - - crashFormat.setForeground(scheme.foreground(KColorScheme::NegativeText)); - nullptrFormat.setForeground(scheme.foreground(KColorScheme::NegativeText)); - nullptrFormat.setFontWeight(QFont::Bold); - assertFormat = nullptrFormat; - threadFormat.setForeground(scheme.foreground(KColorScheme::NeutralText)); - urlFormat.setForeground(scheme.foreground(KColorScheme::LinkText)); - funcFormat.setForeground(scheme.foreground(KColorScheme::VisitedText)); - funcFormat.setFontWeight(QFont::Bold); - otheridFormat.setForeground(scheme.foreground(KColorScheme::PositiveText)); - crapFormat.setForeground(scheme.foreground(KColorScheme::InactiveText)); -} - -void GdbHighlighter::highlightBlock(const QString& text) -{ - int cur = 0; - int next; - int diff; - const QRegExp hexptrPattern(QStringLiteral("0x[0-9a-f]+"), Qt::CaseSensitive, QRegExp::RegExp2); - int lineNr = currentBlock().firstLineNumber(); - while ( cur < text.length() ) { - next = text.indexOf(QLatin1Char('\n'), cur); - if (next == -1) { - next = text.length(); - } - if (lineNr == 0) { - // line that contains 'Application: ...' - ++lineNr; - cur = next; - continue; - } - - diff = next - cur; - - const QString lineStr = text.mid(cur, diff).append(QLatin1Char('\n')); - // -1 since we skip the first line - QMap< int, BacktraceLine >::iterator it = lines.lowerBound(lineNr - 1); - Q_ASSERT(it != lines.end()); - // lowerbound would return the next higher item, even though we want the former one - if (it.key() > lineNr - 1) { - --it; - } - const BacktraceLine& line = it.value(); - - if (line.type() == BacktraceLine::KCrash) { - setFormat(cur, diff, crashFormat); - } else if (line.type() == BacktraceLine::ThreadStart || line.type() == BacktraceLine::ThreadIndicator) { - setFormat(cur, diff, threadFormat); - } else if (line.type() == BacktraceLine::Crap) { - setFormat(cur, diff, crapFormat); - } else if (line.type() == BacktraceLine::StackFrame) { - if (!line.fileName().isEmpty()) { - int colonPos = line.fileName().lastIndexOf(QLatin1Char(':')); - setFormat(lineStr.indexOf(line.fileName()), colonPos == -1 ? line.fileName().length() : colonPos, urlFormat); - } - if (!line.libraryName().isEmpty()) { - setFormat(lineStr.indexOf(line.libraryName()), line.libraryName().length(), urlFormat); - } - if (!line.functionName().isEmpty()) { - int idx = lineStr.indexOf(line.functionName()); - if (idx != -1) { - // highlight Id::Id::Id::Func - // Id should have otheridFormat, :: no format and Func funcFormat - int i = idx; - int from = idx; - while (i < idx + line.functionName().length()) { - if (lineStr.at(i) == QLatin1Char(':')) { - setFormat(from, i - from, otheridFormat); - // skip :: - i += 2; - from = i; - continue; - } else if (lineStr.at(i) == QLatin1Char('<') || lineStr.at(i) == QLatin1Char('>')) { - setFormat(from, i - from, otheridFormat); - ++i; - from = i; - continue; - } - ++i; - } - if (line.functionName() == QLatin1String("qFatal") || line.functionName() == QLatin1String("abort") || line.functionName() == QLatin1String("__assert_fail") - || line.functionName() == QLatin1String("*__GI___assert_fail") || line.functionName() == QLatin1String("*__GI_abort")) { - setFormat(from, i - from, assertFormat); - } else { - setFormat(from, i - from, funcFormat); - } - } - } - // highlight hexadecimal ptrs - int idx = 0; - while ((idx = hexptrPattern.indexIn(lineStr, idx)) != -1) { - if (hexptrPattern.cap() == QLatin1String("0x0")) { - setFormat(idx, hexptrPattern.matchedLength(), nullptrFormat); - } - idx += hexptrPattern.matchedLength(); - } - } - - cur = next; - ++lineNr; - } -} diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/gdbhighlighter.h drkonqi-5.18.3+p20.04+git20200328.1643/src/gdbhighlighter.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/gdbhighlighter.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/gdbhighlighter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -/* - Copyright (C) 2010 Milian Wolff - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef GDBHIGHLIGHTER_H -#define GDBHIGHLIGHTER_H - -#include - -#include "parser/backtraceline.h" - -class GdbHighlighter : public QSyntaxHighlighter -{ -public: - GdbHighlighter(QTextDocument* parent, const QList & gdbLines); - -protected: - void highlightBlock(const QString& text) override; - -private: - QMap lines; - QTextCharFormat crashFormat; - QTextCharFormat nullptrFormat; - QTextCharFormat assertFormat; - QTextCharFormat threadFormat; - QTextCharFormat urlFormat; - QTextCharFormat funcFormat; - QTextCharFormat otheridFormat; - QTextCharFormat crapFormat; -}; - -#endif // GDBHIGHLIGHTER_H diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceline.h drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceline.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceline.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceline.h 2020-03-28 16:43:56.000000000 +0000 @@ -35,7 +35,8 @@ ThreadStart, //line indicates the start of a thread's stack. SignalHandlerStart, //line indicates the signal handler start //(contains "") - StackFrame //line is a normal stack frame + StackFrame, //line is a normal stack frame + Info //< additional information on the bt }; enum LineRating { diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparser.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparser.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparser.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparser.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -22,7 +22,8 @@ #include "backtraceparsercdb.h" #include "backtraceparsernull.h" #include "drkonqi_parser_debug.h" -#include + +#include #include //factory @@ -145,24 +146,25 @@ || line.rating() == BacktraceLine::MissingFunction ) return false; - //this is the base frame for all threads except the main thread - //FIXME that probably works only on linux - if ( line.functionName() == QLatin1String("start_thread") ) - return true; - - QRegExp regExp; - regExp.setPattern(QStringLiteral("(kde)?main")); //main() or kdemain() is the base for the main thread - if ( regExp.exactMatch(line.functionName()) ) + // "start_thread" is the base frame for all threads except the main thread, FIXME "start_thread" + // probably works only on linux + // main() or kdemain() is the base for the main thread + if (line.functionName() == QLatin1String("start_thread") + || line.functionName() == QLatin1String("main") + || line.functionName() == QLatin1String("kdemain")) { return true; + } //HACK for better rating. we ignore all stack frames below any function that matches //the following regular expression. The functions that match this expression are usually //"QApplicationPrivate::notify_helper", "QApplication::notify" and similar, which //are used to send any kind of event to the Qt application. All stack frames below this, //with or without debug symbols, are useless to KDE developers, so we ignore them. - regExp.setPattern(QStringLiteral("(Q|K)(Core)?Application(Private)?::notify.*")); - if ( regExp.exactMatch(line.functionName()) ) + const QRegularExpression re(QRegularExpression::anchoredPattern( + QStringLiteral("(Q|K)(Core)?Application(Private)?::notify.*"))); + if (re.match(line.functionName()).hasMatch()) { return true; + } //attempt to recognize crashes that happen after main has returned (bug 200993) if ( line.functionName() == QLatin1String("~KCleanUpGlobalStatic") || @@ -198,20 +200,23 @@ for some reason. Currently it ignores all libc/libstdc++/libpthread functions. */ static bool lineShouldBeIgnored(const BacktraceLine & line) { - if ( line.libraryName().contains(QLatin1String("libc.so")) - || line.libraryName().contains(QLatin1String("libstdc++.so")) - || line.functionName().startsWith(QLatin1String("*__GI_")) //glibc2.9 uses *__GI_ as prefix - || line.libraryName().contains(QLatin1String("libpthread.so")) - || line.libraryName().contains(QLatin1String("libglib-2.0.so")) -#ifdef Q_OS_MACOS - || (line.libraryName().startsWith(QLatin1String("libsystem_")) && line.libraryName().endsWith(QLatin1String(".dylib"))) - || line.libraryName().contains(QLatin1String("Foundation`")) -#endif - || line.libraryName().contains(QLatin1String("ntdll.dll")) - || line.libraryName().contains(QLatin1String("kernel32.dll")) - || line.functionName().contains(QLatin1String("_tmain")) - || line.functionName() == QLatin1String("WinMain") ) + if (line.libraryName().contains(QLatin1String("libc.so")) + || line.libraryName().contains(QLatin1String("libstdc++.so")) + || line.functionName().startsWith(QLatin1String("*__GI_")) //glibc2.9 uses *__GI_ as prefix + || line.libraryName().contains(QLatin1String("libpthread.so")) + || line.libraryName().contains(QLatin1String("libglib-2.0.so")) + || line.functionName() == QLatin1String("__libc_start_main") // below main on apps without symbols + || line.functionName() == QLatin1String("_start") // below main on apps without symbols + #ifdef Q_OS_MACOS + || (line.libraryName().startsWith(QLatin1String("libsystem_")) && line.libraryName().endsWith(QLatin1String(".dylib"))) + || line.libraryName().contains(QLatin1String("Foundation`")) + #endif + || line.libraryName().contains(QLatin1String("ntdll.dll")) + || line.libraryName().contains(QLatin1String("kernel32.dll")) + || line.functionName().contains(QLatin1String("_tmain")) + || line.functionName() == QLatin1String("WinMain")) { return true; + } return false; } @@ -384,10 +389,10 @@ //if there is no stack base, the executable is probably stripped, //so we need to be more strict with rating if ( !haveSeenStackBase ) { - //less than 4 stack frames is useless - if ( counter < 4 ) { + //less than 1 stack frame is useless + if ( counter < 1 ) { d->m_usefulness = Useless; - //more than 4 stack frames might have some value, so let's not be so strict, just lower the rating + //more than 1 stack frames might have some value, so let's not be so strict, just lower the rating } else if ( d->m_usefulness > Useless ) { d->m_usefulness = (Usefulness) (d->m_usefulness - 1); } @@ -400,4 +405,11 @@ qCDebug(DRKONQI_PARSER_LOG) << "Have seen stack base:" << haveSeenStackBase << "Lines counted:" << counter; } - +QString BacktraceParser::informationLines() const +{ + Q_D(const BacktraceParser); + QString ret = d->m_infoLines.join(QLatin1Char('\n')); + if (!ret.endsWith(QLatin1Char('\n'))) + ret += QLatin1Char('\n'); + return ret; +} diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparsergdb.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparsergdb.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparsergdb.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparsergdb.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -18,13 +18,16 @@ #include "backtraceparsergdb.h" #include "backtraceparser_p.h" #include "drkonqi_parser_debug.h" -#include + #include +#include //BEGIN BacktraceLineGdb +const QLatin1String BacktraceParserGdb::KCRASH_INFO_MESSAGE("KCRASH_INFO_MESSAGE: "); + BacktraceLineGdb::BacktraceLineGdb(const QString & lineStr) - : BacktraceLine() + : BacktraceLine() { d->m_line = lineStr; d->m_functionName = QLatin1String("??"); @@ -36,7 +39,6 @@ void BacktraceLineGdb::parse() { - QRegExp regExp; if (d->m_line == QLatin1Char('\n')) { d->m_type = EmptyLine; @@ -49,14 +51,20 @@ return; } - regExp.setPattern(QStringLiteral("^#([0-9]+)" //matches the stack frame number, ex. "#0" - "[\\s]+(0x[0-9a-f]+[\\s]+in[\\s]+)?" // matches " 0x0000dead in " (optionally) - "((\\(anonymous namespace\\)::)?[^\\(]+)?" //matches the function name + static QRegularExpression regExp; + // make dot "." char match new lines, to match e.g.: + // "#5 0x00007f50e99f776f in QWidget::testAttribute_helper (this=0x6e6440,\n attribute=Qt::WA_WState_Created) at kernel/qwidget.cpp:9081\n" + // gdb breaks long stack frame lines into multiple ones for readability + regExp.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); + regExp.setPattern(QStringLiteral( + "^#([0-9]+)" //matches the stack frame number, ex. "#0" + "[\\s]+(?:0x[0-9a-f]+[\\s]+in[\\s]+)?" // matches " 0x0000dead in " (optionally) + "((?:\\(anonymous namespace\\)::)?[^\\(]+)?" //matches the function name //(anything except left parenthesis, which is the start of the arguments section) //and optionally the prefix "(anonymous namespace)::" - "(\\(.*\\))?" //matches the function arguments + "(?:\\(.*\\))?" //matches the function arguments //(when the app doesn't have debugging symbols) - "[\\s]+(const[\\s]+)?" //matches a traling const, if it exists + "[\\s]+(?:const[\\s]+)?" //matches a traling const, if it exists "\\(.*\\)" //matches the arguments of the function with their values //(when the app has debugging symbols) "([\\s]+" //beginning of optional file information @@ -66,22 +74,23 @@ //the )? at the end closes the parenthesis before [\\s]+(from|at) and //notes that the whole expression from there is optional. - if (regExp.exactMatch(d->m_line)) { + QRegularExpressionMatch match = regExp.match(d->m_line); + if (match.hasMatch()) { d->m_type = StackFrame; - d->m_stackFrameNumber = regExp.cap(1).toInt(); - d->m_functionName = regExp.cap(3).trimmed(); + d->m_stackFrameNumber = match.captured(1).toInt(); + d->m_functionName = match.captured(2).trimmed(); - if (!regExp.cap(7).isEmpty()) { //we have file information (stuff after from|at) - bool file = regExp.cap(8) == QLatin1String("at"); //'at' means we have a source file (likely) + if (!match.captured(3).isEmpty()) { //we have file information (stuff after from|at) + bool file = match.captured(4) == QLatin1String("at"); //'at' means we have a source file (likely) // Gdb isn't entirely consistent here, when it uses 'from' it always refers to a library, but // sometimes the stack can resolve to a library even when it uses the 'at' key word. // This specifically seems to happen when a frame has no function name. - const QString path = regExp.cap(9); + const QString path = match.captured(5); file = file && !QFileInfo(path).completeSuffix().contains(QLatin1String(".so")); if (file) { - d->m_file = regExp.cap(9); + d->m_file = match.captured(5); } else { //'from' means we have a library - d->m_library = regExp.cap(9); + d->m_library = match.captured(5); } } @@ -89,26 +98,32 @@ return; } + if (d->m_line.contains(BacktraceParserGdb::KCRASH_INFO_MESSAGE)) { + qCDebug(DRKONQI_PARSER_LOG) << "info:" << d->m_line; + d->m_type = Info; + return; + } + regExp.setPattern(QStringLiteral(".*\\(no debugging symbols found\\).*|" ".*\\[Thread debugging using libthread_db enabled\\].*|" ".*\\[New .*|" "0x[0-9a-f]+.*|" "Current language:.*")); - if (regExp.exactMatch(d->m_line)) { + if (regExp.match(d->m_line).hasMatch()) { qCDebug(DRKONQI_PARSER_LOG) << "garbage detected:" << d->m_line; d->m_type = Crap; return; } regExp.setPattern(QStringLiteral("Thread [0-9]+\\s+\\(Thread [0-9a-fx]+\\s+\\(.*\\)\\):\n")); - if (regExp.exactMatch(d->m_line)) { + if (regExp.match(d->m_line).hasMatch()) { qCDebug(DRKONQI_PARSER_LOG) << "thread start detected:" << d->m_line; d->m_type = ThreadStart; return; } regExp.setPattern(QStringLiteral("\\[Current thread is [0-9]+ \\(.*\\)\\]\n")); - if (regExp.exactMatch(d->m_line)) { + if (regExp.match(d->m_line).hasMatch()) { qCDebug(DRKONQI_PARSER_LOG) << "thread indicator detected:" << d->m_line; d->m_type = ThreadIndicator; return; @@ -196,6 +211,9 @@ switch (line.type()) { case BacktraceLine::Crap: break; //we don't want crap in the backtrace ;) + case BacktraceLine::Info: + d->m_infoLines << line.toString().mid(KCRASH_INFO_MESSAGE.size()); + break; case BacktraceLine::ThreadStart: d->m_linesList.append(line); d->m_possibleKCrashStart = d->m_linesList.size(); diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparsergdb.h drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparsergdb.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparsergdb.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparsergdb.h 2020-03-28 16:43:56.000000000 +0000 @@ -40,6 +40,7 @@ QString parsedBacktrace() const override; QList parsedBacktraceLines() const override; + static const QLatin1String KCRASH_INFO_MESSAGE; protected: BacktraceParserPrivate *constructPrivate() const override; diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparser.h drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparser.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparser.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparser.h 2020-03-28 16:43:56.000000000 +0000 @@ -67,6 +67,8 @@ /*! Returns a list of libraries/executables that are missing debug symbols. */ virtual QSet librariesWithMissingDebugSymbols() const; + QString informationLines() const; + private Q_SLOTS: void resetState(); diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparserkdbgwin.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparserkdbgwin.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparserkdbgwin.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparserkdbgwin.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -19,6 +19,8 @@ #include "backtraceparser_p.h" #include "drkonqi_parser_debug.h" +#include + //BEGIN BacktraceLineKdbgwin class BacktraceLineKdbgwin : public BacktraceLine @@ -54,17 +56,18 @@ return; } - QRegExp regExp; - regExp.setPattern(QStringLiteral("([^!]+)!" //match the module name, followed by ! - "([^\\(]+)\\(\\) " //match the function name, followed by () - "\\[([^@]+)@ [\\-\\d]+\\] " // [filename @ line] - "at 0x.*")); //at 0xdeadbeef + static const QRegularExpression re(QRegularExpression::anchoredPattern(QStringLiteral( + "([^!]+)!" //match the module name, followed by ! + "([^\\(]+)\\(\\) " //match the function name, followed by () + "\\[([^@]+)@ [\\-\\d]+\\] " // [filename @ line] + "at 0x.*"))); //at 0xdeadbeef - if (regExp.exactMatch(d->m_line)) { + const QRegularExpressionMatch match = re.match(d->m_line); + if (match.hasMatch()) { d->m_type = StackFrame; - d->m_library = regExp.cap(1); - d->m_functionName = regExp.cap(2); - d->m_file = regExp.cap(3).trimmed(); + d->m_library = match.captured(1); + d->m_functionName = match.captured(2); + d->m_file = match.captured(3).trimmed(); qCDebug(DRKONQI_PARSER_LOG) << d->m_functionName << d->m_file << d->m_library; return; diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparser_p.h drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparser_p.h --- drkonqi-5.18.3+p20.04+git20200311.0743/src/parser/backtraceparser_p.h 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/parser/backtraceparser_p.h 2020-03-28 16:43:56.000000000 +0000 @@ -26,6 +26,7 @@ BacktraceParserPrivate() : m_usefulness(BacktraceParser::InvalidUsefulness) {} ~BacktraceParserPrivate() {} + QStringList m_infoLines; QList m_linesList; QList m_linesToRate; QStringList m_firstUsefulFunctions; diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/tests/backtraceparsertest/backtraceparsertest_data/test_bug192412_b drkonqi-5.18.3+p20.04+git20200328.1643/src/tests/backtraceparsertest/backtraceparsertest_data/test_bug192412_b --- drkonqi-5.18.3+p20.04+git20200311.0743/src/tests/backtraceparsertest/backtraceparsertest_data/test_bug192412_b 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/tests/backtraceparsertest/backtraceparsertest_data/test_bug192412_b 2020-03-28 16:43:56.000000000 +0000 @@ -4,6 +4,5 @@ #0 0x00007fdda985f5b5 in waitpid () from /lib/libpthread.so.0 #1 0x00007fddaa7e660d in KCrash::startDirectly (argv=0x7fffb2db2800) at /home/gkiagia/kde/src/KDE/kdelibs/kdeui/util/kcrash.cpp:436 #2 0x00007fddaa7e7581 in KCrash::defaultCrashHandler (sig=11) at /home/gkiagia/kde/src/KDE/kdelibs/kdeui/util/kcrash.cpp:340 -#3 -#4 KCmdLineArgs::arg (this=0x0, n=0) at /home/gkiagia/kde/src/KDE/kdelibs/kdecore/kernel/kcmdlineargs.cpp:1530 -#5 0x00000000004023af in _start () +#5 0x00007f6e4e3edc34 in Phonon::AbstractMediaStreamPrivate::writeData () from /usr/lib/libphonon.so.4 +#6 0x000000000045cdbc in _start () diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/tests/crashtest/CMakeLists.txt drkonqi-5.18.3+p20.04+git20200328.1643/src/tests/crashtest/CMakeLists.txt --- drkonqi-5.18.3+p20.04+git20200311.0743/src/tests/crashtest/CMakeLists.txt 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/tests/crashtest/CMakeLists.txt 2020-03-28 16:43:56.000000000 +0000 @@ -2,6 +2,6 @@ ecm_mark_as_test(crashtest) ecm_mark_nongui_executable(crashtest) target_link_libraries(crashtest - KF5::I18n KF5::Crash KF5::CoreAddons Qt5::Widgets + KF5::Crash KF5::CoreAddons Qt5::Gui Qt5::Concurrent) diff -Nru drkonqi-5.18.3+p20.04+git20200311.0743/src/tests/crashtest/crashtest.cpp drkonqi-5.18.3+p20.04+git20200328.1643/src/tests/crashtest/crashtest.cpp --- drkonqi-5.18.3+p20.04+git20200311.0743/src/tests/crashtest/crashtest.cpp 2020-03-11 07:43:56.000000000 +0000 +++ drkonqi-5.18.3+p20.04+git20200328.1643/src/tests/crashtest/crashtest.cpp 2020-03-28 16:43:56.000000000 +0000 @@ -31,12 +31,11 @@ #include #include #include -#include #include -#include +#include #include -enum CrashType { Crash, Malloc, Div0, Assert, QAssert, Threads }; +enum CrashType { Crash, Malloc, Div0, Assert, QAssert, Threads, FatalErrorMessage }; struct SomeStruct { @@ -88,6 +87,12 @@ QtConcurrent::blockingMap(foo, map_function); } +void do_fatalErrorMessage() +{ + KCrash::setErrorMessage(QStringLiteral("So long, my friends...")); + qFatal("So long!\n"); +} + void level4(int t) { if (t == Malloc) @@ -100,6 +105,8 @@ do_qassert(); else if (t == Threads) do_threads(); + else if (t == FatalErrorMessage) + do_fatalErrorMessage(); else do_crash(); } @@ -121,17 +128,17 @@ int main(int argc, char *argv[]) { - QApplication app(argc, argv); - KAboutData aboutData(QStringLiteral("crashtext"), i18n("Crash Test for DrKonqi"), + QGuiApplication app(argc, argv); + KAboutData aboutData(QStringLiteral("crashtest"), QStringLiteral("Crash Test for DrKonqi"), QStringLiteral("1.1"), - i18n("Crash Test for DrKonqi"), + QStringLiteral("Crash Test for DrKonqi"), KAboutLicense::GPL, - i18n("(c) 2000-2002 David Faure, Waldo Bastian")); + QStringLiteral("(c) 2000-2002 David Faure, Waldo Bastian")); QCommandLineParser parser; - parser.addOption(QCommandLineOption(QStringLiteral("autorestart"), i18n("Automatically restart"))); - parser.addOption(QCommandLineOption(QStringLiteral("kdeinit"), i18n("Start DrKonqi using kdeinit"))); - parser.addPositionalArgument(QStringLiteral("type"), i18n("Type of crash."), QStringLiteral("crash|malloc|div0|assert|threads")); + parser.addOption(QCommandLineOption(QStringLiteral("autorestart"), QStringLiteral("Automatically restart"))); + parser.addOption(QCommandLineOption(QStringLiteral("kdeinit"), QStringLiteral("Start DrKonqi using kdeinit"))); + parser.addPositionalArgument(QStringLiteral("type"), QStringLiteral("Type of crash."), QStringLiteral("crash|malloc|div0|assert|threads|fatal")); aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); @@ -157,6 +164,8 @@ crashtype = QAssert; else if (type == "threads") crashtype = Threads; + else if (type == "fatal") + crashtype = FatalErrorMessage; level1(crashtype); return app.exec(); }