From 634bcc88adda9c3dfafffb7a7b0680751b544957 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 21 Mar 2011 15:04:31 +0100 Subject: [PATCH] debugger: intercept calls to qFatal On Windows that might kill the inferior even if we only want to examine data. Task-number: QTCREATORBUG-4145 --- .../debugger/gdb/abstractplaingdbadapter.cpp | 30 -------- .../debugger/gdb/abstractplaingdbadapter.h | 2 - src/plugins/debugger/gdb/gdbengine.cpp | 68 +++++++++++++++++-- src/plugins/debugger/gdb/gdbengine.h | 4 ++ 4 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp index 62530a3908b..c9a96a13857 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp @@ -92,36 +92,6 @@ void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &respon } void AbstractPlainGdbAdapter::runEngine() -{ - QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); - QString fileName; - { - QTemporaryFile symbols(QDir::tempPath() + "/gdb_ns_"); - symbols.open(); - fileName = symbols.fileName(); - } - m_engine->postCommand("maint print msymbols " + fileName.toLocal8Bit(), - CB(handleNamespaceExtraction), fileName); -} - -void AbstractPlainGdbAdapter::handleNamespaceExtraction(const GdbResponse &response) -{ - QFile file(response.cookie.toString()); - file.open(QIODevice::ReadOnly); - QByteArray ba = file.readAll(); - file.remove(); - int pos = ba.indexOf("7QString9fromAscii"); - int pos1 = pos - 1; - while (pos1 > 0 && ba.at(pos1) != 'N' && ba.at(pos1) > '@') - --pos1; - ++pos1; - const QByteArray ns = ba.mid(pos1, pos - pos1); - if (!ns.isEmpty()) - m_engine->setQtNamespace(ns + "::"); - doRunEngine(); -} - -void AbstractPlainGdbAdapter::doRunEngine() { m_engine->postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun)); } diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.h b/src/plugins/debugger/gdb/abstractplaingdbadapter.h index 94847392300..1e3256a6c8d 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.h +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.h @@ -52,7 +52,6 @@ public: protected: void handleInfoTarget(const GdbResponse &response); - void handleNamespaceExtraction(const GdbResponse &response); private: virtual QByteArray execFilePath() const = 0; @@ -61,7 +60,6 @@ private: virtual QString fromLocalEncoding(const QByteArray &ba) const = 0; void handleExecRun(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response); - void doRunEngine(); }; } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index af77b4680c4..a5652adb90b 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -215,6 +215,7 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters, m_stackNeeded = false; m_preparedForQmlBreak = false; m_disassembleUsesComma = false; + m_qFatalBreakpointNumber = 0; invalidateSourcesList(); @@ -1246,7 +1247,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (bkptno && frame.isValid() && !isQmlStepBreakpoint1(bkptno) - && !isQmlStepBreakpoint2(bkptno)) { + && !isQmlStepBreakpoint2(bkptno) + && !isQFatalBreakpoint(bkptno)) { // Use opportunity to update the breakpoint marker position. BreakHandler *handler = breakHandler(); //qDebug() << " PROBLEM: " << m_qmlBreakpointNumbers << bkptno @@ -1268,7 +1270,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction) && QFileInfo(fullName).exists() && !isQmlStepBreakpoint1(bkptno) - && !isQmlStepBreakpoint2(bkptno)) + && !isQmlStepBreakpoint2(bkptno) + && !isQFatalBreakpoint(bkptno)) gotoLocation(Location(fullName, lineNumber)); if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { @@ -2169,7 +2172,7 @@ void GdbEngine::updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkp } else if (child.hasName("func")) { response.functionName = _(child.data()); } else if (child.hasName("addr")) { - // happens in constructors, inline functions, and + // happens in constructors, inline functions, and // at other places like 'foreach' lines. In this case there are // fields named "addr" in the response and/or the address // is called . @@ -2438,6 +2441,8 @@ void GdbEngine::handleBreakList(const GdbMi &table) needle.number = bkpt.findChild("number").data().toInt(); if (isQmlStepBreakpoint2(needle.number)) continue; + if (isQFatalBreakpoint(needle.number)) + continue; BreakpointId id = breakHandler()->findSimilarBreakpoint(needle); if (id != BreakpointId(-1)) { updateBreakpointDataFromOutput(id, bkpt); @@ -4622,8 +4627,10 @@ void GdbEngine::handleInferiorPrepared() // Apply source path mappings from global options. const SourcePathMap sourcePathMap = - DebuggerSourcePathMappingWidget::mergePlatformQtPath(startParameters().qtInstallPath, - debuggerCore()->globalDebuggerOptions()->sourcePathMap); + DebuggerSourcePathMappingWidget::mergePlatformQtPath( + startParameters().qtInstallPath, + debuggerCore()->globalDebuggerOptions()->sourcePathMap); + if (!sourcePathMap.isEmpty()) { const SourcePathMapIterator cend = sourcePathMap.constEnd(); for (SourcePathMapIterator it = sourcePathMap.constBegin(); it != cend; ++it) { @@ -4653,6 +4660,52 @@ void GdbEngine::handleInferiorPrepared() void GdbEngine::finishInferiorSetup() { QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); + // Extract Qt namespace. + QString fileName; + { + QTemporaryFile symbols(QDir::tempPath() + _("/gdb_ns_")); + symbols.open(); + fileName = symbols.fileName(); + } + postCommand("maint print msymbols " + fileName.toLocal8Bit(), + CB(handleNamespaceExtraction), fileName); +} + +void GdbEngine::handleNamespaceExtraction(const GdbResponse &response) +{ + QFile file(response.cookie.toString()); + file.open(QIODevice::ReadOnly); + QByteArray ba = file.readAll(); + //file.remove(); + int pos = ba.indexOf("7QString9fromAscii"); + int pos1 = pos - 1; + while (pos1 > 0 && ba.at(pos1) != 'N' && ba.at(pos1) > '@') + --pos1; + ++pos1; + const QByteArray ns = ba.mid(pos1, pos - pos1); + if (ns.isEmpty()) { + showMessage(_("FOUND NON-NAMESPACED QT")); + } else { + showMessage(_("FOUND NAMESPACED QT: " + ns)); + setQtNamespace(ns + "::"); + } + postCommand("-break-insert -f '" + qtNamespace() + "qFatal'", + CB(handleBreakOnQFatal)); +} + +void GdbEngine::handleBreakOnQFatal(const GdbResponse &response) +{ + if (response.resultClass == GdbResultDone) { + GdbMi bkpt = response.data.findChild("bkpt"); + GdbMi number = bkpt.findChild("number"); + int bpnr = number.data().toInt(); + if (bpnr) { + m_qFatalBreakpointNumber = bpnr; + postCommand("-break-commands " + number.data() + " return"); + } + } + + // Continue setup. notifyInferiorSetupOk(); } @@ -4786,6 +4839,11 @@ bool GdbEngine::isQmlStepBreakpoint2(int bpnr) const return bpnr && m_qmlBreakpointNumbers[2] == bpnr; } +bool GdbEngine::isQFatalBreakpoint(int bpnr) const +{ + return bpnr && m_qFatalBreakpointNumber == bpnr; +} + // // Factory // diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 95ff06c09a3..55df525f6b4 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -137,6 +137,7 @@ private: ////////// Gdb Process Management ////////// void handleGdbExit(const GdbResponse &response); void handleRemoteSetupDone(int gdbServerPort, int qmlPort); void handleRemoteSetupFailed(const QString &message); + void handleNamespaceExtraction(const GdbResponse &response); void handleAdapterStarted(); void defaultInferiorShutdown(const char *cmd); @@ -432,6 +433,7 @@ private: ////////// View & Data Stuff ////////// //void handleFetchDisassemblerByMiRangeMixed(const GdbResponse &response); //void handleFetchDisassemblerByMiRangePlain(const GdbResponse &response); void handleDisassemblerCheck(const GdbResponse &response); + void handleBreakOnQFatal(const GdbResponse &response); DisassemblerLines parseDisassembler(const GdbMi &data); DisassemblerLines parseCliDisassembler(const GdbMi &lines); DisassemblerLines parseMiDisassembler(const GdbMi &lines); @@ -581,11 +583,13 @@ private: ////////// View & Data Stuff ////////// void handleSetQmlStepBreakpoint(const GdbResponse &response); bool isQmlStepBreakpoint1(int bpnr) const; bool isQmlStepBreakpoint2(int bpnr) const; + bool isQFatalBreakpoint(int bpnr) const; // HACK: StackFrame m_targetFrame; QByteArray m_currentThread; QString m_lastWinException; + int m_qFatalBreakpointNumber; }; } // namespace Internal