From 8cc94d10a2aa1b9949ac0fd4c2fbed05376cec68 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 30 Sep 2009 17:13:52 +0200 Subject: [PATCH] CDB: Implement "Run to line/function", fix step by instruction. Remove unused exec functions, replace by calls to the respective stepExec/nextExec, which sets the code level automagically according to the OperateByInstruction action. --- src/plugins/debugger/cdb/cdbbreakpoint.cpp | 33 +++-- src/plugins/debugger/cdb/cdbbreakpoint.h | 5 +- src/plugins/debugger/cdb/cdbdebugengine.cpp | 154 ++++++++++++-------- src/plugins/debugger/cdb/cdbdebugengine_p.h | 1 + 4 files changed, 116 insertions(+), 77 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index e5433741cf8..40bec69fae0 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -179,12 +179,15 @@ static inline QString msgCannotAddBreakPoint(const QString &why) } bool CDBBreakPoint::add(CIDebugControl* debugControl, - quint64 *address, unsigned long *id, - QString *errorMessage) const + QString *errorMessage, + unsigned long *id, + quint64 *address) const { IDebugBreakpoint2* ibp = 0; - *address = 0; - *id = 0; + if (address) + *address = 0; + if (id) + *id = 0; HRESULT hr = debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &ibp); if (FAILED(hr)) { *errorMessage = msgCannotAddBreakPoint(msgComFailed("AddBreakpoint2", hr)); @@ -196,14 +199,18 @@ bool CDBBreakPoint::add(CIDebugControl* debugControl, } if (!apply(ibp, errorMessage)) return false; - // GetOffset can fail when attaching to remote processes. - hr = ibp->GetOffset(address); - if (FAILED(hr)) - *address = 0; - hr = ibp->GetId(id); - if (FAILED(hr)) { - *errorMessage = msgCannotAddBreakPoint(msgComFailed("GetId", hr)); - return false; + // GetOffset can fail when attaching to remote processes, ignore return + if (address) { + hr = ibp->GetOffset(address); + if (FAILED(hr)) + *address = 0; + } + if (id) { + hr = ibp->GetId(id); + if (FAILED(hr)) { + *errorMessage = msgCannotAddBreakPoint(msgComFailed("GetId", hr)); + return false; + } } return true; } @@ -458,7 +465,7 @@ bool CDBBreakPoint::synchronizeBreakPoints(CIDebugControl* debugControl, quint64 address; unsigned long id; CDBBreakPoint ncdbbp(*nbd); - breakPointOk = ncdbbp.add(debugControl, &address, &id, &warning); + breakPointOk = ncdbbp.add(debugControl, &warning, &id, &address); if (breakPointOk) { if (debugBP) qDebug() << "Added " << id << " at " << address << ncdbbp; diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.h b/src/plugins/debugger/cdb/cdbbreakpoint.h index 4b8f8567c14..7b1379617e5 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.h +++ b/src/plugins/debugger/cdb/cdbbreakpoint.h @@ -63,7 +63,10 @@ struct CDBBreakPoint // Apply parameters bool apply(IDebugBreakpoint2 *ibp, QString *errorMessage) const; // Convenience to add to a IDebugControl4 - bool add(CIDebugControl* debugControl, quint64 *address, unsigned long *id, QString *errorMessage) const; + bool add(CIDebugControl* debugControl, + QString *errorMessage, + unsigned long *id = 0, + quint64 *address = 0) const; // Retrieve/parse breakpoints from the interfaces bool retrieve(IDebugBreakpoint2 *ibp, QString *errorMessage); diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 834ce2c18b7..d020447d713 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -943,8 +943,31 @@ void CdbDebugEngine::updateWatchData(const WatchData &incomplete) qDebug() << *manager()->watchHandler()->model(LocalsWatch); } +// Continue inferior with a debugger command, such as "p", "pt" +// or its thread variations +bool CdbDebugEnginePrivate::executeContinueCommand(const QString &command) +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << command; + clearForRun(); + setCodeLevel(); // Step by instruction + m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); + manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Continuing with '%1'...").arg(command)); + QString errorMessage; + const bool success = CdbDebugEnginePrivate::executeDebuggerCommand(m_cif.debugControl, command, &errorMessage); + if (success) { + m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); + m_engine->startWatchTimer(); + } else { + m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); + m_engine->warning(CdbDebugEngine::tr("Unable to continue: %1").arg(errorMessage)); + } + return success; +} + void CdbDebugEngine::stepExec() { + // Step into if (debugCDB) qDebug() << Q_FUNC_INFO; @@ -964,55 +987,57 @@ void CdbDebugEngine::stepExec() void CdbDebugEngine::stepOutExec() { - if (debugCDB) - qDebug() << Q_FUNC_INFO; + if (debugCDB) + qDebug() << Q_FUNC_INFO; + // emulate gdb 'exec-finish' (exec until return of current function) + // by running up to address of the above stack frame (mostly works). + const StackHandler* sh = manager()->stackHandler(); + const int idx = sh->currentIndex() + 1; + const QList stackframes = sh->frames(); + if (idx < 0 || idx >= stackframes.size()) { + warning(QString::fromLatin1("Cannot step out of stack frame %1.").arg(idx)); + return; + } + // Set a temporary breakpoint and continue + const StackFrame& frame = stackframes.at(idx); + bool success = false; + QString errorMessage; + do { + const ULONG64 address = frame.address.toULongLong(&success, 16); + if (!success) { + errorMessage = QLatin1String("Cannot obtain address from stack frame"); + break; + } + manager()->showDebuggerOutput(LogMisc, tr("Running to 0x%1...").arg(address, 0, 16)); + IDebugBreakpoint2* pBP; + HRESULT hr = m_d->m_cif.debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP); + if (FAILED(hr) || !pBP) { + errorMessage = QString::fromLatin1("Cannot create temporary breakpoint: %1").arg(msgDebugEngineComResult(hr)); + break; + } - StackHandler* sh = manager()->stackHandler(); - const int idx = sh->currentIndex() + 1; - QList stackframes = sh->frames(); - if (idx < 0 || idx >= stackframes.size()) { - warning(QString::fromLatin1("Cannot step out of stack frame %1").arg(idx)); - return; - } - - // Set a temporary breakpoint and continue - const StackFrame& frame = stackframes.at(idx); - bool success = false; - QString errorMessage; - do { - const ULONG64 address = frame.address.toULongLong(&success, 16); - if (!success) { - errorMessage = QLatin1String("Cannot obtain address from stack frame"); - break; - } - - IDebugBreakpoint2* pBP; - HRESULT hr = m_d->m_cif.debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP); - if (FAILED(hr) || !pBP) { - errorMessage = QString::fromLatin1("Cannot create temporary breakpoint: %1").arg(msgDebugEngineComResult(hr)); - break; - } - - pBP->SetOffset(address); - pBP->AddFlags(DEBUG_BREAKPOINT_ENABLED); - pBP->AddFlags(DEBUG_BREAKPOINT_ONE_SHOT); - if (!m_d->continueInferior(&errorMessage)) - break; - success = true; - } while (false); - if (!success) - warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); + pBP->SetOffset(address); + pBP->AddFlags(DEBUG_BREAKPOINT_ENABLED); + pBP->AddFlags(DEBUG_BREAKPOINT_ONE_SHOT); + if (!m_d->continueInferior(&errorMessage)) + break; + success = true; + } while (false); + if (!success) + warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); } void CdbDebugEngine::nextExec() { + // Step over if (debugCDB) qDebug() << Q_FUNC_INFO; - m_d->clearForRun(); - m_d->setCodeLevel(); + m_d->setCodeLevel(); // Step by instruction setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); + // To control threads, use: + // -- const HRESULT hr = m_d->m_cif.debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "~* p", 0); if (SUCCEEDED(hr)) { setState(InferiorRunning, Q_FUNC_INFO, __LINE__); startWatchTimer(); @@ -1023,26 +1048,14 @@ void CdbDebugEngine::nextExec() } void CdbDebugEngine::stepIExec() -{ - warning(QString::fromLatin1("CdbDebugEngine::stepIExec() not implemented")); +{ + // Step by instruction + nextExec(); } void CdbDebugEngine::nextIExec() { - if (debugCDB) - qDebug() << Q_FUNC_INFO; - - m_d->clearForRun(); - m_d->setCodeLevel(); - setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); - const HRESULT hr = m_d->m_cif.debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); - if (SUCCEEDED(hr)) { - setState(InferiorRunning, Q_FUNC_INFO, __LINE__); - startWatchTimer(); - } else { - setState(InferiorStopped, Q_FUNC_INFO, __LINE__); - warning(msgFunctionFailed(Q_FUNC_INFO, msgDebugEngineComResult(hr))); - } + nextExec(); } void CdbDebugEngine::continueInferior() @@ -1148,20 +1161,34 @@ void CdbDebugEngine::interruptInferior() void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber) { - if (debugCDB) - qDebug() << Q_FUNC_INFO << fileName << lineNumber; + manager()->showDebuggerOutput(LogMisc, tr("Running up to %1:%2...").arg(fileName).arg(lineNumber)); + QString errorMessage; + CDBBreakPoint tempBreakPoint; + tempBreakPoint.fileName = fileName; + tempBreakPoint.lineNumber = lineNumber; + tempBreakPoint.oneShot = true; + const bool ok = tempBreakPoint.add(m_d->m_cif.debugControl, &errorMessage) + && m_d->continueInferior(&errorMessage); + if (!ok) + warning(errorMessage); } void CdbDebugEngine::runToFunctionExec(const QString &functionName) { - if (debugCDB) - qDebug() << Q_FUNC_INFO << functionName; + manager()->showDebuggerOutput(LogMisc, tr("Running up to function '%1()'...").arg(functionName)); + QString errorMessage; + CDBBreakPoint tempBreakPoint; + tempBreakPoint.funcName = functionName; + tempBreakPoint.oneShot = true; + const bool ok = tempBreakPoint.add(m_d->m_cif.debugControl, &errorMessage) + && m_d->continueInferior(&errorMessage); + if (!ok) + warning(errorMessage); } -void CdbDebugEngine::jumpToLineExec(const QString &fileName, int lineNumber) +void CdbDebugEngine::jumpToLineExec(const QString & /* fileName */, int /*lineNumber*/) { - if (debugCDB) - qDebug() << Q_FUNC_INFO << fileName << lineNumber; + warning(tr("Jump to line is not implemented")); } void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value) @@ -1300,7 +1327,7 @@ void CdbDebugEngine::activateFrame(int frameIndex) } } while (false); if (!success) { - const QString msg = QString::fromLatin1("Internal error: activateFrame() failed for frame #1 of %2, thread %3: %4"). + const QString msg = QString::fromLatin1("Internal error: activateFrame() failed for frame #%1 of %2, thread %3: %4"). arg(frameIndex).arg(stackHandler->stackSize()).arg(m_d->m_currentThreadId).arg(errorMessage); warning(msg); } @@ -1577,6 +1604,7 @@ void CdbDebugEnginePrivate::handleDebugEvent() m_engine->setState(InferiorStopping, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); m_currentThreadId = updateThreadList(); + manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Stopped, current thread: %1").arg(m_currentThreadId)); ThreadsHandler *threadsHandler = manager()->threadsHandler(); const int threadIndex = threadIndexById(threadsHandler, m_currentThreadId); if (threadIndex != -1) diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index e5b4fafc538..afbb7ab36cf 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -131,6 +131,7 @@ struct CdbDebugEnginePrivate bool continueInferiorProcess(QString *errorMessage = 0); bool continueInferior(QString *errorMessage); + bool executeContinueCommand(const QString &command); bool attemptBreakpointSynchronization(QString *errorMessage); void notifyCrashed();