forked from qt-creator/qt-creator
Debugger[CDB]: Format a verbose message when stopping.
Including reason, etc, and show in status bar. Switch to assembler in activateFrame() in case someone clicks on an unusable frame.
This commit is contained in:
@@ -133,7 +133,8 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager,
|
|||||||
m_currentStackTrace(0),
|
m_currentStackTrace(0),
|
||||||
m_firstActivatedFrame(true),
|
m_firstActivatedFrame(true),
|
||||||
m_inferiorStartupComplete(false),
|
m_inferiorStartupComplete(false),
|
||||||
m_mode(AttachCore)
|
m_mode(AttachCore),
|
||||||
|
m_stoppedReason(StoppedOther)
|
||||||
{
|
{
|
||||||
connect(this, SIGNAL(watchTimerDebugEvent()), this, SLOT(handleDebugEvent()));
|
connect(this, SIGNAL(watchTimerDebugEvent()), this, SLOT(handleDebugEvent()));
|
||||||
connect(this, SIGNAL(modulesLoaded()), this, SLOT(slotModulesLoaded()));
|
connect(this, SIGNAL(modulesLoaded()), this, SLOT(slotModulesLoaded()));
|
||||||
@@ -201,6 +202,8 @@ void CdbDebugEnginePrivate::clearForRun()
|
|||||||
m_eventThreadId = m_interruptArticifialThreadId = -1;
|
m_eventThreadId = m_interruptArticifialThreadId = -1;
|
||||||
m_interrupted = false;
|
m_interrupted = false;
|
||||||
cleanStackTrace();
|
cleanStackTrace();
|
||||||
|
m_stoppedReason = StoppedOther;
|
||||||
|
m_stoppedMessage.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::cleanStackTrace()
|
void CdbDebugEnginePrivate::cleanStackTrace()
|
||||||
@@ -1005,12 +1008,15 @@ void CdbDebugEngine::activateFrame(int frameIndex)
|
|||||||
stackHandler->setCurrentIndex(frameIndex);
|
stackHandler->setCurrentIndex(frameIndex);
|
||||||
|
|
||||||
const StackFrame &frame = stackHandler->currentFrame();
|
const StackFrame &frame = stackHandler->currentFrame();
|
||||||
if (!frame.isUsable()) {
|
|
||||||
// Clean out model
|
const bool showAssembler = !frame.isUsable();
|
||||||
|
if (showAssembler) { // Assembly code: Clean out model and force instruction mode.
|
||||||
watchHandler->beginCycle();
|
watchHandler->beginCycle();
|
||||||
watchHandler->endCycle();
|
watchHandler->endCycle();
|
||||||
errorMessage = QString::fromLatin1("%1: file %2 unusable.").
|
QAction *assemblerAction = theDebuggerAction(OperateByInstruction);
|
||||||
arg(QLatin1String(Q_FUNC_INFO), frame.file);
|
if (!assemblerAction->isChecked())
|
||||||
|
assemblerAction->trigger();
|
||||||
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1263,7 +1269,8 @@ void CdbDebugEnginePrivate::notifyException(long code, bool fatal, const QString
|
|||||||
// Cannot go over crash point to execute calls.
|
// Cannot go over crash point to execute calls.
|
||||||
if (fatal) {
|
if (fatal) {
|
||||||
m_dumper->disable();
|
m_dumper->disable();
|
||||||
manager()->showStatusMessage(message, 15000);
|
m_stoppedReason = StoppedCrash;
|
||||||
|
m_stoppedMessage = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1412,6 +1419,38 @@ static inline unsigned long dumperThreadId(const QList<StackFrame> &frames,
|
|||||||
return currentThread;
|
return currentThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format stop message with all available information.
|
||||||
|
QString CdbDebugEnginePrivate::stoppedMessage(const StackFrame *topFrame /* = 0 */) const
|
||||||
|
{
|
||||||
|
QString msg;
|
||||||
|
if (topFrame) {
|
||||||
|
if (topFrame->isUsable()) {
|
||||||
|
// Stopped at basename:line
|
||||||
|
const int lastSlashPos = topFrame->file.lastIndexOf(QLatin1Char('/'));
|
||||||
|
const QString file = lastSlashPos == -1 ? topFrame->file : topFrame->file.mid(lastSlashPos + 1);
|
||||||
|
msg = CdbDebugEngine::tr("Stopped at %1:%2 in thread %3.").
|
||||||
|
arg(file).arg(topFrame->line).arg(m_currentThreadId);
|
||||||
|
} else {
|
||||||
|
// Somewhere in assembly code.
|
||||||
|
if (topFrame->function.isEmpty()) {
|
||||||
|
msg = CdbDebugEngine::tr("Stopped at %1 in thread %2 (missing debug information).").
|
||||||
|
arg(topFrame->address).arg(m_currentThreadId);
|
||||||
|
} else {
|
||||||
|
msg = CdbDebugEngine::tr("Stopped at %1 (%2) in thread %3 (missing debug information).").
|
||||||
|
arg(topFrame->address).arg(topFrame->function).arg(m_currentThreadId);
|
||||||
|
}
|
||||||
|
} // isUsable
|
||||||
|
} else {
|
||||||
|
msg = CdbDebugEngine::tr("Stopped in thread %1 (missing debug information).").arg(m_currentThreadId);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!m_stoppedMessage.isEmpty()) {
|
||||||
|
msg += QLatin1Char(' ');
|
||||||
|
msg += m_stoppedMessage;
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::updateStackTrace()
|
void CdbDebugEnginePrivate::updateStackTrace()
|
||||||
{
|
{
|
||||||
if (debugCDB)
|
if (debugCDB)
|
||||||
@@ -1443,15 +1482,8 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
|||||||
current = i;
|
current = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Visibly warn the users about missing top frames/all frames, as they otherwise
|
// Format stop message.
|
||||||
// might think stepping is broken.
|
const QString stopMessage = stoppedMessage(stackFrames.isEmpty() ? static_cast<const StackFrame *>(0) : &stackFrames.front());
|
||||||
if (!stackFrames.at(0).isUsable()) {
|
|
||||||
const QString topFunction = count ? stackFrames.at(0).function : QString();
|
|
||||||
const QString msg = current >= 0 ?
|
|
||||||
CdbDebugEngine::tr("Thread %1: Missing debug information for top stack frame (%2).").arg(m_currentThreadId).arg(topFunction) :
|
|
||||||
CdbDebugEngine::tr("Thread %1: No debug information available (%2).").arg(m_currentThreadId).arg(topFunction);
|
|
||||||
m_engine->warning(msg);
|
|
||||||
}
|
|
||||||
// Set up dumper with a thread (or invalid)
|
// Set up dumper with a thread (or invalid)
|
||||||
const unsigned long dumperThread = dumperThreadId(stackFrames, m_currentThreadId);
|
const unsigned long dumperThread = dumperThreadId(stackFrames, m_currentThreadId);
|
||||||
if (debugCDBExecution)
|
if (debugCDBExecution)
|
||||||
@@ -1469,6 +1501,8 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
|||||||
manager()->watchHandler()->endCycle();
|
manager()->watchHandler()->endCycle();
|
||||||
}
|
}
|
||||||
manager()->watchHandler()->updateWatchers();
|
manager()->watchHandler()->updateWatchers();
|
||||||
|
// Show message after a lengthy dumper initialization
|
||||||
|
manager()->showStatusMessage(stopMessage, 15000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::updateModules()
|
void CdbDebugEnginePrivate::updateModules()
|
||||||
@@ -1495,6 +1529,17 @@ void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP)
|
|||||||
Q_UNUSED(pBP)
|
Q_UNUSED(pBP)
|
||||||
if (debugCDB)
|
if (debugCDB)
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
m_stoppedReason = StoppedBreakpoint;
|
||||||
|
CdbCore::BreakPoint breakpoint;
|
||||||
|
// Format message unless it is a temporary step-out breakpoint with empty expression.
|
||||||
|
QString expression;
|
||||||
|
if (breakpoint.retrieve(pBP, &expression)) {
|
||||||
|
expression = breakpoint.expression();
|
||||||
|
} else {
|
||||||
|
expression.clear();
|
||||||
|
}
|
||||||
|
if (!expression.isEmpty())
|
||||||
|
m_stoppedMessage = CdbDebugEngine::tr("Breakpoint: %1").arg(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::reloadSourceFiles()
|
void CdbDebugEngine::reloadSourceFiles()
|
||||||
|
@@ -62,6 +62,12 @@ public:
|
|||||||
BreakEventSyncBreakPoints,
|
BreakEventSyncBreakPoints,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StoppedReason {
|
||||||
|
StoppedCrash,
|
||||||
|
StoppedBreakpoint,
|
||||||
|
StoppedOther
|
||||||
|
};
|
||||||
|
|
||||||
explicit CdbDebugEnginePrivate(DebuggerManager *parent,
|
explicit CdbDebugEnginePrivate(DebuggerManager *parent,
|
||||||
const QSharedPointer<CdbOptions> &options,
|
const QSharedPointer<CdbOptions> &options,
|
||||||
CdbDebugEngine* engine);
|
CdbDebugEngine* engine);
|
||||||
@@ -102,6 +108,8 @@ public:
|
|||||||
|
|
||||||
void updateCodeLevel();
|
void updateCodeLevel();
|
||||||
|
|
||||||
|
QString stoppedMessage(const StackFrame *topFrame = 0) const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleDebugEvent();
|
void handleDebugEvent();
|
||||||
void slotModulesLoaded();
|
void slotModulesLoaded();
|
||||||
@@ -129,6 +137,9 @@ public:
|
|||||||
|
|
||||||
DebuggerStartMode m_mode;
|
DebuggerStartMode m_mode;
|
||||||
Utils::ConsoleProcess m_consoleStubProc;
|
Utils::ConsoleProcess m_consoleStubProc;
|
||||||
|
|
||||||
|
StoppedReason m_stoppedReason;
|
||||||
|
QString m_stoppedMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { messageTimeOut = 5000 };
|
enum { messageTimeOut = 5000 };
|
||||||
|
Reference in New Issue
Block a user