diff --git a/src/backtracegenerator.cpp b/src/backtracegenerator.cpp --- a/src/backtracegenerator.cpp +++ b/src/backtracegenerator.cpp @@ -92,17 +92,23 @@ 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); m_proc->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Text); // 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 --git a/src/data/debuggers/internal/gdbrc b/src/data/debuggers/internal/gdbrc --- a/src/data/debuggers/internal/gdbrc +++ b/src/data/debuggers/internal/gdbrc @@ -74,5 +74,6 @@ Backends=KCrash [KCrash] -Exec=gdb -nw -n -batch -x %tempfile -p %pid %execpath -BatchCommands=set width 200\nprint "Content of s_kcrashErrorMessage:"\nprint s_kcrashErrorMessage\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 --git a/src/data/debuggers/internal/lldbrc b/src/data/debuggers/internal/lldbrc --- a/src/data/debuggers/internal/lldbrc +++ b/src/data/debuggers/internal/lldbrc @@ -39,4 +39,4 @@ [KCrash] Exec=lldb -p %pid ExecInputFile=%tempfile -BatchCommands=settings set term-width 200\nprint "Content of s_kcrashErrorMessage:"\nprint s_kcrashErrorMessage\nthread info\nbt all\ndetach +BatchCommands=settings set term-width 200\nthread info\nbt all diff --git a/src/debugger.h b/src/debugger.h --- a/src/debugger.h +++ b/src/debugger.h @@ -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 --git a/src/debugger.cpp b/src/debugger.cpp --- a/src/debugger.cpp +++ b/src/debugger.cpp @@ -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 --git a/src/parser/backtraceline.h b/src/parser/backtraceline.h --- a/src/parser/backtraceline.h +++ b/src/parser/backtraceline.h @@ -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 --git a/src/parser/backtraceparser.h b/src/parser/backtraceparser.h --- a/src/parser/backtraceparser.h +++ b/src/parser/backtraceparser.h @@ -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 --git a/src/parser/backtraceparser.cpp b/src/parser/backtraceparser.cpp --- a/src/parser/backtraceparser.cpp +++ b/src/parser/backtraceparser.cpp @@ -405,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 --git a/src/parser/backtraceparser_p.h b/src/parser/backtraceparser_p.h --- a/src/parser/backtraceparser_p.h +++ b/src/parser/backtraceparser_p.h @@ -26,6 +26,7 @@ BacktraceParserPrivate() : m_usefulness(BacktraceParser::InvalidUsefulness) {} ~BacktraceParserPrivate() {} + QStringList m_infoLines; QList m_linesList; QList m_linesToRate; QStringList m_firstUsefulFunctions; diff --git a/src/parser/backtraceparsergdb.h b/src/parser/backtraceparsergdb.h --- a/src/parser/backtraceparsergdb.h +++ b/src/parser/backtraceparsergdb.h @@ -40,6 +40,7 @@ QString parsedBacktrace() const override; QList parsedBacktraceLines() const override; + static const QLatin1String KCRASH_INFO_MESSAGE; protected: BacktraceParserPrivate *constructPrivate() const override; diff --git a/src/parser/backtraceparsergdb.cpp b/src/parser/backtraceparsergdb.cpp --- a/src/parser/backtraceparsergdb.cpp +++ b/src/parser/backtraceparsergdb.cpp @@ -24,8 +24,10 @@ //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("??"); @@ -96,6 +98,12 @@ 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 .*|" @@ -203,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();