From fd3d7de92c9388781d0007ed2644ac22b7dbc652 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 19 Jan 2011 14:34:25 +0100 Subject: [PATCH] debugger: implement qml->c++ cross-stepping --- src/plugins/debugger/debuggerengine.h | 4 +- .../debugger/gdb/abstractplaingdbadapter.cpp | 80 +------------------ .../debugger/gdb/abstractplaingdbadapter.h | 2 - src/plugins/debugger/gdb/gdbengine.cpp | 37 ++++++--- src/plugins/debugger/gdb/gdbengine.h | 6 +- src/plugins/debugger/qml/qmlcppengine.cpp | 10 +-- src/plugins/debugger/qml/qmlcppengine.h | 2 +- 7 files changed, 40 insertions(+), 101 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 3b320586625..3c143aad635 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -244,8 +244,8 @@ public: bool isMasterEngine() const; DebuggerEngine *masterEngine() const; - virtual bool prepareForQmlBreak(bool /*on*/) { return false; } - virtual void handlePrepareForQmlBreak() {} + virtual bool setupQmlStep(bool /*on*/) { return false; } + virtual void readyToExecuteQmlStep() {} signals: void stateChanged(const DebuggerState &state); diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp index ab09626db01..6b1575819ba 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp @@ -80,10 +80,6 @@ void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &respon if (m_engine->m_gdbVersion < 70000) m_engine->postCommand("info target", CB(handleInfoTarget)); } - //if (m_engine->isSlaveEngine()) - //m_engine->postCommand("qmlb", GdbEngine::ConsoleCommand); - //m_engine->postCommand("rbreak QScript::FunctionWrapper::proxyCall"); - // m_engine->postCommand("-break-insert -f 'myns::QScript::FunctionWrapper::proxyCall'"); m_engine->handleInferiorPrepared(); } else { QByteArray ba = response.data.findChild("msg").data(); @@ -105,15 +101,15 @@ void AbstractPlainGdbAdapter::runEngine() fileName = symbols.fileName(); } m_engine->postCommand("maint print msymbols " + fileName.toLocal8Bit(), - CB(handleNamespaceExtraction1), fileName); - //m_engine->postCommand("print QString", CB(handleNamespaceExtraction)); + CB(handleNamespaceExtraction), fileName); } -void AbstractPlainGdbAdapter::handleNamespaceExtraction1(const GdbResponse &response) +void AbstractPlainGdbAdapter::handleNamespaceExtraction(const GdbResponse &response) { QFile file(response.cookie.toString()); file.open(QIODevice::ReadOnly); QByteArray ba = file.readAll(); + file.remove(); int pos = ba.indexOf("7QString9fromAscii"); int pos1 = pos - 1; while (pos1 > 0 && ba.at(pos1) != 'N' && ba.at(pos1) > '@') @@ -122,75 +118,7 @@ void AbstractPlainGdbAdapter::handleNamespaceExtraction1(const GdbResponse &resp const QByteArray ns = ba.mid(pos1, pos - pos1); if (!ns.isEmpty()) m_engine->setQtNamespace(ns + "::"); - if (m_engine->isSlaveEngine()) { - for (int i = 1; i <= 8; ++i) { - m_engine->postCommand("-break-insert -f '" + m_engine->qtNamespace() - + "QScript::qScriptBreaker" + QByteArray::number(i) + "'", - CB(handleFindScriptBreaker), i); - } - } else { - doRunEngine(); - } - file.remove(); -} - -void AbstractPlainGdbAdapter::handleNamespaceExtraction(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - // $1 = {void (myns::QString * const, const char *)} 0x8058e2c "} - const QByteArray ba = response.data.findChild("consolestreamoutput").data(); - const int posQString = ba.indexOf("QString"); - const int posNs = ba.lastIndexOf('(', posQString) + 1; - const QByteArray ns = ba.mid(posNs, posQString - posNs); - if (!ns.isEmpty()) - m_engine->setQtNamespace(ns); - } - if (m_engine->isSlaveEngine()) { - for (int i = 1; i <= 8; ++i) { - m_engine->postCommand("-break-insert -f '" + m_engine->qtNamespace() - + "QScript::qScriptBreaker" + QByteArray::number(i) + "'", - CB(handleFindScriptBreaker), i); - } - } else { - doRunEngine(); - } -} - -void AbstractPlainGdbAdapter::handleFindScriptBreaker(const GdbResponse &response) -{ - //QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); - if (response.resultClass == GdbResultDone) { - const int qmlBpType = response.cookie.toInt(); - // 20^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y", - // addr="",pending="'myns::QScript::qScriptBreaker'" - const GdbMi bkpt = response.data.findChild("bkpt"); - const GdbMi number = bkpt.findChild("number"); - const int bpnr = number.data().toInt(); - m_engine->addQmlBreakpointNumber(qmlBpType, bpnr); - //m_engine->postCommand("disable " + number.data()); - switch (qmlBpType) { - case 5: - m_engine->postCommand("enable " + number.data()); - m_engine->postCommand("command " + number.data() + - //"\necho \"STEP NOW\"\nfinish\nend") - "\nup" - "\necho \"YYY\"" - "\ntbreak" - "\ncommands" - "\necho \"XXX\"" - "\nstep" - "\nend" - "\ncontinue" - "\nend"); - break; - default: - //m_engine->postCommand("command " + number.data() + - // "\nfinish\nend"); - break; - } - } - if (response.cookie.toInt() == 8) - doRunEngine(); + doRunEngine(); } void AbstractPlainGdbAdapter::doRunEngine() diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.h b/src/plugins/debugger/gdb/abstractplaingdbadapter.h index 084e9739fde..94847392300 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.h +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.h @@ -53,7 +53,6 @@ public: protected: void handleInfoTarget(const GdbResponse &response); void handleNamespaceExtraction(const GdbResponse &response); - void handleNamespaceExtraction1(const GdbResponse &response); private: virtual QByteArray execFilePath() const = 0; @@ -62,7 +61,6 @@ private: virtual QString fromLocalEncoding(const QByteArray &ba) const = 0; void handleExecRun(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response); - void handleFindScriptBreaker(const GdbResponse &response); void doRunEngine(); }; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 50a5ed23f91..3eebb5d58d2 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1178,7 +1178,10 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (fullName.isEmpty()) fullName = QString::fromUtf8(frame.findChild("file").data()); - if (bkptno && frame.isValid()) { + const bool isSpecialQmlBreakpoint = + m_qmlBreakpointNumbers.keys().contains(bkptno); + + if (bkptno && frame.isValid() && !isSpecialQmlBreakpoint) { // Use opportunity to update the breakpoint marker position. BreakHandler *handler = breakHandler(); BreakpointId id = handler->findBreakpointByNumber(bkptno); @@ -1194,7 +1197,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) // Quickly set the location marker. if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction) - && QFileInfo(fullName).exists()) + && QFileInfo(fullName).exists() && !isSpecialQmlBreakpoint) gotoLocation(Location(fullName, lineNumber)); if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { @@ -1263,6 +1266,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data) } */ + if (isSpecialQmlBreakpoint) + return; + handleStop0(data); } @@ -4534,27 +4540,36 @@ void GdbEngine::handleRemoteSetupFailed(const QString &message) m_gdbAdapter->handleRemoteSetupFailed(message); } -bool GdbEngine::prepareForQmlBreak(bool on) +bool GdbEngine::setupQmlStep(bool on) { QTC_ASSERT(isSlaveEngine(), return false); + Q_UNUSED(on); + postCommand("tbreak '" + qtNamespace() + "QScript::FunctionWrapper::proxyCall'\n" + "commands\n" + "set $d=(void*)((FunctionWrapper*)callee)->data->function\n" + "tbreak *$d\ncontinue\nend", + NeedsStop, CB(handleSetQmlStepBreakpoint)); m_preparedForQmlBreak = on; return true; } -void GdbEngine::handleQmlBreakpoint(const GdbResponse &response) +void GdbEngine::handleSetQmlStepBreakpoint(const GdbResponse &response) { + //QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); if (response.resultClass == GdbResultDone) { - qDebug() << "RESPONSE: " << response.toString(); + // 20^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y", + // addr="",pending="'myns::QScript::qScriptBreaker'"} + const GdbMi bkpt = response.data.findChild("bkpt"); + const GdbMi number = bkpt.findChild("number"); + const int bpnr = number.data().toInt(); + m_qmlBreakpointNumbers[1] = bpnr; + //postCommand("disable " + number.data()); + //postCommand("enable " + number.data()); } QTC_ASSERT(masterEngine(), return); - masterEngine()->handlePrepareForQmlBreak(); + masterEngine()->readyToExecuteQmlStep(); } -void GdbEngine::addQmlBreakpointNumber(int type, int nr) -{ - qDebug() << "ADD SPECIAL QML BREAKPOINT, TYPE: " << type << "NR: " << nr; - m_qmlBreakpointNumbers[type] = nr; -} // // Factory diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index fab42f61064..49ebd585779 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -553,12 +553,10 @@ private: ////////// View & Data Stuff ////////// // // Qml // - void addQmlBreakpointNumber(int type /* 1-8 */, int nr); QHash m_qmlBreakpointNumbers; bool m_preparedForQmlBreak; - bool prepareForQmlBreak(bool on); - void handleQmlBreakpoint(const GdbResponse &response); - + bool setupQmlStep(bool on); + void handleSetQmlStepBreakpoint(const GdbResponse &response); // HACK: StackFrame m_targetFrame; diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index c3c7177bbcf..7257a936831 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -220,16 +220,16 @@ void QmlCppEngine::executeStep() { if (d->m_activeEngine == d->m_qmlEngine) { QTC_ASSERT(d->m_cppEngine->state() == InferiorRunOk, /**/); - d->m_cppEngine->prepareForQmlBreak(true); + if (d->m_cppEngine->setupQmlStep(true)) + return; // Wait for callback to readyToExecuteQmlStep() } - notifyInferiorRunRequested(); - d->m_activeEngine->executeStep(); + readyToExecuteQmlStep(); } -void QmlCppEngine::handlePrepareForQmlBreak() +void QmlCppEngine::readyToExecuteQmlStep() { notifyInferiorRunRequested(); - d->m_activeEngine->executeStep(); + d->m_qmlEngine->executeStep(); } void QmlCppEngine::executeStepOut() diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index f538da03bee..a3e652edf94 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -94,7 +94,7 @@ private: void setState(DebuggerState newState, bool forced = false); void slaveEngineStateChanged(DebuggerEngine *slaveEngine, DebuggerState state); - virtual void handlePrepareForQmlBreak(); + void readyToExecuteQmlStep(); private: QScopedPointer d;