diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index b8db4f753bae551d72657cdeb92c07dadb29b70c..7f80abcb37c0a66fc69ee853ff610bd43aa7ca57 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -620,6 +620,29 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v { if (debugCDB) qDebug() << Q_FUNC_INFO << expr << value; + const int frameIndex = m_d->m_debuggerManagerAccess->stackHandler()->currentIndex(); + QString errorMessage; + bool success = false; + do { + QString newValue; + CdbSymbolGroupContext *sg = m_d->getStackFrameSymbolGroupContext(frameIndex, &errorMessage); + if (!sg) + break; + if (!sg->assignValue(expr, value, &newValue, &errorMessage)) + break; + // Update view + WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler(); + if (WatchData *fwd = watchHandler->findData(expr)) { + fwd->setValue(newValue); + watchHandler->insertData(*fwd); + watchHandler->rebuildModel(); + } + success = true; + } while (false); + if (!success) { + const QString msg = tr("Unable to assign the value '%1' to '%2': %3").arg(value, expr, errorMessage); + qWarning("%s\n", qPrintable(msg)); + } } void CdbDebugEngine::executeDebuggerCommand(const QString &command) @@ -901,12 +924,13 @@ void CdbDebugEnginePrivate::updateStackTrace() } m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames); + m_firstActivatedFrame = true; if (current >= 0) { m_debuggerManagerAccess->stackHandler()->setCurrentIndex(current); m_debuggerManager->gotoLocation(stackFrames.at(current).file, stackFrames.at(current).line, true); - } - m_firstActivatedFrame = true; + m_engine->activateFrame(current); + } } void CdbDebugEnginePrivate::handleDebugOutput(const char *szOutputString) diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp index d7178c31203ffc271953705f7f5cec3eba0907d1..5666fd58aa70b80eaeb00fa444351b50d37b911d 100644 --- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp @@ -33,7 +33,10 @@ #include "watchutils.h" #include <QtCore/QTextStream> -enum { maxRecursionDepth = 10 }; +static inline QString msgSymbolNotFound(const QString &s) +{ + return QString::fromLatin1("The symbol '%1' could not be found.").arg(s); +} static inline bool isTopLevelSymbol(const DEBUG_SYMBOL_PARAMETERS &p) { return p.ParentSymbol == DEBUG_ANY_ID; } @@ -217,7 +220,7 @@ CdbSymbolGroupContext::SymbolState CdbSymbolGroupContext::symbolState(const QStr const NameIndexMap::const_iterator it = m_inameIndexMap.constFind(prefix); if (it != m_inameIndexMap.constEnd()) return symbolState(it.value()); - qWarning("WARNING %s: %s not found.\n", Q_FUNC_INFO, qPrintable(prefix)); + qWarning("WARNING %s: %s\n", Q_FUNC_INFO, msgSymbolNotFound(prefix)); return LeafSymbol; } @@ -314,23 +317,6 @@ void CdbSymbolGroupContext::clear() m_inameIndexMap.clear(); } -// Expand all top level symbols -bool CdbSymbolGroupContext::expandTopLevel(QString *errorMessage) -{ - if (debugCDB) - qDebug() << '>' << Q_FUNC_INFO; - - for (int i = m_symbolParameters.size() - 1; i >= 0; i --) { - const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i); - if (isTopLevelSymbol(p) && (getSymbolState(p) == CollapsedSymbol) && isSymbolDisplayable(p)) - if (!expandSymbol(symbolINameAt(i), i, errorMessage)) - return false; - } - if (debugCDB) - qDebug() << '<' << Q_FUNC_INFO << '\n' << toString(); - return true; -} - int CdbSymbolGroupContext::getDisplayableChildCount(unsigned long index) const { if (!isExpanded(index)) @@ -355,12 +341,22 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const return m_inameIndexMap.key(index); } +static inline QString hexSymbolOffset(IDebugSymbolGroup2 *sg, unsigned long index) +{ + ULONG64 rc = 0; + if (FAILED(sg->GetSymbolOffset(index, &rc))) + rc = 0; + return QLatin1String("0x") + QString::number(rc, 16); +} + WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const { WatchData wd; wd.iname = symbolINameAt(index); + wd.exp = wd.iname; const int lastDelimiterPos = wd.iname.lastIndexOf(m_nameDelimiter); wd.name = lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1); + wd.addr = hexSymbolOffset(m_symbolGroup, index); wd.setType(getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index)); wd.setValue(getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index).toUtf8()); wd.setChildrenNeeded(); // compensate side effects of above setters @@ -381,6 +377,29 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const return wd; } +bool CdbSymbolGroupContext::assignValue(const QString &iname, const QString &value, + QString *newValue, QString *errorMessage) +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << '\n' << iname << value; + const NameIndexMap::const_iterator it = m_inameIndexMap.constFind(iname); + if (it == m_inameIndexMap.constEnd()) { + *errorMessage = msgSymbolNotFound(iname); + return false; + } + const unsigned long index = it.value(); + const HRESULT hr = m_symbolGroup->WriteSymbolWide(index, value.utf16()); + if (FAILED(hr)) { + *errorMessage = QString::fromLatin1("Unable to assign '%1' to '%2': %3"). + arg(value, iname, msgComFailed("WriteSymbolWide", hr)); + return false; + } + if (newValue) + *newValue = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index); + return true; +} + +// - Watch model functions class WatchDataBackInserter { public: explicit WatchDataBackInserter(QList<WatchData> &wh) : m_wh(wh) {} @@ -399,7 +418,7 @@ private: static bool insertChildrenRecursion(const QString &iname, CdbSymbolGroupContext *sg, WatchHandler *watchHandler, - bool forceRecursion, + int maxRecursionLevel, int level, QString *errorMessage, int *childCount = 0); @@ -408,22 +427,21 @@ static bool insertChildrenRecursion(const QString &iname, static bool insertSymbolRecursion(WatchData wd, CdbSymbolGroupContext *sg, WatchHandler *watchHandler, - bool forceRecursion, + int maxRecursionLevel, int level, QString *errorMessage) { - if (level > maxRecursionDepth) { - *errorMessage = QString::fromLatin1("Max recursion level %1 reached for '%2', bailing out.").arg(level).arg(wd.iname); - return false; - } // Find out whether to recurse (has children or at least knows it has children) - const bool recurse = forceRecursion && (wd.childCount > 0 || wd.isChildrenNeeded()); + // Open next level if specified by recursion depth or child is already expanded + // (Sometimes, some root children are already expanded after creating the context). + const bool hasChildren = wd.childCount > 0 || wd.isChildrenNeeded(); + const bool recurse = hasChildren && (level < maxRecursionLevel || sg->isExpanded(wd.iname)); if (debugCDB) qDebug() << Q_FUNC_INFO << '\n' << wd.iname << "level=" << level << "recurse=" << recurse; bool rc = true; if (recurse) { // Determine number of children and indicate in model int childCount; - rc = insertChildrenRecursion(wd.iname, sg, watchHandler, false, level, errorMessage, &childCount); + rc = insertChildrenRecursion(wd.iname, sg, watchHandler, maxRecursionLevel, level, errorMessage, &childCount); if (rc) { wd.setChildCount(childCount); wd.setChildrenUnneeded(); @@ -445,7 +463,7 @@ static bool insertSymbolRecursion(WatchData wd, static bool insertChildrenRecursion(const QString &iname, CdbSymbolGroupContext *sg, WatchHandler *watchHandler, - bool forceRecursion, + int maxRecursionLevel, int level, QString *errorMessage, int *childCountPtr) @@ -465,7 +483,7 @@ static bool insertChildrenRecursion(const QString &iname, for (int c = 0; c < childCount; c++) { const WatchData &wd = watchList.at(c); if (wd.isValid()) { // We sometimes get empty names for deeply nested data - if (!insertSymbolRecursion(wd, sg, watchHandler, forceRecursion, level + 1, errorMessage)) + if (!insertSymbolRecursion(wd, sg, watchHandler, maxRecursionLevel, level + 1, errorMessage)) return false; succeededChildCount++; } else { @@ -486,16 +504,13 @@ bool CdbSymbolGroupContext::populateModelInitially(CdbSymbolGroupContext *sg, if (debugCDB) qDebug() << "###" << Q_FUNC_INFO; - if (!sg->expandTopLevel(errorMessage)) - return false; - - // Insert root items and known children of level 1 + // Insert root items QList<WatchData> watchList; if (!sg->getChildSymbols(sg->prefix(), WatchDataBackInserter(watchList), errorMessage)) return false; foreach(const WatchData &wd, watchList) - if (!insertSymbolRecursion(wd, sg, watchHandler, true, 0, errorMessage)) + if (!insertSymbolRecursion(wd, sg, watchHandler, 0, 0, errorMessage)) return false; return true; } @@ -508,7 +523,7 @@ bool CdbSymbolGroupContext::completeModel(CdbSymbolGroupContext *sg, if (debugCDB) qDebug().nospace() << "###>" << Q_FUNC_INFO << ' ' << incomplete.size() << '\n'; // The view reinserts any node being expanded with flag 'ChildrenNeeded'. - // Expand next level in context unless this is already the case. + // Recurse down one level in context unless this is already the case. foreach(WatchData wd, incomplete) { const bool contextExpanded = sg->isExpanded(wd.iname); if (debugCDB) @@ -517,7 +532,7 @@ bool CdbSymbolGroupContext::completeModel(CdbSymbolGroupContext *sg, wd.setChildrenUnneeded(); watchHandler->insertData(wd); } else { - if (!insertSymbolRecursion(wd, sg, watchHandler, true, 0, errorMessage)) + if (!insertSymbolRecursion(wd, sg, watchHandler, 1, 0, errorMessage)) return false; } } diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h index 50bc01d588133b2fa7b9584642de0fd76d3258b6..a7501128973438a219c8e25e1b5f4a1f5f327115 100644 --- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h @@ -65,11 +65,14 @@ class CdbSymbolGroupContext public: ~CdbSymbolGroupContext(); static CdbSymbolGroupContext *create(const QString &prefix, - IDebugSymbolGroup2 *symbolGroup, + IDebugSymbolGroup2 *symbolGroup, QString *errorMessage); QString prefix() const { return m_prefix; } + bool assignValue(const QString &iname, const QString &value, + QString *newValue /* = 0 */, QString *errorMessage); + static bool populateModelInitially(CdbSymbolGroupContext *sg, WatchHandler *wh, QString *errorMessage); static bool completeModel(CdbSymbolGroupContext *sg, WatchHandler *wh, QString *errorMessage); @@ -77,8 +80,6 @@ public: template <class OutputIterator> bool getChildSymbols(const QString &prefix, OutputIterator it, QString *errorMessage); - bool expandTopLevel(QString *errorMessage); - enum SymbolState { LeafSymbol, ExpandedSymbol, CollapsedSymbol }; SymbolState symbolState(unsigned long index) const; SymbolState symbolState(const QString &prefix) const; diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index f6388fa835947b36a5fa3d9c348bad86bb1eb47c..13b367dd7ecd4fb93c270e58b877bdbfb91302e5 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -93,5 +93,5 @@ DEFINES += USE_MODEL_TEST=1 win32 { include(win/win.pri) - CONFIG(cdbdebugger):include(cdb/cdb.pri) + include(cdb/cdb.pri) }