Commit ecd475c9 authored by hjk's avatar hjk
Browse files

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

missing
parent 93876009
......@@ -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); }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment