Debugger: evaluate expression before assigning when using python dumper

Fixes: QTCREATORBUG-23711
Change-Id: Ic386b3e4bdd948e74f52116248de1b33a35fe03a
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2020-04-23 10:00:23 +02:00
parent f057adcff2
commit f71286db98
2 changed files with 69 additions and 42 deletions

View File

@@ -160,7 +160,7 @@ static const CommandDescription commandDescriptions[] = {
{"assign","Assigns a value to a variable in current symbol group.", {"assign","Assigns a value to a variable in current symbol group.",
"[-t token] [-h] <iname=value>\n" "[-t token] [-h] <iname=value>\n"
"-h Data are hex-encoded, binary data\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]"}, {"threads","Lists threads in GDBMI format.","[-t token]"},
{"registers","Lists registers in GDBMI format","[-t token]"}, {"registers","Lists registers in GDBMI format","[-t token]"},
@@ -819,56 +819,76 @@ extern "C" HRESULT CALLBACK assign(CIDebugClient *client, PCSTR argsIn)
ExtensionCommandContext exc(client); ExtensionCommandContext exc(client);
std::string errorMessage; std::string errorMessage;
bool success = false;
bool encoded = false; bool encoded = false;
bool evaluateExpression = false;
int token = 0; int token = 0;
do {
StringList tokens = commandTokens<StringList>(argsIn, &token); StringList tokens = commandTokens<StringList>(argsIn, &token);
if (tokens.empty()) { while (!tokens.empty()) {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
break;
}
if (tokens.front() == "-h") { if (tokens.front() == "-h") {
encoded = true; encoded = true;
tokens.pop_front(); tokens.pop_front();
continue;
} }
if (tokens.empty()) { if (tokens.front() == "-e") {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]); evaluateExpression = true;
break; tokens.pop_front();
continue;
} }
break;
};
// Parse 'assign locals.x=5' // Parse 'assign locals.x=5'
const std::string::size_type equalsPos = tokens.front().find('='); const std::string::size_type equalsPos = tokens.empty() ? std::string::npos
: tokens.front().find('=');
if (equalsPos == std::string::npos) { if (equalsPos == std::string::npos) {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]); errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
break; } 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;
} }
const std::string iname = tokens.front().substr(0, equalsPos); }
const std::string value = tokens.front().substr(equalsPos + 1, tokens.front().size() - equalsPos - 1); } else {
// get the symbolgroup // get the symbolgroup
int currentFrame = ExtensionContext::instance().symbolGroupFrame(); int currentFrame = ExtensionContext::instance().symbolGroupFrame();
if (currentFrame < 0) { if (currentFrame < 0) {
CIDebugControl *control = ExtensionCommandContext::instance()->control(); CIDebugControl *control = ExtensionCommandContext::instance()->control();
DEBUG_STACK_FRAME frame; DEBUG_STACK_FRAME frame;
if (FAILED(control->GetStackTrace(0, 0, 0, &frame, 1, NULL))) { if (FAILED(control->GetStackTrace(0, 0, 0, &frame, 1, NULL)))
errorMessage = "No current frame."; errorMessage = "No current frame.";
break; else
}
currentFrame = frame.FrameNumber; currentFrame = frame.FrameNumber;
} }
SymbolGroup *symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), currentFrame, &errorMessage); if (currentFrame >= 0) {
if (!symGroup) symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(),
break; exc.threadId(),
success = symGroup->assign(iname, encoded ? stringFromHex(value) : value, currentFrame,
SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()),
&errorMessage); &errorMessage);
} while (false); }
}
if (success) if (symGroup
&& symGroup->assign(iname,
encoded ? stringFromHex(value) : value,
SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()),
&errorMessage)) {
ExtensionContext::instance().report('R', token, 0, "assign", "Ok"); ExtensionContext::instance().report('R', token, 0, "assign", "Ok");
else return S_OK;
}
}
ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str()); ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str());
return S_OK; return S_OK;
} }

View File

@@ -929,8 +929,15 @@ void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const Q
qWarning("Internal error: assignValueInDebugger: Invalid state or no stack frame."); qWarning("Internal error: assignValueInDebugger: Invalid state or no stack frame.");
return; return;
} }
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()), runCommand({m_extensionCommandPrefix + "assign -h " + w->iname + '=' + toHex(value.toString()),
NoFlags}); NoFlags});
}
// Update all locals in case we change a union or something pointed to // Update all locals in case we change a union or something pointed to
// that affects other variables, too. // that affects other variables, too.
updateLocals(); updateLocals();