forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user