forked from qt-creator/qt-creator
debugger: fall back to instructionwise stepping when debuginfo for frame is
missing
This commit is contained in:
@@ -1084,9 +1084,9 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
|
||||
return ok;
|
||||
}
|
||||
|
||||
void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent,
|
||||
const StackFrame & frame)
|
||||
void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent)
|
||||
{
|
||||
StackFrame frame = agent->frame();
|
||||
enum { ContextLines = 40 };
|
||||
bool ok = false;
|
||||
QString errorMessage;
|
||||
|
||||
@@ -88,8 +88,7 @@ public:
|
||||
|
||||
virtual void attemptBreakpointSynchronization();
|
||||
|
||||
virtual void fetchDisassembler(DisassemblerViewAgent *agent,
|
||||
const StackFrame &frame);
|
||||
virtual void fetchDisassembler(DisassemblerViewAgent *agent);
|
||||
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length);
|
||||
|
||||
virtual void reloadModules();
|
||||
|
||||
@@ -153,8 +153,11 @@ public:
|
||||
|
||||
struct DisassemblerViewAgentPrivate
|
||||
{
|
||||
DisassemblerViewAgentPrivate() { tryMixed = true; }
|
||||
|
||||
QPointer<TextEditor::ITextEditor> editor;
|
||||
StackFrame frame;
|
||||
bool tryMixed;
|
||||
QPointer<DebuggerManager> manager;
|
||||
LocationMark2 *locationMark;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
if (!frame.function.isEmpty() && frame.function != _("??")) {
|
||||
d->tryMixed = tryMixed;
|
||||
if (isMixed()) {
|
||||
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
|
||||
if (it != d->cache.end()) {
|
||||
QString msg = _("Use cache disassembler for '%1' in '%2'")
|
||||
@@ -245,7 +262,7 @@ void DisassemblerViewAgent::setFrame(const StackFrame &frame)
|
||||
}
|
||||
IDebuggerEngine *engine = d->manager->currentEngine();
|
||||
QTC_ASSERT(engine, return);
|
||||
engine->fetchDisassembler(this, frame);
|
||||
engine->fetchDisassembler(this);
|
||||
}
|
||||
|
||||
void DisassemblerViewAgent::setContents(const QString &contents)
|
||||
|
||||
@@ -83,12 +83,14 @@ public:
|
||||
explicit DisassemblerViewAgent(DebuggerManager *manager);
|
||||
~DisassemblerViewAgent();
|
||||
|
||||
void setFrame(const StackFrame &frame);
|
||||
void setFrame(const StackFrame &frame, bool tryMixed = true);
|
||||
const StackFrame &frame() const;
|
||||
void resetLocation();
|
||||
Q_SLOT void setContents(const QString &contents);
|
||||
QString address() const;
|
||||
bool contentsCoversAddress(const QString &contents) const;
|
||||
void cleanup();
|
||||
bool isMixed() const;
|
||||
|
||||
private:
|
||||
DisassemblerViewAgentPrivate *d;
|
||||
|
||||
@@ -1727,9 +1727,35 @@ void GdbEngine::stepExec()
|
||||
setState(InferiorRunningRequested);
|
||||
showStatusMessage(tr("Step requested..."), 5000);
|
||||
if (manager()->isReverseDebugging())
|
||||
postCommand("-reverse-step", RunRequest, CB(handleExecContinue));
|
||||
postCommand("-reverse-step", RunRequest, CB(handleExecStep));
|
||||
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()
|
||||
@@ -1760,9 +1786,35 @@ void GdbEngine::nextExec()
|
||||
setState(InferiorRunningRequested);
|
||||
showStatusMessage(tr("Step next requested..."), 5000);
|
||||
if (manager()->isReverseDebugging())
|
||||
postCommand("-reverse-next", RunRequest, CB(handleExecContinue));
|
||||
postCommand("-reverse-next", RunRequest, CB(handleExecNext));
|
||||
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()
|
||||
@@ -3405,18 +3457,20 @@ struct DisassemblerAgentCookie
|
||||
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()) {
|
||||
fetchDisassemblerByAddress(agent, true);
|
||||
} else {
|
||||
if (agent->isMixed()) {
|
||||
// Disassemble full function:
|
||||
const StackFrame &frame = agent->frame();
|
||||
QByteArray cmd = "-data-disassemble"
|
||||
" -f " + frame.file.toLocal8Bit() +
|
||||
" -l " + QByteArray::number(frame.line) + " -n -1 -- 1";
|
||||
postCommand(cmd, Discardable, CB(handleFetchDisassemblerByLine),
|
||||
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||
} else {
|
||||
fetchDisassemblerByAddress(agent, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -300,6 +300,8 @@ private: ////////// Inferior Management //////////
|
||||
virtual void jumpToLineExec(const QString &fileName, int lineNumber);
|
||||
|
||||
void handleExecContinue(const GdbResponse &response);
|
||||
void handleExecStep(const GdbResponse &response);
|
||||
void handleExecNext(const GdbResponse &response);
|
||||
|
||||
qint64 inferiorPid() const { return m_manager->inferiorPid(); }
|
||||
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
|
||||
@@ -357,8 +359,7 @@ private: ////////// View & Data Stuff //////////
|
||||
//
|
||||
// Disassembler specific stuff
|
||||
//
|
||||
virtual void fetchDisassembler(DisassemblerViewAgent *agent,
|
||||
const StackFrame &frame);
|
||||
virtual void fetchDisassembler(DisassemblerViewAgent *agent);
|
||||
void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
|
||||
bool useMixedMode);
|
||||
void handleFetchDisassemblerByLine(const GdbResponse &response);
|
||||
|
||||
@@ -56,7 +56,6 @@ namespace Internal {
|
||||
|
||||
class DisassemblerViewAgent;
|
||||
class MemoryViewAgent;
|
||||
struct StackFrame;
|
||||
class Symbol;
|
||||
class WatchData;
|
||||
|
||||
@@ -111,7 +110,7 @@ public:
|
||||
virtual void watchPoint(const QPoint &) {}
|
||||
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 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)
|
||||
{ Q_UNUSED(regnr); Q_UNUSED(value); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user