forked from qt-creator/qt-creator
debugger: fix chain of fallbacks for disassembler view.
Use non-mixed mode if source is not available.
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
#include <QtGui/QPlainTextEdit>
|
#include <QtGui/QPlainTextEdit>
|
||||||
#include <QtGui/QTextCursor>
|
#include <QtGui/QTextCursor>
|
||||||
#include <QtGui/QSyntaxHighlighter>
|
#include <QtGui/QSyntaxHighlighter>
|
||||||
@@ -182,7 +183,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager)
|
DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager)
|
||||||
: QObject(manager), d(new DisassemblerViewAgentPrivate)
|
: QObject(0), d(new DisassemblerViewAgentPrivate), m_manager(manager)
|
||||||
{
|
{
|
||||||
d->editor = 0;
|
d->editor = 0;
|
||||||
d->locationMark = new LocationMark2();
|
d->locationMark = new LocationMark2();
|
||||||
@@ -212,13 +213,21 @@ void DisassemblerViewAgent::resetLocation()
|
|||||||
d->editor->markableInterface()->removeMark(d->locationMark);
|
d->editor->markableInterface()->removeMark(d->locationMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString frameKey(const StackFrame &frame)
|
||||||
|
{
|
||||||
|
return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from);
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblerViewAgent::setFrame(const StackFrame &frame)
|
void DisassemblerViewAgent::setFrame(const StackFrame &frame)
|
||||||
{
|
{
|
||||||
d->frame = frame;
|
d->frame = frame;
|
||||||
if (!frame.function.isEmpty()) {
|
if (!frame.function.isEmpty() && frame.function != _("??")) {
|
||||||
QHash<QString, QString>::ConstIterator it =
|
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
|
||||||
d->cache.find(frame.function + frame.file);
|
|
||||||
if (it != d->cache.end()) {
|
if (it != d->cache.end()) {
|
||||||
|
QString msg = QString::fromLatin1("Use cache dissassembler for %1 in %2")
|
||||||
|
.arg(frame.function).arg(frame.file);
|
||||||
|
qDebug() << msg;
|
||||||
|
m_manager->showDebuggerOutput(msg);
|
||||||
setContents(*it);
|
setContents(*it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -234,7 +243,7 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
|||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
d->cache.insert(d->frame.function + d->frame.file, contents);
|
d->cache.insert(frameKey(d->frame), contents);
|
||||||
QPlainTextEdit *plainTextEdit = 0;
|
QPlainTextEdit *plainTextEdit = 0;
|
||||||
EditorManager *editorManager = EditorManager::instance();
|
EditorManager *editorManager = EditorManager::instance();
|
||||||
if (!d->editor) {
|
if (!d->editor) {
|
||||||
@@ -273,6 +282,19 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d, return false);
|
||||||
|
for (int pos = 0, line = 0; ; ++line, ++pos) {
|
||||||
|
if (contents.midRef(pos, d->frame.address.size()) == d->frame.address)
|
||||||
|
return true;
|
||||||
|
pos = contents.indexOf('\n', pos + 1);
|
||||||
|
if (pos == -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString DisassemblerViewAgent::address() const
|
QString DisassemblerViewAgent::address() const
|
||||||
{
|
{
|
||||||
return d->frame.address;
|
return d->frame.address;
|
||||||
|
|||||||
@@ -86,10 +86,12 @@ public:
|
|||||||
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;
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DisassemblerViewAgentPrivate *d;
|
DisassemblerViewAgentPrivate *d;
|
||||||
|
DebuggerManager *m_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1634,14 +1634,14 @@ void DebuggerManager::setState(DebuggerState state)
|
|||||||
|
|
||||||
showDebuggerOutput(LogDebug, msg);
|
showDebuggerOutput(LogDebug, msg);
|
||||||
|
|
||||||
resetLocation();
|
//resetLocation();
|
||||||
if (state == d->m_state)
|
if (state == d->m_state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->m_state = state;
|
d->m_state = state;
|
||||||
|
|
||||||
if (d->m_state == InferiorStopped)
|
//if (d->m_state == InferiorStopped)
|
||||||
resetLocation();
|
// resetLocation();
|
||||||
|
|
||||||
if (d->m_state == DebuggerNotReady) {
|
if (d->m_state == DebuggerNotReady) {
|
||||||
setBusyCursor(false);
|
setBusyCursor(false);
|
||||||
|
|||||||
@@ -228,9 +228,10 @@ public slots:
|
|||||||
|
|
||||||
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
|
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
|
||||||
|
|
||||||
private slots:
|
public slots: // FIXME
|
||||||
void showDebuggerOutput(const QString &msg)
|
void showDebuggerOutput(const QString &msg)
|
||||||
{ showDebuggerOutput(LogDebug, msg); }
|
{ showDebuggerOutput(LogDebug, msg); }
|
||||||
|
private slots:
|
||||||
void showDebuggerOutput(int channel, const QString &msg);
|
void showDebuggerOutput(int channel, const QString &msg);
|
||||||
void showDebuggerInput(int channel, const QString &msg);
|
void showDebuggerInput(int channel, const QString &msg);
|
||||||
void showApplicationOutput(const QString &data);
|
void showApplicationOutput(const QString &data);
|
||||||
|
|||||||
@@ -967,10 +967,7 @@ void GdbEngine::handleExecRunToFunction(const GdbResponse &response)
|
|||||||
setState(InferiorStopped);
|
setState(InferiorStopped);
|
||||||
showStatusMessage(tr("Function reached. Stopped."));
|
showStatusMessage(tr("Function reached. Stopped."));
|
||||||
GdbMi frame = response.data.findChild("frame");
|
GdbMi frame = response.data.findChild("frame");
|
||||||
StackFrame f;
|
StackFrame f = parseStackFrame(frame, 0);
|
||||||
f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
|
|
||||||
f.line = frame.findChild("line").data().toInt();
|
|
||||||
f.address = _(frame.findChild("addr").data());
|
|
||||||
gotoLocation(f, true);
|
gotoLocation(f, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,11 +1163,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
|||||||
// system="0.00136",start="1218810678.805432",end="1218810678.812011"}
|
// system="0.00136",start="1218810678.805432",end="1218810678.812011"}
|
||||||
setState(InferiorStopped);
|
setState(InferiorStopped);
|
||||||
showStatusMessage(tr("Run to Function finished. Stopped."));
|
showStatusMessage(tr("Run to Function finished. Stopped."));
|
||||||
GdbMi frame = data.findChild("frame");
|
StackFrame f = parseStackFrame(data.findChild("frame"), 0);
|
||||||
StackFrame f;
|
|
||||||
f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
|
|
||||||
f.line = frame.findChild("line").data().toInt();
|
|
||||||
f.address = _(frame.findChild("addr").data());
|
|
||||||
gotoLocation(f, true);
|
gotoLocation(f, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1288,13 +1281,11 @@ void GdbEngine::handleStop2(const GdbMi &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick shot
|
// Quick shot: Jump to stack frame #0.
|
||||||
StackFrame f;
|
if (frame.isValid()) {
|
||||||
f.file = QFile::decodeName(fullName.data());
|
const StackFrame f = parseStackFrame(frame, 0);
|
||||||
f.line = frame.findChild("line").data().toInt();
|
gotoLocation(f, true);
|
||||||
f.address = _(frame.findChild("addr").data());
|
}
|
||||||
f.function = _(frame.findChild("func").data());
|
|
||||||
gotoLocation(f, true);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Stack
|
// Stack
|
||||||
@@ -2253,6 +2244,22 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level)
|
||||||
|
{
|
||||||
|
//qDebug() << "HANDLING FRAME:" << frameMi.toString();
|
||||||
|
QStringList files;
|
||||||
|
files.append(QFile::decodeName(frameMi.findChild("fullname").data()));
|
||||||
|
files.append(QFile::decodeName(frameMi.findChild("file").data()));
|
||||||
|
StackFrame frame;
|
||||||
|
frame.level = level;
|
||||||
|
frame.file = fullName(files);
|
||||||
|
frame.function = _(frameMi.findChild("func").data());
|
||||||
|
frame.from = _(frameMi.findChild("from").data());
|
||||||
|
frame.line = frameMi.findChild("line").data().toInt();
|
||||||
|
frame.address = _(frameMi.findChild("addr").data());
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
void GdbEngine::handleStackListFrames(const GdbResponse &response)
|
void GdbEngine::handleStackListFrames(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
@@ -2274,19 +2281,8 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
|
|||||||
|
|
||||||
int n = stack.childCount();
|
int n = stack.childCount();
|
||||||
for (int i = 0; i != n; ++i) {
|
for (int i = 0; i != n; ++i) {
|
||||||
//qDebug() << "HANDLING FRAME:" << stack.childAt(i).toString();
|
stackFrames.append(parseStackFrame(stack.childAt(i), i));
|
||||||
const GdbMi frameMi = stack.childAt(i);
|
const StackFrame &frame = stackFrames.back();
|
||||||
StackFrame frame(i);
|
|
||||||
QStringList files;
|
|
||||||
files.append(QFile::decodeName(frameMi.findChild("fullname").data()));
|
|
||||||
files.append(QFile::decodeName(frameMi.findChild("file").data()));
|
|
||||||
frame.file = fullName(files);
|
|
||||||
frame.function = _(frameMi.findChild("func").data());
|
|
||||||
frame.from = _(frameMi.findChild("from").data());
|
|
||||||
frame.line = frameMi.findChild("line").data().toInt();
|
|
||||||
frame.address = _(frameMi.findChild("addr").data());
|
|
||||||
|
|
||||||
stackFrames.append(frame);
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
const bool isBogus =
|
const bool isBogus =
|
||||||
@@ -3875,18 +3871,18 @@ void GdbEngine::fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
|
|||||||
QTC_ASSERT(agent, return);
|
QTC_ASSERT(agent, return);
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
quint64 address = agent->address().toULongLong(&ok, 0);
|
quint64 address = agent->address().toULongLong(&ok, 0);
|
||||||
qDebug() << "ADDRESS: " << agent->address() << address;
|
//qDebug() << "ADDRESS: " << agent->address() << address;
|
||||||
QTC_ASSERT(ok, return);
|
QTC_ASSERT(ok, return);
|
||||||
quint64 start = address - 20;
|
QString start = QString::number(address - 20, 16);
|
||||||
quint64 end = address + 100;
|
QString end = QString::number(address + 100, 16);
|
||||||
// -data-disassemble [ -s start-addr -e end-addr ]
|
// -data-disassemble [ -s start-addr -e end-addr ]
|
||||||
// | [ -f filename -l linenum [ -n lines ] ] -- mode
|
// | [ -f filename -l linenum [ -n lines ] ] -- mode
|
||||||
if (useMixedMode)
|
if (useMixedMode)
|
||||||
postCommand(_("-data-disassemble -s %1 -e %2 -- 1").arg(start).arg(end),
|
postCommand(_("-data-disassemble -s 0x%1 -e 0x%2 -- 1").arg(start).arg(end),
|
||||||
Discardable, CB(handleFetchDisassemblerByAddress1),
|
Discardable, CB(handleFetchDisassemblerByAddress1),
|
||||||
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||||
else
|
else
|
||||||
postCommand(_("-data-disassemble -s %1 -e %2 -- 0").arg(start).arg(end),
|
postCommand(_("-data-disassemble -s 0x%1 -e 0x%2 -- 0").arg(start).arg(end),
|
||||||
Discardable, CB(handleFetchDisassemblerByAddress0),
|
Discardable, CB(handleFetchDisassemblerByAddress0),
|
||||||
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||||
}
|
}
|
||||||
@@ -3957,8 +3953,13 @@ void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
|
|||||||
|
|
||||||
if (response.resultClass == GdbResultDone) {
|
if (response.resultClass == GdbResultDone) {
|
||||||
GdbMi lines = response.data.findChild("asm_insns");
|
GdbMi lines = response.data.findChild("asm_insns");
|
||||||
|
if (!lines.children().isEmpty())
|
||||||
|
qDebug() << "LINES: " << lines.childAt(0).findChild("line").data();
|
||||||
if (lines.children().isEmpty())
|
if (lines.children().isEmpty())
|
||||||
fetchDisassemblerByAddress(ac.agent, true);
|
fetchDisassemblerByAddress(ac.agent, true);
|
||||||
|
else if (lines.children().size() == 1
|
||||||
|
&& lines.childAt(0).findChild("line").data() == "0")
|
||||||
|
fetchDisassemblerByAddress(ac.agent, true);
|
||||||
else
|
else
|
||||||
ac.agent->setContents(parseDisassembler(lines));
|
ac.agent->setContents(parseDisassembler(lines));
|
||||||
} else if (response.resultClass == GdbResultError) {
|
} else if (response.resultClass == GdbResultError) {
|
||||||
@@ -3980,8 +3981,15 @@ void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResponse &response)
|
|||||||
GdbMi lines = response.data.findChild("asm_insns");
|
GdbMi lines = response.data.findChild("asm_insns");
|
||||||
if (lines.children().isEmpty())
|
if (lines.children().isEmpty())
|
||||||
fetchDisassemblerByAddress(ac.agent, false);
|
fetchDisassemblerByAddress(ac.agent, false);
|
||||||
else
|
else {
|
||||||
ac.agent->setContents(parseDisassembler(lines));
|
QString contents = parseDisassembler(lines);
|
||||||
|
if (ac.agent->contentsCoversAddress(contents)) {
|
||||||
|
ac.agent->setContents(parseDisassembler(lines));
|
||||||
|
} else {
|
||||||
|
qDebug() << "FALL BACK TO NON-MIXED";
|
||||||
|
fetchDisassemblerByAddress(ac.agent, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 26^error,msg="Cannot access memory at address 0x801ca308"
|
// 26^error,msg="Cannot access memory at address 0x801ca308"
|
||||||
QByteArray msg = response.data.findChild("msg").data();
|
QByteArray msg = response.data.findChild("msg").data();
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ private:
|
|||||||
|
|
||||||
bool supportsThreads() const;
|
bool supportsThreads() const;
|
||||||
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
|
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
|
||||||
|
StackFrame parseStackFrame(const GdbMi &mi, int level);
|
||||||
|
|
||||||
void connectAdapter();
|
void connectAdapter();
|
||||||
void disconnectAdapter();
|
void disconnectAdapter();
|
||||||
|
|||||||
@@ -969,8 +969,10 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
|
|||||||
lib.dataseg = dataseg;
|
lib.dataseg = dataseg;
|
||||||
m_session.libraries.append(lib);
|
m_session.libraries.append(lib);
|
||||||
logMessage(logMsg);
|
logMessage(logMsg);
|
||||||
// This lets gdb trigger a register update etc
|
// This lets gdb trigger a register update etc.
|
||||||
sendGdbServerMessage("T05library:;");
|
// With CS gdb 6.4 we get a non-standard $qfDllInfo#7f+ request
|
||||||
|
// afterwards, so don't use it for now.
|
||||||
|
//sendGdbServerMessage("T05library:;");
|
||||||
sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
|
sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,16 +38,16 @@ namespace Internal {
|
|||||||
|
|
||||||
struct StackFrame
|
struct StackFrame
|
||||||
{
|
{
|
||||||
StackFrame(int level = 0);
|
StackFrame();
|
||||||
bool isUsable() const;
|
bool isUsable() const;
|
||||||
QString toToolTip() const;
|
QString toToolTip() const;
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
int level;
|
int level;
|
||||||
QString function;
|
QString function;
|
||||||
QString file; // we try to put an absolute file name in there
|
QString file; // We try to put an absolute file name in there.
|
||||||
QString from;
|
QString from; // Sometimes something like "/usr/lib/libstdc++.so.6"
|
||||||
QString to;
|
QString to; // Used in ScriptEngine only.
|
||||||
int line;
|
int line;
|
||||||
QString address;
|
QString address;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,8 +39,8 @@
|
|||||||
|
|
||||||
using namespace Debugger::Internal;
|
using namespace Debugger::Internal;
|
||||||
|
|
||||||
StackFrame::StackFrame(int l)
|
StackFrame::StackFrame()
|
||||||
: level(l), line(0)
|
: level(0), line(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool StackFrame::isUsable() const
|
bool StackFrame::isUsable() const
|
||||||
|
|||||||
Reference in New Issue
Block a user