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.
This commit is contained in:
Friedemann Kleint
2009-09-30 17:13:52 +02:00
parent 8356d3360b
commit 8cc94d10a2
4 changed files with 116 additions and 77 deletions

View File

@@ -179,11 +179,14 @@ static inline QString msgCannotAddBreakPoint(const QString &why)
} }
bool CDBBreakPoint::add(CIDebugControl* debugControl, bool CDBBreakPoint::add(CIDebugControl* debugControl,
quint64 *address, unsigned long *id, QString *errorMessage,
QString *errorMessage) const unsigned long *id,
quint64 *address) const
{ {
IDebugBreakpoint2* ibp = 0; IDebugBreakpoint2* ibp = 0;
if (address)
*address = 0; *address = 0;
if (id)
*id = 0; *id = 0;
HRESULT hr = debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &ibp); HRESULT hr = debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &ibp);
if (FAILED(hr)) { if (FAILED(hr)) {
@@ -196,15 +199,19 @@ bool CDBBreakPoint::add(CIDebugControl* debugControl,
} }
if (!apply(ibp, errorMessage)) if (!apply(ibp, errorMessage))
return false; return false;
// GetOffset can fail when attaching to remote processes. // GetOffset can fail when attaching to remote processes, ignore return
if (address) {
hr = ibp->GetOffset(address); hr = ibp->GetOffset(address);
if (FAILED(hr)) if (FAILED(hr))
*address = 0; *address = 0;
}
if (id) {
hr = ibp->GetId(id); hr = ibp->GetId(id);
if (FAILED(hr)) { if (FAILED(hr)) {
*errorMessage = msgCannotAddBreakPoint(msgComFailed("GetId", hr)); *errorMessage = msgCannotAddBreakPoint(msgComFailed("GetId", hr));
return false; return false;
} }
}
return true; return true;
} }
@@ -458,7 +465,7 @@ bool CDBBreakPoint::synchronizeBreakPoints(CIDebugControl* debugControl,
quint64 address; quint64 address;
unsigned long id; unsigned long id;
CDBBreakPoint ncdbbp(*nbd); CDBBreakPoint ncdbbp(*nbd);
breakPointOk = ncdbbp.add(debugControl, &address, &id, &warning); breakPointOk = ncdbbp.add(debugControl, &warning, &id, &address);
if (breakPointOk) { if (breakPointOk) {
if (debugBP) if (debugBP)
qDebug() << "Added " << id << " at " << address << ncdbbp; qDebug() << "Added " << id << " at " << address << ncdbbp;

View File

@@ -63,7 +63,10 @@ struct CDBBreakPoint
// Apply parameters // Apply parameters
bool apply(IDebugBreakpoint2 *ibp, QString *errorMessage) const; bool apply(IDebugBreakpoint2 *ibp, QString *errorMessage) const;
// Convenience to add to a IDebugControl4 // 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 // Retrieve/parse breakpoints from the interfaces
bool retrieve(IDebugBreakpoint2 *ibp, QString *errorMessage); bool retrieve(IDebugBreakpoint2 *ibp, QString *errorMessage);

View File

@@ -943,8 +943,31 @@ void CdbDebugEngine::updateWatchData(const WatchData &incomplete)
qDebug() << *manager()->watchHandler()->model(LocalsWatch); 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() void CdbDebugEngine::stepExec()
{ {
// Step into
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
@@ -966,15 +989,15 @@ void CdbDebugEngine::stepOutExec()
{ {
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
// emulate gdb 'exec-finish' (exec until return of current function)
StackHandler* sh = manager()->stackHandler(); // by running up to address of the above stack frame (mostly works).
const StackHandler* sh = manager()->stackHandler();
const int idx = sh->currentIndex() + 1; const int idx = sh->currentIndex() + 1;
QList<StackFrame> stackframes = sh->frames(); const QList<StackFrame> stackframes = sh->frames();
if (idx < 0 || idx >= stackframes.size()) { if (idx < 0 || idx >= stackframes.size()) {
warning(QString::fromLatin1("Cannot step out of stack frame %1").arg(idx)); warning(QString::fromLatin1("Cannot step out of stack frame %1.").arg(idx));
return; return;
} }
// Set a temporary breakpoint and continue // Set a temporary breakpoint and continue
const StackFrame& frame = stackframes.at(idx); const StackFrame& frame = stackframes.at(idx);
bool success = false; bool success = false;
@@ -985,7 +1008,7 @@ void CdbDebugEngine::stepOutExec()
errorMessage = QLatin1String("Cannot obtain address from stack frame"); errorMessage = QLatin1String("Cannot obtain address from stack frame");
break; break;
} }
manager()->showDebuggerOutput(LogMisc, tr("Running to 0x%1...").arg(address, 0, 16));
IDebugBreakpoint2* pBP; IDebugBreakpoint2* pBP;
HRESULT hr = m_d->m_cif.debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP); HRESULT hr = m_d->m_cif.debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
if (FAILED(hr) || !pBP) { if (FAILED(hr) || !pBP) {
@@ -1006,13 +1029,15 @@ void CdbDebugEngine::stepOutExec()
void CdbDebugEngine::nextExec() void CdbDebugEngine::nextExec()
{ {
// Step over
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
m_d->clearForRun(); m_d->clearForRun();
m_d->setCodeLevel(); m_d->setCodeLevel(); // Step by instruction
setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__);
const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); 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)) { if (SUCCEEDED(hr)) {
setState(InferiorRunning, Q_FUNC_INFO, __LINE__); setState(InferiorRunning, Q_FUNC_INFO, __LINE__);
startWatchTimer(); startWatchTimer();
@@ -1024,25 +1049,13 @@ void CdbDebugEngine::nextExec()
void CdbDebugEngine::stepIExec() void CdbDebugEngine::stepIExec()
{ {
warning(QString::fromLatin1("CdbDebugEngine::stepIExec() not implemented")); // Step by instruction
nextExec();
} }
void CdbDebugEngine::nextIExec() void CdbDebugEngine::nextIExec()
{ {
if (debugCDB) nextExec();
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)));
}
} }
void CdbDebugEngine::continueInferior() void CdbDebugEngine::continueInferior()
@@ -1148,20 +1161,34 @@ void CdbDebugEngine::interruptInferior()
void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber) void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber)
{ {
if (debugCDB) manager()->showDebuggerOutput(LogMisc, tr("Running up to %1:%2...").arg(fileName).arg(lineNumber));
qDebug() << Q_FUNC_INFO << fileName << 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) void CdbDebugEngine::runToFunctionExec(const QString &functionName)
{ {
if (debugCDB) manager()->showDebuggerOutput(LogMisc, tr("Running up to function '%1()'...").arg(functionName));
qDebug() << Q_FUNC_INFO << 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) warning(tr("Jump to line is not implemented"));
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
} }
void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value) void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value)
@@ -1300,7 +1327,7 @@ void CdbDebugEngine::activateFrame(int frameIndex)
} }
} while (false); } while (false);
if (!success) { 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); arg(frameIndex).arg(stackHandler->stackSize()).arg(m_d->m_currentThreadId).arg(errorMessage);
warning(msg); warning(msg);
} }
@@ -1577,6 +1604,7 @@ void CdbDebugEnginePrivate::handleDebugEvent()
m_engine->setState(InferiorStopping, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorStopping, Q_FUNC_INFO, __LINE__);
m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__);
m_currentThreadId = updateThreadList(); m_currentThreadId = updateThreadList();
manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Stopped, current thread: %1").arg(m_currentThreadId));
ThreadsHandler *threadsHandler = manager()->threadsHandler(); ThreadsHandler *threadsHandler = manager()->threadsHandler();
const int threadIndex = threadIndexById(threadsHandler, m_currentThreadId); const int threadIndex = threadIndexById(threadsHandler, m_currentThreadId);
if (threadIndex != -1) if (threadIndex != -1)

View File

@@ -131,6 +131,7 @@ struct CdbDebugEnginePrivate
bool continueInferiorProcess(QString *errorMessage = 0); bool continueInferiorProcess(QString *errorMessage = 0);
bool continueInferior(QString *errorMessage); bool continueInferior(QString *errorMessage);
bool executeContinueCommand(const QString &command);
bool attemptBreakpointSynchronization(QString *errorMessage); bool attemptBreakpointSynchronization(QString *errorMessage);
void notifyCrashed(); void notifyCrashed();