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;
|
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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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); }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user