forked from qt-creator/qt-creator
Debugger: Use the usual callback mechanism for LLDB, too
... instead of the custom mechanisms to funnel breakpoint ids, cookies and similar through individual bridge functions. Change-Id: I2b6e906078eefdbcd4ffa166dc1881a1d0f7fb51 Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
@@ -107,7 +107,7 @@ LldbEngine::LldbEngine(const DebuggerRunParameters &startParameters)
|
||||
connect(action(AutoDerefPointers), &SavedAction::valueChanged,
|
||||
this, &LldbEngine::updateLocals);
|
||||
connect(action(CreateFullBacktrace), &QAction::triggered,
|
||||
this, &LldbEngine::createFullBacktrace);
|
||||
this, &LldbEngine::fetchFullBacktrace);
|
||||
connect(action(UseDebuggingHelpers), &SavedAction::valueChanged,
|
||||
this, &LldbEngine::updateLocals);
|
||||
connect(action(UseDynamicType), &SavedAction::valueChanged,
|
||||
@@ -138,6 +138,7 @@ void LldbEngine::runCommand(const DebuggerCommand &command_)
|
||||
QByteArray token = QByteArray::number(tok);
|
||||
QByteArray cmd = command.function + "({" + command.args + "})";
|
||||
showMessage(_(token + cmd + '\n'), LogInput);
|
||||
m_commandForToken[currentToken()] = command;
|
||||
m_lldbProc.write("script theDumper." + cmd + "\n");
|
||||
}
|
||||
|
||||
@@ -316,12 +317,11 @@ void LldbEngine::setupInferior()
|
||||
}
|
||||
|
||||
DebuggerCommand cmd1("loadDumpers");
|
||||
cmd1.callback = [this](const DebuggerResponse &response) {
|
||||
watchHandler()->addDumpers(response.data);
|
||||
};
|
||||
runCommand(cmd1);
|
||||
}
|
||||
|
||||
// FIXME: splitting of setupInferior() necessary to support LLDB <= 310 - revert asap
|
||||
void LldbEngine::setupInferiorStage2()
|
||||
{
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
|
||||
QString executable;
|
||||
@@ -329,33 +329,16 @@ void LldbEngine::setupInferiorStage2()
|
||||
QtcProcess::prepareCommand(QFileInfo(rp.executable).absoluteFilePath(),
|
||||
rp.processArgs, &executable, &args);
|
||||
|
||||
DebuggerCommand cmd("setupInferior");
|
||||
cmd.arg("executable", executable);
|
||||
cmd.arg("breakOnMain", rp.breakOnMain);
|
||||
cmd.arg("useTerminal", rp.useTerminal);
|
||||
cmd.arg("startMode", rp.startMode);
|
||||
DebuggerCommand cmd2("setupInferior");
|
||||
cmd2.arg("executable", executable);
|
||||
cmd2.arg("breakOnMain", rp.breakOnMain);
|
||||
cmd2.arg("useTerminal", rp.useTerminal);
|
||||
cmd2.arg("startMode", rp.startMode);
|
||||
|
||||
cmd.beginList("bkpts");
|
||||
foreach (Breakpoint bp, breakHandler()->unclaimedBreakpoints()) {
|
||||
if (acceptsBreakpoint(bp)) {
|
||||
showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2")
|
||||
.arg(bp.id().toString()).arg(bp.state()));
|
||||
bp.setEngine(this);
|
||||
bp.notifyBreakpointInsertProceeding();
|
||||
cmd.beginGroup();
|
||||
bp.addToCommand(&cmd);
|
||||
cmd.endGroup();
|
||||
} else {
|
||||
showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE")
|
||||
.arg(bp.id().toString()).arg(bp.state()));
|
||||
}
|
||||
}
|
||||
cmd.endList();
|
||||
|
||||
cmd.beginList("processArgs");
|
||||
cmd2.beginList("processArgs");
|
||||
foreach (const QString &arg, args.toUnixArgs())
|
||||
cmd.arg(arg.toUtf8().toHex());
|
||||
cmd.endList();
|
||||
cmd2.arg(arg.toUtf8().toHex());
|
||||
cmd2.endList();
|
||||
|
||||
if (rp.useTerminal) {
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
@@ -365,28 +348,45 @@ void LldbEngine::setupInferiorStage2()
|
||||
? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
|
||||
: QString::fromLatin1("Attaching to %1").arg(attachedPID);
|
||||
showMessage(msg, LogMisc);
|
||||
cmd.arg("attachPid", attachedPID);
|
||||
cmd2.arg("attachPid", attachedPID);
|
||||
|
||||
} else {
|
||||
|
||||
cmd.arg("startMode", rp.startMode);
|
||||
cmd2.arg("startMode", rp.startMode);
|
||||
// it is better not to check the start mode on the python sid (as we would have to duplicate the
|
||||
// enum values), and thus we assume that if the rp.attachPID is valid we really have to attach
|
||||
QTC_CHECK(rp.attachPID <= 0 || (rp.startMode == AttachCrashedExternal
|
||||
|| rp.startMode == AttachExternal));
|
||||
cmd.arg("attachPid", rp.attachPID);
|
||||
cmd.arg("sysRoot", rp.deviceSymbolsRoot.isEmpty() ? rp.sysRoot : rp.deviceSymbolsRoot);
|
||||
cmd.arg("remoteChannel", ((rp.startMode == AttachToRemoteProcess
|
||||
cmd2.arg("attachPid", rp.attachPID);
|
||||
cmd2.arg("sysRoot", rp.deviceSymbolsRoot.isEmpty() ? rp.sysRoot : rp.deviceSymbolsRoot);
|
||||
cmd2.arg("remoteChannel", ((rp.startMode == AttachToRemoteProcess
|
||||
|| rp.startMode == AttachToRemoteServer)
|
||||
? rp.remoteChannel : QString()));
|
||||
cmd.arg("platform", rp.platform);
|
||||
cmd2.arg("platform", rp.platform);
|
||||
QTC_CHECK(!rp.continueAfterAttach || (rp.startMode == AttachToRemoteProcess
|
||||
|| rp.startMode == AttachExternal
|
||||
|| rp.startMode == AttachToRemoteServer));
|
||||
m_continueAtNextSpontaneousStop = false;
|
||||
}
|
||||
|
||||
runCommand(cmd);
|
||||
cmd2.callback = [this](const DebuggerResponse &response) {
|
||||
bool success = response.data["success"].toInt();
|
||||
if (success) {
|
||||
foreach (Breakpoint bp, breakHandler()->unclaimedBreakpoints()) {
|
||||
if (acceptsBreakpoint(bp)) {
|
||||
bp.setEngine(this);
|
||||
insertBreakpoint(bp);
|
||||
} else {
|
||||
showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE")
|
||||
.arg(bp.id().toString()).arg(bp.state()));
|
||||
}
|
||||
}
|
||||
notifyInferiorSetupOk();
|
||||
} else {
|
||||
notifyInferiorSetupFailed();
|
||||
}
|
||||
};
|
||||
runCommand(cmd2);
|
||||
}
|
||||
|
||||
void LldbEngine::runEngine()
|
||||
@@ -395,10 +395,8 @@ void LldbEngine::runEngine()
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state(); return);
|
||||
showStatusMessage(tr("Running requested..."), 5000);
|
||||
DebuggerCommand cmd("runEngine");
|
||||
if (rp.startMode == AttachCore) {
|
||||
if (rp.startMode == AttachCore)
|
||||
cmd.arg("coreFile", rp.coreFile);
|
||||
cmd.arg("continuation", "updateAll");
|
||||
}
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
@@ -447,7 +445,12 @@ void LldbEngine::continueInferior()
|
||||
{
|
||||
resetLocation();
|
||||
notifyInferiorRunRequested();
|
||||
runCommand("continueInferior");
|
||||
DebuggerCommand cmd("continueInferior");
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
if (response.resultClass == ResultError)
|
||||
notifyEngineIll();
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::handleResponse(const QByteArray &response)
|
||||
@@ -457,72 +460,31 @@ void LldbEngine::handleResponse(const QByteArray &response)
|
||||
|
||||
foreach (const GdbMi &item, all.children()) {
|
||||
const QByteArray name = item.name();
|
||||
if (name == "all") {
|
||||
updateLocalsView(item);
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
} else if (name == "dumpers") {
|
||||
watchHandler()->addDumpers(item);
|
||||
setupInferiorStage2();
|
||||
} else if (name == "stack")
|
||||
refreshStack(item);
|
||||
else if (name == "registers")
|
||||
refreshRegisters(item);
|
||||
else if (name == "threads")
|
||||
refreshThreads(item);
|
||||
else if (name == "current-thread")
|
||||
refreshCurrentThread(item);
|
||||
else if (name == "typeinfo")
|
||||
refreshTypeInfo(item);
|
||||
else if (name == "state")
|
||||
refreshState(item);
|
||||
else if (name == "location")
|
||||
refreshLocation(item);
|
||||
else if (name == "modules")
|
||||
refreshModules(item);
|
||||
else if (name == "symbols")
|
||||
refreshSymbols(item);
|
||||
else if (name == "breakpoint-added")
|
||||
refreshAddedBreakpoint(item);
|
||||
else if (name == "breakpoint-changed")
|
||||
refreshChangedBreakpoint(item);
|
||||
else if (name == "breakpoint-removed")
|
||||
refreshRemovedBreakpoint(item);
|
||||
else if (name == "output")
|
||||
refreshOutput(item);
|
||||
else if (name == "disassembly")
|
||||
refreshDisassembly(item);
|
||||
else if (name == "memory")
|
||||
refreshMemory(item);
|
||||
else if (name == "full-backtrace")
|
||||
showFullBacktrace(item);
|
||||
else if (name == "continuation")
|
||||
handleContinuation(item);
|
||||
else if (name == "statusmessage") {
|
||||
QString msg = QString::fromUtf8(item.data());
|
||||
if (name == "result") {
|
||||
QString msg = item["status"].toUtf8();
|
||||
if (msg.size())
|
||||
msg[0] = msg.at(0).toUpper();
|
||||
showStatusMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::handleContinuation(const GdbMi &data)
|
||||
{
|
||||
if (data.data() == "updateLocals") {
|
||||
updateLocals();
|
||||
} else if (data.data() == "updateAll") {
|
||||
updateAll();
|
||||
} else {
|
||||
QTC_ASSERT(false, qDebug() << "Unknown continuation: " << data.data());
|
||||
int token = item["token"].toInt();
|
||||
showMessage(QString::fromLatin1("%1^").arg(token), LogOutput);
|
||||
if (m_commandForToken.contains(token)) {
|
||||
DebuggerCommand cmd = m_commandForToken.take(token);
|
||||
DebuggerResponse response;
|
||||
response.token = token;
|
||||
response.data = item;
|
||||
if (cmd.callback)
|
||||
cmd.callback(response);
|
||||
}
|
||||
} else if (name == "state")
|
||||
handleStateNotification(item);
|
||||
else if (name == "location")
|
||||
handleLocationNotification(item);
|
||||
else if (name == "output")
|
||||
handleOutputNotification(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::showFullBacktrace(const GdbMi &data)
|
||||
{
|
||||
Internal::openTextEditor(_("Backtrace $"),
|
||||
QString::fromUtf8(QByteArray::fromHex(data.data())));
|
||||
}
|
||||
|
||||
void LldbEngine::executeRunToLine(const ContextData &data)
|
||||
{
|
||||
resetLocation();
|
||||
@@ -559,13 +521,8 @@ void LldbEngine::activateFrame(int frameIndex)
|
||||
return;
|
||||
|
||||
StackHandler *handler = stackHandler();
|
||||
|
||||
const int n = handler->stackSize();
|
||||
if (frameIndex == n) {
|
||||
DebuggerCommand cmd("reportStack");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
cmd.arg("stacklimit", n * 10 + 3);
|
||||
runCommand(cmd);
|
||||
if (frameIndex == handler->stackSize()) {
|
||||
fetchStack(handler->stackSize() * 10 + 3);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -576,20 +533,23 @@ void LldbEngine::activateFrame(int frameIndex)
|
||||
DebuggerCommand cmd("activateFrame");
|
||||
cmd.arg("index", frameIndex);
|
||||
cmd.arg("thread", threadsHandler()->currentThread().raw());
|
||||
cmd.arg("continuation", "updateLocals");
|
||||
runCommand(cmd);
|
||||
|
||||
updateLocals();
|
||||
reloadRegisters();
|
||||
}
|
||||
|
||||
void LldbEngine::selectThread(ThreadId threadId)
|
||||
{
|
||||
DebuggerCommand cmd1("selectThread");
|
||||
cmd1.arg("id", threadId.raw());
|
||||
runCommand(cmd1);
|
||||
|
||||
DebuggerCommand cmd("reportStack");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
|
||||
cmd.arg("continuation", "updateLocals");
|
||||
DebuggerCommand cmd("selectThread");
|
||||
cmd.arg("id", threadId.raw());
|
||||
cmd.callback = [this](const DebuggerResponse &) {
|
||||
DebuggerCommand cmd("fetchStack");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
|
||||
runCommand(cmd);
|
||||
updateLocals();
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
@@ -620,6 +580,10 @@ bool LldbEngine::acceptsBreakpoint(Breakpoint bp) const
|
||||
void LldbEngine::insertBreakpoint(Breakpoint bp)
|
||||
{
|
||||
DebuggerCommand cmd("insertBreakpoint");
|
||||
cmd.callback = [this, bp](const DebuggerResponse &response) {
|
||||
QTC_CHECK(bp.state() == BreakpointInsertProceeding);
|
||||
updateBreakpointData(bp, response.data, true);
|
||||
};
|
||||
bp.addToCommand(&cmd);
|
||||
bp.notifyBreakpointInsertProceeding();
|
||||
runCommand(cmd);
|
||||
@@ -630,6 +594,10 @@ void LldbEngine::changeBreakpoint(Breakpoint bp)
|
||||
const BreakpointResponse &response = bp.response();
|
||||
DebuggerCommand cmd("changeBreakpoint");
|
||||
cmd.arg("lldbid", response.id.toByteArray());
|
||||
cmd.callback = [this, bp](const DebuggerResponse &response) {
|
||||
QTC_CHECK(!bp.isValid() || bp.state() == BreakpointChangeProceeding);
|
||||
updateBreakpointData(bp, response.data, false);
|
||||
};
|
||||
bp.addToCommand(&cmd);
|
||||
bp.notifyBreakpointChangeProceeding();
|
||||
runCommand(cmd);
|
||||
@@ -638,19 +606,23 @@ void LldbEngine::changeBreakpoint(Breakpoint bp)
|
||||
void LldbEngine::removeBreakpoint(Breakpoint bp)
|
||||
{
|
||||
const BreakpointResponse &response = bp.response();
|
||||
DebuggerCommand cmd("removeBreakpoint");
|
||||
cmd.arg("modelid", bp.id().toByteArray());
|
||||
cmd.arg("lldbid", response.id.toByteArray());
|
||||
bp.notifyBreakpointRemoveProceeding();
|
||||
runCommand(cmd);
|
||||
if (response.id.isValid()) {
|
||||
DebuggerCommand cmd("removeBreakpoint");
|
||||
cmd.arg("lldbid", response.id.toByteArray());
|
||||
cmd.callback = [this, bp](const DebuggerResponse &) {
|
||||
QTC_CHECK(bp.state() == BreakpointRemoveProceeding);
|
||||
Breakpoint bp0 = bp;
|
||||
bp0.notifyBreakpointRemoveOk();
|
||||
};
|
||||
bp.notifyBreakpointRemoveProceeding();
|
||||
runCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
|
||||
void LldbEngine::updateBreakpointData(Breakpoint bp, const GdbMi &bkpt, bool added)
|
||||
{
|
||||
BreakHandler *handler = breakHandler();
|
||||
BreakpointResponseId rid = BreakpointResponseId(bkpt["lldbid"].data());
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
Breakpoint bp = handler->breakpointById(id);
|
||||
if (!bp.isValid())
|
||||
bp = handler->findBreakpointByResponseId(rid);
|
||||
BreakpointResponse response = bp.response();
|
||||
@@ -694,50 +666,7 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
|
||||
bp.notifyBreakpointChangeOk();
|
||||
}
|
||||
|
||||
void LldbEngine::refreshDisassembly(const GdbMi &data)
|
||||
{
|
||||
DisassemblerLines result;
|
||||
|
||||
int cookie = data["cookie"].toInt();
|
||||
QPointer<DisassemblerAgent> agent = m_disassemblerAgents.key(cookie);
|
||||
if (!agent.isNull()) {
|
||||
foreach (const GdbMi &line, data["lines"].children()) {
|
||||
DisassemblerLine dl;
|
||||
dl.address = line["address"].toAddress();
|
||||
//dl.data = line["data"].toUtf8();
|
||||
//dl.rawData = line["rawdata"].data();
|
||||
dl.data = line["rawdata"].toUtf8();
|
||||
if (!dl.data.isEmpty())
|
||||
dl.data += QString(30 - dl.data.size(), QLatin1Char(' '));
|
||||
dl.data += line["data"].toUtf8();
|
||||
dl.offset = line["offset"].toInt();
|
||||
dl.lineNumber = line["line"].toInt();
|
||||
dl.fileName = line["file"].toUtf8();
|
||||
dl.function = line["function"].toUtf8();
|
||||
dl.hunk = line["hunk"].toInt();
|
||||
QByteArray comment = line["comment"].data();
|
||||
if (!comment.isEmpty())
|
||||
dl.data += QString::fromUtf8(" # " + comment);
|
||||
result.appendLine(dl);
|
||||
}
|
||||
agent->setContents(result);
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::refreshMemory(const GdbMi &data)
|
||||
{
|
||||
int cookie = data["cookie"].toInt();
|
||||
qulonglong addr = data["address"].toAddress();
|
||||
QPointer<MemoryAgent> agent = m_memoryAgents.key(cookie);
|
||||
if (!agent.isNull()) {
|
||||
QPointer<QObject> token = m_memoryAgentTokens.value(cookie);
|
||||
QTC_ASSERT(!token.isNull(), return);
|
||||
QByteArray ba = QByteArray::fromHex(data["contents"].data());
|
||||
agent->addLazyData(token.data(), addr, ba);
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::refreshOutput(const GdbMi &output)
|
||||
void LldbEngine::handleOutputNotification(const GdbMi &output)
|
||||
{
|
||||
QByteArray channel = output["channel"].data();
|
||||
QByteArray data = QByteArray::fromHex(output["data"].data());
|
||||
@@ -749,30 +678,6 @@ void LldbEngine::refreshOutput(const GdbMi &output)
|
||||
showMessage(QString::fromUtf8(data), ch);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshAddedBreakpoint(const GdbMi &bkpt)
|
||||
{
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
Breakpoint bp = breakHandler()->breakpointById(id);
|
||||
QTC_CHECK(bp.state() == BreakpointInsertProceeding);
|
||||
updateBreakpointData(bkpt, true);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshChangedBreakpoint(const GdbMi &bkpt)
|
||||
{
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
Breakpoint bp = breakHandler()->breakpointById(id);
|
||||
QTC_CHECK(!bp.isValid() || bp.state() == BreakpointChangeProceeding);
|
||||
updateBreakpointData(bkpt, false);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshRemovedBreakpoint(const GdbMi &bkpt)
|
||||
{
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
Breakpoint bp = breakHandler()->breakpointById(id);
|
||||
QTC_CHECK(bp.state() == BreakpointRemoveProceeding);
|
||||
bp.notifyBreakpointRemoveOk();
|
||||
}
|
||||
|
||||
void LldbEngine::loadSymbols(const QString &moduleName)
|
||||
{
|
||||
Q_UNUSED(moduleName)
|
||||
@@ -784,48 +689,47 @@ void LldbEngine::loadAllSymbols()
|
||||
|
||||
void LldbEngine::reloadModules()
|
||||
{
|
||||
runCommand("listModules");
|
||||
}
|
||||
|
||||
void LldbEngine::refreshModules(const GdbMi &modules)
|
||||
{
|
||||
ModulesHandler *handler = modulesHandler();
|
||||
handler->beginUpdateAll();
|
||||
foreach (const GdbMi &item, modules.children()) {
|
||||
Module module;
|
||||
module.modulePath = item["file"].toUtf8();
|
||||
module.moduleName = item["name"].toUtf8();
|
||||
module.symbolsRead = Module::UnknownReadState;
|
||||
module.startAddress = item["loaded_addr"].toAddress();
|
||||
module.endAddress = 0; // FIXME: End address not easily available.
|
||||
handler->updateModule(module);
|
||||
}
|
||||
handler->endUpdateAll();
|
||||
DebuggerCommand cmd("fetchModules");
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
const GdbMi &modules = response.data["modules"];
|
||||
ModulesHandler *handler = modulesHandler();
|
||||
handler->beginUpdateAll();
|
||||
foreach (const GdbMi &item, modules.children()) {
|
||||
Module module;
|
||||
module.modulePath = item["file"].toUtf8();
|
||||
module.moduleName = item["name"].toUtf8();
|
||||
module.symbolsRead = Module::UnknownReadState;
|
||||
module.startAddress = item["loaded_addr"].toAddress();
|
||||
module.endAddress = 0; // FIXME: End address not easily available.
|
||||
handler->updateModule(module);
|
||||
}
|
||||
handler->endUpdateAll();
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::requestModuleSymbols(const QString &moduleName)
|
||||
{
|
||||
DebuggerCommand cmd("listSymbols");
|
||||
DebuggerCommand cmd("fetchSymbols");
|
||||
cmd.arg("module", moduleName);
|
||||
cmd.callback = [this, moduleName](const DebuggerResponse &response) {
|
||||
const GdbMi &symbols = response.data["symbols"];
|
||||
QString moduleName = response.data["module"].toUtf8();
|
||||
Symbols syms;
|
||||
foreach (const GdbMi &item, symbols.children()) {
|
||||
Symbol symbol;
|
||||
symbol.address = item["address"].toUtf8();
|
||||
symbol.name = item["name"].toUtf8();
|
||||
symbol.state = item["state"].toUtf8();
|
||||
symbol.section = item["section"].toUtf8();
|
||||
symbol.demangled = item["demangled"].toUtf8();
|
||||
syms.append(symbol);
|
||||
}
|
||||
Internal::showModuleSymbols(moduleName, syms);
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshSymbols(const GdbMi &symbols)
|
||||
{
|
||||
QString moduleName = symbols["module"].toUtf8();
|
||||
Symbols syms;
|
||||
foreach (const GdbMi &item, symbols["symbols"].children()) {
|
||||
Symbol symbol;
|
||||
symbol.address = item["address"].toUtf8();
|
||||
symbol.name = item["name"].toUtf8();
|
||||
symbol.state = item["state"].toUtf8();
|
||||
symbol.section = item["section"].toUtf8();
|
||||
symbol.demangled = item["demangled"].toUtf8();
|
||||
syms.append(symbol);
|
||||
}
|
||||
Internal::showModuleSymbols(moduleName, syms);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -840,27 +744,60 @@ bool LldbEngine::canHandleToolTip(const DebuggerToolTipContext &context) const
|
||||
|
||||
void LldbEngine::updateAll()
|
||||
{
|
||||
DebuggerCommand cmd1("reportThreads");
|
||||
runCommand(cmd1);
|
||||
|
||||
DebuggerCommand cmd2("reportCurrentThread");
|
||||
runCommand(cmd2);
|
||||
|
||||
DebuggerCommand cmd("reportStack");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
|
||||
cmd.arg("continuation", "updateLocals");
|
||||
DebuggerCommand cmd("fetchThreads");
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
threadsHandler()->updateThreads(response.data);
|
||||
fetchStack(action(MaximalStackDepth)->value().toInt());
|
||||
reloadRegisters();
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::reloadFullStack()
|
||||
{
|
||||
DebuggerCommand cmd("reportStack");
|
||||
fetchStack(-1);
|
||||
}
|
||||
|
||||
void LldbEngine::fetchStack(int limit)
|
||||
{
|
||||
DebuggerCommand cmd("fetchStack");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
cmd.arg("stacklimit", -1);
|
||||
cmd.arg("stacklimit", limit);
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
const GdbMi &stack = response.data["stack"];
|
||||
StackHandler *handler = stackHandler();
|
||||
StackFrames frames;
|
||||
foreach (const GdbMi &item, stack["frames"].children()) {
|
||||
StackFrame frame;
|
||||
frame.level = item["level"].toInt();
|
||||
frame.file = item["file"].toUtf8();
|
||||
frame.function = item["func"].toUtf8();
|
||||
frame.from = item["func"].toUtf8();
|
||||
frame.line = item["line"].toInt();
|
||||
frame.address = item["addr"].toAddress();
|
||||
GdbMi usable = item["usable"];
|
||||
if (usable.isValid())
|
||||
frame.usable = usable.data().toInt();
|
||||
else
|
||||
frame.usable = QFileInfo(frame.file).isReadable();
|
||||
if (item["language"].data() == "js"
|
||||
|| frame.file.endsWith(QLatin1String(".js"))
|
||||
|| frame.file.endsWith(QLatin1String(".qml"))) {
|
||||
frame.language = QmlLanguage;
|
||||
frame.fixQmlFrame(runParameters());
|
||||
}
|
||||
frames.append(frame);
|
||||
}
|
||||
bool canExpand = stack["hasmore"].toInt();
|
||||
action(ExpandStack)->setEnabled(canExpand);
|
||||
handler->setFrames(frames, canExpand);
|
||||
|
||||
updateLocals();
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Watch specific stuff
|
||||
@@ -873,6 +810,7 @@ void LldbEngine::assignValueInDebugger(WatchItem *,
|
||||
DebuggerCommand cmd("assignValue");
|
||||
cmd.arg("exp", expression.toLatin1().toHex());
|
||||
cmd.arg("value", value.toString().toLatin1().toHex());
|
||||
cmd.callback = [this](const DebuggerResponse &) { updateLocals(); };
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
@@ -885,7 +823,7 @@ void LldbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
||||
|
||||
watchHandler()->notifyUpdateStarted(params.partialVariables());
|
||||
|
||||
DebuggerCommand cmd("updateData");
|
||||
DebuggerCommand cmd("fetchLocals");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
watchHandler()->appendFormatRequests(&cmd);
|
||||
|
||||
@@ -925,9 +863,12 @@ void LldbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
||||
m_lastDebuggableCommand = cmd;
|
||||
m_lastDebuggableCommand.args.replace("\"passexceptions\":0", "\"passexceptions\":1");
|
||||
|
||||
runCommand(cmd);
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
updateLocalsView(response.data);
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
};
|
||||
|
||||
reloadRegisters();
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::handleLldbError(QProcess::ProcessError error)
|
||||
@@ -991,7 +932,7 @@ void LldbEngine::readLldbStandardOutput()
|
||||
{
|
||||
QByteArray out = m_lldbProc.readAllStandardOutput();
|
||||
out.replace("\r\n", "\n");
|
||||
showMessage(_(out));
|
||||
showMessage(_(out), LogOutput);
|
||||
m_inbuffer.append(out);
|
||||
while (true) {
|
||||
int pos = m_inbuffer.indexOf("@\n");
|
||||
@@ -1006,86 +947,7 @@ void LldbEngine::readLldbStandardOutput()
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::refreshStack(const GdbMi &stack)
|
||||
{
|
||||
StackHandler *handler = stackHandler();
|
||||
StackFrames frames;
|
||||
foreach (const GdbMi &item, stack["frames"].children()) {
|
||||
StackFrame frame;
|
||||
frame.level = item["level"].toInt();
|
||||
frame.file = item["file"].toUtf8();
|
||||
frame.function = item["func"].toUtf8();
|
||||
frame.from = item["func"].toUtf8();
|
||||
frame.line = item["line"].toInt();
|
||||
frame.address = item["addr"].toAddress();
|
||||
GdbMi usable = item["usable"];
|
||||
if (usable.isValid())
|
||||
frame.usable = usable.data().toInt();
|
||||
else
|
||||
frame.usable = QFileInfo(frame.file).isReadable();
|
||||
if (item["language"].data() == "js"
|
||||
|| frame.file.endsWith(QLatin1String(".js"))
|
||||
|| frame.file.endsWith(QLatin1String(".qml"))) {
|
||||
frame.language = QmlLanguage;
|
||||
frame.fixQmlFrame(runParameters());
|
||||
}
|
||||
frames.append(frame);
|
||||
}
|
||||
bool canExpand = stack["hasmore"].toInt();
|
||||
action(ExpandStack)->setEnabled(canExpand);
|
||||
handler->setFrames(frames, canExpand);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshRegisters(const GdbMi ®isters)
|
||||
{
|
||||
RegisterHandler *handler = registerHandler();
|
||||
foreach (const GdbMi &item, registers.children()) {
|
||||
Register reg;
|
||||
reg.name = item["name"].data();
|
||||
reg.value.fromByteArray(item["value"].data(), HexadecimalFormat);
|
||||
reg.size = item["size"].data().toInt();
|
||||
reg.reportedType = item["type"].data();
|
||||
if (reg.reportedType.startsWith("unsigned"))
|
||||
reg.kind = IntegerRegister;
|
||||
handler->updateRegister(reg);
|
||||
}
|
||||
handler->commitUpdates();
|
||||
}
|
||||
|
||||
void LldbEngine::refreshThreads(const GdbMi &threads)
|
||||
{
|
||||
ThreadsHandler *handler = threadsHandler();
|
||||
handler->updateThreads(threads);
|
||||
updateViews(); // Adjust Threads combobox.
|
||||
}
|
||||
|
||||
void LldbEngine::refreshCurrentThread(const GdbMi &data)
|
||||
{
|
||||
ThreadsHandler *handler = threadsHandler();
|
||||
ThreadId id(data["id"].toInt());
|
||||
handler->setCurrentThread(id);
|
||||
updateViews(); // Adjust Threads combobox.
|
||||
}
|
||||
|
||||
void LldbEngine::refreshTypeInfo(const GdbMi &typeInfo)
|
||||
{
|
||||
if (typeInfo.type() == GdbMi::List) {
|
||||
// foreach (const GdbMi &s, typeInfo.children()) {
|
||||
// const GdbMi name = s["name"];
|
||||
// const GdbMi size = s["size"];
|
||||
// if (name.isValid() && size.isValid())
|
||||
// m_typeInfoCache.insert(QByteArray::fromBase64(name.data()),
|
||||
// TypeInfo(size.data().toUInt()));
|
||||
// }
|
||||
}
|
||||
// for (int i = 0; i != list.size(); ++i) {
|
||||
// const TypeInfo ti = m_typeInfoCache.value(list.at(i).type);
|
||||
// if (ti.size)
|
||||
// list[i].size = ti.size;
|
||||
// }
|
||||
}
|
||||
|
||||
void LldbEngine::refreshState(const GdbMi &reportedState)
|
||||
void LldbEngine::handleStateNotification(const GdbMi &reportedState)
|
||||
{
|
||||
QByteArray newState = reportedState.data();
|
||||
if (newState == "running")
|
||||
@@ -1113,10 +975,6 @@ void LldbEngine::refreshState(const GdbMi &reportedState)
|
||||
notifyEngineSetupFailed();
|
||||
else if (newState == "enginerunfailed")
|
||||
notifyEngineRunFailed();
|
||||
else if (newState == "inferiorsetupok")
|
||||
notifyInferiorSetupOk();
|
||||
else if (newState == "inferiorsetupfailed")
|
||||
notifyInferiorSetupFailed();
|
||||
else if (newState == "enginerunandinferiorrunok") {
|
||||
if (runParameters().continueAfterAttach)
|
||||
m_continueAtNextSpontaneousStop = true;
|
||||
@@ -1137,7 +995,7 @@ void LldbEngine::refreshState(const GdbMi &reportedState)
|
||||
notifyInferiorExited();
|
||||
}
|
||||
|
||||
void LldbEngine::refreshLocation(const GdbMi &reportedLocation)
|
||||
void LldbEngine::handleLocationNotification(const GdbMi &reportedLocation)
|
||||
{
|
||||
qulonglong addr = reportedLocation["addr"].toAddress();
|
||||
QString file = reportedLocation["file"].toUtf8();
|
||||
@@ -1153,8 +1011,26 @@ void LldbEngine::refreshLocation(const GdbMi &reportedLocation)
|
||||
|
||||
void LldbEngine::reloadRegisters()
|
||||
{
|
||||
if (Internal::isDockVisible(QLatin1String(DOCKWIDGET_REGISTER)))
|
||||
runCommand("reportRegisters");
|
||||
if (!Internal::isDockVisible(QLatin1String(DOCKWIDGET_REGISTER)))
|
||||
return;
|
||||
|
||||
DebuggerCommand cmd("fetchRegisters");
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
RegisterHandler *handler = registerHandler();
|
||||
GdbMi regs = response.data["registers"];
|
||||
foreach (const GdbMi &item, regs.children()) {
|
||||
Register reg;
|
||||
reg.name = item["name"].data();
|
||||
reg.value.fromByteArray(item["value"].data(), HexadecimalFormat);
|
||||
reg.size = item["size"].data().toInt();
|
||||
reg.reportedType = item["type"].data();
|
||||
if (reg.reportedType.startsWith("unsigned"))
|
||||
reg.kind = IntegerRegister;
|
||||
handler->updateRegister(reg);
|
||||
}
|
||||
handler->commitUpdates();
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::reloadDebuggingHelpers()
|
||||
@@ -1172,17 +1048,47 @@ void LldbEngine::fetchDisassembler(DisassemblerAgent *agent)
|
||||
m_disassemblerAgents.insert(p, id);
|
||||
}
|
||||
const Location &loc = agent->location();
|
||||
DebuggerCommand cmd("disassemble");
|
||||
cmd.arg("cookie", id);
|
||||
DebuggerCommand cmd("fetchDisassembler");
|
||||
cmd.arg("address", loc.address());
|
||||
cmd.arg("function", loc.functionName());
|
||||
cmd.arg("flavor", boolSetting(IntelFlavor) ? "intel" : "att");
|
||||
cmd.callback = [this, id](const DebuggerResponse &response) {
|
||||
DisassemblerLines result;
|
||||
QPointer<DisassemblerAgent> agent = m_disassemblerAgents.key(id);
|
||||
if (!agent.isNull()) {
|
||||
foreach (const GdbMi &line, response.data["lines"].children()) {
|
||||
DisassemblerLine dl;
|
||||
dl.address = line["address"].toAddress();
|
||||
//dl.data = line["data"].toUtf8();
|
||||
//dl.rawData = line["rawdata"].data();
|
||||
dl.data = line["rawdata"].toUtf8();
|
||||
if (!dl.data.isEmpty())
|
||||
dl.data += QString(30 - dl.data.size(), QLatin1Char(' '));
|
||||
dl.data += line["data"].toUtf8();
|
||||
dl.offset = line["offset"].toInt();
|
||||
dl.lineNumber = line["line"].toInt();
|
||||
dl.fileName = line["file"].toUtf8();
|
||||
dl.function = line["function"].toUtf8();
|
||||
dl.hunk = line["hunk"].toInt();
|
||||
QByteArray comment = line["comment"].data();
|
||||
if (!comment.isEmpty())
|
||||
dl.data += QString::fromUtf8(" # " + comment);
|
||||
result.appendLine(dl);
|
||||
}
|
||||
agent->setContents(result);
|
||||
}
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void LldbEngine::createFullBacktrace()
|
||||
void LldbEngine::fetchFullBacktrace()
|
||||
{
|
||||
runCommand("createFullBacktrace");
|
||||
DebuggerCommand cmd("fetchFullBacktrace");
|
||||
cmd.callback = [](const DebuggerResponse &response) {
|
||||
Internal::openTextEditor(_("Backtrace $"),
|
||||
QString::fromUtf8(QByteArray::fromHex(response.data.data())));
|
||||
};
|
||||
runCommand("fetchFullBacktrace");
|
||||
}
|
||||
|
||||
void LldbEngine::fetchMemory(MemoryAgent *agent, QObject *editorToken,
|
||||
@@ -1194,10 +1100,20 @@ void LldbEngine::fetchMemory(MemoryAgent *agent, QObject *editorToken,
|
||||
m_memoryAgents.insert(agent, id);
|
||||
}
|
||||
m_memoryAgentTokens.insert(id, editorToken);
|
||||
|
||||
DebuggerCommand cmd("fetchMemory");
|
||||
cmd.arg("address", addr);
|
||||
cmd.arg("length", length);
|
||||
cmd.arg("cookie", id);
|
||||
cmd.callback = [this, id](const DebuggerResponse &response) {
|
||||
qulonglong addr = response.data["address"].toAddress();
|
||||
QPointer<MemoryAgent> agent = m_memoryAgents.key(id);
|
||||
if (!agent.isNull()) {
|
||||
QPointer<QObject> token = m_memoryAgentTokens.value(id);
|
||||
QTC_ASSERT(!token.isNull(), return);
|
||||
QByteArray ba = QByteArray::fromHex(response.data["contents"].data());
|
||||
agent->addLazyData(token.data(), addr, ba);
|
||||
}
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
@@ -1213,7 +1129,7 @@ void LldbEngine::changeMemory(MemoryAgent *agent, QObject *editorToken,
|
||||
DebuggerCommand cmd("writeMemory");
|
||||
cmd.arg("address", addr);
|
||||
cmd.arg("data", data.toHex());
|
||||
cmd.arg("cookie", id);
|
||||
cmd.callback = [this, id](const DebuggerResponse &response) { Q_UNUSED(response); };
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user