From 28d1d3ffe1615d5f699050a05525ded7a1c2531f Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 14 Apr 2023 09:36:26 +0200 Subject: [PATCH] Debugger: support piping the python dumper to cdb Fixes: QTCREATORBUG-29000 Change-Id: I7454ded07829d06a33dc1b2ec95a838ca977ca95 Reviewed-by: Reviewed-by: hjk --- share/qtcreator/debugger/loadorder.txt | 2 +- src/plugins/debugger/cdb/cdbengine.cpp | 71 ++++++++++++++++++++++---- src/plugins/debugger/cdb/cdbengine.h | 6 +-- src/plugins/debugger/gdb/gdbengine.cpp | 6 ++- 4 files changed, 69 insertions(+), 16 deletions(-) diff --git a/share/qtcreator/debugger/loadorder.txt b/share/qtcreator/debugger/loadorder.txt index e348970ced0..23d4dbf3a4a 100644 --- a/share/qtcreator/debugger/loadorder.txt +++ b/share/qtcreator/debugger/loadorder.txt @@ -1,7 +1,7 @@ utils gdbtracepoint dumper -gdbbridge +***bridge*** boosttypes creatortypes libcpp_stdtypes diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index a45dfdeb200..0bda7399ec3 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -954,9 +954,11 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) return; } - if (dbgCmd.flags == ScriptCommand) { + if (dbgCmd.flags & ScriptCommand) { // repack script command into an extension command DebuggerCommand newCmd("script", ExtensionCommand, dbgCmd.callback); + if (dbgCmd.flags & DebuggerCommand::Silent) + newCmd.flags |= DebuggerCommand::Silent; if (!dbgCmd.args.isNull()) newCmd.args = QString{dbgCmd.function + '(' + dbgCmd.argsToPython() + ')'}; else @@ -975,7 +977,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) } else { const int token = ++m_nextCommandToken; StringInputStream str(fullCmd); - if (dbgCmd.flags == BuiltinCommand) { + if (dbgCmd.flags & BuiltinCommand) { // Post a built-in-command producing free-format output with a callback. // In order to catch the output, it is enclosed in 'echo' commands // printing a specially formatted token to be identifiable in the output. @@ -986,7 +988,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) showMessage("Command is longer than 4096 characters execution will likely fail.", LogWarning); } - } else if (dbgCmd.flags == ExtensionCommand) { + } else if (dbgCmd.flags & ExtensionCommand) { // Post an extension command producing one-line output with a callback, // pass along token for identification in hash. @@ -1020,7 +1022,8 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) if (debug) { qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd)); } - showMessage(cmd, LogInput); + if (!(dbgCmd.flags & DebuggerCommand::Silent)) + showMessage(cmd, LogInput); m_process.write(fullCmd); } @@ -2766,12 +2769,60 @@ void CdbEngine::setupScripting(const DebuggerResponse &response) return; } - QString dumperPath = Core::ICore::resourcePath("debugger").toUserOutput(); - dumperPath.replace('\\', "\\\\"); - runCommand({"sys.path.insert(1, '" + dumperPath + "')", ScriptCommand}); - runCommand({"from cdbbridge import Dumper", ScriptCommand}); - runCommand({"print(dir())", ScriptCommand}); - runCommand({"theDumper = Dumper()", ScriptCommand}); + + if (runParameters().startMode == AttachToRemoteServer) { + FilePath dumperPath = Core::ICore::resourcePath("debugger"); + const FilePath loadOrderFile = dumperPath / "loadorder.txt"; + const expected_str toLoad = loadOrderFile.fileContents(); + if (!toLoad) { + Core::AsynchronousMessageBox::critical( + Tr::tr("Cannot Find Debugger Initialization Script"), + Tr::tr("Cannot read %1: %2").arg(loadOrderFile.toUserOutput(), toLoad.error())); + notifyEngineSetupFailed(); + return; + } + + runCommand({"import sys, types", ScriptCommand}); + QStringList moduleList; + for (const QByteArray &rawModuleName : toLoad->split('\n')) { + QString module = QString::fromUtf8(rawModuleName).trimmed(); + if (module.startsWith('#') || module.isEmpty()) + continue; + if (module == "***bridge***") + module = "cdbbridge"; + + const FilePath codeFile = dumperPath / (module + ".py"); + const expected_str code = codeFile.fileContents(); + if (!code) { + qDebug() << Tr::tr("Cannot read %1: %2").arg(codeFile.toUserOutput(), code.error()); + continue; + } + + showMessage("Reading " + codeFile.toUserOutput(), LogInput); + runCommand({QString("module = types.ModuleType('%1')").arg(module), ScriptCommand}); + runCommand({QString("code = bytes.fromhex('%1').decode('utf-8')") + .arg(QString::fromUtf8(code->toHex())), ScriptCommand | DebuggerCommand::Silent}); + runCommand({QString("exec(code, module.__dict__)"), ScriptCommand}); + runCommand({QString("sys.modules['%1'] = module").arg(module), ScriptCommand}); + runCommand({QString("import %1").arg(module), ScriptCommand}); + + if (module.endsWith("types")) + moduleList.append('"' + module + '"'); + } + + runCommand({"from cdbbridge import Dumper", ScriptCommand}); + runCommand({"print(dir())", ScriptCommand}); + runCommand({"theDumper = Dumper()", ScriptCommand}); + runCommand({QString("theDumper.dumpermodules = [%1]").arg(moduleList.join(',')), ScriptCommand}); + + } else { + QString dumperPath = Core::ICore::resourcePath("debugger").toUserOutput(); + dumperPath.replace('\\', "\\\\"); + runCommand({"sys.path.insert(1, '" + dumperPath + "')", ScriptCommand}); + runCommand({"from cdbbridge import Dumper", ScriptCommand}); + runCommand({"print(dir())", ScriptCommand}); + runCommand({"theDumper = Dumper()", ScriptCommand}); + } const QString path = debuggerSettings()->extraDumperFile.value(); if (!path.isEmpty() && QFileInfo(path).isReadable()) { diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index a231ce39c23..f0c098e415a 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -110,9 +110,9 @@ private: }; enum CommandFlags { NoFlags = 0, - BuiltinCommand, - ExtensionCommand, - ScriptCommand + BuiltinCommand = DebuggerCommand::Silent << 1, + ExtensionCommand = DebuggerCommand::Silent << 2, + ScriptCommand = DebuggerCommand::Silent << 3 }; void init(); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 532c9ef0695..d02b356a95b 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3986,9 +3986,11 @@ void GdbEngine::handleGdbStarted() runCommand({"python import sys, types"}); QStringList moduleList; for (const QByteArray &rawModuleName : toLoad->split('\n')) { - const QString module = QString::fromUtf8(rawModuleName).trimmed(); - if (module.startsWith('#')) + QString module = QString::fromUtf8(rawModuleName).trimmed(); + if (module.startsWith('#') || module.isEmpty()) continue; + if (module == "***bridge***") + module = "gdbbridge"; const FilePath codeFile = dumperPath / (module + ".py"); const expected_str code = codeFile.fileContents();