Cdb: Unify local and watch handling.

Change-Id: Ic997136cc3b67b9f146e56d0b3ee2cb3140b6b10
Reviewed-by: hjk <hjk@theqtcompany.com>
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
David Schulz
2015-06-11 14:48:33 +02:00
parent 5aa4a4b75b
commit 2ce11e0b5a
3 changed files with 51 additions and 111 deletions

View File

@@ -561,7 +561,10 @@ static std::string commandLocals(ExtensionCommandContext &commandExtCtx,PCSTR ar
return dumpRc; return dumpRc;
} }
return symGroup->dump(iname, dumpContext, parameters.dumpParameters, errorMessage); if (WatchesSymbolGroup::isWatchIname(iname))
return watchesSymbolGroup->dump(iname, dumpContext, parameters.dumpParameters, errorMessage);
else
return symGroup->dump(iname, dumpContext, parameters.dumpParameters, errorMessage);
} }
extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args) extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)

View File

@@ -941,88 +941,6 @@ static inline bool isWatchIName(const QByteArray &iname)
return iname.startsWith("watch"); return iname.startsWith("watch");
} }
void CdbEngine::updateWatchItem(WatchItem *item)
{
if (debug || debugLocals || debugWatches)
qDebug("CdbEngine::updateWatchData() %dms accessible=%d %s: %s",
elapsedLogTime(), m_accessible, stateName(state()),
qPrintable(item->toString()));
if (!m_accessible) // Add watch data while running?
return;
// New watch item?
if (item->isWatcher() && item->isValueNeeded()) {
QByteArray args;
ByteArrayInputStream str(args);
WatchData data = *item; // Don't pass pointers to async functions.
str << data.iname << " \"" << data.exp << '"';
postExtensionCommand("addwatch", args, 0,
[this, data](const CdbResponse &r) { handleAddWatch(r, data); });
return;
}
if (item->wantsChildren || item->isValueNeeded()) {
updateLocalVariable(item->iname);
} else {
item->setAllUnneeded();
item->update();
}
}
void CdbEngine::handleAddWatch(const CdbResponse &response, WatchData data)
{
if (debugWatches)
qDebug() << "handleAddWatch ok=" << response.success << data.iname;
if (response.success) {
updateLocalVariable(data.iname);
} else {
auto item = new WatchItem(data);
item->setError(tr("Unable to add expression"));
watchHandler()->insertItem(item);
showMessage(QString::fromLatin1("Unable to add watch item \"%1\"/\"%2\": %3").
arg(QString::fromLatin1(data.iname), QString::fromLatin1(data.exp),
QString::fromLocal8Bit(response.errorMessage)), LogError);
}
}
void CdbEngine::addLocalsOptions(ByteArrayInputStream &str) const
{
if (boolSetting(VerboseLog))
str << blankSeparator << "-v";
if (boolSetting(UseDebuggingHelpers))
str << blankSeparator << "-c";
if (boolSetting(SortStructMembers))
str << blankSeparator << "-a";
const QByteArray typeFormats = watchHandler()->typeFormatRequests();
if (!typeFormats.isEmpty())
str << blankSeparator << "-T " << typeFormats;
const QByteArray individualFormats = watchHandler()->individualFormatRequests();
if (!individualFormats.isEmpty())
str << blankSeparator << "-I " << individualFormats;
}
void CdbEngine::updateLocalVariable(const QByteArray &iname)
{
const bool isWatch = isWatchIName(iname);
if (debugWatches)
qDebug() << "updateLocalVariable watch=" << isWatch << iname;
QByteArray localsArguments;
ByteArrayInputStream str(localsArguments);
addLocalsOptions(str);
if (!isWatch) {
const int stackFrame = stackHandler()->currentIndex();
if (stackFrame < 0) {
qWarning("Internal error; no stack frame in updateLocalVariable");
return;
}
str << blankSeparator << stackFrame;
}
str << blankSeparator << iname;
postExtensionCommand(isWatch ? "watches" : "locals", localsArguments, 0,
[this](const CdbResponse &r) { handleLocals(r, false); });
}
bool CdbEngine::hasCapability(unsigned cap) const bool CdbEngine::hasCapability(unsigned cap) const
{ {
return cap & (DisassemblerCapability | RegisterCapability return cap & (DisassemblerCapability | RegisterCapability
@@ -1408,11 +1326,13 @@ void CdbEngine::activateFrame(int index)
void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters) void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
{ {
Q_UNUSED(updateParameters)
typedef QHash<QByteArray, int> WatcherHash; typedef QHash<QByteArray, int> WatcherHash;
const bool partialUpdate = !updateParameters.partialVariable.isEmpty();
const bool isWatch = isWatchIName(updateParameters.partialVariable);
const int frameIndex = stackHandler()->currentIndex(); const int frameIndex = stackHandler()->currentIndex();
if (frameIndex < 0) { if (frameIndex < 0 && !isWatch) {
watchHandler()->removeAllData(); watchHandler()->removeAllData();
return; return;
} }
@@ -1427,19 +1347,33 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
* Initial expand, get uninitialized and query */ * Initial expand, get uninitialized and query */
QByteArray arguments; QByteArray arguments;
ByteArrayInputStream str(arguments); ByteArrayInputStream str(arguments);
str << "-D";
// Pre-expand if (!partialUpdate) {
const QSet<QByteArray> expanded = watchHandler()->expandedINames(); str << "-D";
if (!expanded.isEmpty()) { // Pre-expand
str << blankSeparator << "-e "; const QSet<QByteArray> expanded = watchHandler()->expandedINames();
int i = 0; if (!expanded.isEmpty()) {
foreach (const QByteArray &e, expanded) { str << blankSeparator << "-e ";
if (i++) int i = 0;
str << ','; foreach (const QByteArray &e, expanded) {
str << e; if (i++)
str << ',';
str << e;
}
} }
} }
addLocalsOptions(str); if (boolSetting(VerboseLog))
str << blankSeparator << "-v";
if (boolSetting(UseDebuggingHelpers))
str << blankSeparator << "-c";
if (boolSetting(SortStructMembers))
str << blankSeparator << "-a";
const QByteArray typeFormats = watchHandler()->typeFormatRequests();
if (!typeFormats.isEmpty())
str << blankSeparator << "-T " << typeFormats;
const QByteArray individualFormats = watchHandler()->individualFormatRequests();
if (!individualFormats.isEmpty())
str << blankSeparator << "-I " << individualFormats;
// Uninitialized variables if desired. Quote as safeguard against shadowed // Uninitialized variables if desired. Quote as safeguard against shadowed
// variables in case of errors in uninitializedVariables(). // variables in case of errors in uninitializedVariables().
if (boolSetting(UseCodeModel)) { if (boolSetting(UseCodeModel)) {
@@ -1457,20 +1391,27 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
str << '"'; str << '"';
} }
} }
// Perform watches synchronization if (!partialUpdate || isWatch) {
str << blankSeparator << "-W"; // Perform watches synchronization
const WatcherHash watcherHash = WatchHandler::watcherNames(); str << blankSeparator << "-W";
if (!watcherHash.isEmpty()) { const WatcherHash watcherHash = WatchHandler::watcherNames();
const WatcherHash::const_iterator cend = watcherHash.constEnd(); if (!watcherHash.isEmpty()) {
for (WatcherHash::const_iterator it = watcherHash.constBegin(); it != cend; ++it) { const WatcherHash::const_iterator cend = watcherHash.constEnd();
str << blankSeparator << "-w " << it.value() << " \"" << it.key() << '"'; for (WatcherHash::const_iterator it = watcherHash.constBegin(); it != cend; ++it) {
str << blankSeparator << "-w " << "watch." + QByteArray::number(it.value())
<< " \"" << it.key() << '"';
}
} }
} }
// Required arguments: frame // Required arguments: frame
str << blankSeparator << frameIndex; str << blankSeparator << frameIndex;
if (partialUpdate)
str << blankSeparator << updateParameters.partialVariable;
postExtensionCommand("locals", arguments, 0, postExtensionCommand("locals", arguments, 0,
[this](const CdbResponse &r) { handleLocals(r, true); }); [this, partialUpdate](const CdbResponse &r) { handleLocals(r, partialUpdate); });
} }
void CdbEngine::updateAll() void CdbEngine::updateAll()
@@ -1830,7 +1771,7 @@ void CdbEngine::handleRegistersExt(const CdbResponse &response)
postCommandSequence(response.commandSequence); postCommandSequence(response.commandSequence);
} }
void CdbEngine::handleLocals(const CdbResponse &response, bool newFrame) void CdbEngine::handleLocals(const CdbResponse &response, bool partialUpdate)
{ {
if (response.success) { if (response.success) {
watchHandler()->notifyUpdateFinished(); watchHandler()->notifyUpdateFinished();
@@ -1844,7 +1785,7 @@ void CdbEngine::handleLocals(const CdbResponse &response, bool newFrame)
GdbMi partial; GdbMi partial;
partial.m_name = "partial"; partial.m_name = "partial";
partial.m_data = QByteArray::number(newFrame ? 0 : 1); partial.m_data = QByteArray::number(partialUpdate ? 1 : 0);
GdbMi all; GdbMi all;
all.m_children.push_back(data); all.m_children.push_back(data);

View File

@@ -89,7 +89,6 @@ public:
virtual void shutdownEngine(); virtual void shutdownEngine();
virtual void abortDebugger(); virtual void abortDebugger();
virtual void detachDebugger(); virtual void detachDebugger();
virtual void updateWatchItem(WatchItem *item);
virtual bool hasCapability(unsigned cap) const; virtual bool hasCapability(unsigned cap) const;
virtual void watchPoint(const QPoint &); virtual void watchPoint(const QPoint &);
virtual void setRegisterValue(const QByteArray &name, const QString &value); virtual void setRegisterValue(const QByteArray &name, const QString &value);
@@ -235,8 +234,7 @@ private:
// Extension commands // Extension commands
void handleThreads(const CdbResponse &response); void handleThreads(const CdbResponse &response);
void handlePid(const CdbResponse &response); void handlePid(const CdbResponse &response);
void handleLocals(const CdbResponse &response, bool newFrame); void handleLocals(const CdbResponse &response, bool partialUpdate);
void handleAddWatch(const CdbResponse &response, WatchData item);
void handleExpandLocals(const CdbResponse &response); void handleExpandLocals(const CdbResponse &response);
void handleRegistersExt(const CdbResponse &response); void handleRegistersExt(const CdbResponse &response);
void handleModules(const CdbResponse &response); void handleModules(const CdbResponse &response);
@@ -246,11 +244,9 @@ private:
void handleBreakPoints(const GdbMi &value); void handleBreakPoints(const GdbMi &value);
void handleAdditionalQmlStack(const CdbResponse &response); void handleAdditionalQmlStack(const CdbResponse &response);
NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f); NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f);
void updateLocalVariable(const QByteArray &iname);
void doUpdateLocals(const UpdateParameters &params) override; void doUpdateLocals(const UpdateParameters &params) override;
void updateAll() override; void updateAll() override;
int elapsedLogTime() const; int elapsedLogTime() const;
void addLocalsOptions(ByteArrayInputStream &s) const;
unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto); unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto);
void mergeStartParametersSourcePathMap(); void mergeStartParametersSourcePathMap();