From f71286db98fbc93f415a7d9a6050bc2bc79fdd07 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 23 Apr 2020 10:00:23 +0200 Subject: [PATCH] Debugger: evaluate expression before assigning when using python dumper Fixes: QTCREATORBUG-23711 Change-Id: Ic386b3e4bdd948e74f52116248de1b33a35fe03a Reviewed-by: hjk Reviewed-by: Christian Stenger --- .../qtcreatorcdbext/qtcreatorcdbextension.cpp | 100 +++++++++++------- src/plugins/debugger/cdb/cdbengine.cpp | 11 +- 2 files changed, 69 insertions(+), 42 deletions(-) diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp index 6bbd71367c0..77e537c275e 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp @@ -160,7 +160,7 @@ static const CommandDescription commandDescriptions[] = { {"assign","Assigns a value to a variable in current symbol group.", "[-t token] [-h] \n" "-h Data are hex-encoded, binary data\n" - "-u Data are hex-encoded, UTF16 data" + "-e iname is an hex-encoded expression to be evaluated " }, {"threads","Lists threads in GDBMI format.","[-t token]"}, {"registers","Lists registers in GDBMI format","[-t token]"}, @@ -819,57 +819,77 @@ extern "C" HRESULT CALLBACK assign(CIDebugClient *client, PCSTR argsIn) ExtensionCommandContext exc(client); std::string errorMessage; - bool success = false; bool encoded = false; + bool evaluateExpression = false; int token = 0; - do { - StringList tokens = commandTokens(argsIn, &token); - if (tokens.empty()) { - errorMessage = singleLineUsage(commandDescriptions[CmdAssign]); - break; - } - + StringList tokens = commandTokens(argsIn, &token); + while (!tokens.empty()) { if (tokens.front() == "-h") { encoded = true; tokens.pop_front(); + continue; } - if (tokens.empty()) { - errorMessage = singleLineUsage(commandDescriptions[CmdAssign]); - break; + if (tokens.front() == "-e") { + evaluateExpression = true; + tokens.pop_front(); + continue; } + break; + }; - // Parse 'assign locals.x=5' - const std::string::size_type equalsPos = tokens.front().find('='); - if (equalsPos == std::string::npos) { - errorMessage = singleLineUsage(commandDescriptions[CmdAssign]); - break; - } - const std::string iname = tokens.front().substr(0, equalsPos); - const std::string value = tokens.front().substr(equalsPos + 1, tokens.front().size() - equalsPos - 1); - // get the symbolgroup - int currentFrame = ExtensionContext::instance().symbolGroupFrame(); - if (currentFrame < 0) { - CIDebugControl *control = ExtensionCommandContext::instance()->control(); - DEBUG_STACK_FRAME frame; - if (FAILED(control->GetStackTrace(0, 0, 0, &frame, 1, NULL))) { - errorMessage = "No current frame."; - break; + // Parse 'assign locals.x=5' + const std::string::size_type equalsPos = tokens.empty() ? std::string::npos + : tokens.front().find('='); + if (equalsPos == std::string::npos) { + errorMessage = singleLineUsage(commandDescriptions[CmdAssign]); + } else { + std::string iname = tokens.front().substr(0, equalsPos); + const std::string value = tokens.front().substr(equalsPos + 1, + tokens.front().size() - equalsPos - 1); + SymbolGroup *symGroup = nullptr; + if (evaluateExpression) { + WatchesSymbolGroup *watchesSymGroup + = ExtensionContext::instance().watchesSymbolGroup(exc.symbols(), &errorMessage); + std::string tempAssignIname = "watch.tmpassign"; + if (watchesSymGroup) { + if (watchesSymGroup->addWatch(exc.symbols(), + tempAssignIname, + stringFromHex(iname), + &errorMessage)) { + iname = tempAssignIname; + symGroup = watchesSymGroup; + } + } + } else { + // get the symbolgroup + int currentFrame = ExtensionContext::instance().symbolGroupFrame(); + if (currentFrame < 0) { + CIDebugControl *control = ExtensionCommandContext::instance()->control(); + DEBUG_STACK_FRAME frame; + if (FAILED(control->GetStackTrace(0, 0, 0, &frame, 1, NULL))) + errorMessage = "No current frame."; + else + currentFrame = frame.FrameNumber; + } + if (currentFrame >= 0) { + symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), + exc.threadId(), + currentFrame, + &errorMessage); } - currentFrame = frame.FrameNumber; } - SymbolGroup *symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), currentFrame, &errorMessage); - if (!symGroup) - break; - success = symGroup->assign(iname, encoded ? stringFromHex(value) : value, - SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), - &errorMessage); - } while (false); + if (symGroup + && symGroup->assign(iname, + encoded ? stringFromHex(value) : value, + SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), + &errorMessage)) { + ExtensionContext::instance().report('R', token, 0, "assign", "Ok"); + return S_OK; + } + } - if (success) - ExtensionContext::instance().report('R', token, 0, "assign", "Ok"); - else - ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str()); + ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str()); return S_OK; } diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 757110161ba..a98ee3e9a7e 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -929,8 +929,15 @@ void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const Q qWarning("Internal error: assignValueInDebugger: Invalid state or no stack frame."); return; } - runCommand({m_extensionCommandPrefix + "assign -h " + w->iname + '=' + toHex(value.toString()), - NoFlags}); + if (m_pythonVersion > 0x030000 && w->isWatcher()) { + runCommand({m_extensionCommandPrefix + "assign -h -e " + toHex(w->expression()) + '=' + + toHex(value.toString()), + NoFlags}); + } else { + runCommand({m_extensionCommandPrefix + "assign -h " + w->iname + '=' + toHex(value.toString()), + NoFlags}); + } + // Update all locals in case we change a union or something pointed to // that affects other variables, too. updateLocals();