diff --git a/src/libs/qtcreatorcdbext/knowntype.h b/src/libs/qtcreatorcdbext/knowntype.h index c8062fb46c86856df050a8e0da350922995e36b7..6736cd508b5b29a8fab899ce58248bbb57075e20 100644 --- a/src/libs/qtcreatorcdbext/knowntype.h +++ b/src/libs/qtcreatorcdbext/knowntype.h @@ -39,27 +39,28 @@ enum KnownType KT_Qt_MovableType = 0x40000, KT_STL_Type = 0x80000, KT_ContainerType = 0x100000, + KT_HasSimpleDumper = 0x200000, // Qt Basic - KT_QChar = KT_Qt_Type + KT_Qt_MovableType + 1, - KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + 2, - KT_QString = KT_Qt_Type + KT_Qt_MovableType + 3, - KT_QColor = KT_Qt_Type + 4, - KT_QFlags = KT_Qt_Type + 5, - KT_QDate = KT_Qt_Type + KT_Qt_MovableType + 6, - KT_QTime = KT_Qt_Type + KT_Qt_MovableType + 7, - KT_QPoint = KT_Qt_Type + KT_Qt_MovableType + 8, - KT_QPointF = KT_Qt_Type +KT_Qt_MovableType + 9, - KT_QSize = KT_Qt_Type + KT_Qt_MovableType + 11, - KT_QSizeF = KT_Qt_Type + KT_Qt_MovableType + 12, - KT_QLine = KT_Qt_Type + KT_Qt_MovableType + 13, - KT_QLineF = KT_Qt_Type + KT_Qt_MovableType + 14, - KT_QRect = KT_Qt_Type + KT_Qt_MovableType + 15, - KT_QRectF = KT_Qt_Type + KT_Qt_MovableType + 16, - KT_QVariant = KT_Qt_Type + KT_Qt_MovableType + 17, - KT_QBasicAtomicInt = KT_Qt_Type + 18, - KT_QAtomicInt = KT_Qt_Type + 19, - KT_QObject = KT_Qt_Type + 20, - KT_QWidget = KT_Qt_Type + 21, + KT_QChar = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 1, + KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 2, + KT_QString = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 3, + KT_QColor = KT_Qt_Type + KT_HasSimpleDumper + 4, + KT_QFlags = KT_Qt_Type + KT_HasSimpleDumper + 5, + KT_QDate = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 6, + KT_QTime = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 7, + KT_QPoint = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 8, + KT_QPointF = KT_Qt_Type +KT_Qt_MovableType + KT_HasSimpleDumper + 9, + KT_QSize = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 11, + KT_QSizeF = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 12, + KT_QLine = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 13, + KT_QLineF = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 14, + KT_QRect = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 15, + KT_QRectF = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 16, + KT_QVariant = KT_Qt_Type + KT_Qt_MovableType + KT_HasSimpleDumper + 17, + KT_QBasicAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 18, + KT_QAtomicInt = KT_Qt_Type + KT_HasSimpleDumper + 19, + KT_QObject = KT_Qt_Type + KT_HasSimpleDumper + 20, + KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + 21, // Various QT movable types KT_QPen = KT_Qt_Type + KT_Qt_MovableType + 30, KT_QUrl = KT_Qt_Type + KT_Qt_MovableType + 31, @@ -130,28 +131,28 @@ enum KnownType KT_QGlyphJustification = KT_Qt_Type + KT_Qt_PrimitiveType + 97, KT_QPainterPath_Element = KT_Qt_Type + KT_Qt_PrimitiveType + 98, // Qt Containers - KT_QStringList = KT_Qt_Type + KT_ContainerType + 1, - KT_QList = KT_Qt_Type + KT_ContainerType + 2, - KT_QLinkedList = KT_Qt_Type + KT_ContainerType + 3, - KT_QVector = KT_Qt_Type + KT_ContainerType + 4, - KT_QStack = KT_Qt_Type + KT_ContainerType + 5, - KT_QQueue = KT_Qt_Type + KT_ContainerType + 6, - KT_QSet = KT_Qt_Type + KT_ContainerType + 7, - KT_QHash = KT_Qt_Type + KT_ContainerType + 8, - KT_QMultiHash = KT_Qt_Type + KT_ContainerType + 9, - KT_QMap = KT_Qt_Type + KT_ContainerType + 10, - KT_QMultiMap = KT_Qt_Type + KT_ContainerType + 11, + KT_QStringList = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 1, + KT_QList = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 2, + KT_QLinkedList = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 3, + KT_QVector = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 4, + KT_QStack = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 5, + KT_QQueue = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 6, + KT_QSet = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 7, + KT_QHash = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 8, + KT_QMultiHash = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 9, + KT_QMap = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 10, + KT_QMultiMap = KT_Qt_Type + KT_ContainerType + KT_HasSimpleDumper + 11, // STL - KT_StdString = KT_STL_Type + 1, - KT_StdWString = KT_STL_Type + 2, + KT_StdString = KT_STL_Type + KT_HasSimpleDumper + 1, + KT_StdWString = KT_STL_Type + KT_HasSimpleDumper + 2, // STL containers - KT_StdVector = KT_STL_Type + KT_ContainerType + 1, - KT_StdList = KT_STL_Type + KT_ContainerType + 2, - KT_StdStack = KT_STL_Type + KT_ContainerType + 3, - KT_StdDeque = KT_STL_Type + KT_ContainerType + 4, - KT_StdSet = KT_STL_Type + KT_ContainerType + 5, - KT_StdMap = KT_STL_Type + KT_ContainerType + 6, - KT_StdMultiMap = KT_STL_Type + KT_ContainerType + 7, + KT_StdVector = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 1, + KT_StdList = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 2, + KT_StdStack = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 3, + KT_StdDeque = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 4, + KT_StdSet = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 5, + KT_StdMap = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 6, + KT_StdMultiMap = KT_STL_Type + KT_ContainerType + KT_HasSimpleDumper + 7, }; #endif // KNOWNTYPE_H diff --git a/src/libs/qtcreatorcdbext/symbolgroupnode.cpp b/src/libs/qtcreatorcdbext/symbolgroupnode.cpp index 1c78a7240a2ec8ecf64f6e4c2b1a3feb8b861f9b..d89fbabd6d94f966b97e888706c2af09eda146b0 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupnode.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupnode.cpp @@ -736,6 +736,19 @@ std::wstring SymbolGroupNode::symbolGroupFixedValue() const return value; } +// A quick check if symbol is valid by checking for inaccessible value +bool SymbolGroupNode::isMemoryAccessible() const +{ + static const char notAccessibleValueC[] = "<Memory access error>"; + char buffer[sizeof(notAccessibleValueC)]; + ULONG obtained = 0; + if (FAILED(symbolGroup()->debugSymbolGroup()->GetSymbolValueText(m_index, buffer, sizeof(notAccessibleValueC), &obtained))) + return false; + if (obtained < sizeof(notAccessibleValueC)) + return true; + return strcmp(buffer, notAccessibleValueC) != 0; +} + // Complex dumpers: Get container/fake children void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx) { diff --git a/src/libs/qtcreatorcdbext/symbolgroupnode.h b/src/libs/qtcreatorcdbext/symbolgroupnode.h index 82446acd1399f9addc9fc8a034a54a39d630f951..88350741a2d92070f4d50a97b779ec088518edc2 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupnode.h +++ b/src/libs/qtcreatorcdbext/symbolgroupnode.h @@ -224,6 +224,8 @@ public: std::wstring symbolGroupRawValue() const; std::wstring symbolGroupFixedValue() const; + // A quick check if symbol is valid by checking for inaccessible value + bool isMemoryAccessible() const; std::string type() const; int dumperType() const { return m_dumperType; } // Valid after dumper run diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index fdc9dceb30fac127f92f000ae01c677b8a33f7ba..58e733637b1a52aea8c2a2c03fbc1b44510c8b62 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -38,6 +38,8 @@ SymbolGroupValue::SymbolGroupValue(SymbolGroupNode *node, const SymbolGroupValueContext &ctx) : m_node(node), m_context(ctx) { + if (m_node && !m_node->isMemoryAccessible()) // Invalid if no value + m_node = 0; } SymbolGroupValue::SymbolGroupValue() : @@ -90,6 +92,11 @@ std::string SymbolGroupValue::type() const return isValid() ? m_node->type() : std::string(); } +std::string SymbolGroupValue::name() const +{ + return isValid() ? m_node->name() : std::string(); +} + unsigned SymbolGroupValue::size() const { return isValid() ? m_node->size() : 0; @@ -300,6 +307,17 @@ std::vector<std::string> SymbolGroupValue::innerTypesOf(const std::string &t) return rc; } +std::ostream &operator<<(std::ostream &str, const SymbolGroupValue &v) +{ + if (v) { + str << '\'' << v.name() << "' 0x" << std::showbase << std::hex << v.address() << + std::dec << ' ' << v.type() << ": '" << wStringToString(v.value()) << '\''; + } else { + str << "Invalid value '" << v.error() << '\''; + } + return str; +} + // -------------------- Simple dumping helpers // Courtesy of qdatetime.cpp @@ -1099,7 +1117,7 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, if (knownTypeIn) *knownTypeIn = kt; - if (kt == KT_Unknown) { + if (kt == KT_Unknown || !(kt & KT_HasSimpleDumper)) { QTC_TRACE_OUT return SymbolGroupNode::SimpleDumperNotApplicable; } diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h index 1939047135a7cfb7a723850558bd517aac2d0116..6e1f3339f521ea7a9e7d5b83427d789cfaf1876f 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h @@ -68,6 +68,7 @@ public: // take pointer value and cast to desired (pointer) type SymbolGroupValue pointerTypeCast(const char *type) const; + std::string name() const; std::string type() const; std::vector<std::string> innerTypes() const { return innerTypesOf(type()); } std::wstring value() const; @@ -107,6 +108,9 @@ private: mutable std::string m_errorMessage; }; +// For debugging purposes +std::ostream &operator<<(std::ostream &, const SymbolGroupValue &v); + /* Helpers for detecting types reported from IDebugSymbolGroup * 1) Class prefix==true is applicable to outer types obtained from * from IDebugSymbolGroup: 'class foo' or 'struct foo'. diff --git a/src/plugins/debugger/cdb2/cdbengine2.cpp b/src/plugins/debugger/cdb2/cdbengine2.cpp index e110e3971be6d2d34bec79481864b584ee978b16..91ba92c6d59584f874c2f26fb36039b6670c961e 100644 --- a/src/plugins/debugger/cdb2/cdbengine2.cpp +++ b/src/plugins/debugger/cdb2/cdbengine2.cpp @@ -523,6 +523,11 @@ void CdbEngine::runEngine() postCommand("g", 0); } +bool CdbEngine::commandsPending() const +{ + return !m_builtinCommandQueue.isEmpty() || !m_extensionCommandQueue.isEmpty(); +} + void CdbEngine::shutdownInferior() { if (debug) @@ -535,7 +540,7 @@ void CdbEngine::shutdownInferior() notifyInferiorShutdownOk(); return; } - if (!canInterruptInferior()) { + if (!canInterruptInferior() || commandsPending()) { notifyInferiorShutdownFailed(); return; } @@ -562,8 +567,10 @@ void CdbEngine::shutdownInferior() void CdbEngine::shutdownEngine() { if (debug) - qDebug("CdbEngine::shutdownEngine in state '%s', process running %d", - stateName(state()), isCdbProcessRunning()); + qDebug("CdbEngine::shutdownEngine in state '%s', process running %d," + "accessible=%d,commands pending=%d", + stateName(state()), isCdbProcessRunning(), m_accessible, + commandsPending()); if (!isCdbProcessRunning()) { // Direct launch: Terminated with process. if (debug) @@ -572,8 +579,12 @@ void CdbEngine::shutdownEngine() return; } - // detach: Wait for debugger to finish. - if (m_accessible) { + // No longer trigger anything from messages + disconnect(&m_process, SIGNAL(readyReadStandardOutput()), this, 0); + disconnect(&m_process, SIGNAL(readyReadStandardError()), this, 0); + // Go for kill if there are commands pending. + if (m_accessible && !commandsPending()) { + // detach: Wait for debugger to finish. if (startParameters().startMode == AttachExternal) detachDebugger(); // Remote requires a bit more force to quit. @@ -1351,6 +1362,10 @@ void CdbEngine::handleSessionIdle(const QByteArray &message) WinException exception; exception.fromGdbMI(stopReason); #ifdef Q_OS_WIN + // It is possible to hit on a startup trap while stepping (if something + // pulls DLLs. Avoid showing a 'stopped' Message box. + if (exception.exceptionCode == winExceptionStartupCompleteTrap) + return; if (Debugger::Internal::isDebuggerWinException(exception.exceptionCode)) { showStatusMessage(msgInterrupted()); return; @@ -1845,7 +1860,7 @@ void CdbEngine::handleStackTrace(const CdbExtensionCommandPtr &command) for (int i = 0; i < count; i++) { if (!frames.at(i).file.isEmpty()) { frames[i].file = QDir::cleanPath(normalizeFileName(frames.at(i).file)); - if (current == -1) + if (current == -1 && frames[i].usable) current = i; } } diff --git a/src/plugins/debugger/cdb2/cdbengine2.h b/src/plugins/debugger/cdb2/cdbengine2.h index 36d7ffff12b3bd3cb29eadb7f77f8413b44ee84a..3bd7e5035f69b8aafed2481c03236aa01e83fd70 100644 --- a/src/plugins/debugger/cdb2/cdbengine2.h +++ b/src/plugins/debugger/cdb2/cdbengine2.h @@ -145,6 +145,7 @@ private slots: private: enum SpecialStopMode { NoSpecialStop, SpecialStopSynchronizeBreakpoints }; + bool commandsPending() const; void handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message); bool doSetupEngine(QString *errorMessage); void handleSessionAccessible(unsigned long cdbExState);