aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorhjk <[email protected]>2009-10-05 12:00:47 +0200
committerhjk <[email protected]>2009-10-05 12:01:23 +0200
commit75529d87d382f9403d71cd8d9c1117ad4bfc58f4 (patch)
tree7f7586bd0256a0bf58e8289b0efb0b250bbba4a7 /src
parent1f1c899cc083c55daf7cc4591bf92f6103fac4ed (diff)
debugger: rework 'jump to source' logic
Diffstat (limited to 'src')
-rw-r--r--src/plugins/debugger/debuggeractions.cpp2
-rw-r--r--src/plugins/debugger/debuggermanager.cpp4
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp231
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h3
-rw-r--r--src/plugins/debugger/stackhandler.h11
5 files changed, 137 insertions, 114 deletions
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 892a79aa225..c5f3addd1d6 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -84,7 +84,7 @@ void DebuggerSettings::writeSettings(QSettings *settings) const
SavedAction *DebuggerSettings::item(int code) const
{
- QTC_ASSERT(m_items.value(code, 0), return 0);
+ QTC_ASSERT(m_items.value(code, 0), qDebug() << "CODE: " << code; return 0);
return m_items.value(code, 0);
}
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index b316bd5f5e4..8394cbbf26f 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -454,6 +454,7 @@ void DebuggerManager::init()
//QTreeView *tooltipView = qobject_cast<QTreeView *>(d->m_tooltipWindow);
//tooltipView->setModel(d->m_watchHandler->model(TooltipsWatch));
qRegisterMetaType<WatchData>("WatchData");
+ qRegisterMetaType<StackCookie>("StackCookie");
d->m_actions.continueAction = new QAction(tr("Continue"), this);
d->m_actions.continueAction->setIcon(QIcon(":/debugger/images/debugger_continue_small.png"));
@@ -707,7 +708,6 @@ void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
void DebuggerManager::notifyInferiorStopped()
{
- resetLocation();
setState(InferiorStopped);
showStatusMessage(tr("Stopped."), 5000);
}
@@ -1349,7 +1349,7 @@ void DebuggerManager::gotoLocation(const Debugger::Internal::StackFrame &frame,
{
if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) {
if (setMarker)
- resetLocation();
+ emit resetLocationRequested();
d->m_disassemblerViewAgent.setFrame(frame);
} else {
// Connected to the plugin.
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 4c2b2428a6c..aba7017a1ce 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -894,18 +894,13 @@ void GdbEngine::updateAll()
{
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/);
tryLoadDebuggingHelpers();
- updateLocals();
- postCommand(_("-stack-list-frames"), WatchUpdate, CB(handleStackListFrames1), false);
+ postCommand(_("-stack-list-frames"), WatchUpdate, CB(handleStackListFrames),
+ QVariant::fromValue<StackCookie>(StackCookie(false, true)));
manager()->stackHandler()->setCurrentIndex(0);
if (supportsThreads())
postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), 0);
manager()->reloadRegisters();
-}
-
-void GdbEngine::handleStackListFrames1(const GdbResponse &response)
-{
- handleStackListFrames(response);
- manager()->gotoLocation(manager()->stackHandler()->currentFrame(), true);
+ updateLocals();
}
void GdbEngine::handleQuerySources(const GdbResponse &response)
@@ -1182,29 +1177,6 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
#endif
}
-void GdbEngine::reloadFullStack()
-{
- QString cmd = _("-stack-list-frames");
- postCommand(cmd, WatchUpdate, CB(handleStackListFrames), true);
-}
-
-void GdbEngine::reloadStack()
-{
- QString cmd = _("-stack-list-frames");
- int stackDepth = theDebuggerAction(MaximalStackDepth)->value().toInt();
- if (stackDepth && !m_gdbAdapter->isTrkAdapter())
- cmd += _(" 0 ") + QString::number(stackDepth);
- postCommand(cmd, WatchUpdate, CB(handleStackListFrames), false);
- // FIXME: gdb 6.4 symbianelf likes to be asked twice. The first time it
- // returns with "^error,msg="Previous frame identical to this frame
- // (corrupt stack?)". Might be related to the fact that we can't
- // access the memory belonging to the lower frames. But as we know
- // this sometimes happens, ask the second time immediately instead
- // of waiting for the first request to fail.
- if (m_gdbAdapter->isTrkAdapter())
- postCommand(cmd, WatchUpdate, CB(handleStackListFrames), false);
-}
-
void GdbEngine::handleStop1(const GdbResponse &response)
{
GdbMi data = response.cookie.value<GdbMi>();
@@ -1307,7 +1279,7 @@ void GdbEngine::handleStop2(const GdbMi &data)
manager()->stackHandler()->setCurrentIndex(0);
updateLocals(); // Quick shot
- reloadStack();
+ reloadStack(false);
if (supportsThreads()) {
int currentId = data.findChild("thread-id").data().toInt();
@@ -2235,13 +2207,52 @@ void GdbEngine::reloadSourceFiles()
//
//////////////////////////////////////////////////////////////////////
+void GdbEngine::selectThread(int index)
+{
+ ThreadsHandler *threadsHandler = manager()->threadsHandler();
+ threadsHandler->setCurrentThread(index);
+
+ QList<ThreadData> threads = threadsHandler->threads();
+ QTC_ASSERT(index < threads.size(), return);
+ int id = threads.at(index).id;
+ showStatusMessage(tr("Retrieving data for stack view..."), 10000);
+ postCommand(_("-thread-select %1").arg(id), CB(handleStackSelectThread));
+}
+
void GdbEngine::handleStackSelectThread(const GdbResponse &)
{
+ QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/);
//qDebug("FIXME: StackHandler::handleOutput: SelectThread");
showStatusMessage(tr("Retrieving data for stack view..."), 3000);
- reloadStack();
+ manager()->reloadRegisters();
+ reloadStack(true);
+ updateLocals();
}
+void GdbEngine::reloadFullStack()
+{
+ QString cmd = _("-stack-list-frames");
+ postCommand(cmd, WatchUpdate, CB(handleStackListFrames),
+ QVariant::fromValue<StackCookie>(StackCookie(true, true)));
+}
+
+void GdbEngine::reloadStack(bool forceGotoLocation)
+{
+ QString cmd = _("-stack-list-frames");
+ int stackDepth = theDebuggerAction(MaximalStackDepth)->value().toInt();
+ if (stackDepth && !m_gdbAdapter->isTrkAdapter())
+ cmd += _(" 0 ") + QString::number(stackDepth);
+ // FIXME: gdb 6.4 symbianelf likes to be asked twice. The first time it
+ // returns with "^error,msg="Previous frame identical to this frame
+ // (corrupt stack?)". Might be related to the fact that we can't
+ // access the memory belonging to the lower frames. But as we know
+ // this sometimes happens, ask the second time immediately instead
+ // of waiting for the first request to fail.
+ if (m_gdbAdapter->isTrkAdapter())
+ postCommand(cmd, WatchUpdate);
+ postCommand(cmd, WatchUpdate, CB(handleStackListFrames),
+ QVariant::fromValue<StackCookie>(StackCookie(false, forceGotoLocation)));
+}
StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level)
{
@@ -2266,94 +2277,94 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
#else
bool handleIt = response.resultClass == GdbResultDone;
#endif
- if (handleIt) {
- bool isFull = response.cookie.toBool();
- QList<StackFrame> stackFrames;
-
- GdbMi stack = response.data.findChild("stack");
- if (!stack.isValid()) {
- qDebug() << "FIXME: stack:" << stack.toString();
- return;
- }
+ if (!handleIt) {
+ // That always happens on symbian gdb with
+ // ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
+ // logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
+ //qDebug() << "LISTING STACK FAILED: " << response.toString();
+ return;
+ }
- int topFrame = -1;
+ StackCookie cookie = response.cookie.value<StackCookie>();
+ QList<StackFrame> stackFrames;
- int n = stack.childCount();
- for (int i = 0; i != n; ++i) {
- stackFrames.append(parseStackFrame(stack.childAt(i), i));
- const StackFrame &frame = stackFrames.back();
+ GdbMi stack = response.data.findChild("stack");
+ if (!stack.isValid()) {
+ qDebug() << "FIXME: stack:" << stack.toString();
+ return;
+ }
- #if defined(Q_OS_WIN)
- const bool isBogus =
- // Assume this is wrong and points to some strange stl_algobase
- // implementation. Happens on Karsten's XP system with Gdb 5.50
- (frame.file.endsWith(__("/bits/stl_algobase.h")) && frame.line == 150)
- // Also wrong. Happens on Vista with Gdb 5.50
- || (frame.function == __("operator new") && frame.line == 151);
+ int targetFrame = -1;
- // Immediately leave bogus frames.
- if (topFrame == -1 && isBogus) {
- postCommand(_("-exec-finish"));
- return;
- }
- #endif
+ int n = stack.childCount();
+ for (int i = 0; i != n; ++i) {
+ stackFrames.append(parseStackFrame(stack.childAt(i), i));
+ const StackFrame &frame = stackFrames.back();
- // Initialize top frame to the first valid frame.
- // FIXME: Check for QFile(frame.fullname).isReadable()?
- const bool isValid = !frame.file.isEmpty() && !frame.function.isEmpty();
- if (isValid && topFrame == -1)
- topFrame = i;
+ #if defined(Q_OS_WIN)
+ const bool isBogus =
+ // Assume this is wrong and points to some strange stl_algobase
+ // implementation. Happens on Karsten's XP system with Gdb 5.50
+ (frame.file.endsWith(__("/bits/stl_algobase.h")) && frame.line == 150)
+ // Also wrong. Happens on Vista with Gdb 5.50
+ || (frame.function == __("operator new") && frame.line == 151);
+
+ // Immediately leave bogus frames.
+ if (targetFrame == -1 && isBogus) {
+ postCommand(_("-exec-finish"));
+ return;
}
-
- bool canExpand = !isFull
- && (n >= theDebuggerAction(MaximalStackDepth)->value().toInt());
- theDebuggerAction(ExpandStack)->setEnabled(canExpand);
- manager()->stackHandler()->setFrames(stackFrames, canExpand);
-
- #ifdef Q_OS_MAC
- // Mac gdb does not add the location to the "stopped" message,
- // so the early gotoLocation() was not triggered. Force it here.
- bool jump = topFrame != -1
- && !theDebuggerBoolSetting(OperateByInstruction);
- #else
- // For topFrame == -1 there is no frame at all, for topFrame == 0
- // we already issued a 'gotoLocation' when reading the *stopped
- // message. Also, when OperateByInstruction we always want to
- // use frame #0.
- bool jump = topFrame != -1 && topFrame != 0
- && !theDebuggerBoolSetting(OperateByInstruction);
#endif
-
- if (jump) {
- const StackFrame &frame = manager()->stackHandler()->currentFrame();
- qDebug() << "GOTO, 2nd try" << frame.toString() << topFrame;
- gotoLocation(frame, true);
- }
- } else {
- // That always happens on symbian gdb with
- // ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
- // logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
- //qDebug() << "LISTING STACK FAILED: " << response.toString();
+
+ // Initialize top frame to the first valid frame.
+ // FIXME: Check for QFile(frame.fullname).isReadable()?
+ const bool isValid = !frame.file.isEmpty() && !frame.function.isEmpty();
+ if (isValid && targetFrame == -1)
+ targetFrame = i;
}
-}
-void GdbEngine::selectThread(int index)
-{
- //reset location arrow
- m_manager->resetLocation();
+ bool canExpand = !cookie.isFull
+ && (n >= theDebuggerAction(MaximalStackDepth)->value().toInt());
+ theDebuggerAction(ExpandStack)->setEnabled(canExpand);
+ manager()->stackHandler()->setFrames(stackFrames, canExpand);
- ThreadsHandler *threadsHandler = manager()->threadsHandler();
- threadsHandler->setCurrentThread(index);
+ // We can't jump to any file if we don't have any frames.
+ if (stackFrames.isEmpty())
+ return;
- QList<ThreadData> threads = threadsHandler->threads();
- QTC_ASSERT(index < threads.size(), return);
- int id = threads.at(index).id;
- showStatusMessage(tr("Retrieving data for stack view..."), 10000);
- postCommand(_("-thread-select %1").arg(id), CB(handleStackSelectThread));
+ // targetFrame contains the top most frame for which we have source
+ // information. That's typically the frame we'd like to jump to, with
+ // a few exceptions:
+
+ // Always jump to frame #0 when stepping by instruction.
+ if (theDebuggerBoolSetting(OperateByInstruction))
+ targetFrame = 0;
+
+ // If there is no frame with source, jump to frame #0.
+ if (targetFrame == -1)
+ targetFrame = 0;
+
+ #ifdef Q_OS_MAC
+ // Mac gdb does not add the location to the "stopped" message,
+ // so the early gotoLocation() was not triggered. Force it here.
+ bool jump = true;
+ #else
+ // For targetFrame == 0 we already issued a 'gotoLocation'
+ // when reading the *stopped message.
+ bool jump = targetFrame != 0;
+ #endif
+
+ manager()->stackHandler()->setCurrentIndex(targetFrame);
+ if (jump || cookie.gotoLocation) {
+ const StackFrame &frame = manager()->stackHandler()->currentFrame();
+ //qDebug() << "GOTO, 2ND ATTEMPT: " << frame.toString() << targetFrame;
+ gotoLocation(frame, true);
+ }
}
void GdbEngine::activateFrame(int frameIndex)
{
+ m_manager->resetLocation();
if (state() != InferiorStopped)
return;
@@ -2394,7 +2405,8 @@ void GdbEngine::handleStackListThreads(const GdbResponse &response)
thread.id = items.at(index).data().toInt();
threads.append(thread);
if (thread.id == id) {
- //qDebug() << "SETTING INDEX TO:" << index << " ID:" << id << " RECOD:" << response.toString();
+ //qDebug() << "SETTING INDEX TO:" << index << " ID:"
+ // << id << " RECOD:" << response.toString();
currentIndex = index;
}
}
@@ -3086,7 +3098,7 @@ void GdbEngine::sendWatchParameters(const QByteArray &params0)
void GdbEngine::handleVarAssign(const GdbResponse &)
{
- // everything might have changed, force re-evaluation
+ // Everything might have changed, force re-evaluation.
// FIXME: Speed this up by re-using variables and only
// marking values as 'unknown'
setTokenBarrier();
@@ -3421,7 +3433,8 @@ void GdbEngine::handleStackListArguments(const GdbResponse &response)
const GdbMi args = frame.findChild("args");
m_currentFunctionArgs = args.children();
} else if (response.resultClass == GdbResultError) {
- qDebug() << "FIXME: GdbEngine::handleStackListArguments: should not happen";
+ qDebug() << "FIXME: GdbEngine::handleStackListArguments: should not happen"
+ << response.toString();
}
}
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 58352b4ab34..6b5b5ebcb9e 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -339,10 +339,9 @@ private:
// Stack specific stuff
//
void handleStackListFrames(const GdbResponse &response);
- void handleStackListFrames1(const GdbResponse &response);
void handleStackSelectThread(const GdbResponse &response);
void handleStackListThreads(const GdbResponse &response);
- Q_SLOT void reloadStack();
+ Q_SLOT void reloadStack(bool forceGotoLocation);
Q_SLOT void reloadFullStack();
diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h
index dd2c0a4997f..8b0d7a165c3 100644
--- a/src/plugins/debugger/stackhandler.h
+++ b/src/plugins/debugger/stackhandler.h
@@ -41,6 +41,14 @@
namespace Debugger {
namespace Internal {
+struct StackCookie
+{
+ StackCookie() : isFull(true), gotoLocation(false) {}
+ StackCookie(bool full, bool jump) : isFull(full), gotoLocation(jump) {}
+ bool isFull;
+ bool gotoLocation;
+};
+
////////////////////////////////////////////////////////////////////////
//
// StackModel
@@ -129,4 +137,7 @@ private:
} // namespace Internal
} // namespace Debugger
+Q_DECLARE_METATYPE(Debugger::Internal::StackCookie)
+
+
#endif // DEBUGGER_STACKHANDLER_H