summaryrefslogtreecommitdiff
path: root/src/plugins/debugger
diff options
context:
space:
mode:
authorhjk <hjk@theqtcompany.com>2015-10-08 16:19:57 +0200
committerChristian Stenger <christian.stenger@theqtcompany.com>2015-10-09 05:19:45 +0000
commit525c33f9991766342b41a0518b534836dc60ed69 (patch)
tree33f0bb24beeae02eb71e85c46e08943a033f0133 /src/plugins/debugger
parentea39476ef2c0017f54021693ba545117ad53afa6 (diff)
downloadqt-creator-525c33f9991766342b41a0518b534836dc60ed69.tar.gz
Debugger: Infrastructure for reworked native mixed debugging
- Remove old experimental native mixed approach. - Move some common stack parsing to Stackhandler. - Mark gdbbridge.py debug output explicitly to remove it from actual reponse handling New native mixed needs QtDeclarative changes and QTC_DEBUGGER_NATIVE_MIXED=1 for now. Change-Id: I09eed1da51cea878636d36756015b7bfaed34203 Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
Diffstat (limited to 'src/plugins/debugger')
-rw-r--r--src/plugins/debugger/breakhandler.cpp5
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp54
-rw-r--r--src/plugins/debugger/debugger.qbs1
-rw-r--r--src/plugins/debugger/debugger_dependencies.pri1
-rw-r--r--src/plugins/debugger/debuggeractions.cpp12
-rw-r--r--src/plugins/debugger/debuggeractions.h1
-rw-r--r--src/plugins/debugger/debuggerconstants.h1
-rw-r--r--src/plugins/debugger/debuggercore.h2
-rw-r--r--src/plugins/debugger/debuggerengine.cpp31
-rw-r--r--src/plugins/debugger/debuggerengine.h5
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp24
-rw-r--r--src/plugins/debugger/debuggerprotocol.cpp25
-rw-r--r--src/plugins/debugger/debuggerprotocol.h6
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp41
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp180
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h4
-rw-r--r--src/plugins/debugger/lldb/lldbengine.cpp40
-rw-r--r--src/plugins/debugger/pdb/pdbengine.cpp8
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp11
-rw-r--r--src/plugins/debugger/stackframe.cpp92
-rw-r--r--src/plugins/debugger/stackframe.h16
-rw-r--r--src/plugins/debugger/stackhandler.cpp16
-rw-r--r--src/plugins/debugger/stackhandler.h12
-rw-r--r--src/plugins/debugger/stackwindow.cpp2
-rw-r--r--src/plugins/debugger/watchdata.cpp4
25 files changed, 319 insertions, 275 deletions
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 44a0ad06f3..b95d196589 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -757,14 +757,15 @@ const BreakpointParameters &Breakpoint::parameters() const
void Breakpoint::addToCommand(DebuggerCommand *cmd) const
{
cmd->arg("modelid", id().toByteArray());
+ cmd->arg("id", int(response().id.majorPart()));
cmd->arg("type", type());
cmd->arg("ignorecount", ignoreCount());
cmd->arg("condition", condition().toHex());
cmd->arg("function", functionName().toUtf8());
cmd->arg("oneshot", isOneShot());
cmd->arg("enabled", isEnabled());
- cmd->arg("fileName", fileName().toUtf8());
- cmd->arg("lineNumber", lineNumber());
+ cmd->arg("file", fileName().toUtf8());
+ cmd->arg("line", lineNumber());
cmd->arg("address", address());
cmd->arg("expression", expression());
}
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 22ce1c2278..1a69843726 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -2539,28 +2539,29 @@ bool CdbEngine::stateAcceptsBreakpointChanges() const
bool CdbEngine::acceptsBreakpoint(Breakpoint bp) const
{
- if (!bp.parameters().isCppBreakpoint())
- return false;
- switch (bp.type()) {
- case UnknownBreakpointType:
- case LastBreakpointType:
- case BreakpointAtFork:
- case WatchpointAtExpression:
- case BreakpointAtSysCall:
- case BreakpointOnQmlSignalEmit:
- case BreakpointAtJavaScriptThrow:
- return false;
- case WatchpointAtAddress:
- case BreakpointByFileAndLine:
- case BreakpointByFunction:
- case BreakpointByAddress:
- case BreakpointAtThrow:
- case BreakpointAtCatch:
- case BreakpointAtMain:
- case BreakpointAtExec:
- break;
+ if (bp.parameters().isCppBreakpoint()) {
+ switch (bp.type()) {
+ case UnknownBreakpointType:
+ case LastBreakpointType:
+ case BreakpointAtFork:
+ case WatchpointAtExpression:
+ case BreakpointAtSysCall:
+ case BreakpointOnQmlSignalEmit:
+ case BreakpointAtJavaScriptThrow:
+ return false;
+ case WatchpointAtAddress:
+ case BreakpointByFileAndLine:
+ case BreakpointByFunction:
+ case BreakpointByAddress:
+ case BreakpointAtThrow:
+ case BreakpointAtCatch:
+ case BreakpointAtMain:
+ case BreakpointAtExec:
+ break;
+ }
+ return true;
}
- return true;
+ return isNativeMixedEnabled();
}
// Context for fixing file/line-type breakpoints, for delayed creation.
@@ -2801,7 +2802,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = 0)
break;
}
StackFrame frame;
- frame.level = i;
+ frame.level = QByteArray::number(i);
const GdbMi fullName = frameMi["fullname"];
if (fullName.isValid()) {
frame.file = QFile::decodeName(fullName.data());
@@ -2811,9 +2812,10 @@ static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = 0)
if (languageMi.isValid() && languageMi.data() == "js")
frame.language = QmlLanguage;
}
- frame.function = QLatin1String(frameMi["func"].data());
- frame.from = QLatin1String(frameMi["from"].data());
- frame.address = frameMi["addr"].data().toULongLong(0, 16);
+ frame.function = QLatin1String(frameMi["function"].data());
+ frame.module = QLatin1String(frameMi["from"].data());
+ frame.context = frameMi["context"].data();
+ frame.address = frameMi["address"].data().toULongLong(0, 16);
rc.push_back(frame);
}
return rc;
@@ -2895,7 +2897,7 @@ void CdbEngine::handleAdditionalQmlStack(const DebuggerResponse &response)
break;
}
for (int i = 0; i < qmlFrameCount; ++i)
- qmlFrames[i].fixQmlFrame(runParameters());
+ qmlFrames[i].fixQrcFrame(runParameters());
stackHandler()->prependFrames(qmlFrames);
} while (false);
if (!errorMessage.isEmpty())
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index e249c0c6b2..c165487a9f 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -15,6 +15,7 @@ QtcPlugin {
Depends { name: "Core" }
Depends { name: "CppTools" }
Depends { name: "ProjectExplorer" }
+ Depends { name: "QtSupport" }
Depends { name: "TextEditor" }
cpp.includePaths: base.concat([project.sharedSourcesDir + "/registryaccess"])
diff --git a/src/plugins/debugger/debugger_dependencies.pri b/src/plugins/debugger/debugger_dependencies.pri
index d337d67c3d..259d30c6b1 100644
--- a/src/plugins/debugger/debugger_dependencies.pri
+++ b/src/plugins/debugger/debugger_dependencies.pri
@@ -12,6 +12,7 @@ QTC_PLUGIN_DEPENDS += \
coreplugin \
cpptools \
projectexplorer \
+ qtsupport \
texteditor
QTC_PLUGIN_RECOMMENDS += \
cppeditor
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index bd025d77a2..b1d7e193dc 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -185,18 +185,6 @@ DebuggerSettings::DebuggerSettings()
insertItem(OperateByInstruction, item);
item = new SavedAction(this);
- item->setText(tr("Native Mixed Mode"));
- item->setCheckable(true);
- item->setDefaultValue(true);
- item->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
- item->setToolTip(tr("<p>This switches the debugger to native-mixed "
- "operation mode. In this mode, stepping and data display will "
- "be handled by the native debugger backend (GDB, LLDB or CDB) "
- "for C++, QML and JS sources."));
- item->setIconVisibleInMenu(false);
- insertItem(OperateNativeMixed, item);
-
- item = new SavedAction(this);
item->setText(tr("Dereference Pointers Automatically"));
item->setCheckable(true);
item->setDefaultValue(true);
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index 843d0dfadb..c7dabd7015 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -99,7 +99,6 @@ enum DebuggerActionCode
LogTimeStamps,
VerboseLog,
OperateByInstruction,
- OperateNativeMixed,
CloseSourceBuffersOnExit,
CloseMemoryBuffersOnExit,
SwitchModeOnExit,
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 9484990362..0fc33fefec 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -61,7 +61,6 @@ const char NEXT[] = "Debugger.NextLine";
const char REVERSE[] = "Debugger.ReverseDirection";
const char RESET[] = "Debugger.Reset";
const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction";
-const char OPERATE_NATIVE_MIXED[] = "Debugger.OperateNativeMixed";
const char QML_SHOW_APP_ON_TOP[] = "Debugger.QmlShowAppOnTop";
const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool";
const char QML_ZOOMTOOL[] = "Debugger.QmlZoomTool";
diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h
index 7e091496d8..7e983ca362 100644
--- a/src/plugins/debugger/debuggercore.h
+++ b/src/plugins/debugger/debuggercore.h
@@ -110,8 +110,6 @@ DebuggerEngine *currentEngine();
QMessageBox *showMessageBox(int icon, const QString &title,
const QString &text, int buttons = 0);
-bool isNativeMixedActive();
-bool isNativeMixedEnabled();
bool isReverseDebuggingEnabled();
} // namespace Internal
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 6b242de2a6..2d5f14c0eb 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -78,6 +78,11 @@
#include <QFileInfo>
#include <QDir>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+
using namespace Core;
using namespace Debugger::Internal;
using namespace ProjectExplorer;
@@ -126,7 +131,7 @@ Location::Location(const StackFrame &frame, bool marker)
m_functionName = frame.function;
m_hasDebugInfo = frame.isUsable();
m_address = frame.address;
- m_from = frame.from;
+ m_from = frame.module;
}
@@ -192,7 +197,7 @@ public:
m_modulesHandler(engine),
m_registerHandler(engine),
m_sourceFilesHandler(),
- m_stackHandler(),
+ m_stackHandler(engine),
m_threadsHandler(),
m_watchHandler(engine),
m_disassemblerAgent(engine),
@@ -203,8 +208,6 @@ public:
this, &DebuggerEnginePrivate::resetLocation);
connect(action(IntelFlavor), &Utils::SavedAction::valueChanged,
this, &DebuggerEnginePrivate::reloadDisassembly);
- connect(action(OperateNativeMixed), &QAction::triggered,
- engine, &DebuggerEngine::reloadFullStack);
Utils::globalMacroExpander()->registerFileVariables(PrefixDebugExecutable,
tr("Debugged executable"),
@@ -2023,6 +2026,26 @@ void DebuggerEngine::checkState(DebuggerState state, const char *file, int line)
qDebug("%s", qPrintable(msg));
}
+bool DebuggerEngine::isNativeMixedEnabled() const
+{
+ return runParameters().nativeMixedEnabled && (runParameters().languages & QmlLanguage);
+}
+
+bool DebuggerEngine::isNativeMixedActive() const
+{
+ return isNativeMixedEnabled(); //&& boolSetting(OperateNativeMixed);
+}
+
+bool DebuggerEngine::isNativeMixedActiveFrame() const
+{
+ if (!isNativeMixedActive())
+ return false;
+ if (stackHandler()->frames().isEmpty())
+ return false;
+ StackFrame frame = stackHandler()->frameAt(0);
+ return frame.language == QmlLanguage;
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 15357a7221..b4edd5eeaa 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -117,6 +117,8 @@ public:
// Used by AttachCrashedExternal.
QString crashParameter;
+ bool nativeMixedEnabled = false;
+
// For Debugger testing.
int testCase = 0;
};
@@ -443,6 +445,9 @@ protected:
void updateLocalsView(const GdbMi &all);
void checkState(DebuggerState state, const char *file, int line);
+ bool isNativeMixedEnabled() const;
+ bool isNativeMixedActive() const;
+ bool isNativeMixedActiveFrame() const;
private:
// Wrapper engine needs access to state of its subengines.
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index bd7716ee9d..d644824e19 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -474,7 +474,6 @@ bool DummyEngine::hasCapability(unsigned cap) const
return cap & (WatchpointByAddressCapability
| BreakConditionCapability
| TracePointCapability
- | OperateNativeMixed
| OperateByInstructionCapability);
// This is a Qml or unknown engine.
@@ -2321,17 +2320,6 @@ QMessageBox *showMessageBox(int icon, const QString &title,
return mb;
}
-bool isNativeMixedEnabled()
-{
- static bool enabled = qEnvironmentVariableIsSet("QTC_DEBUGGER_NATIVE_MIXED");
- return enabled;
-}
-
-bool isNativeMixedActive()
-{
- return isNativeMixedEnabled() && boolSetting(OperateNativeMixed);
-}
-
bool isReverseDebuggingEnabled()
{
static bool enabled = qEnvironmentVariableIsSet("QTC_DEBUGGER_ENABLE_REVERSE");
@@ -2769,16 +2757,6 @@ void DebuggerPluginPrivate::extensionsInitialized()
cmd->setAttribute(Command::CA_Hide);
debugMenu->addAction(cmd);
- if (isNativeMixedEnabled()) {
- SavedAction *act = action(OperateNativeMixed);
- act->setValue(true);
- cmd = ActionManager::registerAction(act, Constants::OPERATE_NATIVE_MIXED);
- cmd->setAttribute(Command::CA_Hide);
- debugMenu->addAction(cmd);
- connect(cmd->action(), &QAction::triggered,
- [this] { currentEngine()->updateAll(); });
- }
-
cmd = ActionManager::registerAction(m_breakAction, "Debugger.ToggleBreak");
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("F8") : tr("F9")));
debugMenu->addAction(cmd);
@@ -2912,8 +2890,6 @@ void DebuggerPluginPrivate::extensionsInitialized()
hbox->addWidget(toolButton(Constants::STEPOUT));
hbox->addWidget(toolButton(Constants::RESET));
hbox->addWidget(toolButton(Constants::OPERATE_BY_INSTRUCTION));
- if (isNativeMixedEnabled())
- hbox->addWidget(toolButton(Constants::OPERATE_NATIVE_MIXED));
if (isReverseDebuggingEnabled()) {
m_reverseToolButton = toolButton(Constants::REVERSE);
diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp
index 651a8c1a2b..763c9477c6 100644
--- a/src/plugins/debugger/debuggerprotocol.cpp
+++ b/src/plugins/debugger/debuggerprotocol.cpp
@@ -80,7 +80,7 @@ void GdbMi::parseResultOrValue(const char *&from, const char *to)
if (from == to || *from == '(')
return;
const char *ptr = from;
- while (ptr < to && *ptr != '=') {
+ while (ptr < to && *ptr != '=' && *ptr != ':') {
//qDebug() << "adding" << QChar(*ptr) << "to name";
++ptr;
}
@@ -770,6 +770,12 @@ QString decodeData(const QByteArray &ba, DebuggerEncoding encoding)
case SpecialEmptyStructureValue: { // 39
return QLatin1String("{...}");
}
+ case SpecialUndefinedValue: { // 40
+ return QLatin1String("Undefined");
+ }
+ case SpecialNullValue: { // 41
+ return QLatin1String("Null");
+ }
}
qDebug() << "ENCODING ERROR: " << encoding;
return QCoreApplication::translate("Debugger", "<Encoding error>");
@@ -857,5 +863,22 @@ QByteArray DebuggerCommand::argsToString() const
return args.toString().toLatin1();
}
+DebuggerEncoding debuggerEncoding(const QByteArray &data)
+{
+ if (data == "utf16")
+ return Hex4EncodedLittleEndianWithQuotes;
+ if (data == "empty")
+ return SpecialEmptyValue;
+ if (data == "minimumitemcount")
+ return SpecialMinimumItemCountValue;
+ if (data == "undefined")
+ return SpecialUndefinedValue;
+ if (data == "null")
+ return SpecialNullValue;
+ if (data == "itemcount")
+ return SpecialItemCountValue;
+ return DebuggerEncoding(data.toInt());
+}
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h
index c8dc3a307d..a8006172ae 100644
--- a/src/plugins/debugger/debuggerprotocol.h
+++ b/src/plugins/debugger/debuggerprotocol.h
@@ -252,9 +252,13 @@ enum DebuggerEncoding
SpecialNotCallableValue = 36,
SpecialNullReferenceValue = 37,
SpecialOptimizedOutValue = 38,
- SpecialEmptyStructureValue = 39
+ SpecialEmptyStructureValue = 39,
+ SpecialUndefinedValue = 40,
+ SpecialNullValue = 41
};
+DebuggerEncoding debuggerEncoding(const QByteArray &data);
+
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, DebuggerEncoding encoding);
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index 9e4af8fd71..2c323a3b1e 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -59,6 +59,8 @@
#include <coreplugin/icore.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
+#include <qtsupport/qtkitinformation.h>
+
#include <QTcpServer>
using namespace Debugger::Internal;
@@ -416,6 +418,19 @@ void DebuggerRunControlCreator::enrich(const RunConfiguration *runConfig, const
if (m_project && m_rp.projectSourceFiles.isEmpty())
m_rp.projectSourceFiles = m_project->files(Project::ExcludeGeneratedFiles);
+ if (m_project && m_rp.projectSourceFiles.isEmpty())
+ m_rp.projectSourceFiles = m_project->files(Project::ExcludeGeneratedFiles);
+
+ if (false && m_project && m_kit) {
+ const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(m_kit);
+ m_rp.nativeMixedEnabled = version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 7, 0);
+ }
+
+ bool ok = false;
+ int nativeMixedOverride = qgetenv("QTC_DEBUGGER_NATIVE_MIXED").toInt(&ok);
+ if (ok)
+ m_rp.nativeMixedEnabled = bool(nativeMixedOverride);
+
// validate debugger if C++ debugging is enabled
if (m_rp.languages & CppLanguage) {
const QList<Task> tasks = DebuggerKitInformation::validateDebugger(m_kit);
@@ -482,9 +497,6 @@ void DebuggerRunControlCreator::enrich(const RunConfiguration *runConfig, const
const QString optimizerKey = _("QML_DISABLE_OPTIMIZER");
if (!m_rp.environment.hasKey(optimizerKey))
m_rp.environment.set(optimizerKey, _("1"));
-
- QtcProcess::addArg(&m_rp.processArgs, QmlDebug::qmlDebugCommandLineArguments(
- QmlDebug::QmlDebuggerServices, m_rp.qmlServerPort));
}
}
}
@@ -502,14 +514,23 @@ void DebuggerRunControlCreator::enrich(const RunConfiguration *runConfig, const
}
if (m_rp.masterEngineType == NoEngineType && m_debuggerAspect) {
- const bool useCppDebugger = m_debuggerAspect->useCppDebugger() && (m_rp.languages & CppLanguage);
- const bool useQmlDebugger = m_debuggerAspect->useQmlDebugger() && (m_rp.languages & QmlLanguage);
-
- if (useQmlDebugger) {
- if (useCppDebugger)
- m_rp.masterEngineType = QmlCppEngineType;
- else
+ const bool wantCppDebugger = m_debuggerAspect->useCppDebugger() && (m_rp.languages & CppLanguage);
+ const bool wantQmlDebugger = m_debuggerAspect->useQmlDebugger() && (m_rp.languages & QmlLanguage);
+
+ if (wantQmlDebugger) {
+ QString qmlArgs;
+ if (wantCppDebugger) {
+ if (m_rp.nativeMixedEnabled) {
+ qmlArgs = QmlDebug::qmlDebugCommandLineArguments(QmlDebug::QmlNativeDebuggerServices);
+ } else {
+ m_rp.masterEngineType = QmlCppEngineType;
+ qmlArgs = QmlDebug::qmlDebugCommandLineArguments(QmlDebug::QmlDebuggerServices, m_rp.qmlServerPort);
+ }
+ } else {
m_rp.masterEngineType = QmlEngineType;
+ qmlArgs = QmlDebug::qmlDebugCommandLineArguments(QmlDebug::QmlDebuggerServices, m_rp.qmlServerPort);
+ }
+ QtcProcess::addArg(&m_rp.processArgs, qmlArgs);
}
}
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index a3686221b2..5692a00245 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -625,6 +625,18 @@ void GdbEngine::handleResponse(const QByteArray &buff)
case '~': {
QByteArray data = GdbMi::parseCString(from, to);
+ if (data.startsWith("bridgemessage={")) {
+ //showMessage(_(data), LogDebug);
+ break;
+ }
+ if (data.startsWith("bridgeresult={")) {
+ //showMessage(_(data), LogDebug);
+ DebuggerResponse response;
+ response.resultClass = ResultDone;
+ response.data.fromStringMultiple(data);
+ handleResultRecord(&response);
+ break;
+ }
m_pendingConsoleStreamOutput += data;
// Parse pid from noise.
@@ -1369,9 +1381,13 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
int lineNumber = 0;
QString fullName;
QByteArray function;
+ QByteArray language;
if (frame.isValid()) {
const GdbMi lineNumberG = frame["line"];
- function = frame["func"].data();
+ function = frame["function"].data(); // V4 protocol
+ if (function.isEmpty())
+ function = frame["func"].data(); // GDB's *stopped messages
+ language = frame["language"].data();
if (lineNumberG.isValid()) {
lineNumber = lineNumberG.toInt();
fullName = cleanupFullName(QString::fromLocal8Bit(frame["fullname"].data()));
@@ -1384,9 +1400,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
if (rid.isValid() && frame.isValid() && !isQFatalBreakpoint(rid)) {
// Use opportunity to update the breakpoint marker position.
- //qDebug() << " PROBLEM: " << m_qmlBreakpointNumbers << rid
- // << isQmlStepBreakpoint1(rid)
- // << isQmlStepBreakpoint2(rid)
Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid);
const BreakpointResponse &response = bp.response();
QString fileName = response.fileName;
@@ -1403,7 +1416,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
if (lineNumber && !boolSetting(OperateByInstruction)
&& QFileInfo::exists(fullName)
&& !isQFatalBreakpoint(rid)
- && function != "qt_v4TriggeredBreakpointHook")
+ && function != "qt_v4TriggeredBreakpointHook"
+ && function != "qt_qmlDebugEventFromService"
+ && language != "js")
gotoLocation(Location(fullName, lineNumber));
if (state() == InferiorRunOk) {
@@ -1479,7 +1494,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
if (boolSetting(SkipKnownFrames)) {
if (reason == "end-stepping-range" || reason == "function-finished") {
//showMessage(frame.toString());
- QString funcName = _(frame["func"].data());
+ QString funcName = _(frame["function"].data());
QString fileName = QString::fromLocal8Bit(frame["file"].data());
if (isLeavableFunction(funcName, fileName)) {
//showMessage(_("LEAVING ") + funcName);
@@ -1978,9 +1993,15 @@ void GdbEngine::continueInferiorInternal()
notifyInferiorRunRequested();
showStatusMessage(tr("Running requested..."), 5000);
CHECK_STATE(InferiorRunRequested);
- DebuggerCommand cmd("-exec-continue", RunRequest);
- cmd.callback = CB(handleExecuteContinue);
- runCommand(cmd);
+ if (isNativeMixedActiveFrame()) {
+ DebuggerCommand cmd("executeContinue", RunRequest|PythonCommand);
+ cmd.callback = CB(handleExecuteContinue);
+ runCommand(cmd);
+ } else {
+ DebuggerCommand cmd("-exec-continue", RunRequest);
+ cmd.callback = CB(handleExecuteContinue);
+ runCommand(cmd);
+ }
}
void GdbEngine::continueInferior()
@@ -1996,10 +2017,10 @@ void GdbEngine::executeStep()
setTokenBarrier();
notifyInferiorRunRequested();
showStatusMessage(tr("Step requested..."), 5000);
- if (isNativeMixedActive()) {
- DebuggerCommand cmd("prepareQmlStep", PythonCommand);
+ if (isNativeMixedActiveFrame()) {
+ DebuggerCommand cmd("executeStep", RunRequest|PythonCommand);
+ cmd.callback = CB(handleExecuteStep);
runCommand(cmd);
- continueInferiorInternal();
} else {
DebuggerCommand cmd(isReverseDebugging() ? "reverse-step" : "-exec-step", RunRequest);
cmd.callback = CB(handleExecuteStep);
@@ -2061,12 +2082,17 @@ void GdbEngine::executeStepOut()
setTokenBarrier();
notifyInferiorRunRequested();
showStatusMessage(tr("Finish function requested..."), 5000);
- runCommand("-exec-finish", CB(handleExecuteContinue), RunRequest);
- // -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");
+ if (isNativeMixedActiveFrame()) {
+ DebuggerCommand cmd("executeStepOut", RunRequest|PythonCommand);
+ runCommand(cmd);
+ } else {
+ runCommand("-exec-finish", CB(handleExecuteContinue), RunRequest);
+ // -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");
+ }
}
void GdbEngine::executeNext()
@@ -2075,10 +2101,9 @@ void GdbEngine::executeNext()
setTokenBarrier();
notifyInferiorRunRequested();
showStatusMessage(tr("Step next requested..."), 5000);
- if (isNativeMixedActive()) {
- DebuggerCommand cmd("prepareQmlStep", PythonCommand);
+ if (isNativeMixedActiveFrame()) {
+ DebuggerCommand cmd("executeNext", RunRequest|PythonCommand);
runCommand(cmd);
- continueInferiorInternal();
} else {
DebuggerCommand cmd(isReverseDebugging() ? "reverse-next" : "-exec-next", RunRequest);
cmd.callback = CB(handleExecuteNext);
@@ -2656,10 +2681,9 @@ bool GdbEngine::acceptsBreakpoint(Breakpoint bp) const
{
if (runParameters().startMode == AttachCore)
return false;
- // We handle QML breakpoint unless specifically
- if (isNativeMixedEnabled() && !(runParameters().languages & QmlLanguage))
+ if (bp.parameters().isCppBreakpoint())
return true;
- return bp.parameters().isCppBreakpoint();
+ return isNativeMixedEnabled();
}
void GdbEngine::insertBreakpoint(Breakpoint bp)
@@ -2672,7 +2696,7 @@ void GdbEngine::insertBreakpoint(Breakpoint bp)
const BreakpointParameters &data = bp.parameters();
if (!data.isCppBreakpoint()) {
- DebuggerCommand cmd("insertQmlBreakpoint", PythonCommand);
+ DebuggerCommand cmd("insertInterpreterBreakpoint", PythonCommand);
bp.addToCommand(&cmd);
runCommand(cmd);
bp.notifyBreakpointInsertOk();
@@ -2791,7 +2815,7 @@ void GdbEngine::removeBreakpoint(Breakpoint bp)
const BreakpointParameters &data = bp.parameters();
if (!data.isCppBreakpoint()) {
- DebuggerCommand cmd("removeQmlBreakpoint", PythonCommand);
+ DebuggerCommand cmd("removeInterpreterBreakpoint", PythonCommand);
bp.addToCommand(&cmd);
runCommand(cmd);
bp.notifyBreakpointRemoveOk();
@@ -3140,13 +3164,11 @@ void GdbEngine::reloadFullStack()
runCommand(cmd);
}
-void GdbEngine::loadAdditionalQmlStack()
+static QString msgCannotLoadQmlStack(const QString &why)
{
- // Scan for QV4::ExecutionContext parameter in the parameter list of a V4 call.
- runCommand("-stack-list-arguments --simple-values", CB(handleQmlStackFrameArguments), NeedsStop);
+ return _("Unable to load QML stack: ") + why;
}
-// Scan the arguments of a stack list for the address of a QV4::ExecutionContext.
static quint64 findJsExecutionContextAddress(const GdbMi &stackArgsResponse, const QByteArray &qtNamespace)
{
const GdbMi frameList = stackArgsResponse.childAt(0);
@@ -3169,29 +3191,30 @@ static quint64 findJsExecutionContextAddress(const GdbMi &stackArgsResponse, con
return 0;
}
-static QString msgCannotLoadQmlStack(const QString &why)
-{
- return _("Unable to load QML stack: ") + why;
-}
-
-void GdbEngine::handleQmlStackFrameArguments(const DebuggerResponse &response)
+void GdbEngine::loadAdditionalQmlStack()
{
- if (!response.data.isValid()) {
- showMessage(msgCannotLoadQmlStack(_("No stack obtained.")), LogError);
- return;
- }
- const quint64 contextAddress = findJsExecutionContextAddress(response.data, qtNamespace());
- if (!contextAddress) {
- showMessage(msgCannotLoadQmlStack(_("The address of the JS execution context could not be found.")), LogError);
- 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);
+ // Scan for QV4::ExecutionContext parameter in the parameter list of a V4 call.
+ DebuggerCommand cmd("-stack-list-arguments --simple-values", NeedsStop);
+ cmd.callback = [this](const DebuggerResponse &response) {
+ if (!response.data.isValid()) {
+ showMessage(msgCannotLoadQmlStack(_("No stack obtained.")), LogError);
+ return;
+ }
+ const quint64 contextAddress = findJsExecutionContextAddress(response.data, qtNamespace());
+ if (!contextAddress) {
+ showMessage(msgCannotLoadQmlStack(_("The address of the JS execution context could not be found.")), LogError);
+ 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(cmd);
}
+// Scan the arguments of a stack list for the address of a QV4::ExecutionContext.
void GdbEngine::handleQmlStackTrace(const DebuggerResponse &response)
{
if (!response.data.isValid()) {
@@ -3216,11 +3239,8 @@ void GdbEngine::handleQmlStackTrace(const DebuggerResponse &response)
}
QList<StackFrame> qmlFrames;
qmlFrames.reserve(qmlFrameCount);
- for (int i = 0; i < qmlFrameCount; ++i) {
- StackFrame frame = parseStackFrame(stackMi.childAt(i), i);
- frame.fixQmlFrame(runParameters());
- qmlFrames.append(frame);
- }
+ for (int i = 0; i < qmlFrameCount; ++i)
+ qmlFrames.append(StackFrame::parseFrame(stackMi.childAt(i), runParameters()));
stackHandler()->prependFrames(qmlFrames);
}
@@ -3228,7 +3248,7 @@ DebuggerCommand GdbEngine::stackCommand(int depth)
{
DebuggerCommand cmd("stackListFrames");
cmd.arg("limit", depth);
- cmd.arg("options", isNativeMixedActive() ? "nativemixed" : "");
+ cmd.arg("nativemixed", isNativeMixedActive());
return cmd;
}
@@ -3241,35 +3261,6 @@ void GdbEngine::reloadStack()
runCommand(cmd);
}
-StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level)
-{
- //qDebug() << "HANDLING FRAME:" << frameMi.toString();
- StackFrame frame;
- frame.level = level;
- GdbMi fullName = frameMi["fullname"];
- if (fullName.isValid())
- frame.file = cleanupFullName(QFile::decodeName(fullName.data()));
- else
- frame.file = QFile::decodeName(frameMi["file"].data());
- frame.function = _(frameMi["func"].data());
- frame.from = _(frameMi["from"].data());
- frame.line = frameMi["line"].toInt();
- frame.address = frameMi["addr"].toAddress();
- GdbMi usable = frameMi["usable"];
- if (usable.isValid())
- frame.usable = usable.data().toInt();
- else
- frame.usable = QFileInfo(frame.file).isReadable();
- if (frameMi["language"].data() == "js"
- || frame.file.endsWith(QLatin1String(".js"))
- || frame.file.endsWith(QLatin1String(".qml"))) {
- frame.file = QFile::decodeName(frameMi["file"].data());
- frame.language = QmlLanguage;
- frame.fixQmlFrame(runParameters());
- }
- return frame;
-}
-
void GdbEngine::handleStackListFrames(const DebuggerResponse &response, bool isFull)
{
if (response.resultClass != ResultDone) {
@@ -3284,8 +3275,10 @@ void GdbEngine::handleStackListFrames(const DebuggerResponse &response, bool isF
QList<StackFrame> stackFrames;
GdbMi stack = response.data["stack"]; // C++
- if (!stack.isValid() || stack.childCount() == 0) // Mixed.
+ if (!stack.isValid() || stack.childCount() == 0) { // Mixed.
stack.fromStringMultiple(response.consoleStreamOutput);
+ stack = stack["frames"];
+ }
if (!stack.isValid()) {
qDebug() << "FIXME: stack:" << stack.toString();
@@ -3296,7 +3289,7 @@ void GdbEngine::handleStackListFrames(const DebuggerResponse &response, bool isF
int n = stack.childCount();
for (int i = 0; i != n; ++i) {
- stackFrames.append(parseStackFrame(stack.childAt(i), i));
+ stackFrames.append(StackFrame::parseFrame(stack.childAt(i), runParameters()));
const StackFrame &frame = stackFrames.back();
// Initialize top frame to the first valid frame.
@@ -3407,7 +3400,7 @@ void GdbEngine::handleThreadNames(const DebuggerResponse &response)
ThreadData thread;
thread.id = ThreadId(name["id"].toInt());
thread.name = decodeData(name["value"].data(),
- DebuggerEncoding(name["valueencoded"].toInt()));
+ debuggerEncoding(name["valueencoded"].data()));
handler->updateThread(thread);
}
updateViews();
@@ -4622,7 +4615,7 @@ void GdbEngine::doUpdateLocals(const UpdateParameters &params)
watchHandler()->notifyUpdateStarted(params.partialVariables());
- DebuggerCommand cmd("showData", Discardable | InUpdateLocals | PythonCommand);
+ DebuggerCommand cmd("fetchVariables", Discardable|InUpdateLocals|PythonCommand);
watchHandler()->appendFormatRequests(&cmd);
watchHandler()->appendWatchersAndTooltipRequests(&cmd);
@@ -4637,23 +4630,20 @@ void GdbEngine::doUpdateLocals(const UpdateParameters &params)
cmd.arg("dyntype", boolSetting(UseDynamicType));
cmd.arg("nativemixed", isNativeMixedActive());
- if (isNativeMixedActive()) {
- StackFrame frame = stackHandler()->currentFrame();
- if (frame.language == QmlLanguage)
- cmd.arg("qmlcontext", "0x" + QByteArray::number(frame.address, 16));
- }
+ StackFrame frame = stackHandler()->currentFrame();
+ cmd.arg("context", frame.context);
cmd.arg("resultvarname", m_resultVarName);
cmd.arg("partialVariable", params.partialVariable);
cmd.arg("sortStructMembers", boolSetting(SortStructMembers));
- cmd.callback = CB(handleStackFrame);
+ cmd.callback = CB(handleFetchVariables);
runCommand(cmd);
cmd.arg("passExceptions", true);
m_lastDebuggableCommand = cmd;
}
-void GdbEngine::handleStackFrame(const DebuggerResponse &response)
+void GdbEngine::handleFetchVariables(const DebuggerResponse &response)
{
m_inUpdateLocals = false;
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index cc4bc0b86c..70e2816404 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -216,7 +216,6 @@ protected:
void handleStop1(const GdbMi &data);
void handleStop2(const GdbMi &data);
Q_SLOT void handleStop2();
- StackFrame parseStackFrame(const GdbMi &mi, int level);
void resetCommandQueue();
bool isSynchronous() const override { return true; }
@@ -367,7 +366,6 @@ protected:
Q_SLOT void reloadStack();
Q_SLOT virtual void reloadFullStack() override;
virtual void loadAdditionalQmlStack() override;
- void handleQmlStackFrameArguments(const DebuggerResponse &response);
void handleQmlStackTrace(const DebuggerResponse &response);
int currentFrame() const;
@@ -399,7 +397,7 @@ protected:
Q_SLOT void createFullBacktrace();
void doUpdateLocals(const UpdateParameters &parameters) override;
- void handleStackFrame(const DebuggerResponse &response);
+ void handleFetchVariables(const DebuggerResponse &response);
void setLocals(const QList<GdbMi> &locals);
diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp
index 39a2936cc0..de99a107b3 100644
--- a/src/plugins/debugger/lldb/lldbengine.cpp
+++ b/src/plugins/debugger/lldb/lldbengine.cpp
@@ -537,7 +537,7 @@ void LldbEngine::selectThread(ThreadId threadId)
cmd.arg("id", threadId.raw());
cmd.callback = [this](const DebuggerResponse &) {
DebuggerCommand cmd("fetchStack");
- cmd.arg("nativeMixed", isNativeMixedActive());
+ cmd.arg("nativemixed", isNativeMixedActive());
cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
runCommand(cmd);
updateLocals();
@@ -563,10 +563,9 @@ bool LldbEngine::acceptsBreakpoint(Breakpoint bp) const
{
if (runParameters().startMode == AttachCore)
return false;
- // We handle QML breakpoint unless specifically disabled.
- if (isNativeMixedEnabled() && !(runParameters().languages & QmlLanguage))
+ if (bp.parameters().isCppBreakpoint())
return true;
- return bp.parameters().isCppBreakpoint();
+ return isNativeMixedEnabled();
}
void LldbEngine::insertBreakpoint(Breakpoint bp)
@@ -753,37 +752,12 @@ void LldbEngine::reloadFullStack()
void LldbEngine::fetchStack(int limit)
{
DebuggerCommand cmd("fetchStack");
- cmd.arg("nativeMixed", isNativeMixedActive());
+ cmd.arg("nativemixed", isNativeMixedActive());
cmd.arg("stacklimit", limit);
+ cmd.arg("context", stackHandler()->currentFrame().context);
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);
-
+ stackHandler()->setAllFrames(stack["frames"], stack["hasmore"].toInt());
updateLocals();
};
runCommand(cmd);
@@ -816,7 +790,7 @@ void LldbEngine::doUpdateLocals(const UpdateParameters &params)
watchHandler()->notifyUpdateStarted(params.partialVariables());
DebuggerCommand cmd("fetchLocals");
- cmd.arg("nativeMixed", isNativeMixedActive());
+ cmd.arg("nativemixed", isNativeMixedActive());
watchHandler()->appendFormatRequests(&cmd);
watchHandler()->appendWatchersAndTooltipRequests(&cmd);
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index 0adc23d058..7fa3801567 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -532,12 +532,12 @@ void PdbEngine::refreshStack(const GdbMi &stack)
StackFrames frames;
foreach (const GdbMi &item, stack["frames"].children()) {
StackFrame frame;
- frame.level = item["level"].toInt();
+ frame.level = item["level"].data();
frame.file = item["file"].toUtf8();
- frame.function = item["func"].toUtf8();
- frame.from = item["func"].toUtf8();
+ frame.function = item["function"].toUtf8();
+ frame.module = item["function"].toUtf8();
frame.line = item["line"].toInt();
- frame.address = item["addr"].toAddress();
+ frame.address = item["address"].toAddress();
GdbMi usable = item["usable"];
if (usable.isValid())
frame.usable = usable.data().toInt();
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index a91ae925be..5031575d29 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -2062,10 +2062,9 @@ void QmlEnginePrivate::handleBacktrace(const QVariantMap &response)
stackIndexLookup.clear();
foreach (const QVariant &frame, frames) {
StackFrame stackFrame = extractStackFrame(frame);
- if (stackFrame.level < 0)
+ if (stackFrame.level.isEmpty())
continue;
- stackIndexLookup.insert(i, stackFrame.level);
- stackFrame.level = i;
+ stackIndexLookup.insert(i, stackFrame.level.toInt());
stackFrames << stackFrame;
i++;
}
@@ -2111,10 +2110,10 @@ StackFrame QmlEnginePrivate::extractStackFrame(const QVariant &bodyVal)
const QVariantMap body = bodyVal.toMap();
StackFrame stackFrame;
- stackFrame.level = body.value(_("index")).toInt();
+ stackFrame.level = body.value(_("index")).toByteArray();
//Do not insert the frame corresponding to the internal function
if (body.value(QLatin1String("sourceLineText")) == QLatin1String(INTERNAL_FUNCTION)) {
- stackFrame.level = -1;
+ stackFrame.level.clear();
return stackFrame;
}
@@ -2129,7 +2128,7 @@ StackFrame QmlEnginePrivate::extractStackFrame(const QVariant &bodyVal)
stackFrame.usable = QFileInfo(stackFrame.file).isReadable();
objectData = extractData(body.value(_("receiver")));
- stackFrame.to = objectData.value.toString();
+ stackFrame.receiver = objectData.value.toString();
stackFrame.line = body.value(_("line")).toInt() + 1;
diff --git a/src/plugins/debugger/stackframe.cpp b/src/plugins/debugger/stackframe.cpp
index cc07c4406e..11fa1a99e5 100644
--- a/src/plugins/debugger/stackframe.cpp
+++ b/src/plugins/debugger/stackframe.cpp
@@ -31,6 +31,7 @@
#include "stackframe.h"
#include "debuggerengine.h"
+#include "debuggerprotocol.h"
#include "watchutils.h"
#include <QDebug>
@@ -49,16 +50,16 @@ namespace Internal {
////////////////////////////////////////////////////////////////////////
StackFrame::StackFrame()
- : language(CppLanguage), level(-1), line(-1), address(0), usable(false)
+ : language(CppLanguage), line(-1), address(0), usable(false)
{}
void StackFrame::clear()
{
- line = level = -1;
+ line = -1;
function.clear();
file.clear();
- from.clear();
- to.clear();
+ module.clear();
+ receiver.clear();
address = 0;
}
@@ -79,11 +80,44 @@ QString StackFrame::toString() const
<< tr("Function:") << ' ' << function << ' '
<< tr("File:") << ' ' << file << ' '
<< tr("Line:") << ' ' << line << ' '
- << tr("From:") << ' ' << from << ' '
- << tr("To:") << ' ' << to;
+ << tr("From:") << ' ' << module << ' '
+ << tr("To:") << ' ' << receiver;
return res;
}
+QList<StackFrame> StackFrame::parseFrames(const GdbMi &data, const DebuggerRunParameters &rp)
+{
+ StackFrames frames;
+ frames.reserve(data.children().size());
+ foreach (const GdbMi &item, data.children())
+ frames.append(parseFrame(item, rp));
+ return frames;
+}
+
+StackFrame StackFrame::parseFrame(const GdbMi &frameMi, const DebuggerRunParameters &rp)
+{
+ StackFrame frame;
+ frame.level = frameMi["level"].data();
+ frame.function = frameMi["function"].toUtf8();
+ frame.module = frameMi["module"].toUtf8();
+ frame.file = QFile::decodeName(frameMi["file"].data());
+ frame.line = frameMi["line"].toInt();
+ frame.address = frameMi["address"].toAddress();
+ frame.context = frameMi["context"].data();
+ if (frameMi["language"].data() == "js"
+ || frame.file.endsWith(QLatin1String(".js"))
+ || frame.file.endsWith(QLatin1String(".qml"))) {
+ frame.language = QmlLanguage;
+ frame.fixQrcFrame(rp);
+ }
+ GdbMi usable = frameMi["usable"];
+ if (usable.isValid())
+ frame.usable = usable.data().toInt();
+ else
+ frame.usable = QFileInfo(frame.file).isReadable();
+ return frame;
+}
+
QString StackFrame::toToolTip() const
{
const QString filePath = QDir::toNativeSeparators(file);
@@ -101,10 +135,10 @@ QString StackFrame::toToolTip() const
str << "<tr><td>" << tr("File:") << "</td><td>" << filePath << "</td></tr>";
if (line != -1)
str << "<tr><td>" << tr("Line:") << "</td><td>" << line << "</td></tr>";
- if (!from.isEmpty())
- str << "<tr><td>" << tr("From:") << "</td><td>" << from << "</td></tr>";
- if (!to.isEmpty())
- str << "<tr><td>" << tr("To:") << "</td><td>" << to << "</td></tr>";
+ if (!module.isEmpty())
+ str << "<tr><td>" << tr("Module:") << "</td><td>" << module << "</td></tr>";
+ if (!receiver.isEmpty())
+ str << "<tr><td>" << tr("Receiver:") << "</td><td>" << receiver << "</td></tr>";
str << "</table>";
str <<"<br> <br><i>" << tr("Note:") << " </i> ";
@@ -133,8 +167,8 @@ QString StackFrame::toToolTip() const
return res;
}
-// Try to resolve files of a QML stack (resource files).
-void StackFrame::fixQmlFrame(const DebuggerRunParameters &rp)
+// Try to resolve files coming from resource files.
+void StackFrame::fixQrcFrame(const DebuggerRunParameters &rp)
{
if (language != QmlLanguage)
return;
@@ -146,19 +180,19 @@ void StackFrame::fixQmlFrame(const DebuggerRunParameters &rp)
if (!file.startsWith(QLatin1String("qrc:/")))
return;
const QString relativeFile = file.right(file.size() - 5);
- if (!rp.projectSourceDirectory.isEmpty()) {
- const QFileInfo pFi(rp.projectSourceDirectory + QLatin1Char('/') + relativeFile);
- if (pFi.isFile()) {
- file = pFi.absoluteFilePath();
- usable = true;
- return;
- }
- const QFileInfo cFi(QDir::currentPath() + QLatin1Char('/') + relativeFile);
- if (cFi.isFile()) {
- file = cFi.absoluteFilePath();
- usable = true;
- return;
- }
+ if (rp.projectSourceDirectory.isEmpty())
+ return;
+ const QFileInfo pFi(rp.projectSourceDirectory + QLatin1Char('/') + relativeFile);
+ if (pFi.isFile()) {
+ file = pFi.absoluteFilePath();
+ usable = true;
+ return;
+ }
+ const QFileInfo cFi(QDir::currentPath() + QLatin1Char('/') + relativeFile);
+ if (cFi.isFile()) {
+ file = cFi.absoluteFilePath();
+ usable = true;
+ return;
}
}
@@ -171,10 +205,10 @@ QDebug operator<<(QDebug d, const StackFrame &f)
str << ' ' << f.function;
if (!f.file.isEmpty())
str << ' ' << f.file << ':' << f.line;
- if (!f.from.isEmpty())
- str << " from=" << f.from;
- if (!f.to.isEmpty())
- str << " to=" << f.to;
+ if (!f.module.isEmpty())
+ str << " from=" << f.module;
+ if (!f.receiver.isEmpty())
+ str << " to=" << f.receiver;
d.nospace() << res;
return d;
}
diff --git a/src/plugins/debugger/stackframe.h b/src/plugins/debugger/stackframe.h
index 8d29f3f004..b9b23dfced 100644
--- a/src/plugins/debugger/stackframe.h
+++ b/src/plugins/debugger/stackframe.h
@@ -44,6 +44,7 @@ namespace Debugger {
namespace Internal {
class DebuggerRunParameters;
+class GdbMi;
class StackFrame
{
@@ -53,24 +54,25 @@ public:
bool isUsable() const;
QString toToolTip() const;
QString toString() const;
- void fixQmlFrame(const DebuggerRunParameters &rp);
+ static StackFrame parseFrame(const GdbMi &data, const DebuggerRunParameters &rp);
+ static QList<StackFrame> parseFrames(const GdbMi &data, const DebuggerRunParameters &rp);
+ void fixQrcFrame(const DebuggerRunParameters &rp);
public:
DebuggerLanguage language;
- qint32 level;
+ QByteArray level;
QString function;
- QString file; // We try to put an absolute file name in there.
- QString from; // Sometimes something like "/usr/lib/libstdc++.so.6"
- QString to; // Used in ScriptEngine only.
+ QString file; // We try to put an absolute file name in there.
+ QString module; // Sometimes something like "/usr/lib/libstdc++.so.6"
+ QString receiver; // Used in ScriptEngine only.
qint32 line;
quint64 address;
bool usable;
+ QByteArray context; // Opaque value produced and consumed by the native backends.
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::StackHandler)
};
-QDebug operator<<(QDebug d, const StackFrame &frame);
-
typedef QList<StackFrame> StackFrames;
} // namespace Internal
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index ec5fe96641..39bbae9a20 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -32,6 +32,7 @@
#include "debuggeractions.h"
#include "debuggercore.h"
+#include "debuggerengine.h"
#include "simplifytype.h"
#include <utils/fileutils.h>
@@ -55,8 +56,9 @@ namespace Internal {
QTreeView.
*/
-StackHandler::StackHandler()
- : m_positionIcon(QIcon(QLatin1String(":/debugger/images/location_16.png"))),
+StackHandler::StackHandler(DebuggerEngine *engine)
+ : m_engine(engine),
+ m_positionIcon(QIcon(QLatin1String(":/debugger/images/location_16.png"))),
m_emptyIcon(QIcon(QLatin1String(":/debugger/images/debugger_empty_14.png")))
{
setObjectName(QLatin1String("StackModel"));
@@ -103,11 +105,11 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) {
switch (index.column()) {
case StackLevelColumn:
- return QString::number(frame.level);
+ return QString::number(index.row() + 1);
case StackFunctionNameColumn:
return simplifyType(frame.function);
case StackFileNameColumn:
- return frame.file.isEmpty() ? frame.from : Utils::FileName::fromString(frame.file).fileName();
+ return frame.file.isEmpty() ? frame.module : Utils::FileName::fromString(frame.file).fileName();
case StackLineNumberColumn:
return frame.line > 0 ? QVariant(frame.line) : QVariant();
case StackAddressColumn:
@@ -166,6 +168,12 @@ StackFrame StackHandler::currentFrame() const
return m_stackFrames.at(m_currentIndex);
}
+void StackHandler::setAllFrames(const GdbMi &frames, bool canExpand)
+{
+ action(ExpandStack)->setEnabled(canExpand);
+ setFrames(StackFrame::parseFrames(frames, m_engine->runParameters()), canExpand);
+}
+
void StackHandler::setCurrentIndex(int level)
{
if (level == -1 || level == m_currentIndex)
diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h
index 0713042dc1..3607eb7d6c 100644
--- a/src/plugins/debugger/stackhandler.h
+++ b/src/plugins/debugger/stackhandler.h
@@ -38,6 +38,8 @@
namespace Debugger {
namespace Internal {
+class DebuggerEngine;
+
enum StackColumns
{
StackLevelColumn,
@@ -48,18 +50,12 @@ enum StackColumns
StackColumnCount
};
-////////////////////////////////////////////////////////////////////////
-//
-// StackModel
-//
-////////////////////////////////////////////////////////////////////////
-
class StackHandler : public QAbstractTableModel
{
Q_OBJECT
public:
- StackHandler();
+ explicit StackHandler(DebuggerEngine *engine);
~StackHandler();
void setFrames(const StackFrames &frames, bool canExpand = false);
@@ -72,6 +68,7 @@ public:
const StackFrame &frameAt(int index) const { return m_stackFrames.at(index); }
int stackSize() const { return m_stackFrames.size(); }
quint64 topAddress() const { return m_stackFrames.at(0).address; }
+ void setAllFrames(const GdbMi &frames, bool canExpand);
// Called from StackHandler after a new stack list has been received
void removeAll();
@@ -93,6 +90,7 @@ private:
Qt::ItemFlags flags(const QModelIndex &index) const;
Q_SLOT void resetModel() { beginResetModel(); endResetModel(); }
+ DebuggerEngine *m_engine;
StackFrames m_stackFrames;
int m_currentIndex;
const QVariant m_positionIcon;
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index cf07816ae5..b6654c466b 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -108,7 +108,7 @@ static inline StackFrame inputFunctionForDisassembly()
return frame;
const int bangPos = function.indexOf(QLatin1Char('!'));
if (bangPos != -1) {
- frame.from = function.left(bangPos);
+ frame.module = function.left(bangPos);
frame.function = function.mid(bangPos + 1);
} else {
frame.function = function;
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index bab3546552..188fe5cd82 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -392,8 +392,8 @@ void WatchData::updateValue(const GdbMi &item)
{
GdbMi value = item["value"];
if (value.isValid()) {
- int encoding = item["valueencoded"].toInt();
- setValue(decodeData(value.data(), DebuggerEncoding(encoding)));
+ DebuggerEncoding encoding = debuggerEncoding(item["valueencoded"].data());
+ setValue(decodeData(value.data(), encoding));
} else {
setValueNeeded();
}