Debugger: Make DebuggerEngine::runCommand() virtual.

Allows default implementation of e.g. stack retrieval in the base
class.

Change-Id: I96460b19aa31347b2c863736b4ce2b5046eb4de6
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
hjk
2015-11-03 12:01:57 +01:00
parent 3febe4e7a2
commit 2b16b97f19
17 changed files with 252 additions and 318 deletions

View File

@@ -340,8 +340,8 @@ void CdbEngine::syncOperateByInstruction(bool operateByInstruction)
return;
QTC_ASSERT(m_accessible, return);
m_operateByInstruction = operateByInstruction;
runCommand(DebuggerCommand(m_operateByInstruction ? QByteArray("l-t") : QByteArray("l+t")));
runCommand(DebuggerCommand(m_operateByInstruction ? QByteArray("l-s") : QByteArray("l+s")));
runCommand({m_operateByInstruction ? "l-t" : "l+t", NoFlags});
runCommand({m_operateByInstruction ? "l-s" : "l+s", NoFlags});
}
void CdbEngine::syncVerboseLog(bool verboseLog)
@@ -350,7 +350,7 @@ void CdbEngine::syncVerboseLog(bool verboseLog)
return;
QTC_ASSERT(m_accessible, return);
m_verboseLog = verboseLog;
runCommand(DebuggerCommand(m_verboseLog ? QByteArray("!sym noisy") : QByteArray("!sym quiet")));
runCommand({m_verboseLog ? "!sym noisy" : "!sym quiet", NoFlags});
}
bool CdbEngine::canHandleToolTip(const DebuggerToolTipContext &context) const
@@ -474,11 +474,9 @@ void CdbEngine::consoleStubExited()
void CdbEngine::createFullBacktrace()
{
DebuggerCommand cmd("~*kp");
cmd.callback = [this](const DebuggerResponse &response) {
runCommand({"~*kp", BuiltinCommand, [this](const DebuggerResponse &response) {
Internal::openTextEditor(QLatin1String("Backtrace $"), response.data.toLatin1());
};
runCommand(cmd, BuiltinCommand);
}});
}
void CdbEngine::setupEngine()
@@ -646,7 +644,7 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
m_hasDebuggee = true;
if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
m_accessible = true;
runCommand(DebuggerCommand(".load " + extensionFileName.toLocal8Bit()));
runCommand({".load " + extensionFileName.toLocal8Bit(), NoFlags});
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk")
notifyEngineSetupOk();
}
@@ -659,27 +657,25 @@ void CdbEngine::setupInferior()
qDebug("setupInferior");
const DebuggerRunParameters &rp = runParameters();
if (!rp.commandsAfterConnect.isEmpty())
runCommand(DebuggerCommand(rp.commandsAfterConnect));
runCommand({rp.commandsAfterConnect, NoFlags});
// QmlCppEngine expects the QML engine to be connected before any breakpoints are hit
// (attemptBreakpointSynchronization() will be directly called then)
attemptBreakpointSynchronization();
if (rp.breakOnMain) {
const BreakpointParameters bp(BreakpointAtMain);
BreakpointModelId id(quint16(-1));
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, id, true));
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
runCommand(cmd, BuiltinCommand);
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, id, true), BuiltinCommand,
[this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }});
}
runCommand(DebuggerCommand("sxn 0x4000001f")); // Do not break on WowX86 exceptions.
runCommand(DebuggerCommand("sxn ibp")); // Do not break on initial breakpoints.
runCommand(DebuggerCommand(".asm source_line")); // Source line in assembly
runCommand(DebuggerCommand(m_extensionCommandPrefixBA + "setparameter maxStringLength="
runCommand({"sxn 0x4000001f", NoFlags}); // Do not break on WowX86 exceptions.
runCommand({"sxn ibp", NoFlags}); // Do not break on initial breakpoints.
runCommand({".asm source_line", NoFlags}); // Source line in assembly
runCommand({m_extensionCommandPrefixBA + "setparameter maxStringLength="
+ action(MaximalStringLength)->value().toByteArray()
+ " maxStackDepth="
+ action(MaximalStackDepth)->value().toByteArray()));
+ action(MaximalStackDepth)->value().toByteArray(), NoFlags});
DebuggerCommand cmd("pid");
cmd.callback = [this](const DebuggerResponse &response) {
runCommand({"pid", ExtensionCommand, [this](const DebuggerResponse &response) {
// Fails for core dumps.
if (response.resultClass == ResultDone)
notifyInferiorPid(response.data.data().toULongLong());
@@ -692,8 +688,7 @@ void CdbEngine::setupInferior()
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupFailed")
notifyInferiorSetupFailed();
}
};
runCommand(cmd, ExtensionCommand);
}});
}
static QByteArray msvcRunTime(const Abi::OSFlavor flavour)
@@ -736,35 +731,25 @@ void CdbEngine::runEngine()
const QStringList breakEvents = stringListSetting(CdbBreakEvents);
foreach (const QString &breakEvent, breakEvents)
runCommand(DebuggerCommand(QByteArray("sxe ") + breakEvent.toLatin1()));
runCommand({"sxe " + breakEvent.toLatin1(), NoFlags});
// Break functions: each function must be fully qualified,
// else the debugger will slow down considerably.
DebuggerCommand cmd;
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
const auto cb = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
if (boolSetting(CdbBreakOnCrtDbgReport)) {
const QByteArray module = msvcRunTime(runParameters().toolChainAbi.osFlavor());
const QByteArray debugModule = module + 'D';
const QByteArray wideFunc = QByteArray(CdbOptionsPage::crtDbgReport).append('W');
cmd.function = breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module);
runCommand(cmd, BuiltinCommand);
cmd.function = breakAtFunctionCommand(wideFunc, module);
runCommand(cmd, BuiltinCommand);
cmd.function = breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule);
runCommand(cmd, BuiltinCommand);
cmd.function = breakAtFunctionCommand(wideFunc, debugModule);
runCommand(cmd, BuiltinCommand);
runCommand({breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module), BuiltinCommand, cb});
runCommand({breakAtFunctionCommand(wideFunc, module), BuiltinCommand, cb});
runCommand({breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule), BuiltinCommand, cb});
}
if (boolSetting(BreakOnWarning)) {
cmd.function = "bm /( QtCored4!qWarning"; // 'bm': All overloads.
runCommand(cmd, BuiltinCommand);
cmd.function = "bm /( Qt5Cored!QMessageLogger::warning";
runCommand(cmd, BuiltinCommand);
runCommand({"bm /( QtCored4!qWarning", BuiltinCommand}); // 'bm': All overloads.
runCommand({"bm /( Qt5Cored!QMessageLogger::warning", BuiltinCommand});
}
if (boolSetting(BreakOnFatal)) {
cmd.function = "bm /( QtCored4!qFatal"; // 'bm': All overloads.
runCommand(cmd, BuiltinCommand);
cmd.function = "bm /( Qt5Cored!QMessageLogger::fatal";
runCommand(cmd, BuiltinCommand);
runCommand({"bm /( QtCored4!qFatal", BuiltinCommand}); // 'bm': All overloads.
runCommand({"bm /( Qt5Cored!QMessageLogger::fatal", BuiltinCommand});
}
if (runParameters().startMode == AttachCore) {
QTC_ASSERT(!m_coreStopReason.isNull(), return; );
@@ -848,10 +833,10 @@ void CdbEngine::shutdownEngine()
detachDebugger();
// Remote requires a bit more force to quit.
if (m_effectiveStartMode == AttachToRemoteServer) {
runCommand(DebuggerCommand(m_extensionCommandPrefixBA + "shutdownex"));
runCommand(DebuggerCommand("qq"));
runCommand({m_extensionCommandPrefixBA + "shutdownex", NoFlags});
runCommand({"qq", NoFlags});
} else {
runCommand(DebuggerCommand("q"));
runCommand({"q", NoFlags});
}
} else {
// Remote process. No can do, currently
@@ -885,7 +870,7 @@ void CdbEngine::processFinished()
void CdbEngine::detachDebugger()
{
runCommand(DebuggerCommand(".detach"));
runCommand({".detach", NoFlags});
}
static inline bool isWatchIName(const QByteArray &iname)
@@ -913,21 +898,21 @@ void CdbEngine::executeStep()
{
if (!m_operateByInstruction)
m_sourceStepInto = true; // See explanation at handleStackTrace().
runCommand(DebuggerCommand(QByteArray("t"))); // Step into-> t (trace)
runCommand({"t", NoFlags}); // Step into-> t (trace)
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
notifyInferiorRunRequested();
}
void CdbEngine::executeStepOut()
{
runCommand(DebuggerCommand(QByteArray("gu"))); // Step out-> gu (go up)
runCommand({"gu", NoFlags}); // Step out-> gu (go up)
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
notifyInferiorRunRequested();
}
void CdbEngine::executeNext()
{
runCommand(DebuggerCommand(QByteArray("p"))); // Step over -> p
runCommand({"p", NoFlags}); // Step over -> p
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
notifyInferiorRunRequested();
}
@@ -951,7 +936,7 @@ void CdbEngine::continueInferior()
void CdbEngine::doContinueInferior()
{
runCommand(DebuggerCommand(QByteArray("g")));
runCommand({"g", NoFlags});
}
bool CdbEngine::canInterruptInferior() const
@@ -1025,9 +1010,8 @@ void CdbEngine::executeRunToLine(const ContextData &data)
bp.lineNumber = data.lineNumber;
}
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true));
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
runCommand(cmd, BuiltinCommand);
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), BuiltinCommand,
[this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }});
continueInferior();
}
@@ -1036,10 +1020,8 @@ void CdbEngine::executeRunToFunction(const QString &functionName)
// Add one-shot breakpoint
BreakpointParameters bp(BreakpointByFunction);
bp.functionName = functionName;
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true));
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
runCommand(cmd, BuiltinCommand);
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), BuiltinCommand,
[this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }});
continueInferior();
}
@@ -1049,7 +1031,7 @@ void CdbEngine::setRegisterValue(const QByteArray &name, const QString &value)
QByteArray cmd;
ByteArrayInputStream str(cmd);
str << "r " << name << '=' << value;
runCommand(DebuggerCommand(cmd));
runCommand({cmd, NoFlags});
reloadRegisters();
}
@@ -1061,25 +1043,25 @@ void CdbEngine::executeJumpToLine(const ContextData &data)
gotoLocation(Location(data.address));
} else {
// Jump to source line: Resolve source line address and go to that location
DebuggerCommand cmd;
ByteArrayInputStream str(cmd.function);
QByteArray cmd;
ByteArrayInputStream str(cmd);
str << "? `" << QDir::toNativeSeparators(data.fileName) << ':' << data.lineNumber << '`';
cmd.callback = [this, data](const DebuggerResponse &r) { handleJumpToLineAddressResolution(r, data); };
runCommand(cmd, BuiltinCommand);
runCommand({cmd, BuiltinCommand, [this, data](const DebuggerResponse &r) {
handleJumpToLineAddressResolution(r, data); }});
}
}
void CdbEngine::jumpToAddress(quint64 address)
{
// Fake a jump to address by setting the PC register.
QByteArray registerCmd;
ByteArrayInputStream str(registerCmd);
QByteArray cmd;
ByteArrayInputStream str(cmd);
// PC-register depending on 64/32bit.
str << "r " << (runParameters().toolChainAbi.wordWidth() == 64 ? "rip" : "eip") << '=';
str.setHexPrefix(true);
str.setIntegerBase(16);
str << address;
runCommand(DebuggerCommand(registerCmd));
runCommand({cmd, NoFlags});
}
void CdbEngine::handleJumpToLineAddressResolution(const DebuggerResponse &response, const ContextData &context)
@@ -1144,7 +1126,7 @@ void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const Q
break;
}
runCommand(DebuggerCommand(cmd));
runCommand({cmd, NoFlags});
// Update all locals in case we change a union or something pointed to
// that affects other variables, too.
updateLocals();
@@ -1168,11 +1150,11 @@ void CdbEngine::handleThreads(const DebuggerResponse &response)
void CdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages languages)
{
if (languages & CppLanguage)
runCommand(DebuggerCommand(command.toLocal8Bit()));
runCommand({command.toLocal8Bit(), NoFlags});
}
// Post command to the cdb process
void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags)
void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
{
QByteArray cmd = dbgCmd.function + dbgCmd.argsToString();
if (!m_accessible) {
@@ -1184,7 +1166,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags)
QByteArray fullCmd;
ByteArrayInputStream str(fullCmd);
if (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.
@@ -1192,7 +1174,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags)
str << ".echo \"" << m_tokenPrefix << token << "<\"\n"
<< cmd << "\n.echo \"" << m_tokenPrefix << token << ">\"";
m_commandForToken.insert(token, dbgCmd);
} else if (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.
const int token = m_nextCommandToken++;
@@ -1331,10 +1313,10 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
if (partialUpdate)
str << blankSeparator << updateParameters.partialVariable;
DebuggerCommand cmd("locals");
DebuggerCommand cmd("locals", ExtensionCommand);
cmd.args = QLatin1String(arguments);
cmd.callback = [this, partialUpdate](const DebuggerResponse &r) { handleLocals(r, partialUpdate); };
runCommand(cmd, ExtensionCommand);
runCommand(cmd);
}
void CdbEngine::updateAll()
@@ -1349,9 +1331,8 @@ void CdbEngine::selectThread(ThreadId threadId)
threadsHandler()->setCurrentThread(threadId);
DebuggerCommand cmd('~' + QByteArray::number(threadId.raw()) + " s");
cmd.callback = [this](const DebuggerResponse &) { reloadFullStack(); };
runCommand(cmd, BuiltinCommand);
runCommand({'~' + QByteArray::number(threadId.raw()) + " s", BuiltinCommand,
[this](const DebuggerResponse &) { reloadFullStack(); }});
}
// Default address range for showing disassembly.
@@ -1401,7 +1382,8 @@ void CdbEngine::postDisassemblerCommand(quint64 address, quint64 endAddress,
// Parse: "00000000`77606060 cc int 3"
agent->setContents(parseCdbDisassembler(response.data.data()));
};
runCommand(cmd, BuiltinCommand);
cmd.flags = BuiltinCommand;
runCommand(cmd);
}
void CdbEngine::postResolveSymbol(const QString &module, const QString &function,
@@ -1413,14 +1395,10 @@ void CdbEngine::postResolveSymbol(const QString &module, const QString &function
const QList<quint64> addresses = m_symbolAddressCache.values(symbol);
if (addresses.isEmpty()) {
showMessage(QLatin1String("Resolving symbol: ") + symbol + QLatin1String("..."), LogMisc);
DebuggerCommand cmd(QByteArray("x ") + symbol.toLatin1());
cmd.callback = [this, symbol, agent](const DebuggerResponse &r) {
handleResolveSymbol(r, symbol, agent);
};
runCommand(cmd, BuiltinCommand);
runCommand({"x " + symbol.toLatin1(), BuiltinCommand,
[this, symbol, agent](const DebuggerResponse &r) { handleResolveSymbol(r, symbol, agent); }});
} else {
showMessage(QString::fromLatin1("Using cached addresses for %1.").
arg(symbol), LogMisc);
showMessage(QString::fromLatin1("Using cached addresses for %1.").arg(symbol), LogMisc);
handleResolveSymbolHelper(addresses, agent);
}
}
@@ -1556,7 +1534,7 @@ void CdbEngine::fetchMemory(MemoryAgent *agent, QObject *editor, quint64 addr, q
void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
{
DebuggerCommand cmd("memory");
DebuggerCommand cmd("memory", ExtensionCommand);
QByteArray args;
ByteArrayInputStream str(args);
str << cookie.address << ' ' << cookie.length;
@@ -1570,7 +1548,7 @@ void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
showMessage(response.data["msg"].toLatin1(), LogWarning);
}
};
runCommand(cmd, ExtensionCommand);
runCommand(cmd);
}
void CdbEngine::changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr, const QByteArray &data)
@@ -1580,15 +1558,13 @@ void CdbEngine::changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr, c
const MemoryChangeCookie cookie(addr, data);
doInterruptInferiorCustomSpecialStop(qVariantFromValue(cookie));
} else {
runCommand(DebuggerCommand(cdbWriteMemoryCommand(addr, data)));
runCommand({cdbWriteMemoryCommand(addr, data), NoFlags});
}
}
void CdbEngine::reloadModules()
{
DebuggerCommand cmd("modules");
cmd.callback = CB(handleModules);
runCommand(cmd, ExtensionCommand);
runCommand({"modules", ExtensionCommand, CB(handleModules)});
}
void CdbEngine::loadSymbols(const QString & /* moduleName */)
@@ -1607,9 +1583,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName)
void CdbEngine::reloadRegisters()
{
QTC_ASSERT(threadsHandler()->currentThreadIndex() >= 0, return);
DebuggerCommand cmd("registers");
cmd.callback = CB(handleRegistersExt);
runCommand(cmd, ExtensionCommand);
runCommand({"registers", ExtensionCommand, CB(handleRegistersExt)});
}
void CdbEngine::reloadSourceFiles()
@@ -1620,18 +1594,18 @@ void CdbEngine::reloadFullStack()
{
if (debug)
qDebug("%s", Q_FUNC_INFO);
DebuggerCommand cmd("stack");
DebuggerCommand cmd("stack", ExtensionCommand);
cmd.args = QStringLiteral("unlimited");
cmd.callback = CB(handleStackTrace);
runCommand(cmd, ExtensionCommand);
runCommand(cmd);
}
void CdbEngine::listBreakpoints()
{
DebuggerCommand cmd("breakpoints");
DebuggerCommand cmd("breakpoints", ExtensionCommand);
cmd.args = QStringLiteral("-v");
cmd.callback = CB(handleBreakPoints);
runCommand(cmd, ExtensionCommand);
runCommand(cmd);
}
void CdbEngine::handleModules(const DebuggerResponse &response)
@@ -1845,8 +1819,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
if (!conditionalBreakPointTriggered && !parameters.condition.isEmpty()) {
*message = msgCheckingConditionalBreakPoint(id, number, parameters.condition,
QString::number(threadId));
DebuggerCommand cmd("expression");
DebuggerCommand cmd("expression", ExtensionCommand);
QByteArray args = parameters.condition;
if (args.contains(' ') && !args.startsWith('"')) {
args.prepend('"');
@@ -1856,7 +1829,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
cmd.callback = [this, id, stopReason](const DebuggerResponse &response) {
handleExpression(response, id, stopReason);
};
runCommand(cmd, ExtensionCommand);
runCommand(cmd);
return StopReportLog;
}
@@ -2004,7 +1977,7 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
// Start sequence to get all relevant data.
if (stopFlags & StopInArtificialThread) {
showMessage(tr("Switching to main thread..."), LogMisc);
runCommand(DebuggerCommand("~0 s"));
runCommand({"~0 s", NoFlags});
forcedThreadId = ThreadId(0);
// Re-fetch stack again.
reloadFullStack();
@@ -2019,9 +1992,8 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
executeStepOut();
return;
case ParseStackWow64:
DebuggerCommand cmd("lm m wow64");
cmd.callback = [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); };
runCommand(cmd, BuiltinCommand);
runCommand({"lm m wow64", BuiltinCommand,
[this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }});
break;
}
} else {
@@ -2112,9 +2084,8 @@ void CdbEngine::handleCheckWow64(const DebuggerResponse &response, const GdbMi &
// start end module name
// 00000000`77490000 00000000`774d5000 wow64 (deferred)
if (response.data.data().contains("wow64")) {
DebuggerCommand cmd("k");
cmd.callback = [this, stack](const DebuggerResponse &r) { ensureUsing32BitStackInWow64(r, stack); };
runCommand(cmd, BuiltinCommand);
runCommand({"k", BuiltinCommand,
[this, stack](const DebuggerResponse &r) { ensureUsing32BitStackInWow64(r, stack); }});
return;
}
m_wow64State = noWow64Stack;
@@ -2134,9 +2105,7 @@ void CdbEngine::ensureUsing32BitStackInWow64(const DebuggerResponse &response, c
return;
} else if (line.startsWith("Child-SP")) {
m_wow64State = wow64Stack64Bit;
DebuggerCommand cmd("!wow64exts.sw");
cmd.callback = CB(handleSwitchWow64Stack);
runCommand(cmd, BuiltinCommand);
runCommand({"!wow64exts.sw", BuiltinCommand, CB(handleSwitchWow64Stack)});
return;
}
}
@@ -2153,9 +2122,7 @@ void CdbEngine::handleSwitchWow64Stack(const DebuggerResponse &response)
else
m_wow64State = noWow64Stack;
// reload threads and the stack after switching the mode
DebuggerCommand cmd("threads");
cmd.callback = CB(handleThreads);
runCommand(cmd, ExtensionCommand);
runCommand({"threads", ExtensionCommand, CB(handleThreads)});
}
void CdbEngine::handleSessionAccessible(unsigned long cdbExState)
@@ -2670,6 +2637,7 @@ void CdbEngine::attemptBreakpointSynchronization()
foreach (Breakpoint bp, bps) {
BreakpointParameters parameters = bp.parameters();
BreakpointModelId id = bp.id();
const auto handleBreakInsertCB = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
BreakpointResponse response;
response.fromParameters(parameters);
response.id = BreakpointResponseId(id.majorPart(), id.minorPart());
@@ -2688,16 +2656,14 @@ void CdbEngine::attemptBreakpointSynchronization()
lineCorrection.reset(new BreakpointCorrectionContext(Internal::cppCodeModelSnapshot(),
CppTools::CppModelManager::instance()->workingCopy()));
response.lineNumber = lineCorrection->fixLineNumber(parameters.fileName, parameters.lineNumber);
DebuggerCommand cmd(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false));
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
runCommand(cmd, BuiltinCommand);
QByteArray cmd = cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false);
runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
} else {
DebuggerCommand cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
runCommand(cmd, BuiltinCommand);
QByteArray cmd = cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false);
runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
}
if (!parameters.enabled)
runCommand(DebuggerCommand("bd " + QByteArray::number(breakPointIdToCdbId(id))));
runCommand({"bd " + QByteArray::number(breakPointIdToCdbId(id)), NoFlags});
bp.notifyBreakpointInsertProceeding();
bp.notifyBreakpointInsertOk();
m_pendingBreakpointMap.insert(id, response);
@@ -2716,24 +2682,23 @@ void CdbEngine::attemptBreakpointSynchronization()
qPrintable(parameters.toString()));
if (parameters.enabled != bp.response().enabled) {
// Change enabled/disabled breakpoints without triggering update.
runCommand(DebuggerCommand((parameters.enabled ? "be " : "bd ")
+ QByteArray::number(breakPointIdToCdbId(id))));
runCommand({(parameters.enabled ? "be " : "bd ")
+ QByteArray::number(breakPointIdToCdbId(id)), NoFlags});
response.pending = false;
response.enabled = parameters.enabled;
bp.setResponse(response);
} else {
// Delete and re-add, triggering update
addedChanged = true;
runCommand(DebuggerCommand(cdbClearBreakpointCommand(id)));
DebuggerCommand cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
runCommand(cmd, BuiltinCommand);
runCommand({cdbClearBreakpointCommand(id), NoFlags});
QByteArray cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
m_pendingBreakpointMap.insert(id, response);
}
bp.notifyBreakpointChangeOk();
break;
case BreakpointRemoveRequested:
runCommand(DebuggerCommand(cdbClearBreakpointCommand(id)));
runCommand({cdbClearBreakpointCommand(id), NoFlags});
bp.notifyBreakpointRemoveProceeding();
bp.notifyBreakpointRemoveOk();
m_pendingBreakpointMap.remove(id);
@@ -2745,7 +2710,7 @@ void CdbEngine::attemptBreakpointSynchronization()
foreach (BreakpointModelId id, m_insertSubBreakpointMap.keys()) {
addedChanged = true;
const BreakpointResponse &response = m_insertSubBreakpointMap.value(id);
runCommand(DebuggerCommand(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false)));
runCommand({cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false), NoFlags});
m_insertSubBreakpointMap.remove(id);
m_pendingSubBreakpointMap.insert(id, response);
}
@@ -2873,9 +2838,7 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
void CdbEngine::loadAdditionalQmlStack()
{
DebuggerCommand cmd("qmlstack");
cmd.callback = CB(handleAdditionalQmlStack);
runCommand(cmd, ExtensionCommand);
runCommand({"qmlstack", ExtensionCommand, CB(handleAdditionalQmlStack)});
}
void CdbEngine::handleAdditionalQmlStack(const DebuggerResponse &response)
@@ -2920,9 +2883,8 @@ void CdbEngine::handleStackTrace(const DebuggerResponse &response)
GdbMi stack = response.data;
if (response.resultClass == ResultDone) {
if (parseStackTrace(stack, false) == ParseStackWow64) {
DebuggerCommand cmd("lm m wow64");
cmd.callback = [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); };
runCommand(cmd, BuiltinCommand);
runCommand({"lm m wow64", BuiltinCommand,
[this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }});
}
} else {
showMessage(stack["msg"].toLatin1(), LogError);
@@ -3096,17 +3058,16 @@ void CdbEngine::watchPoint(const QPoint &p)
void CdbEngine::postWidgetAtCommand()
{
DebuggerCommand cmd("widgetat");
DebuggerCommand cmd("widgetat", ExtensionCommand);
cmd.args = QString::fromLatin1("%1 %2").arg(m_watchPointX, m_watchPointY);
cmd.callback = CB(handleWidgetAt);
runCommand(cmd, ExtensionCommand);
runCommand(cmd);
}
void CdbEngine::handleCustomSpecialStop(const QVariant &v)
{
if (v.canConvert<MemoryChangeCookie>()) {
const MemoryChangeCookie changeData = qvariant_cast<MemoryChangeCookie>(v);
runCommand(DebuggerCommand(cdbWriteMemoryCommand(changeData.address, changeData.data)));
runCommand({cdbWriteMemoryCommand(changeData.address, changeData.data), NoFlags});
return;
}
if (v.canConvert<MemoryViewCookie>()) {

View File

@@ -127,7 +127,7 @@ private slots:
void readyReadStandardError();
void processError();
void processFinished();
void runCommand(const DebuggerCommand &cmd, int flags = 0);
void runCommand(const DebuggerCommand &cmd) override;
void operateByInstructionTriggered(bool);
void verboseLogTriggered(bool);
@@ -164,7 +164,7 @@ private:
ParseStackWow64 = 3 // Hit on a frame with 32bit emulation, switch debugger to 32 bit mode
};
enum CommandFlags {
NoCallBack = 0,
NoFlags = 0,
BuiltinCommand,
ExtensionCommand,
};

View File

@@ -1479,6 +1479,12 @@ void DebuggerEngine::watchPoint(const QPoint &)
{
}
void DebuggerEngine::runCommand(const DebuggerCommand &)
{
// Overridden in the engines that use the interface.
QTC_CHECK(false);
}
void DebuggerEngine::fetchDisassembler(DisassemblerAgent *)
{
}

View File

@@ -33,6 +33,7 @@
#include "debugger_global.h"
#include "debuggerconstants.h"
#include "debuggerprotocol.h"
#include "debuggerstartparameters.h"
#include <projectexplorer/devicesupport/idevice.h>
@@ -61,7 +62,6 @@ namespace Internal {
class DebuggerEnginePrivate;
class DebuggerPluginPrivate;
class DisassemblerAgent;
class GdbMi;
class MemoryAgent;
class WatchData;
class WatchItem;
@@ -217,6 +217,7 @@ public:
MemoryView = 0x4 //!< Open a separate view (using the pos-parameter).
};
virtual void runCommand(const DebuggerCommand &cmd);
virtual void openMemoryView(const MemoryViewSetupData &data);
virtual void fetchMemory(Internal::MemoryAgent *, QObject *,
quint64 addr, quint64 length);

View File

@@ -52,9 +52,10 @@ public:
typedef std::function<void(const DebuggerResponse &)> Callback;
DebuggerCommand() {}
DebuggerCommand(const char *f, int fl = 0) : function(f), flags(fl) {}
DebuggerCommand(const QByteArray &f, int fl = 0) : function(f), flags(fl) {}
DebuggerCommand(const char *f, const QJsonValue &a, int fl = 0) : function(f), args(a), flags(fl) {}
DebuggerCommand(const QByteArray &f) : function(f), flags(0) {}
DebuggerCommand(const QByteArray &f, const QJsonValue &a) : function(f), args(a), flags(0) {}
DebuggerCommand(const QByteArray &f, int fl) : function(f), flags(fl) {}
DebuggerCommand(const QByteArray &f, int fl, const Callback &cb) : function(f), callback(cb), flags(fl) {}
void arg(const char *value);
void arg(const char *name, int value);

View File

@@ -75,9 +75,8 @@ void GdbAttachEngine::runEngine()
{
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
const qint64 pid = runParameters().attachPID;
DebuggerCommand cmd("attach " + QByteArray::number(pid));
cmd.callback = [this](const DebuggerResponse &r) { handleAttach(r); };
runCommand(cmd);
runCommand({"attach " + QByteArray::number(pid), NoFlags,
[this](const DebuggerResponse &r) { handleAttach(r); }});
showStatusMessage(tr("Attached to process %1.").arg(inferiorPid()));
}

View File

@@ -212,9 +212,8 @@ void GdbCoreEngine::setupInferior()
// Do that first, otherwise no symbols are loaded.
QFileInfo fi(m_executable);
QByteArray path = fi.absoluteFilePath().toLocal8Bit();
DebuggerCommand cmd("-file-exec-and-symbols \"" + path + '"');
cmd.callback = CB(handleFileExecAndSymbols);
runCommand(cmd);
runCommand({"-file-exec-and-symbols \"" + path + '"', NoFlags,
CB(handleFileExecAndSymbols)});
}
void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
@@ -237,9 +236,8 @@ void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
void GdbCoreEngine::runEngine()
{
CHECK_STATE(EngineRunRequested);
DebuggerCommand cmd("target core " + coreFileName().toLocal8Bit());
cmd.callback = CB(handleTargetCore);
runCommand(cmd);
runCommand({"target core " + coreFileName().toLocal8Bit(), NoFlags,
CB(handleTargetCore)});
}
void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
@@ -252,7 +250,7 @@ void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
// symbols yet. Load them in order of importance.
reloadStack();
reloadModulesInternal();
runCommand("p 5", CB(handleRoundTrip));
runCommand({"p 5", NoFlags, CB(handleRoundTrip)});
return;
}
showStatusMessage(tr("Attach to core \"%1\" failed:").arg(runParameters().coreFile)

View File

@@ -851,7 +851,7 @@ void GdbEngine::interruptInferior()
return;
if (usesExecInterrupt()) {
runCommand("-exec-interrupt");
runCommand({"-exec-interrupt", NoFlags});
} else {
showStatusMessage(tr("Stop requested..."), 5000);
showMessage(_("TRYING TO INTERRUPT INFERIOR"));
@@ -898,20 +898,6 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
notifyInferiorPid(pid);
}
void GdbEngine::runCommand(const QByteArray &command, const DebuggerCommand::Callback &callback, int flags)
{
DebuggerCommand cmd(command);
cmd.callback = callback;
cmd.flags = flags;
runCommand(cmd);
}
void GdbEngine::runCommand(const QByteArray &command, int flags)
{
DebuggerCommand cmd(command, flags);
runCommand(cmd);
}
void GdbEngine::runCommand(const DebuggerCommand &command)
{
const int token = ++currentToken();
@@ -1227,7 +1213,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages
if (!(languages & CppLanguage))
return;
QTC_CHECK(acceptsDebuggerCommands());
runCommand(command.toLatin1());
runCommand({command.toLatin1(), NoFlags});
}
// This is triggered when switching snapshots.
@@ -1240,7 +1226,7 @@ void GdbEngine::updateAll()
cmd.callback = [this](const DebuggerResponse &r) { handleStackListFrames(r, false); };
runCommand(cmd);
stackHandler()->setCurrentIndex(0);
runCommand("-thread-info", CB(handleThreadInfo));
runCommand({"-thread-info", NoFlags, CB(handleThreadInfo)});
reloadRegisters();
updateLocals();
}
@@ -1386,9 +1372,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
bool gotoHandleStop1 = true;
if (!m_fullStartDone) {
m_fullStartDone = true;
DebuggerCommand cmd("sharedlibrary .*");
cmd.callback = [this, data](const DebuggerResponse &) { handleStop1(data); };
runCommand(cmd);
runCommand({"sharedlibrary .*", NoFlags,
[this, data](const DebuggerResponse &) { handleStop1(data); }});
gotoHandleStop1 = false;
}
@@ -1544,9 +1529,9 @@ void GdbEngine::handleStop1(const GdbMi &data)
if (!m_systemDumpersLoaded) {
m_systemDumpersLoaded = true;
if (m_gdbVersion >= 70400 && boolSetting(LoadGdbDumpers))
runCommand("importPlainDumpers on");
runCommand({"importPlainDumpers on", NoFlags});
else
runCommand("importPlainDumpers off");
runCommand({"importPlainDumpers off", NoFlags});
}
handleStop2(data);
@@ -1701,12 +1686,12 @@ void GdbEngine::handleShowVersion(const DebuggerResponse &response)
.arg(gdbBuildVersion).arg(_(isMacGdb ? " (APPLE)" : "")));
if (usesExecInterrupt())
runCommand("set target-async on", ConsoleCommand);
runCommand({"set target-async on", ConsoleCommand});
else
runCommand("set target-async off", ConsoleCommand);
runCommand({"set target-async off", ConsoleCommand});
if (runParameters().multiProcess)
runCommand("set detach-on-fork off", ConsoleCommand);
runCommand({"set detach-on-fork off", ConsoleCommand});
//runCommand("set build-id-verbose 2", ConsoleCommand);
}
@@ -1892,8 +1877,8 @@ void GdbEngine::notifyAdapterShutdownOk()
switch (m_gdbProc.state()) {
case QProcess::Running: {
if (runParameters().closeMode == KillAndExitMonitorAtClose)
runCommand("monitor exit");
runCommand("exitGdb", CB(handleGdbExit), ExitRequest|PythonCommand);
runCommand({"monitor exit", NoFlags});
runCommand({"exitGdb", ExitRequest|PythonCommand, CB(handleGdbExit)});
break;
}
case QProcess::NotRunning:
@@ -2093,20 +2078,19 @@ void GdbEngine::executeStepI()
void GdbEngine::executeStepOut()
{
CHECK_STATE(InferiorStopOk);
runCommand("-stack-select-frame 0", Discardable);
runCommand({"-stack-select-frame 0", Discardable});
setTokenBarrier();
notifyInferiorRunRequested();
showStatusMessage(tr("Finish function requested..."), 5000);
if (isNativeMixedActiveFrame()) {
DebuggerCommand cmd("executeStepOut", RunRequest|PythonCommand);
runCommand(cmd);
runCommand({"executeStepOut", RunRequest|PythonCommand});
} else {
runCommand("-exec-finish", CB(handleExecuteContinue), RunRequest);
runCommand({"-exec-finish", RunRequest, CB(handleExecuteContinue)});
// -exec-finish in 'main' results (correctly) in
// 40^error,msg="\"finish\" not meaningful in the outermost frame."
// However, this message does not seem to get flushed before
// anything else happen - i.e. "never". Force some extra output.
runCommand("print 32");
runCommand({"print 32"});
}
}
@@ -2186,11 +2170,9 @@ void GdbEngine::executeRunToLine(const ContextData &data)
else
loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':'
+ QByteArray::number(data.lineNumber);
runCommand("tbreak " + loc);
runCommand({"tbreak " + loc, NoFlags});
DebuggerCommand cmd("continue", RunRequest);
cmd.callback = CB(handleExecuteRunToLine);
runCommand(cmd);
runCommand({"continue", RunRequest, CB(handleExecuteRunToLine)});
#else
// Seems to jump to unpredicatable places. Observed in the manual
// tests in the Foo::Foo() constructor with both gdb 6.8 and 7.1.
@@ -2204,7 +2186,7 @@ void GdbEngine::executeRunToFunction(const QString &functionName)
{
CHECK_STATE(InferiorStopOk);
setTokenBarrier();
runCommand("-break-insert -t " + functionName.toLatin1());
runCommand({"-break-insert -t " + functionName.toLatin1(), NoFlags});
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
continueInferiorInternal();
}
@@ -2218,12 +2200,10 @@ void GdbEngine::executeJumpToLine(const ContextData &data)
else
loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':'
+ QByteArray::number(data.lineNumber);
runCommand("tbreak " + loc);
runCommand({"tbreak " + loc, NoFlags});
notifyInferiorRunRequested();
DebuggerCommand cmd("jump" + loc, RunRequest);
cmd.callback = CB(handleExecuteJumpToLine);
runCommand(cmd);
runCommand({"jump" + loc, RunRequest, CB(handleExecuteJumpToLine)});
// will produce something like
// &"jump \"/home/apoenitz/dev/work/test1/test1.cpp\":242"
// ~"Continuing at 0x4058f3."
@@ -2238,7 +2218,7 @@ void GdbEngine::executeReturn()
setTokenBarrier();
notifyInferiorRunRequested();
showStatusMessage(tr("Immediate return from function requested..."), 5000);
runCommand("-exec-finish", CB(handleExecuteReturn), RunRequest);
runCommand({"-exec-finish", RunRequest, CB(handleExecuteReturn)});
}
void GdbEngine::handleExecuteReturn(const DebuggerResponse &response)
@@ -2891,7 +2871,7 @@ void GdbEngine::removeBreakpoint(Breakpoint bp)
void GdbEngine::loadSymbols(const QString &modulePath)
{
// FIXME: gdb does not understand quoted names here (tested with 6.8)
runCommand("sharedlibrary " + dotEscape(modulePath.toLocal8Bit()));
runCommand({"sharedlibrary " + dotEscape(modulePath.toLocal8Bit()), NoFlags});
reloadModulesInternal();
reloadStack();
updateLocals();
@@ -2899,7 +2879,7 @@ void GdbEngine::loadSymbols(const QString &modulePath)
void GdbEngine::loadAllSymbols()
{
runCommand("sharedlibrary .*");
runCommand({"sharedlibrary .*", NoFlags});
reloadModulesInternal();
reloadStack();
updateLocals();
@@ -2915,8 +2895,8 @@ void GdbEngine::loadSymbolsForStack()
foreach (const Module &module, modules) {
if (module.startAddress <= frame.address
&& frame.address < module.endAddress) {
runCommand("sharedlibrary "
+ dotEscape(module.modulePath.toLocal8Bit()));
runCommand({"sharedlibrary " + dotEscape(module.modulePath.toLocal8Bit()),
NoFlags});
needUpdate = true;
}
}
@@ -3059,7 +3039,7 @@ void GdbEngine::reloadModules()
void GdbEngine::reloadModulesInternal()
{
runCommand("info shared", CB(handleModulesList), NeedsStop);
runCommand({"info shared", NeedsStop, CB(handleModulesList)});
}
static QString nameFromPath(const QString &path)
@@ -3246,10 +3226,9 @@ void GdbEngine::loadAdditionalQmlStack()
return;
}
// Call the debug function of QML with the context address to obtain the QML stack trace.
DebuggerCommand cmd = "-data-evaluate-expression \"qt_v4StackTrace((QV4::ExecutionContext *)0x"
+ QByteArray::number(contextAddress, 16) + ")\"";
cmd.callback = CB(handleQmlStackTrace);
runCommand(cmd);
runCommand({"-data-evaluate-expression \"qt_v4StackTrace((QV4::ExecutionContext *)0x"
+ QByteArray::number(contextAddress, 16) + ")\"",
NoFlags, CB(handleQmlStackTrace)});
};
runCommand(cmd);
}
@@ -3345,8 +3324,7 @@ void GdbEngine::activateFrame(int frameIndex)
// after a response to this -stack-select-frame here.
//if (!m_currentThread.isEmpty())
// cmd += " --thread " + m_currentThread;
DebuggerCommand cmd("-stack-select-frame " + QByteArray::number(frameIndex), Discardable);
runCommand(cmd);
runCommand({"-stack-select-frame " + QByteArray::number(frameIndex), Discardable});
}
updateLocals();
@@ -3366,14 +3344,14 @@ void GdbEngine::handleThreadInfo(const DebuggerResponse &response)
}
updateViews(); // Adjust Threads combobox.
if (boolSetting(ShowThreadNames)) {
runCommand("threadnames " + action(MaximalStackDepth)->value().toByteArray(),
CB(handleThreadNames), Discardable);
runCommand({"threadnames " + action(MaximalStackDepth)->value().toByteArray(),
Discardable, CB(handleThreadNames)});
}
reloadStack(); // Will trigger register reload.
} else {
// Fall back for older versions: Try to get at least a list
// of running threads.
runCommand("-thread-list-ids", CB(handleThreadListIds), Discardable);
runCommand({"-thread-list-ids", Discardable, CB(handleThreadListIds)});
}
}
@@ -3474,15 +3452,17 @@ void GdbEngine::reloadRegisters()
if (!m_registerNamesListed) {
// The MI version does not give register size.
// runCommand("-data-list-register-names", CB(handleRegisterListNames));
runCommand("maintenance print raw-registers", CB(handleRegisterListing));
runCommand({"maintenance print raw-registers", NoFlags,
CB(handleRegisterListing)});
m_registerNamesListed = true;
}
// Can cause i386-linux-nat.c:571: internal-error: Got request
// for bad register number 41.\nA problem internal to GDB has been detected.
runCommand("-data-list-register-values r",
CB(handleRegisterListValues), Discardable);
runCommand({"-data-list-register-values r", Discardable,
CB(handleRegisterListValues)});
} else {
runCommand("maintenance print cooked-registers", CB(handleMaintPrintRegisters));
runCommand({"maintenance print cooked-registers", NoFlags,
CB(handleMaintPrintRegisters)});
}
}
@@ -3547,7 +3527,7 @@ void GdbEngine::setRegisterValue(const QByteArray &name, const QString &value)
QByteArray fullName = name;
if (name.startsWith("xmm"))
fullName += ".uint128";
runCommand("set $" + fullName + "=" + value.toLatin1());
runCommand({"set $" + fullName + "=" + value.toLatin1(), NoFlags});
reloadRegisters();
}
@@ -3684,9 +3664,8 @@ void GdbEngine::watchPoint(const QPoint &pnt)
{
QByteArray x = QByteArray::number(pnt.x());
QByteArray y = QByteArray::number(pnt.y());
runCommand("print " + qtNamespace() + "QApplication::widgetAt("
+ x + ',' + y + ')',
CB(handleWatchPoint), NeedsStop);
runCommand({"print " + qtNamespace() + "QApplication::widgetAt(" + x + ',' + y + ')',
NeedsStop, CB(handleWatchPoint)});
}
void GdbEngine::handleWatchPoint(const DebuggerResponse &response)
@@ -3822,9 +3801,9 @@ public:
void GdbEngine::fetchDisassembler(DisassemblerAgent *agent)
{
if (boolSetting(IntelFlavor))
runCommand("set disassembly-flavor intel");
runCommand({"set disassembly-flavor intel"});
else
runCommand("set disassembly-flavor att");
runCommand({"set disassembly-flavor att"});
fetchDisassemblerByCliPointMixed(agent);
}
@@ -4025,9 +4004,9 @@ void GdbEngine::startGdb(const QStringList &args)
}
showMessage(_("GDB STARTED, INITIALIZING IT"));
runCommand("show version", CB(handleShowVersion));
runCommand({"show version", NoFlags, CB(handleShowVersion)});
//runCommand("-list-features", CB(handleListFeatures));
runCommand("show debug-file-directory",CB(handleDebugInfoLocation));
runCommand({"show debug-file-directory", NoFlags, CB(handleDebugInfoLocation)});
//runCommand("-enable-timings");
//rurun print static-members off"); // Seemingly doesn't work.
@@ -4037,7 +4016,7 @@ void GdbEngine::startGdb(const QStringList &args)
//runCommand("define hookpost-stop\nprint 5\nend");
//runCommand("define hook-call\nprint 6\nend");
//runCommand("define hookpost-call\nprint 7\nend");
runCommand("set print object on");
runCommand({"set print object on"});
//runCommand("set step-mode on"); // we can't work with that yes
//runCommand("set exec-done-display on");
//runCommand("set print pretty on");
@@ -4048,8 +4027,8 @@ void GdbEngine::startGdb(const QStringList &args)
// (Mac OS 10.6), but does so for gdb-966 (10.5):
//runCommand("set print inferior-events 1");
runCommand("set breakpoint pending on");
runCommand("set print elements 10000");
runCommand({"set breakpoint pending on"});
runCommand({"set print elements 10000"});
// Produces a few messages during symtab loading
//runCommand("set verbose on");
@@ -4077,11 +4056,11 @@ void GdbEngine::startGdb(const QStringList &args)
// We need "print" as otherwise we will get no feedback whatsoever
// when Custom DebuggingHelper crash (which happen regularly when accessing
// uninitialized variables).
runCommand("handle SIGSEGV nopass stop print");
runCommand({"handle SIGSEGV nopass stop print"});
runCommand("set unwindonsignal on");
runCommand("set width 0");
runCommand("set height 0");
runCommand({"set unwindonsignal on"});
runCommand({"set width 0"});
runCommand({"set height 0"});
// FIXME: Provide proper Gui settings for these:
//runCommand("set breakpoint always-inserted on", ConsoleCommand);
@@ -4111,39 +4090,39 @@ void GdbEngine::startGdb(const QStringList &args)
for (auto it = completeSourcePathMap.constBegin(), cend = completeSourcePathMap.constEnd();
it != cend;
++it) {
runCommand("set substitute-path " + it.key().toLocal8Bit()
+ " " + it.value().toLocal8Bit());
runCommand({"set substitute-path " + it.key().toLocal8Bit()
+ " " + it.value().toLocal8Bit(), NoFlags});
}
// Spaces just will not work.
foreach (const QString &src, rp.debugSourceLocation) {
if (QDir(src).exists())
runCommand("directory " + src.toLocal8Bit());
runCommand({"directory " + src.toLocal8Bit(), NoFlags});
else
showMessage(_("# directory does not exist: ") + src, LogInput);
}
const QByteArray sysroot = rp.sysRoot.toLocal8Bit();
if (!sysroot.isEmpty()) {
runCommand("set sysroot " + sysroot);
runCommand({"set sysroot " + sysroot, NoFlags});
// sysroot is not enough to correctly locate the sources, so explicitly
// relocate the most likely place for the debug source
runCommand("set substitute-path /usr/src " + sysroot + "/usr/src");
runCommand({"set substitute-path /usr/src " + sysroot + "/usr/src", NoFlags});
}
//QByteArray ba = QFileInfo(sp.dumperLibrary).path().toLocal8Bit();
//if (!ba.isEmpty())
// runCommand("set solib-search-path " + ba);
if (attemptQuickStart()) {
runCommand("set auto-solib-add off", ConsoleCommand);
runCommand({"set auto-solib-add off", ConsoleCommand});
} else {
m_fullStartDone = true;
runCommand("set auto-solib-add on", ConsoleCommand);
runCommand({"set auto-solib-add on", ConsoleCommand});
}
if (boolSetting(MultiInferior)) {
//runCommand("set follow-exec-mode new");
runCommand("set detach-on-fork off");
runCommand({"set detach-on-fork off"});
}
// Finally, set up Python.
@@ -4154,15 +4133,15 @@ void GdbEngine::startGdb(const QStringList &args)
ICore::resourcePath().toLocal8Bit() + "/debugger/";
if (terminal()->isUsable())
runCommand("set inferior-tty " + terminal()->slaveDevice());
runCommand({"set inferior-tty " + terminal()->slaveDevice(), NoFlags});
const QFileInfo gdbBinaryFile(m_gdb);
const QByteArray uninstalledData = gdbBinaryFile.absolutePath().toLocal8Bit()
+ "/data-directory/python";
runCommand("python sys.path.insert(1, '" + dumperSourcePath + "')");
runCommand("python sys.path.append('" + uninstalledData + "')");
runCommand("python from gdbbridge import *");
runCommand({"python sys.path.insert(1, '" + dumperSourcePath + "')", NoFlags});
runCommand({"python sys.path.append('" + uninstalledData + "')", NoFlags});
runCommand({"python from gdbbridge import *", NoFlags});
const QString path = stringSetting(ExtraDumperFile);
if (!path.isEmpty() && QFileInfo(path).isReadable()) {
@@ -4173,11 +4152,9 @@ void GdbEngine::startGdb(const QStringList &args)
const QString commands = stringSetting(ExtraDumperCommands);
if (!commands.isEmpty())
runCommand(commands.toLocal8Bit());
runCommand({commands.toLocal8Bit(), NoFlags});
DebuggerCommand cmd("loadDumpers", PythonCommand);
cmd.callback = CB(handlePythonSetup);
runCommand(cmd);
runCommand({"loadDumpers", PythonCommand, CB(handlePythonSetup)});
}
void GdbEngine::handleGdbStartFailed()
@@ -4189,7 +4166,7 @@ void GdbEngine::loadInitScript()
const QString script = runParameters().overrideStartScript;
if (!script.isEmpty()) {
if (QFileInfo(script).isReadable()) {
runCommand("source " + script.toLocal8Bit());
runCommand({"source " + script.toLocal8Bit(), NoFlags});
} else {
AsynchronousMessageBox::warning(
tr("Cannot find debugger initialization script"),
@@ -4201,7 +4178,7 @@ void GdbEngine::loadInitScript()
} else {
const QString commands = stringSetting(GdbStartupCommands);
if (!commands.isEmpty())
runCommand(commands.toLocal8Bit());
runCommand({commands.toLocal8Bit(), NoFlags});
}
}
@@ -4211,15 +4188,16 @@ void GdbEngine::setEnvironmentVariables()
Environment runEnv = runParameters().environment;
foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
if (item.unset)
runCommand("unset environment " + item.name.toUtf8());
runCommand({"unset environment " + item.name.toUtf8(), NoFlags});
else
runCommand("-gdb-set environment " + item.name.toUtf8() + '=' + item.value.toUtf8());
runCommand({"-gdb-set environment " + item.name.toUtf8() + '='
+ item.value.toUtf8(), NoFlags});
}
}
void GdbEngine::reloadDebuggingHelpers()
{
runCommand("reloadDumpers", PythonCommand);
runCommand({"reloadDumpers", PythonCommand});
reloadLocals();
}
@@ -4274,7 +4252,7 @@ void GdbEngine::resetInferior()
foreach (QByteArray command, commands.split('\n')) {
command = command.trimmed();
if (!command.isEmpty())
runCommand(command, int(ConsoleCommand | NeedsStop));
runCommand({command, ConsoleCommand | NeedsStop});
}
}
m_rerunPending = true;
@@ -4313,16 +4291,15 @@ void GdbEngine::handleInferiorPrepared()
if (!rp.commandsAfterConnect.isEmpty()) {
QByteArray commands = globalMacroExpander()->expand(rp.commandsAfterConnect);
foreach (QByteArray command, commands.split('\n')) {
runCommand(command);
}
foreach (QByteArray command, commands.split('\n'))
runCommand({command, NoFlags});
}
//runCommand("set follow-exec-mode new");
if (rp.breakOnMain) {
QByteArray cmd = "tbreak ";
cmd += rp.toolChainAbi.os() == Abi::WindowsOS ? "qMain" : "main";
runCommand(cmd);
runCommand({cmd, NoFlags});
}
// Initial attempt to set breakpoints.
@@ -4348,15 +4325,15 @@ void GdbEngine::finishInferiorSetup()
notifyInferiorSetupOk(); // No breakpoints in core files.
} else {
if (boolSetting(BreakOnAbort))
runCommand("-break-insert -f abort");
runCommand({"-break-insert -f abort"});
if (boolSetting(BreakOnWarning)) {
runCommand("-break-insert -f '" + qtNamespace() + "qWarning'");
runCommand("-break-insert -f '" + qtNamespace() + "QMessageLogger::warning'");
runCommand({"-break-insert -f '" + qtNamespace() + "qWarning'", NoFlags});
runCommand({"-break-insert -f '" + qtNamespace() + "QMessageLogger::warning'", NoFlags});
}
if (boolSetting(BreakOnFatal)) {
auto cb = [this](const DebuggerResponse &r) { handleBreakOnQFatal(r, false); };
runCommand("-break-insert -f '" + qtNamespace() + "qFatal'", cb);
runCommand("-break-insert -f '" + qtNamespace() + "QMessageLogger::fatal'", cb);
runCommand({"-break-insert -f '" + qtNamespace() + "qFatal'", NoFlags, cb});
runCommand({"-break-insert -f '" + qtNamespace() + "QMessageLogger::fatal'", NoFlags, cb});
} else {
notifyInferiorSetupOk();
}
@@ -4369,13 +4346,10 @@ void GdbEngine::handleDebugInfoLocation(const DebuggerResponse &response)
const QByteArray debugInfoLocation = runParameters().debugInfoLocation.toLocal8Bit();
if (QFile::exists(QString::fromLocal8Bit(debugInfoLocation))) {
const QByteArray curDebugInfoLocations = response.consoleStreamOutput.split('"').value(1);
if (curDebugInfoLocations.isEmpty()) {
runCommand("set debug-file-directory " + debugInfoLocation);
} else {
runCommand("set debug-file-directory " + debugInfoLocation
+ HostOsInfo::pathListSeparator().toLatin1()
+ curDebugInfoLocations);
}
QByteArray cmd = "set debug-file-directory " + debugInfoLocation;
if (!curDebugInfoLocations.isEmpty())
cmd += HostOsInfo::pathListSeparator().toLatin1() + curDebugInfoLocations;
runCommand({cmd, NoFlags});
}
}
}
@@ -4388,7 +4362,7 @@ void GdbEngine::handleBreakOnQFatal(const DebuggerResponse &response, bool conti
BreakpointResponseId rid(number.data());
if (rid.isValid()) {
m_qFatalBreakpointResponseId = rid;
runCommand("-break-commands " + number.data() + " return");
runCommand({"-break-commands " + number.data() + " return", NoFlags});
}
}

View File

@@ -172,12 +172,7 @@ private: ////////// Gdb Command Management //////////
};
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
protected:
void runCommand(const DebuggerCommand &command);
void runCommand(const QByteArray &command, int flags);
void runCommand(const QByteArray &command,
const DebuggerCommand::Callback &callback,
int flags = NoFlags);
void runCommand(const DebuggerCommand &command) override;
private:
Q_SLOT void commandTimeout();

View File

@@ -60,10 +60,10 @@ void GdbPlainEngine::setupInferior()
setEnvironmentVariables();
if (!runParameters().processArgs.isEmpty()) {
QString args = runParameters().processArgs;
runCommand("-exec-arguments " + toLocalEncoding(args));
runCommand({"-exec-arguments " + toLocalEncoding(args), NoFlags});
}
runCommand("-file-exec-and-symbols \"" + execFilePath() + '"',
CB(handleFileExecAndSymbols));
runCommand({"-file-exec-and-symbols \"" + execFilePath() + '"', NoFlags,
CB(handleFileExecAndSymbols)});
}
void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
@@ -84,9 +84,9 @@ void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
void GdbPlainEngine::runEngine()
{
if (runParameters().useContinueInsteadOfRun)
runCommand("-exec-continue", CB(handleExecuteContinue), RunRequest);
runCommand({"-exec-continue", RunRequest, CB(handleExecuteContinue)});
else
runCommand("-exec-run", CB(handleExecRun), RunRequest);
runCommand({"-exec-run", RunRequest, CB(handleExecRun)});
}
void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
{
@@ -98,7 +98,7 @@ void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
showMessage(msgInferiorSetupOk(), StatusBar);
// FIXME: That's the wrong place for it.
if (boolSetting(EnableReverseDebugging))
runCommand("target record");
runCommand({"target record", NoFlags});
} else {
QString msg = fromLocalEncoding(response.data["msg"].data());
//QTC_CHECK(status() == InferiorRunOk);

View File

@@ -183,10 +183,10 @@ void GdbRemoteServerEngine::setupInferior()
// postCommand("set architecture " + remoteArch);
const QString solibSearchPath = rp.solibSearchPath.join(HostOsInfo::pathListSeparator());
if (!solibSearchPath.isEmpty())
runCommand("set solib-search-path " + solibSearchPath.toLocal8Bit());
runCommand({"set solib-search-path " + solibSearchPath.toLocal8Bit(), NoFlags});
if (!args.isEmpty())
runCommand("-exec-arguments " + args.toLocal8Bit());
runCommand({"-exec-arguments " + args.toLocal8Bit(), NoFlags});
setEnvironmentVariables();
@@ -210,7 +210,7 @@ void GdbRemoteServerEngine::setupInferior()
// mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)'
// failed.\nA problem internal to GDB has been detected,[...]
if (boolSetting(TargetAsync))
runCommand("set target-async on", CB(handleSetTargetAsync));
runCommand({"set target-async on", NoFlags, CB(handleSetTargetAsync)});
if (executableFileName.isEmpty()) {
showMessage(tr("No symbol file given."), StatusBar);
@@ -219,8 +219,8 @@ void GdbRemoteServerEngine::setupInferior()
}
if (!executableFileName.isEmpty()) {
runCommand("-file-exec-and-symbols \"" + executableFileName.toLocal8Bit() + '"',
CB(handleFileExecAndSymbols));
runCommand({"-file-exec-and-symbols \"" + executableFileName.toLocal8Bit() + '"',
NoFlags, CB(handleFileExecAndSymbols)});
}
}
@@ -270,11 +270,11 @@ void GdbRemoteServerEngine::callTargetRemote()
}
if (m_isQnxGdb)
runCommand("target qnx " + channel, CB(handleTargetQnx));
runCommand({"target qnx " + channel, NoFlags, CB(handleTargetQnx)});
else if (runParameters().multiProcess)
runCommand("target extended-remote " + channel, CB(handleTargetExtendedRemote));
runCommand({"target extended-remote " + channel, NoFlags, CB(handleTargetExtendedRemote)});
else
runCommand("target remote " + channel, CB(handleTargetRemote));
runCommand({"target remote " + channel, NoFlags, CB(handleTargetRemote)});
}
void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
@@ -287,7 +287,7 @@ void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
QString postAttachCommands = stringSetting(GdbPostAttachCommands);
if (!postAttachCommands.isEmpty()) {
foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n')))
runCommand(cmd.toLatin1());
runCommand({cmd.toLatin1(), NoFlags});
}
handleInferiorPrepared();
} else {
@@ -307,15 +307,15 @@ void GdbRemoteServerEngine::handleTargetExtendedRemote(const DebuggerResponse &r
QString postAttachCommands = stringSetting(GdbPostAttachCommands);
if (!postAttachCommands.isEmpty()) {
foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n')))
runCommand(cmd.toLatin1());
runCommand({cmd.toLatin1(), NoFlags});
}
if (runParameters().attachPID > 0) { // attach to pid if valid
// gdb server will stop the remote application itself.
runCommand("attach " + QByteArray::number(runParameters().attachPID),
CB(handleTargetExtendedAttach));
runCommand({"attach " + QByteArray::number(runParameters().attachPID),
NoFlags, CB(handleTargetExtendedAttach)});
} else {
runCommand("-gdb-set remote exec-file " + runParameters().remoteExecutable.toLatin1(),
CB(handleTargetExtendedAttach));
runCommand({"-gdb-set remote exec-file " + runParameters().remoteExecutable.toLatin1(),
NoFlags, CB(handleTargetExtendedAttach)});
}
} else {
QString msg = msgConnectRemoteServerFailed(
@@ -349,9 +349,9 @@ void GdbRemoteServerEngine::handleTargetQnx(const DebuggerResponse &response)
const qint64 pid = isMasterEngine() ? runParameters().attachPID : masterEngine()->runParameters().attachPID;
const QString remoteExecutable = isMasterEngine() ? runParameters().remoteExecutable : masterEngine()->runParameters().remoteExecutable;
if (pid > -1)
runCommand("attach " + QByteArray::number(pid), CB(handleAttach));
runCommand({"attach " + QByteArray::number(pid), NoFlags, CB(handleAttach)});
else if (!remoteExecutable.isEmpty())
runCommand("set nto-executable " + remoteExecutable.toLatin1(), CB(handleSetNtoExecutable));
runCommand({"set nto-executable " + remoteExecutable.toLatin1(), NoFlags, CB(handleSetNtoExecutable)});
else
handleInferiorPrepared();
} else {
@@ -409,7 +409,7 @@ void GdbRemoteServerEngine::runEngine()
const QString remoteExecutable = runParameters().remoteExecutable;
if (!remoteExecutable.isEmpty()) {
runCommand("-exec-run", CB(handleExecRun), RunRequest);
runCommand({"-exec-run", RunRequest, CB(handleExecRun)});
} else {
notifyEngineRunAndInferiorStopOk();
continueInferiorInternal();
@@ -434,7 +434,7 @@ void GdbRemoteServerEngine::interruptInferior2()
{
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
if (boolSetting(TargetAsync)) {
runCommand("-exec-interrupt", CB(handleInterruptInferior));
runCommand({"-exec-interrupt", NoFlags, CB(handleInterruptInferior)});
} else if (m_isQnxGdb && HostOsInfo::isWindowsHost()) {
m_gdbProc.interrupt();
} else {

View File

@@ -134,9 +134,8 @@ void GdbTermEngine::runEngine()
{
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
const qint64 attachedPID = m_stubProc.applicationPID();
DebuggerCommand cmd("attach " + QByteArray::number(attachedPID));
cmd.callback = [this](const DebuggerResponse &r) { handleStubAttached(r); };
runCommand(cmd);
runCommand({"attach " + QByteArray::number(attachedPID), NoFlags,
[this](const DebuggerResponse &r) { handleStubAttached(r); }});
}
void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)

View File

@@ -130,17 +130,17 @@ void LldbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguage
runCommand(cmd);
}
void LldbEngine::runCommand(const DebuggerCommand &command_)
void LldbEngine::runCommand(const DebuggerCommand &cmd)
{
QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll());
const int tok = ++currentToken();
DebuggerCommand command = command_;
DebuggerCommand command = cmd;
command.arg("token", tok);
QByteArray token = QByteArray::number(tok);
QByteArray cmd = command.function + "(" + command.argsToPython() + ")";
showMessage(_(token + cmd + '\n'), LogInput);
QByteArray function = command.function + "(" + command.argsToPython() + ")";
showMessage(_(token + function + '\n'), LogInput);
m_commandForToken[currentToken()] = command;
m_lldbProc.write("script theDumper." + cmd + "\n");
m_lldbProc.write("script theDumper." + function + "\n");
}
void LldbEngine::debugLastCommand()
@@ -151,7 +151,7 @@ void LldbEngine::debugLastCommand()
void LldbEngine::shutdownInferior()
{
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
runCommand(DebuggerCommand("shutdownInferior"));
runCommand({"shutdownInferior"});
}
void LldbEngine::shutdownEngine()
@@ -405,37 +405,37 @@ void LldbEngine::runEngine()
void LldbEngine::interruptInferior()
{
showStatusMessage(tr("Interrupt requested..."), 5000);
runCommand("interruptInferior");
runCommand({"interruptInferior"});
}
void LldbEngine::executeStep()
{
notifyInferiorRunRequested();
runCommand("executeStep");
runCommand({"executeStep"});
}
void LldbEngine::executeStepI()
{
notifyInferiorRunRequested();
runCommand("executeStepI");
runCommand({"executeStepI"});
}
void LldbEngine::executeStepOut()
{
notifyInferiorRunRequested();
runCommand("executeStepOut");
runCommand({"executeStepOut"});
}
void LldbEngine::executeNext()
{
notifyInferiorRunRequested();
runCommand("executeNext");
runCommand({"executeNext"});
}
void LldbEngine::executeNextI()
{
notifyInferiorRunRequested();
runCommand("executeNextI");
runCommand({"executeNextI"});
}
void LldbEngine::continueInferior()
@@ -984,7 +984,7 @@ void LldbEngine::reloadRegisters()
void LldbEngine::reloadDebuggingHelpers()
{
runCommand("reloadDumpers");
runCommand({"reloadDumpers"});
updateAll();
}
@@ -1037,7 +1037,7 @@ void LldbEngine::fetchFullBacktrace()
Internal::openTextEditor(_("Backtrace $"),
QString::fromUtf8(QByteArray::fromHex(response.data.data())));
};
runCommand("fetchFullBacktrace");
runCommand(cmd);
}
void LldbEngine::fetchMemory(MemoryAgent *agent, QObject *editorToken,

View File

@@ -147,7 +147,7 @@ private:
void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result) override;
void runCommand(const DebuggerCommand &cmd);
void runCommand(const DebuggerCommand &cmd) override;
void debugLastCommand() override;
private:

View File

@@ -300,7 +300,7 @@ void PdbEngine::loadAllSymbols()
void PdbEngine::reloadModules()
{
runCommand("listModules");
runCommand({"listModules"});
}
void PdbEngine::refreshModules(const GdbMi &modules)
@@ -557,7 +557,7 @@ void PdbEngine::refreshStack(const GdbMi &stack)
void PdbEngine::updateAll()
{
runCommand("stackListFrames");
runCommand({"stackListFrames"});
updateLocals();
}

View File

@@ -98,7 +98,7 @@ private:
bool isSynchronous() const override { return true; }
void updateItem(const QByteArray &iname) override;
void runCommand(const DebuggerCommand &cmd);
void runCommand(const DebuggerCommand &cmd) override;
void postDirectCommand(const QByteArray &command);
void refreshLocation(const GdbMi &reportedLocation);

View File

@@ -612,7 +612,7 @@ void QmlEngine::shutdownInferior()
// "type" : "request",
// "command" : "disconnect",
// }
d->runCommand(DISCONNECT);
d->runCommand({DISCONNECT});
if (isSlaveEngine())
resetLocation();
@@ -2504,7 +2504,7 @@ void QmlEnginePrivate::stateChanged(State state)
/// Start session.
flushSendBuffer();
runDirectCommand(CONNECT);
runCommand(VERSION); // Only used for logging.
runCommand({VERSION}); // Only used for logging.
}
}