forked from qt-creator/qt-creator
Debugger: support piping the python dumper to cdb
Fixes: QTCREATORBUG-29000 Change-Id: I7454ded07829d06a33dc1b2ec95a838ca977ca95 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
utils
|
utils
|
||||||
gdbtracepoint
|
gdbtracepoint
|
||||||
dumper
|
dumper
|
||||||
gdbbridge
|
***bridge***
|
||||||
boosttypes
|
boosttypes
|
||||||
creatortypes
|
creatortypes
|
||||||
libcpp_stdtypes
|
libcpp_stdtypes
|
||||||
|
@@ -954,9 +954,11 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbgCmd.flags == ScriptCommand) {
|
if (dbgCmd.flags & ScriptCommand) {
|
||||||
// repack script command into an extension command
|
// repack script command into an extension command
|
||||||
DebuggerCommand newCmd("script", ExtensionCommand, dbgCmd.callback);
|
DebuggerCommand newCmd("script", ExtensionCommand, dbgCmd.callback);
|
||||||
|
if (dbgCmd.flags & DebuggerCommand::Silent)
|
||||||
|
newCmd.flags |= DebuggerCommand::Silent;
|
||||||
if (!dbgCmd.args.isNull())
|
if (!dbgCmd.args.isNull())
|
||||||
newCmd.args = QString{dbgCmd.function + '(' + dbgCmd.argsToPython() + ')'};
|
newCmd.args = QString{dbgCmd.function + '(' + dbgCmd.argsToPython() + ')'};
|
||||||
else
|
else
|
||||||
@@ -975,7 +977,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
|||||||
} else {
|
} else {
|
||||||
const int token = ++m_nextCommandToken;
|
const int token = ++m_nextCommandToken;
|
||||||
StringInputStream str(fullCmd);
|
StringInputStream str(fullCmd);
|
||||||
if (dbgCmd.flags == BuiltinCommand) {
|
if (dbgCmd.flags & BuiltinCommand) {
|
||||||
// Post a built-in-command producing free-format output with a callback.
|
// Post a built-in-command producing free-format output with a callback.
|
||||||
// In order to catch the output, it is enclosed in 'echo' commands
|
// In order to catch the output, it is enclosed in 'echo' commands
|
||||||
// printing a specially formatted token to be identifiable in the output.
|
// 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.",
|
showMessage("Command is longer than 4096 characters execution will likely fail.",
|
||||||
LogWarning);
|
LogWarning);
|
||||||
}
|
}
|
||||||
} else if (dbgCmd.flags == ExtensionCommand) {
|
} else if (dbgCmd.flags & ExtensionCommand) {
|
||||||
|
|
||||||
// Post an extension command producing one-line output with a callback,
|
// Post an extension command producing one-line output with a callback,
|
||||||
// pass along token for identification in hash.
|
// pass along token for identification in hash.
|
||||||
@@ -1020,6 +1022,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
|||||||
if (debug) {
|
if (debug) {
|
||||||
qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd));
|
qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd));
|
||||||
}
|
}
|
||||||
|
if (!(dbgCmd.flags & DebuggerCommand::Silent))
|
||||||
showMessage(cmd, LogInput);
|
showMessage(cmd, LogInput);
|
||||||
m_process.write(fullCmd);
|
m_process.write(fullCmd);
|
||||||
}
|
}
|
||||||
@@ -2766,12 +2769,60 @@ void CdbEngine::setupScripting(const DebuggerResponse &response)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (runParameters().startMode == AttachToRemoteServer) {
|
||||||
|
FilePath dumperPath = Core::ICore::resourcePath("debugger");
|
||||||
|
const FilePath loadOrderFile = dumperPath / "loadorder.txt";
|
||||||
|
const expected_str<QByteArray> 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<QByteArray> 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();
|
QString dumperPath = Core::ICore::resourcePath("debugger").toUserOutput();
|
||||||
dumperPath.replace('\\', "\\\\");
|
dumperPath.replace('\\', "\\\\");
|
||||||
runCommand({"sys.path.insert(1, '" + dumperPath + "')", ScriptCommand});
|
runCommand({"sys.path.insert(1, '" + dumperPath + "')", ScriptCommand});
|
||||||
runCommand({"from cdbbridge import Dumper", ScriptCommand});
|
runCommand({"from cdbbridge import Dumper", ScriptCommand});
|
||||||
runCommand({"print(dir())", ScriptCommand});
|
runCommand({"print(dir())", ScriptCommand});
|
||||||
runCommand({"theDumper = Dumper()", ScriptCommand});
|
runCommand({"theDumper = Dumper()", ScriptCommand});
|
||||||
|
}
|
||||||
|
|
||||||
const QString path = debuggerSettings()->extraDumperFile.value();
|
const QString path = debuggerSettings()->extraDumperFile.value();
|
||||||
if (!path.isEmpty() && QFileInfo(path).isReadable()) {
|
if (!path.isEmpty() && QFileInfo(path).isReadable()) {
|
||||||
|
@@ -110,9 +110,9 @@ private:
|
|||||||
};
|
};
|
||||||
enum CommandFlags {
|
enum CommandFlags {
|
||||||
NoFlags = 0,
|
NoFlags = 0,
|
||||||
BuiltinCommand,
|
BuiltinCommand = DebuggerCommand::Silent << 1,
|
||||||
ExtensionCommand,
|
ExtensionCommand = DebuggerCommand::Silent << 2,
|
||||||
ScriptCommand
|
ScriptCommand = DebuggerCommand::Silent << 3
|
||||||
};
|
};
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
@@ -3986,9 +3986,11 @@ void GdbEngine::handleGdbStarted()
|
|||||||
runCommand({"python import sys, types"});
|
runCommand({"python import sys, types"});
|
||||||
QStringList moduleList;
|
QStringList moduleList;
|
||||||
for (const QByteArray &rawModuleName : toLoad->split('\n')) {
|
for (const QByteArray &rawModuleName : toLoad->split('\n')) {
|
||||||
const QString module = QString::fromUtf8(rawModuleName).trimmed();
|
QString module = QString::fromUtf8(rawModuleName).trimmed();
|
||||||
if (module.startsWith('#'))
|
if (module.startsWith('#') || module.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
if (module == "***bridge***")
|
||||||
|
module = "gdbbridge";
|
||||||
|
|
||||||
const FilePath codeFile = dumperPath / (module + ".py");
|
const FilePath codeFile = dumperPath / (module + ".py");
|
||||||
const expected_str<QByteArray> code = codeFile.fileContents();
|
const expected_str<QByteArray> code = codeFile.fileContents();
|
||||||
|
Reference in New Issue
Block a user