debugger: fall back to instructionwise stepping when debuginfo for frame is

missing
This commit is contained in:
hjk
2010-02-01 16:14:57 +01:00
parent 93876009e5
commit ecd475c903
7 changed files with 93 additions and 21 deletions

View File

@@ -1084,9 +1084,9 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
return ok; return ok;
} }
void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent, void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent)
const StackFrame & frame)
{ {
StackFrame frame = agent->frame();
enum { ContextLines = 40 }; enum { ContextLines = 40 };
bool ok = false; bool ok = false;
QString errorMessage; QString errorMessage;

View File

@@ -88,8 +88,7 @@ public:
virtual void attemptBreakpointSynchronization(); virtual void attemptBreakpointSynchronization();
virtual void fetchDisassembler(DisassemblerViewAgent *agent, virtual void fetchDisassembler(DisassemblerViewAgent *agent);
const StackFrame &frame);
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length); virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length);
virtual void reloadModules(); virtual void reloadModules();

View File

@@ -153,8 +153,11 @@ public:
struct DisassemblerViewAgentPrivate struct DisassemblerViewAgentPrivate
{ {
DisassemblerViewAgentPrivate() { tryMixed = true; }
QPointer<TextEditor::ITextEditor> editor; QPointer<TextEditor::ITextEditor> editor;
StackFrame frame; StackFrame frame;
bool tryMixed;
QPointer<DebuggerManager> manager; QPointer<DebuggerManager> manager;
LocationMark2 *locationMark; LocationMark2 *locationMark;
QHash<QString, QString> cache; QHash<QString, QString> cache;
@@ -230,10 +233,24 @@ QString frameKey(const StackFrame &frame)
return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from); return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from);
} }
void DisassemblerViewAgent::setFrame(const StackFrame &frame) const StackFrame &DisassemblerViewAgent::frame() const
{
return d->frame;
}
bool DisassemblerViewAgent::isMixed() const
{
return d->tryMixed
&& d->frame.line > 0
&& !d->frame.function.isEmpty()
&& d->frame.function != _("??");
}
void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed)
{ {
d->frame = frame; d->frame = frame;
if (!frame.function.isEmpty() && frame.function != _("??")) { d->tryMixed = tryMixed;
if (isMixed()) {
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame)); QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
if (it != d->cache.end()) { if (it != d->cache.end()) {
QString msg = _("Use cache disassembler for '%1' in '%2'") QString msg = _("Use cache disassembler for '%1' in '%2'")
@@ -245,7 +262,7 @@ void DisassemblerViewAgent::setFrame(const StackFrame &frame)
} }
IDebuggerEngine *engine = d->manager->currentEngine(); IDebuggerEngine *engine = d->manager->currentEngine();
QTC_ASSERT(engine, return); QTC_ASSERT(engine, return);
engine->fetchDisassembler(this, frame); engine->fetchDisassembler(this);
} }
void DisassemblerViewAgent::setContents(const QString &contents) void DisassemblerViewAgent::setContents(const QString &contents)

View File

@@ -83,12 +83,14 @@ public:
explicit DisassemblerViewAgent(DebuggerManager *manager); explicit DisassemblerViewAgent(DebuggerManager *manager);
~DisassemblerViewAgent(); ~DisassemblerViewAgent();
void setFrame(const StackFrame &frame); void setFrame(const StackFrame &frame, bool tryMixed = true);
const StackFrame &frame() const;
void resetLocation(); void resetLocation();
Q_SLOT void setContents(const QString &contents); Q_SLOT void setContents(const QString &contents);
QString address() const; QString address() const;
bool contentsCoversAddress(const QString &contents) const; bool contentsCoversAddress(const QString &contents) const;
void cleanup(); void cleanup();
bool isMixed() const;
private: private:
DisassemblerViewAgentPrivate *d; DisassemblerViewAgentPrivate *d;

View File

@@ -1727,9 +1727,35 @@ void GdbEngine::stepExec()
setState(InferiorRunningRequested); setState(InferiorRunningRequested);
showStatusMessage(tr("Step requested..."), 5000); showStatusMessage(tr("Step requested..."), 5000);
if (manager()->isReverseDebugging()) if (manager()->isReverseDebugging())
postCommand("-reverse-step", RunRequest, CB(handleExecContinue)); postCommand("-reverse-step", RunRequest, CB(handleExecStep));
else else
postCommand("-exec-step", RunRequest, CB(handleExecContinue)); postCommand("-exec-step", RunRequest, CB(handleExecStep));
}
void GdbEngine::handleExecStep(const GdbResponse &response)
{
if (response.resultClass == GdbResultRunning) {
// The "running" state is picked up in handleResponse()
QTC_ASSERT(state() == InferiorRunning, /**/);
} else {
if (state() == InferiorRunningRequested_Kill) {
setState(InferiorStopped);
shutdown();
return;
}
QTC_ASSERT(state() == InferiorRunningRequested, /**/);
setState(InferiorStopped);
QByteArray msg = response.data.findChild("msg").data();
if (msg.startsWith("Cannot find bounds of current function")) {
if (!m_commandsToRunOnTemporaryBreak.isEmpty())
flushQueuedCommands();
stepIExec(); // Fall back to instruction-wise stepping.
} else {
showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
shutdown();
}
}
} }
void GdbEngine::stepIExec() void GdbEngine::stepIExec()
@@ -1760,9 +1786,35 @@ void GdbEngine::nextExec()
setState(InferiorRunningRequested); setState(InferiorRunningRequested);
showStatusMessage(tr("Step next requested..."), 5000); showStatusMessage(tr("Step next requested..."), 5000);
if (manager()->isReverseDebugging()) if (manager()->isReverseDebugging())
postCommand("-reverse-next", RunRequest, CB(handleExecContinue)); postCommand("-reverse-next", RunRequest, CB(handleExecNext));
else else
postCommand("-exec-next", RunRequest, CB(handleExecContinue)); postCommand("-exec-next", RunRequest, CB(handleExecNext));
}
void GdbEngine::handleExecNext(const GdbResponse &response)
{
if (response.resultClass == GdbResultRunning) {
// The "running" state is picked up in handleResponse()
QTC_ASSERT(state() == InferiorRunning, /**/);
} else {
if (state() == InferiorRunningRequested_Kill) {
setState(InferiorStopped);
shutdown();
return;
}
QTC_ASSERT(state() == InferiorRunningRequested, /**/);
setState(InferiorStopped);
QByteArray msg = response.data.findChild("msg").data();
if (msg.startsWith("Cannot find bounds of current function")) {
if (!m_commandsToRunOnTemporaryBreak.isEmpty())
flushQueuedCommands();
nextIExec(); // Fall back to instruction-wise stepping.
} else {
showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
shutdown();
}
}
} }
void GdbEngine::nextIExec() void GdbEngine::nextIExec()
@@ -3405,18 +3457,20 @@ struct DisassemblerAgentCookie
QPointer<DisassemblerViewAgent> agent; QPointer<DisassemblerViewAgent> agent;
}; };
void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent,
const StackFrame &frame) // FIXME: add agent->frame() accessor and use that
void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent)
{ {
if (frame.file.isEmpty()) { if (agent->isMixed()) {
fetchDisassemblerByAddress(agent, true);
} else {
// Disassemble full function: // Disassemble full function:
const StackFrame &frame = agent->frame();
QByteArray cmd = "-data-disassemble" QByteArray cmd = "-data-disassemble"
" -f " + frame.file.toLocal8Bit() + " -f " + frame.file.toLocal8Bit() +
" -l " + QByteArray::number(frame.line) + " -n -1 -- 1"; " -l " + QByteArray::number(frame.line) + " -n -1 -- 1";
postCommand(cmd, Discardable, CB(handleFetchDisassemblerByLine), postCommand(cmd, Discardable, CB(handleFetchDisassemblerByLine),
QVariant::fromValue(DisassemblerAgentCookie(agent))); QVariant::fromValue(DisassemblerAgentCookie(agent)));
} else {
fetchDisassemblerByAddress(agent, true);
} }
} }

View File

@@ -300,6 +300,8 @@ private: ////////// Inferior Management //////////
virtual void jumpToLineExec(const QString &fileName, int lineNumber); virtual void jumpToLineExec(const QString &fileName, int lineNumber);
void handleExecContinue(const GdbResponse &response); void handleExecContinue(const GdbResponse &response);
void handleExecStep(const GdbResponse &response);
void handleExecNext(const GdbResponse &response);
qint64 inferiorPid() const { return m_manager->inferiorPid(); } qint64 inferiorPid() const { return m_manager->inferiorPid(); }
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); } void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
@@ -357,8 +359,7 @@ private: ////////// View & Data Stuff //////////
// //
// Disassembler specific stuff // Disassembler specific stuff
// //
virtual void fetchDisassembler(DisassemblerViewAgent *agent, virtual void fetchDisassembler(DisassemblerViewAgent *agent);
const StackFrame &frame);
void fetchDisassemblerByAddress(DisassemblerViewAgent *agent, void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
bool useMixedMode); bool useMixedMode);
void handleFetchDisassemblerByLine(const GdbResponse &response); void handleFetchDisassemblerByLine(const GdbResponse &response);

View File

@@ -56,7 +56,6 @@ namespace Internal {
class DisassemblerViewAgent; class DisassemblerViewAgent;
class MemoryViewAgent; class MemoryViewAgent;
struct StackFrame;
class Symbol; class Symbol;
class WatchData; class WatchData;
@@ -111,7 +110,7 @@ public:
virtual void watchPoint(const QPoint &) {} virtual void watchPoint(const QPoint &) {}
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length) virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length)
{ Q_UNUSED(addr); Q_UNUSED(length); } { Q_UNUSED(addr); Q_UNUSED(length); }
virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame &) {} virtual void fetchDisassembler(DisassemblerViewAgent *) {}
virtual void setRegisterValue(int regnr, const QString &value) virtual void setRegisterValue(int regnr, const QString &value)
{ Q_UNUSED(regnr); Q_UNUSED(value); } { Q_UNUSED(regnr); Q_UNUSED(value); }